summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
committerTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
commitefb33d6494d88c27c8766553b6a963ddf2654458 (patch)
tree76dd5e56b79191074998c0fb6bf7b81276116a4b /ext
parent072da88eee57e5d16f0b75c7b90c8a0bc6a60cb3 (diff)
Included Log4Qt in project
Diffstat (limited to 'ext')
-rw-r--r--ext/Log4Qt/.gitignore74
-rwxr-xr-xext/Log4Qt/CMakeLists.txt300
-rw-r--r--ext/Log4Qt/Log4Qt.pro21
-rw-r--r--ext/Log4Qt/Readme.txt51
-rw-r--r--ext/Log4Qt/cmake_uninstall.cmake.in22
-rw-r--r--ext/Log4Qt/deploy/include/Appender1
-rw-r--r--ext/Log4Qt/deploy/include/Appenderskeleton1
-rw-r--r--ext/Log4Qt/deploy/include/AsyncAppender1
-rw-r--r--ext/Log4Qt/deploy/include/BasicConfigurator1
-rw-r--r--ext/Log4Qt/deploy/include/ColorConsoleAppender1
-rw-r--r--ext/Log4Qt/deploy/include/ConsoleAppender1
-rw-r--r--ext/Log4Qt/deploy/include/DailyRollingFileAppender1
-rw-r--r--ext/Log4Qt/deploy/include/DatabaseAppender1
-rw-r--r--ext/Log4Qt/deploy/include/DatabaseLayout1
-rw-r--r--ext/Log4Qt/deploy/include/FileAppender1
-rw-r--r--ext/Log4Qt/deploy/include/Hierarchy1
-rw-r--r--ext/Log4Qt/deploy/include/Layout1
-rw-r--r--ext/Log4Qt/deploy/include/Level1
-rw-r--r--ext/Log4Qt/deploy/include/Log4Qt1
-rw-r--r--ext/Log4Qt/deploy/include/Log4QtShared1
-rw-r--r--ext/Log4Qt/deploy/include/LogManager1
-rw-r--r--ext/Log4Qt/deploy/include/LogStream1
-rw-r--r--ext/Log4Qt/deploy/include/Logger1
-rw-r--r--ext/Log4Qt/deploy/include/LoggerRepository1
-rw-r--r--ext/Log4Qt/deploy/include/LoggingEvent1
-rw-r--r--ext/Log4Qt/deploy/include/MDC1
-rw-r--r--ext/Log4Qt/deploy/include/MainthreadAppender1
-rw-r--r--ext/Log4Qt/deploy/include/NDC1
-rw-r--r--ext/Log4Qt/deploy/include/PatternLayout1
-rw-r--r--ext/Log4Qt/deploy/include/PropertyConfigurator1
-rw-r--r--ext/Log4Qt/deploy/include/RollingFileAppender1
-rw-r--r--ext/Log4Qt/deploy/include/SignalAppender1
-rw-r--r--ext/Log4Qt/deploy/include/SimpleLayout1
-rw-r--r--ext/Log4Qt/deploy/include/SimpleTimeLayout1
-rw-r--r--ext/Log4Qt/deploy/include/SystemlogAppender1
-rw-r--r--ext/Log4Qt/deploy/include/TTCCLayout1
-rw-r--r--ext/Log4Qt/deploy/include/TelnetAppender1
-rw-r--r--ext/Log4Qt/deploy/include/WriterAppender1
-rw-r--r--ext/Log4Qt/project-config.cmake.in11
-rw-r--r--ext/Log4Qt/src/Log4Qt.pri108
-rwxr-xr-xext/Log4Qt/src/appender.h135
-rw-r--r--ext/Log4Qt/src/appenderskeleton.cpp269
-rw-r--r--ext/Log4Qt/src/appenderskeleton.h230
-rw-r--r--ext/Log4Qt/src/asyncappender.cpp157
-rw-r--r--ext/Log4Qt/src/asyncappender.h138
-rwxr-xr-xext/Log4Qt/src/basicconfigurator.cpp107
-rwxr-xr-xext/Log4Qt/src/basicconfigurator.h83
-rw-r--r--ext/Log4Qt/src/colorconsoleappender.cpp290
-rwxr-xr-xext/Log4Qt/src/colorconsoleappender.h111
-rwxr-xr-xext/Log4Qt/src/consoleappender.cpp199
-rwxr-xr-xext/Log4Qt/src/consoleappender.h160
-rwxr-xr-xext/Log4Qt/src/dailyrollingfileappender.cpp352
-rwxr-xr-xext/Log4Qt/src/dailyrollingfileappender.h196
-rwxr-xr-xext/Log4Qt/src/databaseappender.cpp224
-rwxr-xr-xext/Log4Qt/src/databaseappender.h161
-rwxr-xr-xext/Log4Qt/src/databaselayout.cpp218
-rwxr-xr-xext/Log4Qt/src/databaselayout.h144
-rwxr-xr-xext/Log4Qt/src/fileappender.cpp317
-rwxr-xr-xext/Log4Qt/src/fileappender.h233
-rw-r--r--ext/Log4Qt/src/helpers/appenderattachable.cpp199
-rw-r--r--ext/Log4Qt/src/helpers/appenderattachable.h121
-rwxr-xr-xext/Log4Qt/src/helpers/classlogger.cpp100
-rwxr-xr-xext/Log4Qt/src/helpers/classlogger.h117
-rwxr-xr-xext/Log4Qt/src/helpers/configuratorhelper.cpp136
-rwxr-xr-xext/Log4Qt/src/helpers/configuratorhelper.h211
-rwxr-xr-xext/Log4Qt/src/helpers/datetime.cpp326
-rwxr-xr-xext/Log4Qt/src/helpers/datetime.h212
-rw-r--r--ext/Log4Qt/src/helpers/dispatcher.cpp59
-rw-r--r--ext/Log4Qt/src/helpers/dispatcher.h80
-rw-r--r--ext/Log4Qt/src/helpers/factory.cpp515
-rwxr-xr-xext/Log4Qt/src/helpers/factory.h444
-rwxr-xr-xext/Log4Qt/src/helpers/initialisationhelper.cpp182
-rwxr-xr-xext/Log4Qt/src/helpers/initialisationhelper.h435
-rwxr-xr-xext/Log4Qt/src/helpers/logerror.cpp352
-rwxr-xr-xext/Log4Qt/src/helpers/logerror.h550
-rwxr-xr-xext/Log4Qt/src/helpers/logobject.cpp74
-rwxr-xr-xext/Log4Qt/src/helpers/logobject.h219
-rwxr-xr-xext/Log4Qt/src/helpers/logobjectptr.cpp65
-rwxr-xr-xext/Log4Qt/src/helpers/logobjectptr.h187
-rwxr-xr-xext/Log4Qt/src/helpers/optionconverter.cpp301
-rwxr-xr-xext/Log4Qt/src/helpers/optionconverter.h141
-rw-r--r--ext/Log4Qt/src/helpers/patternformatter.cpp902
-rwxr-xr-xext/Log4Qt/src/helpers/patternformatter.h195
-rwxr-xr-xext/Log4Qt/src/helpers/properties.cpp364
-rwxr-xr-xext/Log4Qt/src/helpers/properties.h161
-rwxr-xr-xext/Log4Qt/src/hierarchy.cpp212
-rwxr-xr-xext/Log4Qt/src/hierarchy.h141
-rw-r--r--ext/Log4Qt/src/layout.cpp84
-rwxr-xr-xext/Log4Qt/src/layout.h156
-rwxr-xr-xext/Log4Qt/src/level.cpp242
-rwxr-xr-xext/Log4Qt/src/level.h154
-rwxr-xr-xext/Log4Qt/src/log4qt.cpp15
-rw-r--r--ext/Log4Qt/src/log4qt.h623
-rw-r--r--ext/Log4Qt/src/log4qtshared.h9
-rw-r--r--ext/Log4Qt/src/logger.cpp1047
-rwxr-xr-xext/Log4Qt/src/logger.h810
-rwxr-xr-xext/Log4Qt/src/loggerrepository.cpp77
-rwxr-xr-xext/Log4Qt/src/loggerrepository.h129
-rw-r--r--ext/Log4Qt/src/loggingevent.cpp279
-rw-r--r--ext/Log4Qt/src/loggingevent.h223
-rwxr-xr-xext/Log4Qt/src/logmanager.cpp458
-rwxr-xr-xext/Log4Qt/src/logmanager.h337
-rw-r--r--ext/Log4Qt/src/logstream.cpp66
-rw-r--r--ext/Log4Qt/src/logstream.h98
-rw-r--r--ext/Log4Qt/src/mainthreadappender.cpp125
-rw-r--r--ext/Log4Qt/src/mainthreadappender.h129
-rwxr-xr-xext/Log4Qt/src/mdc.cpp116
-rwxr-xr-xext/Log4Qt/src/mdc.h122
-rwxr-xr-xext/Log4Qt/src/ndc.cpp154
-rwxr-xr-xext/Log4Qt/src/ndc.h121
-rwxr-xr-xext/Log4Qt/src/patternlayout.cpp147
-rwxr-xr-xext/Log4Qt/src/patternlayout.h167
-rwxr-xr-xext/Log4Qt/src/propertyconfigurator.cpp588
-rwxr-xr-xext/Log4Qt/src/propertyconfigurator.h194
-rwxr-xr-xext/Log4Qt/src/rollingfileappender.cpp191
-rwxr-xr-xext/Log4Qt/src/rollingfileappender.h169
-rwxr-xr-xext/Log4Qt/src/signalappender.cpp63
-rwxr-xr-xext/Log4Qt/src/signalappender.h84
-rwxr-xr-xext/Log4Qt/src/simplelayout.cpp84
-rwxr-xr-xext/Log4Qt/src/simplelayout.h102
-rwxr-xr-xext/Log4Qt/src/simpletimelayout.cpp89
-rwxr-xr-xext/Log4Qt/src/simpletimelayout.h102
-rwxr-xr-xext/Log4Qt/src/spi/filter.cpp70
-rwxr-xr-xext/Log4Qt/src/spi/filter.h124
-rw-r--r--ext/Log4Qt/src/systemlogappender.cpp181
-rw-r--r--ext/Log4Qt/src/systemlogappender.h98
-rw-r--r--ext/Log4Qt/src/telnetappender.cpp255
-rw-r--r--ext/Log4Qt/src/telnetappender.h228
-rwxr-xr-xext/Log4Qt/src/ttcclayout.cpp182
-rwxr-xr-xext/Log4Qt/src/ttcclayout.h235
-rwxr-xr-xext/Log4Qt/src/varia/debugappender.cpp130
-rwxr-xr-xext/Log4Qt/src/varia/debugappender.h133
-rwxr-xr-xext/Log4Qt/src/varia/denyallfilter.cpp77
-rwxr-xr-xext/Log4Qt/src/varia/denyallfilter.h105
-rwxr-xr-xext/Log4Qt/src/varia/levelmatchfilter.cpp100
-rwxr-xr-xext/Log4Qt/src/varia/levelmatchfilter.h137
-rwxr-xr-xext/Log4Qt/src/varia/levelrangefilter.cpp104
-rwxr-xr-xext/Log4Qt/src/varia/levelrangefilter.h153
-rwxr-xr-xext/Log4Qt/src/varia/listappender.cpp153
-rwxr-xr-xext/Log4Qt/src/varia/listappender.h174
-rwxr-xr-xext/Log4Qt/src/varia/nullappender.cpp104
-rwxr-xr-xext/Log4Qt/src/varia/nullappender.h102
-rwxr-xr-xext/Log4Qt/src/varia/stringmatchfilter.cpp101
-rwxr-xr-xext/Log4Qt/src/varia/stringmatchfilter.h133
-rwxr-xr-xext/Log4Qt/src/writerappender.cpp288
-rwxr-xr-xext/Log4Qt/src/writerappender.h200
-rw-r--r--ext/ext.pro9
147 files changed, 22475 insertions, 0 deletions
diff --git a/ext/Log4Qt/.gitignore b/ext/Log4Qt/.gitignore
new file mode 100644
index 0000000..9c02ba4
--- /dev/null
+++ b/ext/Log4Qt/.gitignore
@@ -0,0 +1,74 @@
+doc/html/
+sql/
+winbuild/
+build/
+*.dll
+!doc/src
+bin/
+lib/
+
+# object files
+*.[oa]
+*.so
+*.so.*
+
+# qt creator projects
+*.cbp
+*.user
+
+# qt creator cmake directories
+qt-creator*/
+qtcreator*/
+
+# manually cmake build directories
+build*/
+
+# win32 libs
+*.dll
+# win32 impl
+*.lib
+
+# temporary dirs
+tmp/
+
+# logger dirs
+log/
+
+# html docs because it's generated by doxygen
+doc/html/
+
+# test
+test/
+test*/
+
+# qmake mocs
+moc_*.cpp
+
+# qt ui headers
+ui*.h
+
+# qt translations files
+*.qm
+
+# temporary files
+*~
+
+# emacs temporary files
+##*##
+
+# make files
+Makefile
+
+# cmake build system
+CMakeFiles/
+CMakeCache.txt
+
+# cmake mocs
+moc*.cxx
+*.moc
+
+# include cmake build file
+#!CMakeLists.txt
+
+#Doxygen file generated by cmake
+Doxyfile \ No newline at end of file
diff --git a/ext/Log4Qt/CMakeLists.txt b/ext/Log4Qt/CMakeLists.txt
new file mode 100755
index 0000000..81773e2
--- /dev/null
+++ b/ext/Log4Qt/CMakeLists.txt
@@ -0,0 +1,300 @@
+cmake_minimum_required(VERSION 2.6)
+
+# cmake options
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib")
+# postfix for library
+set(CMAKE_DEBUG_POSTFIX d)
+set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
+# variable for project name, used in many places
+set (PROJECT Log4Qt)
+
+project(${PROJECT})
+
+string(TOUPPER ${PROJECT_NAME} PROJECT_TO_UPPER)
+string(TOLOWER ${PROJECT_NAME} PROJECT_TO_LOWER)
+
+find_package(Qt4 REQUIRED)
+# COMPILER customization
+ # compilers flags
+ if (MSVC)
+ add_definitions (/W3 -Zc:wchar_t-)
+ elseif (CMAKE_COMPILER_IS_GNUCXX)
+ add_definitions (-Wall)
+ else ()
+ message ("Unknown compiler")
+ endif ()
+ #compiler options
+ set(OPTIMIZATION_FLAGS "-O2" )
+message("Building project ${PROJECT_NAME}")
+
+message("
+Configuration
+-------------
+CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}
+CXXFLAGS = $ENV{CXXFLAGS}
+CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}
+LDFLAGS = $ENV{LDFLAGS}
+CMAKE_EXE_LINKER_FLAGS = ${CMAKE_EXE_LINKER_FLAGS}
+CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}
+")
+
+# remove when release
+if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
+ set(CMAKE_VERBOSE_MAKEFILE TRUE)
+endif (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
+
+# SOURCE FILES AND DIRECTORIES
+set(LOG4QT_SOURCES)
+# Q_SOURCES, var contains files, for which need call qt4_automoc
+set(LOG4QT_Q_SOURCES)
+set(LOG4QT_HEADERS)
+# Q_HEADERS, var contains files, for which qt4_wrap_cpp called
+set(LOG4QT_Q_HEADERS)
+
+set(LOG4QT_HEADERS
+ src/basicconfigurator.h
+ src/helpers/classlogger.h
+ src/helpers/datetime.h
+ src/helpers/factory.h
+ src/hierarchy.h
+ src/helpers/initialisationhelper.h
+ src/level.h
+ src/log4qt.h
+ src/log4qtshared.h
+ src/loggerrepository.h
+ src/loggingevent.h
+ src/logmanager.h
+ src/helpers/logobjectptr.h
+ src/mdc.h
+ src/ndc.h
+ src/helpers/optionconverter.h
+ src/helpers/patternformatter.h
+ src/helpers/properties.h
+ src/propertyconfigurator.h
+ src/helpers/logerror.h
+ src/helpers/appenderattachable.h
+ src/logstream.h
+)
+
+set(LOG4QT_Q_HEADERS src/appender.h
+ src/appenderskeleton.h
+ src/asyncappender.h
+ src/colorconsoleappender.h
+ src/consoleappender.h
+ src/dailyrollingfileappender.h
+ src/fileappender.h
+ src/mainthreadappender.h
+ src/layout.h
+ src/logger.h
+ src/patternlayout.h
+ src/rollingfileappender.h
+ src/signalappender.h
+ src/simplelayout.h
+ src/simpletimelayout.h
+ src/ttcclayout.h
+ src/writerappender.h
+ src/systemlogappender.h
+ src/helpers/configuratorhelper.h
+ src/helpers/logobject.h
+ src/helpers/dispatcher.h
+ src/spi/filter.h
+ src/varia/debugappender.h
+ src/varia/denyallfilter.h
+ src/varia/levelmatchfilter.h
+ src/varia/levelrangefilter.h
+ src/varia/listappender.h
+ src/varia/nullappender.h
+ src/varia/stringmatchfilter.h)
+
+set(LOG4QT_SOURCES
+ src/helpers/classlogger.cpp
+ src/helpers/configuratorhelper.cpp
+ src/helpers/datetime.cpp
+ src/helpers/factory.cpp
+ src/helpers/initialisationhelper.cpp
+ src/helpers/logerror.cpp
+ src/helpers/logobject.cpp
+ src/helpers/dispatcher.cpp
+ src/helpers/logobjectptr.cpp
+ src/helpers/optionconverter.cpp
+ src/helpers/patternformatter.cpp
+ src/helpers/properties.cpp
+ src/helpers/appenderattachable.cpp
+ src/spi/filter.cpp
+ src/varia/debugappender.cpp
+ src/varia/denyallfilter.cpp
+ src/varia/levelmatchfilter.cpp
+ src/varia/levelrangefilter.cpp
+ src/varia/listappender.cpp
+ src/varia/nullappender.cpp
+ src/varia/stringmatchfilter.cpp
+ src/systemlogappender.cpp
+ src/appenderskeleton.cpp
+ src/basicconfigurator.cpp
+ src/colorconsoleappender.cpp
+ src/consoleappender.cpp
+ src/asyncappender.cpp
+ src/dailyrollingfileappender.cpp
+ src/fileappender.cpp
+ src/mainthreadappender.cpp
+ src/hierarchy.cpp
+ src/layout.cpp
+ src/level.cpp
+ src/log4qt.cpp
+ src/logger.cpp
+ src/loggerrepository.cpp
+ src/loggingevent.cpp
+ src/logmanager.cpp
+ src/mdc.cpp
+ src/ndc.cpp
+ src/patternlayout.cpp
+ src/propertyconfigurator.cpp
+ src/rollingfileappender.cpp
+ src/signalappender.cpp
+ src/simplelayout.cpp
+ src/simpletimelayout.cpp
+ src/ttcclayout.cpp
+ src/writerappender.cpp
+ src/logstream.cpp
+)
+
+# project version
+set(LOG4QT_VERSION_MAJOR 1)
+set(LOG4QT_VERSION_MINOR 0)
+set(LOG4QT_VERSION_RELEASE 0)
+set(LOG4QT_VERSION "${LOG4QT_VERSION_MAJOR}.${LOG4QT_VERSION_MINOR}.${LOG4QT_VERSION_RELEASE}")
+set(VERSION ${LOG4QT_VERSION})
+set(SOVERSION ${LOG4QT_VERSION})
+add_definitions(-DLOG4QT_VERSION=${LOG4QT_VERSION_MAJOR}*65536+${LOG4QT_VERSION_MINOR}*256+${LOG4QT_VERSION_RELEASE})
+add_definitions(-DLOG4QT_VERSION_STR="${LOG4QT_VERSION}")
+
+# Make sure LOG4QT_BUILD_STATIC is defined since the variable value is used when configuring
+# the project-config.cmake file.
+if (NOT DEFINED LOG4QT_BUILD_STATIC)
+ set (LOG4QT_BUILD_STATIC FALSE)
+endif (NOT DEFINED LOG4QT_BUILD_STATIC)
+
+# QT
+set(QT_DONT_USE_QTGUI TRUE)
+include(${QT_USE_FILE})
+
+if (QT_USE_QTSQL)
+ message("With QT_USE_QTSQL DatabaseAppender, DatabaseLayout compiled")
+ list(APPEND LOG4QT_Q_HEADERS src/databaseappender.h src/databaselayout.h)
+ list(APPEND LOG4QT_SOURCES src/databaseappender.cpp src/databaselayout.cpp)
+endif (QT_USE_QTSQL)
+
+if (QT_USE_QTNETWORK)
+ message("With QT_USE_QTNETWORK TelnetAppender compiled")
+ list(APPEND LOG4QT_Q_HEADERS src/telnetappender.h )
+ list(APPEND LOG4QT_SOURCES src/telnetappender.cpp)
+endif (QT_USE_QTNETWORK)
+
+include_directories(src)
+
+# COMPILATION
+# if you use Q_OBJECT
+qt4_wrap_cpp(LOG4QT_MOC_SOURCES ${LOG4QT_Q_HEADERS})
+qt4_automoc(${LOG4QT_Q_SOURCES})
+
+# BUILD STATIC LIBRARY
+if (LOG4QT_BUILD_STATIC)
+set(LOG4QT_BUILD_CONFIGURATION STATIC)
+# BUILD SHARED LIBRARY
+else (LOG4QT_BUILD_STATIC)
+set(LOG4QT_BUILD_CONFIGURATION SHARED)
+endif (LOG4QT_BUILD_STATIC)
+
+add_library(${PROJECT_NAME} ${LOG4QT_BUILD_CONFIGURATION}
+ ${LOG4QT_SOURCES}
+ ${LOG4QT_Q_SOURCES}
+ ${LOG4QT_MOC_SOURCES}
+ ${LOG4QT_HEADERS}
+ ${LOG4QT_Q_HEADERS})
+
+# LINKING
+target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
+
+set_target_properties(${PROJECT_NAME} PROPERTIES
+ SOVERSION ${LOG4QT_VERSION}
+ VERSION ${LOG4QT_VERSION}
+ DEFINE_SYMBOL ${PROJECT_TO_UPPER}_EXPORTS)
+
+# Allow install location to be overridden for libraries, includes, binaries and cmake configuration
+# files. This provides fine-grained control over where various pieces get installed. The
+# LIB_INSTALL_DIR and BIN_INSTALL_DIR locations are particularly useful for platforms where 32-bit
+# and 64-bit binaries must be separate. (Idea shamelessly stolen from the QJson project.)
+# NOTE: these locations will be used *only* if CMAKE_INSTALL_PREFIX is explicitly defined (see
+# comment below).
+set (BIN_SUFFIX "" CACHE STRING "Define suffix of binary directory name (32/64)" )
+set (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin${BIN_SUFFIX}" CACHE PATH "The directory where binaries will install")
+set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${BIN_SUFFIX}" CACHE PATH "The directory where lib will install")
+set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/${PROJECT_TO_LOWER}" CACHE PATH "The directory where headers will install")
+set (CMAKECONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME}" CACHE PATH "The directory where Log4QtConfig.cmake will install")
+
+if (NOT LOG4QT_DONT_INSTALL)
+
+ # The original implementation of this module used hardcoded paths for the install locations on
+ # Mac OS X (everything was installed under the /usr directory); or would install directly into
+ # the Qt directories on other platforms. CMAKE_INSTALL_PREFIX was ignored. This original
+ # behaviour is preserved for anyone who was relying on it. We continue to use those default
+ # install locations if CMAKE_INSTALL_PREFIX has *not* been explicitly defined. The rationale is
+ # that folks who were satisfied with the old, default install locations would not have been
+ # trying to use CMAKE_INSTALL_PREFIX.
+ if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ if (NOT APPLE)
+ SET(TARGET_INCLUDE_DIR "${QT_INCLUDE_DIR}/${PROJECT_NAME}")
+ SET(TARGET_LIB_DIR "${QT_LIBRARY_DIR}")
+ SET(TARGET_BIN_DIR "${QT_BINARY_DIR}")
+ else()
+ #Qt is the framework but log4qt is not. So it should not be placed into the frameworks location
+ #Also the include dir should not be retrieved from the Qt itself, see http://www.paraview.org/Bug/view.php?id=10632
+ SET(TARGET_INCLUDE_DIR "/usr/include/${PROJECT_NAME}")
+ SET(TARGET_LIB_DIR "/usr/lib")
+ SET(TARGET_BIN_DIR "/usr/bin")
+ endif()
+ # copy project file into qt_libdir and create project.cmake file for use this library in your cmake projects
+ set(EXPORT_TARGET_DESTINATION "${QT_MKSPECS_DIR}/cmake/${PROJECT_NAME}")
+ else()
+ SET(TARGET_INCLUDE_DIR "${INCLUDE_INSTALL_DIR}")
+ SET(TARGET_LIB_DIR "${LIB_INSTALL_DIR}")
+ SET(TARGET_BIN_DIR "${BIN_INSTALL_DIR}")
+ SET(EXPORT_TARGET_DESTINATION "${CMAKECONFIG_INSTALL_DIR}")
+ endif (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+
+ # for using library in your cmake projects
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/project-config.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_TO_LOWER}-config.cmake"
+ IMMEDIATE @ONLY)
+
+ # INSTALLATION
+ # install and export project target
+ set(PROJECT_TARGETS ${PROJECT_NAME}-targets)
+
+ install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_TARGETS}
+ RUNTIME DESTINATION ${TARGET_BIN_DIR}
+ LIBRARY DESTINATION ${TARGET_LIB_DIR}
+ ARCHIVE DESTINATION ${TARGET_LIB_DIR})
+
+ # install exported project target cmake file into export target
+ install(EXPORT ${PROJECT_TARGETS} DESTINATION ${EXPORT_TARGET_DESTINATION} COMPONENT Devel)
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/" DESTINATION "${TARGET_INCLUDE_DIR}" COMPONENT Devel
+ FILES_MATCHING PATTERN "*.h")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deploy/include/" DESTINATION "${TARGET_INCLUDE_DIR}" COMPONENT Devel)
+
+ # install cmake config file
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_TO_LOWER}-config.cmake DESTINATION ${EXPORT_TARGET_DESTINATION} COMPONENT Devel)
+
+ # UNINSTALL TARGET
+ # create cmake uninstall files and unregister docs scripts
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+
+ add_custom_target(uninstall
+ COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+endif (NOT LOG4QT_DONT_INSTALL)
diff --git a/ext/Log4Qt/Log4Qt.pro b/ext/Log4Qt/Log4Qt.pro
new file mode 100644
index 0000000..65700d2
--- /dev/null
+++ b/ext/Log4Qt/Log4Qt.pro
@@ -0,0 +1,21 @@
+
+include(src/Log4Qt.pri)
+
+TEMPLATE = lib
+QT += core xml network
+TARGET = log4qt
+
+LOG4QT_VERSION_MAJOR = 1
+LOG4QT_VERSION_MINOR = 1
+LOG4QT_VERSION_RELEASE = 0
+
+LOG4QT_VERSION = '\\"$${LOG4QT_VERSION_MAJOR}.$${LOG4QT_VERSION_MINOR}.$${LOG4QT_VERSION_RELEASE}\\"'
+DEFINES += LOG4QT_VERSION_STR=\"$${LOG4QT_VERSION}\"
+DEFINES += LOG4QT_VERSION=$${LOG4QT_VERSION}
+
+VERSION = 1.1.0
+
+DEPENDPATH += src src/helpers src/spisrc/ varia
+INCLUDEPATH += src src/helpers src/spi src/varia
+
+
diff --git a/ext/Log4Qt/Readme.txt b/ext/Log4Qt/Readme.txt
new file mode 100644
index 0000000..61ddd8f
--- /dev/null
+++ b/ext/Log4Qt/Readme.txt
@@ -0,0 +1,51 @@
+Build and install
+
+*NIX
+ STATIC
+ cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -DLOG4QT_BUILD_STATIC=True .
+ make
+ make install
+ SHARED
+ cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release .
+ make
+ make install
+
+WIN*
+ STATIC
+ cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" -DLOG4QT_BUILD_STATIC=True .
+ mingw32-make
+ mingw32-make install
+ SHARED
+ cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" .
+ mingw32-make
+ mingw32-make install
+
+If you dont want to use log4qt sql features you must not define QT_USE_QTSQL.
+If you dont want to use log4qt network features you must not define QT_USE_QTNETWORK.
+
+Using in your projects
+
+If your have cmake-based project
+ for shared linking you must:
+ 1. make log4qt in shared mode;
+ 2. install it;
+ 1. add log4qt package to your CMakeLists.txt;
+ 2. include header directory;
+ 3. link library to target.
+
+ For example:
+ find_package(log4qt REQUIRED HINTS "${QT_MKSPECS_DIR}/cmake/Log4Qt" NO_DEFAULT_PATHS)
+ include_directories(${LOG4QT_INCLUDE_DIRS})
+ target_link_libraries(main ${QT_LIBRARIES} log4qt)
+
+ for static linking:
+ 1. add subdirectory to your project
+ 2. include log4qt/src
+ 3. link library to target
+
+ For example:
+ add_subdirectory(../log4qt ${CMAKE_CURRENT_BINARY_DIR}/log4qt)
+ include_directories(../log4qt/src)
+ target_link_libraries(main ${QT_LIBRARIES} log4qt)
+
+
diff --git a/ext/Log4Qt/cmake_uninstall.cmake.in b/ext/Log4Qt/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..65750dd
--- /dev/null
+++ b/ext/Log4Qt/cmake_uninstall.cmake.in
@@ -0,0 +1,22 @@
+
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+# IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+# ELSE(EXISTS "$ENV{DESTDIR}${file}")
+# MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+# ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
diff --git a/ext/Log4Qt/deploy/include/Appender b/ext/Log4Qt/deploy/include/Appender
new file mode 100644
index 0000000..d6dc380
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Appender
@@ -0,0 +1 @@
+#include "appender.h"
diff --git a/ext/Log4Qt/deploy/include/Appenderskeleton b/ext/Log4Qt/deploy/include/Appenderskeleton
new file mode 100644
index 0000000..a00c2bb
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Appenderskeleton
@@ -0,0 +1 @@
+#include "appenderskeleton.h"
diff --git a/ext/Log4Qt/deploy/include/AsyncAppender b/ext/Log4Qt/deploy/include/AsyncAppender
new file mode 100644
index 0000000..244f918
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/AsyncAppender
@@ -0,0 +1 @@
+#include "asyncappender.h"
diff --git a/ext/Log4Qt/deploy/include/BasicConfigurator b/ext/Log4Qt/deploy/include/BasicConfigurator
new file mode 100644
index 0000000..72d6d38
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/BasicConfigurator
@@ -0,0 +1 @@
+#include "basicconfigurator.h"
diff --git a/ext/Log4Qt/deploy/include/ColorConsoleAppender b/ext/Log4Qt/deploy/include/ColorConsoleAppender
new file mode 100644
index 0000000..70e6126
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/ColorConsoleAppender
@@ -0,0 +1 @@
+#include "colorconsoleappender.h"
diff --git a/ext/Log4Qt/deploy/include/ConsoleAppender b/ext/Log4Qt/deploy/include/ConsoleAppender
new file mode 100644
index 0000000..16132b1
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/ConsoleAppender
@@ -0,0 +1 @@
+#include "consoleappender.h"
diff --git a/ext/Log4Qt/deploy/include/DailyRollingFileAppender b/ext/Log4Qt/deploy/include/DailyRollingFileAppender
new file mode 100644
index 0000000..0b655e0
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/DailyRollingFileAppender
@@ -0,0 +1 @@
+#include "dailyrollingfileappender.h"
diff --git a/ext/Log4Qt/deploy/include/DatabaseAppender b/ext/Log4Qt/deploy/include/DatabaseAppender
new file mode 100644
index 0000000..9f08924
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/DatabaseAppender
@@ -0,0 +1 @@
+#include "databaseappender.h"
diff --git a/ext/Log4Qt/deploy/include/DatabaseLayout b/ext/Log4Qt/deploy/include/DatabaseLayout
new file mode 100644
index 0000000..2b9c0c4
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/DatabaseLayout
@@ -0,0 +1 @@
+#include "databaselayout.h"
diff --git a/ext/Log4Qt/deploy/include/FileAppender b/ext/Log4Qt/deploy/include/FileAppender
new file mode 100644
index 0000000..60ff85e
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/FileAppender
@@ -0,0 +1 @@
+#include "fileappender.h"
diff --git a/ext/Log4Qt/deploy/include/Hierarchy b/ext/Log4Qt/deploy/include/Hierarchy
new file mode 100644
index 0000000..e48fdae
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Hierarchy
@@ -0,0 +1 @@
+#include "hierarchy.h"
diff --git a/ext/Log4Qt/deploy/include/Layout b/ext/Log4Qt/deploy/include/Layout
new file mode 100644
index 0000000..34b7a35
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Layout
@@ -0,0 +1 @@
+#include "layout.h"
diff --git a/ext/Log4Qt/deploy/include/Level b/ext/Log4Qt/deploy/include/Level
new file mode 100644
index 0000000..81f1d33
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Level
@@ -0,0 +1 @@
+#include "level.h"
diff --git a/ext/Log4Qt/deploy/include/Log4Qt b/ext/Log4Qt/deploy/include/Log4Qt
new file mode 100644
index 0000000..ca511fd
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Log4Qt
@@ -0,0 +1 @@
+#include "log4qt.h"
diff --git a/ext/Log4Qt/deploy/include/Log4QtShared b/ext/Log4Qt/deploy/include/Log4QtShared
new file mode 100644
index 0000000..c519afc
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Log4QtShared
@@ -0,0 +1 @@
+#include "log4qtshared.h"
diff --git a/ext/Log4Qt/deploy/include/LogManager b/ext/Log4Qt/deploy/include/LogManager
new file mode 100644
index 0000000..bb4b529
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/LogManager
@@ -0,0 +1 @@
+#include "logmanager.h"
diff --git a/ext/Log4Qt/deploy/include/LogStream b/ext/Log4Qt/deploy/include/LogStream
new file mode 100644
index 0000000..90f7263
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/LogStream
@@ -0,0 +1 @@
+#include "logstream.h"
diff --git a/ext/Log4Qt/deploy/include/Logger b/ext/Log4Qt/deploy/include/Logger
new file mode 100644
index 0000000..86198b3
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/Logger
@@ -0,0 +1 @@
+#include "logger.h"
diff --git a/ext/Log4Qt/deploy/include/LoggerRepository b/ext/Log4Qt/deploy/include/LoggerRepository
new file mode 100644
index 0000000..eb21725
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/LoggerRepository
@@ -0,0 +1 @@
+#include "loggerrepository.h"
diff --git a/ext/Log4Qt/deploy/include/LoggingEvent b/ext/Log4Qt/deploy/include/LoggingEvent
new file mode 100644
index 0000000..93128b4
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/LoggingEvent
@@ -0,0 +1 @@
+#include "loggingevent.h"
diff --git a/ext/Log4Qt/deploy/include/MDC b/ext/Log4Qt/deploy/include/MDC
new file mode 100644
index 0000000..80f077f
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/MDC
@@ -0,0 +1 @@
+#include "mdc.h"
diff --git a/ext/Log4Qt/deploy/include/MainthreadAppender b/ext/Log4Qt/deploy/include/MainthreadAppender
new file mode 100644
index 0000000..ca3fcec
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/MainthreadAppender
@@ -0,0 +1 @@
+#include "mainthreadappender.h"
diff --git a/ext/Log4Qt/deploy/include/NDC b/ext/Log4Qt/deploy/include/NDC
new file mode 100644
index 0000000..3c4e33b
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/NDC
@@ -0,0 +1 @@
+#include "ndc.h"
diff --git a/ext/Log4Qt/deploy/include/PatternLayout b/ext/Log4Qt/deploy/include/PatternLayout
new file mode 100644
index 0000000..e611ff3
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/PatternLayout
@@ -0,0 +1 @@
+#include "patternlayout.h"
diff --git a/ext/Log4Qt/deploy/include/PropertyConfigurator b/ext/Log4Qt/deploy/include/PropertyConfigurator
new file mode 100644
index 0000000..d7a7664
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/PropertyConfigurator
@@ -0,0 +1 @@
+#include "propertyconfigurator.h"
diff --git a/ext/Log4Qt/deploy/include/RollingFileAppender b/ext/Log4Qt/deploy/include/RollingFileAppender
new file mode 100644
index 0000000..f537b6e
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/RollingFileAppender
@@ -0,0 +1 @@
+#include "rollingfileappender.h"
diff --git a/ext/Log4Qt/deploy/include/SignalAppender b/ext/Log4Qt/deploy/include/SignalAppender
new file mode 100644
index 0000000..154dd55
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/SignalAppender
@@ -0,0 +1 @@
+#include "signalappender.h"
diff --git a/ext/Log4Qt/deploy/include/SimpleLayout b/ext/Log4Qt/deploy/include/SimpleLayout
new file mode 100644
index 0000000..a9d929f
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/SimpleLayout
@@ -0,0 +1 @@
+#include "simplelayout.h"
diff --git a/ext/Log4Qt/deploy/include/SimpleTimeLayout b/ext/Log4Qt/deploy/include/SimpleTimeLayout
new file mode 100644
index 0000000..706fd72
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/SimpleTimeLayout
@@ -0,0 +1 @@
+#include "simpletimelayout.h"
diff --git a/ext/Log4Qt/deploy/include/SystemlogAppender b/ext/Log4Qt/deploy/include/SystemlogAppender
new file mode 100644
index 0000000..7e9ade3
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/SystemlogAppender
@@ -0,0 +1 @@
+#include "systemlogappender.h"
diff --git a/ext/Log4Qt/deploy/include/TTCCLayout b/ext/Log4Qt/deploy/include/TTCCLayout
new file mode 100644
index 0000000..43703e3
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/TTCCLayout
@@ -0,0 +1 @@
+#include "ttcclayout.h"
diff --git a/ext/Log4Qt/deploy/include/TelnetAppender b/ext/Log4Qt/deploy/include/TelnetAppender
new file mode 100644
index 0000000..7334f57
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/TelnetAppender
@@ -0,0 +1 @@
+#include "telnetappender.h"
diff --git a/ext/Log4Qt/deploy/include/WriterAppender b/ext/Log4Qt/deploy/include/WriterAppender
new file mode 100644
index 0000000..72d2e50
--- /dev/null
+++ b/ext/Log4Qt/deploy/include/WriterAppender
@@ -0,0 +1 @@
+#include "writerappender.h"
diff --git a/ext/Log4Qt/project-config.cmake.in b/ext/Log4Qt/project-config.cmake.in
new file mode 100644
index 0000000..a75271e
--- /dev/null
+++ b/ext/Log4Qt/project-config.cmake.in
@@ -0,0 +1,11 @@
+get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+include(${SELF_DIR}/@PROJECT_NAME@-targets.cmake)
+
+string(TOUPPER @PROJECT_NAME@ PROJECT_TO_UPPER)
+
+add_definitions(-D${PROJECT_TO_UPPER})
+if (NOT @LOG4QT_BUILD_STATIC@)
+ add_definitions(-D${PROJECT_TO_UPPER}_IMPORTS)
+endif()
+set(${PROJECT_TO_UPPER}_INCLUDE_DIRS @TARGET_INCLUDE_DIR@)
diff --git a/ext/Log4Qt/src/Log4Qt.pri b/ext/Log4Qt/src/Log4Qt.pri
new file mode 100644
index 0000000..66b9757
--- /dev/null
+++ b/ext/Log4Qt/src/Log4Qt.pri
@@ -0,0 +1,108 @@
+
+HEADERS += $$PWD/appender.h \
+ $$PWD/appenderskeleton.h \
+ $$PWD/basicconfigurator.h \
+ $$PWD/colorconsoleappender.h \
+ $$PWD/consoleappender.h \
+ $$PWD/dailyrollingfileappender.h \
+ $$PWD/asyncappender.h \
+ $$PWD/mainthreadappender.h \
+# $$PWD/ databaseappender.h \
+# $$PWD/ databaselayout.h \
+ $$PWD/fileappender.h \
+ $$PWD/hierarchy.h \
+ $$PWD/layout.h \
+ $$PWD/level.h \
+ $$PWD/log4qt.h \
+ $$PWD/log4qtshared.h \
+ $$PWD/logger.h \
+ $$PWD/loggerrepository.h \
+ $$PWD/loggingevent.h \
+ $$PWD/logmanager.h \
+ $$PWD/mdc.h \
+ $$PWD/ndc.h \
+ $$PWD/patternlayout.h \
+ $$PWD/propertyconfigurator.h \
+ $$PWD/rollingfileappender.h \
+ $$PWD/signalappender.h \
+ $$PWD/simplelayout.h \
+ $$PWD/simpletimelayout.h \
+ $$PWD/ttcclayout.h \
+ $$PWD/telnetappender.h \
+ $$PWD/writerappender.h \
+ $$PWD/systemlogappender.h \
+ $$PWD/helpers/classlogger.h \
+ $$PWD//helpers/appenderattachable.h \
+ $$PWD/helpers/configuratorhelper.h \
+ $$PWD/helpers/datetime.h \
+ $$PWD/helpers/factory.h \
+ $$PWD/helpers/initialisationhelper.h \
+ $$PWD/helpers/logerror.h \
+ $$PWD/helpers/logobject.h \
+ $$PWD/helpers/logobjectptr.h \
+ $$PWD/helpers/optionconverter.h \
+ $$PWD/helpers/patternformatter.h \
+ $$PWD/helpers/properties.h \
+ $$PWD/helpers/dispatcher.h \
+ $$PWD/spi/filter.h \
+ $$PWD/varia/debugappender.h \
+ $$PWD/varia/denyallfilter.h \
+ $$PWD/varia/levelmatchfilter.h \
+ $$PWD/varia/levelrangefilter.h \
+ $$PWD/varia/listappender.h \
+ $$PWD/varia/nullappender.h \
+ $$PWD/varia/stringmatchfilter.h \
+ $$PWD/logstream.h
+
+SOURCES += $$PWD/appenderskeleton.cpp \
+ $$PWD/basicconfigurator.cpp \
+ $$PWD/colorconsoleappender.cpp \
+ $$PWD/consoleappender.cpp \
+ $$PWD/dailyrollingfileappender.cpp \
+ $$PWD/asyncappender.cpp \
+ $$PWD/mainthreadappender.cpp \
+# $$PWD/databaseappender.cpp \
+# $$PWD/databaselayout.cpp \
+ $$PWD/fileappender.cpp \
+ $$PWD/hierarchy.cpp \
+ $$PWD/layout.cpp \
+ $$PWD/level.cpp \
+ $$PWD/log4qt.cpp \
+ $$PWD/logger.cpp \
+ $$PWD/loggerrepository.cpp \
+ $$PWD/loggingevent.cpp \
+ $$PWD/logmanager.cpp \
+ $$PWD/mdc.cpp \
+ $$PWD/ndc.cpp \
+ $$PWD/patternlayout.cpp \
+ $$PWD/propertyconfigurator.cpp \
+ $$PWD/rollingfileappender.cpp \
+ $$PWD/signalappender.cpp \
+ $$PWD/simplelayout.cpp \
+ $$PWD/simpletimelayout.cpp \
+ $$PWD/ttcclayout.cpp \
+ $$PWD/telnetappender.cpp \
+ $$PWD/writerappender.cpp \
+ $$PWD/systemlogappender.cpp \
+ $$PWD/helpers/classlogger.cpp \
+ $$PWD/helpers/appenderattachable.cpp \
+ $$PWD/helpers/configuratorhelper.cpp \
+ $$PWD/helpers/datetime.cpp \
+ $$PWD/helpers/factory.cpp \
+ $$PWD/helpers/initialisationhelper.cpp \
+ $$PWD/helpers/logerror.cpp \
+ $$PWD/helpers/logobject.cpp \
+ $$PWD/helpers/logobjectptr.cpp \
+ $$PWD/helpers/optionconverter.cpp \
+ $$PWD/helpers/patternformatter.cpp \
+ $$PWD/helpers/properties.cpp \
+ $$PWD/helpers/dispatcher.cpp \
+ $$PWD/spi/filter.cpp \
+ $$PWD/varia/debugappender.cpp \
+ $$PWD/varia/denyallfilter.cpp \
+ $$PWD/varia/levelmatchfilter.cpp \
+ $$PWD/varia/levelrangefilter.cpp \
+ $$PWD/varia/listappender.cpp \
+ $$PWD/varia/nullappender.cpp \
+ $$PWD/varia/stringmatchfilter.cpp \
+ $$PWD/logstream.cpp
diff --git a/ext/Log4Qt/src/appender.h b/ext/Log4Qt/src/appender.h
new file mode 100755
index 0000000..a87d19a
--- /dev/null
+++ b/ext/Log4Qt/src/appender.h
@@ -0,0 +1,135 @@
+/******************************************************************************
+ *
+ * package:
+ * file: appender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ********************************************************************************/
+
+#ifndef LOG4QT_APPENDER_H
+#define LOG4QT_APPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "helpers/logobject.h"
+
+#include "helpers/logobjectptr.h"
+
+#include "logger.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Filter;
+ class Layout;
+ class LoggingEvent;
+
+ /*!
+ * \brief The class Appender is the base class for all Appenders.
+ *
+ * To allow the whole hirarchy to be an ascendant of QObject Appender is
+ * not an interface.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT Appender : public LogObject
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the Layout used by the Appender.
+ *
+ * \sa layout(), setLayout()
+ */
+ Q_PROPERTY(Layout* layout READ layout WRITE setLayout)
+
+ /*!
+ * The property holds the name of the Appender.
+ *
+ * \sa name(), setName()
+ */
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+ /*!
+ * The property holds if the Appender requires a Layout or not.
+ *
+ * \sa requiresLayout(), setRequiresLayout()
+ */
+ Q_PROPERTY(bool requiresLayout READ requiresLayout)
+
+ public:
+ Appender(QObject *pParent = 0);
+ virtual ~Appender();
+ private:
+ Appender(const Appender &rOther); // Not implemented
+ Appender &operator=(const Appender &rOther); // Not implemented
+
+ public:
+ // JAVA: ErrorHandler* errorHandler();
+ virtual Filter *filter() const = 0;
+ virtual QString name() const = 0;
+ virtual Layout *layout() const = 0;
+ virtual bool requiresLayout() const = 0;
+ // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler);
+ virtual void setLayout(Layout *pLayout) = 0;
+ virtual void setName(const QString &rName) = 0;
+
+ virtual void addFilter(Filter *pFilter) = 0;
+ virtual void clearFilters() = 0;
+ virtual void close() = 0;
+ virtual void doAppend(const LoggingEvent &rEvent) = 0;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Appender::Appender(QObject *pParent) :
+ LogObject(pParent)
+ {}
+
+ inline Appender::~Appender()
+ {}
+
+
+} // namespace Log4Qt
+
+
+//Q_DECLARE_TYPEINFO(::Appender, Q_COMPLEX_TYPE); // Use default
+//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Appender>, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_APPENDER_H
diff --git a/ext/Log4Qt/src/appenderskeleton.cpp b/ext/Log4Qt/src/appenderskeleton.cpp
new file mode 100644
index 0000000..78be62c
--- /dev/null
+++ b/ext/Log4Qt/src/appenderskeleton.cpp
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ * package:
+ * file: appenderskeleton.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "appenderskeleton.h"
+
+#include <QtCore/QDebug>
+#include "layout.h"
+#include "loggingevent.h"
+#include "logmanager.h"
+#include "spi/filter.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ ***************************************************************************/
+
+
+ /*!
+ * \brief The class RecursionGuardLocker controls a boolean flag.
+ *
+ * It is a helper class to control a boolean flag. The class sets the flag
+ * on creation and resets it on destruction.
+ */
+ class RecursionGuardLocker
+ {
+ public:
+ RecursionGuardLocker(bool *pGuard);
+ ~RecursionGuardLocker();
+ private:
+ RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented
+ RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented
+ private:
+ bool *mpGuard;
+ };
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: RecursionGuardLocker
+ ***************************************************************************/
+
+
+ inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard)
+ {
+ Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null");
+
+ mpGuard = pGuard;
+ *mpGuard = true;
+ }
+
+
+ inline RecursionGuardLocker::~RecursionGuardLocker()
+ {
+ *mpGuard = false;
+ }
+
+
+ /**************************************************************************
+ * Class implementation: AppenderSkeleton
+ **************************************************************************/
+
+
+ AppenderSkeleton::AppenderSkeleton(QObject *pParent) :
+ Appender(pParent),
+ mObjectGuard(QMutex::Recursive), // Recursive for doAppend()
+ mAppendRecursionGuard(false),
+ mIsActive(true),
+ mIsClosed(false),
+ mpLayout(0),
+ mThreshold(Level::NULL_INT),
+ mpHeadFilter(0),
+ mpTailFilter(0)
+ {
+ }
+
+
+ AppenderSkeleton::AppenderSkeleton(const bool isActive,
+ QObject *pParent) :
+ Appender(pParent),
+ mObjectGuard(QMutex::Recursive), // Recursive for doAppend()
+ mAppendRecursionGuard(false),
+ mIsActive(isActive),
+ mIsClosed(false),
+ mpLayout(0),
+ mThreshold(Level::NULL_INT),
+ mpHeadFilter(0),
+ mpTailFilter(0)
+ {
+ }
+
+
+ void AppenderSkeleton::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (requiresLayout() && !layout())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"),
+ APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR);
+ e << name();
+ logger()->error(e);
+ return;
+ }
+ mIsActive = true;
+ }
+
+
+ void AppenderSkeleton::addFilter(Filter *pFilter)
+ {
+ if(!pFilter)
+ {
+ logger()->warn("Adding null Filter to Appender '%1'", name());
+ return;
+ }
+
+ QMutexLocker locker(&mObjectGuard);
+
+ mpTailFilter = pFilter;
+ if (mpHeadFilter)
+ mpHeadFilter->setNext(pFilter);
+ else
+ mpHeadFilter = pFilter;
+ }
+
+
+ void AppenderSkeleton::clearFilters()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ mpTailFilter = 0;
+ mpHeadFilter = 0;
+ }
+
+
+ void AppenderSkeleton::close()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ mIsClosed = true;
+ mIsActive = false;
+ }
+
+ void AppenderSkeleton::customEvent(QEvent* event)
+ {
+ if (event->type() == LoggingEvent::eventId) {
+ LoggingEvent *logEvent = static_cast<LoggingEvent*>(event);
+ doAppend(*logEvent);
+ return ;
+ }
+ QObject::customEvent(event);
+ }
+
+ void AppenderSkeleton::doAppend(const LoggingEvent &rEvent)
+ {
+ // The mutex serialises concurrent access from multiple threads.
+ // - e.g. two threads using the same logger
+ // - e.g. two threads using different logger with the same appender
+ //
+ // A call from the same thread will pass the mutex (QMutex::Recursive)
+ // and get to the recursion guard. The recursion guard blocks recursive
+ // invocation and prevents a possible endless loop.
+ // - e.g. an appender logs an error with a logger that uses it
+
+ QMutexLocker locker(&mObjectGuard);
+
+ if (mAppendRecursionGuard)
+ return;
+
+ RecursionGuardLocker recursion_locker(&mAppendRecursionGuard);
+
+ if (!checkEntryConditions())
+ return;
+ if (!isAsSevereAsThreshold(rEvent.level()))
+ return;
+
+ Filter *p_filter = mpHeadFilter;
+ while(p_filter)
+ {
+ Filter::Decision decision = p_filter->decide(rEvent);
+ if (decision == Filter::ACCEPT)
+ break;
+ else if (decision == Filter::DENY)
+ return;
+ else
+ p_filter = p_filter->next();
+ }
+
+ append(rEvent);
+ }
+
+
+ bool AppenderSkeleton::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (!isActive())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"),
+ APPENDER_NOT_ACTIVATED_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+ if (isClosed())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"),
+ APPENDER_CLOSED_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+ if (requiresLayout() && !layout())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"),
+ APPENDER_USE_MISSING_LAYOUT_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/appenderskeleton.h b/ext/Log4Qt/src/appenderskeleton.h
new file mode 100644
index 0000000..f100a8f
--- /dev/null
+++ b/ext/Log4Qt/src/appenderskeleton.h
@@ -0,0 +1,230 @@
+/******************************************************************************
+ *
+ * package:
+ * file: appenderskeleton.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _APPENDERSKELETON_H
+#define _APPENDERSKELETON_H
+
+
+/******************************************************************************
+ * Dependencies
+******************************************************************************/
+
+#include "appender.h"
+#include "log4qtshared.h"
+
+#include <QtCore/QMutex>
+#include "helpers/logobjectptr.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Filter;
+ class Layout;
+ class Logger;
+ class LoggingEvent;
+
+ /*!
+ * \brief The class AppenderSkeleton implements general Appender functionality.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed. See
+ * \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT AppenderSkeleton : public Appender
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds if the Appender has been activated.
+ *
+ * \sa isActive()
+ */
+ Q_PROPERTY(bool isActive READ isActive)
+
+ /*!
+ * The property holds if the Appender has been closed.
+ *
+ * \sa isClosed()
+ */
+ Q_PROPERTY(bool isClosed READ isClosed)
+
+ /*!
+ * The property holds the threshold level used by the Appender.
+ *
+ * \sa threshold(), setThreshold()
+ */
+ Q_PROPERTY(Log4Qt::Level threshold READ threshold WRITE setThreshold)
+
+ public:
+ AppenderSkeleton(QObject *pParent = 0);
+
+ protected:
+ AppenderSkeleton(const bool isActive,
+ QObject *pParent = 0);
+
+ public:
+ // virtual ~AppenderSkeleton(); Use compiler default
+ private:
+ AppenderSkeleton(const AppenderSkeleton &rOther); // Not implemented
+ AppenderSkeleton &operator=(const AppenderSkeleton &rOther); // Not implemented
+
+ public:
+ // JAVA: ErrorHandler* errorHandler();
+ virtual Filter *filter() const;
+ virtual Layout *layout() const;
+ bool isActive() const;
+ bool isClosed() const;
+ virtual QString name() const;
+ Level threshold() const;
+ // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler);
+ virtual void setLayout(Layout *pLayout);
+ virtual void setName(const QString &rName);
+ void setThreshold(Level level);
+
+ virtual void activateOptions();
+ virtual void addFilter(Filter *pFilter);
+ virtual void clearFilters();
+ virtual void close();
+
+ /*!
+ * Performs checks and delegates the actuall appending to the subclass
+ * specific append() function.
+ *
+ * \sa append(), checkEntryConditions(), isAsSevereAsThreshold(), Filter
+ */
+ virtual void doAppend(const LoggingEvent &rEvent);
+
+ // JAVA: void finalize();
+ Filter* firstFilter() const;
+ bool isAsSevereAsThreshold(Level level) const;
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent) = 0;
+ void customEvent(QEvent* event);
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false.
+ *
+ * The checked conditions are:
+ * - That the appender has been activated (APPENDER_NOT_ACTIVATED_ERROR)
+ * - That the appender was not closed (APPENDER_CLOSED_ERROR)
+ * - That the appender has a layout set, if it requires one
+ * (logging_error(APPENDER_USE_MISSING_LAYOUT_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by doAppend(). The doAppend() function calls the subclass
+ * specific checkEntryConditions() function. The function checks the
+ * class specific conditions and calls checkEntryConditions() of
+ * it's parent class. The last function called is
+ * AppenderSkeleton::checkEntryConditions().
+ *
+ * \sa doAppend()
+ */
+ virtual bool checkEntryConditions() const;
+
+ protected:
+ mutable QMutex mObjectGuard;
+
+ private:
+ bool mAppendRecursionGuard;
+ volatile bool mIsActive;
+ volatile bool mIsClosed;
+ LogObjectPtr<Layout> mpLayout;
+ Level mThreshold;
+ LogObjectPtr<Filter> mpHeadFilter;
+ LogObjectPtr<Filter> mpTailFilter;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Filter *AppenderSkeleton::filter() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mpHeadFilter; }
+
+ inline Layout *AppenderSkeleton::layout() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mpLayout; }
+
+ inline QString AppenderSkeleton::name() const
+ { QMutexLocker locker(&mObjectGuard);
+ return objectName(); }
+
+ inline Level AppenderSkeleton::threshold() const
+ { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe
+ return mThreshold; }
+
+ inline void AppenderSkeleton::setLayout(Layout *pLayout)
+ { QMutexLocker locker(&mObjectGuard);
+ mpLayout = pLayout; }
+
+ inline void AppenderSkeleton::setName(const QString &rName)
+ { QMutexLocker locker(&mObjectGuard);
+ setObjectName(rName); }
+
+ inline void AppenderSkeleton::setThreshold(Level level)
+ { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe
+ mThreshold = level; }
+
+ inline bool AppenderSkeleton::isActive() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mIsActive; }
+
+ inline bool AppenderSkeleton::isClosed() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mIsClosed; }
+
+ inline Filter *AppenderSkeleton::firstFilter() const
+ { QMutexLocker locker(&mObjectGuard);
+ return filter(); }
+
+ inline bool AppenderSkeleton::isAsSevereAsThreshold(Level level) const
+ { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe
+ return (mThreshold <= level); }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(::AppenderSkeleton, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // _APPENDERSKELETON_H
diff --git a/ext/Log4Qt/src/asyncappender.cpp b/ext/Log4Qt/src/asyncappender.cpp
new file mode 100644
index 0000000..251f87f
--- /dev/null
+++ b/ext/Log4Qt/src/asyncappender.cpp
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: asyncappender.cpp
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "asyncappender.h"
+#include "loggingevent.h"
+#include "helpers/dispatcher.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QReadLocker>
+
+namespace Log4Qt
+{
+
+/**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+/**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Class implementation: AsyncAppender
+ **************************************************************************/
+
+
+AsyncAppender::AsyncAppender(QObject *parent) : AppenderSkeleton(parent)
+ ,mpThread(0)
+ ,mpDispatcher(0)
+{
+}
+
+AsyncAppender::~AsyncAppender()
+{
+ close();
+}
+
+bool AsyncAppender::requiresLayout() const
+{
+ return false;
+}
+
+void AsyncAppender::activateOptions()
+{
+ if (mpThread)
+ return;
+
+ mpThread = new QThread();
+ mpDispatcher = new Dispatcher();
+ mpDispatcher->setAsyncAppender(this);
+
+ mpDispatcher->moveToThread(mpThread);
+ mpThread->start();
+}
+
+void AsyncAppender::close()
+{
+ if (mpThread)
+ {
+ mpDispatcher->setAsyncAppender(0);
+ mpThread->quit();
+ mpThread->wait();
+ delete mpThread;
+ mpThread = 0;
+ delete mpDispatcher;
+ mpDispatcher = 0;
+ }
+}
+
+void AsyncAppender::callAppenders(const LoggingEvent &rEvent) const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ Appender *pAppender;
+ Q_FOREACH(pAppender, mAppenders)
+ pAppender->doAppend(rEvent);
+}
+
+void AsyncAppender::append(const LoggingEvent &rEvent)
+{
+ // Post to the event loop of the dispatcher
+ LoggingEvent *event = new LoggingEvent(rEvent);
+ qApp->postEvent(mpDispatcher, event);
+}
+
+bool AsyncAppender::checkEntryConditions() const
+{
+ if (mpThread && !mpThread->isRunning())
+ {
+ LogError
+ e =
+ LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a running dispatcher thread"),
+ APPENDER_ASNC_DISPATCHER_NOT_RUNNING);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return AppenderSkeleton::checkEntryConditions();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %AsyncAppender(name:"WA" )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+QDebug AsyncAppender::debug(QDebug &rDebug) const
+{
+ rDebug.nospace() << "AsyncAppender("
+ << "name:" << name() << " "
+ << ")";
+
+ return rDebug.space();
+}
+#endif // QT_NO_DEBUG_STREAM
+
+
+/**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/asyncappender.h b/ext/Log4Qt/src/asyncappender.h
new file mode 100644
index 0000000..d004e82
--- /dev/null
+++ b/ext/Log4Qt/src/asyncappender.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: asyncappender.h
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_ASYNCAPPENDER_H
+#define LOG4QT_ASYNCAPPENDER_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+#include "helpers/appenderattachable.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QMutex>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+class Dispatcher;
+
+/*!
+ * \brief The class AsyncAppender lets users log events asynchronously.
+ *
+ * The AsyncAppender will collect the events sent to it and then dispatch them to all the
+ * appenders that are attached to it. You can attach multiple appenders to an AsyncAppender.
+ *
+ * The AsyncAppender uses a separate thread to serve the events fromthe event loop.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ * &nbsp;
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+class LOG4QT_EXPORT AsyncAppender : public AppenderSkeleton, public AppenderAttachable
+{
+Q_OBJECT
+
+public:
+ AsyncAppender(QObject *parent = 0);
+ virtual ~AsyncAppender();
+
+ virtual bool requiresLayout() const;
+
+ virtual void activateOptions();
+ virtual void close();
+ void callAppenders(const LoggingEvent &rEvent) const;
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * AppenderSkeleton::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - dispatcher thread running (APPENDER_ASNC_DISPATCHER_NOT_RUNNING)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %AsyncAppender(name:"WA" encoding:"" immediateFlush:true
+ * isactive:false isclosed:false layout:"TTCC"
+ * referencecount:1 threshold:"NULL"
+ * writer:0x0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+private:
+ Q_DISABLE_COPY(AsyncAppender)
+
+ //! Event dispatcher trhead
+ QThread *mpThread;
+ Dispatcher *mpDispatcher;
+};
+
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::AsyncAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_AsyncAppender_H
diff --git a/ext/Log4Qt/src/basicconfigurator.cpp b/ext/Log4Qt/src/basicconfigurator.cpp
new file mode 100755
index 0000000..d6998c6
--- /dev/null
+++ b/ext/Log4Qt/src/basicconfigurator.cpp
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ * package:
+ * file: basicconfigurator.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "basicconfigurator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QThread>
+#include "consoleappender.h"
+#include "helpers/configuratorhelper.h"
+#include "helpers/logobjectptr.h"
+#include "logmanager.h"
+#include "patternlayout.h"
+#include "varia/listappender.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: BasicConfigurator
+ **************************************************************************/
+
+
+ bool BasicConfigurator::configure()
+ {
+ LogObjectPtr<ListAppender> list = new ListAppender;
+ list->setName(QLatin1String("BasicConfigurator"));
+ list->setConfiguratorList(true);
+ list->setThreshold(Level::ERROR_INT);
+ LogManager::logLogger()->addAppender(list);
+
+ PatternLayout *p_layout = new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN);
+ p_layout->setName(QLatin1String("BasicConfigurator TTCC"));
+ p_layout->activateOptions();
+ ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET);
+ p_appender->setName(QLatin1String("BasicConfigurator stdout"));
+ p_appender->activateOptions();
+ LogManager::rootLogger()->addAppender(p_appender);
+
+ LogManager::logLogger()->removeAppender(list);
+ ConfiguratorHelper::setConfigureError(list->list());
+ return (list->list().count() == 0);
+ }
+
+
+ void BasicConfigurator::configure(Appender *pAppender)
+ {
+ LogManager::rootLogger()->addAppender(pAppender);
+ }
+
+
+ void BasicConfigurator::resetConfiguration()
+ {
+ LogManager::resetConfiguration();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/basicconfigurator.h b/ext/Log4Qt/src/basicconfigurator.h
new file mode 100755
index 0000000..6189cc0
--- /dev/null
+++ b/ext/Log4Qt/src/basicconfigurator.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ *
+ * package:
+ * file: basicconfigurator.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_BASICCONFIGURATOR_H
+#define LOG4QT_BASICCONFIGURATOR_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include <QtCore/Qt>
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Appender;
+
+ /*!
+ * \brief The class BasicConfigurator provides a simple package
+ * configuration.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT BasicConfigurator
+ {
+ private:
+ BasicConfigurator(); // Not implemented
+ // BasicConfigurator(const BasicConfigurator &rOther); // Use compiler default
+ // virtual ~BasicConfigurator(); // Use compiler default
+ // BasicConfigurator &operator=(const BasicConfigurator &rOther); // Use compiler default
+
+ public:
+ static bool configure();
+ static void configure(Appender *pAppender);
+ static void resetConfiguration();
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namspace
+
+
+// Q_DECLARE_TYPEINFO(::BasicConfigurator, Q_MOVABLE_TYPE); // Use default
+
+
+#endif // _BASICCONFIGURATOR_H
diff --git a/ext/Log4Qt/src/colorconsoleappender.cpp b/ext/Log4Qt/src/colorconsoleappender.cpp
new file mode 100644
index 0000000..e83fafd
--- /dev/null
+++ b/ext/Log4Qt/src/colorconsoleappender.cpp
@@ -0,0 +1,290 @@
+/******************************************************************************
+ *
+ * package: log4qt
+ * file: colorconsoleappender.cpp
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "colorconsoleappender.h"
+
+#include <QtCore/QTextStream>
+
+#include "loggingevent.h"
+#include "layout.h"
+
+#define NIX_BACK_BLACK 40
+#define NIX_BACK_RED 41
+#define NIX_BACK_GREEN 42
+#define NIX_BACK_YELLOW 43
+#define NIX_BACK_BLUE 44
+#define NIX_BACK_MAGNETTA 45
+#define NIX_BACK_CYAN 46
+#define NIX_BACK_GRAY 47
+
+#define NIX_FORE_BLACK 30
+#define NIX_FORE_RED 31
+#define NIX_FORE_GREEN 32
+#define NIX_FORE_YELLOW 33
+#define NIX_FORE_BLUE 34
+#define NIX_FORE_MAGNETTA 35
+#define NIX_FORE_CYAN 36
+#define NIX_FORE_GRAY 37
+
+#define NIX_FORE_BOLD 1
+
+#define NIX_DEFAULT 0
+
+#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+//#include <windows.h>
+#define WIN_BACK_BLACK 0
+#define WIN_BACK_RED BACKGROUND_RED
+#define WIN_BACK_LIGHT_RED BACKGROUND_RED | BACKGROUND_INTENSITY
+#define WIN_BACK_GREEN BACKGROUND_GREEN
+#define WIN_BACK_LIGHT_GREEN BACKGROUND_GREEN | BACKGROUND_INTENSITY
+#define WIN_BACK_YELLOW BACKGROUND_GREEN | BACKGROUND_RED
+#define WIN_BACK_LIGHT_YELLOW BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
+#define WIN_BACK_BLUE BACKGROUND_BLUE
+#define WIN_BACK_LIGHT_BLUE BACKGROUND_BLUE | BACKGROUND_INTENSITY
+#define WIN_BACK_MAGNETTA BACKGROUND_RED | BACKGROUND_BLUE
+#define WIN_BACK_LIGHT_MAGNETTA BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY
+#define WIN_BACK_CYAN BACKGROUND_BLUE | BACKGROUND_GREEN
+#define WIN_BACK_LIGHT_CYAN BACKGROUND_BLUE | BACKGROUND_GREEN
+#define WIN_BACK_GRAY BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED
+#define WIN_BACK_WHITE BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
+
+#define WIN_FORE_BLACK 0
+#define WIN_FORE_RED FOREGROUND_RED
+#define WIN_FORE_LIGHT_RED FOREGROUND_RED | FOREGROUND_INTENSITY
+#define WIN_FORE_GREEN FOREGROUND_GREEN
+#define WIN_FORE_LIGHT_GREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY
+#define WIN_FORE_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
+#define WIN_FORE_LIGHT_YELLOW FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
+#define WIN_FORE_BLUE FOREGROUND_BLUE
+#define WIN_FORE_LIGHT_BLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY
+#define WIN_FORE_MAGNETTA FOREGROUND_RED | FOREGROUND_BLUE
+#define WIN_FORE_LIGHT_MAGNETTA FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
+#define WIN_FORE_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN
+#define WIN_FORE_LIGHT_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN
+#define WIN_FORE_GRAY FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+#define WIN_FORE_WHITE FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
+
+#define WIN_FORE_BOLD FOREGROUND_INTENSITY
+
+#define WIN_DEFAULT FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+
+static void colorOutputString(HANDLE hConsole, const QString& output)
+{
+ QString message = output;
+
+ // save colors
+ CONSOLE_SCREEN_BUFFER_INFO cbi;
+ GetConsoleScreenBufferInfo(hConsole,&cbi);
+
+ wchar_t *wideMessage;
+
+ QStringList colorizedMessage = message.split('\033');
+
+ int actualSize;
+ DWORD out;
+
+ WORD color = 0;
+ WORD newColor = 0;
+ QString parsedWordString;
+ QStringList escParams;
+ int indexOfM;
+ // display first part of message
+ if (!colorizedMessage.at(0).isEmpty()) {
+ wideMessage = new wchar_t [colorizedMessage.at(0).size()];
+ actualSize = colorizedMessage.at(0).toWCharArray(wideMessage);
+ WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0);
+ delete [] wideMessage;
+ colorizedMessage.removeAt(0);
+ }
+ foreach (QString it, colorizedMessage) {
+ // color setted
+ if (it.startsWith("[")) {
+ indexOfM = it.indexOf('m');
+ // not esc-sequence
+ if (indexOfM != -1) {
+ parsedWordString = it.mid(1, indexOfM - 1);
+
+ escParams = parsedWordString.split(';');
+ foreach(QString param, escParams) {
+ color = param.toUInt();
+ switch(color) {
+ case NIX_DEFAULT:
+ newColor = WIN_DEFAULT;
+ break;
+ case NIX_FORE_BOLD:
+ newColor |= WIN_FORE_BOLD;
+ break;
+ case NIX_BACK_BLACK :
+ newColor = (newColor & 0x0f) | WIN_BACK_BLACK;
+ break;
+ case NIX_BACK_RED :
+ newColor = (newColor & 0x0f) | WIN_BACK_RED;
+ break;
+ case NIX_BACK_GREEN :
+ newColor = (newColor & 0x0f) | WIN_BACK_GREEN;
+ break;
+ case NIX_BACK_YELLOW :
+ newColor = (newColor & 0x0f) | WIN_BACK_YELLOW;
+ break;
+ case NIX_BACK_BLUE :
+ newColor = (newColor & 0x0f) | WIN_BACK_BLUE;
+ break;
+ case NIX_BACK_MAGNETTA :
+ newColor = (newColor & 0x0f) | WIN_BACK_MAGNETTA;
+ break;
+ case NIX_BACK_CYAN :
+ newColor = (newColor & 0x0f) | WIN_BACK_CYAN;
+ break;
+ case NIX_BACK_GRAY :
+ newColor = (newColor & 0x0f) | WIN_BACK_GRAY;
+ break;
+ case NIX_FORE_BLACK :
+ newColor = (newColor & 0xF8)| WIN_FORE_BLACK;
+ break;
+ case NIX_FORE_RED :
+ newColor = (newColor & 0xF8) | WIN_FORE_RED;
+ break;
+ case NIX_FORE_GREEN :
+ newColor = (newColor & 0xF8) | WIN_FORE_GREEN;
+ break;
+ case NIX_FORE_YELLOW :
+ newColor = (newColor & 0xF8) | WIN_FORE_YELLOW;
+ break;
+ case NIX_FORE_BLUE :
+ newColor = (newColor & 0xF8) | WIN_FORE_BLUE;
+ break;
+ case NIX_FORE_MAGNETTA :
+ newColor = (newColor & 0xF8) | WIN_FORE_MAGNETTA;
+ break;
+ case NIX_FORE_CYAN :
+ newColor = (newColor & 0xF8) | WIN_FORE_CYAN;
+ break;
+ case NIX_FORE_GRAY :
+ newColor = (newColor & 0xF8) | WIN_FORE_GRAY;
+ break;
+ default:break;
+ }
+ }
+ it = it.mid(indexOfM + 1);
+
+ SetConsoleTextAttribute(hConsole, newColor);
+ }
+ }
+
+ wideMessage = new wchar_t [it.size()];
+ actualSize = it.toWCharArray(wideMessage);
+ WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0);
+ delete [] wideMessage;
+ }
+ // load old colors
+ SetConsoleTextAttribute(hConsole, cbi.wAttributes);
+
+ //qDebug() << colorizedMessage;
+
+}
+#endif
+
+namespace Log4Qt {
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+ /**************************************************************************
+ * Class implementation: ColorConsoleAppender
+ **************************************************************************/
+
+ ColorConsoleAppender::ColorConsoleAppender(QObject *pParent) :
+ ConsoleAppender(pParent)
+ {
+ }
+
+ ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, QObject *pParent) :
+ ConsoleAppender(pLayout, pParent)
+ {
+ }
+
+ ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout,
+ const QString &rTarget, QObject *pParent) :
+ ConsoleAppender(pLayout, rTarget, pParent)
+ {
+ }
+
+ ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, Target target,
+ QObject *pParent) :
+ ConsoleAppender(pLayout, target, pParent)
+ {
+ }
+
+#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+void ColorConsoleAppender::append(const LoggingEvent &rEvent)
+{
+ QString message = layout()->format(rEvent);
+
+ colorOutputString(hConsole, message);
+
+ // обрабатываем ошибки, по умолчанию метод не реализован
+ if (handleIoErrors())
+ return;
+
+ if (immediateFlush())
+ {
+ writer()->flush();
+ if (handleIoErrors())
+ return;
+ }
+}
+
+void ColorConsoleAppender::activateOptions()
+{
+ ConsoleAppender::activateOptions();
+
+ if (target() == "STDOUT_TARGET")
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ else
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
+}
+
+void ColorConsoleAppender::close()
+{
+ ConsoleAppender::close();
+ CloseHandle(hConsole);
+}
+
+#endif
+
+/******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/colorconsoleappender.h b/ext/Log4Qt/src/colorconsoleappender.h
new file mode 100755
index 0000000..5027b5d
--- /dev/null
+++ b/ext/Log4Qt/src/colorconsoleappender.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * package: log4qt
+ * file: colorconsoleappender.h
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _COLORCONSOLEAPPENDER_H
+#define _COLORCONSOLEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "consoleappender.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtCore/QRegExp>
+
+// if we are in WIN*
+#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#include <windows.h>
+#endif
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QFile;
+class QTextStream;
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class ColorConsoleAppender appends to stdout or stderr with color formatting.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT ColorConsoleAppender : public ConsoleAppender
+ {
+ Q_OBJECT
+
+ public:
+
+ ColorConsoleAppender(QObject *pParent = 0);
+ ColorConsoleAppender(Layout *pLayout,
+ QObject *pParent = 0);
+ ColorConsoleAppender(Layout *pLayout,
+ const QString &rTarget,
+ QObject *pParent = 0);
+
+ /*!
+ * Creates a ConsoleAppender with the layout \a pLayout, the target
+ * value specified by the \a target constant and the parent
+ * \a pParent.
+ */
+ ColorConsoleAppender(Layout *pLayout,
+ Target target,
+ QObject *pParent = 0);
+ // if we are in WIN*
+ #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+
+ virtual void activateOptions();
+
+ virtual void close();
+protected:
+ virtual void append(const LoggingEvent& rEvent);
+ private:
+ HANDLE hConsole;
+ #endif
+
+ };
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+} // namespace Log4Qt
+
+
+#endif // #ifndef _COLORCONSOLEAPPENDER_H
diff --git a/ext/Log4Qt/src/consoleappender.cpp b/ext/Log4Qt/src/consoleappender.cpp
new file mode 100755
index 0000000..c33159e
--- /dev/null
+++ b/ext/Log4Qt/src/consoleappender.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ *
+ * package:
+ * file: consoleappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "consoleappender.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+#include "helpers/optionconverter.h"
+#include "layout.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ConsoleAppender
+ **************************************************************************/
+
+
+ ConsoleAppender::ConsoleAppender(QObject *pParent) :
+ WriterAppender(pParent),
+ mTarget(STDOUT_TARGET),
+ mpTextStream(0)
+ {
+ }
+
+
+ ConsoleAppender::ConsoleAppender(Layout *pLayout,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mTarget(STDOUT_TARGET),
+ mpTextStream(0)
+ {
+ }
+
+
+ ConsoleAppender::ConsoleAppender(Layout *pLayout,
+ const QString &rTarget,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mTarget(STDOUT_TARGET),
+ mpTextStream(0)
+ {
+ setTarget(rTarget);
+ }
+
+
+ ConsoleAppender::ConsoleAppender(Layout *pLayout,
+ Target target,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mTarget(target),
+ mpTextStream(0)
+ {
+ }
+
+
+ ConsoleAppender::~ConsoleAppender()
+ {
+ close();
+
+ }
+
+
+ QString ConsoleAppender::target() const
+ {
+ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+
+ if (mTarget == STDOUT_TARGET)
+ return QLatin1String("STDOUT_TARGET");
+ else
+ return QLatin1String("STDERR_TARGET");
+ }
+
+
+ void ConsoleAppender::setTarget(const QString &rTarget)
+ {
+ bool ok;
+ Target target = static_cast<Target>(OptionConverter::toTarget(rTarget, &ok));
+ if (ok)
+ setTarget(target);
+ }
+
+
+ void ConsoleAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ closeStream();
+
+ if (mTarget == STDOUT_TARGET)
+ mpTextStream = new QTextStream(stdout);
+ else
+ mpTextStream = new QTextStream(stderr);
+ setWriter(mpTextStream);
+
+ WriterAppender::activateOptions();
+ }
+
+
+ void ConsoleAppender::close()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (isClosed())
+ return;
+
+ WriterAppender::close();
+ closeStream();
+ }
+
+
+ void ConsoleAppender::closeStream()
+ {
+ // Q_ASSERT_X(, "ConsoleAppender::closeStream()", "Lock must be held by caller")
+
+ setWriter(0);
+ delete mpTextStream;
+ mpTextStream = 0;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug ConsoleAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+ QString target;
+ if (mTarget == STDOUT_TARGET)
+ target = QLatin1String("STDOUT");
+ else
+ target = QLatin1String("STDERR");
+
+ rDebug.nospace() << "ConsoleAppender("
+ << "name:" << name() << " "
+ << "filter:" << firstFilter() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "target:" << target << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/consoleappender.h b/ext/Log4Qt/src/consoleappender.h
new file mode 100755
index 0000000..c2b3f9c
--- /dev/null
+++ b/ext/Log4Qt/src/consoleappender.h
@@ -0,0 +1,160 @@
+/******************************************************************************
+ *
+ * package:
+ * file: consoleappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _CONSOLEAPPENDER_H
+#define _CONSOLEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "writerappender.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QFile;
+class QTextStream;
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class ConsoleAppender appends to stdout or stderr.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT ConsoleAppender : public WriterAppender
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the target used by the appender.
+ *
+ * The default is STDOUT_TARGET for the standard output.
+ *
+ * \sa Target, target(), setTarget()
+ */
+ Q_PROPERTY(QString target READ target WRITE setTarget)
+
+ public:
+ /*!
+ * The enum defines the possible output targets
+ *
+ * \sa target(), setTarget()
+ */
+ enum Target {
+ /*! The output target is standard out. */
+ STDOUT_TARGET,
+ /*! The output target is standard error. */
+ STDERR_TARGET
+ };
+ Q_ENUMS(Target)
+
+ ConsoleAppender(QObject *pParent = 0);
+ ConsoleAppender(Layout *pLayout,
+ QObject *pParent = 0);
+ ConsoleAppender(Layout *pLayout,
+ const QString &rTarget,
+ QObject *pParent = 0);
+
+ /*!
+ * Creates a ConsoleAppender with the layout \a pLayout, the target
+ * value specified by the \a target constant and the parent
+ * \a pParent.
+ */
+ ConsoleAppender(Layout *pLayout,
+ Target target,
+ QObject *pParent = 0);
+
+ virtual ~ConsoleAppender();
+ private:
+ ConsoleAppender(const ConsoleAppender &rOther); // Not implemented
+ ConsoleAppender &operator=(const ConsoleAppender &rOther); // Not implemented
+
+ public:
+ // JAVA: bool follow() const;
+ QString target() const;
+ // JAVA: void setFollow(bool follow);
+ void setTarget(const QString &rTarget);
+
+ /*!
+ * Sets the target to the value specified by the \a target constant.
+ */
+ void setTarget(Target target);
+
+ virtual void activateOptions();
+ virtual void close();
+
+ protected:
+ void closeStream();
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %ConsoleAppender(name:"CA" filter:0x0 isactive:true isclosed:false
+ * layout:"PL" target:"STDERR" referenceCount:1
+ * threshold:"WARN_SET")
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif // QT_NO_DEBUG_STREAM
+
+ private:
+ volatile Target mTarget;
+ QTextStream *mpTextStream;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline void ConsoleAppender::setTarget(Target target)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mTarget = target; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(::ConsoleAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // _CONSOLEAPPENDER_H
diff --git a/ext/Log4Qt/src/dailyrollingfileappender.cpp b/ext/Log4Qt/src/dailyrollingfileappender.cpp
new file mode 100755
index 0000000..a385d10
--- /dev/null
+++ b/ext/Log4Qt/src/dailyrollingfileappender.cpp
@@ -0,0 +1,352 @@
+/******************************************************************************
+ *
+ * package:
+ * file: dailyrollingfileappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "dailyrollingfileappender.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QMetaEnum>
+#include <QtCore/QTextCodec>
+#include "helpers/datetime.h"
+#include "layout.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DailyRollingFileAppender
+ **************************************************************************/
+
+
+ DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) :
+ FileAppender(pParent),
+ mDatePattern()
+ {
+ setDatePattern(DAILY_ROLLOVER);
+ }
+
+
+ DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ const QString &rDatePattern,
+ QObject *pParent) :
+ FileAppender(pLayout, rFileName, pParent),
+ mDatePattern()
+ {
+ setDatePattern(rDatePattern);
+ }
+
+
+ DailyRollingFileAppender::~DailyRollingFileAppender()
+ {
+ close();
+ }
+
+
+ void DailyRollingFileAppender::setDatePattern(DatePattern datePattern)
+ {
+ switch (datePattern)
+ {
+ case MINUTELY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm"));
+ break;
+ case HOURLY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh"));
+ break;
+ case HALFDAILY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-MM-dd-a"));
+ break;
+ case DAILY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-MM-dd"));
+ break;
+ case WEEKLY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-ww"));
+ break;
+ case MONTHLY_ROLLOVER:
+ setDatePattern(QLatin1String("'.'yyyy-MM"));
+ break;
+ default:
+ Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant");
+ setDatePattern(DAILY_ROLLOVER);
+ };
+ }
+
+
+ void DailyRollingFileAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ computeFrequency();
+ if (!mActiveDatePattern.isEmpty())
+ {
+ computeRollOverTime();
+ FileAppender::activateOptions();
+ }
+ }
+
+
+ void DailyRollingFileAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller")
+
+ if (QDateTime::currentDateTime() > mRollOverTime)
+ rollOver();
+ FileAppender::append(rEvent);
+ }
+
+
+ bool DailyRollingFileAppender::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (mActiveDatePattern.isEmpty())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"),
+ APPENDER_USE_INVALID_PATTERN_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return FileAppender::checkEntryConditions();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+ QString codec_name;
+ if (encoding())
+ codec_name = QLatin1String(encoding()->name());
+
+ rDebug.nospace() << "DailyRollingFileAppender("
+ << "name:" << name() << " "
+ << "activedatepattern:" << mActiveDatePattern << " "
+ << "appendfile:" << appendFile() << " "
+ << "bufferedio:" << bufferedIo() << " "
+ << "datepattern:" << datePattern() << " "
+ << "encoding:" << codec_name << " "
+ << "frequency:" << frequencyToString() << " "
+ << "file:" << file() << " "
+ << "filter:" << firstFilter() << " "
+ << "immediateflush:" << immediateFlush() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "referencecount:" << referenceCount() << " "
+ << "rollovertime:" << mRollOverTime
+ << "threshold:" << threshold().toString()
+ << "writer:" << writer()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+ void DailyRollingFileAppender::computeFrequency()
+ {
+ // Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller")
+
+ const DateTime start_time(QDate(1999, 1, 1), QTime(0, 0));
+ const QString start_string = start_time.toString(mDatePattern);
+ mActiveDatePattern.clear();
+
+ if (start_string != static_cast<DateTime>(start_time.addSecs(60)).toString(mDatePattern))
+ mFrequency = MINUTELY_ROLLOVER;
+ else if (start_string != static_cast<DateTime>(start_time.addSecs(60 * 60)).toString(mDatePattern))
+ mFrequency = HOURLY_ROLLOVER;
+ else if (start_string != static_cast<DateTime>(start_time.addSecs(60 * 60 * 12)).toString(mDatePattern))
+ mFrequency = HALFDAILY_ROLLOVER;
+ else if (start_string != static_cast<DateTime>(start_time.addDays(1)).toString(mDatePattern))
+ mFrequency = DAILY_ROLLOVER;
+ else if (start_string != static_cast<DateTime>(start_time.addDays(7)).toString(mDatePattern))
+ mFrequency = WEEKLY_ROLLOVER;
+ else if (start_string != static_cast<DateTime>(start_time.addMonths(1)).toString(mDatePattern))
+ mFrequency = MONTHLY_ROLLOVER;
+ else
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"),
+ APPENDER_INVALID_PATTERN_ERROR);
+ e << mDatePattern << name();
+ logger()->error(e);
+ return;
+ }
+
+ mActiveDatePattern = mDatePattern;
+ logger()->trace("Frequency set to %2 using date pattern %1",
+ mActiveDatePattern,
+ frequencyToString());
+ }
+
+
+ void DailyRollingFileAppender::computeRollOverTime()
+ {
+ // Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller")
+ Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern");
+
+ QDateTime now = QDateTime::currentDateTime();
+ QDate now_date = now.date();
+ QTime now_time = now.time();
+ QDateTime start;
+
+ switch (mFrequency)
+ {
+ case MINUTELY_ROLLOVER:
+ {
+ start = QDateTime(now_date,
+ QTime(now_time.hour(),
+ now_time.minute(),
+ 0, 0));
+ mRollOverTime = start.addSecs(60);
+ }
+ break;
+ case HOURLY_ROLLOVER:
+ {
+ start = QDateTime(now_date,
+ QTime(now_time.hour(),
+ 0, 0, 0));
+ mRollOverTime = start.addSecs(60*60);
+ }
+ break;
+ case HALFDAILY_ROLLOVER:
+ {
+ int hour = now_time.hour();
+ if (hour >= 12)
+ hour = 12;
+ else
+ hour = 0;
+ start = QDateTime(now_date,
+ QTime(hour, 0, 0, 0));
+ mRollOverTime = start.addSecs(60*60*12);
+ }
+ break;
+ case DAILY_ROLLOVER:
+ {
+ start = QDateTime(now_date,
+ QTime(0, 0, 0, 0));
+ mRollOverTime = start.addDays(1);
+ }
+ break;
+ case WEEKLY_ROLLOVER:
+ {
+ // QT numbers the week days 1..7. The week starts on Monday.
+ // Change it to being numbered 0..6, starting with Sunday.
+ int day = now_date.dayOfWeek();
+ if (day == Qt::Sunday)
+ day = 0;
+ start = QDateTime(now_date,
+ QTime(0, 0, 0, 0)).addDays(-1 * day);
+ mRollOverTime = start.addDays(7);
+ }
+ break;
+ case MONTHLY_ROLLOVER:
+ {
+ start = QDateTime(QDate(now_date.year(),
+ now_date.month(),
+ 1),
+ QTime(0, 0, 0, 0));
+ mRollOverTime = start.addMonths(1);
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant");
+ mRollOverTime = QDateTime::fromTime_t(0);
+ }
+
+ mRollOverSuffix = static_cast<DateTime>(start).toString(mActiveDatePattern);
+ Q_ASSERT_X(static_cast<DateTime>(now).toString(mActiveDatePattern) == mRollOverSuffix,
+ "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval");
+ Q_ASSERT_X(mRollOverSuffix != static_cast<DateTime>(mRollOverTime).toString(mActiveDatePattern),
+ "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover");
+
+ logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3",
+ now,
+ start,
+ mRollOverTime);
+ }
+
+
+ QString DailyRollingFileAppender::frequencyToString() const
+ {
+ QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern"));
+ return QLatin1String(meta_enum.valueToKey(mFrequency));
+ }
+
+
+ void DailyRollingFileAppender::rollOver()
+ {
+ // Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller")
+ Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern");
+
+ QString roll_over_suffix = mRollOverSuffix;
+ computeRollOverTime();
+ if (roll_over_suffix == mRollOverSuffix)
+ return;
+
+ closeFile();
+
+ QString target_file_name = file() + roll_over_suffix;
+ QFile f(target_file_name);
+ if (f.exists() && !removeFile(f))
+ return;
+ f.setFileName(file());
+ if (!renameFile(f, target_file_name))
+ return;
+ openFile();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/dailyrollingfileappender.h b/ext/Log4Qt/src/dailyrollingfileappender.h
new file mode 100755
index 0000000..f01658b
--- /dev/null
+++ b/ext/Log4Qt/src/dailyrollingfileappender.h
@@ -0,0 +1,196 @@
+/******************************************************************************
+ *
+ * package:
+ * file: dailyrollingfileappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _DAILYROLLINGFILEAPPENDER_H
+#define _DAILYROLLINGFILEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "fileappender.h"
+
+#include <QtCore/QDateTime>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DailyRollingFileAppender extends FileAppender so that the
+ * underlying file is rolled over at a specified frequency.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed. See
+ * \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT DailyRollingFileAppender : public FileAppender
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the date pattern used by the appender.
+ *
+ * The default is DAILY_ROLLOVER for rollover at midnight each day.
+ *
+ * \sa datePattern(), setDatePattern()
+ */
+ Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern)
+
+ public:
+ /*!
+ * The enum DatePattern defines constants for date patterns.
+ *
+ * \sa setDatePattern(DatePattern)
+ */
+ enum DatePattern
+ {
+ /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */
+ MINUTELY_ROLLOVER = 0,
+ /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */
+ HOURLY_ROLLOVER,
+ /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */
+ HALFDAILY_ROLLOVER,
+ /*! The daily date pattern string is "'.'yyyy-MM-dd". */
+ DAILY_ROLLOVER,
+ /*! The weekly date pattern string is "'.'yyyy-ww". */
+ WEEKLY_ROLLOVER,
+ /*! The monthly date pattern string is "'.'yyyy-MM". */
+ MONTHLY_ROLLOVER
+ };
+ Q_ENUMS(DatePattern)
+
+ DailyRollingFileAppender(QObject *pParent = 0);
+ DailyRollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ const QString &rDatePattern,
+ QObject *pParent = 0);
+ virtual ~DailyRollingFileAppender();
+ private:
+ DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented
+ DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented
+
+ public:
+ QString datePattern() const;
+
+ /*!
+ * Sets the datePattern to the value specified by the \a datePattern
+ * constant.
+ */
+ void setDatePattern(DatePattern datePattern);
+
+ void setDatePattern(const QString &rDatePattern);
+
+ virtual void activateOptions();
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * FileAppender::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm"
+ * appendfile:false bufferedio:true
+ * datepattern:"'.'yyyy-MM-dd-hh-mm"
+ * encoding:"" frequency:"MINUTELY_ROLLOVER"
+ * file:"log.txt" filter:0x0 immediateflush:true
+ * isactive:true isclosed:false layout:"TTCC"
+ * referencecount:1
+ * rollovertime:QDateTime("Mon Oct 22 05:23:00 2007")
+ * threshold: "NULL" writer: 0x0 )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ void computeFrequency();
+ void computeRollOverTime();
+ QString frequencyToString() const;
+ void rollOver();
+
+ private:
+ QString mDatePattern;
+ DatePattern mFrequency;
+ QString mActiveDatePattern;
+ QDateTime mRollOverTime;
+ QString mRollOverSuffix;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QString DailyRollingFileAppender::datePattern() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mDatePattern; }
+
+ inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern)
+ { QMutexLocker locker(&mObjectGuard);
+ mDatePattern = rDatePattern; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(::DailyRollingFileAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // _DAILYROLLINGFILEAPPENDER_H
diff --git a/ext/Log4Qt/src/databaseappender.cpp b/ext/Log4Qt/src/databaseappender.cpp
new file mode 100755
index 0000000..7b1900d
--- /dev/null
+++ b/ext/Log4Qt/src/databaseappender.cpp
@@ -0,0 +1,224 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: databaseappender.cpp
+ * created: Marth 2010
+ * author: Michael Filonenko
+ *
+ *
+ * Copyright 2010 Michael Filonenko
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "databaseappender.h"
+
+#include <QtCore/QDebug>
+
+#include <QtSql/QSqlDriver>
+#include <QtSql/QSqlQuery>
+#include <QtSql/QSqlRecord>
+#include <QtSql/QSqlField>
+#include <QtSql/QSqlError>
+
+
+#include "databaselayout.h"
+#include "loggingevent.h"
+
+#include "helpers/datetime.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DatabaseAppender
+ **************************************************************************/
+
+
+ DatabaseAppender::DatabaseAppender(QObject *pParent) :
+ AppenderSkeleton(false, pParent)
+ , connectionName(QSqlDatabase::defaultConnection)
+ , tableName(QString::null)
+ {
+ }
+
+
+ DatabaseAppender::DatabaseAppender(Layout *pLayout,
+ QObject *pParent) :
+ AppenderSkeleton(false, pParent)
+ , connectionName(QSqlDatabase::defaultConnection)
+ , tableName(QString::null)
+ {
+ setLayout(pLayout);
+ }
+
+
+ DatabaseAppender::DatabaseAppender(Layout *pLayout
+ ,const QString& tableName
+ ,const QString& connection
+ ,QObject *pParent) :
+ AppenderSkeleton(false, pParent)
+ , connectionName(connection)
+ , tableName(tableName)
+ {
+ setLayout(pLayout);
+ }
+
+
+ DatabaseAppender::~DatabaseAppender()
+ {
+ close();
+ }
+
+
+ void DatabaseAppender::setConnection(const QString& connection)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (connectionName == connection)
+ return;
+
+ connectionName = connection;
+ }
+
+
+ void DatabaseAppender::setTable(const QString& table)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (table == tableName)
+ return;
+
+ tableName = table;
+ }
+
+
+ void DatabaseAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!QSqlDatabase::contains(connectionName) || tableName.isEmpty())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires sql connection and table and has no connection or table set")
+ , APPENDER_MISSING_DATABASE_OR_TABLE_ERROR);
+ e << name();
+ logger()->error(e);
+ return;
+ }
+
+ AppenderSkeleton::activateOptions();
+ }
+
+
+
+ bool DatabaseAppender::requiresLayout() const
+ {
+ return true;
+ }
+
+
+ void DatabaseAppender::append(const LoggingEvent &rEvent)
+ {
+ DatabaseLayout *databaseLayout = qobject_cast<DatabaseLayout *>(layout());
+
+ if (databaseLayout) {
+ QSqlRecord record = databaseLayout->formatRecord(rEvent);
+
+ QSqlDatabase database = QSqlDatabase::database(connectionName);
+ QSqlQuery query(database);
+ if (!query.exec(database.driver()->sqlStatement(QSqlDriver::InsertStatement
+ , tableName, record, false)))
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Sql query exec error: '%1'"),
+ APPENDER_EXEC_SQL_QUERY_ERROR,
+ Q_FUNC_INFO);
+ e << query.lastQuery() + " " + query.lastError().text();
+ logger()->error(e);
+ }
+ } else {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' with invalid layout"),
+ APPENDER_INVALID_DATABASE_LAYOUT_ERROR);
+ e << name();
+ logger()->error(e);
+ }
+ }
+
+
+ bool DatabaseAppender::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "DatabaseAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (!QSqlDatabase::contains(connectionName) || tableName.isEmpty())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' with invalid database or empty table name"),
+ APPENDER_MISSING_DATABASE_OR_TABLE_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return AppenderSkeleton::checkEntryConditions();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug DatabaseAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "DatabaseAppender("
+ << "name:" << name() << " "
+ << "connection:" << connectionName << " "
+ << "table:" << tableName
+ << "filter:" << firstFilter()
+ << "isactive:" << isActive()
+ << "isclosed:" << isClosed()
+ << "layout:" << layout_name
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+ /******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/databaseappender.h b/ext/Log4Qt/src/databaseappender.h
new file mode 100755
index 0000000..815fb2b
--- /dev/null
+++ b/ext/Log4Qt/src/databaseappender.h
@@ -0,0 +1,161 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: databaseappender.h
+ * created: Marth 2010
+ * author: Michael Filonenko
+ *
+ *
+ * Copyright 2010 Michael Filonenko
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _DATABASEAPPENDER_H
+#define _DATABASEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+#include <QtSql/QSqlDatabase>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DatabaseAppender appends log events to a sql database.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ * &nbsp;
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT DatabaseAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds sql database connection the appender uses.
+ *
+ * The default is null to use the codec the writer has set.
+ *
+ * \sa connection(), setConnection()
+ */
+ Q_PROPERTY(QString connection READ connection WRITE setConnection)
+
+ /*!
+ * The property holds sql database table name
+ *
+ \sa table(), setTable()
+ */
+ Q_PROPERTY(QString table READ table WRITE setTable)
+ public:
+ DatabaseAppender(QObject *pParent = 0);
+ DatabaseAppender(Layout *pLayout,
+ QObject *pParent = 0);
+ DatabaseAppender(Layout *pLayout
+ ,const QString& tableName
+ ,const QString& connection = QSqlDatabase::defaultConnection
+ ,QObject *pParent = 0);
+ virtual ~DatabaseAppender();
+
+ private:
+ DatabaseAppender(const DatabaseAppender &rOther); // Not implemented
+ DatabaseAppender &operator=(const DatabaseAppender &rOther); // Not implemented
+
+ public:
+ virtual bool requiresLayout() const;
+
+ QString connection() const;
+ QString table() const;
+
+ void setConnection(const QString& connection);
+ void setTable(const QString& table);
+
+ virtual void activateOptions();
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * AppenderSkeleton::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+ void closeWriter();
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %WriterAppender(name:"WA" encoding:"" immediateFlush:true
+ * isactive:false isclosed:false layout:"TTCC"
+ * referencecount:1 threshold:"NULL"
+ * writer:0x0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ private:
+ QString connectionName;
+ QString tableName;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QString DatabaseAppender::connection() const
+ { QMutexLocker locker(&mObjectGuard);
+ return connectionName; }
+
+ inline QString DatabaseAppender::table() const
+ { QMutexLocker locker(&mObjectGuard);
+ return tableName; }
+
+} // namespace Log4Qt
+
+
+#endif // _DATABASEAPPENDER_H
diff --git a/ext/Log4Qt/src/databaselayout.cpp b/ext/Log4Qt/src/databaselayout.cpp
new file mode 100755
index 0000000..06cdb34
--- /dev/null
+++ b/ext/Log4Qt/src/databaselayout.cpp
@@ -0,0 +1,218 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: databaselayout.cpp
+ * created: March 2010
+ * author: Michael Filonenko
+ *
+ *
+ * Copyright 2010 Michael Filonenko
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "databaselayout.h"
+
+#include <QtCore/QDebug>
+
+#include <QtSql/QSqlField>
+#include "loggingevent.h"
+
+#include "helpers/datetime.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DatabaseLayout
+ **************************************************************************/
+
+ QSqlRecord DatabaseLayout::formatRecord(const LoggingEvent &rEvent)
+ {
+ QSqlField field;
+ QSqlRecord record;
+
+ if (!mTimeStamp.isEmpty()) {
+ field.setName(mTimeStamp);
+ field.setType(QVariant::DateTime);
+ field.setGenerated(true);
+ field.setValue(DateTime::fromMilliSeconds(rEvent.timeStamp()));
+ record.append(field);
+ }
+
+ if (!mLoggerName.isEmpty()) {
+ field.setName(mLoggerName);
+ field.setType(QVariant::String);
+ field.setGenerated(true);
+ field.setValue(rEvent.loggerName());
+ record.append(field);
+ }
+
+ if (!mThreadName.isEmpty()) {
+ field.setName(mThreadName);
+ field.setType(QVariant::String);
+ field.setGenerated(true);
+ field.setValue(rEvent.threadName());
+ record.append(field);
+ }
+
+ if (!mLevel.isEmpty()) {
+ field.setName(mLevel);
+ field.setType(QVariant::String);
+ field.setGenerated(true);
+ field.setValue(rEvent.level().toString());
+ record.append(field);
+ }
+
+ if (!mMessage.isEmpty()) {
+ field.setName(mMessage);
+ field.setType(QVariant::String);
+ field.setGenerated(true);
+ field.setValue(rEvent.message());
+ record.append(field);
+ }
+ return record;
+ }
+
+
+ QString DatabaseLayout::format(const LoggingEvent &rEvent)
+ {
+ QString result;
+
+ if (!mTimeStamp.isEmpty()) {
+ result.append(mTimeStamp);
+ result.append(":");
+ result.append(DateTime::fromMilliSeconds(rEvent.timeStamp()).toString("dd.MM.yyyy hh:mm"));
+ }
+
+ if (!mThreadName.isEmpty()) {
+ result.append(mThreadName);
+ result.append(":");
+ result.append(mThreadName);
+ result.append("; ");
+ }
+
+ if (!mLevel.isEmpty()) {
+ result.append(mLevel);
+ result.append(":");
+ result.append(mLevel);
+ result.append("; ");
+ }
+
+ if (!mLoggerName.isEmpty()) {
+ result.append(mLoggerName);
+ result.append(":");
+ result.append(mLoggerName);
+ result.append("; ");
+ }
+
+ if (!mMessage.isEmpty()) {
+ result.append(mMessage);
+ result.append(":");
+ result.append(mMessage);
+ result.append("; ");
+ }
+ return result;
+ }
+
+ QString DatabaseLayout::timeStampColumn() const
+ {
+ return mTimeStamp;
+ }
+ QString DatabaseLayout::loggerNameColumn() const
+ {
+ return mLoggerName;
+ }
+ QString DatabaseLayout::threadNameColumn() const
+ {
+ return mThreadName;
+ }
+
+ QString DatabaseLayout::levelColumn() const
+ {
+ return mLevel;
+ }
+
+ QString DatabaseLayout::messageColumn() const
+ {
+ return mMessage;
+ }
+
+
+ void DatabaseLayout::setTimeStampColumn(const QString& columnName)
+ {
+ mTimeStamp = columnName;
+ }
+
+ void DatabaseLayout::setLoggerNameColumn(const QString& columnName)
+ {
+ mLoggerName = columnName;
+ }
+
+ void DatabaseLayout::setThreadNameColumn(const QString& columnName)
+ {
+ mThreadName = columnName;
+ }
+
+ void DatabaseLayout::setLevelColumn(const QString& columnName)
+ {
+ mLevel = columnName;
+ }
+
+ void DatabaseLayout::setMessageColumn(const QString& columnName)
+ {
+ mMessage = columnName;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug DatabaseLayout::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "DatabaseLayout("
+ << "name:" << name() << " "
+ << "referencecount:" << referenceCount()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/databaselayout.h b/ext/Log4Qt/src/databaselayout.h
new file mode 100755
index 0000000..4e22121
--- /dev/null
+++ b/ext/Log4Qt/src/databaselayout.h
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: databaselayout.h
+ * created: March 2010
+ * author: Michael Filonenko
+ *
+ *
+ * Copyright 2010 Michael Filonenko
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_DATABASELAYOUT_H
+#define LOG4QT_DATABASELAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "layout.h"
+
+#include <QtSql/QSqlRecord>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DatabaseLayout outputs loggin event into sql table.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT DatabaseLayout : public Layout
+ {
+ Q_OBJECT
+
+ /*!
+ The property holds column name to save timestamp of log event
+ */
+ Q_PROPERTY(QString timeStampColumn READ timeStampColumn WRITE setTimeStampColumn)
+ /*!
+ The property holds column name to save logger name of log event
+ */
+ Q_PROPERTY(QString loggerNameColumn READ loggerNameColumn WRITE setLoggerNameColumn)
+ /*!
+ The property holds column name to save thread name of log event
+ */
+ Q_PROPERTY(QString threadNameColumn READ threadNameColumn WRITE setThreadNameColumn)
+ /*!
+ The property holds column name to save level of log event
+ */
+ Q_PROPERTY(QString levelColumn READ levelColumn WRITE setLevelColumn)
+ /*!
+ The property holds column name to save message of log event
+ */
+ Q_PROPERTY(QString messageColumn READ messageColumn WRITE setMessageColumn)
+
+
+ public:
+ DatabaseLayout(QObject *pParent = 0);
+ // virtual ~DatabaseLayout(); // Use compiler default
+ private:
+ DatabaseLayout(const DatabaseLayout &rOther); // Not implemented
+ DatabaseLayout &operator=(const DatabaseLayout &rOther); // Not implemented
+
+ public:
+ virtual QSqlRecord formatRecord(const LoggingEvent &rEvent);
+ virtual QString format(const LoggingEvent &rEvent);
+
+ QString timeStampColumn() const;
+ QString loggerNameColumn() const;
+ QString threadNameColumn() const;
+ QString levelColumn() const;
+ QString messageColumn() const;
+
+ void setTimeStampColumn(const QString& columnName);
+ void setLoggerNameColumn(const QString& columnName);
+ void setThreadNameColumn(const QString& columnName);
+ void setLevelColumn(const QString& columnName);
+ void setMessageColumn(const QString& columnName);
+
+ protected:
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %DatabaseLayout(name:"SL" referencecount:1)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ private:
+ QString mTimeStamp;
+ QString mLoggerName;
+ QString mThreadName;
+ QString mLevel;
+ QString mMessage;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline DatabaseLayout::DatabaseLayout(QObject *pParent) :
+ Layout(pParent)
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::DatabaseLayout, Q_COMPLEX_TYPE); // Use default
+
+#endif // LOG4QT_DATABASELAYOUT_H
diff --git a/ext/Log4Qt/src/fileappender.cpp b/ext/Log4Qt/src/fileappender.cpp
new file mode 100755
index 0000000..717d767
--- /dev/null
+++ b/ext/Log4Qt/src/fileappender.cpp
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * package:
+ * file: fileappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "fileappender.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+#include <QtCore/QTextCodec>
+#include "layout.h"
+#include "loggingevent.h"
+
+// if we are in WIN*
+#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+#include <windows.h>
+#endif
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: FileAppender
+ **************************************************************************/
+
+
+ FileAppender::FileAppender(QObject *pParent) :
+ WriterAppender(pParent),
+ mAppendFile(false),
+ mBufferedIo(true),
+ mFileName(),
+ mpFile(0),
+ mpTextStream(0)
+ {
+ }
+
+
+ FileAppender::FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mAppendFile(false),
+ mBufferedIo(true),
+ mFileName(rFileName),
+ mpFile(0),
+ mpTextStream(0)
+ {
+ }
+
+
+ FileAppender::FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mAppendFile(append),
+ mBufferedIo(true),
+ mFileName(rFileName),
+ mpFile(0),
+ mpTextStream(0)
+ {
+ }
+
+
+ FileAppender::FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ bool buffered,
+ QObject *pParent) :
+ WriterAppender(pLayout, pParent),
+ mAppendFile(append),
+ mBufferedIo(buffered),
+ mFileName(rFileName),
+ mpFile(0),
+ mpTextStream(0)
+ {
+ }
+
+
+ FileAppender::~FileAppender()
+ {
+ close();
+ }
+
+
+ void FileAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (mFileName.isEmpty())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"),
+ APPENDER_ACTIVATE_MISSING_FILE_ERROR);
+ e << name();
+ logger()->error(e);
+ return;
+ }
+ closeFile();
+ openFile();
+ WriterAppender::activateOptions();
+ }
+
+
+ void FileAppender::close()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (isClosed())
+ return;
+
+ WriterAppender::close();
+ closeFile();
+ }
+
+
+ bool FileAppender::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (!mpFile || !mpTextStream)
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"),
+ APPENDER_NO_OPEN_FILE_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return WriterAppender::checkEntryConditions();
+ }
+
+
+ void FileAppender::closeFile()
+ {
+ // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller")
+
+ if (mpFile)
+ logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name());
+
+ setWriter(0);
+ delete mpTextStream;
+ mpTextStream = 0;
+ delete mpFile;
+ mpFile = 0;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug FileAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+ QString codec_name;
+ if (encoding())
+ codec_name = QLatin1String(encoding()->name());
+
+ rDebug.nospace() << "FileAppender("
+ << "name:" << name() << " "
+ << "appendfile:" << appendFile() << " "
+ << "bufferedio:" << bufferedIo() << " "
+ << "encoding:" << codec_name << " "
+ << "file:" << file() << " "
+ << "filter:" << firstFilter() << " "
+ << "immediateflush:" << immediateFlush() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString() << " "
+ << "writer:" << writer()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+ bool FileAppender::handleIoErrors() const
+ {
+ // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller")
+
+ if (mpFile->error() == QFile::NoError)
+ return false;
+
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"),
+ APPENDER_WRITING_FILE_ERROR);
+ e << mFileName << name();
+ e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
+ logger()->error(e);
+ return true;
+ }
+
+
+ void FileAppender::openFile()
+ {
+ Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file");
+
+ QFileInfo file_info(mFileName);
+ QDir parent_dir = file_info.dir();
+ if (!parent_dir.exists())
+ {
+ logger()->trace("Creating missing parent directory for file %1", mFileName);
+ QString name = parent_dir.dirName();
+ parent_dir.cdUp();
+ parent_dir.mkdir(name);
+ }
+
+#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
+ // Let windows resolve any environment variables included in the file path
+ wchar_t buffer[MAX_PATH];
+ if (ExpandEnvironmentStringsW((wchar_t*)mFileName.utf16(), buffer, MAX_PATH)) {
+ mFileName = QString::fromWCharArray(buffer);
+ }
+#endif
+
+ mpFile = new QFile(mFileName);
+ QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text;
+ if (mAppendFile)
+ mode |= QIODevice::Append;
+ else
+ mode |= QIODevice::Truncate;
+ if (!mBufferedIo)
+ mode |= QIODevice::Unbuffered;
+ if (!mpFile->open(mode))
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"),
+ APPENDER_OPENING_FILE_ERROR);
+ e << mFileName << name();
+ e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
+ logger()->error(e);
+ return;
+ }
+ mpTextStream = new QTextStream(mpFile);
+ setWriter(mpTextStream);
+ logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name());
+ }
+
+
+ bool FileAppender::removeFile(QFile &rFile) const
+ {
+ if (rFile.remove())
+ return true;
+
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"),
+ APPENDER_REMOVE_FILE_ERROR);
+ e << rFile.fileName() << name();
+ e.addCausingError(LogError(rFile.errorString(), rFile.error()));
+ logger()->error(e);
+ return false;
+ }
+
+
+ bool FileAppender::renameFile(QFile &rFile,
+ const QString &rFileName) const
+ {
+ logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName);
+ if (rFile.rename(rFileName))
+ return true;
+
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"),
+ APPENDER_RENAMING_FILE_ERROR);
+ e << rFile.fileName() << rFileName << name();
+ e.addCausingError(LogError(rFile.errorString(), rFile.error()));
+ logger()->error(e);
+ return false;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/fileappender.h b/ext/Log4Qt/src/fileappender.h
new file mode 100755
index 0000000..6234af5
--- /dev/null
+++ b/ext/Log4Qt/src/fileappender.h
@@ -0,0 +1,233 @@
+/******************************************************************************
+ *
+ * package:
+ * file: fileappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _FILEAPPENDER_H
+#define _FILEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "writerappender.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QFile;
+class QTextStream;
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class FileAppender appends log events to a file.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed. See
+ * \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT FileAppender : public WriterAppender
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds, if the output is appended to the file.
+ *
+ * The default is false for not appending.
+ *
+ * \sa appendFile(), setAppendFile()
+ */
+ Q_PROPERTY(bool appendFile READ appendFile WRITE setAppendFile)
+
+ /*!
+ * The property holds, if the output is buffered.
+ *
+ * The default is true for buffering.
+ *
+ * \sa bufferedIo(), setBufferedIo()
+ */
+ Q_PROPERTY(bool bufferedIo READ bufferedIo WRITE setBufferedIo)
+
+ /*!
+ * The property holds the name of the file.
+ *
+ * \sa file(), setFile()
+ */
+ Q_PROPERTY(QString file READ file WRITE setFile)
+
+ public:
+ FileAppender(QObject *pParent = 0);
+ FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ QObject *pParent = 0);
+ FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ QObject *pParent = 0);
+ FileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ bool buffered,
+ QObject *pParent = 0);
+ virtual ~FileAppender();
+ private:
+ FileAppender(const FileAppender &rOther); // Not implemented
+ FileAppender &operator=(const FileAppender &rOther); // Not implemented
+
+ public:
+ bool appendFile() const;
+ QString file() const;
+ bool bufferedIo() const;
+ // JAVA: int bufferSize() const;
+ void setAppendFile(bool append);
+ void setBufferedIo(bool buffered);
+ // JAVA: void setBufferSize(int bufferSize);
+ void setFile(const QString &rFileName);
+
+ virtual void activateOptions();
+ virtual void close();
+
+ protected:
+ /*!
+ * Tests if all entry conditions for using append() in this class are met.
+ *
+ * If a conditions is not met, an error is logged and the function returns
+ * false. Otherwise the result of WriterAppender::checkEntryConditions()
+ * is returned.
+ *
+ * The checked conditions are:
+ * - That a file is set and open (APPENDER_NO_OPEN_FILE_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(), AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+ void closeFile();
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %FileAppender(name:"FA" appendfile:false bufferedio:true encoding:""
+ * file:"log.txt" filter: 0x0 immediateflush:true isactive:false
+ * isclosed:false layout:"TTCC" referencecount:2
+ * threshold:"NULL" writer:0x0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ /*!
+ * Checks for file I/O errrors. If an error is found it is logged and the
+ * function returns true. Otherwise false is returned.
+ */
+ virtual bool handleIoErrors() const;
+
+ /*!
+ * Opens the file for the appender based on the specified file name and
+ * mode. A text stream is created and passed on to the super class
+ * WriterAppender.
+ *
+ * If the parent directory of the specified file does not exists,
+ * it is created.
+ */
+ void openFile();
+
+ /*!
+ * Removes the file \a rFile. If the operation is successful, true is
+ * returned. Otherwise an APPENDER_REMOVE_FILE_ERROR error is logged
+ * and false is returned.
+ */
+ bool removeFile(QFile &rFile) const;
+
+ /*!
+ * Renames the file \a rFile to \a rFileName. If the operation is
+ * successful, true is returned. Otherwise an
+ * APPENDER_RENAMING_FILE_ERROR error is logged and false is returned.
+ */
+ bool renameFile(QFile &rFile,
+ const QString &rFileName) const;
+
+ // JAVA: void setQWForFiles(Writer writer);
+
+ private:
+ volatile bool mAppendFile;
+ volatile bool mBufferedIo;
+ QString mFileName;
+ QFile *mpFile;
+ QTextStream *mpTextStream;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool FileAppender::appendFile() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mAppendFile; }
+
+ inline QString FileAppender::file() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mFileName; }
+
+ inline bool FileAppender::bufferedIo() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mBufferedIo; }
+
+ inline void FileAppender::setAppendFile(bool append)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mAppendFile = append; }
+
+ inline void FileAppender::setBufferedIo(bool buffered)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mBufferedIo = buffered; }
+
+ inline void FileAppender::setFile(const QString &rFileName)
+ { QMutexLocker locker(&mObjectGuard);
+ mFileName = rFileName; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(::FileAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // _FILEAPPENDER_H
diff --git a/ext/Log4Qt/src/helpers/appenderattachable.cpp b/ext/Log4Qt/src/helpers/appenderattachable.cpp
new file mode 100644
index 0000000..2fe0c1f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/appenderattachable.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: appenderattachable.cpp
+ * created: Dezember 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2007 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/appenderattachable.h"
+#include "varia/listappender.h"
+#include "appender.h"
+
+#include <QtCore/QDebug>
+
+namespace Log4Qt
+{
+
+
+/**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+/**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+/**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+AppenderAttachable::AppenderAttachable() :
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ mAppenderGuard()
+#else
+ mAppenderGuard(QReadWriteLock::Recursive)
+#endif
+{
+}
+
+QList<Appender *> AppenderAttachable::appenders() const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ QList<Appender *> result;
+ Appender *p_appender;
+ Q_FOREACH(p_appender, mAppenders)
+ result << p_appender;
+
+ return result;
+}
+
+void AppenderAttachable::addAppender(Appender *pAppender)
+{
+ // Avoid deadlock:
+ // - Handle warnings, before write lock is aquired
+
+ // Keep objects with a 0 reference count safe
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ {
+ QReadLocker locker(&mAppenderGuard);
+
+ if (!p_appender) {
+ //logger()->warn("Adding null Appender to Logger '%1'", name());
+ return;
+ }
+
+ if (mAppenders.contains(p_appender)) {
+ //logger()->warn("Adding of duplicate appender '%2' to logger '%1'",
+ //name(), p_appender->name());
+ return;
+ }
+ }
+ {
+ QWriteLocker locker(&mAppenderGuard);
+
+ if (mAppenders.contains(p_appender))
+ return;
+ mAppenders.append(p_appender);
+ }
+}
+
+Appender *AppenderAttachable::appender(const QString &rName) const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ Appender *p_appender;
+ Q_FOREACH(p_appender, mAppenders)
+ if (p_appender->name() == rName)
+ return p_appender;
+ return 0;
+}
+
+bool AppenderAttachable::isAttached(Appender *pAppender) const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ // Keep objects with a 0 reference count safe
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ return mAppenders.contains(p_appender);
+}
+
+void AppenderAttachable::removeAllAppenders()
+{
+// Avoid deadlock:
+// - Only log warnings without having the write log aquired
+// - Hold a reference to all appenders so that the remove does not
+// destruct the appender over the reference count while the write
+// log is held. The appender may log messages.
+
+ //logger()->trace("Removing all appenders from logger '%1'", name());
+
+ QList < LogObjectPtr<Appender> > appenders;
+ {
+ QWriteLocker locker(&mAppenderGuard);
+ QMutableListIterator < LogObjectPtr<Appender> > i(mAppenders);
+ while (i.hasNext()) {
+ Appender *p_appender = i.next();
+ ListAppender *p_listappender = qobject_cast<ListAppender*> (p_appender);
+ if (p_listappender && p_listappender->configuratorList())
+ continue;
+ else {
+ appenders << p_appender;
+ i.remove();
+ }
+ }
+ }
+ appenders.clear();
+}
+
+ void AppenderAttachable::removeAppender(Appender *pAppender)
+ {
+ // Avoid deadlock:
+ // - Only log warnings without having the write log aquired
+ // - Hold a reference to the appender so that the remove does not
+ // destruct the appender over the reference count while the write
+ // log is held. The appender may log messages.
+
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ if (!p_appender) {
+ //logger()->warn("Request to remove null Appender from Logger '%1'", name());
+ return;
+ }
+ int n;
+ {
+ QWriteLocker locker(&mAppenderGuard);
+
+ n = mAppenders.removeAll(p_appender);
+ }
+ if (n == 0) {
+ //logger()->warn(
+ // "Request to remove Appender '%2', which is not part of Logger '%1' appenders",
+ // name(), p_appender->name());
+ return;
+ }
+}
+
+void AppenderAttachable::removeAppender(const QString &rName)
+{
+ Appender *p_appender = appender(rName);
+ if (p_appender)
+ removeAppender(p_appender);
+}
+
+
+/**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/appenderattachable.h b/ext/Log4Qt/src/helpers/appenderattachable.h
new file mode 100644
index 0000000..8d1832e
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/appenderattachable.h
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: appenderattachable.h
+ * created: December 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2010 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_APPENDERATTACHABLE_H
+#define LOG4QT_APPENDERATTACHABLE_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+#include "../log4qt.h"
+#include "logobjectptr.h"
+
+#include <QtCore/QList>
+#include <QtCore/QReadWriteLock>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+class Appender;
+
+/*!
+ * \brief Implementation for attaching appenders to objects
+ */
+class LOG4QT_EXPORT AppenderAttachable
+{
+
+public:
+ AppenderAttachable();
+ virtual ~AppenderAttachable() {}
+
+ /*!
+ * Add an appender.
+ */
+ virtual void addAppender(Appender *pAppender);
+
+ /*!
+ * Get all previously added appenders as an Enumeration.
+ */
+ virtual QList<Appender *> appenders() const;
+
+ /*!
+ * Get an appender by name.
+ */
+ virtual Appender *appender(const QString &rName) const;
+
+ /*!
+ Returns <code>true</code> if the specified appender is in the
+ list of attached appenders, <code>false</code> otherwise.
+ */
+ virtual bool isAttached(Appender *pAppender) const;
+
+ /*!
+ * Removes all appenders that have been previously added from this
+ * Logger.
+ *
+ * To allow configurators to collect events during the configuration
+ * process ListAppenders with the configuratorList property set, will
+ * not be removed.
+ *
+ * \sa LisAppender::setConfiguratorList()
+ */
+ virtual void removeAllAppenders();
+
+ /*!
+ * Remove the appender passed as parameter from the list of appenders.
+ */
+ virtual void removeAppender(Appender *pAppender);
+
+ /*!
+ * Remove the appender with the name passed as parameter from the
+ * list of appenders.
+ */
+ virtual void removeAppender(const QString &rName);
+
+protected:
+ QList< LogObjectPtr<Appender> > mAppenders;
+ mutable QReadWriteLock mAppenderGuard;
+};
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::AppenderAttachable, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_APPENDERATTACHABLE_H
diff --git a/ext/Log4Qt/src/helpers/classlogger.cpp b/ext/Log4Qt/src/helpers/classlogger.cpp
new file mode 100755
index 0000000..950fed2
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/classlogger.cpp
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: classlogger.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/classlogger.h"
+
+#include <QtCore/QDebug>
+#include "logmanager.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ClassLogger
+ **************************************************************************/
+
+
+ ClassLogger::ClassLogger() :
+ mpLogger(0)
+ {
+ }
+
+
+ Logger *ClassLogger::logger(const QObject *pObject)
+ {
+ Q_ASSERT_X(pObject, "ClassLogger::logger()", "pObject must not be null");
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ if (!mpLogger)
+ q_atomic_test_and_set_ptr(&mpLogger,
+ 0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(mpLogger);
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ if (!static_cast<Logger *>(mpLogger))
+ mpLogger.testAndSetOrdered(0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(static_cast<Logger *>(mpLogger));
+#else
+ if (!static_cast<Logger *>(mpLogger.loadAcquire()))
+ mpLogger.testAndSetOrdered(0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(static_cast<Logger *>(mpLogger.loadAcquire()));
+#endif
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/classlogger.h b/ext/Log4Qt/src/helpers/classlogger.h
new file mode 100755
index 0000000..cc7bca6
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/classlogger.h
@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: classlogger.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_CLASSLOGGER_H
+#define LOG4QT_CLASSLOGGER_H
+
+#include "../log4qtshared.h"
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# include <QtCore/QAtomicPointer>
+# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+# warning "QAtomicPointer test and set is not native. The class Log4Qt::ClassLogger is not thread-safe."
+# endif
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+ class Logger;
+
+ /*!
+ * \brief The class ClassLogger provides logging for a QObject derived
+ * class.
+ *
+ * The class ClassLogger provides a logger for a specified QObject derived
+ * object. It is used by \ref LOG4QT_DECLARE_QCLASS_LOGGER to implement the
+ * member functions provided by the macro.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa LOG4QT_DECLARE_QCLASS_LOGGER
+ */
+ class LOG4QT_EXPORT ClassLogger
+ {
+ public:
+ /*!
+ * Creates a ClassLogger object.
+ */
+ ClassLogger();
+ // ~ClassLogger(); // Use compiler default
+ // ClassLogger(const ClassLogger &rOther); // Use compiler default
+ // ClassLogger &operator=(const ClassLogger &rOther); // Use compiler default
+
+ /*!
+ * Returns a pointer to a Logger named after the class of the object
+ * \a pObject.
+ *
+ * On the first invocation the Logger is requested by a call to
+ * LogManager::logger(const char *pName). The pointer is stored to be
+ * returned on subsequent invocations.
+ *
+ * \sa LogManager::logger(const char *pName)
+ */
+ Logger *logger(const QObject *pObject);
+
+ private:
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ volatile Logger *mpLogger;
+#else
+ mutable QAtomicPointer<Logger> mpLogger;
+#endif
+ };
+
+
+ /******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEinfo(Log4Qt::ClassLogger, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_CLASSLOGGER_H
diff --git a/ext/Log4Qt/src/helpers/configuratorhelper.cpp b/ext/Log4Qt/src/helpers/configuratorhelper.cpp
new file mode 100755
index 0000000..29167b2
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/configuratorhelper.cpp
@@ -0,0 +1,136 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: configuratorhelper.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/configuratorhelper.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFileSystemWatcher>
+#include "helpers/initialisationhelper.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ConfiguratorHelper
+ **************************************************************************/
+
+
+ ConfiguratorHelper::ConfiguratorHelper() :
+ mObjectGuard(),
+ mConfigurationFile(),
+ mpConfigureFunc(0),
+ mpConfigurationFileWatch(0),
+ mConfigureError()
+ {
+ }
+
+
+ ConfiguratorHelper::~ConfiguratorHelper()
+ {
+ delete mpConfigurationFileWatch;
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(ConfiguratorHelper)
+
+
+ void ConfiguratorHelper::doConfigurationFileChanged(const QString &rFileName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mpConfigureFunc)
+ return;
+ mpConfigureFunc(rFileName);
+ // Shall we hold the lock while emitting the signal?
+ emit configurationFileChanged(rFileName, mConfigureError.count() > 0);
+ }
+
+
+
+ void ConfiguratorHelper::doSetConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ mConfigurationFile.clear();
+ mpConfigureFunc = 0;
+ delete mpConfigurationFileWatch;
+ if (rFileName.isEmpty())
+ return;
+
+ mConfigurationFile = rFileName;
+ mpConfigureFunc = pConfigureFunc;
+ mpConfigurationFileWatch = new QFileSystemWatcher();
+ mpConfigurationFileWatch->addPath(rFileName);
+ connect(mpConfigurationFileWatch,
+ SIGNAL(fileChanged(const QString &)),
+ SLOT(configurationFileChanged(const QString &)));
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper)
+ {
+ debug.nospace() << "ConfiguratorHelper("
+ << "configurationfile:" << ConfiguratorHelper::configurationFile()
+ << "configurefunc:" << rConfiguratorHelper.mpConfigureFunc
+ << "filesystemwatcher:" << rConfiguratorHelper.mpConfigurationFileWatch
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/helpers/configuratorhelper.h b/ext/Log4Qt/src/helpers/configuratorhelper.h
new file mode 100755
index 0000000..45fe670
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/configuratorhelper.h
@@ -0,0 +1,211 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: configuratorhelper.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_CONFIGURATORHELPER_H
+#define LOG4QT_HELPERS_CONFIGURATORHELPER_H
+
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include "loggingevent.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QFileSystemWatcher;
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class ConfiguratorHelper provides a confiuration file watch
+ * and last error for configurator classes.
+ *
+ * A configuration file can be set using setConfigurationFile(). The file
+ * is watched for changes. If a change occurs the configuration is reloaded
+ * and the ConfigurationFileChanged() signal is emitted. Error information
+ * for the last call to a configure function or the last configuration file
+ * change can be accessed using configureError().
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT ConfiguratorHelper : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ /*!
+ * Prototype for a configure callback function. The function is called
+ * when then configuration file is changed and takes the
+ * configuration file as a parameter.
+ *
+ * \sa setConfigurationFile(),
+ * PropertyConfigurator::configure(const QString &)
+ */
+ typedef bool (*ConfigureFunc)(const QString &rFileName);
+
+ private:
+ ConfiguratorHelper();
+ ConfiguratorHelper(const ConfiguratorHelper &rOther); // Not implemented
+ virtual ~ConfiguratorHelper();
+ ConfiguratorHelper &operator=(const ConfiguratorHelper &rOther); // Not implemented
+
+ public:
+
+ /*!
+ * Returns the error information for the last configuration operation
+ * that took place. The configuration operation could be the result of
+ * a call to one of the configure methods or through a change
+ * to the configuration file.
+ *
+ * \sa setConfigureError(), PropertyConfigurator::configure(),
+ * setConfigurationFile()
+ */
+ static QList<LoggingEvent> configureError();
+
+ /*!
+ * Returns the current configuration file.
+ *
+ * \sa setConfigurationFile()
+ */
+ static QString configurationFile();
+
+ /*!
+ * Returns the ConfiguratorHelper instance.
+ */
+ static ConfiguratorHelper *instance();
+
+ /*!
+ * Sets the configuration error information for the last configuration
+ * operation.
+ *
+ * \sa configureError()
+ */
+ static void setConfigureError(const QList<LoggingEvent> &rConfigureError);
+
+ /*!
+ * Sets the configuration file to \a rFileName. The file is watched for
+ * changes. On a file change the function \a pConfigureFunc will be called
+ * and the signal configurationFileChange() will be emitted.
+ *
+ * Setting the configuration file to an empty string stops the file watch.
+ *
+ * \sa configurationFile(), PropertyConfigurator::configureAndWatch(),
+ * configureError()
+ */
+ static void setConfigurationFile(const QString &rFileName = QString(),
+ ConfigureFunc pConfigureFunc = 0);
+
+ signals:
+ /*!
+ * The signal is emitted after a change to the file \a rFileName
+ * was processed. If an error occured during the configuration, the
+ * flag \a error will be true and error information is available
+ * over configureError().
+ */
+ void configurationFileChanged(const QString &rFileName,
+ bool error);
+
+ private slots:
+ void doConfigurationFileChanged(const QString &rFileName);
+
+ private:
+ void doSetConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc);
+
+ private:
+ mutable QMutex mObjectGuard;
+ QString mConfigurationFile;
+ ConfigureFunc mpConfigureFunc;
+ QFileSystemWatcher *mpConfigurationFileWatch;
+ QList<LoggingEvent> mConfigureError;
+
+#ifndef QT_NO_DEBUG_STREAM
+ // Needs to be friend to access details
+ friend QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper);
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates ConfiguratorHelper
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %ConfiguratorHelper(configurationfile: "" configurefunc: false
+ * filesystemwatcher: QObject(0x0) )
+ * </tt>
+ * \sa QDebug, ConfiguratorHelper::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper);
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QList<LoggingEvent> ConfiguratorHelper::configureError()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mConfigureError; }
+
+ inline QString ConfiguratorHelper::configurationFile()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mConfigurationFile; }
+
+ inline void ConfiguratorHelper::setConfigureError(const QList<LoggingEvent> &rConfigureError)
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ instance()->mConfigureError = rConfigureError; }
+
+ inline void ConfiguratorHelper::setConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc)
+ { instance()->doSetConfigurationFile(rFileName, pConfigureFunc); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::ConfiguratorHelper, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_CONFIGURATORHELPER_H
diff --git a/ext/Log4Qt/src/helpers/datetime.cpp b/ext/Log4Qt/src/helpers/datetime.cpp
new file mode 100755
index 0000000..a51b8eb
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/datetime.cpp
@@ -0,0 +1,326 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: datetime.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/datetime.h"
+
+#include <QtCore/QDebug>
+#include "helpers/initialisationhelper.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DateTime
+ **************************************************************************/
+
+
+ QString DateTime::toString(const QString &rFormat) const
+ {
+ QString format(rFormat);
+
+ if (format.isEmpty())
+ return QString();
+ if (!isValid())
+ return QString();
+ if (format == QLatin1String("NONE"))
+ return QString();
+
+ if (format == QLatin1String("RELATIVE"))
+ return QString::number(toMilliSeconds() - InitialisationHelper::startTime());
+
+ if (format == QLatin1String("ISO8601"))
+ format = QLatin1String("yyyy-MM-dd hh:mm:ss.zzz");
+ if (format == QLatin1String("ABSOLUTE"))
+ format = QLatin1String("HH:mm:ss.zzz");
+ if (format == QLatin1String("DATE"))
+ format = QLatin1String("dd MMM YYYY HH:mm:ss.zzzz");
+
+ return formatDateTime(format);
+ }
+
+
+ QString DateTime::formatDateTime(const QString &rFormat) const
+ {
+ if (rFormat.isEmpty())
+ return QString();
+ if (!isValid())
+ return QString();
+
+ const QLatin1Char null('0');
+ const QLatin1Char quote('\'');
+ const QString tokens = QLatin1String("\'dMyhHmszAPapw");
+ const bool am_pm = hasAMPM(rFormat);
+
+ QString result;
+ QString token;
+ QChar expected = null;
+
+ QChar c;
+ int i;
+ for (i = 0; i < rFormat.length(); i++)
+ {
+ c = rFormat.at(i);
+
+ // Handle literal text
+ if (expected == quote)
+ {
+ if (c == quote)
+ {
+ Q_ASSERT_X(i > 0, "DateTime::toString()", "Found quote with status quote at i = 0");
+ if (i > 0 && rFormat.at(i - 1) == quote)
+ // Second of two quotes
+ result += quote;
+ expected = null;
+ }
+ else
+ // Next literal character
+ result += c;
+ }
+ else if (c == expected)
+ {
+ // Extend token
+ token += c;
+ }
+ else
+ {
+ // Close last token
+ result += formatToken(token, am_pm);
+ token.clear();
+ expected = null;
+
+ // Test for valid character
+ if (tokens.indexOf(c) >= 0)
+ {
+ if (c == QLatin1Char('a'))
+ expected = QLatin1Char('p');
+ else if (c == QLatin1Char('A'))
+ expected = QLatin1Char('P');
+ else if (c.toLower() == QLatin1Char('p'))
+ expected = null;
+ else
+ expected = c;
+ if (c != quote)
+ token += c;
+ } else
+ result += c;
+ }
+ }
+
+ result += formatToken(token, am_pm);
+ return result;
+ }
+
+
+ QString DateTime::formatToken(const QString &rToken, bool am_pm) const
+ {
+ if (rToken.isEmpty())
+ return QString();
+
+ const QChar c = rToken.at(0);
+ QString result;
+ int used = 0;
+
+ // Qt data format strings
+ if (rToken.startsWith(QLatin1String("dddd")))
+ {
+ result = QDate::longDayName(date().dayOfWeek());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("ddd")))
+ {
+ result = QDate::shortDayName(date().dayOfWeek());
+ used = 3;
+ }
+ else if (rToken.startsWith(QLatin1String("dd")))
+ {
+ result = QString::number(date().day()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('d'))
+ {
+ result = QString::number(date().day());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("MMMM")))
+ {
+ result = QDate::longMonthName(date().month());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("MMM")))
+ {
+ result = QDate::shortMonthName(date().month());
+ used = 3;
+ }
+ else if (rToken.startsWith(QLatin1String("MM")))
+ {
+ result = QString::number(date().month()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('M'))
+ {
+ result = QString::number(date().month());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("yyyy")))
+ {
+ result = QString::number(date().year());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("yy")))
+ {
+ result = QString::number(date().year() % 100).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+
+ // Qt time format strings
+ else if (rToken.startsWith(QLatin1String("hh")) || rToken.startsWith(QLatin1String("HH")))
+ {
+ int hour = time().hour();
+ if (am_pm && c == QLatin1Char('h') && hour > 12)
+ hour -= 12;
+ result = QString::number(hour).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('h') || c == QLatin1Char('H'))
+ {
+ int hour = time().hour();
+ if (am_pm && c == QLatin1Char('h') && hour > 12)
+ hour -= 12;
+ result = QString::number(hour);
+ used = 2;
+ }
+ else if (rToken.startsWith(QLatin1String("mm")))
+ {
+ result = QString::number(time().minute()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == (QLatin1Char('m')))
+ {
+ result = QString::number(time().minute());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("ss")))
+ {
+ result = QString::number(time().second()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('s'))
+ {
+ result = QString::number(time().second());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("zzz")))
+ {
+ result = QString::number(time().msec()).rightJustified(3, QLatin1Char('0'), true);
+ used = 3;
+ }
+ else if (c == QLatin1Char('z'))
+ {
+ result = QString::number(time().msec());
+ used = 1;
+ }
+ else if (c.toLower() == QLatin1Char('a'))
+ {
+ bool is_lower = c == QLatin1Char('a');
+ if (time().hour() < 12)
+ result = QLatin1String("AM");
+ else
+ result = QLatin1String("PM");
+ if (is_lower)
+ result = result.toLower();
+ if (rToken.size() > 1 &&
+ ((is_lower && rToken.at(1) == QLatin1Char('p')) ||
+ (!is_lower && rToken.at(1) == QLatin1Char('P')))
+ )
+ used = 2;
+ else
+ used = 1;
+ }
+
+ // Extension for week number
+ else if (rToken.startsWith(QLatin1String("ww")))
+ {
+ result = QString::number(date().weekNumber()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('w'))
+ {
+ result = QString::number(date().weekNumber());
+ used = 1;
+ }
+
+ if (used)
+ return result + formatToken(rToken.mid(used), am_pm);
+ else
+ return result;
+ }
+
+
+ bool DateTime::hasAMPM(const QString &rToken)
+ {
+ bool in_literal = false;
+ QChar c;
+ int i;
+ for (i = 0; i < rToken.length(); i++)
+ {
+ c = rToken.at(i);
+ if (c == QLatin1Char('\''))
+ in_literal = !in_literal;
+ else if (!in_literal && c.toLower() == QLatin1Char('a'))
+ return true;
+ }
+ return false;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/datetime.h b/ext/Log4Qt/src/helpers/datetime.h
new file mode 100755
index 0000000..19a074f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/datetime.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: datetime.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Resolved compilation problem with Microsoft Visual Studio 2005
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_DATETIME_H
+#define LOG4QT_HELPERS_DATETIME_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QDateTime>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DateTime provides extended functionality for QDateTime.
+ *
+ * The class DateTime implements additional formatting options for
+ * toString() and provides conversion functions from and to milliseconds.
+ */
+ class LOG4QT_EXPORT DateTime : public QDateTime
+ {
+ public:
+ /*!
+ * Constructs a null date time.
+ *
+ * \sa QDateTime::QDateTime()
+ */
+ DateTime();
+
+ // DateTime(const DateTime &rOther); // Use compiler default
+
+ /*!
+ * Constructs a copy of another QDateTime.
+ *
+ * \sa QDateTime::QDateTime(const QDateTime &rOther)
+ */
+ DateTime(const QDateTime &rOther);
+
+ /*!
+ * Constructs a datetime with the given \a rDate and \a rTime, using
+ * the time specification defined by \a timeSpec.
+ *
+ * \sa QDateTime::QDateTime(const QDate &rDate, const QTime &rTime,
+ * Qt::TimeSpec timeSpec = Qt::LocalTime)
+ */
+ DateTime(const QDate &rDate,
+ const QTime &rTime,
+ Qt::TimeSpec timeSpec = Qt::LocalTime);
+
+ // virtual ~DateTime(); // Use compiler default
+
+ /*!
+ * Assigns \a rOther to this DateTime and returns a reference to it.
+ */
+ DateTime &operator=(const DateTime &rOther);
+
+ /*!
+ * Returns the datetime as the number of milliseconds that have passed
+ * since 1970-01-01T00:00:00,000, Coordinated Universal Time (Qt::UTC).
+ *
+ * \sa QDateTime::toTime_t()
+ */
+ qint64 toMilliSeconds() const;
+
+ /*!
+ * Returns the datetime as a string. The \a rFormat parameter
+ * determines the format of the result string.
+ *
+ * In addition to the expressions of QDateTime::toString(const QString
+ * &rFormat) the following expression can be used.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="20%"> Expression </th>
+ * <th> Output </th>
+ * </tr><tr>
+ * <td> w </td>
+ * <td> the week of the year as number without a leading zero (1 to 53) </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> ww </td>
+ * <td> the week of the year as number with a leading zero (01 to 53) </td>
+ * </tr>
+ * </table>
+ *
+ * Alternatively the \a rFormat parameter can specify one of the
+ * following strings.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="20%"> String </th>
+ * <th> Format </th>
+ * </tr><tr>
+ * <td> ABSOLUTE </td>
+ * <td> uses the format HH:mm:ss.zzz </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> DATE </td>
+ * <td> uses the format dd MMM YYYY HH:mm:ss.zzzz </td>
+ * </tr><tr>
+ * <td> ISO8601 </td>
+ * <td> uses the format yyyy-MM-dd hh:mm:ss.zzz </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> NONE </td>
+ * <td> uses an empty string as format </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> RELATIVE </td>
+ * <td> returns the milliseconds since start of the program</td>
+ * </tr>
+ * </table>
+ *
+ * \sa QDateTime::toString(const QString &rFormat)
+ */
+ QString toString(const QString &rFormat) const;
+
+ /*!
+ * Returns the current datetime, as reported by the system clock, in
+ * the local time zone.
+ *
+ * \sa QDateTime::currentDateTime()
+ */
+ static DateTime currentDateTime();
+
+ /*!
+ * Returns a datetime whose date and time are the number of
+ * milliseconds that have passed since 1970-01-01T00:00:00,
+ * Coordinated Universal Time (Qt::UTC).
+ *
+ * \sa QDateTime::fromTime_t(uint seconds)
+ */
+ static DateTime fromMilliSeconds(qint64 milliSeconds);
+
+ private:
+ QString formatDateTime(const QString &rFormat) const;
+ QString formatToken(const QString &rToken, bool am_pm) const;
+ static bool hasAMPM(const QString &rFormat);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline DateTime::DateTime() : QDateTime()
+ {}
+
+ inline DateTime::DateTime(const QDateTime &rOther) : QDateTime(rOther)
+ {}
+
+ inline DateTime::DateTime(const QDate &rDate,
+ const QTime &rTime,
+ Qt::TimeSpec timeSpec) :
+ QDateTime(rDate, rTime, timeSpec)
+ {}
+
+ inline DateTime &DateTime::operator=(const DateTime &rOther)
+ { QDateTime::operator=(rOther); return *this; }
+
+ inline qint64 DateTime::toMilliSeconds() const
+ { return static_cast<qint64>(1000) * toTime_t() + time().msec(); }
+
+ inline DateTime DateTime::currentDateTime()
+ { return DateTime(QDateTime::currentDateTime()); }
+
+ inline DateTime DateTime::fromMilliSeconds(qint64 milliSeconds)
+ { return DateTime(QDateTime::fromTime_t(milliSeconds / 1000).addMSecs(milliSeconds % 1000)); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::DateTime, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_HELPERS_DATETIME_H
diff --git a/ext/Log4Qt/src/helpers/dispatcher.cpp b/ext/Log4Qt/src/helpers/dispatcher.cpp
new file mode 100644
index 0000000..08d385f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/dispatcher.cpp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: dispatcher.cpp
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "dispatcher.h"
+#include "loggingevent.h"
+#include "asyncappender.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+namespace Log4Qt
+{
+
+/**************************************************************************
+ * Class implementation: Dispatcher
+ **************************************************************************/
+Dispatcher::Dispatcher(QObject *parent) : QObject(parent)
+ , mpAsyncAppender(0)
+{}
+
+void Dispatcher::customEvent(QEvent* event)
+{
+ if (event->type() == LoggingEvent::eventId)
+ {
+ LoggingEvent *logEvent = static_cast<LoggingEvent*>(event);
+ if (mpAsyncAppender)
+ mpAsyncAppender->callAppenders(*logEvent);
+ }
+ QObject::customEvent(event);
+}
+
+void Dispatcher::setAsyncAppender(AsyncAppender *pAsyncAppender)
+{
+ mpAsyncAppender = pAsyncAppender;
+}
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/dispatcher.h b/ext/Log4Qt/src/helpers/dispatcher.h
new file mode 100644
index 0000000..00e7167
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/dispatcher.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: dispatcher.h
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QTDISPATCHER_H
+#define LOG4QTDISPATCHER_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QThread>
+#include <QtCore/QList>
+
+#include "loggingevent.h"
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+class AsyncAppender;
+
+/*!
+ * \brief The class Dispatcher does the actual logging to the attached appanders.
+ *
+ * The Dispatcher is the worker object which class the attached apperders in the
+ * the context of the DispatcherThread.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+class Dispatcher : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Dispatcher(QObject *parent = 0);
+
+ void setAsyncAppender(AsyncAppender *pAsyncAppender);
+
+protected:
+ virtual void customEvent(QEvent* event);
+
+private:
+ AsyncAppender *mpAsyncAppender;
+};
+
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+} // namespace Log4Qt
+
+#endif // DISPATCHER_H
diff --git a/ext/Log4Qt/src/helpers/factory.cpp b/ext/Log4Qt/src/helpers/factory.cpp
new file mode 100644
index 0000000..f5411b5
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/factory.cpp
@@ -0,0 +1,515 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: factory.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/factory.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+#include "consoleappender.h"
+#include "colorconsoleappender.h"
+#include "dailyrollingfileappender.h"
+#include "fileappender.h"
+#include "helpers/logerror.h"
+#include "helpers/initialisationhelper.h"
+#include "helpers/optionconverter.h"
+#include "patternlayout.h"
+#include "rollingfileappender.h"
+#include "signalappender.h"
+#include "simplelayout.h"
+#include "simpletimelayout.h"
+#include "ttcclayout.h"
+
+#if defined(QT_NETWORK_LIB)
+#include "telnetappender.h"
+#endif
+
+#if defined(QT_SQL_LIB)
+#include "databaseappender.h"
+#include "databaselayout.h"
+#endif //#ifdef QT_SQL_LIB
+
+#include "varia/debugappender.h"
+#include "varia/denyallfilter.h"
+#include "varia/levelmatchfilter.h"
+#include "varia/levelrangefilter.h"
+#include "varia/listappender.h"
+#include "varia/nullappender.h"
+#include "varia/stringmatchfilter.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory)
+
+
+ // Appenders
+
+ Appender *console_file_appender()
+ { return new ConsoleAppender; }
+
+ Appender *create_daily_rolling_file_appender()
+ { return new DailyRollingFileAppender; }
+
+ Appender *create_debug_appender()
+ { return new DebugAppender; }
+
+ Appender *create_file_appender()
+ { return new FileAppender; }
+
+ Appender *create_list_appender()
+ { return new ListAppender; }
+
+ Appender *create_null_appender()
+ { return new NullAppender; }
+
+ Appender *create_rolling_file_appender()
+ { return new RollingFileAppender; }
+
+ Appender *create_signal_appender()
+ { return new SignalAppender; }
+
+ Appender *create_color_console_appender()
+ { return new ColorConsoleAppender;}
+
+#if defined(QT_SQL_LIB)
+ Appender *create_database_appender()
+ { return new DatabaseAppender; }
+#endif //#if defined(QT_SQL_LIB)
+
+#if defined(QT_NETWORK_LIB)
+ Appender *create_telnet_appender()
+ { return new TelnetAppender; }
+#endif
+ // Filters
+
+ Filter *create_deny_all_filter()
+ { return new DenyAllFilter; }
+
+ Filter *create_level_match_filter()
+ { return new LevelMatchFilter; }
+
+ Filter *create_level_range_filter()
+ { return new LevelRangeFilter; }
+
+ Filter *create_string_match_filter()
+ { return new StringMatchFilter; }
+
+
+ // Layouts
+
+ Layout *create_pattern_layout()
+ { return new PatternLayout; }
+
+ Layout *create_simple_layout()
+ { return new SimpleLayout; }
+
+ Layout *create_simple_time_layout()
+ { return new SimpleTimeLayout; }
+
+#if defined(QT_SQL_LIB)
+ Layout *create_database_layout()
+ { return new DatabaseLayout; }
+#endif //#if defined(QT_SQL_LIB)
+
+ Layout *create_ttcc_layout()
+ { return new TTCCLayout; }
+
+
+
+ /**************************************************************************
+ * Class implementation: Factory
+ **************************************************************************/
+
+
+ Factory::Factory() :
+ mObjectGuard(),
+ mAppenderRegistry(),
+ mFilterRegistry(),
+ mLayoutRegistry()
+ {
+ registerDefaultAppenders();
+ registerDefaultFilters();
+ registerDefaultLayouts();
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(Factory)
+
+
+ Appender *Factory::doCreateAppender(const QString &rAppenderClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mAppenderRegistry.contains(rAppenderClassName))
+ {
+ logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName);
+ return 0;
+ }
+ return mAppenderRegistry.value(rAppenderClassName)();
+ }
+
+
+ Filter *Factory::doCreateFilter(const QString &rFilterClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mFilterRegistry.contains(rFilterClassName))
+ {
+ logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName);
+ return 0;
+ }
+ return mFilterRegistry.value(rFilterClassName)();
+ }
+
+
+ Layout *Factory::doCreateLayout(const QString &rLayoutClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mLayoutRegistry.contains(rLayoutClassName))
+ {
+ logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName);
+ return 0;
+ }
+ return mLayoutRegistry.value(rLayoutClassName)();
+ }
+
+
+ void Factory::doRegisterAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rAppenderClassName.isEmpty())
+ {
+ logger()->warn("Registering Appender factory function with empty class name");
+ return;
+ }
+ mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc);
+ }
+
+
+ void Factory::doRegisterFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rFilterClassName.isEmpty())
+ {
+ logger()->warn("Registering Filter factory function with empty class name");
+ return;
+ }
+ mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc);
+ }
+
+
+ void Factory::doRegisterLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rLayoutClassName.isEmpty())
+ {
+ logger()->warn("Registering Layout factory function with empty class name");
+ return;
+ }
+ mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc);
+ }
+
+
+ void Factory::doSetObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue)
+ {
+ // - Validate property
+ // - Get correct property name from meta object
+ // - Find specific property setter
+ // - If no specfifc propery setter can be found,
+ // find general property setter
+ // - Call property setter
+
+ QMetaProperty meta_property;
+ if (!validateObjectProperty(meta_property, rProperty, pObject))
+ return;
+
+ QString property = QLatin1String(meta_property.name());
+ QString type = QLatin1String(meta_property.typeName());
+ logger()->debug("Setting property '%1' on object of class '%2' to value '%3'",
+ property,
+ QLatin1String(pObject->metaObject()->className()),
+ rValue);
+
+ QVariant value;
+ bool ok = true;
+ if (type == QLatin1String("bool"))
+ value = OptionConverter::toBoolean(rValue, &ok);
+ else if (type == QLatin1String("int"))
+ value = OptionConverter::toInt(rValue, &ok);
+ else if (type == QLatin1String("Log4Qt::Level"))
+ value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok));
+ else if (type == QLatin1String("QString"))
+ value = rValue;
+ else
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"),
+ CONFIGURATOR_UNKNOWN_TYPE_ERROR,
+ "Log4Qt::Factory");
+ e << type
+ << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ logger()->error(e);
+ return;
+ }
+ if (!ok)
+ return;
+
+ // Everything is checked and the type is the one of the property.
+ // Write should never return false
+ if (!meta_property.write(pObject, value))
+ logger()->warn("Unxpected error result from QMetaProperty.write()");
+ }
+
+
+ void Factory::doUnregisterAppender(const QString &rAppenderClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mAppenderRegistry.contains(rAppenderClassName))
+ {
+ logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName);
+ return;
+ }
+ mAppenderRegistry.remove(rAppenderClassName);
+ }
+
+
+ void Factory::doUnregisterFilter(const QString &rFilterClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mFilterRegistry.contains(rFilterClassName))
+ {
+ logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName);
+ return;
+ }
+ mFilterRegistry.remove(rFilterClassName);
+ }
+
+
+ void Factory::doUnregisterLayout(const QString &rLayoutClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mLayoutRegistry.contains(rLayoutClassName))
+ {
+ logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName);
+ return;
+ }
+ mLayoutRegistry.remove(rLayoutClassName);
+ }
+
+
+ void Factory::registerDefaultAppenders()
+ {
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender);
+
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.SignalAppender"), create_signal_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::SignalAppender"), create_signal_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ColorConsoleAppender"), create_color_console_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ColorConsoleAppender"), create_color_console_appender);
+
+#if defined(QT_SQL_LIB)
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DatabaseAppender"), create_database_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DatabaseAppender"), create_database_appender);
+#endif //#ifdef QT_SQL_LIB
+
+#if defined(QT_NETWORK_LIB)
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.TelnetAppender"), create_telnet_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::TelnetAppender"), create_telnet_appender);
+#endif
+ }
+
+
+ void Factory::registerDefaultFilters()
+ {
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter);
+ }
+
+
+ void Factory::registerDefaultLayouts()
+ {
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout);
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout);
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout);
+
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleTimeLayout"), create_simple_time_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleTimeLayout"), create_simple_time_layout);
+
+#if defined(QT_SQL_LIB)
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.DatabaseLayout"), create_database_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::DatabaseLayout"), create_database_layout);
+#endif //#ifdef (QT_SQL_LIB)
+ }
+
+
+ bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty,
+ const QString &rProperty,
+ QObject *pObject)
+ {
+ // Validate:
+ // - No null object pointer
+ // - No empty property name
+ // - Property exists on the object (QT or Java name)
+ // - Property is readable
+ // - Property is writable
+
+ const char *p_context = "Log4Qt::Factory";
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"),
+ CONFIGURATOR_PROPERTY_ERROR,
+ p_context);
+
+ if (!pObject)
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"),
+ 0,
+ p_context);
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ if (rProperty.isEmpty())
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"),
+ 0,
+ p_context);
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ const QMetaObject *p_meta_object = pObject->metaObject();
+ QString property = rProperty;
+ int i = p_meta_object->indexOfProperty(property.toLatin1());
+ if (i < 0)
+ {
+ // Try name with lower case first character. Java properties names
+ // start upper case
+ property[0] = property[0].toLower();
+ i = p_meta_object->indexOfProperty(property.toLatin1());
+ if (i < 0)
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"),
+ 0,
+ p_context);
+ ce << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ }
+ rMetaProperty = p_meta_object->property(i);
+ if (!rMetaProperty.isWritable())
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"),
+ 0,
+ p_context);
+ ce << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const Factory &rFactory)
+ {
+ debug.nospace() << "Factory("
+ << "appenderfactories:" << rFactory.registeredAppenders()
+ << "filterfactories:" << rFactory.registeredFilters()
+ << "layoutfactories:" << rFactory.registeredLayouts()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/helpers/factory.h b/ext/Log4Qt/src/helpers/factory.h
new file mode 100755
index 0000000..365f1ea
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/factory.h
@@ -0,0 +1,444 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: factory.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_FACTORY_H
+#define LOG4QT_HELPERS_FACTORY_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+#include <QtCore/QStringList>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Appender;
+ class Filter;
+ class Layout;
+
+ /*!
+ * \brief The class Factory provides factories for Appender, Filter and
+ * Layout objects.
+ *
+ * The functions createAppender(), createFilter() and createLayout()
+ * allow to create objects by specifying their class names. By default
+ * all classes of the package are recognised with their Log4j and Log4Qt
+ * classanmes. For example an object of the class FileAppender can be
+ * craeted using "org.apache.log4j.FileAppender" or "Log4Qt::FileAppender".
+ * Additional classes can be registered using registerAppender(),
+ * registerFilter() and registerLayout().
+ *
+ * An QObject property can be set from a string value with
+ * setObjectProperty(). The function handles the required error checking
+ * and type conversion.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa PropertyConfigurator
+ */
+ class LOG4QT_EXPORT Factory
+ {
+ public:
+ /*!
+ * Prototype for an Appender factory function. The function creates
+ * an Appender object on the heap and returns a pointer to it.
+ *
+ * \sa registerAppender(), createAppender()
+ */
+ typedef Appender *(*AppenderFactoryFunc)();
+
+ /*!
+ * Prototype for a Filter factory function. The function creates
+ * a Filter object on the heap and returns a pointer to it.
+ *
+ * \sa registerFilter(), createFilter()
+ */
+ typedef Filter *(*FilterFactoryFunc)();
+
+ /*!
+ * Prototype for a Layout factory function. The function creates
+ * a Layout object on the heap and returns a pointer to it.
+ *
+ * \sa registerLayout(), createLayout()
+ */
+ typedef Layout *(*LayoutFactoryFunc)();
+
+ private:
+ Factory();
+ Factory(const Factory &rOther); // Not implemented
+ // virtual ~Factory(); // Use compiler default
+ Factory &operator=(const Factory &rOther); // Not implemented
+
+ public:
+ /*!
+ * Creates an object for the class \a rAppenderClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerAppender(), unregisterAppender(), registeredAppenders()
+ */
+ static Appender *createAppender(const QString &rAppenderClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Appender *createAppender(const char *pAppenderClassName);
+
+ /*!
+ * Creates an object for the class \a rFilterClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerFilter(), unregisterFilter(), registeredFilters()
+ */
+ static Filter *createFilter(const QString &rFilterClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Filter *createFilter(const char *pFilterClassName);
+
+ /*!
+ * Creates an object for the class \a rLayoutClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerLayout(), unregisterLayout(), registeredLayouts()
+ */
+ static Layout *createLayout(const QString &rLayoutClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Layout *createLayout(const char *pLayoutClassName);
+
+ /*!
+ * Returns the Factory instance.
+ */
+ static Factory *instance();
+
+ /*!
+ * Registers the Appender factory function \a pAppenderFactoryFunc
+ * for the class \a rAppenderClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pAppenderFactoryFunc.
+ *
+ * \sa unregisterAppender(), registeredAppenders(), createAppender()
+ */
+ static void registerAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerAppender(const char *pAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+
+ /*!
+ * Registers the Filter factory function \a pFilterFactoryFunc
+ * for the class \a rFilterClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pFilterFactoryFunc.
+ *
+ * \sa unregisterFilter(), registeredFilters(), createFilter()
+ */
+ static void registerFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerFilter(const char *pFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+
+ /*!
+ * Registers the Layout factory function \a pLayoutFactoryFunc
+ * for the class \a rLayoutClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pLayoutFactoryFunc.
+ *
+ * \sa unregisterLayout(), registeredLayout(), createLayout()
+ */
+ static void registerLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerLayout(const char *pLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+
+ /*!
+ * Returns a list of the class names for registered Appender factory
+ * functions.
+ *
+ * \sa registerAppender(), unregisterAppender()
+ */
+ static QStringList registeredAppenders();
+
+ /*!
+ * Returns a list of the class names for registered Filter factory
+ * functions.
+ *
+ * \sa registerFilter(), unregisterFilter()
+ */
+ static QStringList registeredFilters();
+
+ /*!
+ * Returns a list of the class names for registered Layout factory
+ * functions.
+ *
+ * \sa registerLayout(), unregisterLayout()
+ */
+ static QStringList registeredLayouts();
+
+ /*!
+ * Sets the property \a rProperty of the object \a pObject to the
+ * value \a rValue. The function will test that the property
+ * \a rProperty is writeable and of a type the function can convert to.
+ * The types bool, int, Level and QString are supported.
+ *
+ * \sa OptionConverter
+ */
+ static void setObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void setObjectProperty(QObject *pObject,
+ const char *pProperty,
+ const QString &rValue);
+
+ /*!
+ * Unregisters the Appender factory function for the class
+ * \a rAppenderClassName.
+ *
+ * \sa registerAppender(), registeredAppenders()
+ */
+ static void unregisterAppender(const QString &rAppenderClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterAppender(const char *pAppenderClassName);
+
+ /*!
+ * Unregisters the Filter factory function for the class
+ * \a rFilterClassName.
+ *
+ * \sa registerFilter(), registeredFilters()
+ */
+ static void unregisterFilter(const QString &rFilterClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterFilter(const char *pFilterClassName);
+
+ /*!
+ * Unregisters the Layout factory function for the class
+ * \a rLayoutClassName.
+ *
+ * \sa registerLayout(), registeredLayouts()
+ */
+ static void unregisterLayout(const QString &rLayoutClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterLayout(const char *pLayoutClassName);
+
+ private:
+ Appender *doCreateAppender(const QString &rAppenderClassName);
+ Filter *doCreateFilter(const QString &rFilterClassName);
+ Layout *doCreateLayout(const QString &rLayoutClassName);
+ void doRegisterAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+ void doRegisterFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+ void doRegisterLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+ void doSetObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue);
+ void doUnregisterAppender(const QString &rAppenderClassName);
+ void doUnregisterFilter(const QString &rFilterClassName);
+ void doUnregisterLayout(const QString &rLayoutClassName);
+ void registerDefaultAppenders();
+ void registerDefaultFilters();
+ void registerDefaultLayouts();
+ bool validateObjectProperty(QMetaProperty &rMetaProperty,
+ const QString &rProperty,
+ QObject *pObject);
+
+ private:
+ mutable QMutex mObjectGuard;
+ QHash<QString, AppenderFactoryFunc> mAppenderRegistry;
+ QHash<QString, FilterFactoryFunc> mFilterRegistry;
+ QHash<QString, LayoutFactoryFunc> mLayoutRegistry;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Factory
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %Factory(appenderfactories:("Log4Qt::DebugAppender", "Log4Qt::NullAppender",
+ * "Log4Qt::ConsoleAppender", "org.apache.log4j.varia.DebugAppender",
+ * "org.apache.log4j.FileAppender", "org.apache.log4j.RollingFileAppender",
+ * "org.apache.log4j.DailyRollingFileAppender",
+ * "org.apache.log4j.varia.ListAppender",
+ * "org.apache.log4j.varia.NullAppender",
+ * "Log4Qt::FileAppender", "org.apache.log4j.ConsoleAppender",
+ * "Log4Qt::DailyRollingFileAppender", "Log4Qt::ListAppender",
+ * "Log4Qt::RollingFileAppender") filterfactories:
+ * ("Log4Qt::DenyAllFilter", "Log4Qt::StringMatchFilter",
+ * "Log4Qt::LevelRangeFilter", "org.apache.log4j.varia.DenyAllFilter",
+ * "org.apache.log4j.varia.LevelRangeFilter",
+ * "org.apache.log4j.varia.StringMatchFilter", "Log4Qt::LevelMatchFilter",
+ * "org.apache.log4j.varia.LevelMatchFilter") layoutfactories:
+ * ("org.apache.log4j.SimpleLayout", "Log4Qt::PatternLayout",
+ * "Log4Qt::SimpleLayout", "org.apache.log4j.TTCCLayout",
+ * "Log4Qt::TTCCLayout", "org.apache.log4j.PatternLayout") )
+ * </tt>
+ * \sa QDebug, Factory::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const Factory &rFactory);
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Appender *Factory::createAppender(const QString &rAppenderClassName)
+ { return instance()->doCreateAppender(rAppenderClassName); }
+
+ inline Appender *Factory::createAppender(const char *pAppenderClassName)
+ { return instance()->doCreateAppender(QLatin1String(pAppenderClassName)); }
+
+ inline Filter *Factory::createFilter(const QString &rFilterClassName)
+ { return instance()->doCreateFilter(rFilterClassName); }
+
+ inline Filter *Factory::createFilter(const char *pFilterClassName)
+ { return instance()->doCreateFilter(QLatin1String(pFilterClassName)); }
+
+ inline Layout *Factory::createLayout(const QString &rLayoutClassName)
+ { return instance()->doCreateLayout(rLayoutClassName); }
+
+ inline Layout *Factory::createLayout(const char *pLayoutClassName)
+ { return instance()->doCreateLayout(QLatin1String(pLayoutClassName)); }
+
+ inline void Factory::registerAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ { instance()->doRegisterAppender(rAppenderClassName, pAppenderFactoryFunc); }
+
+ inline void Factory::registerAppender(const char *pAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ { instance()->doRegisterAppender(QLatin1String(pAppenderClassName), pAppenderFactoryFunc); }
+
+ inline void Factory::registerFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ { instance()->doRegisterFilter(rFilterClassName, pFilterFactoryFunc); }
+
+ inline void Factory::registerFilter(const char *pFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ { instance()->doRegisterFilter(QLatin1String(pFilterClassName), pFilterFactoryFunc); }
+
+ inline void Factory::registerLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ { instance()->doRegisterLayout(rLayoutClassName, pLayoutFactoryFunc); }
+
+ inline void Factory::registerLayout(const char *pLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ { instance()->doRegisterLayout(QLatin1String(pLayoutClassName), pLayoutFactoryFunc); }
+
+ inline QStringList Factory::registeredAppenders()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mAppenderRegistry.keys(); }
+
+ inline QStringList Factory::registeredFilters()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mFilterRegistry.keys(); }
+
+ inline QStringList Factory::registeredLayouts()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mLayoutRegistry.keys(); }
+
+ inline void Factory::setObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue)
+ { instance()->doSetObjectProperty(pObject, rProperty, rValue); }
+
+ inline void Factory::setObjectProperty(QObject *pObject,
+ const char *pProperty,
+ const QString &rValue)
+ { instance()->doSetObjectProperty(pObject, QLatin1String(pProperty), rValue); }
+
+ inline void Factory::unregisterAppender(const QString &rAppenderClassName)
+ { instance()->doUnregisterAppender(rAppenderClassName); }
+
+ inline void Factory::unregisterAppender(const char *pAppenderClassName)
+ { instance()->doUnregisterAppender(QLatin1String(pAppenderClassName)); }
+
+ inline void Factory::unregisterFilter(const QString &rFilterClassName)
+ { instance()->doUnregisterFilter(rFilterClassName); }
+
+ inline void Factory::unregisterFilter(const char *pFilterClassName)
+ { instance()->doUnregisterFilter(QLatin1String(pFilterClassName)); }
+
+ inline void Factory::unregisterLayout(const QString &rLayoutClassName)
+ { instance()->doUnregisterLayout(rLayoutClassName); }
+
+ inline void Factory::unregisterLayout(const char *pLayoutClassName)
+ { instance()->doUnregisterLayout(QLatin1String(pLayoutClassName)); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::Factory, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_FACTORY_H
diff --git a/ext/Log4Qt/src/helpers/initialisationhelper.cpp b/ext/Log4Qt/src/helpers/initialisationhelper.cpp
new file mode 100755
index 0000000..c2d72a8
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/initialisationhelper.cpp
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: initialisationhelper.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/initialisationhelper.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QMutex>
+#include <QtCore/QProcess>
+#include <QtCore/QSettings>
+#include "helpers/datetime.h"
+#include "helpers/logerror.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: InitialisationHelper
+ **************************************************************************/
+
+
+ InitialisationHelper::InitialisationHelper() :
+ mStartTime(DateTime::currentDateTime().toMilliSeconds()),
+ mEnvironmentSettings()
+ {
+ doRegisterTypes();
+ doInitialiseEnvironmentSettings();
+ }
+
+
+ InitialisationHelper::~InitialisationHelper()
+ {
+ Q_ASSERT_X(false, "InitialisationHelper::~InitialisationHelper()", "Unexpected destruction of singleton object");
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(InitialisationHelper)
+
+
+ void InitialisationHelper::doInitialiseEnvironmentSettings()
+ {
+ // Is Process::systemEnvironment() safe to be used before a QCoreApplication
+ // object has been created?
+
+ QStringList setting_keys;
+ setting_keys << QLatin1String("Debug");
+ setting_keys << QLatin1String("DefaultInitOverride");
+ setting_keys << QLatin1String("Configuration");
+ setting_keys << QLatin1String("ConfiguratorClass");
+
+ QHash<QString, QString> env_keys;
+ QString entry;
+ Q_FOREACH(entry, setting_keys)
+ env_keys.insert(QString::fromLatin1("log4qt_").append(entry).toUpper(), entry);
+
+ QStringList sys_env = QProcess::systemEnvironment();
+ Q_FOREACH(entry, sys_env)
+ {
+ int i = entry.indexOf(QLatin1Char('='));
+ if (i == -1)
+ continue;
+ QString key = entry.left(i);
+ QString value = entry.mid(i + 1).trimmed();
+ if (env_keys.contains(key))
+ mEnvironmentSettings.insert(env_keys.value(key), value);
+ }
+ }
+
+
+ void InitialisationHelper::doRegisterTypes()
+ {
+ qRegisterMetaType<Log4Qt::LogError>("Log4Qt::LogError");
+ qRegisterMetaType<Log4Qt::Level>("Log4Qt::Level");
+ qRegisterMetaType<Log4Qt::LoggingEvent>("Log4Qt::LoggingEvent");
+
+#ifndef QT_NO_DATASTREAM
+ qRegisterMetaTypeStreamOperators<Log4Qt::LogError>("Log4Qt::LogError");
+ qRegisterMetaTypeStreamOperators<Log4Qt::Level>("Log4Qt::Level");
+ qRegisterMetaTypeStreamOperators<LoggingEvent>("Log4Qt::LoggingEvent");
+#endif
+ }
+
+
+ QString InitialisationHelper::doSetting(const QString &rKey,
+ const QString &rDefault) const
+ {
+ if (mEnvironmentSettings.contains(rKey))
+ return mEnvironmentSettings.value(rKey);
+
+ if (QCoreApplication::instance())
+ {
+ QSettings s;
+ s.beginGroup(QLatin1String("Log4Qt"));
+ return s.value(rKey, rDefault).toString().trimmed();
+ }
+ else
+ return rDefault;
+ }
+
+
+ bool InitialisationHelper::staticInitialisation()
+ {
+ instance();
+ return true;
+ }
+
+
+ bool InitialisationHelper::msStaticInitialisation = staticInitialisation();
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper)
+ {
+ Q_UNUSED(rInitialisationHelper);
+ debug.nospace() << "InitialisationHelper("
+ << "starttime:" << InitialisationHelper::startTime()
+ << "(" << DateTime::fromMilliSeconds(InitialisationHelper::startTime()) << ")"
+ << "environmentsettings:" << InitialisationHelper::environmentSettings()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/initialisationhelper.h b/ext/Log4Qt/src/helpers/initialisationhelper.h
new file mode 100755
index 0000000..ea508da
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/initialisationhelper.h
@@ -0,0 +1,435 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: initialisationhelper.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QBasicAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H
+#define LOG4QT_HELPERS_INITIALISATIONHELPER_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QAtomicPointer>
+#include <QtCore/QHash>
+#include <QString>
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+# warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe."
+# endif
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QMutex;
+
+namespace Log4Qt
+{
+ /*!
+ * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that
+ * returns a pointer to a singleton object of the type \a TYPE.
+ *
+ * The macro uses a static variable to store a pointer to the singleton
+ * object. On the first invocation an object of the type \a TYPE is created
+ * on the heap and the pointer is set. Any further invocations will return
+ * the stored pointer. If multiple threads are accessing the function
+ * without the pointer being set, each thread will create an object of the
+ * type \a TYPE. The threads that find the pointer already been set will
+ * delete their object. The singleton object will not be deleted during static
+ * de-initialisation.
+ *
+ * The following example uses a global global mutex object to synchronise
+ * access to a static member variable.
+ *
+ * \code
+ * #file: myclass.h
+ *
+ * class MyClass
+ * {
+ * public:
+ * MyClass();
+ * ~MyClass();
+ * private:
+ * static qint64 msObjectCount;
+ * }
+ * \endcode
+ * \code
+ * #file: myclass.cpp
+ *
+ * #include myclass.h
+ *
+ * LOG4QT_GLOBAL_STATIC(QMutex, class_guard)
+ *
+ * MyClass::MyClass()
+ * {
+ * QMutexLocker(class_guard());
+ * msObjectCount++;
+ * }
+ *
+ * MyClass::~MyClass()
+ * {
+ * QMutexLocker(class_guard());
+ * msObjectCount--;
+ * }
+ *
+ * qint64 MyClass::msObjectCount = 0;
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE",
+ * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
+ */
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static volatile TYPE *sp_global_static_##FUNCTION = 0; \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \
+ 0, p_temp)) \
+ delete p_temp; \
+ } \
+ return const_cast<TYPE *>(sp_global_static_##FUNCTION); \
+ }
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
+ p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_global_static_##FUNCTION; \
+ }
+#else
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION.loadAcquire()) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
+ p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_global_static_##FUNCTION.loadAcquire(); \
+ }
+#endif
+
+ /*!
+ * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a
+ * singleton class \a TYPE.
+ *
+ * The function works like the one created by
+ * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC".
+ *
+ * The following example illustrates how to use the macro to create a
+ * singleton class:
+ *
+ * \code
+ * #file: mysingleton.h
+ *
+ * class MySingleton
+ * {
+ * private:
+ * MySingleton();
+ * ~MySingleton();
+ * public:
+ * MySingleton *instance();
+ * }
+ * \endcode
+ * \code
+ * #file: mysingleton.cpp
+ *
+ * #include mysingleton.h
+ *
+ * MySingleton::MySingleton()
+ * {}
+ *
+ * MySingleton::~MySingleton()
+ * {}
+ *
+ * LOG4QT_IMPLEMENT_INSTANCE(MySingleton)
+ *
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC",
+ * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
+ */
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static TYPE *sp_singleton_##TYPE = 0; \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \
+ 0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE; \
+ }
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE; \
+ }
+#else
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE.loadAcquire()) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE.loadAcquire(); \
+ }
+#endif
+
+ /*!
+ * \brief The class InitialisationHelper performs static initialisation
+ * tasks.
+ *
+ * The InitialisationHelper is either created on the first call or through
+ * static initialisation. It will capture the programs startup time,
+ * which can be retrieved using startTime(). The system environment
+ * is analysed for package related definitions. The result is available
+ * over environmentSettings(). The packages custom types are registered with
+ * the Qt type system.
+ *
+ * Settings for the package can be retrieved using setting(). Two macros
+ * are available to help with the creation of singletons / global static
+ * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and
+ * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE").
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa \ref Init "Initialization procedure",
+ */
+ class LOG4QT_EXPORT InitialisationHelper
+ {
+ private:
+ InitialisationHelper();
+ InitialisationHelper(const InitialisationHelper &rOther); // Not implemented
+ virtual ~InitialisationHelper();
+ InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented
+
+ public:
+
+ /*!
+ * Returns a hash with the settings retrieved from the system
+ * environment on startup.
+ *
+ * The following table shows the environment variables taken into
+ * account and the setting key used for them.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="25%"> Environment variable </th>
+ * <th width="25%"> Setting key </th>
+ * </tr><tr>
+ * <td> LOG4QT_DEBUG </td>
+ * <td> Debug </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> LOG4QT_DEFAULTINITOVERRIDE </td>
+ * <td> DefaultInitOverride </td>
+ * </tr><tr>
+ * <td> LOG4QT_CONFIGURATION </td>
+ * <td> Configuration </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> LOG4QT_CONFIGURATORCLASS </td>
+ * <td> ConfiguratorClass </td>
+ * </tr>
+ * </table>
+ *
+ * \sa \ref Env "Environment Variables",
+ * setting()
+ */
+ static QHash<QString, QString> environmentSettings();
+
+ /*!
+ * Returns the InitialisationHelper instance.
+ */
+ static InitialisationHelper *instance();
+
+ /*!
+ * Returns the value for the setting \a rKey or \a rDefault, if it is
+ * not defined.
+ *
+ * A setting can be either defined by an environment variable or by a
+ * key in the application setting. The function will first test the
+ * settings made by environment variables for the key \a rKey using
+ * environmentSettings(). If the key is not present and a
+ * QCoreApplication exists, the application settings are tested for
+ * the key \a rKey in the group \c %Log4Qt.
+ *
+ * The following setting exists:
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="25%"> Setting key </th>
+ * <th> Description </th>
+ * </tr><tr>
+ * <td> Debug </td>
+ * <td> The variable controls the Level value for the logger
+ * LogManager::logLogger(). If the value is a valid Level string,
+ * the level for the logger is set to the level. If the value is not
+ * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used.
+ * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used. </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> DefaultInitOverride </td>
+ * <td> The variable controls the \ref Init "initialization procedure"
+ * performed by the \ref LogManager "LogManager" on startup.
+ * If it is set to any other value then \c false the \ref Init
+ * "initialization procedure" is skipped.</td>
+ * </tr><tr>
+ * <td> Configuration </td>
+ * <td> Specifies the configuration file used for initialising the package.</td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> ConfiguratorClass </td>
+ * <td> Specifies the configurator class used for initialising the package.</td>
+ * </tr>
+ * </table>
+ *
+ * \sa environmentSettings(), \ref Env "Environment Variables",
+ * \ref Init "Initialization procedure",
+ * LogManager::configureLogLogger(), LogManager::startup()
+ */
+ static QString setting(const QString &rKey,
+ const QString &rDefault = QString());
+
+ /*!
+ * Returns the start time of the program as the number of milliseconds
+ * that have passed since 1970-01-01T00:00:00,000, Coordinated
+ * Universal Time (Qt::UTC).
+ *
+ * \sa DateTime::fromMilliSeconds(),
+ * DateTime::toMilliSeconds()
+ */
+ static qint64 startTime();
+
+ private:
+ void doInitialiseEnvironmentSettings();
+ void doRegisterTypes();
+ QString doSetting(const QString &rKey,
+ const QString &rDefault) const;
+ static bool shutdown();
+ static bool staticInitialisation();
+
+ private:
+ // QMutex mObjectGuard;
+ const qint64 mStartTime;
+ QHash <QString, QString> mEnvironmentSettings;
+ static bool msStaticInitialisation;
+
+#ifndef QT_NO_DEBUG_STREAM
+ // Needs to be friend to access details
+ friend QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper);
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates InitialisationHelper
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %InitialisationHelper(InitialisationHelper(starttime:1193883677438(
+ * QDateTime("Wed Oct 31 21:21:17 2007") )
+ * environmentsettings: QHash(("configuration", "\myapp.log4j")
+ * ("Debug", "DEBUG")) ) )
+ * </tt>
+ * \sa QDebug, InitialisationHelper::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QHash<QString, QString> InitialisationHelper::environmentSettings()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return instance()->mEnvironmentSettings; }
+
+ inline QString InitialisationHelper::setting(const QString &rKey,
+ const QString &rDefault)
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const
+ return instance()->doSetting(rKey, rDefault); }
+
+ inline qint64 InitialisationHelper::startTime()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return instance()->mStartTime; }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H
diff --git a/ext/Log4Qt/src/helpers/logerror.cpp b/ext/Log4Qt/src/helpers/logerror.cpp
new file mode 100755
index 0000000..1bf8030
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logerror.cpp
@@ -0,0 +1,352 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logerror.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ *****************************************************************************/
+
+
+#include "helpers/logerror.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QByteArray>
+#include <QtCore/QDataStream>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+#include <QtCore/QThreadStorage>
+#include "helpers/initialisationhelper.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+ typedef QThreadStorage<LogError *> ThreadError;
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_GLOBAL_STATIC(ThreadError, thread_error)
+
+
+
+ /**************************************************************************
+ * Class implementation: LogError
+ **************************************************************************/
+
+
+ LogError::LogError() :
+ mCode(0),
+ mContext(),
+ mMessage(),
+ mSymbol(),
+ mArgs(),
+ mCausingErrors()
+ {
+ }
+
+
+ LogError::LogError(const QString &rMessage,
+ int code,
+ const QString &rSymbol,
+ const QString &rContext) :
+ mCode(code),
+ mContext(rContext),
+ mMessage(cleanMessage(rMessage)),
+ mSymbol(rSymbol),
+ mArgs(),
+ mCausingErrors()
+ {
+ }
+
+
+ LogError::LogError(const char *pMessage,
+ int code,
+ const char *pSymbol,
+ const char *pContext,
+ Encoding encoding) :
+ mCode(code),
+ mContext(QString::fromLatin1(pContext)),
+ mMessage(),
+ mSymbol(QString::fromLatin1(pSymbol)),
+ mArgs(),
+ mCausingErrors()
+ {
+ switch(encoding)
+ {
+ case LATIN1:
+ mMessage = QString::fromLatin1(pMessage);
+ break;
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ case CODECFORTR:
+ mMessage = QTextCodec::codecForTr()->toUnicode(pMessage);
+ break;
+#endif
+ case UNICODEUTF8:
+ mMessage = QString::fromUtf8(pMessage);
+ break;
+ default:
+ Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant");
+ mMessage = QString::fromLatin1(pMessage);
+ }
+ mMessage = cleanMessage(mMessage);
+
+ if (mSymbol == QString::number(mCode))
+ mSymbol.clear();
+ }
+
+
+ QString LogError::translatedMessage() const
+ {
+ return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ , QCoreApplication::UnicodeUTF8
+#endif
+ );
+ }
+
+
+ LogError LogError::lastError()
+ {
+ if (!thread_error()->hasLocalData())
+ return LogError();
+ else
+ return *thread_error()->localData();
+ }
+
+
+ void LogError::setLastError(const LogError &rLogError)
+ {
+ if (!thread_error()->hasLocalData())
+ thread_error()->setLocalData(new LogError);
+
+ *thread_error()->localData() = rLogError;
+ }
+
+
+ QString LogError::toString() const
+ {
+ QString result = messageWithArgs();
+
+ QString context_symbol = mContext;
+ if (!context_symbol.isEmpty() && !mSymbol.isEmpty())
+ context_symbol.append(QLatin1String("::"));
+ context_symbol.append(mSymbol);
+
+ if (!context_symbol.isEmpty() || mCode)
+ {
+ result.append(QLatin1String(" ("));
+ if (!context_symbol.isEmpty())
+ result.append(context_symbol);
+ if (!context_symbol.isEmpty() && mCode)
+ result.append(QLatin1String(", "));
+ if (mCode)
+ result.append(QString::number(mCode));
+ result.append(QLatin1String(")"));
+ }
+
+ if (!mCausingErrors.isEmpty())
+ {
+ QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString();
+ int i = 1;
+ while (i < mCausingErrors.count())
+ {
+ causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString());
+ i++;
+ }
+ result.append(causing_errors_str);
+ }
+
+ return result;
+ }
+
+
+ QString LogError::insertArgs(const QString &rMessage) const
+ {
+ QString result;
+
+ /*
+
+ // Don't use a loop to be able to handle arguments that conatin strings
+ // like %1.
+ // Using this method only 9 arguments can be handled as the %1
+ // in %11 gets also replaced with the first argument.
+
+ switch (mArgs.count())
+ {
+ case 0:
+ break;
+ case 1:
+ result = rMessage.arg(mArgs.at(0));
+ break;
+ case 2:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1));
+ break;
+ case 3:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2));
+ break;
+ case 4:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3));
+ break;
+ case 5:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4));
+ break;
+ case 6:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5));
+ break;
+ case 7:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6));
+ break;
+ case 8:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7));
+ break;
+ default:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8));
+ break;
+ }
+
+ if (mArgs.count() > 9)
+ {
+ int i = 9;
+ while(i < mArgs.count())
+ {
+ result = result.arg(mArgs.at(i));
+ i++;
+ }
+ }
+ */
+
+ result = rMessage;
+ QVariant arg;
+ Q_FOREACH(arg, mArgs)
+ result = result.arg(arg.toString());
+ return result;
+ }
+
+
+ QString LogError::cleanMessage(const QString &rMessage)
+ {
+ if (rMessage.isEmpty())
+ return rMessage;
+
+ QString result = rMessage;
+ if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.'))
+ result = rMessage.left(rMessage.size() - 1);
+ return result;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DATASTREAM
+ QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError)
+ {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version = 0;
+ stream << version;
+ // version 0 data
+ stream << rLogError.mCode
+ << rLogError.mContext
+ << rLogError.mMessage
+ << rLogError.mSymbol
+ << rLogError.mArgs
+ << rLogError.mCausingErrors;
+
+ buffer.close();
+ rStream << buffer.buffer();
+ return rStream;
+ }
+
+
+ QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError)
+ {
+ QByteArray array;
+ rStream >> array;
+ QBuffer buffer(&array);
+ buffer.open(QIODevice::ReadOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version;
+ stream >> version;
+ // Version 0 data
+ QString level;
+ QString logger;
+ stream >> rLogError.mCode
+ >> rLogError.mContext
+ >> rLogError.mMessage
+ >> rLogError.mSymbol
+ >> rLogError.mArgs
+ >> rLogError.mCausingErrors;
+
+ buffer.close();
+ return rStream;
+ }
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LogError &rLogError)
+ {
+ // Escape % sign
+ QString message = rLogError.message();
+ message.replace(QLatin1String("%"), QLatin1String("%%"));
+
+ debug.nospace() << "LogError("
+ << "code:" << rLogError.code() << " "
+ << "context:" << rLogError.context() << " "
+ << "message:" << message << " "
+ << "symbol:" << rLogError.symbol() << " "
+ << "args:" << rLogError.args()
+ << "translatedMessage:" << rLogError.translatedMessage()
+ << ")";
+ return debug.maybeSpace();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logerror.h b/ext/Log4Qt/src/helpers/logerror.h
new file mode 100755
index 0000000..4ea7cfe
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logerror.h
@@ -0,0 +1,550 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logerror.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGERROR_H
+#define LOG4QT_LOGERROR_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+ /*!
+ * Creates an LogError object with the error message \a message, the error
+ * code \a code and the context \a context. The symbol of the error is
+ * set to \a code as string value.
+ *
+ * The following example logs an error, if a character is not a digit.
+ *
+ * \code
+ * if (!c.isDigit())
+ * {
+ * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."),
+ * LAYOUT_EXPECTED_DIGIT_ERROR,
+ * "Log4Qt::PatternFormatter");
+ * e << QString(c);
+ * logger()->error(e);
+ * }
+ * \endcode
+ */
+ #define LOG4QT_ERROR(message, code, context) \
+ LogError(message, code, #code, context)
+
+ /*!
+ * Creates an LogError object with the error message \a message and the
+ * error code \a code. The symbol of the error is set to \a code as string
+ * value. The context is set to the class name of the current object. The
+ * current objects class must be derived from QObject.
+ *
+ * The following example handles an error while opening a file.
+ *
+ * \code
+ * if (!mpFile->open(mode))
+ * {
+ * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"),
+ * APPENDER_OPENING_FILE_ERROR);
+ * e << mFileName << name();
+ * e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
+ * logger()->error(e);
+ * return;
+ * }
+ * \endcode
+ */
+ #define LOG4QT_QCLASS_ERROR(message, code) \
+ LogError(message, code, #code, this->metaObject()->className())
+
+ /*!
+ * \brief The class LogError represents an error.
+ *
+ * The class error allows storing error information in a structured way.
+ * The error message is stored separately from the information that may be
+ * substituted into the message string. This way it is possible to access
+ * all information after the error has been raised. It also allows to
+ * translate the error at a later point in time or to get a translated and
+ * a not translated error text (e.g. translated for the UI and not
+ * translated for a log).
+ *
+ * The message is accessed using message() and setMessage(). Arguments for
+ * the message can be added using addArg() or operator<<(). The arguments
+ * can be retrieved using args(). The message with substituted arguments
+ * is returned by messageWithArgs().
+ *
+ * An error code can be set as integer value code() and/or a symbolic value
+ * symbol().
+ *
+ * To allow the translation of the message the error stores the translation
+ * context (context(), setContext()). The translated message can be accessed
+ * using translatedMessage() or using translatedMessageWithArgs(), if it
+ * should contain the arguments.
+ *
+ * An error can have one or more related errors that caused it. An error is
+ * related using addCausingError(). All causing errors can be retrieved using
+ * causingErrors().
+ *
+ * A per thread error can be maintained using lastError() and setLastError().
+ *
+ * There are two macros avaiable to simplify the error creation. The macro
+ * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived
+ * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
+ * is used with classes derived from QObject.
+ */
+ class LOG4QT_EXPORT LogError
+ {
+ public:
+
+ /*!
+ * The enum Encoding defines the 8-bit encoding of a character string
+ * arguments to \ref LogError::LogError(const char *, int, const char *,
+ * const char *, Encoding) "LogError::LogError()".
+ *
+ * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()"
+ */
+ enum Encoding
+ {
+ /*! LATIN-1 */
+ LATIN1,
+ /*!
+ * The encoding specified by QTextCodec::codecForTr()
+ * (Latin-1 if none has been set).
+ */
+ CODECFORTR,
+ /*! UTF-8 */
+ UNICODEUTF8
+ };
+ //Q_ENUMS(Encoding)
+
+ /*!
+ * Creates an empty error. The error code is set to 0 and all other
+ * members are set to be empty.
+ *
+ * \sa isEmpty()
+ */
+ LogError();
+
+ /*!
+ * Creates an error with the Message \a rMessage and the error code
+ * \a code. The symbol for the error code is set to \a rSymbol and the
+ * context to \a rContext.
+ *
+ * \a rContext must be string that can be converted to Latin-1. The
+ * Latin-1 representation of the string is used with
+ * QApplication::translate(), if a translation for \a rMessage is
+ * requested.
+ *
+ * \sa translatedMessage(), translatedMessageWithArgs()
+ */
+ LogError(const QString &rMessage,
+ int code = 0,
+ const QString &rSymbol = QString(),
+ const QString &rContext = QString());
+
+ /*!
+ * Creates an error with the Message \a pMessage and the error code
+ * \a code. The symbol for the error code is set to \a pSymbol and the
+ * context to \a pContext.
+ *
+ * \a encoding specifies the encoding of \a pMessage. \a pSymbol and
+ * \a pContext are expected to be Latin-1.
+ *
+ * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR"
+ * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
+ * the function tests, if \a pSymbol is the string representation of
+ * \a code. If it is, the symbol is set to be empty. Otherwise symbol
+ * is set to \a pSymbol.
+ *
+ * \sa translatedMessage(), translatedMessageWithArgs()
+ */
+ LogError(const char *pMessage,
+ int code = 0,
+ const char *pSymbol = 0,
+ const char *pContext = 0,
+ Encoding encoding = LATIN1);
+
+ // LogError(const LogError &rOther); // Use compiler default
+ // virtual ~LogError(); // Use compiler default
+ // LogError &operator=(const LogError &rOther); // Use compiler default
+
+ /*!
+ * Returns the error code.
+ *
+ * \sa setCode()
+ */
+ int code() const;
+
+ /*!
+ * Returns the context for the error.
+ *
+ * \sa setContext()
+ */
+ QString context() const;
+
+ /*!
+ * Returns the error message.
+ *
+ * \sa setMessage()
+ */
+ QString message() const;
+
+ /*!
+ * Returns the symbol for the error code.
+ *
+ * \sa setSymbol()
+ */
+ QString symbol() const;
+
+ /*!
+ * Returns the translated error message.
+ *
+ * The translated message is created by calling
+ * QCoreApplication::translate() using context().toLatin1() as
+ * context and message.toUtf8() as message.
+ *
+ * \sa translatedMessageWithArgs()
+ */
+ QString translatedMessage() const;
+
+ /*!
+ * Sets the error code to \a code.
+ *
+ * \sa code()
+ */
+ void setCode(int code);
+
+ /*!
+ * Sets the context to \a rClassName.
+ *
+ * \a rContext must be string that can be converted to Latin-1. The
+ * Latin-1 representation of the string is used with
+ * QApplication::translate(), if a translation for \a rMessage is
+ * requestd.
+ *
+ * \sa context(), translatedMessage(), translatedMessageWithArgs()
+ */
+ void setContext(const QString &rClassName);
+
+ /*!
+ * Sets the error message to \a rMessage
+ *
+ * \sa message()
+ */
+ void setMessage(const QString &rMessage);
+
+ /*!
+ * Sets the symbol for the error code to \a rSymbol.
+ *
+ * \sa symbol()
+ */
+ void setSymbol(const QString &rSymbol);
+
+ /*!
+ * Returns the last error set for the current thread using
+ * setLastError().
+ *
+ * \note: This function is thread-safe.
+ *
+ * \sa setLastError()
+ */
+ static LogError lastError();
+
+ /*!
+ * Sets the last error for the current thread to \a rLogError.
+ *
+ * \note: This function is thread-safe.
+ *
+ * \sa lastError()
+ */
+ static void setLastError(const LogError &rLogError);
+
+ /*!
+ * Appends \a rArg to the list of arguments and returns a reference to
+ * this error.
+ *
+ * \sa operator<<(), args(), clearArgs()
+ */
+ LogError &addArg(const QVariant &rArg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &addArg(int arg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &addArg(const QString &rArg);
+
+ /*!
+ * Appends \a rLogError to the list of causing errors and returns a
+ * reference to this error.
+ *
+ * \sa causingErrors(), clearCausingErrors()
+ */
+ LogError &addCausingError(const LogError &rLogError);
+
+ /*!
+ * Returns the list of arguments that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), clearArgs()
+ */
+ QList<QVariant> args() const;
+
+ /*!
+ * Returns the list of causing errors that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), clearArgs()
+ */
+ QList<LogError> causingErrors() const;
+
+ /*!
+ * Clears the list of arguments that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), args()
+ */
+ void clearArgs();
+
+ /*!
+ * Clears the list of causing errors that have been added to this error.
+ *
+ * \sa addCausingError(), causingErrors()
+ */
+ void clearCausingErrors();
+
+ /*!
+ * Returns true, if the error code is 0 and the message is empty.
+ * Otherwise it returns false.
+ *
+ * \sa code(), message()
+ */
+ bool isEmpty() const;
+
+ /*!
+ * Returns the message with arguments. The arguments are incoorporated
+ * into the messag using QString::arg().
+ *
+ * \sa QString::arg(), translatedMessageWithArgs()
+ */
+ QString messageWithArgs() const;
+
+ /*!
+ * Returns the translated message with arguments. The arguments are
+ * incoorporated into the messag using QString::arg().
+ *
+ * \sa QString::arg(), messageWithArgs(), translatedMessage()
+ */
+ QString translatedMessageWithArgs() const;
+
+ /*!
+ * Appends \a rArg to the list of arguments and returns a reference to
+ * this error.
+ *
+ * \sa addArg()
+ */
+ LogError &operator<<(const QVariant &rArg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &operator<<(int arg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &operator<<(const QString &rArg);
+
+ /*!
+ * Returns a string representation of the error.
+ *
+ * The string has the following format:
+ *
+ * <tt>
+ * message (context::symbol, code): causing_error, causing_error
+ * </tt>
+ *
+ * If members are empty they are omitted:
+ * - Omit context, if empty
+ * - Omit symbol, if empty
+ * - Omit double colon with context and symbol, if both are empty
+ * - Omit code, if 0
+ * - Omit bracket with context/symbol and code, if all are empty
+ * - Omit colon with causing errors, if no causing errors exist
+ */
+ QString toString() const;
+
+ private:
+ QString insertArgs(const QString &rMessage) const;
+ QString cleanMessage(const QString &rMessage);
+
+ private:
+ int mCode;
+ QString mContext;
+ QString mMessage;
+ QString mSymbol;
+ QList<QVariant> mArgs;
+ QList<LogError> mCausingErrors;
+
+#ifndef QT_NO_DATASTREAM
+ // Needs to be friend to stream objects
+ friend QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError);
+ friend QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError);
+#endif // QT_NO_DATASTREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+ /*!
+ * \relates LogError
+ *
+ * Writes the given error \a rLogError to the given stream \a rStream,
+ * and returns a reference to the stream.
+ */
+ QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError);
+
+ /*!
+ * \relates LogError
+ *
+ * Reads an error from the given stream \a rStream into the given
+ * error \a rLogError, and returns a reference to the stream.
+ */
+ QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError);
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LogError
+ *
+ * Writes all object member variables to the given debug stream \a debug and
+ * returns the stream.
+ *
+ * <tt>
+ * %LogError(code:7 context:"Log4Qt::FileAppender"
+ * message:"Unable to open file '%1' for appender '%2'"
+ * symbol:"APPENDER_OPENING_FILE_ERROR"
+ * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") )
+ * translatedMessage: "Unable to open file '%1' for appender '%2'" )
+ * </tt>
+ *
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const LogError &rLogError);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline int LogError::code() const
+ { return mCode; }
+
+ inline QString LogError::context() const
+ { return mContext; }
+
+ inline QString LogError::message() const
+ { return mMessage; }
+
+ inline QString LogError::symbol() const
+ { return mSymbol; }
+
+ inline void LogError::setCode(int code)
+ { mCode = code; }
+
+ inline void LogError::setContext(const QString &rContext)
+ { mContext = rContext; }
+
+ inline void LogError::setMessage(const QString &rMessage)
+ { mMessage = cleanMessage(rMessage); }
+
+ inline void LogError::setSymbol(const QString &rSymbol)
+ { mSymbol = rSymbol; }
+
+ inline LogError &LogError::addArg(const QVariant &rArg)
+ { mArgs << rArg; return *this; }
+
+ inline LogError &LogError::addArg(int arg)
+ { mArgs << QVariant(arg); return *this; }
+
+ inline LogError &LogError::addArg(const QString &rArg)
+ { mArgs << QVariant(rArg); return *this; }
+
+ inline LogError &LogError::addCausingError(const LogError &rLogError)
+ { mCausingErrors << rLogError; return *this; }
+
+ inline QList<QVariant> LogError::args() const
+ { return mArgs; }
+
+ inline void LogError::clearArgs()
+ { mArgs.clear(); }
+
+ inline void LogError::clearCausingErrors()
+ { mCausingErrors.clear(); }
+
+ inline QList<LogError> LogError::causingErrors() const
+ { return mCausingErrors; }
+
+ inline bool LogError::isEmpty() const
+ { return mCode || !mMessage.isEmpty(); }
+
+ inline QString LogError::messageWithArgs() const
+ { return insertArgs(message()); }
+
+ inline QString LogError::translatedMessageWithArgs() const
+ { return insertArgs(translatedMessage()); }
+
+ inline LogError &LogError::operator<<(const QVariant &rArg)
+ { return addArg(rArg); }
+
+ inline LogError &LogError::operator<<(int arg)
+ { return addArg(arg); }
+
+ inline LogError &LogError::operator<<(const QString &rArg)
+ { return addArg(rArg); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_METATYPE(Log4Qt::LogError)
+Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_ERROR_H
diff --git a/ext/Log4Qt/src/helpers/logobject.cpp b/ext/Log4Qt/src/helpers/logobject.cpp
new file mode 100755
index 0000000..61331aa
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobject.cpp
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobject.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/logobject.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LogObject
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject)
+ {
+ return rLogObject.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logobject.h b/ext/Log4Qt/src/helpers/logobject.h
new file mode 100755
index 0000000..ab8d964
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobject.h
@@ -0,0 +1,219 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobject.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_increment and q_atomic_decrement
+ * with QAtomicInt.
+ * Feb 2009, Martin Heinrich
+ * - Fixed a problem where the pParent parameter of the constructor
+ * was not passed on to the QObject constructor
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGOBJECT_H
+#define LOG4QT_LOGOBJECT_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include "classlogger.h"
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# include <QtCore/QAtomicInt>
+# ifndef Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+# warning "QAtomicInt reference counting is not native. The class Log4Qt::LogObject is not thread-safe."
+# endif
+#endif
+
+
+namespace Log4Qt
+{
+
+ class Logger;
+
+ /*!
+ * \brief The class LogObject is the common base class for many classes
+ * in the package.
+ *
+ * The class inherits QObject to allow its subclass to be accessed using
+ * the Qt property system.
+ *
+ * LogObject objects provide a reference counter. A reference to the
+ * object is established by calling retain() and freed by calling
+ * release(). The object will delete itself when the reference counter
+ * is decremented to 0.
+ *
+ * A class specific logger can be accessed over logger().
+ *
+ * The class also implements generic streaming to QDebug. Streaming an
+ * object to QDebug will invoke debug() to create class specific output.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa \ref Ownership "Object ownership",
+ * LOG4QT_DECLARE_QCLASS_LOGGER
+ */
+ class LOG4QT_EXPORT LogObject : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ /*!
+ * Creates a LogObject which is a child of \a pObject.
+ */
+ LogObject(QObject *pObject = 0);
+
+ /*!
+ * Destroys the LogObject.
+ */
+ virtual ~LogObject();
+
+ private:
+ LogObject(const LogObject &rOther); // Not implemented
+ LogObject &operator=(const LogObject &rOther); // Not implemented
+
+ public:
+ /*!
+ * Returns the value of the reference counter.
+ */
+ int referenceCount() const;
+
+ /*!
+ * Decrements the reference count of the object. If the reference count
+ * count reaches zero and the object does not have a parent the object
+ * is deleted.
+ */
+ void release();
+
+ /*!
+ * Increments the reference count of the object.
+ */
+ void retain();
+
+ protected:
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * The member function is used by
+ * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to
+ * generate class specific output.
+ *
+ * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const = 0;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject);
+ #endif // QT_NO_DEBUG_STREAM
+
+ /*!
+ * Returns a pointer to a Logger named after of the object.
+ *
+ * \sa Logger::logger(const char *pName)
+ */
+ Logger* logger() const;
+
+ private:
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ volatile int mReferenceCount;
+#else
+ mutable QAtomicInt mReferenceCount;
+#endif
+ mutable ClassLogger mLog4QtClassLogger;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LogObject
+ *
+ * Writes all object member variables to the given debug stream \a debug
+ * and returns the stream.
+ *
+ * To handle sub-classing the function uses the virtual member function
+ * debug(). This allows each class to generate its own output.
+ *
+ * \sa QDebug, debug()
+ */
+ QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject);
+ #endif
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline LogObject::LogObject(QObject *pParent) :
+ QObject(pParent),
+ mReferenceCount()
+ {}
+
+ inline LogObject::~LogObject()
+ {}
+
+ inline int LogObject::referenceCount() const
+ {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ return mReferenceCount;
+#else
+ return mReferenceCount.loadAcquire();
+#endif
+ }
+
+ inline void LogObject::release()
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ { if ((q_atomic_decrement(&mReferenceCount) == 0) && !parent())
+ delete(this); }
+#else
+ { if (!mReferenceCount.deref())
+ delete(this); }
+#endif
+
+ inline void LogObject::retain()
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ { q_atomic_increment(&mReferenceCount); }
+#else
+ { mReferenceCount.ref(); }
+#endif
+
+ inline Logger *LogObject::logger() const
+ { return mLog4QtClassLogger.logger(this); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LogObject, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LOGOBJECT_H
diff --git a/ext/Log4Qt/src/helpers/logobjectptr.cpp b/ext/Log4Qt/src/helpers/logobjectptr.cpp
new file mode 100755
index 0000000..07d97c0
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobjectptr.cpp
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobjectptr.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/logobjectptr.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LogObjectPtr
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logobjectptr.h b/ext/Log4Qt/src/helpers/logobjectptr.h
new file mode 100755
index 0000000..cd74078
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobjectptr.h
@@ -0,0 +1,187 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobjectptr.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGOBJECTPTR_H
+#define LOG4QT_LOGOBJECTPTR_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "logobject.h"
+
+namespace Log4Qt
+{
+ /*!
+ * \brief The class LogObjectPtr implements automatic reference counting
+ * for LogObject objects.
+ */
+ template <class T>
+ class LogObjectPtr
+ {
+ public:
+ /*!
+ * Constructs a 0 LogObject pointer.
+ */
+ LogObjectPtr();
+
+ /*!
+ * Constructs a LogObject pointer that points to the same object then
+ * \a rOther. The reference counter of the object is incremented by
+ * one.
+ */
+ LogObjectPtr(const LogObjectPtr<T> &rOther);
+
+ /*!
+ * Constructs a LogObject pointer that points to the object
+ * \a LogObject. The reference counter of the object is incremented by
+ * one.
+ */
+ LogObjectPtr(T *pLogObject);
+
+ /*!
+ * Assignment operator. Sets the LogObject pointer to point to the
+ * same object that \a rOther points to. The reference counter of the
+ * object the LogObjectPtr pointed to before the assignment is
+ * decremented by one. The reference counter of the object \a rOther
+ * is pointing to is incremented by one.
+ */
+ LogObjectPtr<T> &operator=(const LogObjectPtr<T> &rOther);
+
+ /*!
+ * Destructs the object. The reference counter of the object the
+ * LogObjectPtr points to is decremented by one.
+ */
+ ~LogObjectPtr();
+
+ /*!
+ * Assignment operator. Sets the LogObject pointer to point to the
+ * object \a pLogObject. The reference counter of the object the
+ * LogObjectPtr pointed to before the assignment is decremented by
+ * one. The reference counter of the object \a pLogObject is pointing
+ * to is incremented by one.
+ */
+ LogObjectPtr<T> &operator=(T *pLogObject);
+
+ /*!
+ * Arrow operator. Returns the LogObject the object points to.
+ */
+ T *operator->() const;
+
+ /*!
+ * Dereference operator. Returns a pointer to the LogObject the
+ * object points to.
+ */
+ T &operator*() const;
+
+ /*!
+ * Cast operator. Cast the object to the LogObject the object points
+ * to.
+ */
+ operator T*() const;
+
+ private:
+ void retain() const;
+ void release() const;
+
+ private:
+ T *mpLogObject;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr() :
+ mpLogObject(0)
+ {}
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr(const LogObjectPtr<T> &rOther) :
+ mpLogObject(rOther.mpLogObject)
+ { retain(); }
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr(T *pLogObject) :
+ mpLogObject(pLogObject)
+ { retain(); }
+
+ template <class T>
+ inline LogObjectPtr<T> &LogObjectPtr<T>::operator=(const LogObjectPtr<T> &rOther)
+ { rOther.retain();
+ release();
+ mpLogObject = rOther.mpLogObject;
+ return *this; }
+
+ template <class T>
+ inline LogObjectPtr<T>::~LogObjectPtr()
+ { release(); }
+
+ template <class T>
+ inline LogObjectPtr<T> &LogObjectPtr<T>::operator=(T *pLogObject)
+ { if (pLogObject)
+ reinterpret_cast<LogObject *>(pLogObject)->retain();
+ release();
+ mpLogObject = pLogObject;
+ return *this; }
+
+ template <class T>
+ inline T *LogObjectPtr<T>::operator->() const
+ { return mpLogObject; }
+
+ template <class T>
+ inline T &LogObjectPtr<T>::operator*() const
+ { return *mpLogObject; }
+
+ template <class T>
+ inline LogObjectPtr<T>::operator T*() const
+ { return mpLogObject; }
+
+ template <class T>
+ inline void LogObjectPtr<T>::retain() const
+ { if (mpLogObject)
+ reinterpret_cast<LogObject *>(mpLogObject)->retain(); }
+
+ template <class T>
+ inline void LogObjectPtr<T>::release() const
+ {
+ if (mpLogObject)
+ reinterpret_cast<LogObject *>(mpLogObject)->release();
+ }
+
+} // namespace Log4Qt
+
+
+//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<T>, Q_MOVABLE_TYPE); // Declare within T
+
+
+#endif // LOG4QT_LOGOBJECTPTR_H
diff --git a/ext/Log4Qt/src/helpers/optionconverter.cpp b/ext/Log4Qt/src/helpers/optionconverter.cpp
new file mode 100755
index 0000000..e148a2d
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/optionconverter.cpp
@@ -0,0 +1,301 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: optionconverter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed a problem were OptionConverter::toBoolean would not
+ * return the default value, if the conversion fails.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/optionconverter.h"
+
+#include <QtCore/QDebug>
+#include "helpers/logerror.h"
+#include "helpers/properties.h"
+#include "logger.h"
+#include "consoleappender.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::OptionConverter)
+
+
+
+ /**************************************************************************
+ * Class implementation: OptionConverter
+ **************************************************************************/
+
+
+ QString OptionConverter::findAndSubst(const Properties &rProperties,
+ const QString &rKey)
+ {
+ QString value = rProperties.property(rKey);
+ if (value.isNull())
+ return value;
+
+ const QString begin_subst = QLatin1String("${");
+ const QString end_subst = QLatin1String("}");
+ const int begin_length = begin_subst.length();
+ const int end_length = end_subst.length();
+
+ // Don't return a null string, the null string indicates that the
+ // property key does not exist.
+ QString result = QLatin1String("");
+
+ int i = 0;
+ int begin;
+ int end;
+ while (i < value.length())
+ {
+ begin = value.indexOf(begin_subst, i);
+ if (begin == -1)
+ {
+ result += value.mid(i);
+ i = value.length();
+ }
+ else
+ {
+ result += value.mid(i, begin - i);
+ end = value.indexOf(end_subst, i + begin_length);
+ if (end == -1)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2."),
+ CONFIGURATOR_INVALID_SUBSTITUTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << begin << value;
+ logger()->error(e);
+ return result;
+ }
+ else
+ {
+ result += findAndSubst(rProperties, value.mid(begin + begin_length, end - begin - end_length - 1));
+ i = end + end_length;
+ }
+ }
+ }
+ return result;
+ }
+
+
+ QString OptionConverter::classNameJavaToCpp(const QString &rClassName)
+ {
+ const QLatin1String java_class_delimiter(".");
+ const QLatin1String cpp_class_delimiter("::");
+
+ QString result = rClassName;
+ return result.replace(java_class_delimiter, cpp_class_delimiter);
+ }
+
+
+ bool OptionConverter::toBoolean(const QString &rOption,
+ bool *p_ok)
+ {
+ const QLatin1String str_true("true");
+ const QLatin1String str_enabled("enabled");
+ const QLatin1String str_one("1");
+ const QLatin1String str_false("false");
+ const QLatin1String str_disabled("disabled");
+ const QLatin1String str_zero("0");
+
+ if (p_ok)
+ *p_ok = true;
+ QString s = rOption.trimmed().toLower();
+ if (s == str_true || s == str_enabled || s == str_one)
+ return true;
+ if (s == str_false || s == str_disabled || s == str_zero)
+ return false;
+
+ if (p_ok)
+ *p_ok = false;
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a boolean"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return false;
+ }
+
+
+ bool OptionConverter::toBoolean(const QString &rOption,
+ bool default_value)
+ {
+ bool ok;
+ bool result = toBoolean(rOption, &ok);
+ if (ok)
+ return result;
+ else
+ return default_value;
+ }
+
+ qint64 OptionConverter::toFileSize(const QString &rOption,
+ bool *p_ok)
+ {
+ // - Search for unit
+ // - Convert characters befor unit to int
+ // - Error, if
+ // - the conversion failed
+ // - the value < 0
+ // - there is text after the unit characters
+
+ if (p_ok)
+ *p_ok = false;
+ QString s = rOption.trimmed().toLower();
+ qint64 f = 1;
+ int i;
+ i = s.indexOf(QLatin1String("kb"));
+ if (i >= 0)
+ f = 1024;
+ else
+ {
+ i = s.indexOf(QLatin1String("mb"));
+ if (i >= 0)
+ f = 1024 * 1024;
+ else
+ {
+ i = s.indexOf(QLatin1String("gb"));
+ if (i >= 0)
+ f = 1024 * 1024 * 1024;
+ }
+ }
+ if (i < 0)
+ i = s.length();
+ bool ok;
+ qint64 value = s.left(i).toLongLong(&ok);
+ if (!ok || value < 0 || s.length() > i + 2)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a file size"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return 0;
+ }
+ if (p_ok)
+ *p_ok = true;
+ return value * f;
+ }
+
+
+ int OptionConverter::toInt(const QString &rOption,
+ bool *p_ok)
+ {
+ int value = rOption.trimmed().toInt(p_ok);
+ if (*p_ok)
+ return value;
+
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for an integer"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return 0;
+ }
+
+
+ Level OptionConverter::toLevel(const QString &rOption,
+ bool *p_ok)
+ {
+ bool ok;
+ Level level = Level::fromString(rOption.toUpper().trimmed(), &ok);
+ if (p_ok)
+ *p_ok = ok;
+ if (ok)
+ return level;
+
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a level"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return level;
+ }
+
+
+ Level OptionConverter::toLevel(const QString &rOption,
+ const Level &rDefaultValue)
+ {
+ bool ok;
+ Level result = toLevel(rOption, &ok);
+ if (ok)
+ return result;
+ else
+ return rDefaultValue;
+ }
+
+
+ int OptionConverter::toTarget(const QString &rOption,
+ bool *p_ok)
+ {
+ const QLatin1String java_stdout("system.out");
+ const QLatin1String cpp_stdout("stdout_target");
+ const QLatin1String java_stderr("system.err");
+ const QLatin1String cpp_stderr("stderr_target");
+
+ if (p_ok)
+ *p_ok = true;
+ QString s = rOption.trimmed().toLower();
+ if (s == java_stdout || s == cpp_stdout)
+ return ConsoleAppender::STDOUT_TARGET;
+ if (s == java_stderr || s == cpp_stderr)
+ return ConsoleAppender::STDERR_TARGET;
+
+ if (p_ok)
+ *p_ok = false;
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a target"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return ConsoleAppender::STDOUT_TARGET;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/optionconverter.h b/ext/Log4Qt/src/helpers/optionconverter.h
new file mode 100755
index 0000000..ebdd567
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/optionconverter.h
@@ -0,0 +1,141 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: optionconverter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_OPTIONCONVERTER_H
+#define LOG4QT_OPTIONCONVERTER_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include "level.h"
+
+namespace Log4Qt
+{
+ class Properties;
+
+ /*!
+ * \brief The class OptionConverter provides functions to convert strings
+ * to property values.
+ */
+ class LOG4QT_EXPORT OptionConverter
+ {
+ private:
+ OptionConverter();
+ OptionConverter(const OptionConverter &rOther); // Not implemented
+ // virtual ~OptionConverter(); // Use compiler default
+ OptionConverter &operator=(const OptionConverter &rOther); // Not implemented
+
+ public:
+ static QString findAndSubst(const Properties &rProperties,
+ const QString &rKey);
+
+ /*!
+ * Returns the JAVA class name \a rClassName as C++ class name by
+ * replacing all . characters with ::.
+ */
+ static QString classNameJavaToCpp(const QString &rClassName);
+
+ /*!
+ * Converts the option \a rOption to a boolean value. Valid strings
+ * for true are "true", "enabled" and "1". Valid strings
+ * for false are "false", "disabled" and "0". If the conversion is
+ * successful, the target is returned and \a p_ok is set to true.
+ * Otherwise an error is written to the log, \a p_ok is set to false
+ * and false is returned.
+ */
+ static bool toBoolean(const QString &rOption,
+ bool *p_ok = 0);
+
+ static bool toBoolean(const QString &rOption,
+ bool default_value);
+
+ /*!
+ * Converts the option string \a rOption to a file size. The string can
+ * be a positive integer followed by an optional unit suffix "KB", "MB"
+ * or "GB". If a unit suffix is specified the the integer is
+ * interpreted as kilobytes, megabytes or gigabytes. If the conversion
+ * is successful, the size is returned and \a p_ok is set to true.
+ * Otherwise an error is written to the log, \a p_ok is set to false
+ * and 0 is returned.
+ */
+ static qint64 toFileSize(const QString &rOption,
+ bool *p_ok = 0);
+
+ /*!
+ * Converts the option \a rOption to a integer value using
+ * QString::toInt(). If the conversion is successful, the integer is
+ * returned and \a p_ok is set to true. Otherwise an error is written
+ * to the log, \a p_ok is set to false and 0 is returned.
+ */
+ static int toInt(const QString &rOption,
+ bool *p_ok = 0);
+
+ /*!
+ * Converts the option \a rOption to a level value using
+ * Level::fromString(). If the conversion is successful, the level
+ * is returned and \a p_ok is set to true. Otherwise an error is
+ * written to the log, \a p_ok is set to false and a level with
+ * the value Level::NULL_INT is returned.
+ *
+ * \sa Level::fromString()
+ */
+ static Level toLevel(const QString &rOption,
+ bool *p_ok = 0);
+
+ static Level toLevel(const QString &rOption,
+ const Level &rDefaultValue);
+
+ /*!
+ * Converts the option \a rOption to a ConsoleAppender::Target value.
+ * Valid strings for \a rOption are "System.out", "STDOUT_TARGET",
+ * "System.err" and "STDERR_TARGET". If the conversion is successful,
+ * the target is returned and \a p_ok is set to true. Otherwise an
+ * error is written to the log, \a p_ok is set to false and
+ * ConsoleAppender::STDOUT_TARGET is returned.
+ */
+ static int toTarget(const QString &rOption,
+ bool *p_ok = 0);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::OptionConverter, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_OPTIONCONVERTER_H
diff --git a/ext/Log4Qt/src/helpers/patternformatter.cpp b/ext/Log4Qt/src/helpers/patternformatter.cpp
new file mode 100644
index 0000000..cf23198
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/patternformatter.cpp
@@ -0,0 +1,902 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternformatter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in LiteralPatternConverter::convert.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "helpers/patternformatter.h"
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <limits.h>
+#include "helpers/datetime.h"
+#include "helpers/logerror.h"
+#include "layout.h"
+#include "logger.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+ /*!
+ * \brief The class FormattingInfo stores the formatting modifier for a
+ * pattern converter.
+ *
+ * \sa PatternConverter
+ */
+ class FormattingInfo
+ {
+ public:
+ FormattingInfo()
+ { clear(); }
+ // FormattingInfo(const FormattingInfo &rOther); // Use compiler default
+ // virtual ~FormattingInfo(); // Use compiler default
+ // FormattingInfo &operator=(const FormattingInfo &rOther); // Use compiler default
+
+ void clear();
+ static QString intToString(int i);
+
+ public:
+ int mMinLength;
+ int mMaxLength;
+ bool mLeftAligned;
+ };
+
+
+ /*!
+ * \brief The class PatternConverter is the abstract base class for all
+ * pattern converters.
+ *
+ * PatternConverter handles the minimum and maximum modifier for a
+ * conversion character. The actual conversion is by calling the
+ * convert() member function of the derived class.
+ *
+ * \sa PatternLayout::format()
+ */
+ class PatternConverter
+ {
+ public:
+ PatternConverter(const FormattingInfo &rFormattingInfo = FormattingInfo()) :
+ mFormattingInfo(rFormattingInfo)
+ {};
+ virtual ~PatternConverter()
+ {};
+ private:
+ PatternConverter(const PatternConverter &rOther); // Not implemented
+ PatternConverter &operator=(const PatternConverter &rOther); // Not implemented
+
+ public:
+ void format(QString &rFormat, const LoggingEvent &rLoggingEvent) const;
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const = 0;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const = 0;
+ friend QDebug operator<<(QDebug, const PatternConverter &rPatternConverter);
+ #endif
+
+ protected:
+ FormattingInfo mFormattingInfo;
+ };
+
+
+ /*!
+ * \brief The class BasicPatternConverter converts several members of a
+ * LoggingEvent to a string.
+ *
+ * BasicPatternConverter is used by PatternLayout to convert members that
+ * do not reuquire additional formatting to a string as part of formatting
+ * the LoggingEvent. It handles the following conversion characters:
+ * 'm', 'p', 't', 'x'
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class BasicPatternConverter : public PatternConverter
+ {
+ public:
+ enum Type {
+ MESSAGE_CONVERTER,
+ NDC_CONVERTER,
+ LEVEL_CONVERTER,
+ THREAD_CONVERTER
+ };
+
+ public:
+ BasicPatternConverter(const FormattingInfo &rFormattingInfo,
+ Type type) :
+ PatternConverter(rFormattingInfo),
+ mType(type)
+ {};
+ // virtual ~BasicPatternConverter(); // Use compiler default
+ private:
+ BasicPatternConverter(const BasicPatternConverter &rOther); // Not implemented
+ BasicPatternConverter &operator=(const BasicPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ Type mType;
+ };
+
+
+ /*!
+ * \brief The class DatePatternConverter converts the time stamp of a
+ * LoggingEvent to a string.
+ *
+ * DatePatternConverter is used by PatternLayout to convert the time stamp
+ * of a LoggingEvent to a string as part of formatting the LoggingEvent.
+ * It handles the 'd' and 'r' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class DatePatternConverter : public PatternConverter
+ {
+ public:
+ DatePatternConverter(const FormattingInfo &rFormattingInfo,
+ const QString &rFormat) :
+ PatternConverter(rFormattingInfo),
+ mFormat(rFormat)
+ {};
+ // virtual ~DatePatternConverter(); // Use compiler default
+ private:
+ DatePatternConverter(const DatePatternConverter &rOther); // Not implemented
+ DatePatternConverter &operator=(const DatePatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mFormat;
+ };
+
+
+ /*!
+ * \brief The class LiteralPatternConverter provides string literals.
+ *
+ * LiteralPatternConverter is used by PatternLayout to embed string
+ * literals as part of formatting the LoggingEvent. It handles string
+ * literals and the 'n' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class LiteralPatternConverter : public PatternConverter
+ {
+ public:
+ LiteralPatternConverter(const QString &rLiteral) :
+ PatternConverter(),
+ mLiteral(rLiteral)
+ {};
+ // virtual ~LiteralPatternConverter(); // Use compiler default
+ private:
+ LiteralPatternConverter(const LiteralPatternConverter &rOther); // Not implemented
+ LiteralPatternConverter &operator=(const LiteralPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mLiteral;
+ };
+
+
+ /*!
+ * \brief The class LoggerPatternConverter converts the Logger name of a
+ * LoggingEvent to a string.
+ *
+ * LoggerPatternConverter is used by PatternLayout to convert the Logger
+ * name of a LoggingEvent to a string as part of formatting the
+ * LoggingEvent. It handles the 'c' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class LoggerPatternConverter : public PatternConverter
+ {
+ public:
+ LoggerPatternConverter(const FormattingInfo &rFormattingInfo,
+ int precision) :
+ PatternConverter(rFormattingInfo),
+ mPrecision(precision)
+ {};
+ // virtual ~LoggerPatternConverter(); // Use compiler default
+ private:
+ LoggerPatternConverter(const LoggerPatternConverter &rOther); // Not implemented
+ LoggerPatternConverter &operator=(const LoggerPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ int mPrecision;
+ };
+
+
+
+ /*!
+ * \brief The class MDCPatternConverter converts the MDC data of a
+ * LoggingEvent to a string.
+ *
+ * MDCPatternConverter is used by PatternLayout to convert the MDC data of
+ * a LoggingEvent to a string as part of formatting the LoggingEvent. It
+ * handles the 'X' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class MDCPatternConverter : public PatternConverter
+ {
+ public:
+ MDCPatternConverter(const FormattingInfo &rFormattingInfo,
+ const QString &rKey) :
+ PatternConverter(rFormattingInfo),
+ mKey(rKey)
+ {};
+ // virtual ~MDCPatternConverter(); // Use compiler default
+ private:
+ MDCPatternConverter(const MDCPatternConverter &rOther); // Not implemented
+ MDCPatternConverter &operator=(const MDCPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mKey;
+ };
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug, const FormattingInfo &rFormattingInfo);
+ #endif
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug, const PatternConverter &rPatternConverter);
+ #endif
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PatternFormatter)
+
+
+
+ /**************************************************************************
+ * Class implementation: PatternFormatter
+ **************************************************************************/
+
+
+ PatternFormatter::PatternFormatter(const QString &rPattern) :
+ mIgnoreCharacters(QLatin1String("CFlLM")),
+ mConversionCharacters(QLatin1String("cdmprtxX")),
+ mOptionCharacters(QLatin1String("cd")),
+ mPattern(rPattern),
+ mPatternConverters()
+ {
+ parse();
+ }
+
+
+ PatternFormatter::~PatternFormatter()
+ {
+ PatternConverter *p_converter;
+ Q_FOREACH(p_converter, mPatternConverters)
+ delete p_converter;
+ }
+
+
+ QString PatternFormatter::format(const LoggingEvent &rLoggingEvent) const
+ {
+ QString result;
+ PatternConverter *p_converter;
+ Q_FOREACH(p_converter, mPatternConverters)
+ p_converter->format(result, rLoggingEvent);
+ return result;
+ }
+
+
+ bool PatternFormatter::addDigit(const QChar &rDigit,
+ int &rValue)
+ {
+ if (!rDigit.isDigit())
+ return false;
+
+ int digit_value = rDigit.digitValue();
+ if (rValue > (INT_MAX - digit_value) / 10)
+ rValue = INT_MAX;
+ else
+ rValue = rValue * 10 + digit_value;
+ return true;
+ }
+
+
+ void PatternFormatter::createConverter(const QChar &rChar,
+ const FormattingInfo &rFormattingInfo,
+ const QString &rOption)
+ {
+ Q_ASSERT_X(mConversionCharacters.indexOf(rChar) >= 0, "PatternFormatter::createConverter", "Unknown conversion character" );
+
+ LogError e("Creating Converter for character '%1' min %2, max %3, left %4 and option '%5'");
+ e << QString(rChar)
+ << FormattingInfo::intToString(rFormattingInfo.mMinLength)
+ << FormattingInfo::intToString(rFormattingInfo.mMaxLength)
+ << rFormattingInfo.mLeftAligned
+ << rOption;
+ logger()->trace(e);
+
+ switch (rChar.toLatin1())
+ {
+ case 'c':
+ mPatternConverters << new LoggerPatternConverter(rFormattingInfo,
+ parseIntegerOption(rOption));
+ break;
+ case 'd':
+ {
+ QString option = rOption;
+ if (rOption.isEmpty()) {
+ option = QLatin1String("ISO8601");
+ } else if (rOption == "locale:long") {
+ option = QLocale().dateTimeFormat(QLocale::LongFormat);
+ } else if (rOption == "locale:short") {
+ option = QLocale().dateTimeFormat(QLocale::ShortFormat);
+ } else if (rOption == "locale:narrow") {
+ option = QLocale().dateTimeFormat(QLocale::NarrowFormat);
+ } else if (rOption == "locale") {
+ option = QLocale().dateTimeFormat(QLocale::ShortFormat);
+ }
+ mPatternConverters << new DatePatternConverter(rFormattingInfo,
+ option);
+ break;
+ }
+ case 'm':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::MESSAGE_CONVERTER);
+ break;
+ case 'p':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::LEVEL_CONVERTER);
+ break;
+ case 'r':
+ mPatternConverters << new DatePatternConverter(rFormattingInfo,
+ QLatin1String("RELATIVE"));
+ break;
+ case 't':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::THREAD_CONVERTER);
+ break;
+ case 'x':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::NDC_CONVERTER);
+ break;
+ case 'X':
+ mPatternConverters << new MDCPatternConverter(rFormattingInfo,
+ rOption);
+ break;
+ default:
+ Q_ASSERT_X(false, "PatternFormatter::createConverter", "Unknown pattern character");
+ }
+ }
+
+
+ void PatternFormatter::createLiteralConverter(const QString &rLiteral)
+ {
+ logger()->trace("Creating literal LiteralConverter with Literal '%1'",
+ rLiteral);
+ mPatternConverters << new LiteralPatternConverter(rLiteral);
+ }
+
+
+ void PatternFormatter::parse()
+ {
+ enum State {
+ LITERAL_STATE,
+ ESCAPE_STATE,
+ MIN_STATE,
+ DOT_STATE,
+ MAX_STATE,
+ CHARACTER_STATE,
+ POSSIBLEOPTION_STATE,
+ OPTION_STATE
+ };
+
+ int i = 0;
+ QChar c;
+ char ch;
+ State state = LITERAL_STATE;
+ FormattingInfo formatting_info;
+ QString literal;
+ int converter_start = 0;
+ int option_start = 0;
+ while (i < mPattern.length())
+ {
+ // i points to the current character
+ // c contains the current character
+ // ch contains the Latin1 equivalent of the current character
+ // i is incremented at the end of the loop to consume the character
+ // continue is used to change state without consuming the character
+
+ c = mPattern.at(i);
+ ch = c.toLatin1();
+ switch (state)
+ {
+ case LITERAL_STATE:
+ if (ch == '%')
+ {
+ formatting_info.clear();
+ converter_start = i;
+ state = ESCAPE_STATE;
+ } else
+ literal += c;
+ break;
+ case ESCAPE_STATE:
+ if (ch == '%')
+ {
+ literal += c;
+ state = LITERAL_STATE;
+ }
+ else if (ch == 'n')
+ {
+ literal += Layout::endOfLine();
+ state = LITERAL_STATE;
+ }
+ else
+ {
+ if (!literal.isEmpty())
+ {
+ createLiteralConverter(literal);
+ literal.clear();
+ }
+ if (ch == '-')
+ formatting_info.mLeftAligned = true;
+ else if (c.isDigit())
+ {
+ formatting_info.mMinLength = c.digitValue();
+ state = MIN_STATE;
+ }
+ else if (ch == '.')
+ state = DOT_STATE;
+ else
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ }
+ break;
+ case MIN_STATE:
+ if (!addDigit(c, formatting_info.mMinLength))
+ {
+ if (ch == '.')
+ state = DOT_STATE;
+ else
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ }
+ break;
+ case DOT_STATE:
+ if (c.isDigit())
+ {
+ formatting_info.mMaxLength = c.digitValue();
+ state = MAX_STATE;
+ }
+ else
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."),
+ LAYOUT_EXPECTED_DIGIT_ERROR,
+ "Log4Qt::PatternFormatter");
+ e << QString(c);
+ logger()->error(e);
+ }
+ break;
+ case MAX_STATE:
+ if (!addDigit(c, formatting_info.mMaxLength))
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ break;
+ case CHARACTER_STATE:
+ if (mIgnoreCharacters.indexOf(c) >= 0)
+ state = LITERAL_STATE;
+ else if (mOptionCharacters.indexOf(c) >= 0)
+ state = POSSIBLEOPTION_STATE;
+ else if (mConversionCharacters.indexOf(c) >= 0)
+ {
+ createConverter(c, formatting_info);
+ state = LITERAL_STATE;
+ }
+ else
+ {
+ logger()->warn("Invalid conversion character '%1' at %2 in pattern '%3'",
+ c, i, mPattern);
+ createLiteralConverter(mPattern.mid(converter_start, i - converter_start + 1));
+ state = LITERAL_STATE;
+ }
+ break;
+ case POSSIBLEOPTION_STATE:
+ if (ch == '{')
+ {
+ option_start = i;
+ state = OPTION_STATE;
+ }
+ else
+ {
+ createConverter(mPattern.at(i - 1),
+ formatting_info);
+ state = LITERAL_STATE;
+ continue;
+ }
+ break;
+ case OPTION_STATE:
+ if (ch == '}')
+ {
+ createConverter(mPattern.at(option_start - 1),
+ formatting_info,
+ mPattern.mid(option_start + 1, i - option_start - 1));
+ state = LITERAL_STATE;
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, "PatternFormatter::parse()", "Unknown parsing state constant");
+ state = LITERAL_STATE;
+ }
+ i++;
+ }
+
+ if (state != LITERAL_STATE)
+ {
+ logger()->warn("Unexptected end of pattern '%1'", mPattern);
+ if (state == ESCAPE_STATE)
+ literal += c;
+ else
+ literal += mPattern.mid(converter_start);
+ }
+
+ if (!literal.isEmpty())
+ createLiteralConverter(literal);
+ }
+
+
+ int PatternFormatter::parseIntegerOption(const QString &rOption)
+ {
+ if (rOption.isEmpty())
+ return 0;
+
+ bool ok;
+ int result = rOption.toInt(&ok);
+ if (!ok)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option '%1' cannot be converted into an integer"),
+ LAYOUT_OPTION_IS_NOT_INTEGER_ERROR,
+ "Log4Qt::PatterFormatter");
+ e << rOption;
+ logger()->error(e);
+ }
+ if (result < 0)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option %1 isn't a positive integer"),
+ LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR,
+ "Log4Qt::PatterFormatter");
+ e << result;
+ logger()->error(e);
+ result = 0;
+ }
+ return result;
+ }
+
+
+ /**************************************************************************
+ * Class implementation: FormattingInfo
+ **************************************************************************/
+
+
+ void FormattingInfo::clear()
+ {
+ mMinLength = 0;
+ mMaxLength = INT_MAX;
+ mLeftAligned = false;
+ }
+
+
+ QString FormattingInfo::intToString(int i)
+ {
+ if (i == INT_MAX)
+ return QLatin1String("INT_MAX");
+ else
+ return QString::number(i);
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: PatternConverter
+ **************************************************************************/
+
+
+ void PatternConverter::format(QString &rFormat, const LoggingEvent &rLoggingEvent) const
+ {
+ const QLatin1Char space(' ');
+ QString s = convert(rLoggingEvent);
+
+ if (s.length() > mFormattingInfo.mMaxLength)
+ rFormat += s.left(mFormattingInfo.mMaxLength);
+ else if (mFormattingInfo.mLeftAligned)
+ rFormat += s.leftJustified(mFormattingInfo.mMinLength, space, false);
+ else
+ rFormat += s.rightJustified(mFormattingInfo.mMinLength, space, false);
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: BasicPatternConverter
+ **************************************************************************/
+
+
+ QString BasicPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ switch (mType)
+ {
+ case MESSAGE_CONVERTER:
+ return rLoggingEvent.message();
+ break;
+ case NDC_CONVERTER:
+ return rLoggingEvent.ndc();
+ break;
+ case LEVEL_CONVERTER:
+ return rLoggingEvent.level().toString();
+ break;
+ case THREAD_CONVERTER:
+ return rLoggingEvent.threadName();
+ break;
+ default:
+ Q_ASSERT_X(false, "BasicPatternConverter::convert()", "Unkown type constant");
+ return QString();
+ }
+ }
+
+
+ QDebug BasicPatternConverter::debug(QDebug &rDebug) const
+ {
+ QString type;
+ switch (mType)
+ {
+ case MESSAGE_CONVERTER:
+ type = QLatin1String("MESSAGE_CONVERTER");
+ break;
+ case NDC_CONVERTER:
+ type = QLatin1String("NDC_CONVERTER");
+ break;
+ case LEVEL_CONVERTER:
+ type = QLatin1String("LEVEL_CONVERTER");
+ break;
+ case THREAD_CONVERTER:
+ type = QLatin1String("THREAD_CONVERTER");
+ break;
+ default:
+ Q_ASSERT_X(false, "BasicPatternConverter::debug()", "Unkown type constant");
+ }
+ rDebug.nospace() << "BasicPatternConverter("
+ << mFormattingInfo
+ << "type:" << type
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: DatePatternConverter
+ **************************************************************************/
+
+
+ QString DatePatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ return DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()).toString(mFormat);
+ }
+
+
+ QDebug DatePatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "DatePatternConverter("
+ << mFormattingInfo
+ << "format:" << mFormat
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: LiteralPatternConverter
+ **************************************************************************/
+
+
+ QString LiteralPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ Q_UNUSED(rLoggingEvent);
+ return mLiteral;
+ }
+
+
+ QDebug LiteralPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "LiteralPatternConverter("
+ << mFormattingInfo
+ << "literal:" << mLiteral
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: LoggerPatternConverter
+ **************************************************************************/
+
+
+ QString LoggerPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ if (!rLoggingEvent.logger())
+ return QString();
+ QString name = rLoggingEvent.logger()->name();
+ if (mPrecision <= 0 || (name.isEmpty()))
+ return name;
+
+ const QString separator(QLatin1String("::"));
+
+ int i = mPrecision;
+ int begin = name.length();
+ while ((i > 0) && (begin >= 0))
+ {
+ begin = name.lastIndexOf(separator, begin - name.length() - 1);
+ i--;
+ }
+ if (begin < 0)
+ begin = 0;
+ else
+ begin += 2;
+ return name.mid(begin);
+ }
+
+
+ QDebug LoggerPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "LoggerPatternConverter("
+ << mFormattingInfo
+ << "precision:" << mPrecision
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /******************************************************************************
+ * Class implementation: MDCPatternConverter
+ ******************************************************************************/
+
+
+ QString MDCPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ return rLoggingEvent.mdc().value(mKey);
+ }
+
+
+ QDebug MDCPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "MDCPatternConverter("
+ << mFormattingInfo
+ << "key:" << mKey
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const PatternFormatter &rPatternFormatter)
+ {
+ debug.nospace() << "PatternFormatter("
+ << "pattern:" << rPatternFormatter.mPattern << " "
+ << "converters:(";
+ int i;
+ for (i = 0; i < rPatternFormatter.mPatternConverters.size(); i++)
+ {
+ if (i > 0)
+ debug.nospace() << ", ";
+ debug.nospace() << *rPatternFormatter.mPatternConverters.at(i);
+ }
+ debug.nospace() << ") )";
+ return debug.space();
+ }
+ #endif
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const FormattingInfo &rFormattingInfo)
+ {
+ debug.nospace() << "FormattingInfo("
+ << "min:" << FormattingInfo::intToString(rFormattingInfo.mMinLength) << " "
+ << "max:" << FormattingInfo::intToString(rFormattingInfo.mMaxLength) << " "
+ << "left:" << rFormattingInfo.mLeftAligned
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const PatternConverter &rPatternConverter)
+ {
+ return rPatternConverter.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/patternformatter.h b/ext/Log4Qt/src/helpers/patternformatter.h
new file mode 100755
index 0000000..4bbe5fc
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/patternformatter.h
@@ -0,0 +1,195 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternformatter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PATTERNFORMATTER_H
+#define LOG4QT_PATTERNFORMATTER_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ class FormattingInfo;
+ class PatternConverter;
+ class LoggingEvent;
+
+ /*!
+ * \brief The class PatternFormatter formats a logging event based on a
+ * pattern string.
+ *
+ * The class PatternFormatter formats a LoggingEvent base on a pattern
+ * string. It is used by the patternLayout and TTCCLayout class to
+ * implement the formatting.
+ *
+ * On object construction the provided patterns tring is parsed. Based on
+ * the information found a chain of PatternConverter is created. Each
+ * PatternConverter handles a certain member of a LoggingEvent.
+ *
+ * \sa PatternLayout::format()
+ * \sa TTCCLayout::format()
+ */
+ class LOG4QT_EXPORT PatternFormatter
+ {
+ public:
+ /*!
+ * Creates a PatternFormatter using a the specified \a rPattern.
+ */
+ PatternFormatter(const QString &rPattern);
+
+ /*!
+ * Destroys the PatternFormatter and all PatternConverter.
+ */
+ virtual ~PatternFormatter();
+
+ private:
+ PatternFormatter(const PatternFormatter &rOther); // Not implemented
+ PatternFormatter &operator=(const PatternFormatter &rOther); // Not implemented
+
+ public:
+ /*!
+ * Formats the given \a rLoggingEvent using the chain of
+ * PatternConverter created during construction from the specified
+ * pattern.
+ */
+ QString format(const LoggingEvent &rLoggingEvent) const;
+
+ private:
+ /*!
+ * If the character \a rDigit is a digit the digit is added to the
+ * integer \a rValue and the function returns true. Otherwise the
+ * function returns false.
+ *
+ * The function adds the digit by multiplying the existing value
+ * with ten and adding the numerical value of the digit. If the
+ * maximum integer value would be exceeded by the operation
+ * \a rValue is set to INT_MAX.
+ */
+ bool addDigit(const QChar &rDigit,
+ int &rValue);
+
+ /*!
+ * Creates a PatternConverter based on the specified conversion
+ * character \a rChar, the formatting information
+ * \a rFormattingInfo and the option \a rOption.
+ *
+ * The PatternConverter converter is appended to the list of
+ * PatternConverters.
+ */
+ void createConverter(const QChar &rChar,
+ const FormattingInfo &rFormattingInfo,
+ const QString &rOption = QString());
+
+ /*!
+ * Creates a LiteralPatternConverter with the string literal
+ * \a rLiteral.
+ *
+ * The PatternConverter converter is appended to the list of
+ * PatternConverters.
+ */
+ void createLiteralConverter(const QString &rLiteral);
+
+ /*!
+ * Parses the pattern string specified on construction and creates
+ * PatternConverter according to it.
+ */
+ void parse();
+
+ /*!
+ * Parses an integer option from an option string. If the string is
+ * not a valid integer or the integer value is less then zero, zero
+ * is returned. Returns the end of line seperator for the operating
+ * system.
+ */
+ int parseIntegerOption(const QString &rOption);
+
+ private:
+ const QString mIgnoreCharacters;
+ const QString mConversionCharacters;
+ const QString mOptionCharacters;
+ QString mPattern;
+ QList<PatternConverter *> mPatternConverters;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug, const PatternFormatter &rPatternFormatter);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates PatternFormatter
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %PatternFormatter(pattern:"%r [%t] %p %c %x - %m%n"
+ * converters:(
+ * DatePatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) format: "RELATIVE" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " [" ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "THREAD_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "] " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "LEVEL_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) ,
+ * LoggerPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) precision: 0 ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "NDC_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " - " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "MESSAGE_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "" ) ) )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const PatternFormatter &rPatternFormatter);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::PatternFormatter, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_PATTERNFORMATTER_H
diff --git a/ext/Log4Qt/src/helpers/properties.cpp b/ext/Log4Qt/src/helpers/properties.cpp
new file mode 100755
index 0000000..5bfecd0
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/properties.cpp
@@ -0,0 +1,364 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: properties.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "helpers/properties.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QIODevice>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+#include "logger.h"
+
+
+
+namespace Log4Qt
+{
+
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties)
+
+
+
+ /**************************************************************************
+ * Class implementation: Properties
+ **************************************************************************/
+
+
+ void Properties::load(QIODevice *pDevice)
+ {
+ const QLatin1Char append_char(msEscapeChar);
+
+ if (!pDevice)
+ {
+ logger()->warn("No device specified for load.");
+ return;
+ }
+
+ QTextStream stream(pDevice);
+ QString line;
+ int line_number = 0;
+ QString property;
+ int property_start_line = 1;
+
+ do {
+ line = trimLeft(stream.readLine());
+ line_number++;
+
+ if (!line.isEmpty() && line.at(line.length() - 1) == append_char)
+ property += line.left(line.length() - 1);
+ else
+ {
+ property += line;
+ parseProperty(property, property_start_line);
+ property.clear();
+ property_start_line = line_number + 1;
+ }
+ }
+ while (!line.isNull());
+ }
+
+
+ void Properties::load(const QSettings &rSettings)
+ {
+ QStringList keys = rSettings.childKeys();
+ QString key;
+ Q_FOREACH(key, keys)
+ insert(key, rSettings.value(key).toString());
+ }
+
+
+ QString Properties::property(const QString &rKey) const
+ {
+ // Null string indicates the property does not contain the key.
+
+ if (contains(rKey))
+ {
+ QString value = this->value(rKey);
+ if (value.isNull())
+ return QString(QLatin1String(""));
+ else
+ return value;
+ }
+
+ if (mpDefaultProperties)
+ return mpDefaultProperties->property(rKey);
+ else
+ return QString();
+ }
+
+
+ QString Properties::property(const QString &rKey,
+ const QString &rDefaultValue) const
+ {
+ QString value = property(rKey);
+ if (value.isNull())
+ return rDefaultValue;
+ else
+ return value;
+ }
+
+
+ QStringList Properties::propertyNames() const
+ {
+ QStringList default_keys;
+ if (mpDefaultProperties)
+ default_keys = mpDefaultProperties->propertyNames();
+
+ QStringList keys = this->keys();
+ QString key;
+ Q_FOREACH(key, default_keys)
+ if (!keys.contains(key))
+ keys << key;
+
+ return keys;
+ }
+
+
+ void Properties::parseProperty(const QString &rProperty,
+ int line)
+ {
+ Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces");
+
+ enum State
+ {
+ KEY_STATE,
+ KEYSPACE_STATE,
+ SPACEVALUE_STATE,
+ VALUE_STATE,
+ KEYESCAPE_STATE,
+ VALUEESCAPE_STATE,
+ UNICODEESCAPE_STATE
+ };
+ const QString value_escape_codes =QLatin1String(msValueEscapeCodes);
+ const QString value_escape_chars = QLatin1String(msValueEscapeChars);
+ Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map");
+ const QString key_escape_codes = QLatin1String(msKeyEscapeCodes);
+ const QString key_escape_chars = QLatin1String(msKeyEscapeChars);
+ Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map");
+
+ if (rProperty.isEmpty())
+ return;
+
+ int i = 0;
+ QChar c;
+ char ch;
+ State state = KEY_STATE;
+ QString key;
+ QString value;
+ QString *p_string = &key;
+ uint ucs = 0;
+ int ucs_digits = 0;
+ while (i < rProperty.length())
+ {
+ // i points to the current character.
+ // c contains the current character
+ // ch contains the Latin1 equivalent of the current character
+ // i is incremented at the end of the loop to consume the character.
+ // continue is used to change state without consuming the character
+
+ c = rProperty.at(i);
+ ch = c.toLatin1();
+
+ switch (state)
+ {
+ case KEY_STATE:
+ if (ch == '!' || ch == '#' )
+ return;
+ else if (c.isSpace())
+ {
+ p_string = &value;
+ state = KEYSPACE_STATE;
+ }
+ else if (ch == '=' || ch == ':')
+ {
+ p_string = &value;
+ state = SPACEVALUE_STATE;
+ }
+ else if (ch == msEscapeChar)
+ state = KEYESCAPE_STATE;
+ else
+ *p_string += c;
+ break;
+ case KEYSPACE_STATE:
+ if (ch == '=' || ch == ':')
+ state = SPACEVALUE_STATE;
+ else if (!c.isSpace())
+ {
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ case SPACEVALUE_STATE:
+ if (!c.isSpace())
+ {
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ case VALUE_STATE:
+ if (ch == msEscapeChar)
+ state = VALUEESCAPE_STATE;
+ else
+ *p_string += c;
+ break;
+ case KEYESCAPE_STATE:
+ {
+ int convert = key_escape_codes.indexOf(c);
+ if (convert >= 0)
+ *p_string += key_escape_chars.at(convert);
+ else
+ {
+ logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2",
+ QString(c),
+ line);
+ *p_string += c;
+ }
+ state = KEY_STATE;
+ break;
+ }
+ case VALUEESCAPE_STATE:
+ {
+ int convert = value_escape_codes.indexOf(c);
+ if (convert >= 0)
+ {
+ *p_string += value_escape_chars.at(convert);
+ state = VALUE_STATE;
+ }
+ else if (ch == 'u')
+ {
+ ucs = 0;
+ ucs_digits = 0;
+ state = UNICODEESCAPE_STATE;
+ }
+ else
+ {
+ logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line);
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ }
+ case UNICODEESCAPE_STATE:
+ {
+ int hex = hexDigitValue(c);
+ if (hex >= 0)
+ {
+ ucs = ucs * 16 + hex;
+ ucs_digits++;
+ if (ucs_digits == 4 || i == rProperty.length() - 1)
+ {
+ *p_string += QChar(ucs);
+ state = VALUE_STATE;
+ }
+ }
+ else
+ {
+ if (ucs_digits > 0)
+ *p_string += QChar(ucs);
+ state = VALUE_STATE;
+ continue;
+ }
+ break;
+ }
+ default:
+ Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant");
+ return;
+ }
+ i++;
+ }
+
+ if (key.isEmpty() && !value.isEmpty())
+ logger()->warn("Found value with no key in property starting at line %1", line);
+
+ logger()->trace("Loaded property '%1' : '%2'", key, value);
+ insert(key, value);
+ }
+
+
+ int Properties::hexDigitValue(const QChar &rDigit)
+ {
+ bool ok;
+ int result = QString(rDigit).toInt(&ok, 16);
+ if (!ok)
+ return -1;
+ else
+ return result;
+ }
+
+
+ QString Properties::trimLeft(const QString &rLine)
+ {
+ int i = 0;
+ while (i < rLine.length() && rLine.at(i).isSpace())
+ i++;
+ return rLine.right(rLine.length() - i);
+ }
+
+
+ const char Properties::msEscapeChar ='\\';
+ const char *Properties::msValueEscapeCodes = "tnr\\\"\' ";
+ const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' ";
+ const char *Properties::msKeyEscapeCodes = " :=";
+ const char *Properties::msKeyEscapeChars = " :=";
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const Properties &rProperties)
+ {
+ debug.nospace() << "Properties("
+ << "default:" << rProperties.defaultProperties() << " "
+ << "properties:" << *reinterpret_cast<const QHash <QString, QString > *>(&rProperties)
+ << ")";
+ return debug.space();
+ }
+#endif
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/properties.h b/ext/Log4Qt/src/helpers/properties.h
new file mode 100755
index 0000000..0866431
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/properties.h
@@ -0,0 +1,161 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: properties.h
+ * created: September
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PROPERTIES_H
+#define LOG4QT_PROPERTIES_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QIODevice;
+class QSettings;
+
+
+namespace Log4Qt
+{
+ /*!
+ * \brief The class Properties implements a JAVA property hash.
+ */
+ class LOG4QT_EXPORT Properties : public QHash<QString, QString>
+ {
+ public:
+ Properties(Properties *pDefaultProperties = 0);
+ // virtual ~Properties(); // Use compiler default
+ // Properties(const Properties &rOther); // Use compiler default
+ // Properties &operator=(const Properties &rOther); // Not implemented
+
+ public:
+ Properties *defaultProperties() const;
+ QString property(const QString &rKey) const;
+ QString property(const QString &rKey,
+ const QString &rDefaultValue) const;
+ void setDefaultProperties(Properties *pDefault);
+ void setProperty(const QString &rKey,
+ const QString &rValue);
+
+ // JAVA: void list(QTextStream &rTextStream);
+ void load(QIODevice *pDevice);
+
+ /*!
+ * Reads all child keys from the QSettings object \a rSettings and
+ * inserts them into this object. The value is created using
+ * QVariant::toString(). Types that do not support toString() are
+ * resulting in an empty string.
+ *
+ * \code
+ * QSettings settings;
+ * settings.setValue("Package", "Full");
+ * settings.setValue("Background", Qt::white);
+ * settings.setValue("Support", true);
+ * settings.setValue("Help/Language", "en_UK");
+ *
+ * Properties properties
+ * properties.load(&settings)
+ *
+ * // properties (("Package", "Full"), ("Background", ""), ("Support", "true"))
+ * \endcode
+ */
+ void load(const QSettings &rSettings);
+
+ QStringList propertyNames() const;
+ // JAVA: void save(QIODevice *pDevice) const;
+
+ private:
+ void parseProperty(const QString &rProperty,
+ int line);
+ static int hexDigitValue(const QChar &rDigit);
+ static QString trimLeft(const QString &rString);
+
+ private:
+ Properties *mpDefaultProperties;
+ static const char msEscapeChar;
+ static const char *msValueEscapeCodes;
+ static const char *msValueEscapeChars;
+ static const char *msKeyEscapeCodes;
+ static const char *msKeyEscapeChars;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Properties
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %Properties(default:0x0 properties:QHash(("log4j.appender.testAppender.layout", "org.apache.log4j.PatternLayout ")
+ * ("log4j.appender.testAppender.layout.ConversionPattern", "[%t] %-5p %l: %m%n")
+ * ("log4j.appender.testAppender.Append", "false ")
+ * ("log4j.appender.testAppender.File", "output/temp ")
+ * ("log4j.rootCategory", "TRACE, testAppender")
+ * ("log4j.appender.testAppender", "org.apache.log4j.FileAppender")) )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const Properties &rProperties);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Properties::Properties(Properties *pDefaultProperties) :
+ mpDefaultProperties(pDefaultProperties)
+ {}
+
+ inline Properties *Properties::defaultProperties() const
+ { return mpDefaultProperties; }
+
+ inline void Properties::setDefaultProperties(Properties *pDefaultProperties)
+ { mpDefaultProperties = pDefaultProperties; }
+
+ inline void Properties::setProperty(const QString &rKey,
+ const QString &rValue)
+ { insert(rKey, rValue); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::Properties, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_PROPERTIES_H
diff --git a/ext/Log4Qt/src/hierarchy.cpp b/ext/Log4Qt/src/hierarchy.cpp
new file mode 100755
index 0000000..90a5cf6
--- /dev/null
+++ b/ext/Log4Qt/src/hierarchy.cpp
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * package:
+ * file: hierarchy.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Fixed problem in Qt 4.4 where QReadWriteLock is by default
+ * non-recursive.
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "hierarchy.h"
+
+#include <QtCore/QDebug>
+#include "logger.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(static_logger, ::LoggerRepository)
+
+
+
+ /**************************************************************************
+ * Class implementation: Hierarchy
+ **************************************************************************/
+
+
+ Hierarchy::Hierarchy() :
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ mObjectGuard(),
+#else
+ mObjectGuard(QReadWriteLock::Recursive),
+#endif
+ mLoggers(),
+ mThreshold(Level::NULL_INT),
+ mpRootLogger(logger(QString()))
+ {
+ // Store root logger to allow rootLogger() to be const
+ }
+
+
+ Hierarchy::~Hierarchy()
+ {
+ static_logger()->warn("Unexpected destruction of Hierarchy");
+
+ // QWriteLocker locker(&mObjectGuard);
+ //
+ // resetConfiguration();
+ // clear();
+ // delete mpRootLogger;
+ }
+
+
+ bool Hierarchy::exists(const QString &rName) const
+ {
+ QReadLocker locker(&mObjectGuard);
+
+ return mLoggers.contains(rName);
+ }
+
+
+ Logger *Hierarchy::logger(const QString &rName)
+ {
+ QWriteLocker locker(&mObjectGuard);
+
+ return createLogger(rName);
+ }
+
+
+ QList<Logger *> Hierarchy::loggers() const
+ {
+ QReadLocker locker(&mObjectGuard);
+
+ return mLoggers.values();
+ }
+
+
+ void Hierarchy::setThreshold(const QString &rThreshold)
+ {
+ setThreshold(Level::fromString(rThreshold));
+ }
+
+
+ void Hierarchy::resetConfiguration()
+ {
+ QWriteLocker locker(&mObjectGuard);
+
+ // Reset all loggers.
+ // Leave log, qt and root logger to the last to allow debugging of shutdown.
+
+ Logger *p_logging_logger = logger(QLatin1String(""));
+ Logger *p_qt_logger = logger(QLatin1String("Qt"));
+ Logger *p_root_logger = rootLogger();
+
+ Logger *p_logger;
+ Q_FOREACH(p_logger, mLoggers)
+ {
+ if ((p_logger == p_logging_logger) || (p_logger == p_qt_logger) || (p_logger == p_root_logger))
+ continue;
+ resetLogger(p_logger, Level::NULL_INT);
+ }
+ resetLogger(p_qt_logger, Level::NULL_INT);
+ resetLogger(p_logging_logger, Level::NULL_INT);
+ resetLogger(p_root_logger, Level::DEBUG_INT);
+ }
+
+
+ void Hierarchy::shutdown()
+ {
+ static_logger()->debug("Shutting down Hierarchy");
+ resetConfiguration();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug Hierarchy::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "Hierarchy("
+ << "loggers:" << loggers().count() << " "
+ << "threshold:" << threshold().toString() << " "
+ << "root-level:" << rootLogger()->level().toString() << " "
+ << "root-appenders:" << rootLogger()->appenders().count()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+ Logger *Hierarchy::createLogger(const QString &rName)
+ {
+ // Q_ASSERT_X(, "Hierarchy::createLogger", "Lock must be held by caller")
+
+ const QString name_separator = QLatin1String("::");
+
+ Logger *p_logger = mLoggers.value(rName, 0);
+ if (p_logger != 0)
+ return p_logger;
+
+ if (rName.isEmpty())
+ {
+ p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), 0);
+ mLoggers.insert(QString(), p_logger);
+ return p_logger;
+ }
+ QString parent_name;
+ int index = rName.lastIndexOf(name_separator);
+ if (index >=0)
+ parent_name = rName.left(index);
+ p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name));
+ mLoggers.insert(rName, p_logger);
+ return p_logger;
+ }
+
+
+ void Hierarchy::resetLogger(Logger *pLogger, Level level) const
+ {
+ // Q_ASSERT_X(, "Hierarchy::resetLogger", "Lock must be held by caller")
+
+ pLogger->removeAllAppenders();
+ pLogger->setAdditivity(true);
+ pLogger->setLevel(level);
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/hierarchy.h b/ext/Log4Qt/src/hierarchy.h
new file mode 100755
index 0000000..3199523
--- /dev/null
+++ b/ext/Log4Qt/src/hierarchy.h
@@ -0,0 +1,141 @@
+/******************************************************************************
+ *
+ * package:
+ * file: hierarchy.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef _HIERARCHY_H
+#define _HIERARCHY_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "loggerrepository.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QReadWriteLock>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class Hierarchy implements a logger repository.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT Hierarchy : public LoggerRepository
+ {
+ public:
+ Hierarchy();
+ // Hierarchy(const Hierarchy &rOther); // Use compiler default
+ virtual ~Hierarchy();
+ // Hierarchy &operator=(const Hierarchy &rOther); // Use compiler default
+
+ public:
+ virtual bool exists(const QString &rName) const;
+ virtual Logger *logger(const QString &rName);
+ virtual QList<Logger *> loggers() const;
+ // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory);
+ virtual Logger *rootLogger() const;
+ virtual Level threshold() const;
+ virtual void setThreshold(Level level);
+ virtual void setThreshold(const QString &rThreshold);
+
+ // JAVA: void clear();
+ virtual bool isDisabled(Level level);
+ virtual void resetConfiguration();
+ virtual void shutdown();
+
+ // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener);
+ // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const;
+ // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const;
+
+ // JAVA: void addRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer);
+ // JAVA: QHash<QString, ObjectRenderer *> getRendererMap() const;
+ // JAVA: setRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer);
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %Hierarchy(loggers:6 threshold:"ALL" root-level:"DEBUG" root-appenders:0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LoggerRepository &rLoggerRepository)
+ */
+ virtual QDebug debug(QDebug &rdebug) const;
+#endif
+
+ private:
+ Logger *createLogger(const QString &rName);
+ void resetLogger(Logger *pLogger, Level level) const;
+
+ private:
+ mutable QReadWriteLock mObjectGuard;
+ QHash<QString, Logger*> mLoggers;
+ volatile bool mHandleQtMessages;
+ Level mThreshold;
+ Logger *mpRootLogger;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Logger *Hierarchy::rootLogger() const
+ { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime
+ return mpRootLogger; }
+
+ inline Level Hierarchy::threshold() const
+ { // QReadLocker locker(&mObjectGuard); // Level is threadsafe
+ return mThreshold; }
+
+ inline void Hierarchy::setThreshold(Level level)
+ { // QReadLocker locker(&mObjectGuard); // Level is threadsafe
+ mThreshold = level; }
+
+ inline bool Hierarchy::isDisabled(Level level)
+ { // QReadLocker locker(&mObjectGuard); // Level is threadsafe
+ return level < mThreshold; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(::Hierarchy, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // _HIERARCHY_H
diff --git a/ext/Log4Qt/src/layout.cpp b/ext/Log4Qt/src/layout.cpp
new file mode 100644
index 0000000..19c5059
--- /dev/null
+++ b/ext/Log4Qt/src/layout.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: layout.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "layout.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+#include "logmanager.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /***************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: Layout
+ **************************************************************************/
+
+
+ QString Layout::contentType() const
+ {
+ return QString::fromLatin1("text/plain");
+ }
+
+
+ void Layout::activateOptions()
+ {
+ }
+
+
+ QString Layout::endOfLine()
+ {
+ // There seams to be no function in Qt for this. MinGW enter '\r\n' automatically
+ return QLatin1String("\n");
+ }
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/layout.h b/ext/Log4Qt/src/layout.h
new file mode 100755
index 0000000..1946454
--- /dev/null
+++ b/ext/Log4Qt/src/layout.h
@@ -0,0 +1,156 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: layout.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LAYOUT_H
+#define LOG4QT_LAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "helpers/logobject.h"
+
+#include "helpers/logobjectptr.h"
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class LoggingEvent;
+
+ /*!
+ * \brief The class Layout is the base class for all layouts.
+ *
+ * \note The ownership and lifetime of objects of this class are managed. See
+ * \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT Layout : public LogObject
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the content type of the layout.
+ *
+ * \sa contentType()
+ */
+ Q_PROPERTY(QString footercontentType READ contentType)
+ /*!
+ * The property holds the footer used by the layout.
+ *
+ * \sa footer(), setFooter()
+ */
+ Q_PROPERTY(QString footer READ footer WRITE setFooter)
+ /*!
+ * The property holds the header used by the layout.
+ *
+ * \sa header(), setHeader()
+ */
+ Q_PROPERTY(QString header READ header WRITE setHeader)
+
+ public:
+ Layout(QObject *pParent = 0);
+ virtual ~Layout();
+ private:
+ Layout(const Layout &rOther); // Not implemented
+ Layout &operator=(const Layout &rOther); // Not implemented
+
+ public:
+ virtual QString contentType() const;
+ QString footer() const;
+ QString header() const;
+ // JAVA: virtual bool ignoresThrowable() const;
+ QString name() const;
+ void setFooter(const QString &rFooter);
+ void setHeader(const QString &rHeader);
+ void setName(const QString &rName);
+ // JAVA: void setIgnoresThrowable(bool) const;
+
+ virtual void activateOptions();
+ virtual QString format(const LoggingEvent &rEvent) = 0;
+
+ /*!
+ * Returns the end of line seperator for the operating system.
+ *
+ * Windows: \\r\\n
+ * Mac: \\r
+ * UNIX: \\n
+ */
+ static QString endOfLine();
+
+ // Member variables
+ private:
+ QString mFooter;
+ QString mHeader;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Layout::Layout(QObject *pParent) :
+ LogObject(pParent)
+ {}
+
+ inline Layout::~Layout()
+ {}
+
+ inline QString Layout::footer() const
+ { return mFooter; }
+
+ inline QString Layout::header() const
+ { return mHeader; }
+
+ inline QString Layout::name() const
+ { return objectName(); }
+
+ inline void Layout::setFooter(const QString &rFooter)
+ { mFooter = rFooter; }
+
+ inline void Layout::setHeader(const QString &rHeader)
+ { mHeader = rHeader; }
+
+ inline void Layout::setName(const QString &rName)
+ { setObjectName(rName); }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::Layout, Q_COMPLEX_TYPE); // Use default
+Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Layout>, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_LAYOUT_H
diff --git a/ext/Log4Qt/src/level.cpp b/ext/Log4Qt/src/level.cpp
new file mode 100755
index 0000000..f546740
--- /dev/null
+++ b/ext/Log4Qt/src/level.cpp
@@ -0,0 +1,242 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: level.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "level.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include "logger.h"
+#include <QDataStream>
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Level)
+
+
+
+ /**************************************************************************
+ * Class implementation: Level
+ **************************************************************************/
+
+
+ int Level::syslogEquivalent() const
+ {
+ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+
+ switch (mValue)
+ {
+ case NULL_INT:
+ case ALL_INT:
+ case TRACE_INT:
+ case DEBUG_INT:
+ return 7;
+ case INFO_INT:
+ return 6;
+ case WARN_INT:
+ return 4;
+ case ERROR_INT:
+ return 3;
+ case FATAL_INT:
+ case OFF_INT:
+ return 0;
+ default:
+ Q_ASSERT_X(false, "Level::syslogEquivalent()", "Unknown level value");
+ return 7;
+ }
+ }
+
+
+ QString Level::toString() const
+ {
+ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+
+ const char *p_context = "Level";
+
+ switch (mValue)
+ {
+ case NULL_INT:
+ return QCoreApplication::translate(p_context, "NULL");
+ case ALL_INT:
+ return QCoreApplication::translate(p_context, "ALL");
+ case TRACE_INT:
+ return QCoreApplication::translate(p_context, "TRACE");
+ case DEBUG_INT:
+ return QCoreApplication::translate(p_context, "DEBUG");
+ case INFO_INT:
+ return QCoreApplication::translate(p_context, "INFO");
+ case WARN_INT:
+ return QCoreApplication::translate(p_context, "WARN");
+ case ERROR_INT:
+ return QCoreApplication::translate(p_context, "ERROR");
+ case FATAL_INT:
+ return QCoreApplication::translate(p_context, "FATAL");
+ case OFF_INT:
+ return QCoreApplication::translate(p_context, "OFF");
+ default:
+ Q_ASSERT_X(false, "Level::toString()", "Unknown level value");
+ return QCoreApplication::translate(p_context, "NULL");
+ }
+ }
+
+
+ Level Level::fromString(const QString &rLevel, bool *pOk)
+ {
+ const char *p_context = "Level";
+ if (pOk)
+ *pOk = true;
+
+ if (rLevel == QLatin1String("OFF") ||
+ rLevel == QCoreApplication::translate(p_context, "OFF"))
+ return OFF_INT;
+ if (rLevel == QLatin1String("FATAL") ||
+ rLevel == QCoreApplication::translate(p_context, "FATAL"))
+ return FATAL_INT;
+ if (rLevel == QLatin1String("ERROR") ||
+ rLevel == QCoreApplication::translate(p_context, "ERROR"))
+ return ERROR_INT;
+ if (rLevel == QLatin1String("WARN") ||
+ rLevel == QCoreApplication::translate(p_context, "WARN"))
+ return WARN_INT;
+ if (rLevel == QLatin1String("INFO") ||
+ rLevel == QCoreApplication::translate(p_context, "INFO"))
+ return INFO_INT;
+ if (rLevel == QLatin1String("DEBUG") ||
+ rLevel == QCoreApplication::translate(p_context, "DEBUG"))
+ return DEBUG_INT;
+ if (rLevel == QLatin1String("TRACE") ||
+ rLevel == QCoreApplication::translate(p_context, "TRACE"))
+ return TRACE_INT;
+ if (rLevel == QLatin1String("ALL") ||
+ rLevel == QCoreApplication::translate(p_context, "ALL"))
+ return ALL_INT;
+ if (rLevel == QLatin1String("NULL") ||
+ rLevel == QCoreApplication::translate(p_context, "NULL"))
+ return NULL_INT;
+
+ logger()->warn("Use of invalid level string '%1'. Using 'Level::NULL_INT' instead.", rLevel);
+ if (pOk)
+ *pOk = false;
+ return NULL_INT;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DATASTREAM
+ QDataStream &operator<<(QDataStream &rStream,
+ const Level &rLevel)
+ {
+ quint8 l = rLevel.mValue;
+ rStream << l;
+ return rStream;
+ }
+
+
+ QDataStream &operator>>(QDataStream &rStream,
+ Level &rLevel)
+ {
+ quint8 l;
+ rStream >> l;
+ rLevel.mValue = static_cast<Level::Value>(l);
+ return rStream;
+ }
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const Level &rLevel)
+ {
+ debug.nospace() << "Level("
+ << rLevel.toString()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+Level::Level(Value value)
+ : mValue(value)
+{
+}
+
+int Level::toInt() const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue;
+}
+
+bool Level::operator==(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue == rOther.mValue;
+}
+
+bool Level::operator!=(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue != rOther.mValue;
+}
+
+bool Level::operator<(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue < rOther.mValue;
+}
+
+bool Level::operator<=(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue <= rOther.mValue;
+}
+
+bool Level::operator>(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue > rOther.mValue;
+}
+
+bool Level::operator>=(const Level &rOther) const
+{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mValue >= rOther.mValue;
+}
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/level.h b/ext/Log4Qt/src/level.h
new file mode 100755
index 0000000..056e82a
--- /dev/null
+++ b/ext/Log4Qt/src/level.h
@@ -0,0 +1,154 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: level.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LEVEL_H
+#define LOG4QT_LEVEL_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include <QtCore/QMetaType>
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class Level defines the level of a logging event.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT Level
+ {
+ public:
+ // Comparisson operators rely on the order:
+ // NULL_INT < ALL_INT < TRACE_INT < ...
+ // Serialisation uses unsigned 8 bit int
+
+ /*!
+ * The enumeration Value contains all possible Level values.
+ */
+ enum Value
+ {
+ /*! NULL_INT is used for no level has been specified */
+ NULL_INT = 0,
+ ALL_INT = 32,
+ TRACE_INT = 64,
+ DEBUG_INT = 96,
+ INFO_INT = 128,
+ WARN_INT = 150,
+ ERROR_INT = 182,
+ FATAL_INT = 214,
+ OFF_INT = 255
+ };
+
+ public:
+ Level(Value value = NULL_INT);
+ // Level(const Level &rOther); // Use compiler default
+ // virtual ~Level(); // Use compiler default
+ // Level &operator=(const Level &rOther); // Use compiler default
+
+ int syslogEquivalent() const;
+ int toInt() const;
+
+ bool operator==(const Level &rOther) const;
+ bool operator!=(const Level &rOther) const;
+ bool operator<(const Level &rOther) const;
+ bool operator<=(const Level &rOther) const;
+ bool operator>(const Level &rOther) const;
+ bool operator>=(const Level &rOther) const;
+ QString toString() const;
+
+ static Level fromString(const QString &rName, bool *pOk = 0);
+
+ private:
+ // QMutex mObjectGuard;
+ volatile Value mValue;
+
+#ifndef QT_NO_DATASTREAM
+ // Needs to be friend to stream objects
+ friend QDataStream &operator<<(QDataStream &rStream,
+ const Level &rLevel);
+ friend QDataStream &operator>>(QDataStream &rStream,
+ Level &rLevel);
+#endif // QT_NO_DATASTREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+ /*!
+ * \relates Level
+ *
+ * Writes the given error \a rLevel to the given stream \a rStream,
+ * and returns a reference to the stream.
+ */
+ QDataStream &operator<<(QDataStream &rStream,
+ const Level &rLevel);
+
+ /*!
+ * \relates Level
+ *
+ * Reads an error from the given stream \a rStream into the given
+ * error \a rLevel, and returns a reference to the stream.
+ */
+ QDataStream &operator>>(QDataStream &rStream,
+ Level &rLevel);
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Level
+ *
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %Level("ERROR")
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const Level &rLevel);
+#endif // QT_NO_DEBUG_STREAM
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_METATYPE(Log4Qt::Level)
+Q_DECLARE_TYPEINFO(Log4Qt::Level, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_LEVEL_H
diff --git a/ext/Log4Qt/src/log4qt.cpp b/ext/Log4Qt/src/log4qt.cpp
new file mode 100755
index 0000000..430b022
--- /dev/null
+++ b/ext/Log4Qt/src/log4qt.cpp
@@ -0,0 +1,15 @@
+//============================================================================
+// Name : log4qt.cpp
+// Author :
+// Version :
+// Copyright : Your copyright notice
+// Description : Hello World in C++, Ansi-style
+//============================================================================
+
+#include <iostream>
+using namespace std;
+
+int main() {
+ cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
+ return 0;
+}
diff --git a/ext/Log4Qt/src/log4qt.h b/ext/Log4Qt/src/log4qt.h
new file mode 100644
index 0000000..b3c32ed
--- /dev/null
+++ b/ext/Log4Qt/src/log4qt.h
@@ -0,0 +1,623 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logging.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Added a compile time version check for the Qt version
+ * Jan 2009, Martin Heinrich:
+ * - Updated documentation and version information for version 0.2
+ * Feb 2009, Martin Heinrich:
+ * - Updated version information for version 0.3
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_H
+#define LOG4QT_H
+
+#include "log4qtshared.h"
+
+/*!
+ * \page Log4Qt Main Page
+ *
+ * %Log4Qt is a C++ port of the Apache Software Foundation Log4j package
+ * using the Trolltech Qt Framework.
+ *
+ * The documentation describes classes and methods that have been added or
+ * changed compared to Log4j.
+ *
+ * The following sections are describing the implementation in more detail:
+ * - \ref Changes "Differences to Log4j"
+ * - \ref Ownership "Object ownership"
+ * - \ref LogLog "Logging within the package"
+ * - \ref Init "Initialization procedure"
+ * - \ref Env "Environment Variables"
+ * - \ref Undocumented "Undocumented functions"
+ * - \ref Assumptions "Assumptions"
+ *
+ * \author Martin Heinrich
+ * \version 0.3 (January 2009)
+ *
+ */
+
+/*!
+ * \page Changes Differences to Log4j
+ *
+ * The following fundamental differences exist between %Log4Qt and Log4j:
+ *
+ * - As a JAVA package Log4j does not have to manage object ownership and
+ * lifetime in the same way then it is required in C++. For details on
+ * how object ownership is handled see \ref Ownership "Object ownership".
+ * - The package uses itself for its internal logging similar to Log4j 1.3.
+ * For details see \ref LogLog "Logging within the package".
+ * - The configuration using system properties was replaced with a combination
+ * of environment variables and application settings. For details see
+ * \ref Env "Environment Variables".
+ * - Custom levels are not supported.
+ * - Multiple Logger Repositories are not supported
+ *
+ * The following classes have been changed:
+ *
+ * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton"
+ * - The procedure of checking, if logging is possible, originally used by
+ * \ref Log4Qt::WriterAppender "WriterAppender" was generalised and is used
+ * in \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" and derived classes
+ * (\ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()").
+ * - The \ref Log4Qt::AppenderSkeleton::doAppend() "doAppend()" member function will
+ * check the entry conditions by calling the sub-class specific
+ * \ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()".
+ * If successful the sub-class specific
+ * \ref Log4Qt::AppenderSkeleton::append() "append()" function is called.
+ *
+ * - Configurator
+ * - Configure functions return a boolean indicating, if the configuration
+ * was successful.
+ * - Configure errors are accessible over
+ * \ref Log4Qt::ConfiguratorHelper::configureError()
+ * "ConfiguratorHelper::configureError()".
+ * - Watching for configuration file changes is a function performed
+ * centrally by the \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper".
+ * The class provides signals to notify on configuration change and errors.
+ * - The class \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" was
+ * extended to be able to read configuration data from a QSettings object.
+ *
+ * - \ref Log4Qt::Level "Level"
+ * - A new value \ref Log4Qt::Level::NULL_INT "Level::NULL_INT" was
+ * introduced to indicate there is no level set.
+ *
+ * - \ref Log4Qt::Logger "Logger"
+ * - The method \ref Log4Qt::Logger::isEnabledFor() "isEnabledFor()"
+ * does also take the repository threshold into account.
+ * - Several overloaded convenience member function are available to log
+ * messages with arguments of different types.
+ * - Two macros, \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER"
+ * and \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER",
+ * allows retrieving and caching of a pointer to a logger object.
+ *
+ * - \ref Log4Qt::LogManager "LogManager"
+ * - A QtMessage handler can be installed via
+ * \ref Log4Qt::LogManager::setHandleQtMessages() "setHandleQtMessages()",
+ * to redirect all messages created by calls to qDebug(), qWarning(),
+ * qCritical() and qFatal() to a logger. The logger is named Qt and can be
+ * accessed using \ref Log4Qt::LogManager::qtLogger() "qtLogger()".
+ * - The initialisation procedure is available over a public method
+ * (\ref Log4Qt::LogManager::startup() "startup()").
+ * - The LogManager provides access to the logger used internally by the
+ * package (\ref Log4Qt::LogManager::logLogger() "logLogger()") and to
+ * its default initialisation procedure
+ * (\ref Log4Qt::LogManager::configureLogLogger() "configureLogLogger()").
+ *
+ * - \ref Log4Qt::WriterAppender "WriterAppender"
+ * - The class will call \ref Log4Qt::WriterAppender::handleIoErrors()
+ * "handleIoErrors()" after all I/O operations. Sub-classes should
+ * re-implement the function to handle errors.
+ *
+ * The following classes have been added:
+ *
+ * - An additional appender class, \ref Log4Qt::DebugAppender "DebugAppender",
+ * was added. The class appends logging events to the platform specific debug
+ * output.
+ * - Various helper class have been introduced:
+ * - \ref Log4Qt::ClassLogger "ClassLogger": The class ClassLogger provides
+ * logging for a QObject derived class.
+ * - \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper": The class
+ * ConfiguratorHelper provides a configuration file watch and last error
+ * for configurator classes.
+ * - \ref Log4Qt::DateTime "DateTime": The class DateTime provides extended
+ * functionality for QDateTime.
+ * - \ref Log4Qt::LogError "LogError": The class LogError represents an error.
+ * - \ref Log4Qt::Factory "Factory": The class Factory provides factories
+ * for Appender, Filter and Layout objects.
+ * - \ref Log4Qt::InitialisationHelper "InitialisationHelper": The class
+ * InitialisationHelper performs static initialisation tasks.
+ * - \ref Log4Qt::LogObject "LogObject": The class LogObject is the common
+ * base class for many classes in the package.
+ * - \ref Log4Qt::LogObjectPtr "LogObjectPtr": The class LogObjectPtr
+ * implements automatic reference counting for LogObject objects.
+ * - \ref Log4Qt::PatternFormatter "PatternFormatter": The class
+ * PatternFormatter formats a logging event based on a pattern string.
+ * - \ref Log4Qt::Properties "Properties": The class Properties implements a
+ * JAVA property hash.
+ */
+
+/*!
+ * \page Ownership Object ownership
+ *
+ * In difference to the JAVA Log4j package %Log4Qt must manage ownership and
+ * lifetime of the objects used. This is non trivial as objects are created
+ * and used in different ways.
+ *
+ * In general an object can be created explicitly for example an application
+ * may create Loggers, Appenders and Layouts during creation of a QApplication
+ * object. But they can also be automatically created by the package on
+ * startup using a \ref Log4Qt::PropertyConfigurator "PropertyConfigurator"
+ * configuration file. Objects may also be created the one way and then used
+ * the other. Object may be used by multiple other objects. A Layout for example
+ * may be used by multiple Appenders. Objects are also created from multiple
+ * threads. The creation may happen during static initialisation and the
+ * deletion during static de-initialization.
+ *
+ * The parent child model used by QObject cannot be used to handle this. It
+ * cannot automatically delete an object that is used by multiple others as
+ * for example an Appender used by multiple Loggers. In addition to this
+ * QObjects and their children must reside in the same thread. This would
+ * either mean to impose restriction on how objects can be created or to move
+ * objects to a specific thread.
+ *
+ * To allow an automatic deletion of not required objects the package
+ * implements reference counting for Appenders, Layouts and Filters. The
+ * reference counting is implemented in \ref Log4Qt::LogObject "LogObject",
+ * which is used as a common base class. The reference count can be explicitly
+ * changed using the methods \ref Log4Qt::LogObject::retain() "retain()" and
+ * \ref Log4Qt::LogObject::release() "release()". Alternatively an auto pointer
+ * is available \ref Log4Qt::LogObjectPtr "LogObjectPtr", which is used
+ * throughout the package.
+ *
+ * The reference counting mechanism will test, if an object has a QObject
+ * parent object set. If a parent is set, the object will not be deleted, if
+ * the reference count reaches 0. This allows to mix the reference counted
+ * paradigm with the QObject parent child one.
+ *
+ * The following example configures a logger and uses reference counting to
+ * manage the ownership of objects.
+ *
+ * \code
+ * // Create layout
+ * TTCCLayout *p_layout = new TTCCLayout();
+ *
+ * // Create appender
+ * ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET);
+ * p_appender->activateOptions();
+ *
+ * // Get logger
+ * Logger *p_logger = Logger::logger("MyClass");
+ * p_logger->addAppender(p_appender);
+ *
+ * // ...
+ *
+ * // Remove appender from Logger
+ * p_logger->removeAllAppenders(); // p_appender and p_layout are deleted here
+ * \endcode
+ *
+ * The following example configures a logger and uses QObject ownership of
+ * objects.
+ *
+ * \code
+ * QObject *p_parent = new MyObject;
+ *
+ * // Create objects
+ * ConsoleAppender *p_appender = new ConsoleAppender(p_parent);
+ * TTCCLayout *p_layout = new TTCCLayout(p_appender);
+ *
+ * // Configure appender
+ * p_appender->setTarget(ConsoleAppender::STDOUT_TARGET);
+ * p_appender->setLayout(p_layout);
+ * p_appender->activateOptions();
+ *
+ * // Get logger
+ * Logger *p_logger = Logger::logger("MyClass");
+ * p_logger->addAppender(p_appender);
+ *
+ * // ...
+ *
+ * // Remove appender from Logger
+ * p_logger->removeAllAppenders();
+ *
+ * delete p_parent; // p_appender and p_layout are deleted here
+ * \endcode
+ *
+ * The following example shows how to use objects created on the stack.
+ *
+ * \code
+ * {
+ * // Create layout
+ * TTCCLayout layout;
+ * layout.retain();
+ *
+ * // Create appender
+ * ConsoleAppender appender(&layout, ConsoleAppender::STDOUT_TARGET);
+ * appender.retain();
+ * appender.activateOptions();
+ *
+ * // Get logger
+ * Logger *p_logger = Logger::logger("MyClass");
+ * p_logger->addAppender(&appender);
+ *
+ * // ...
+ *
+ * // Remove appender from Logger
+ * p_logger->removeAllAppenders(); // Without retain() program crashes here
+ *
+ * } // p_appender and p_layout are deleted here
+ * \endcode
+ */
+
+/*!
+ * \page LogLog Logging within the package
+ *
+ * The package uses itself for logging similar to Log4j 1.3. This brings much
+ * more flexibility over logging to stdout, stderr like in Log4j 1.2 using
+ * logLog. It also enables the program to capture and handle errors raised by
+ * the package.
+ *
+ * Using this approach introduces the issue of recursion. The following example
+ * explains a situation where this happens. Let's say all logger are configured
+ * to be additive and only the root logger has an appender set. The appender
+ * is a \ref Log4Qt::FileAppender "FileAppender". During the logging of an
+ * event an I/O error occurs. The \ref Log4Qt::FileAppender "FileAppender" logs
+ * an event by itself using the logger %Log4Qt::FileAppender. The event is
+ * passed to the root logger, which calls then the \ref Log4Qt::FileAppender
+ * "FileAppender". This causes another I/O error, which is logged by
+ * the \ref Log4Qt::FileAppender "FileAppender".
+ *
+ * To avoid an endless loop the appender will drop the event on a recursive
+ * invocation. This check is done by \ref Log4Qt::AppenderSkeleton
+ * "AppenderSkeleton" in \ref Log4Qt::AppenderSkeleton::doAppend()
+ * "doAppend()".
+ *
+ * The problem only occurs, if a logger, appender, layout or filter log an
+ * event while an event is appended. Neither the logger class nor any of the
+ * layout or filter classes log events during appending of an event. Most of
+ * the appender classes may log errors during appending. Only the
+ * \ref Log4Qt::ListAppender "ListAppender" and
+ * \ref Log4Qt::ListAppender "ConsoleAppender" are not logging events.
+ *
+ * The default configuration uses two \ref Log4Qt::ListAppender
+ * "ConsoleAppender", one for stderr and one for stdout. No event will be
+ * dropped, because no recursive invocations can occur.
+ */
+
+/*!
+ * \page Init Initialization procedure
+ *
+ * The package is initialised in two stages. The first stage takes place during
+ * static initialization. The second stage takes place when the
+ * \ref Log4Qt::LogManager "LogManager" singleton is created.
+ *
+ * During static initialisation the \ref Log4Qt::InitialisationHelper
+ * "InitialisationHelper" singleton is created . On construction it captures
+ * the program startup time, reads the required values from the system
+ * environment and registers the package types with the Qt type system.
+ *
+ * The \ref Log4Qt::LogManager "LogManager" singleton is created on first use.
+ * The creation is usually triggered by the request for a \ref Log4Qt::Logger
+ * "Logger" object. The call to \ref Log4Qt::Logger::logger()
+ * "Logger::logger()" is passed through to \ref Log4Qt::LogManager::logger()
+ * "LogManager::logger()". On creation the \ref Log4Qt::LogManager "LogManager"
+ * creates a \ref Log4Qt::Hierarchy "Hierarchy" object as logger repository.
+ *
+ * After the singleton is created the logging of the package is configured to
+ * its default by a call to \ref Log4Qt::LogManager::configureLogLogger()
+ * "LogManager::configureLogLogger()". The logger
+ * \ref Log4Qt::LogManager::logLogger() "logLogger()" is configured to be not
+ * additive. Messages with the level \ref Log4Qt::Level::ERROR_INT
+ * "Level::ERROR_INT" and \ref Log4Qt::Level::FATAL_INT "Level::FATAL_INT" are
+ * written to \c stderr using a ConsoleAppender. The remaining messages are
+ * written to \c stdout using a second ConsoleAppender. The level is read from
+ * the system environment or application settings using
+ * \ref Log4Qt::InitialisationHelper::setting()
+ * "InitialisationHelper::setting()" with the key \c Debug. If a level value
+ * is found, but it is not a valid Level string,
+ * \ref Log4Qt::Level::DEBUG_INT "Level::DEBUG_INT" is used. If no level string
+ * is found \ref Log4Qt::Level::ERROR_INT "Level::ERROR_INT" is used.
+ *
+ * Once the logging is configured the package is initialised by a call to
+ * \ref Log4Qt::LogManager::startup() "LogManager::startup()". The function
+ * will test for the setting \c DefaultInitOverride in the system environment
+ * and application settings using \ref Log4Qt::InitialisationHelper::setting()
+ * "InitialisationHelper::setting()". If the value is present and set to
+ * anything else then \c false, the initialisation is aborted.<br>
+ * The system environment and application settings are tested for the setting
+ * \c Configuration. If it is found and it is a valid path to a file, the
+ * package is configured with the file using
+ * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *)
+ * "PropertyConfigurator::doConfigure()". If the setting \c Configuration is
+ * not available and a QCoreApplication object is present, the application
+ * settings are tested for a group \c Properties. If the group exists,
+ * the package is configured with the setting using the
+ * \ref Log4Qt::PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *)
+ * "PropertyConfiguratordoConfigure()". If neither a configuration file nor
+ * configuration settings could be found, the current working directory is
+ * searched for the file \c "log4qt.properties". If it is found, the package
+ * is configured with the file using
+ * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *)
+ * "PropertyConfigurator::doConfigure()".
+ *
+ * The following example shows how to use application settings to initialise the
+ * package.
+ *
+ * \code
+ * # file: myapplication.h
+ *
+ * #include qapplication.h
+ *
+ * class MyApplication : public QApplication
+ * {
+ * Q_OBJECT
+ *
+ * public:
+ * MyApplication();
+ * ~MyApplication();
+ * void setupLog4Qt();
+ * }
+ * \endcode
+ * \code
+ * # file: myapplication.cpp
+ *
+ * #include myapplication.h
+ *
+ * MyApplication::MyApplication(
+ * {
+ * // Set Application data to allow Log4Qt initialisation to read the
+ * // correct values
+ * setApplicationName("MyApplication");
+ * setOrganisationName("MyOrganisation");
+ * setOrganizationDomain("www.myorganisation.com");
+ *
+ * // Log first message, which initialises Log4Qt
+ * Log4Qt::Logger::logger("MyApplication")->info("Hello World");
+ * }
+ *
+ * MyApplication::~MyApplication()
+ * {
+ * }
+ *
+ * void MyApplication::setupLog4Qt()
+ * {
+ * QSettings s;
+ *
+ * // Set logging level for Log4Qt to TRACE
+ * s.beginGroup("Log4Qt");
+ * s.setValue("Debug", "TRACE");
+ *
+ * // Configure logging to log to the file C:/myapp.log using the level TRACE
+ * s.beginGroup("Properties");
+ * s.setValue("log4j.appender.A1", "org.apache.log4j.FileAppender");
+ * s.setValue("log4j.appender.A1.file", "C:/myapp.log");
+ * s.setValue("log4j.appender.A1.layout", "org.apache.log4j.TTCCLayout");
+ * s.setValue("log4j.appender.A1.layout.DateFormat", "ISO8601");
+ * s.setValue("log4j.rootLogger", "TRACE, A1");
+ *
+ * // Settings will become active on next application startup
+ * }
+ * \endcode
+ */
+
+/*!
+ * \page Env Environment Variables
+ *
+ * The package uses environment variables to control the initialization
+ * procedure. The environment variables replace the system property entries
+ * used by Log4j.
+ *
+ * For compability reasons the Log4j entry is recognised. Alternatively a
+ * environment variable style Log4Qt form can be used. The following entries
+ * are used:
+ *
+ * - LOG4QT_DEBUG<br>
+ * The variable controls the \ref Log4Qt::Level "Level" value for the
+ * logger \ref Log4Qt::LogManager::logLogger() "LogManager::logLogger()".
+ * If the value is a valid \ref Log4Qt::Level "Level" string, the level for
+ * the is set to the level. If the value is not a valid
+ * \ref Log4Qt::Level "Level" string, \ref Log4Qt::Level::DEBUG_INT
+ * "DEBUG_INT" is used. Otherwise \ref Log4Qt::Level::ERROR_INT "ERROR_INT"
+ * is used.
+ * - \ref Log4Qt::LogManager::configureLogLogger()
+ * "LogManager::configureLogLogger()"
+ *
+ * - LOG4QT_DEFAULTINITOVERRIDE<br>
+ * The variable controls the \ref Init "initialization procedure" performed
+ * by the \ref Log4Qt::LogManager "LogManager" on startup. If it is set to
+ * any other value then \c false the \ref Init "initialization procedure"
+ * is skipped.
+ * - \ref Log4Qt::LogManager::startup() "LogManager::startup()"
+ *
+ * - LOG4QT_CONFIGURATION<br>
+ * The variable specifies the configuration file used for initialising the
+ * package.
+ * - \ref Log4Qt::LogManager::startup() "LogManager::startup()"
+ *
+ * - LOG4QT_CONFIGURATORCLASS<br>
+ * The variable specifies the configurator class used for initialising the
+ * package.
+ *
+ * Environment variables are read during static initialisation on creation of
+ * the \ref Log4Qt::InitialisationHelper "InitialisationHelper". They can be
+ * accessed by calling \ref Log4Qt::InitialisationHelper::environmentSettings()
+ * "InitialisationHelper::environmentSettings()".
+ *
+ * All settings can also be made in the application settings under the group
+ * \c %Log4Qt. For example the environment variable \c LOG4QT_DEBUG is
+ * equivalent to the setting \c Debug. If an environment variable is
+ * set it takes precedence over the application setting. Settings are only
+ * used, if an QApplication object is available, when the
+ * \ref Log4Qt::LogManager "LogManager" is
+ * initialised (see \ref Log4Qt::InitialisationHelper::setting()
+ * "InitialisationHelper::setting()" for details).
+ */
+
+/*!
+ * \page Undocumented Undocumented functions
+ *
+ * In general it was tried to avoid the usage of undocumented features of Qt.
+ * Nice to have features like for example Q_DECLARE_PRIVATE are not used. Only
+ * features that would have been resulted in re-coding the same functionality
+ * are used.
+ *
+ * - QT_WA: The macro is used to call Windows A/W functions
+ * - \ref Log4Qt::DebugAppender "DebugAppender"
+ * - QBasicAtomicPointer: The class is used instead of QAtomicPointer, because
+ * it allows the initialisation as plain old data type.
+ * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC"
+ * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"
+ * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER"
+ * - Q_BASIC_ATOMIC_INITIALIZER: The macro is used to initialise QAtomicPointer
+ * objects as plain old data type.
+ * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC"
+ * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"
+ * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER"
+ */
+
+/*!
+ * \page Assumptions Assumptions
+ *
+ * The following assumptions are used throughout the package:
+ *
+ * - Reading / writing of bool or int is thread-safe, if declared volatile
+ * - \ref Log4Qt::ListAppender "ListAppender"
+ * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton"
+ * - \ref Log4Qt::ConsoleAppender "ConsoleAppender"
+ * - \ref Log4Qt::FileAppender "FileAppender"
+ * - \ref Log4Qt::Hierarchy "Hierarchy"
+ * - \ref Log4Qt::Level "Level"
+ * - \ref Log4Qt::Logger "Logger"
+ * - \ref Log4Qt::WriterAppender "WriterAppender"
+ * - \ref Log4Qt::Layout::format() "Layout::format()" is implemented reentrant
+ * in all sub-classes.
+ * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton"
+ * - Being able to use singleton objects during static de-initialization without
+ * order issues is more valuable then their destruction.
+ * - \ref Log4Qt::LogManager "LogManager"
+ * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC"
+ * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE"
+ */
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#if QT_VERSION < QT_VERSION_CHECK(4, 3, 0)
+# error "Log4Qt requires Qt version 4.3.0 or higher"
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+/*!
+ * \brief The namespace Log4Qt %Log4Qt encloses all parts of the package.
+ */
+namespace Log4Qt
+{
+ /*!
+ * This macro expands a numeric value of the form 0xMMmmPP (MM = major,
+ * mm = minor, PP = patch) that specifies Log4Qt's version number.
+ * This is the version against which the application is compiled.
+ *
+ * \sa \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR",
+ * \ref Log4Qt::LogManager::version() "LogManager::version()"
+ */
+ // Defined in CMakeLists.txt or pro file
+ //#define LOG4QT_VERSION 1.0.0
+
+ /*!
+ * The macro expands to a string that specifies the Log4Qt's version
+ * number. This is the version against which the application is compiled.
+ *
+ * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION",
+ * \ref Log4Qt::LogManager::version() "LogManager::version()"
+ */
+ // Defined in CMakeLists.txt or pro file
+ //#define LOG4QT_VERSION_STR "1.0.0"
+
+
+ enum ErrorCode
+ {
+ OK = 0,
+ // AppenderSkeleton, FileAppender, WriterAppender
+ APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR,
+ APPENDER_ACTIVATE_MISSING_WRITER_ERROR,
+ APPENDER_ACTIVATE_MISSING_FILE_ERROR,
+ APPENDER_CLOSED_ERROR,
+ APPENDER_INVALID_PATTERN_ERROR,
+ APPENDER_NO_OPEN_FILE_ERROR,
+ APPENDER_NOT_ACTIVATED_ERROR,
+ APPENDER_OPENING_FILE_ERROR,
+ APPENDER_RENAMING_FILE_ERROR,
+ APPENDER_REMOVE_FILE_ERROR,
+ APPENDER_USE_INVALID_PATTERN_ERROR,
+ APPENDER_USE_MISSING_LAYOUT_ERROR,
+ APPENDER_USE_MISSING_WRITER_ERROR,
+ APPENDER_WRITING_FILE_ERROR,
+ // Level
+ LEVEL_INVALID_LEVEL_STRING,
+ // Layouts, PatternFormatter
+ LAYOUT_EXPECTED_DIGIT_ERROR,
+ LAYOUT_OPTION_IS_NOT_INTEGER_ERROR,
+ LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR,
+ // Logger
+ LOGGER_INVALID_LEVEL_FOR_ROOT,
+ // PropertyConfigurator, OptionHandler
+ CONFIGURATOR_OPENING_FILE_ERROR,
+ CONFIGURATOR_READING_FILE_ERROR,
+ CONFIGURATOR_INVALID_SUBSTITUTION_ERROR,
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ CONFIGURATOR_MISSING_APPENDER_ERROR,
+ CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR,
+ CONFIGURATOR_MISSING_LAYOUT_ERROR,
+ CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR,
+ CONFIGURATOR_PROPERTY_ERROR,
+ CONFIGURATOR_UNKNOWN_TYPE_ERROR,
+ APPENDER_MISSING_DATABASE_OR_TABLE_ERROR,
+ APPENDER_EXEC_SQL_QUERY_ERROR,
+ APPENDER_INVALID_DATABASE_LAYOUT_ERROR,
+ APPENDER_TELNET_SERVER_NOT_RUNNING,
+ APPENDER_ASNC_DISPATCHER_NOT_RUNNING
+ };
+
+
+ /******************************************************************************
+ * Operators, Helpers
+ ******************************************************************************/
+
+
+ /******************************************************************************
+ * Inline
+ ******************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+#endif // LOG4QT_H
diff --git a/ext/Log4Qt/src/log4qtshared.h b/ext/Log4Qt/src/log4qtshared.h
new file mode 100644
index 0000000..f8bd853
--- /dev/null
+++ b/ext/Log4Qt/src/log4qtshared.h
@@ -0,0 +1,9 @@
+#include <QtCore/QtGlobal>
+
+#if defined(LOG4QT_EXPORTS)
+# define LOG4QT_EXPORT Q_DECL_EXPORT
+#elif defined (LOG4QT_IMPORTS)
+# define LOG4QT_EXPORT Q_DECL_IMPORT
+#else
+# define LOG4QT_EXPORT /**/
+#endif
diff --git a/ext/Log4Qt/src/logger.cpp b/ext/Log4Qt/src/logger.cpp
new file mode 100644
index 0000000..8c66eb0
--- /dev/null
+++ b/ext/Log4Qt/src/logger.cpp
@@ -0,0 +1,1047 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logger.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Fixed problem in Qt 4.4 where QReadWriteLock is by default
+ * non-recursive.
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "logger.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QThread>
+#include <QtCore/QCoreApplication>
+
+#include "appenderskeleton.h"
+#include "varia/listappender.h"
+#include "loggingevent.h"
+#include "log4qt.h"
+#include "loggerrepository.h"
+#include "logmanager.h"
+#include "logstream.h"
+
+namespace Log4Qt {
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+ /**************************************************************************
+ * Class implementation: Logger
+ **************************************************************************/
+
+ Logger::Logger(LoggerRepository* pLoggerRepository, Level level,
+ const QString &rName, Logger *pParent) :
+ QObject(0),
+ mName(rName), mpLoggerRepository(pLoggerRepository), mAdditivity(true),
+ mLevel(level), mpParent(pParent)
+ {
+ Q_ASSERT_X(pLoggerRepository, "Logger::Logger()",
+ "Construction of Logger with null LoggerRepository");
+
+ setObjectName( mName);
+ }
+
+ Logger::~Logger()
+ {
+ logger()->warn("Unexpected destruction of Logger");
+
+ // QWriteLocker locker(&mObjectGuard);
+ //
+ // QMutableListIterator< LogObjectPtr<Appender> > i(mAppenders);
+ // while (i.hasNext())
+ // {
+ // i.next();
+ // i.remove();
+ // }
+ }
+
+ void Logger::setLevel(Level level)
+ {
+ // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe
+
+ if ((parentLogger() == 0) && (level == Level::NULL_INT)) {
+ logger()->warn(
+ "Invalid root logger level NULL_INT. Using DEBUG_INT instead");
+ level = Level::DEBUG_INT;
+ }
+ mLevel = level;
+ }
+
+ // Note: use MainThreadAppender if you want write the log from non-main threads
+ // within the main trhead
+ void Logger::callAppenders(const LoggingEvent &rEvent) const
+ {
+ QReadLocker locker(&mAppenderGuard);
+
+ Appender *p_appender;
+ Q_FOREACH(p_appender, mAppenders)
+ p_appender->doAppend(rEvent);
+ if (additivity() && (parentLogger() != 0))
+ parentLogger()->callAppenders(rEvent);
+ }
+
+ Level Logger::effectiveLevel() const
+ {
+ Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT,
+ "Logger::effectiveLevel()", "Root logger level must not be NULL_INT");
+
+ QReadLocker locker(&mAppenderGuard);
+
+ const Logger *p_logger = this;
+ while (p_logger->level() == Level::NULL_INT)
+ p_logger = p_logger->parentLogger();
+ return p_logger->level();
+ }
+
+ bool Logger::isEnabledFor(Level level) const
+ {
+ if (mpLoggerRepository->isDisabled(level))
+ return false;
+ return (effectiveLevel() <= level);
+ }
+
+ Logger *Logger::logger(const QString &rName)
+ {
+ return LogManager::logger(rName);
+ }
+
+ Logger *Logger::logger(const char *pName)
+ {
+ return LogManager::logger(QLatin1String(pName));
+ }
+
+ Logger *Logger::rootLogger()
+ {
+ return LogManager::rootLogger();
+ }
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug Logger::debug(QDebug &rDebug) const
+ {
+ QReadLocker locker(&mAppenderGuard);
+
+ QString parent_logger;
+ if (mpParent)
+ parent_logger = mpParent->name();
+
+ rDebug.nospace() << "Logger(" << "name:" << name() << " " << "appenders:"
+ << mAppenders.count() << " " << "additivity:" << mAdditivity << " "
+ << mLevel << "parentLogger:" << parent_logger << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+ void Logger::forcedLog(Level level, const QString &rMessage) const
+ {
+ QReadLocker locker(&mAppenderGuard);
+
+ LoggingEvent event(this, level, rMessage);
+ callAppenders(event);
+ }
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const Logger &rLogger)
+ {
+ return rLogger.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ bool Logger::additivity() const
+ { // QReadLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mAdditivity; }
+
+ Level Logger::level() const
+ { // QReadLocker locker(&mObjectGuard); // Level is thread-safe
+ return mLevel; }
+
+ LoggerRepository *Logger::loggerRepository() const
+ { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime
+ return mpLoggerRepository; }
+
+ QString Logger::name() const
+ { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime
+ return mName; }
+
+ Logger *Logger::parentLogger() const
+ { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime
+ return mpParent; }
+
+ void Logger::setAdditivity(bool additivity)
+ { // QWriteLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mAdditivity = additivity; }
+
+ // Level operations
+
+ bool Logger::isDebugEnabled() const
+ { return isEnabledFor(Level::DEBUG_INT); }
+
+ bool Logger::isErrorEnabled() const
+ { return isEnabledFor(Level::ERROR_INT); }
+
+ bool Logger::isFatalEnabled() const
+ { return isEnabledFor(Level::FATAL_INT); }
+
+ bool Logger::isInfoEnabled() const
+ { return isEnabledFor(Level::INFO_INT); }
+
+ bool Logger::isTraceEnabled() const
+ { return isEnabledFor(Level::TRACE_INT); }
+
+ bool Logger::isWarnEnabled() const
+ { return isEnabledFor(Level::WARN_INT); }
+
+ // Log operations: debug
+
+ LogStream Logger::debug() const
+ { return LogStream(*this, Level::DEBUG_INT); }
+
+ void Logger::debug(const LogError &rLogError) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, rLogError.toString()); }
+
+ void Logger::debug(const QString &rMessage) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, rMessage); }
+
+ void Logger::debug(const char *pMessage) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::debug(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::debug(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::DEBUG_INT))
+ forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: error
+
+ LogStream Logger::error() const
+ { return LogStream(*this, Level::ERROR_INT); }
+
+ void Logger::error(const QString &rMessage) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, rMessage); }
+
+ void Logger::error(const LogError &rLogError) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, rLogError.toString()); }
+
+ void Logger::error(const char *pMessage) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::error(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::error(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::error(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::ERROR_INT))
+ forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: fatal
+
+ LogStream Logger::fatal() const
+ { return LogStream(*this, Level::FATAL_INT); }
+
+ void Logger::fatal(const QString &rMessage) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, rMessage); }
+
+ void Logger::fatal(const LogError &rLogError) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, rLogError.toString()); }
+
+ void Logger::fatal(const char *pMessage) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1, const QString &rArg2) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1, int arg2) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::fatal(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::FATAL_INT))
+ forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: info
+
+ LogStream Logger::info() const
+ { return LogStream(*this, Level::INFO_INT); }
+
+ void Logger::info(const QString &rMessage) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, rMessage); }
+
+ void Logger::info(const LogError &rLogError) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, rLogError.toString()); }
+
+ void Logger::info(const char *pMessage) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::info(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::info(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::info(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::INFO_INT))
+ forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: log
+
+ LogStream Logger::log(Level level) const
+ { return LogStream(*this, level); }
+
+ void Logger::log(Level level,
+ const QString &rMessage) const
+ { if (isEnabledFor(level))
+ forcedLog(level, rMessage); }
+
+ void Logger::log(Level level,
+ const LogError &rLogError) const
+ { if (isEnabledFor(level))
+ forcedLog(level, rLogError.toString()); }
+
+ void Logger::log(Level level,
+ const char *pMessage) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1, int arg2) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::log(Level level,
+ const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(level))
+ forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: trace
+
+ LogStream Logger::trace() const
+ { return LogStream(*this, Level::TRACE_INT); }
+
+ void Logger::trace(const QString &rMessage) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, rMessage); }
+
+ void Logger::trace(const LogError &rLogError) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, rLogError.toString()); }
+
+ void Logger::trace(const char *pMessage) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::trace(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::trace(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::TRACE_INT))
+ forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+ // Log operations: warn
+
+ LogStream Logger::warn() const
+ { return LogStream(*this, Level::WARN_INT); }
+
+ void Logger::warn(const QString &rMessage) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, rMessage); }
+
+ void Logger::warn(const LogError &rLogError) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, rLogError.toString()); }
+
+ void Logger::warn(const char *pMessage) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ int arg2) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); }
+
+ void Logger::warn(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); }
+
+ void Logger::warn(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const
+ { if (isEnabledFor(Level::WARN_INT))
+ forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); }
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/logger.h b/ext/Log4Qt/src/logger.h
new file mode 100755
index 0000000..3e04d4e
--- /dev/null
+++ b/ext/Log4Qt/src/logger.h
@@ -0,0 +1,810 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logger.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QBasicAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGGER_H
+#define LOG4QT_LOGGER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include <QtCore/QAtomicPointer>
+#include <QtCore/QList>
+#include <QtCore/QReadWriteLock>
+#include "helpers/logerror.h"
+#include "helpers/classlogger.h"
+#include "helpers/logobjectptr.h"
+#include "helpers/appenderattachable.h"
+#include "level.h"
+#include "logstream.h"
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+# warning "QAtomicPointer test and set is not native. The macro Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER is not thread-safe."
+# endif
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * LOG4QT_DECLARE_STATIC_LOGGER declares a static function \a FUNCTION that
+ * returns a pointer to a \ref Log4Qt::Logger "Logger" named after \a CLASS.
+ *
+ * On the first invocation the \ref Log4Qt::Logger "Logger" is requested
+ * by calling \ref Log4Qt::Logger::logger(const char *pName)
+ * "Logger::logger( #CLASS )". The pointer is stored to be returned on
+ * subsequent invocations.
+ *
+ * The following example shows how to use the macro to define a logger to be
+ * used within a class not derived from QObject.
+ *
+ * \code
+ * #file: counter.h
+ *
+ * #include logger.h
+ *
+ * class Counter
+ * {
+ * public:
+ * Counter();
+ * Counter(int preset);
+ * private:
+ * int mCount;
+ * }
+ * \endcode
+ * \code
+ * #file: counter.cpp
+ *
+ * #include counter.h
+ *
+ * LOG4QT_DECLARE_STATIC_LOGGER(logger, Counter)
+ *
+ * Counter::Counter() :
+ * mCount(0)
+ * {}
+ *
+ * void Counter::Counter(int preset) :
+ * mCount(preset)
+ * {
+ * if (preset < 0)
+ * {
+ * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset);
+ * mCount = 0;
+ * }
+ * }
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)"
+ */
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \
+ static Log4Qt::Logger *FUNCTION() \
+ { \
+ static Log4Qt::Logger *p_logger = 0; \
+ if (!p_logger) \
+ { \
+ q_atomic_test_and_set_ptr( \
+ &p_logger, \
+ 0, \
+ Log4Qt::Logger::logger( #CLASS )); \
+ } \
+ return p_logger; \
+ }
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \
+ static Log4Qt::Logger *FUNCTION() \
+ { \
+ static QBasicAtomicPointer<Log4Qt::Logger > p_logger = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ if (!p_logger) \
+ { \
+ p_logger.testAndSetOrdered(0, \
+ Log4Qt::Logger::logger( #CLASS )); \
+ } \
+ return p_logger; \
+ }
+#else
+#define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \
+ static Log4Qt::Logger *FUNCTION() \
+ { \
+ static QBasicAtomicPointer<Log4Qt::Logger > p_logger = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ if (!p_logger.loadAcquire()) \
+ { \
+ p_logger.testAndSetOrdered(0, \
+ Log4Qt::Logger::logger( #CLASS )); \
+ } \
+ return p_logger.loadAcquire(); \
+ }
+#endif
+
+ /*!
+ * LOG4QT_DECLARE_QCLASS_LOGGER declares member functions to retrieve
+ * \ref Log4Qt::Logger "Logger" for the class it is used in.
+ *
+ * On the first invocation the \ref Log4Qt::Logger "Logger" is requested
+ * by a call to \ref Log4Qt::Logger::logger(const char *pName)
+ * "Logger::logger(const char *pName)". The pointer is stored to be
+ * returned on subsequent invocations.
+ *
+ * The following example shows how to use the macro to define a logger to be
+ * used within a class derived from QObject.
+ *
+ * \code
+ * #file: counter.h
+ *
+ * #include qobject.h
+ * #include logger.h
+ *
+ * class Counter : public QObject
+ * {
+ * Q_OBJECT
+ * LOG4QT_DECLARE_QCLASS_LOGGER
+ * public:
+ * Counter();
+ * Counter(int preset);
+ * private:
+ * int mCount;
+ * }
+ * \endcode
+ * \code
+ * #file: counter.cpp
+ *
+ * #include counter.h
+ *
+ * Counter::Counter() :
+ * mCount(0)
+ * {}
+ *
+ * void Counter::Counter(int preset)
+ * mCount(preset)
+ * {
+ * if (preset < 0)
+ * {
+ * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset);
+ * mCount = 0;
+ * }
+ * }
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)",
+ * \ref Log4Qt::ClassLogger "ClassLogger"
+ */
+ #define LOG4QT_DECLARE_QCLASS_LOGGER \
+ private: \
+ mutable Log4Qt::ClassLogger mLog4QtClassLogger; \
+ public: \
+ inline Log4Qt::Logger *logger() const \
+ { return mLog4QtClassLogger.logger(this); } \
+ private:
+
+ class Appender;
+ class LoggingEvent;
+ class LoggerRepository;
+
+ /*!
+ * \brief The class Logger provides logging services.
+ *
+ * A pointer to a logger can be retrieved by calling Logger::logger() or
+ * LogManager::logger() with the class name as argument. Because a logger
+ * is never destroyed it is possible to store the pointer to the logger.
+ * This way the lookup of the pointer in the repository is only required
+ * on the first logging operation. The macros \ref
+ * Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" and
+ * \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER"
+ * provide a thread-safe implementation to store the logger pointer.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT Logger : public QObject, public AppenderAttachable
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds, if the logger is additive.
+ *
+ * The default is true for being additive.
+ *
+ * \sa additive(), setAdditive()
+ */
+ Q_PROPERTY(bool additivity READ additivity WRITE setAdditivity)
+
+ /*!
+ * The property holds the level used by the logger.
+ *
+ * The default is Level::NULL_INT.
+ * \sa level(), setLevel()
+ */
+ Q_PROPERTY(Log4Qt::Level level READ level WRITE setLevel)
+
+ /*!
+ * The property holds the LoggerRepository of the logger.
+ *
+ * \sa loggerRepository()
+ */
+ Q_PROPERTY(LoggerRepository* loggerRepository READ loggerRepository)
+
+ /*!
+ * The property holds the name of the logger.
+ *
+ * \sa name()
+ */
+ Q_PROPERTY(QString name READ name)
+
+ /*!
+ * The property holds the parent logger of the logger.
+ *
+ * \sa parentLogger()
+ */
+ Q_PROPERTY(Logger* parentLogger READ parentLogger)
+
+ LOG4QT_DECLARE_QCLASS_LOGGER
+
+ protected:
+ Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent = 0);
+ virtual ~Logger();
+ private:
+ Logger(const Logger &rOther); // Not implemented
+ Logger &operator=(const Logger &rOther); // Not implemented
+
+ public:
+ bool additivity() const;
+ Level level() const;
+ LoggerRepository *loggerRepository() const;
+ QString name() const;
+ Logger *parentLogger() const;
+ // JAVA: ResourceBundle *resourceBundle() const;
+ // JAVA: void setResourceBundle(ResourceBundle *pResourceBundle);
+ void setAdditivity(bool additivity);
+ virtual void setLevel(Level level);
+
+ void callAppenders(const LoggingEvent &rEvent) const;
+
+ // JAVA: QString resourceBundleString(const QString &rKey) const;
+
+ Level effectiveLevel() const;
+ bool isDebugEnabled() const;
+
+ /*!
+ * Checks if this logger is enabled for a given Level \a level. If the
+ * logger is enabled the function returns true. Otherwise it returns
+ * false.
+ *
+ * A logger is enabled for a level, if the level is greater or equal
+ * then the repository threshold and greater and equal then the loggers
+ * effective level.
+ *
+ * \sa LoggerRepository::isDisabled(), effectiveLevel()
+ */
+ bool isEnabledFor(Level level) const;
+
+ bool isErrorEnabled() const;
+ bool isFatalEnabled() const;
+ bool isInfoEnabled() const;
+ bool isTraceEnabled() const;
+ bool isWarnEnabled() const;
+
+ LogStream debug() const;
+ void debug(const QString &rMessage) const;
+ void debug(const LogError &rLogError) const;
+ void debug(const char *pMessage) const;
+ void debug(const char *pMessage,
+ const QString &rArg1) const;
+ void debug(const char *pMessage,
+ int arg1) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void debug(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void debug(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void debug(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void debug(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void debug(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void debug(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ LogStream error() const;
+ void error(const QString &rMessage) const;
+ void error(const LogError &rLogError) const;
+ void error(const char *pMessage) const;
+ void error(const char *pMessage,
+ const QString &rArg1) const;
+ void error(const char *pMessage,
+ int arg1) const;
+ void error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void error(const char *pMessage,
+ const QString &rArg1, int arg2) const;
+ void error(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void error(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void error(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void error(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void error(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void error(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void error(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void error(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void error(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void error(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ LogStream fatal() const;
+ void fatal(const QString &rMessage) const;
+ void fatal(const LogError &rLogError) const;
+ void fatal(const char *pMessage) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1) const;
+ void fatal(const char *pMessage,
+ int arg1) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void fatal(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void fatal(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void fatal(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ LogStream info() const;
+ void info(const QString &rMessage) const;
+ void info(const LogError &rLogError) const;
+ void info(const char *pMessage) const;
+ void info(const char *pMessage,
+ const QString &rArg1) const;
+ void info(const char *pMessage,
+ int arg1) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void info(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void info(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void info(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void info(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void info(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void info(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void info(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void info(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ LogStream log(Level level) const;
+ void log(Level level,
+ const QString &rMessage) const;
+ void log(Level level,
+ const LogError &rLogError) const;
+ void log(Level level,
+ const char *pMessage) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void log(Level level,
+ const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void log(Level level,
+ const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void log(Level level,
+ const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ // JAVA: void l7dlog(Level level,
+ // const QString &rKey);
+ // JAVA: void l7dlog(Level level,
+ // const QString &rKey,
+ // const QList<Object *> rParameters);
+
+ LogStream trace() const;
+ void trace(const QString &rMessage) const;
+ void trace(const LogError &rLogError) const;
+ void trace(const char *pMessage) const;
+ void trace(const char *pMessage,
+ const QString &rArg1) const;
+ void trace(const char *pMessage,
+ int arg1) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void trace(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void trace(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void trace(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void trace(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void trace(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void trace(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ LogStream warn() const;
+ void warn(const QString &rMessage) const;
+ void warn(const LogError &rLogError) const;
+ void warn(const char *pMessage) const;
+ void warn(const char *pMessage,
+ const QString &rArg1) const;
+ void warn(const char *pMessage,
+ int arg1) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2) const;
+ void warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2) const;
+ void warn(const char *pMessage,
+ int arg1,
+ int arg2) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ const QString &rArg2,
+ int arg3) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ const QString &rArg3) const;
+ void warn(const char *pMessage,
+ const QString &rArg1,
+ int arg2,
+ int arg3) const;
+ void warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ const QString &rArg3) const;
+ void warn(const char *pMessage,
+ int arg1,
+ const QString &rArg2,
+ int arg3) const;
+ void warn(const char *pMessage,
+ int arg1,
+ int arg2,
+ const QString &rArg3) const;
+ void warn(const char *pMessage,
+ int arg1,
+ int arg2,
+ int arg3) const;
+ void warn(const char *pMessage,
+ const QVariant &rArg1,
+ const QVariant &rArg2,
+ const QVariant &rArg3) const;
+
+ // LogManager operations
+ static Logger *logger(const QString &rName);
+ static Logger *logger(const char *pName);
+ static Logger *rootLogger();
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %Logger(name:"Log4Qt" appenders:0 additivity:true Level("NULL")
+ * parentLogger: "root" )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const Appender &rAppender)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+ friend QDebug operator<<(QDebug debug,
+ const Logger &rLogger);
+#endif // QT_NO_DEBUG_STREAM
+
+ void forcedLog(Level level, const QString &rMessage) const;
+
+ private:
+ const QString mName;
+ LoggerRepository* mpLoggerRepository;
+ volatile bool mAdditivity;
+ Level mLevel;
+ Logger *mpParent;
+
+ // Needs to be friend to create Logger objects
+ friend class Hierarchy;
+ };
+
+
+ /******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Logger
+ *
+ * Writes all object member variables to the given debug stream \a debug and
+ * returns the stream.
+ *
+ * To handle subclassing the function uses the virtual member function debug().
+ * This allows each class to generate its own output.
+ *
+ * \sa QDebug, debug()
+ */
+ QDebug operator<<(QDebug debug,
+ const Logger &rLogger);
+#endif // QT_NO_DEBUG_STREAM
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEinfo(Log4Qt::Logger, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LOGGER_H
diff --git a/ext/Log4Qt/src/loggerrepository.cpp b/ext/Log4Qt/src/loggerrepository.cpp
new file mode 100755
index 0000000..2f19bac
--- /dev/null
+++ b/ext/Log4Qt/src/loggerrepository.cpp
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: loggerrepository.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "loggerrepository.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LoggerRepository
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+ LoggerRepository::~LoggerRepository() {}
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LoggerRepository &rLoggerRepository)
+ {
+ return rLoggerRepository.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/loggerrepository.h b/ext/Log4Qt/src/loggerrepository.h
new file mode 100755
index 0000000..b6d42b6
--- /dev/null
+++ b/ext/Log4Qt/src/loggerrepository.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: loggerrepository.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGGERREPOSITORY_H
+#define LOG4QT_LOGGERREPOSITORY_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QList>
+#include "level.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Logger;
+
+ /*!
+ * \brief The class LoggerRepository is abstract base class for a logger
+ * repository.
+ */
+ class LOG4QT_EXPORT LoggerRepository
+ {
+ public:
+ // LoggerRepository(); // Use compiler default
+ // LoggerRepository(const LoggerRepository &rOther); // Use compiler default
+
+ // LoggerRepository &operator=(const LoggerRepository &rOther); // Use compiler default
+ virtual ~LoggerRepository();
+
+ public:
+ virtual bool exists(const QString &rName) const = 0;
+ virtual Logger *logger(const QString &rName) = 0;
+ // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory);
+ virtual QList<Logger *> loggers() const = 0;
+ virtual Logger *rootLogger() const = 0;
+ virtual Level threshold() const = 0;
+ virtual void setThreshold(Level level) = 0;
+ virtual void setThreshold(const QString &rThreshold) = 0;
+
+ virtual bool isDisabled(Level level) = 0;
+ virtual void resetConfiguration() = 0;
+ virtual void shutdown() = 0;
+
+ // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener);
+ // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const;
+ // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const;
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ *\relates LoggerRepository
+ *
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * The member function is used by
+ * QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository)
+ * to generate class specific output.
+ *
+ * \sa QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository)
+ */
+ virtual QDebug debug(QDebug &rDebug) const = 0;
+ friend QDebug operator<<(QDebug debug,
+ const LoggerRepository &rLoggerRepository);
+#endif
+ };
+
+
+ /******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LoggerRepository
+ * Writes all object member variables to the given debug stream \a debug
+ * and returns the stream.
+ *
+ * To handle subclassing the function uses the virtual member function
+ * debug(). This allows each class to generate its own output.
+ *
+ * \sa QDebug, debug()
+ */
+ QDebug operator<<(QDebug debug,
+ const LoggerRepository &rLoggerRepository);
+#endif
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LoggerRepository, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LOGGERREPOSITORY_H
diff --git a/ext/Log4Qt/src/loggingevent.cpp b/ext/Log4Qt/src/loggingevent.cpp
new file mode 100644
index 0000000..91602bb
--- /dev/null
+++ b/ext/Log4Qt/src/loggingevent.cpp
@@ -0,0 +1,279 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: loggingevent.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "loggingevent.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QByteArray>
+#include <QtCore/QDataStream>
+#include <QtCore/QDebug>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+#include "helpers/datetime.h"
+#include "helpers/initialisationhelper.h"
+#include "logger.h"
+#include "mdc.h"
+#include "ndc.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+ LOG4QT_GLOBAL_STATIC(QMutex, sequence_guard)
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LoggingEvent
+ **************************************************************************/
+
+
+ LoggingEvent::LoggingEvent() :
+ QEvent(eventId),
+ mLevel(Level::NULL_INT),
+ mpLogger(0),
+ mMessage(),
+ mNdc(NDC::peek()),
+ mProperties(MDC::context()),
+ mSequenceNumber(nextSequenceNumber()),
+ mThreadName(),
+ mTimeStamp(DateTime::currentDateTime().toMilliSeconds())
+ {
+ setThreadNameToCurrent();
+ }
+
+
+ LoggingEvent::LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage) :
+ QEvent(eventId),
+ mLevel(level),
+ mpLogger(pLogger),
+ mMessage(rMessage),
+ mNdc(NDC::peek()),
+ mProperties(MDC::context()),
+ mSequenceNumber(nextSequenceNumber()),
+ mThreadName(),
+ mTimeStamp(DateTime::currentDateTime().toMilliSeconds())
+ {
+ setThreadNameToCurrent();
+ }
+
+
+ LoggingEvent::LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage,
+ qint64 timeStamp) :
+ QEvent(eventId),
+ mLevel(level),
+ mpLogger(pLogger),
+ mMessage(rMessage),
+ mNdc(NDC::peek()),
+ mProperties(MDC::context()),
+ mSequenceNumber(nextSequenceNumber()),
+ mThreadName(),
+ mTimeStamp(timeStamp)
+ {
+ setThreadNameToCurrent();
+ }
+
+
+ LoggingEvent::LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage,
+ const QString &rNdc,
+ const QHash<QString, QString> &rProperties,
+ const QString &rThreadName,
+ qint64 timeStamp) :
+ QEvent(eventId),
+ mLevel(level),
+ mpLogger(pLogger),
+ mMessage(rMessage),
+ mNdc(rNdc),
+ mProperties(rProperties),
+ mSequenceNumber(nextSequenceNumber()),
+ mThreadName(rThreadName),
+ mTimeStamp(timeStamp)
+ {
+ }
+
+
+ QString LoggingEvent::loggerName() const
+ {
+ if (mpLogger)
+ return mpLogger->name();
+ else
+ return QString();
+ }
+
+
+ QString LoggingEvent::toString() const
+ {
+ return level().toString() + QLatin1Char(':') + message();
+ }
+
+
+ qint64 LoggingEvent::sequenceCount()
+ {
+ QMutexLocker locker(sequence_guard());
+
+ return msSequenceCount;
+ }
+
+
+ qint64 LoggingEvent::startTime()
+ {
+ return InitialisationHelper::startTime();
+ }
+
+
+ void LoggingEvent::setThreadNameToCurrent()
+ {
+ if (QThread::currentThread())
+ {
+ mThreadName = QThread::currentThread()->objectName();
+ // if object name is not set use thread function address for thread identification
+ if (mThreadName.isEmpty())
+ mThreadName = QString("0x%1").arg((quintptr)(QThread::currentThread()), QT_POINTER_SIZE * 2, 16, QChar('0'));
+ }
+ }
+
+
+ qint64 LoggingEvent::nextSequenceNumber()
+ {
+ QMutexLocker locker(sequence_guard());
+
+ return ++msSequenceCount;
+ }
+
+ qint64 LoggingEvent::msSequenceCount = 0;
+ const QEvent::Type LoggingEvent::eventId = static_cast<QEvent::Type>(QEvent::registerEventType());
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DATASTREAM
+ QDataStream &operator<<(QDataStream &rStream, const LoggingEvent &rLoggingEvent)
+ {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version = 0;
+ stream << version;
+ // version 0 data
+ stream << rLoggingEvent.mLevel
+ << rLoggingEvent.loggerName()
+ << rLoggingEvent.mMessage
+ << rLoggingEvent.mNdc
+ << rLoggingEvent.mProperties
+ << rLoggingEvent.mSequenceNumber
+ << rLoggingEvent.mThreadName
+ << rLoggingEvent.mTimeStamp;
+
+ buffer.close();
+ rStream << buffer.buffer();
+ return rStream;
+ }
+
+
+ QDataStream &operator>>(QDataStream &rStream, LoggingEvent &rLoggingEvent)
+ {
+ QByteArray array;
+ rStream >> array;
+ QBuffer buffer(&array);
+ buffer.open(QIODevice::ReadOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version;
+ stream >> version;
+ // Version 0 data
+ QString logger;
+ stream >> rLoggingEvent.mLevel
+ >> logger
+ >> rLoggingEvent.mMessage
+ >> rLoggingEvent.mNdc
+ >> rLoggingEvent.mProperties
+ >> rLoggingEvent.mSequenceNumber
+ >> rLoggingEvent.mThreadName
+ >> rLoggingEvent.mTimeStamp;
+ if (logger.isEmpty())
+ rLoggingEvent.mpLogger = 0;
+ else
+ rLoggingEvent.mpLogger = Logger::logger(logger);
+
+ buffer.close();
+ return rStream;
+ }
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LoggingEvent &rLoggingEvent)
+ {
+ QString logger;
+ if (rLoggingEvent.logger() != 0)
+ logger = rLoggingEvent.logger()->name();
+
+ debug.nospace() << "LoggingEvent("
+ << "level:" << rLoggingEvent.level().toString() << " "
+ << "logger:" << logger << " "
+ << "message:" << rLoggingEvent.message() << " "
+ << "sequencenumber:" << rLoggingEvent.sequenceNumber() << " "
+ << "threadname:" << rLoggingEvent.threadName() << " "
+ << "timestamp:" << rLoggingEvent.timeStamp()
+ << "(" << DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()) << ")"
+ << "sequenceCount:" << rLoggingEvent.sequenceCount()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/loggingevent.h b/ext/Log4Qt/src/loggingevent.h
new file mode 100644
index 0000000..d06c842
--- /dev/null
+++ b/ext/Log4Qt/src/loggingevent.h
@@ -0,0 +1,223 @@
+/******************************************************************************
+*
+* package: Log4Qt
+* file: loggingevent.h
+* created: September 2007
+* author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+******************************************************************************/
+
+#ifndef LOG4QT_LOG4QTEVENT_H
+#define LOG4QT_LOG4QTEVENT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QDateTime>
+#include <QtCore/QHash>
+#include <QtCore/QMetaType>
+#include <QtCore/QStringList>
+#include <QtCore/QEvent>
+#include "level.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Logger;
+
+ /*!
+ * \brief The class LoggingEvent is the internal representation of a
+ * logging event.
+ *
+ * The class uses milliseconds since 1970-01-01T00:00:00, Coordinated
+ * Universal Time for time values. For converstion from and to QDateTime
+ * use DateTime.
+ */
+ class LOG4QT_EXPORT LoggingEvent : public QEvent
+ {
+ public:
+ static const QEvent::Type eventId;
+ LoggingEvent();
+ LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage);
+ LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage,
+ qint64 timeStamp);
+ LoggingEvent(const Logger *pLogger,
+ Level level,
+ const QString &rMessage,
+ const QString &rNdc,
+ const QHash<QString, QString> &rProperties,
+ const QString &rThreadName,
+ qint64 timeStamp);
+ // LoggingEvent(const LoggingEvent &LoggingEvent::rOther); // Use compiler default
+ // virtual ~LoggingEvent(); // Use compiler default
+ // LoggingEvent &operator=(const LoggingEvent &LoggingEvent::rOther); // Use compiler default
+
+ // JAVA: QString fqnOfLoggerClass() const;
+ Level level() const;
+ // LocationInformation locationInformation() const;
+ const Logger *logger() const;
+ QString message() const;
+ QHash<QString, QString> mdc() const;
+ QString ndc() const;
+ QHash<QString, QString> properties() const;
+ qint64 sequenceNumber() const;
+ QString threadName() const;
+ // JAVA: ThrowableInformation throwableInformation() const;
+ qint64 timeStamp() const;
+
+ // JAVA: bool locationInformationExists() const;
+ QString loggerName() const;
+ QString property(const QString &rKey) const;
+ QStringList propertyKeys() const;
+ void setProperty(const QString &rKey, const QString &rValue);
+ // JAVA: QString throwableStrRep() const;
+ QString toString() const;
+ static qint64 sequenceCount();
+ static qint64 startTime();
+
+ private:
+ void setThreadNameToCurrent();
+ static qint64 nextSequenceNumber();
+
+ private:
+ Level mLevel;
+ const Logger *mpLogger;
+ QString mMessage;
+ QString mNdc;
+ QHash<QString, QString> mProperties;
+ qint64 mSequenceNumber;
+ QString mThreadName;
+ qint64 mTimeStamp;
+ static qint64 msSequenceCount;
+
+#ifndef QT_NO_DATASTREAM
+ // Needs to be friend to stream objects
+ friend QDataStream &operator<<(QDataStream &rStream,
+ const LoggingEvent &rLoggingEvent);
+ friend QDataStream &operator>>(QDataStream &rStream,
+ LoggingEvent &rLoggingEvent);
+#endif // QT_NO_DATASTREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+ /*!
+ * \relates LoggingEvent
+ *
+ * Writes the given error \a rLoggingEvent to the given stream \a rStream,
+ * and returns a reference to the stream.
+ */
+ QDataStream &operator<<(QDataStream &rStream,
+ const LoggingEvent &rLoggingEvent);
+
+ /*!
+ * \relates LoggingEvent
+ *
+ * Reads an error from the given stream \a rStream into the given
+ * error \a rLoggingEvent, and returns a reference to the stream.
+ */
+ QDataStream &operator>>(QDataStream &rStream,
+ LoggingEvent &rLoggingEvent);
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LoggingEvent
+ *
+ * Writes all object member variables to the given debug stream \a debug and
+ * returns the stream.
+ *
+ * <tt>
+ * %LoggingEvent(level:"WARN" logger:"Log4Qt::Properties"
+ * message:"Unknown escape sequence '\j' in property starting at line 1"
+ * sequencenumber:14 threadname:"main"
+ * timestamp:1194337148937(QDateTime("Tue Nov 6 03:19:08 2007") )
+ * sequenceCount: 14 )
+ * </tt>
+ *
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const LoggingEvent &rLoggingEvent);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Level LoggingEvent::level() const
+ { return mLevel; }
+
+ inline const Logger *LoggingEvent::logger() const
+ { return mpLogger; }
+
+ inline QString LoggingEvent::message() const
+ { return mMessage; }
+
+ inline QHash<QString, QString> LoggingEvent::mdc() const
+ { return mProperties; }
+
+ inline QString LoggingEvent::ndc() const
+ { return mNdc; }
+
+ inline QHash<QString, QString> LoggingEvent::properties() const
+ { return mProperties; }
+
+ inline qint64 LoggingEvent::sequenceNumber() const
+ { return mSequenceNumber; }
+
+ inline QString LoggingEvent::threadName() const
+ { return mThreadName; }
+
+ inline qint64 LoggingEvent::timeStamp() const
+ { return mTimeStamp; }
+
+ inline QString LoggingEvent::property(const QString &rKey) const
+ { return mProperties.value(rKey); }
+
+ inline QStringList LoggingEvent::propertyKeys() const
+ { return QStringList(mProperties.keys()); }
+
+ inline void LoggingEvent::setProperty(const QString &rKey, const QString &rValue)
+ { mProperties.insert(rKey, rValue); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_METATYPE(Log4Qt::LoggingEvent)
+Q_DECLARE_TYPEINFO(Log4Qt::LoggingEvent, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_LOG4QTEVENT_H
diff --git a/ext/Log4Qt/src/logmanager.cpp b/ext/Log4Qt/src/logmanager.cpp
new file mode 100755
index 0000000..5d47c6f
--- /dev/null
+++ b/ext/Log4Qt/src/logmanager.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logmanager.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Resolved compilation problem with Microsoft Visual Studio 2005
+ * Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "logmanager.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QMutex>
+#include <QtCore/QSettings>
+#include <QtCore/QStringList>
+#include "consoleappender.h"
+#include "helpers/datetime.h"
+#include "helpers/initialisationhelper.h"
+#include "helpers/optionconverter.h"
+#include "hierarchy.h"
+#include "propertyconfigurator.h"
+#include "ttcclayout.h"
+#include "varia/denyallfilter.h"
+#include "varia/levelrangefilter.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager)
+ LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard)
+
+
+
+ /**************************************************************************
+ * Class implementation: LogManager
+ **************************************************************************/
+
+
+ LogManager::LogManager() :
+ mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger()
+ mpLoggerRepository(new Hierarchy()),
+ mHandleQtMessages(false),
+ mOldQtMsgHandler(0)
+ {
+ }
+
+
+ LogManager::~LogManager()
+ {
+ static_logger()->warn("Unexpected destruction of LogManager");
+
+ // doSetConfigureHandleQtMessages(false);
+ // delete mpLoggerRepository;
+ }
+
+
+ Logger *LogManager::rootLogger()
+ {
+ return instance()->mpLoggerRepository->rootLogger();
+ }
+
+
+ QList<Logger*> LogManager::loggers()
+ {
+ return instance()->mpLoggerRepository->loggers();
+ }
+
+
+ Level LogManager::threshold()
+ {
+ return instance()->mpLoggerRepository->threshold();
+ }
+
+
+ void LogManager::setThreshold(Level level)
+ {
+ instance()->mpLoggerRepository->setThreshold(level);
+ }
+
+
+ bool LogManager::exists(const char *pName)
+ {
+ return instance()->mpLoggerRepository->exists(QLatin1String(pName));
+ }
+
+
+ LogManager *LogManager::instance()
+ {
+ // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive
+ // to construct, an exit handler must be set and doStartup must be
+ // called.
+
+ if (!mspInstance)
+ {
+ QMutexLocker locker(singleton_guard());
+ if (!mspInstance)
+ {
+ mspInstance = new LogManager;
+ // qAddPostRoutine(shutdown);
+ atexit(shutdown);
+ mspInstance->doConfigureLogLogger();
+ mspInstance->welcome();
+ mspInstance->doStartup();
+ }
+ }
+ return mspInstance;
+ }
+
+
+ Logger *LogManager::logger(const QString &rName)
+ {
+ return instance()->mpLoggerRepository->logger(rName);
+ }
+
+
+ void LogManager::resetConfiguration()
+ {
+ setHandleQtMessages(false);
+ instance()->mpLoggerRepository->resetConfiguration();
+ configureLogLogger();
+ }
+
+
+ const char* LogManager::version()
+ {
+ return LOG4QT_VERSION_STR;
+ }
+
+
+ void LogManager::shutdown()
+ {
+ instance()->mpLoggerRepository->shutdown();
+ }
+
+
+ void LogManager::doSetHandleQtMessages(bool handleQtMessages)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (instance()->mHandleQtMessages == handleQtMessages)
+ return;
+
+ instance()->mHandleQtMessages = handleQtMessages;
+ if (instance()->mHandleQtMessages)
+ {
+ static_logger()->trace("Activate Qt message handling");
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler);
+#else
+ instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler);
+#endif
+
+ }
+ else
+ {
+ static_logger()->trace("Deactivate Qt message handling");
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ qInstallMsgHandler(instance()->mOldQtMsgHandler);
+#else
+ qInstallMessageHandler(instance()->mOldQtMsgHandler);
+#endif
+ }
+ }
+
+
+ void LogManager::doConfigureLogLogger()
+ {
+ QMutexLocker locker(&instance()->mObjectGuard);
+
+ // Level
+ QString value = InitialisationHelper::setting(QLatin1String("Debug"),
+ QLatin1String("ERROR"));
+ logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT));
+
+ // Common layout
+ TTCCLayout *p_layout = new TTCCLayout();
+ p_layout->setName(QLatin1String("LogLog TTCC"));
+ p_layout->setContextPrinting(false);
+ p_layout->activateOptions();
+
+ // Common deny all filter
+ Filter *p_denyall = new DenyAllFilter();
+ p_denyall->activateOptions();
+
+ // ConsoleAppender on stdout for all events <= INFO
+ ConsoleAppender *p_appender;
+ LevelRangeFilter *p_filter;
+ p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET);
+ p_filter = new LevelRangeFilter();
+ p_filter->setNext(p_denyall);
+ p_filter->setLevelMin(Level::NULL_INT);
+ p_filter->setLevelMax(Level::INFO_INT);
+ p_filter->activateOptions();
+ p_appender->setName(QLatin1String("LogLog stdout"));
+ p_appender->addFilter(p_filter);
+ p_appender->activateOptions();
+ logLogger()->addAppender(p_appender);
+
+ // ConsoleAppender on stderr for all events >= WARN
+ p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET);
+ p_filter = new LevelRangeFilter();
+ p_filter->setNext(p_denyall);
+ p_filter->setLevelMin(Level::WARN_INT);
+ p_filter->setLevelMax(Level::OFF_INT);
+ p_filter->activateOptions();
+ p_appender->setName(QLatin1String("LogLog stderr"));
+ p_appender->addFilter(p_filter);
+ p_appender->activateOptions();
+ logLogger()->addAppender(p_appender);
+ }
+
+
+ void LogManager::doStartup()
+ {
+ QMutexLocker locker(&instance()->mObjectGuard);
+
+ // Override
+ QString default_value = QLatin1String("false");
+ QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"),
+ default_value);
+ if (value != default_value)
+ {
+ static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation");
+ return;
+ }
+
+ // Configuration using setting Configuration
+ value = InitialisationHelper::setting(QLatin1String("Configuration"));
+ if (QFile::exists(value))
+ {
+ static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value);
+ PropertyConfigurator::configure(value);
+ return;
+ }
+
+ // Configuration using setting
+ if (QCoreApplication::instance())
+ {
+ const QLatin1String log4qt_group("Log4Qt");
+ const QLatin1String properties_group("Properties");
+ QSettings s;
+ s.beginGroup(log4qt_group);
+ if (s.childGroups().contains(properties_group))
+ {
+ const QString group(QLatin1String("Properties"));
+ static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group);
+ s.beginGroup(properties_group);
+ PropertyConfigurator::configure(s);
+ return;
+ }
+ }
+
+ // Configuration using default file
+ const QString default_file(QLatin1String("log4qt.properties"));
+ if (QFile::exists(default_file))
+ {
+ static_logger()->debug("Default initialisation configures from default file '%1'", default_file);
+ PropertyConfigurator::configure(default_file);
+ return;
+ }
+
+ static_logger()->debug("Default initialisation leaves package unconfigured");
+ }
+
+
+ void LogManager::welcome()
+ {
+ static_logger()->info("Initialising Log4Qt %1",
+ QLatin1String(LOG4QT_VERSION_STR));
+
+ // Debug: Info
+ if (static_logger()->isDebugEnabled())
+ {
+ // Create a nice timestamp with UTC offset
+ DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime());
+ QString offset;
+ {
+ QDateTime utc = start_time.toUTC();
+ QDateTime local = start_time.toLocalTime();
+ QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC);
+ int min = utc.secsTo(local_as_utc) / 60;
+ if (min < 0)
+ offset += QLatin1Char('-');
+ else
+ offset += QLatin1Char('+');
+ min = abs(min);
+ offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0'));
+ offset += QLatin1Char(':');
+ offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0'));
+ }
+ static_logger()->debug("Program startup time is %1 (UTC%2)",
+ start_time.toString(QLatin1String("ISO8601")),
+ offset);
+ static_logger()->debug("Internal logging uses the level %1",
+ logLogger()->level().toString());
+ }
+
+ // Trace: Dump settings
+ if (static_logger()->isTraceEnabled())
+ {
+ static_logger()->trace("Settings from the system environment:");
+ QString entry;
+ Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ InitialisationHelper::environmentSettings().value(entry));
+
+ static_logger()->trace("Settings from the application settings:");
+ if (QCoreApplication::instance())
+ {
+ const QLatin1String log4qt_group("Log4Qt");
+ const QLatin1String properties_group("Properties");
+ static_logger()->trace(" %1:", log4qt_group);
+ QSettings s;
+ s.beginGroup(log4qt_group);
+ Q_FOREACH (entry, s.childKeys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ s.value(entry).toString());
+ static_logger()->trace(" %1/%2:", log4qt_group, properties_group);
+ s.beginGroup(properties_group);
+ Q_FOREACH (entry, s.childKeys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ s.value(entry).toString());
+ } else
+ static_logger()->trace(" QCoreApplication::instance() is not available");
+ }
+ }
+
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage)
+ {
+#else
+ void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & pMessage)
+ {
+#endif
+ Level level;
+ switch (type)
+ {
+ case QtDebugMsg:
+ level = Level::DEBUG_INT;
+ break;
+ case QtWarningMsg:
+ level = Level::WARN_INT;
+ break;
+ case QtCriticalMsg:
+ level = Level::ERROR_INT;
+ break;
+ case QtFatalMsg:
+ level = Level::FATAL_INT;
+ break;
+ default:
+ level = Level::TRACE_INT;
+ }
+ instance()->qtLogger()->log(level, pMessage);
+
+ // Qt fatal behaviour copied from global.cpp qt_message_output()
+ // begin {
+
+ if ((type == QtFatalMsg) ||
+ ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) )
+ {
+#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
+ // get the current report mode
+ int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
+ _CrtSetReportMode(_CRT_ERROR, reportMode);
+ int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage);
+ if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
+ return; // ignore
+ else if (ret == 1)
+ _CrtDbgBreak();
+#endif
+
+#if defined(Q_OS_UNIX) && defined(QT_DEBUG)
+ abort(); // trap; generates core dump
+#else
+ exit(1); // goodbye cruel world
+#endif
+ }
+
+ // } end
+ }
+
+
+ LogManager *LogManager::mspInstance = 0;
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const LogManager &rLogManager)
+ {
+ Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008
+ QList<Logger *> loggers = rLogManager.loggers();
+ debug.nospace() << "LogManager("
+ << "loggerrepository:" << *rLogManager.loggerRepository()
+ << "log-level:" << rLogManager.logLogger()->level().toString()
+ << "log-appenders:" << rLogManager.logLogger()->appenders().count()
+ << "qt-level:" << rLogManager.qtLogger()->level().toString()
+ << "qt-appenders:" << rLogManager.qtLogger()->appenders().count()
+ << "handleqtmessages:" << rLogManager.handleQtMessages()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/logmanager.h b/ext/Log4Qt/src/logmanager.h
new file mode 100755
index 0000000..641f658
--- /dev/null
+++ b/ext/Log4Qt/src/logmanager.h
@@ -0,0 +1,337 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logmanager.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGMANAGER_H
+#define LOG4QT_LOGMANAGER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include <QtCore/QString>
+#include "level.h"
+#include "logger.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class LoggerRepository;
+
+ /*!
+ * \brief The class LogManager manages Logger in the default
+ * LoggerRepository.
+ *
+ * The LogManager manages logger in a single Hierarchy instance. It
+ * provides access to special logger over the logLogger(), qtLogger()
+ * and rootLogger() member functions.
+ *
+ * The LogManager is handling the initialisation on startup. The
+ * initialisation procedure will first attempt to configure the package
+ * based on environment variables. If the attempt fails it will check for
+ * the existence of configuration files in several location. For detailed
+ * description of the initialisation procedure see \ref Init
+ * "Initialization procedure".
+ *
+ * Messages created by qDebug(), qWarning(), qCritical() and qFatal() can
+ * be can be handled by the LogManager. By default the message handling
+ * is disabled. It can be enabled by calling setHandleQtMessages(). Once
+ * enabled all messages are logged using the logger qtLogger().
+ *
+ * The Log4Qt runtime version is accessible over version(). The macros
+ * \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION" and
+ * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" provide the
+ * compile time version.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT LogManager
+ {
+ private:
+ LogManager();
+ LogManager(const LogManager &rOther); // Not implemented
+ virtual ~LogManager();
+ LogManager &operator=(const LogManager &rOther); // Not implemented
+
+ public:
+ /*!
+ * Returns if the handling of messages created by calls to qDebug(),
+ * qWarning(), qCritical() and qFatal() is activated.
+ *
+ * \sa setHandleQtMessages()
+ */
+ static bool handleQtMessages();
+
+ static LoggerRepository *loggerRepository();
+
+ /*!
+ * Returns the logger used for logging internal messages. See
+ * \ref LogLog "Logging within the package" for more details.
+ *
+ * Calling this function is equivalent to calling logger("Log4Qt").
+ */
+ static Logger *logLogger();
+
+ /*!
+ * Returns a pointer to the logger used for logging messages created by
+ * calls to qDebug(), qWarning(), qCritical() and qFatal().
+ *
+ * Calling this function is equivalent to calling logger("Qt").
+ *
+ * \sa setHandleQtMessages()
+ */
+ static Logger *qtLogger();
+
+ static Logger *rootLogger();
+ static QList<Logger*> loggers();
+ static Level threshold();
+ static void setThreshold(Level level);
+
+ /*!
+ * Activates or deactivates the handling of messages created by calls
+ * to qDebug(), qWarning(), qCritical() and qFatal() is activated.
+ *
+ * If activated, a Qt message handler is installed. Messages are logged
+ * using the logger returned by qtLogger(). For fatal messages the same
+ * exit procedure is implemented as for qFatal().
+ *
+ * The following mappping is used from QtMsgType to Level:
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th> &nbsp;&nbsp;&nbsp; QtMsgType &nbsp;&nbsp;&nbsp;</th>
+ * <th> %Level </th>
+ * </tr><tr>
+ * <td> QtDebugMsg </td>
+ * <td> Level::DEBUG_INT </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> QtWarningMsg </td>
+ * <td> Level::WARN_INT </td>
+ * </tr><tr>
+ * <td> QtCriticalMsg </td>
+ * <td> Level::ERROR_INT </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> QtFatalMsg </td>
+ * <td> Level::FATAL_INT </td>
+ * </tr><tr>
+ * <td> QtSystemMsg </td>
+ * <td> Level::TRACE_INT </td>
+ * </tr>
+ * </table>
+ *
+ * The default value is false for not handling Qt messages.
+ *
+ * \sa handleQtMessages(), qInstallMsgHandler(), qFatal()
+ */
+ static void setHandleQtMessages(bool handleQtMessages);
+
+ /*!
+ * Configures the logging for the package to its default behaviour.
+ *
+ * The logger logLogger() is configured to be not additive. Messages
+ * with the level Level::ERROR_INT and Level::FATAL_INT are written
+ * to \c stderr using a ConsoleAppender. The remaining messages are
+ * written to \c stdout using a second ConsoleAppender. The level is
+ * read from the system environment or application settings using
+ * InitialisationHelper::setting() with the key \c Debug. If a level
+ * value is found, but it is not a valid Level string,
+ * Level::DEBUG_INT is used. If no level string is found
+ * Level::ERROR_INT is used.
+ *
+ * The function does not remove any appender from the logger
+ * logLogger().
+ *
+ * \sa \ref LogLog "Logging within the package",
+ * \ref Env "Environment Variables",
+ * resetConfiguration(), InitialisationHelper::setting()
+ */
+ static void configureLogLogger();
+
+ static bool exists(const char *pName);
+ // JAVA: void fireAddAppenderEvent(Logger *pLogger, Appender *pAppender);
+
+ /*!
+ * Returns the LogManager instance.
+ */
+ static LogManager *instance();
+
+ static Logger *logger(const QString &rName);
+
+ /*!
+ * Reset all values contained in logger repository to their default.
+ *
+ * All appenders are removed from all loggers. The loggers are handled
+ * in no particular order. The last loggers to be reset are qtLogger(),
+ * logLogger() and rootLogger() in that order.
+ *
+ * The handling of messages created by calls to qDebug(), qWarning(),
+ * qCritical() and qFatal() is deactivated.
+ *
+ * The internal logging is initialised to its default bahaviour
+ * using configureLogLogger().
+ *
+ * \sa LoggerRepository::resetConfiguration(), setHandleQtMessages(),
+ * configureLogLogger()
+ */
+ static void resetConfiguration();
+
+ static void shutdown();
+
+ /*!
+ * Executes the default initialisation procedure of the package.
+ *
+ * The function will test for the setting \c DefaultInitOverride in
+ * the system environment and application settings using
+ * \ref InitialisationHelper::setting(). If the value is present and
+ * set to anything else then \c false, the initialisation is aborted.
+ * <br>
+ * The system environment and application settings are tested for the
+ * setting \c Configuration. If it is found and it is a valid path to
+ * a file, the package is configured with the file using
+ * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *)
+ * "PropertyConfigurator::doConfigure()". If the setting
+ * \c Configuration is not available and a QCoreApplication object is
+ * present, the application settings are tested for a group
+ * \c Properties. If the group exists, the package is configured
+ * with the setting using the
+ * \ref PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *)
+ * "PropertyConfiguratordoConfigure()". If neither a configuration
+ * file nor configuration settings could be found, the current working
+ * directory is searched for the file \c "log4qt.properties". If it is
+ * found, the package is configured with the file using
+ * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *)
+ * "PropertyConfigurator::doConfigure()".
+ *
+ * \sa \ref Init "Initialization procedure",
+ * \ref Env "Environment Variables",
+ * InitialisationHelper::setting()
+ */
+ static void startup();
+
+ /*!
+ * Returns the version number of Log4Qt at run-time. This may be a
+ * different version than the version the application was compiled
+ * against.
+ *
+ * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION",
+ * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR"
+
+ */
+ static const char* version();
+
+ private:
+ void doSetHandleQtMessages(bool handleQtMessages);
+ void doConfigureLogLogger();
+ void doStartup();
+ void welcome();
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ static void qtMessageHandler(QtMsgType type,
+ const char *pMessage);
+#else
+ static void qtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & pMessage);
+#endif
+
+ private:
+ mutable QMutex mObjectGuard;
+ LoggerRepository *mpLoggerRepository;
+ Logger *mpNullLogger;
+ bool mHandleQtMessages;
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ QtMsgHandler mOldQtMsgHandler;
+#else
+ QtMessageHandler mOldQtMsgHandler;
+#endif
+ static LogManager *mspInstance;
+ };
+
+
+ /***************************************************************************
+ * Operators, Helper
+ ***************************************************************************/
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LogManager
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %LogManager(loggerrepository:Hierarchy(loggers:6 root-level:"DEBUG"
+ * root-appenders:0 log-level: "NULL" log-appenders:0
+ * qt-level: "NULL" qt-appenders:0 handleqtmessages: false )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const LogManager &rLogManager);
+ #endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline LoggerRepository *LogManager::loggerRepository()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return instance()->mpLoggerRepository; }
+
+ inline bool LogManager::handleQtMessages()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Read/Write of bool is safe
+ return instance()->mHandleQtMessages; }
+
+ inline Logger *LogManager::logLogger()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return logger(QLatin1String("Log4Qt")); }
+
+ inline Logger *LogManager::qtLogger()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return logger(QLatin1String("Qt")); }
+
+ inline void LogManager::setHandleQtMessages(bool handleQtMessages)
+ { instance()->doSetHandleQtMessages(handleQtMessages); }
+
+ inline void LogManager::configureLogLogger()
+ { instance()->doConfigureLogLogger(); }
+
+ inline void LogManager::startup()
+ { instance()->doStartup(); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LogManager, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LOGMANAGER_H
diff --git a/ext/Log4Qt/src/logstream.cpp b/ext/Log4Qt/src/logstream.cpp
new file mode 100644
index 0000000..ed62660
--- /dev/null
+++ b/ext/Log4Qt/src/logstream.cpp
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logstream.h
+ * created: March, 2011
+ * author: Tim Besard
+ *
+ *
+ * Copyright 2011 Tim Besard
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "logstream.h"
+#include "logger.h"
+
+
+namespace Log4Qt {
+
+ /**************************************************************************
+ * Class implementation: Logger
+ **************************************************************************/
+
+ LogStream::~LogStream()
+ {
+ if (!--stream->ref) {
+ switch (mLevel.toInt())
+ {
+ case Level::TRACE_INT:
+ mLogger.trace(stream->buffer);
+ break;
+ case Level::DEBUG_INT:
+ mLogger.debug(stream->buffer);
+ break;
+ case Level::INFO_INT:
+ mLogger.info(stream->buffer);
+ break;
+ case Level::WARN_INT:
+ mLogger.warn(stream->buffer);
+ break;
+ case Level::ERROR_INT:
+ mLogger.error(stream->buffer);
+ break;
+ case Level::FATAL_INT:
+ mLogger.fatal(stream->buffer);
+ break;
+ }
+ delete stream;
+ }
+ }
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/logstream.h b/ext/Log4Qt/src/logstream.h
new file mode 100644
index 0000000..a0e355c
--- /dev/null
+++ b/ext/Log4Qt/src/logstream.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logstream.h
+ * created: March, 2011
+ * author: Tim Besard
+ *
+ *
+ * Copyright 2011 Tim Besard
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGSTREAM_H
+#define LOG4QT_LOGSTREAM_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QTextStream>
+#include <QtCore/QString>
+#include "level.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+ class Logger;
+
+ class LOG4QT_EXPORT LogStream
+ {
+
+ private:
+ struct Stream {
+ Stream() : ts(&buffer, QIODevice::WriteOnly), ref(1) {}
+ QTextStream ts;
+ QString buffer;
+ int ref;
+ } *stream;
+
+ public:
+ inline LogStream(const Logger& iLogger, Level iLevel) : stream(new Stream()), mLogger(iLogger), mLevel(iLevel)
+ {
+ }
+ inline LogStream(const LogStream &o):stream(o.stream),mLogger(o.mLogger),mLevel(o.mLevel)
+ {
+ ++stream->ref;
+ }
+ ~LogStream();
+
+ inline LogStream &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return *this; }
+#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
+ inline LogStream &operator<<(QBool t) { stream->ts << (bool(t != 0) ? "true" : "false"); return *this; }
+#endif
+ inline LogStream &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return *this; }
+ inline LogStream &operator<<(char t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(signed short t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(unsigned short t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(signed int t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(unsigned int t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(signed long t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(unsigned long t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(qint64 t) { stream->ts << QString::number(t); return *this; }
+ inline LogStream &operator<<(quint64 t) { stream->ts << QString::number(t); return *this; }
+ inline LogStream &operator<<(float t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(double t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(const char* t) { stream->ts << QString::fromLatin1(t); return *this; }
+ inline LogStream &operator<<(const QString & t) { stream->ts << t ; return *this; }
+ inline LogStream &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
+ inline LogStream &operator<<(const QLatin1String &t) { stream->ts << t.latin1(); return *this; }
+ inline LogStream &operator<<(const QByteArray & t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(const void * t) { stream->ts << t; return *this; }
+ inline LogStream &operator<<(QTextStreamFunction f) { stream->ts << f; return *this; }
+ inline LogStream &operator<<(QTextStreamManipulator m) { stream->ts << m; return *this; }
+
+ private:
+ const Logger& mLogger;
+ Level mLevel;
+ };
+}
+
+#endif // LOG4QT_LOGSTREAM_H
diff --git a/ext/Log4Qt/src/mainthreadappender.cpp b/ext/Log4Qt/src/mainthreadappender.cpp
new file mode 100644
index 0000000..5417aa7
--- /dev/null
+++ b/ext/Log4Qt/src/mainthreadappender.cpp
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: mainthreadappender.cpp
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "mainthreadappender.h"
+#include "loggingevent.h"
+#include "helpers/dispatcher.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QReadLocker>
+
+namespace Log4Qt
+{
+
+/**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+/**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Class implementation: MainThreadAppender
+ **************************************************************************/
+
+
+MainThreadAppender::MainThreadAppender(QObject *parent) : AppenderSkeleton(parent)
+{}
+
+MainThreadAppender::~MainThreadAppender()
+{
+ close();
+}
+
+bool MainThreadAppender::requiresLayout() const
+{
+ return false;
+}
+
+void MainThreadAppender::activateOptions()
+{
+}
+
+void MainThreadAppender::close()
+{
+}
+
+void MainThreadAppender::append(const LoggingEvent &rEvent)
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ Appender *pAppender;
+ Q_FOREACH(pAppender, mAppenders)
+ {
+ if (QThread::currentThread() != qApp->thread())
+ {
+ LoggingEvent *event = new LoggingEvent(rEvent);
+ qApp->postEvent(pAppender, event);
+
+ }
+ else
+ pAppender->doAppend(rEvent);
+ }
+}
+
+bool MainThreadAppender::checkEntryConditions() const
+{
+ return AppenderSkeleton::checkEntryConditions();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %MainThreadAppender(name:"WA" )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+QDebug MainThreadAppender::debug(QDebug &rDebug) const
+{
+ rDebug.nospace() << "MainThreadAppender("
+ << "name:" << name() << " "
+ << ")";
+
+ return rDebug.space();
+}
+#endif // QT_NO_DEBUG_STREAM
+
+
+/**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/mainthreadappender.h b/ext/Log4Qt/src/mainthreadappender.h
new file mode 100644
index 0000000..1e26955
--- /dev/null
+++ b/ext/Log4Qt/src/mainthreadappender.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: mainthreadappender.h
+ * created: Febrary 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_MAINTHREADAPPENDER_H
+#define LOG4QT_MAINTHREADAPPENDER_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+#include "helpers/appenderattachable.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QMutex>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+/*!
+ * \brief The class MainThreadAppender uses the QEvent system to write
+ * log from not main threads within the main thread.
+ *
+ *
+ * \note All the functions declared in this class are thread-safe.
+ * &nbsp;
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+class LOG4QT_EXPORT MainThreadAppender : public AppenderSkeleton, public AppenderAttachable
+{
+Q_OBJECT
+
+public:
+ MainThreadAppender(QObject *parent = 0);
+ virtual ~MainThreadAppender();
+
+ virtual bool requiresLayout() const;
+
+ virtual void activateOptions();
+ virtual void close();
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * AppenderSkeleton::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - none
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %MainThreadAppender(name:"WA" encoding:"" immediateFlush:true
+ * isactive:false isclosed:false layout:"TTCC"
+ * referencecount:1 threshold:"NULL"
+ * writer:0x0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+private:
+ Q_DISABLE_COPY(MainThreadAppender)
+
+};
+
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::MainThreadAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif
diff --git a/ext/Log4Qt/src/mdc.cpp b/ext/Log4Qt/src/mdc.cpp
new file mode 100755
index 0000000..3a1e26d
--- /dev/null
+++ b/ext/Log4Qt/src/mdc.cpp
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: mdc.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "mdc.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+#include "helpers/initialisationhelper.h"
+#include "logger.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: MDC
+ **************************************************************************/
+
+
+ QString MDC::get(const QString &rKey)
+ {
+ if (!instance()->mHash.hasLocalData())
+ return QString();
+
+ return instance()->mHash.localData()->value(rKey);
+ }
+
+
+ QHash<QString, QString> MDC::context()
+ {
+ if (!instance()->mHash.hasLocalData())
+ return QHash<QString, QString>();
+
+ return *instance()->mHash.localData();
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(MDC)
+
+
+ QHash<QString, QString> *MDC::localData()
+ {
+ if (!instance()->mHash.hasLocalData())
+ instance()->mHash.setLocalData(new QHash<QString, QString>);
+ return instance()->mHash.localData();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const MDC &rMDC)
+ {
+ Q_UNUSED(rMDC); // To avoid warning C4100 on VS 2008
+ debug.nospace() << "MDC("
+ << "thread:" << QThread::currentThread()->objectName() << " "
+ << "context:" << rMDC.context()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/mdc.h b/ext/Log4Qt/src/mdc.h
new file mode 100755
index 0000000..f4d7abc
--- /dev/null
+++ b/ext/Log4Qt/src/mdc.h
@@ -0,0 +1,122 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: mdc.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_MDC_H
+#define LOG4QT_MDC_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include <QtCore/QHash>
+#include <QtCore/QThreadStorage>
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+
+/*!
+ * \brief The class MDC implements a mapped diagnostic context.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT MDC
+ {
+ private:
+ MDC();
+ MDC(const MDC &rOther); // Not implemented
+ // virtual ~MDC(); // Use compiler default
+ MDC &operator=(const MDC &rOther); // Not implemented
+
+ public:
+ static QString get(const QString &rKey);
+ static QHash<QString, QString> context();
+
+ /*!
+ * Returns the MDC instance.
+ */
+ static MDC *instance();
+
+ static void put(const QString &rKey, const QString &rValue);
+ static void remove(const QString &rKey);
+
+ private:
+ static QHash<QString, QString> *localData();
+
+ private:
+ QThreadStorage< QHash<QString, QString> * > mHash;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates MDC
+ *
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %MDC(thread:"main" context:QHash(("login", "Peter")("database", "UAT")) )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const MDC &rMDC);
+ #endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline MDC::MDC() :
+ mHash()
+ {}
+
+ inline void MDC::put(const QString &rKey, const QString &rValue)
+ { localData()->insert(rKey, rValue); }
+
+ inline void MDC::remove(const QString &rKey)
+ { localData()->remove(rKey); }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::MDC, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_MDC_H
diff --git a/ext/Log4Qt/src/ndc.cpp b/ext/Log4Qt/src/ndc.cpp
new file mode 100755
index 0000000..4995a60
--- /dev/null
+++ b/ext/Log4Qt/src/ndc.cpp
@@ -0,0 +1,154 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: ndc.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "ndc.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+#include "helpers/initialisationhelper.h"
+#include "logger.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt:NDC)
+
+
+
+ /**************************************************************************
+ * Class implementation: NDC
+ **************************************************************************/
+
+
+ void NDC::clear()
+ {
+ if (!instance()->mStack.hasLocalData())
+ return;
+
+ instance()->mStack.localData()->clear();
+ }
+
+
+ int NDC::depth()
+ {
+ if (!instance()->mStack.hasLocalData())
+ return 0;
+
+ return instance()->mStack.localData()->count();
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(NDC)
+
+
+ QString NDC::pop()
+ {
+ if (!instance()->mStack.hasLocalData() || instance()->mStack.localData()->isEmpty())
+ {
+ logger()->warn("Requesting pop from empty NDC stack");
+ return QString();
+ }
+
+ return instance()->mStack.localData()->pop();
+ }
+
+
+ void NDC::push(const QString &rMessage)
+ {
+ if (!instance()->mStack.hasLocalData())
+ instance()->mStack.setLocalData(new QStack<QString>);
+
+ instance()->mStack.localData()->push(rMessage);
+ }
+
+
+ void NDC::setMaxDepth(int maxDepth)
+ {
+ if (!instance()->mStack.hasLocalData() ||
+ instance()->mStack.localData()->size() <= maxDepth)
+ return;
+
+ instance()->mStack.localData()->resize(maxDepth);
+ }
+
+
+ QString NDC::peek()
+ {
+ if (!instance()->mStack.hasLocalData() ||
+ instance()->mStack.localData()->isEmpty())
+ return QString();
+
+ return instance()->mStack.localData()->top();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const NDC &rNDC)
+ {
+ Q_UNUSED(rNDC); // To avoid warning C4100 on VS 2008
+ debug.nospace() << "NDC("
+ << "thread:" << QThread::currentThread()->objectName() << " "
+ << "peek:" << rNDC.peek() << " "
+ << "depth:" << rNDC.depth()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/ndc.h b/ext/Log4Qt/src/ndc.h
new file mode 100755
index 0000000..74585c7
--- /dev/null
+++ b/ext/Log4Qt/src/ndc.h
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: ndc.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_NDC_H
+#define LOG4QT_NDC_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include <QtCore/QStack>
+#include <QtCore/QThreadStorage>
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class NDC implements a nested diagnostic context.
+ *
+ * The method remove() is not required. QThreadStorage cleans up on thread
+ * exit.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT NDC
+ {
+ private:
+ NDC();
+ NDC(const NDC &rOther); // Not implemented
+ // virtual ~NDC(); // Use compiler default
+ NDC &operator=(const NDC &rOther); // Not implemented
+
+ public:
+ static void clear();
+ // JAVA: static QStack<QString> cloneStack();
+ // JAVA: static QString get();
+ static int depth();
+ // JAVA: inherit(Stack stack)
+
+ /*!
+ * Returns the NDC instance.
+ */
+ static NDC *instance();
+
+ static QString pop();
+ static void push(const QString &rMessage);
+ // JAVA: static void remove(); // Not required
+ static void setMaxDepth(int maxDepth);
+ static QString peek();
+
+ private:
+ QThreadStorage< QStack<QString> * > mStack;
+ };
+
+
+ /******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates NDC
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %NDC(thread:"main" peek:"i = 3" depth:4)
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const NDC &rNDC);
+ #endif // QT_NO_DEBUG_STREAM
+
+
+ /******************************************************************************
+ * Inline
+ ******************************************************************************/
+
+ inline NDC::NDC() :
+ mStack()
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::NDC, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_NDC_H
diff --git a/ext/Log4Qt/src/patternlayout.cpp b/ext/Log4Qt/src/patternlayout.cpp
new file mode 100755
index 0000000..1f3e354
--- /dev/null
+++ b/ext/Log4Qt/src/patternlayout.cpp
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternlayout.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "patternlayout.h"
+
+#include <QtCore/QDebug>
+#include "helpers/patternformatter.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: PatternLayout
+ **************************************************************************/
+
+
+ PatternLayout::PatternLayout(QObject *pParent) :
+ Layout(pParent),
+ mPattern(),
+ mpPatternFormatter(0)
+ {
+ setConversionPattern(DEFAULT_CONVERSION_PATTERN);
+ }
+
+
+ PatternLayout::PatternLayout(const QString &rPattern,
+ QObject *pParent) :
+ Layout(pParent),
+ mPattern(),
+ mpPatternFormatter(0)
+ {
+ setConversionPattern(rPattern);
+ }
+
+
+ PatternLayout::PatternLayout(ConversionPattern conversionPattern,
+ QObject *pParent) :
+ Layout(pParent),
+ mPattern(),
+ mpPatternFormatter(0)
+ {
+ setConversionPattern(conversionPattern);
+ }
+
+
+ PatternLayout::~PatternLayout()
+ {
+ delete mpPatternFormatter;
+ }
+
+
+ void PatternLayout::setConversionPattern(ConversionPattern conversionPattern)
+ {
+ switch (conversionPattern)
+ {
+ case DEFAULT_CONVERSION_PATTERN:
+ setConversionPattern(QLatin1String("%m%n"));
+ break;
+ case TTCC_CONVERSION_PATTERN:
+ setConversionPattern(QLatin1String("%r [%t] %p %c %x - %m%n"));
+ break;
+ default:
+ Q_ASSERT_X(false, "PatternLayout::setConversionFormat", "Unkown ConversionFormat");
+ setConversionPattern(QString());
+ }
+ }
+
+
+ QString PatternLayout::format(const LoggingEvent &rEvent)
+ {
+ Q_ASSERT_X(mpPatternFormatter, "PatternLayout::format()", "mpPatternConverter must not be null");
+
+ return mpPatternFormatter->format(rEvent);
+ }
+
+
+ void PatternLayout::updatePatternFormatter()
+ {
+ delete mpPatternFormatter;
+ mpPatternFormatter = new PatternFormatter(mPattern);
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug PatternLayout::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "PatternLayout("
+ << "name:" << name() << " "
+ << "pattern:" << conversionPattern() << " "
+ << "referencecount:" << referenceCount()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/patternlayout.h b/ext/Log4Qt/src/patternlayout.h
new file mode 100755
index 0000000..e54b9fa
--- /dev/null
+++ b/ext/Log4Qt/src/patternlayout.h
@@ -0,0 +1,167 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternlayout.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PATTERNLAYOUT_H
+#define LOG4QT_PATTERNLAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "layout.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ class PatternFormatter;
+
+ /*!
+ * \brief The class PatternLayout outputs a logging event based on a
+ * pattern string.
+ \li c{section_count} : logger name with optional parameter section_count. Section count from end of logger name, sections delimiter is "::";
+ \li d{format_string} : date with optional parameters in "{}"-brackets which used by QDateTime::toString();
+ \li m : message
+ \li p : level name
+ \li r : relative date/time to start application
+ \li t : thread name
+ \li x : ndc name
+ \li X : mdc name
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT PatternLayout : public Layout
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the conversion pattern used by the appender.
+ *
+ * The default is "%m%n".
+ *
+ * \sa conversionPattern(), setConversionPattern()
+ */
+ Q_PROPERTY(QString conversionPattern READ conversionPattern WRITE setConversionPattern)
+
+ public:
+ /*!
+ * The enum ConversionPattern defines constants for pattern strings.
+ *
+ * \sa setConversionPattern(ConversionPattern);
+ */
+ enum ConversionPattern
+ {
+ /*! The default conversion pattern string is "%m,%n". */
+ DEFAULT_CONVERSION_PATTERN,
+ /*!
+ * The ttcc conversion pattern string is
+ * "%r [%t] %p %c %x - %m%n".
+ */
+ TTCC_CONVERSION_PATTERN
+ };
+ Q_ENUMS(ConversionPattern)
+
+ PatternLayout(QObject *pParent = 0);
+ PatternLayout(const QString &rPattern,
+ QObject *pParent = 0);
+
+ /*!
+ * Creates a PatternLayout with the conversion pattern value specified
+ * by the \a conversionPattern constant.
+ */
+ PatternLayout(ConversionPattern conversionPattern,
+ QObject *pParent = 0);
+
+ virtual ~PatternLayout();
+ private:
+ PatternLayout(const PatternLayout &rOther); // Not implemented
+ PatternLayout &operator=(const PatternLayout &rOther); // Not implemented
+
+ public:
+ QString conversionPattern() const;
+ void setConversionPattern(const QString &rPattern);
+
+ /*!
+ * Sets the conversion pattern to the value specified by the
+ * \a conversionPattern constant.
+ */
+ void setConversionPattern(ConversionPattern conversionPattern);
+
+ virtual QString format(const LoggingEvent &rEvent);
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %PatternLayout(name:"PL" pattern:"%r [%t] %p %c %x - %m%n"
+ * "referencecount:3")
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ void updatePatternFormatter();
+
+ private:
+ QString mPattern;
+ PatternFormatter *mpPatternFormatter;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QString PatternLayout::conversionPattern() const
+ { return PatternLayout::mPattern; }
+
+ inline void PatternLayout::setConversionPattern(const QString &rPattern)
+ { mPattern = rPattern;
+ updatePatternFormatter(); }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::PatternLayout, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_PATTERNLAYOUT_H
diff --git a/ext/Log4Qt/src/propertyconfigurator.cpp b/ext/Log4Qt/src/propertyconfigurator.cpp
new file mode 100755
index 0000000..1fe3860
--- /dev/null
+++ b/ext/Log4Qt/src/propertyconfigurator.cpp
@@ -0,0 +1,588 @@
+/******************************************************************************
+ *
+ * package: Logging
+ * file: propertyconfigurator.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "propertyconfigurator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include "helpers/configuratorhelper.h"
+#include "helpers/factory.h"
+#include "helpers/optionconverter.h"
+#include "helpers/properties.h"
+#include "appender.h"
+#include "layout.h"
+#include "logger.h"
+#include "logmanager.h"
+#include "loggerrepository.h"
+#include "varia/listappender.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator)
+
+
+
+ /**************************************************************************
+ * Class implementation: PropertyConfigurator
+ **************************************************************************/
+
+
+ bool PropertyConfigurator::doConfigure(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository)
+ {
+ startCaptureErrors();
+ configureFromProperties(rProperties, pLoggerRepository);
+ return stopCaptureErrors();
+ }
+
+
+ bool PropertyConfigurator::doConfigure(const QString &rConfigFileName,
+ LoggerRepository *pLoggerRepository)
+ {
+ startCaptureErrors();
+ configureFromFile(rConfigFileName, pLoggerRepository);
+ return stopCaptureErrors();
+ }
+
+
+ bool PropertyConfigurator::doConfigure(const QSettings &rSettings,
+ LoggerRepository *pLoggerRepository)
+ {
+ startCaptureErrors();
+ configureFromSettings(rSettings, pLoggerRepository);
+ return stopCaptureErrors();
+ }
+
+
+ bool PropertyConfigurator::configure(const Properties &rProperties)
+ {
+ PropertyConfigurator configurator;
+ return configurator.doConfigure(rProperties);
+ }
+
+
+ bool PropertyConfigurator::configure(const QString &rConfigFilename)
+ {
+ PropertyConfigurator configurator;
+ return configurator.doConfigure(rConfigFilename);
+ }
+
+
+ bool PropertyConfigurator::configure(const QSettings &rSettings)
+ {
+ PropertyConfigurator configurator;
+ return configurator.doConfigure(rSettings);
+ }
+
+
+ bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName)
+ {
+ // Stop an existing watch to avoid a possible concurrent configuration
+ ConfiguratorHelper::setConfigurationFile();
+ if (rConfigFileName.isEmpty())
+ return true;
+
+ PropertyConfigurator configurator;
+ bool result = configurator.doConfigure(rConfigFileName);
+ ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure);
+ return result;
+ }
+
+
+ void PropertyConfigurator::configureFromFile(const QString &rConfigFileName,
+ LoggerRepository *pLoggerRepository)
+ {
+ QFile file(rConfigFileName);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"),
+ CONFIGURATOR_OPENING_FILE_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << rConfigFileName;
+ e.addCausingError(LogError(file.errorString(), file.error()));
+ logger()->error(e);
+ return;
+ }
+ Properties properties;
+ properties.load(&file);
+ if (file.error())
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"),
+ CONFIGURATOR_READING_FILE_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << rConfigFileName;
+ e.addCausingError(LogError(file.errorString(), file.error()));
+ logger()->error(e);
+ return;
+ }
+ configureFromProperties(properties, pLoggerRepository);
+ }
+
+
+ void PropertyConfigurator::configureFromProperties(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository)
+ {
+ if (!pLoggerRepository)
+ pLoggerRepository = LogManager::loggerRepository();
+
+ configureGlobalSettings(rProperties, pLoggerRepository);
+ configureRootLogger(rProperties, pLoggerRepository);
+ configureNonRootElements(rProperties, pLoggerRepository);
+ mAppenderRegistry.clear();
+ }
+
+
+ void PropertyConfigurator::configureFromSettings(const QSettings &rSettings,
+ LoggerRepository *pLoggerRepository)
+ {
+ Properties properties;
+ properties.load(rSettings);
+ configureFromProperties(properties, pLoggerRepository);
+ }
+
+
+ void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository) const
+ {
+ Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null.");
+
+ const QLatin1String key_reset("log4j.reset");
+ const QLatin1String key_debug("log4j.Debug");
+ const QLatin1String key_config_debug("log4j.configDebug");
+ const QLatin1String key_threshold("log4j.threshold");
+ const QLatin1String key_handle_qt_messages("log4j.handleQtMessages");
+
+ // Test each global setting and set it
+ // - Reset: log4j.reset
+ // - Debug: log4j.Debug, log4j.configDebug
+ // - Threshold: log4j.threshold
+ // - Handle Qt Messages: log4j.handleQtMessages
+
+ // Reset
+ QString value = rProperties.property(key_reset);
+ if (!value.isEmpty() && OptionConverter::toBoolean(value, false))
+ {
+ // Use LogManager and not pLoggerRepository to reset internal
+ // logging.
+ LogManager::resetConfiguration();
+ logger()->debug("Reset configuration");
+ }
+
+ // Debug
+ value = rProperties.property(key_debug);
+ if (value.isNull())
+ {
+ value = rProperties.property(key_config_debug);
+ if (!value.isNull())
+ logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug);
+ }
+ if (!value.isNull())
+ {
+ // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting
+ bool ok;
+ Level level = Level::fromString(value, &ok);
+ if (!ok)
+ level = Level::DEBUG_INT;
+ LogManager::logLogger()->setLevel(level);
+ logger()->debug("Set level for Log4Qt logging to %1",
+ LogManager::logLogger()->level().toString());
+ }
+
+ // Threshold
+ value = rProperties.property(key_threshold);
+ if (!value.isNull())
+ {
+ pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT));
+ logger()->debug("Set threshold for LoggerRepository to %1",
+ pLoggerRepository->threshold().toString());
+ }
+
+ // Handle Qt messages
+ value = rProperties.property(key_handle_qt_messages);
+ if (!value.isNull())
+ {
+ LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false));
+ logger()->debug("Set handling of Qt messages LoggerRepository to %1",
+ QVariant(LogManager::handleQtMessages()).toString());
+ }
+ }
+
+
+ void PropertyConfigurator::configureNonRootElements(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository)
+ {
+ Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null.");
+
+ const QString logger_prefix = QLatin1String("log4j.logger.");
+ const QString category_prefix = QLatin1String("log4j.category.");
+
+ // Iterate through all entries:
+ // - Test for the logger/category prefix
+ // - Convert JAVA class names to C++ ones
+ // - Parse logger data (Level, Appender)
+ // - Parse logger additivity
+
+ QStringList keys = rProperties.propertyNames();
+ QString key;
+ Q_FOREACH(key, keys)
+ {
+ QString java_name;
+ if (key.startsWith(logger_prefix))
+ java_name = key.mid(logger_prefix.length());
+ else if (key.startsWith(category_prefix))
+ java_name = key.mid(category_prefix.length());
+ QString cpp_name = OptionConverter::classNameJavaToCpp(java_name);
+ if (!java_name.isEmpty())
+ {
+ Logger *p_logger = pLoggerRepository->logger(cpp_name);
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ parseLogger(rProperties, p_logger, key, value);
+ parseAdditivityForLogger(rProperties, p_logger, java_name);
+ }
+ }
+ }
+
+
+ void PropertyConfigurator::configureRootLogger(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository)
+ {
+ Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null.");
+
+ const QLatin1String key_root_logger("log4j.rootLogger");
+ const QLatin1String key_root_category("log4j.rootCategory");
+
+ // - Test for the logger/category prefix
+ // - Parse logger data for root logger
+
+ QString key = key_root_logger;
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ if (value.isNull())
+ {
+ key = key_root_category;
+ value = OptionConverter::findAndSubst(rProperties, key);
+ if (!value.isNull())
+ logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger);
+ }
+
+ if (value.isNull())
+ logger()->debug("Could not find root logger information. Is this correct?");
+ else
+ parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value);
+ }
+
+
+ void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties,
+ Logger *pLogger,
+ const QString &rLog4jName) const
+ {
+ Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null.");
+
+ const QLatin1String additivity_prefix("log4j.additivity.");
+
+ // - Lookup additivity key for logger
+ // - Set additivity, if specified
+
+ QString key = additivity_prefix + rLog4jName;
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value);
+ if (!value.isEmpty())
+ {
+ bool additivity = OptionConverter::toBoolean(value, true);
+ logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString());
+ pLogger->setAdditivity(additivity);
+ }
+ }
+
+
+ LogObjectPtr<Appender> PropertyConfigurator::parseAppender(const Properties &rProperties,
+ const QString &rName)
+ {
+ // - Test if appender has been parsed before
+ // - Find appender key
+ // - Create appender object
+ // - Set layout, if required by appender
+ // - Set properties
+ // - Activate options
+ // - Add appender to registry
+
+ const QLatin1String appender_prefix("log4j.appender.");
+
+ logger()->debug("Parsing appender named '%1'", rName);
+
+ if (mAppenderRegistry.contains(rName))
+ {
+ logger()->debug("Appender '%1' was already parsed.", rName);
+ return mAppenderRegistry.value(rName);
+ }
+
+ QString key = appender_prefix + rName;
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ if (value.isNull())
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"),
+ CONFIGURATOR_MISSING_APPENDER_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << rName;
+ logger()->error(e);
+ return 0;
+ }
+ LogObjectPtr<Appender> p_appender = Factory::createAppender(value);
+ if (!p_appender)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"),
+ CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << value << rName;
+ logger()->error(e);
+ return 0;
+ }
+ p_appender->setName(rName);
+
+ if (p_appender->requiresLayout())
+ {
+ LogObjectPtr<Layout> p_layout = parseLayout(rProperties, key);
+ if (p_layout)
+ p_appender->setLayout(p_layout);
+ else
+ return 0;
+ }
+
+ QStringList exclusions;
+ exclusions << QLatin1String("layout");
+ setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender);
+ AppenderSkeleton *p_appenderskeleton = qobject_cast<AppenderSkeleton *>(p_appender);
+ if (p_appenderskeleton)
+ p_appenderskeleton->activateOptions();
+
+ mAppenderRegistry.insert(rName, p_appender);
+ return p_appender;
+ }
+
+
+ LogObjectPtr<Layout> PropertyConfigurator::parseLayout(const Properties &rProperties,
+ const QString &rAppenderKey)
+ {
+ Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty.");
+
+ // - Find layout key
+ // - Create layput object
+ // - Set properties
+ // - Activate options
+
+ const QLatin1String layout_suffix(".layout");
+
+ logger()->debug("Parsing layout for appender named '%1'", rAppenderKey);
+
+ QString key = rAppenderKey + layout_suffix;
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ if (value.isNull())
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"),
+ CONFIGURATOR_MISSING_LAYOUT_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << rAppenderKey;
+ logger()->error(e);
+ return 0;
+ }
+ LogObjectPtr<Layout> p_layout = Factory::createLayout(value);
+ if (!p_layout)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layoput of class '%1' requested by appender '%2'"),
+ CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR,
+ "Log4Qt::PropertyConfigurator");
+ e << value << rAppenderKey;
+ logger()->error(e);
+ return 0;
+ }
+
+ QStringList exclusions;
+ setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout);
+ p_layout->activateOptions();
+
+ return p_layout;
+ }
+
+
+ void PropertyConfigurator::parseLogger(const Properties &rProperties,
+ Logger *pLogger,
+ const QString &rKey,
+ const QString &rValue)
+ {
+ Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null.");
+ Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty.");
+
+ const QLatin1String keyword_inherited("INHERITED");
+
+ // - Split value on comma
+ // - If level value, is specified
+ // - Test for NULL and INHERITED
+ // - Ensure root logger is not set to NULL
+ // - Set level
+ // - For each entry
+ // - Create Appender
+
+ logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue);
+ QStringList appenders = rValue.split(QLatin1Char(','));
+ QStringListIterator i (appenders);
+
+ // First entry is the level. There will be always one entry, even if the rValue is
+ // empty or does not contain a comma.
+ QString value = i.next().trimmed();
+ if (!value.isEmpty())
+ {
+ Level level;
+ if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0)
+ level = Level::NULL_INT;
+ else
+ level = OptionConverter::toLevel(value, Level::DEBUG_INT);
+ if (level == Level::NULL_INT && pLogger->name() == QString())
+ logger()->warn("The root logger level cannot be set to NULL.");
+ else
+ {
+ pLogger->setLevel(level);
+ logger()->debug("Set level for logger '%1' to '%2'",
+ pLogger->name(), pLogger->level().toString());
+ }
+ }
+
+ pLogger->removeAllAppenders();
+ while(i.hasNext())
+ {
+ value = i.next().trimmed();
+ if(value.isEmpty())
+ continue;
+ LogObjectPtr<Appender> p_appender = parseAppender(rProperties, value);
+ if (p_appender)
+ pLogger->addAppender(p_appender);
+ }
+ }
+
+
+ void PropertyConfigurator::setProperties(const Properties &rProperties,
+ const QString &rPrefix,
+ const QStringList &rExclusions,
+ QObject *pObject)
+ {
+ Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty.");
+ Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null.");
+
+ // Iterate through all entries:
+ // - Test for prefix to determine, if setting is for object
+ // - Skip empty property name
+ // - Skip property names in exclusion list
+ // - Set property on object
+
+ logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'",
+ QLatin1String(pObject->metaObject()->className()),
+ rPrefix);
+
+ QStringList keys = rProperties.propertyNames();
+ QString key;
+ Q_FOREACH(key, keys)
+ {
+ if (!key.startsWith(rPrefix))
+ continue;
+ QString property = key.mid(rPrefix.length());
+ if (property.isEmpty())
+ continue;
+ QStringList split_property = property.split(QLatin1Char('.'));
+ if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive))
+ continue;
+ QString value = OptionConverter::findAndSubst(rProperties, key);
+ Factory::setObjectProperty(pObject, property, value);
+ }
+ }
+
+
+ void PropertyConfigurator::startCaptureErrors()
+ {
+ Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty.");
+
+ mpConfigureErrors = new ListAppender;
+ mpConfigureErrors->setName(QLatin1String("PropertyConfigurator"));
+ mpConfigureErrors->setConfiguratorList(true);
+ mpConfigureErrors->setThreshold(Level::ERROR_INT);
+ LogManager::logLogger()->addAppender(mpConfigureErrors);
+ }
+
+
+ bool PropertyConfigurator::stopCaptureErrors()
+ {
+ Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty.");
+
+ LogManager::logLogger()->removeAppender(mpConfigureErrors);
+ ConfiguratorHelper::setConfigureError(mpConfigureErrors->list());
+ bool result = (mpConfigureErrors->list().count() == 0);
+ mpConfigureErrors = 0;
+ return result;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const PropertyConfigurator &rPropertyConfigurator)
+ {
+ Q_UNUSED(rPropertyConfigurator);
+ debug.nospace() << "PropertyConfigurator("
+ << ")";
+ return debug.space();
+ }
+#endif
+
+
+
+} // namespace Log4Qt Logging
diff --git a/ext/Log4Qt/src/propertyconfigurator.h b/ext/Log4Qt/src/propertyconfigurator.h
new file mode 100755
index 0000000..23588a3
--- /dev/null
+++ b/ext/Log4Qt/src/propertyconfigurator.h
@@ -0,0 +1,194 @@
+/******************************************************************************
+ *
+ * package: Logging
+ * file: propertyconfigurator.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PROPERTYCONFIGURATOR_H
+#define LOG4QT_PROPERTYCONFIGURATOR_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include <QtCore/QHash>
+#include "helpers/logobjectptr.h"
+#include "log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QSettings;
+
+namespace Log4Qt
+{
+
+ class Appender;
+ class Layout;
+ class ListAppender;
+ class Logger;
+ class Properties;
+ class LoggerRepository;
+
+ /*!
+ * \brief The class PropertyConfigurator allows the configuration of the
+ * package from a JAVA properties file.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT PropertyConfigurator
+ {
+ public:
+ PropertyConfigurator();
+ // virtual ~PropertyConfigurator(); // Use compiler default
+ private:
+ PropertyConfigurator(const PropertyConfigurator &rOther); // Not implemented
+ PropertyConfigurator &operator=(const PropertyConfigurator &rOther); // Not implemented
+
+ public:
+ /*!
+ * \sa ConfiguratorHelper::configureError()
+ */
+ bool doConfigure(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository = 0);
+
+ /*!
+ * \sa ConfiguratorHelper::configureError()
+ */
+ bool doConfigure(const QString &rConfigFileName,
+ LoggerRepository *pLoggerRepository = 0);
+
+ /*!
+ * Reads the configuration data from the QSettings object
+ * \a rSettings.
+ *
+ * \sa \ref Properties::load(const QSettings &) "Properties::load()",
+ * ConfiguratorHelper::configureError()
+ */
+ bool doConfigure(const QSettings &rSettings,
+ LoggerRepository *pLoggerRepository = 0);
+
+ // JAVA: void doConfigure(const QUrl &rUrl, LoggerRepository *pLoggerRepository);
+
+ /*!
+ * \sa ConfiguratorHelper::configureError()
+ */
+ static bool configure(const Properties &rProperties);
+
+ /*!
+ * \sa ConfiguratorHelper::configureError()
+ */
+ static bool configure(const QString &rConfigFilename);
+
+ /*!
+ * Reads the configuration data from the QSettings object
+ * \a rSettings.
+ *
+ * \sa \ref doConfigure(const QSettings &, LoggerRepository *) "doConfigure()",
+ * \ref Properties::load(const QSettings &) "Properties::load()",
+ * ConfiguratorHelper::configureError()
+ */
+ static bool configure(const QSettings &rSettings);
+
+ // JAVA: static void configure(const QUrl &rUrl);
+
+ /*!
+ * \sa ConfiguratorHelper::configureError(),
+ * ConfiguratorHelper::configurationFile()
+ */
+ static bool configureAndWatch(const QString &rConfigFilename);
+
+ private:
+ void configureFromFile(const QString &rConfigFileName,
+ LoggerRepository *pLoggerRepository);
+ void configureFromProperties(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository);
+ void configureFromSettings(const QSettings &rSettings,
+ LoggerRepository *pLoggerRepository);
+ void configureGlobalSettings(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository) const;
+ void configureNonRootElements(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository);
+ void configureRootLogger(const Properties &rProperties,
+ LoggerRepository *pLoggerRepository);
+ void parseAdditivityForLogger(const Properties &rProperties,
+ Logger *pLogger,
+ const QString &rLog4jName) const;
+ LogObjectPtr<Appender> parseAppender(const Properties &rProperties,
+ const QString &rName);
+ LogObjectPtr<Layout> parseLayout(const Properties &rProperties,
+ const QString &rAppenderName);
+ void parseLogger(const Properties &rProperties,
+ Logger *pLogger,
+ const QString &rKey,
+ const QString &rValue);
+ void setProperties(const Properties &rProperties,
+ const QString &rPrefix,
+ const QStringList &rExclusions,
+ QObject *pObject);
+ void startCaptureErrors();
+ bool stopCaptureErrors();
+
+ private:
+ LogObjectPtr<ListAppender> mpConfigureErrors;
+ QHash< QString, LogObjectPtr<Appender> > mAppenderRegistry;
+ };
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates PropertyConfigurator
+ *
+ * Writes all object member variables to the given debug stream \a debug
+ * and returns the stream.
+ *
+ * <tt>
+ * %PropertyConfigurator()
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const PropertyConfigurator &rPropertyConfigurator);
+#endif
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline PropertyConfigurator::PropertyConfigurator()
+ {}
+
+
+} // namspace Logging
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::PropertyConfigurator, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_PROPERTYCONFIGURATOR_H
diff --git a/ext/Log4Qt/src/rollingfileappender.cpp b/ext/Log4Qt/src/rollingfileappender.cpp
new file mode 100755
index 0000000..9b13135
--- /dev/null
+++ b/ext/Log4Qt/src/rollingfileappender.cpp
@@ -0,0 +1,191 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: rollingfileappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "rollingfileappender.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QTextCodec>
+#include "helpers/optionconverter.h"
+#include "layout.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /************************************************************************
+ Declarations
+ *************************************************************************/
+
+
+
+ /************************************************************************
+ C helper functions
+ *************************************************************************/
+
+
+
+ /************************************************************************
+ Class implementation: RollingFileAppender
+ *************************************************************************/
+
+
+ RollingFileAppender::RollingFileAppender(QObject *pParent) :
+ FileAppender(pParent),
+ mMaxBackupIndex(1),
+ mMaximumFileSize(10*1024*1024)
+ {
+ }
+
+
+ RollingFileAppender::RollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ QObject *pParent) :
+ FileAppender(pLayout, rFileName, pParent),
+ mMaxBackupIndex(1),
+ mMaximumFileSize(10*1024*1024)
+ {
+ }
+
+
+ RollingFileAppender::RollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ QObject *pParent) :
+ FileAppender(pLayout, rFileName, append, pParent),
+ mMaxBackupIndex(1),
+ mMaximumFileSize(10*1024*1024)
+ {
+ }
+
+
+ RollingFileAppender::~RollingFileAppender()
+ {
+ close();
+ }
+
+
+ void RollingFileAppender::setMaxFileSize(const QString &rMaxFileSize)
+ {
+ bool ok;
+ qint64 max_file_size = OptionConverter::toFileSize(rMaxFileSize, &ok);
+ if (ok)
+ setMaximumFileSize(max_file_size);
+ }
+
+
+ void RollingFileAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller")
+
+ FileAppender::append(rEvent);
+ if (writer()->device()->size() > this->mMaximumFileSize)
+ rollOver();
+ }
+
+
+ void RollingFileAppender::rollOver()
+ {
+ // Q_ASSERT_X(, "RollingFileAppender::rollOver()", "Lock must be held by caller")
+
+ logger()->debug("Rolling over with maxBackupIndex = %1", mMaxBackupIndex);
+
+ closeFile();
+
+ QFile f;
+ f.setFileName(file() + QLatin1Char('.') + QString::number(mMaxBackupIndex));
+ if (f.exists() && !removeFile(f))
+ return;
+
+ QString target_file_name;
+ int i;
+ for (i = mMaxBackupIndex - 1; i >=1; i--)
+ {
+ f.setFileName(file() + QLatin1Char('.') + QString::number(i));
+ if (f.exists())
+ {
+ target_file_name = file() + QLatin1Char('.') + QString::number(i + 1);
+ if (!renameFile(f, target_file_name))
+ return;
+ }
+ }
+
+ f.setFileName(file());
+ target_file_name = file() + QLatin1String(".1");
+ if (!renameFile(f, target_file_name))
+ return;
+
+ openFile();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug RollingFileAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+ QString codec_name;
+ if (encoding())
+ codec_name = QLatin1String(encoding()->name());
+
+ rDebug.nospace() << "RollingFileAppender("
+ << "name:" << name() << " "
+ << "appendfile:" << appendFile() << " "
+ << "bufferedio:" << bufferedIo() << " "
+ << "encoding:" << codec_name << " "
+ << "file:" << file() << " "
+ << "filter:" << firstFilter() << " "
+ << "immediateflush:" << immediateFlush() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "maxbackupindex:" << maxBackupIndex() << " "
+ << "maximumfilesize:" << maximumFileSize() << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString() << " "
+ << "writer:" << writer()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/rollingfileappender.h b/ext/Log4Qt/src/rollingfileappender.h
new file mode 100755
index 0000000..4b01af1
--- /dev/null
+++ b/ext/Log4Qt/src/rollingfileappender.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: rollingfileappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_ROLINGFILEAPPENDER_H
+#define LOG4QT_ROLINGFILEAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "fileappender.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class RollingFileAppender extends FileAppender to backup
+ * the log files when they reach a certain size.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT RollingFileAppender : public FileAppender
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the maximum backup count used by the appender.
+ *
+ * The default is 1.
+ *
+ * \sa maxBackupIndex(), setMaxBackupIndex()
+ */
+ Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex)
+
+ /*!
+ * The property holds the maximum file size used by the appender.
+ *
+ * The default is 10 MB (10 * 1024 * 1024).
+ *
+ * \sa maximumFileSize(), setMaximumFileSize()
+ */
+ Q_PROPERTY(qint64 maximumFileSize READ maximumFileSize WRITE setMaximumFileSize)
+
+ /*!
+ * The property sets the maximum file size from a string value.
+ *
+ * \sa setMaxFileSize(), maximumFileSize()
+ */
+ Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize)
+
+ public:
+ RollingFileAppender(QObject *pParent = 0);
+ RollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ QObject *pParent = 0);
+ RollingFileAppender(Layout *pLayout,
+ const QString &rFileName,
+ bool append,
+ QObject *pParent = 0);
+ virtual ~RollingFileAppender();
+ private:
+ RollingFileAppender(const RollingFileAppender &rOther); // Not implemented
+ RollingFileAppender &operator=(const RollingFileAppender &rOther); // Not implemented
+
+ public:
+ int maxBackupIndex() const;
+ qint64 maximumFileSize() const;
+ QString maxFileSize() const;
+ void setMaxBackupIndex(int maxBackupIndex);
+ void setMaximumFileSize(qint64 maximumFileSize);
+ void setMaxFileSize(const QString &rMaxFileSize);
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %RollingFileAppender(name:"RFA" appendfile:false bufferedio:true
+ * encoding:"" file:"log.txt" filter: 0x0
+ * immediateflush:true isactive:true
+ * isclosed:false layout:"TTCC" maxbackupindex:2
+ * maximumfilesize:40 referencecount:1
+ * threshold:"NULL" writer:0x4175af8)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ void rollOver();
+
+ private:
+ int mMaxBackupIndex;
+ qint64 mMaximumFileSize;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline int RollingFileAppender::maxBackupIndex() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mMaxBackupIndex; }
+
+ inline qint64 RollingFileAppender::maximumFileSize() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mMaximumFileSize; }
+
+ inline QString RollingFileAppender::maxFileSize() const
+ { QMutexLocker locker(&mObjectGuard);
+ return QString::number(mMaximumFileSize); }
+
+ inline void RollingFileAppender::setMaxBackupIndex(int maxBackupIndex)
+ { QMutexLocker locker(&mObjectGuard);
+ mMaxBackupIndex = maxBackupIndex; }
+
+ inline void RollingFileAppender::setMaximumFileSize(qint64 maximumFileSize)
+ { QMutexLocker locker(&mObjectGuard);
+ mMaximumFileSize = maximumFileSize; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::RollingFileAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_ROLINGFILEAPPENDER_H
diff --git a/ext/Log4Qt/src/signalappender.cpp b/ext/Log4Qt/src/signalappender.cpp
new file mode 100755
index 0000000..f180d18
--- /dev/null
+++ b/ext/Log4Qt/src/signalappender.cpp
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: signalappender.cpp
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "signalappender.h"
+
+#include "layout.h"
+
+#include <QtCore/QDebug>
+
+namespace Log4Qt {
+ SignalAppender::SignalAppender(QObject *parent) :
+ AppenderSkeleton(parent)
+ {
+ }
+
+ void SignalAppender::append(const LoggingEvent &rEvent)
+ {
+ QString message(layout()->format(rEvent));
+ emit appended(message);
+ }
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug SignalAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "WriterAppender("
+ << "name:" << name() << " "
+ << "filter:" << firstFilter()
+ << "isactive:" << isActive()
+ << "isclosed:" << isClosed()
+ << "layout:" << layout_name
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+}
diff --git a/ext/Log4Qt/src/signalappender.h b/ext/Log4Qt/src/signalappender.h
new file mode 100755
index 0000000..4fca738
--- /dev/null
+++ b/ext/Log4Qt/src/signalappender.h
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: signalappender.h
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef SIGNALAPPENDER_H
+#define SIGNALAPPENDER_H
+
+#include "appenderskeleton.h"
+
+#include "loggingevent.h"
+
+namespace Log4Qt {
+
+ /*!
+ \ingroup log4qt
+ Класс генерирующий сигнал при полчении какого-либо лог-сообщения. Удобно использовать для GUI интерфейса.
+ \note не объявлен в простанстве имен log4qt вроде из-за отстуствия у moc (Qt metaobject compiler) средств для обработки пространств имен.
+* @class SignalAppender signalappender.h "src/kernel/components/signalappender.h"
+*/
+ class LOG4QT_EXPORT SignalAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+ public:
+ explicit SignalAppender(QObject *parent = 0);
+
+ bool requiresLayout() const;
+
+ protected:
+ virtual void append(const Log4Qt::LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * The member function is used by
+ * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to
+ * generate class specific output.
+ *
+ * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject);
+#endif // QT_NO_DEBUG_STREAM
+
+ signals:
+ /*!
+ Генерируется во время получения лог-сообщения.
+ * @param message
+ */
+ void appended(const QString& message);
+ public slots:
+
+ };
+
+ inline bool SignalAppender::requiresLayout() const
+ { return true; }
+
+} // namespace Log4Qt
+
+#endif // SIGNALAPPENDER_H
diff --git a/ext/Log4Qt/src/simplelayout.cpp b/ext/Log4Qt/src/simplelayout.cpp
new file mode 100755
index 0000000..36ce26f
--- /dev/null
+++ b/ext/Log4Qt/src/simplelayout.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: simplelayout.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "simplelayout.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: SimpleLayout
+ **************************************************************************/
+
+
+ QString SimpleLayout::format(const LoggingEvent &rEvent)
+ {
+ return rEvent.level().toString() + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug SimpleLayout::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "SimpleLayout("
+ << "name:" << name() << " "
+ << "referencecount:" << referenceCount()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/simplelayout.h b/ext/Log4Qt/src/simplelayout.h
new file mode 100755
index 0000000..fbf6545
--- /dev/null
+++ b/ext/Log4Qt/src/simplelayout.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: simplelayout.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_SIMPLELAYOUT_H
+#define LOG4QT_SIMPLELAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "layout.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class SimpleLayout outputs the level and message of a logging
+ * event.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT SimpleLayout : public Layout
+ {
+ Q_OBJECT
+
+ public:
+ SimpleLayout(QObject *pParent = 0);
+ // virtual ~SimpleLayout(); // Use compiler default
+ private:
+ SimpleLayout(const SimpleLayout &rOther); // Not implemented
+ SimpleLayout &operator=(const SimpleLayout &rOther); // Not implemented
+
+ public:
+ virtual QString format(const LoggingEvent &rEvent);
+
+ protected:
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %SimpleLayout(name:"SL" referencecount:1)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline SimpleLayout::SimpleLayout(QObject *pParent) :
+ Layout(pParent)
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::SimpleLayout, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_SIMPLELAYOUT_H
diff --git a/ext/Log4Qt/src/simpletimelayout.cpp b/ext/Log4Qt/src/simpletimelayout.cpp
new file mode 100755
index 0000000..7e73295
--- /dev/null
+++ b/ext/Log4Qt/src/simpletimelayout.cpp
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: simpletimelayout.cpp
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "simpletimelayout.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+#include "helpers/datetime.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: SimpleTimeLayout
+ **************************************************************************/
+
+
+ QString SimpleTimeLayout::format(const LoggingEvent &rEvent)
+ {
+ return DateTime::fromMilliSeconds(rEvent.timeStamp()).toString("dd.MM.yyyy hh:mm")
+ + QLatin1String("[") + rEvent.threadName() + QLatin1String("]")
+ + QLatin1String(" ") + rEvent.level().toString()
+ + QLatin1String(" ") + rEvent.loggerName()
+ + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine();
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug SimpleTimeLayout::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "SimpleTimeLayout("
+ << "name:" << name() << " "
+ << "referencecount:" << referenceCount()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/simpletimelayout.h b/ext/Log4Qt/src/simpletimelayout.h
new file mode 100755
index 0000000..297f495
--- /dev/null
+++ b/ext/Log4Qt/src/simpletimelayout.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: simpletimelayout.h
+ * created: March 2010
+ * author: Filonenko Michael
+ *
+ *
+ * Copyright 2010 Filonenko Michael
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_SIMPLETIMELAYOUT_H
+#define LOG4QT_SIMPLETIMELAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "layout.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class SimpleTimeLayout outputs the time, logger name, thread, level and message of a logging
+ * event.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT SimpleTimeLayout : public Layout
+ {
+ Q_OBJECT
+
+ public:
+ SimpleTimeLayout(QObject *pParent = 0);
+ // virtual ~SimpleTimeLayout(); // Use compiler default
+ private:
+ SimpleTimeLayout(const SimpleTimeLayout &rOther); // Not implemented
+ SimpleTimeLayout &operator=(const SimpleTimeLayout &rOther); // Not implemented
+
+ public:
+ virtual QString format(const LoggingEvent &rEvent);
+
+ protected:
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %SimpleTimeLayout(name:"SL" referencecount:1)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline SimpleTimeLayout::SimpleTimeLayout(QObject *pParent) :
+ Layout(pParent)
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::SimpleTimeLayout, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_SIMPLETIMELAYOUT_H
diff --git a/ext/Log4Qt/src/spi/filter.cpp b/ext/Log4Qt/src/spi/filter.cpp
new file mode 100755
index 0000000..31c1c9a
--- /dev/null
+++ b/ext/Log4Qt/src/spi/filter.cpp
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: filter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "spi/filter.h"
+
+#include <QtCore/QDebug>
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+
+
+ void Filter::setNext(Filter *pFilter)
+ {
+ mpNext = pFilter;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/spi/filter.h b/ext/Log4Qt/src/spi/filter.h
new file mode 100755
index 0000000..99861d8
--- /dev/null
+++ b/ext/Log4Qt/src/spi/filter.h
@@ -0,0 +1,124 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: filter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_FILTER_H
+#define LOG4QT_FILTER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "helpers/logobject.h"
+
+#include "helpers/logobjectptr.h"
+#include "../log4qt.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class LoggingEvent;
+
+ /*!
+ * \brief The class Filter is the base class for all filters.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT Filter : public LogObject
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the next filter of this filter.
+ *
+ * The default is 0 for no next filter.
+ *
+ * \sa next(), setNext()
+ */
+ Q_PROPERTY(Filter* next READ next WRITE setNext)
+
+ public:
+ enum Decision
+ {
+ ACCEPT,
+ DENY,
+ NEUTRAL
+ };
+ Q_ENUMS(Decision)
+
+ public:
+ Filter(QObject *pObject = 0);
+ // Filter(const Filter &rOther); // Use compiler default
+ virtual ~Filter();
+ // Filter &operator=(const Filter &rOther); // Use compiler default
+
+ Filter* next() const;
+ void setNext(Filter *pFilter);
+
+ virtual void activateOptions();
+ virtual Decision decide(const LoggingEvent &rEvent) const = 0;
+
+ private:
+ LogObjectPtr<Filter> mpNext;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Filter::Filter(QObject *pObject) :
+ LogObject(pObject),
+ mpNext(0)
+ {}
+
+ inline Filter::~Filter()
+ {}
+
+ inline Filter* Filter::next() const
+ { return mpNext; }
+
+ inline void Filter::activateOptions()
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::Filter, Q_COMPLEX_TYPE); // Use default
+Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Filter>, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_FILTER_H
diff --git a/ext/Log4Qt/src/systemlogappender.cpp b/ext/Log4Qt/src/systemlogappender.cpp
new file mode 100644
index 0000000..806a50a
--- /dev/null
+++ b/ext/Log4Qt/src/systemlogappender.cpp
@@ -0,0 +1,181 @@
+#include "systemlogappender.h"
+
+#include "layout.h"
+#include "level.h"
+#include "loggingevent.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+
+#if defined(Q_OS_WIN32)
+#ifndef UNICODE
+#define UNICODE
+#endif
+#include <qt_windows.h>
+#include <QtCore/QLibrary>
+
+
+
+typedef HANDLE(WINAPI*PDeregisterEventSource)(HANDLE);
+static PDeregisterEventSource pDeregisterEventSource = 0;
+typedef BOOL(WINAPI*PReportEvent)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCTSTR*,LPVOID);
+static PReportEvent pReportEvent = 0;
+typedef HANDLE(WINAPI*PRegisterEventSource)(LPCTSTR,LPCTSTR);
+static PRegisterEventSource pRegisterEventSource = 0;
+
+#define RESOLVE(name) p##name = (P##name)lib.resolve(#name);
+#define RESOLVEA(name) p##name = (P##name)lib.resolve(#name"A");
+#define RESOLVEW(name) p##name = (P##name)lib.resolve(#name"W");
+
+static bool winServiceInit()
+{
+ if (!pDeregisterEventSource) {
+ QLibrary lib("advapi32");
+
+ // only resolve unicode versions
+ RESOLVE(DeregisterEventSource);
+ RESOLVEW(ReportEvent);
+ RESOLVEW(RegisterEventSource);
+ }
+ return pDeregisterEventSource != 0;
+}
+#else
+
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+static QString encodeName(const QString &name, bool allowUpper = false)
+{
+ QString n = name.toLower();
+ QString legal = QLatin1String("abcdefghijklmnopqrstuvwxyz1234567890");
+ if (allowUpper)
+ legal += QLatin1String("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ int pos = 0;
+ while (pos < n.size()) {
+ if (legal.indexOf(n[pos]) == -1)
+ n.remove(pos, 1);
+ else
+ ++pos;
+ }
+ return n;
+}
+#endif //#if defined(Q_OS_WIN32)
+namespace Log4Qt {
+ SystemLogAppender::SystemLogAppender(QObject *parent) :
+ AppenderSkeleton(parent), ident(0)
+ {
+ setServiceName(QCoreApplication::applicationName());
+ }
+
+ SystemLogAppender::~SystemLogAppender()
+ {
+ if (ident)
+ delete[] ident;
+ }
+
+ void SystemLogAppender::append(const LoggingEvent &rEvent)
+ {
+ QString message(layout()->format(rEvent));
+
+#if defined(Q_OS_WIN32)
+ // Q_D(QtServiceBase);
+ if (!winServiceInit())
+ return;
+ WORD wType;
+ switch (rEvent.level().toInt()) {
+ case Level::WARN_INT:
+ wType = EVENTLOG_WARNING_TYPE;
+ break;
+ case Level::ERROR_INT:
+ wType = EVENTLOG_ERROR_TYPE;
+ break;
+ case Level::FATAL_INT:
+ wType = EVENTLOG_ERROR_TYPE;
+ break;
+ case Level::OFF_INT:
+ wType = EVENTLOG_SUCCESS;
+ break;
+ default:
+ wType = EVENTLOG_INFORMATION_TYPE;
+ break;
+ }
+
+ HANDLE h = pRegisterEventSource(0, (wchar_t *) serviceName().utf16());
+ if (h) {
+ int id = 0;
+ uint category = 0;
+ const wchar_t *msg = (wchar_t*) message.utf16();
+ const char *bindata = 0;//data.size() ? data.constData() : 0;
+ const int datasize = 0;
+ pReportEvent(h, wType, category, id, 0, 1, datasize,
+ (const wchar_t **) &msg, const_cast<char *> (bindata));
+ pDeregisterEventSource(h);
+ }
+#else
+
+ int st;
+ switch (rEvent.level().toInt()) {
+ case Level::WARN_INT:
+ st = LOG_WARNING;
+ break;
+ case Level::ERROR_INT:
+ st = LOG_ERR;
+ break;
+ case Level::FATAL_INT:
+ st = LOG_ERR;
+ break;
+ default:
+ st = LOG_INFO;
+ }
+
+ openlog(ident, LOG_PID, LOG_DAEMON);
+ foreach(const QString& line, message.split('\n', QString::SkipEmptyParts))
+ syslog(st, "%s", line.toLocal8Bit().constData());
+ closelog();
+
+#endif //#if defined(Q_OS_WIN32)
+ }
+
+ QString SystemLogAppender::serviceName() const
+ {
+ return mServiceName;
+ }
+
+ void SystemLogAppender::setServiceName(const QString& serviceName)
+ {
+ mServiceName = serviceName;
+
+#if !defined(Q_OS_WIN32)
+ if (ident)
+ delete[] ident;
+ QString tmp = encodeName(mServiceName, true);
+ int len = tmp.toLocal8Bit().size();
+ ident = new char[len + 1];
+ ident[len] = '\0';
+ ::memcpy(ident, tmp.toLocal8Bit().constData(), len);
+#endif
+ }
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug SystemLogAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "WriterAppender(" << "name:" << name() << " "
+ << "filter:" << firstFilter() << "isactive:" << isActive() << "isclosed:"
+ << isClosed() << "layout:" << layout_name << "referencecount:"
+ << referenceCount() << " " << "threshold:" << threshold().toString()
+ << "serviceName:" << serviceName() << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+}
+
diff --git a/ext/Log4Qt/src/systemlogappender.h b/ext/Log4Qt/src/systemlogappender.h
new file mode 100644
index 0000000..ad8325d
--- /dev/null
+++ b/ext/Log4Qt/src/systemlogappender.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: databaseappender.h
+ * created: December 2010
+ * author: Michael Filonenko
+ *
+ *
+ * Copyright 2010 Michael Filonenko
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#ifndef SYSTEMLOGAPPENDER_H
+#define SYSTEMLOGAPPENDER_H
+
+#include "appenderskeleton.h"
+
+namespace Log4Qt {
+
+ /*!
+ * \brief The class SystemLogAppender appends log events to a Event Log under win*
+ * and to syslog under *nix.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT SystemLogAppender: public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ /**
+ * The property holds the port used by the telenet appender.
+ *
+ * The default is QCoreApplication::applicationName()
+ *
+ * \sa serviceName(), setServiceName()
+ */
+ Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName)
+ public:
+ explicit SystemLogAppender(QObject *parent = 0);
+ ~SystemLogAppender();
+
+ bool requiresLayout() const;
+
+ /**
+ *
+ *
+ */
+ QString serviceName() const;
+ /**
+ *
+ */
+ void setServiceName(const QString& serviceName);
+
+ protected:
+ virtual void append(const Log4Qt::LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * The member function is used by
+ * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to
+ * generate class specific output.
+ *
+ * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug debug, const LogObject &rLogObject);
+#endif // QT_NO_DEBUG_STREAM
+ QString mServiceName;
+ char *ident;
+ };
+
+ inline bool SystemLogAppender::requiresLayout() const
+ {
+ return true;
+ }
+
+}
+
+#endif //#ifndef SYSTEMLOGAPPENDER_H
diff --git a/ext/Log4Qt/src/telnetappender.cpp b/ext/Log4Qt/src/telnetappender.cpp
new file mode 100644
index 0000000..4c96e9f
--- /dev/null
+++ b/ext/Log4Qt/src/telnetappender.cpp
@@ -0,0 +1,255 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: telnetappender.cpp
+ * created: July 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2010 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "telnetappender.h"
+
+#include <QtCore/QDebug>
+
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+#include <QtNetwork/QHostAddress>
+
+#include "layout.h"
+#include "loggingevent.h"
+
+namespace Log4Qt {
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+ /**************************************************************************
+ * Class implementation: TelnetAppender
+ **************************************************************************/
+
+ TelnetAppender::TelnetAppender(QObject *pParent) :
+ AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(23),
+ mpTcpServer(0), mImmediateFlush(false)
+ {
+ }
+
+ TelnetAppender::TelnetAppender(Layout *pLayout, QObject *pParent) :
+ AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(23),
+ mpTcpServer(0), mImmediateFlush(false)
+ {
+ setLayout(pLayout);
+ }
+
+ TelnetAppender::TelnetAppender(Layout *pLayout, int port, QObject *pParent) :
+ AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(port),
+ mpTcpServer(0), mImmediateFlush(false)
+ {
+ setLayout(pLayout);
+ }
+
+ TelnetAppender::TelnetAppender(Layout *pLayout, const QHostAddress& address,
+ int port, QObject *pParent) :
+ AppenderSkeleton(false, pParent), mAddress(address), mPort(port),
+ mpTcpServer(0), mImmediateFlush(false)
+ {
+ setLayout(pLayout);
+ }
+
+ TelnetAppender::~TelnetAppender()
+ {
+ close();
+ }
+
+ void TelnetAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ closeServer();
+ openServer();
+
+ AppenderSkeleton::activateOptions();
+ }
+
+ void TelnetAppender::close()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (isClosed())
+ return;
+
+ AppenderSkeleton::close();
+ closeServer();
+ }
+
+ void TelnetAppender::setAddress(const QHostAddress& address)
+ {
+ mAddress = address;
+ }
+
+ QHostAddress TelnetAppender::address() const
+ {
+ return mAddress;
+ }
+
+ void TelnetAppender::setPort(int port)
+ {
+ mPort = port;
+ }
+
+ int TelnetAppender::port() const
+ {
+ return mPort;
+ }
+
+ void TelnetAppender::setWelcomeMessage(const QString & welcomeMessage)
+ {
+ mWelcomeMessage = welcomeMessage;
+ }
+
+ bool TelnetAppender::requiresLayout() const
+ {
+ return true;
+ }
+
+ void TelnetAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "TelnetAppender::append()", "Lock must be held by caller");
+ Q_ASSERT_X(layout(), "TelnetAppender::append()", "Layout must not be null");
+
+ QString message(layout()->format(rEvent));
+
+ Q_FOREACH (QTcpSocket * pClientConnection, mTcpSockets)
+ {
+ pClientConnection->write(message.toLocal8Bit().constData());
+ if (immediateFlush())
+ pClientConnection->flush();
+ }
+ }
+
+ bool TelnetAppender::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "TelnetAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (!mpTcpServer && !mpTcpServer->isListening()) {
+ LogError
+ e =
+ LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a listing telnet server"),
+ APPENDER_TELNET_SERVER_NOT_RUNNING);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return AppenderSkeleton::checkEntryConditions();
+ }
+
+ void TelnetAppender::openServer()
+ {
+ mpTcpServer = new QTcpServer(this);
+ connect(mpTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
+ mpTcpServer->listen(mAddress, mPort);
+ }
+
+ void TelnetAppender::closeServer()
+ {
+ if (mpTcpServer)
+ mpTcpServer->close();
+
+ Q_FOREACH(QTcpSocket * pClientConnection, mTcpSockets)
+ delete pClientConnection;
+
+ mTcpSockets.clear();
+
+ delete mpTcpServer;
+ mpTcpServer = 0;
+ }
+
+ QList<QTcpSocket*> TelnetAppender::clients() const
+ {
+ return mTcpSockets;
+ }
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug TelnetAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "TelnetAppender(" << "name:" << name() << " "
+ << "filter:" << firstFilter() << "isactive:" << isActive()
+ << "isclosed:" << isClosed() << "layout:" << layout_name
+ << "referencecount:" << referenceCount() << " " << "threshold:"
+ << threshold().toString() << "address:" << address() << "port:"
+ << port() << " " << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+ bool TelnetAppender::handleIoErrors() const
+ {
+ // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller")
+ return false;
+ }
+
+ void TelnetAppender::onNewConnection()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (mpTcpServer && mpTcpServer->hasPendingConnections()) {
+ QTcpSocket * pClientConnection = mpTcpServer->nextPendingConnection();
+ if (pClientConnection) {
+ mTcpSockets.append(pClientConnection);
+ connect(pClientConnection, SIGNAL(disconnected()), this,
+ SLOT(onClientDisconnected()));
+ sendWelcomeMessage(pClientConnection);
+ }
+ }
+ }
+
+ void TelnetAppender::sendWelcomeMessage(QTcpSocket * pClientConnection)
+ {
+ if (mWelcomeMessage.isEmpty())
+ return;
+
+ pClientConnection->write(mWelcomeMessage.toLocal8Bit().constData());
+ }
+
+ void TelnetAppender::onClientDisconnected()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ QTcpSocket* pClientConnection = qobject_cast<QTcpSocket*> (sender());
+ if (pClientConnection) {
+ mTcpSockets.removeOne(pClientConnection);
+ pClientConnection->deleteLater();
+ }
+ }
+
+/******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/telnetappender.h b/ext/Log4Qt/src/telnetappender.h
new file mode 100644
index 0000000..b1c2021
--- /dev/null
+++ b/ext/Log4Qt/src/telnetappender.h
@@ -0,0 +1,228 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: telnetappender.h
+ * created: July 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2010 Andreas Bacher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_TELNETAPPENDER_H
+#define LOG4QT_TELNETAPPENDER_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+#include <QtCore/QString>
+
+#include <QtNetwork/QHostAddress>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QTcpServer;
+class QTcpSocket;
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class TelnetAppender appends log events to a read-only socket (telnet)
+ *T
+ * \note All the functions declared in this class are thread-safe.
+ * &nbsp;
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT TelnetAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the port used by the telenet appender.
+ *
+ * The default is 23 for the port.
+ *
+ * \sa port, port(), setPort()
+ */
+ Q_PROPERTY(int port READ port WRITE setPort)
+
+ /*!
+ * The property holds, if the writer flushes after all write operations.
+ *
+ * The default is false for flushing.
+ *
+ * \sa immediateFlush(), setImmediateFlush()
+ */
+ Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush)
+
+ Q_PROPERTY(QHostAddress address READ address WRITE setAddress)
+
+ public:
+ TelnetAppender(QObject *pParent = 0);
+ TelnetAppender(Layout *pLayout,
+ QObject *pParent = 0);
+ TelnetAppender(Layout *pLayout,
+ const QHostAddress& address,
+ int port,
+ QObject *pParent = 0);
+ TelnetAppender(Layout *pLayout,
+ int port,
+ QObject *pParent = 0);
+ virtual ~TelnetAppender();
+
+ private:
+ TelnetAppender(const TelnetAppender &rOther); // Not implemented
+ TelnetAppender &operator=(const TelnetAppender &rOther); // Not implemented
+
+ public:
+ virtual bool requiresLayout() const;
+ virtual void activateOptions();
+ virtual void close();
+
+ /*!
+ * Sets the listening port of the telnet server (default = 23)
+ */
+ void setPort(int port);
+ /*!
+ * Returns the listening port of the telnet server
+ */
+ int port() const;
+ /*!
+ * Set the property immediate flush (default: false)
+ */
+ void setImmediateFlush(bool immediateFlush);
+ /*!
+ * Returns <true> immediate flush is enabled
+ */
+ bool immediateFlush() const;
+
+ /*!
+ * Sets the listenning address of the telnet server (default QHostAddress::Any)
+ */
+ void setAddress(const QHostAddress& address);
+ /*!
+ * Returns the listenning address of the telnet server
+ */
+ QHostAddress address() const;
+ /*!
+ * Set the welcome message which is send on
+ */
+ void setWelcomeMessage(const QString & welcomeMessage);
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * AppenderSkeleton::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+ /*!
+ * Creates and starts (listening) the TCP server
+ */
+ void openServer();
+ /*!
+ * Stops and destroys the TCP server
+ */
+ void closeServer();
+
+ QList<QTcpSocket*> clients() const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %TelnetAppender(name:"WA" filter:"0x0"
+ * isactive:false isclosed:false layout:"TTCC"
+ * referencecount:1 threshold:"NULL port:"23")
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ virtual bool handleIoErrors() const;
+
+ private slots:
+ /*!
+ * Handles a new incomming connection
+ */
+ void onNewConnection();
+ /*!
+ * Handles a client disconnect
+ */
+ void onClientDisconnected();
+
+ private:
+ QHostAddress mAddress;
+ int mPort;
+ QTcpServer * mpTcpServer;
+ QList<QTcpSocket*> mTcpSockets;
+ QString mWelcomeMessage;
+ volatile bool mImmediateFlush;
+
+ void sendWelcomeMessage(QTcpSocket * pClientConnection);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool TelnetAppender::immediateFlush() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mImmediateFlush; }
+
+ inline void TelnetAppender::setImmediateFlush(bool immediateFlush)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mImmediateFlush = immediateFlush; }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::TelnetAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_TELNETAPPENDER_H
diff --git a/ext/Log4Qt/src/ttcclayout.cpp b/ext/Log4Qt/src/ttcclayout.cpp
new file mode 100755
index 0000000..cb1d36f
--- /dev/null
+++ b/ext/Log4Qt/src/ttcclayout.cpp
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: ttcclayout.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "ttcclayout.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDateTime>
+#include "helpers/datetime.h"
+#include "helpers/patternformatter.h"
+#include "logger.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: TTCCLayout
+ **************************************************************************/
+
+
+ TTCCLayout::TTCCLayout(QObject *pParent) :
+ Layout(pParent),
+ mCategoryPrefixing(true),
+ mContextPrinting(true),
+ mDateFormat(),
+ mThreadPrinting(true),
+ mpPatternFormatter(0)
+ {
+ setDateFormat(RELATIVE);
+ }
+
+
+ TTCCLayout::TTCCLayout(const QString &rDateFormat,
+ QObject *pParent) :
+ Layout(pParent),
+ mCategoryPrefixing(true),
+ mContextPrinting(true),
+ mDateFormat(rDateFormat),
+ mThreadPrinting(true),
+ mpPatternFormatter(0)
+ {
+ }
+
+
+ TTCCLayout::TTCCLayout(DateFormat dateFormat,
+ QObject *pParent) :
+ Layout(pParent),
+ mCategoryPrefixing(true),
+ mContextPrinting(true),
+ mDateFormat(),
+ mThreadPrinting(true),
+ mpPatternFormatter(0)
+ {
+ setDateFormat(dateFormat);
+ }
+
+
+ TTCCLayout::~TTCCLayout()
+ {
+ delete mpPatternFormatter;
+ }
+
+
+ void TTCCLayout::setDateFormat(DateFormat dateFormat)
+ {
+ switch (dateFormat)
+ {
+ case NONE:
+ setDateFormat(QLatin1String("NONE"));
+ break;
+ case ISO8601:
+ setDateFormat(QLatin1String("ISO8601"));
+ break;
+ case ABSOLUTE:
+ setDateFormat(QLatin1String("ABSOLUTE"));
+ break;
+ case DATE:
+ setDateFormat(QLatin1String("DATE"));
+ break;
+ case RELATIVE:
+ setDateFormat(QLatin1String("RELATIVE"));
+ break;
+ default:
+ Q_ASSERT_X(false, "TTCCLayout::setDateFormat", "Unkown DateFormat");
+ setDateFormat(QString());
+ }
+ }
+
+
+ QString TTCCLayout::format(const LoggingEvent &rEvent)
+ {
+ Q_ASSERT_X(mpPatternFormatter, "TTCCLayout::format()", "mpPatternConverter must not be null");
+
+ return mpPatternFormatter->format(rEvent);
+ }
+
+
+ void TTCCLayout::updatePatternFormatter()
+ {
+ QString pattern;
+
+ pattern += QLatin1String("%d{") + mDateFormat + QLatin1String("}");
+ if (mThreadPrinting)
+ pattern += QLatin1String(" [%t]");
+ pattern += QLatin1String(" %-5p");
+ if (mCategoryPrefixing)
+ pattern += QLatin1String(" %c");
+ if (mContextPrinting)
+ pattern += QLatin1String(" %x");
+ pattern += QLatin1String(" - %m%n");
+
+ delete mpPatternFormatter;
+ mpPatternFormatter = new PatternFormatter(pattern);
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug TTCCLayout::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "TTCCLayout("
+ << "name:" << name() << " "
+ << "categoryprefixing:" << categoryPrefixing() << " "
+ << "contextprinting:" << contextPrinting() << " "
+ << "dateformat:" << dateFormat() << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threadprinting:" << threadPrinting()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/ttcclayout.h b/ext/Log4Qt/src/ttcclayout.h
new file mode 100755
index 0000000..3375a67
--- /dev/null
+++ b/ext/Log4Qt/src/ttcclayout.h
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: ttcclayout.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_TTCCLAYOUT_H
+#define LOG4QT_TTCCLAYOUT_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "layout.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class LoggingEvent;
+ class PatternFormatter;
+
+ /*!
+ * \brief The class TTCCLayout outputs the time, thread, logger and nested
+ * diagnostic context information of a logging event.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT TTCCLayout : public Layout
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds if the logger name is part of the formatted output.
+ *
+ * The default value is true for including the logger name.
+ *
+ * \sa categoryPrefixing(), setCategoryPrefixing()
+ */
+ Q_PROPERTY(bool categoryPrefixing READ categoryPrefixing WRITE setCategoryPrefixing)
+
+ /*!
+ * The property holds if the nested context information is part of the
+ * formatted output.
+ *
+ * The default value it true for including the nested context information.
+ *
+ * \sa contextPrinting(), setContextPrinting()
+ */
+ Q_PROPERTY(bool contextPrinting READ contextPrinting WRITE setContextPrinting)
+
+ /*!
+ * The property holds the date format used by the layout.
+ *
+ * The default date format is "RELATIVE".
+ *
+ * \sa dateFormat(), setDateFormat()
+ */
+ Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat)
+
+ /*!
+ * The property holds if the thread name is part of the formatted output.
+ *
+ * The default value it true for including the thread name.
+ *
+ * \sa threadPrinting(), setThreadPrinting()
+ */
+ Q_PROPERTY(bool threadPrinting READ threadPrinting WRITE setThreadPrinting)
+
+ public:
+ /*!
+ * The enum DateFormat defines constants for date formats.
+ *
+ * \sa setDateFormat(DateFormat), DateTime::toString()
+ */
+ enum DateFormat
+ {
+ /*! The none date format string is "NONE". */
+ NONE,
+ /*!
+ * The iso8601 date format string is "ISO8601". The date will be
+ * formatted as yyyy-MM-dd hh:mm:ss.zzz.
+ */
+ ISO8601,
+ /*!
+ * The absolute date format string is "ABSOLUTE". The date will be
+ * formatted as HH:mm:ss.zzz.
+ */
+ ABSOLUTE,
+ /*!
+ * The date date format string is "DATE". The date will be formatted
+ * as MMM YYYY HH:mm:ss.zzzz.
+ */
+ DATE,
+ /*!
+ * The relative date format string is "RELATIVE". The date will be
+ * formatted as milliseconds since start of the program.
+ */
+ RELATIVE
+ };
+ Q_ENUMS(DateFormat)
+
+ TTCCLayout(QObject *pParent = 0);
+ TTCCLayout(const QString &rDateFormat,
+ QObject *pParent = 0);
+
+ /*!
+ * Creates a TTCCLayout with the date formar value specified by
+ * the \a dateFormat constant and the parent \a pParent.
+ */
+ TTCCLayout(DateFormat dateFormat,
+ QObject *pParent = 0);
+
+ virtual ~TTCCLayout();
+ private:
+ TTCCLayout(const TTCCLayout &rOther); // Not implemented
+ TTCCLayout &operator=(const TTCCLayout &rOther); // Not implemented
+
+ public:
+ bool categoryPrefixing() const;
+ bool contextPrinting() const;
+ QString dateFormat() const;
+ // JAVA: bool ignoresThrowable() const;
+ bool threadPrinting() const;
+ void setCategoryPrefixing(bool categoryPrefixing);
+ void setContextPrinting(bool contextPrinting);
+ void setDateFormat(const QString &rDateFormat);
+
+ /*!
+ * Sets the date format to the value specified by the \a dateFormat
+ * constant.
+ */
+ void setDateFormat(DateFormat dateFormat);
+
+ // JAVA: setIgnoresThrowable(bool ignoresThrowable);
+ void setThreadPrinting(bool threadPrinting);
+ virtual QString format(const LoggingEvent &rEvent);
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %TTCCLayout(name:"TTCC" categoryprefixing:true
+ * contextprinting:true dateformat:"ISO8601"
+ * referencecount:1 threadprinting:true)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ void updatePatternFormatter();
+
+ private:
+ bool mCategoryPrefixing;
+ bool mContextPrinting;
+ QString mDateFormat;
+ bool mThreadPrinting;
+ PatternFormatter *mpPatternFormatter;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool TTCCLayout::categoryPrefixing() const
+ { return mCategoryPrefixing; }
+
+ inline bool TTCCLayout::contextPrinting() const
+ { return mContextPrinting; }
+
+ inline QString TTCCLayout::dateFormat() const
+ { return mDateFormat; }
+
+ inline bool TTCCLayout::threadPrinting() const
+ { return mThreadPrinting; }
+
+ inline void TTCCLayout::setCategoryPrefixing(bool categoryPrefixing)
+ { mCategoryPrefixing = categoryPrefixing;
+ updatePatternFormatter(); }
+
+ inline void TTCCLayout::setContextPrinting(bool contextPrinting)
+ { mContextPrinting = contextPrinting;
+ updatePatternFormatter(); }
+
+ inline void TTCCLayout::setDateFormat(const QString &rDateFormat)
+ { mDateFormat = rDateFormat;
+ updatePatternFormatter(); }
+
+ inline void TTCCLayout::setThreadPrinting(bool threadPrinting)
+ { mThreadPrinting = threadPrinting;
+ updatePatternFormatter(); }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::TTCCLayout, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_TTCCLAYOUT_H
diff --git a/ext/Log4Qt/src/varia/debugappender.cpp b/ext/Log4Qt/src/varia/debugappender.cpp
new file mode 100755
index 0000000..c77ee33
--- /dev/null
+++ b/ext/Log4Qt/src/varia/debugappender.cpp
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: debugappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/debugappender.h"
+
+#include <QtCore/QDebug>
+#include <iostream>
+
+#include "layout.h"
+#include "loggingevent.h"
+
+#if defined(Q_OS_WIN32)
+#include <windows.h>
+#endif
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DebugAppender
+ **************************************************************************/
+
+
+ DebugAppender::DebugAppender(Layout *pLayout,
+ QObject *pParent) :
+ AppenderSkeleton(pParent)
+ {
+ setLayout(pLayout);
+ }
+
+
+ bool DebugAppender::requiresLayout() const
+ {
+ return true;
+ }
+
+
+ void DebugAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "DebugAppender::append()", "Lock must be held by caller");
+ Q_ASSERT_X(layout(), "DebugAppender::append()", "Layout must not be null");
+
+ QString message(layout()->format(rEvent));
+#if defined(Q_OS_WIN32)
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ QT_WA({
+ OutputDebugStringW(reinterpret_cast<const WCHAR*>(message.utf16()));
+ }, {
+ OutputDebugStringA(message.toLocal8Bit().data());
+ });
+#else
+ OutputDebugStringW(reinterpret_cast<const WCHAR*>(message.utf16()));
+#endif
+#else
+ std::cerr << message.toLocal8Bit().constData() << std::endl;
+ std::cerr << std::flush;
+#endif
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug DebugAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "DebugAppender("
+ << "name:" << name() << " "
+ << "filter:" << firstFilter() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namspace Log4Qt
diff --git a/ext/Log4Qt/src/varia/debugappender.h b/ext/Log4Qt/src/varia/debugappender.h
new file mode 100755
index 0000000..4df6c02
--- /dev/null
+++ b/ext/Log4Qt/src/varia/debugappender.h
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: debugappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_DEBUGAPPENDER_H
+#define LOG4QT_DEBUGAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DebugAppender appends logging events to the platform
+ * specific debug output.
+ *
+ * A DebugAppender appends to the Debugger on Windows and to stderr on all
+ * other systems.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT DebugAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ public:
+ /*!
+ * Creates a DebugAppender.
+ */
+ DebugAppender(QObject *pParent = 0);
+
+ /*!
+ * Creates a DebugAppender with the specified layout \a pLayout
+ */
+ DebugAppender(Layout *pLayout,
+ QObject *pParent = 0);
+
+ // virtual ~DebugAppender(); // Use compiler default
+ private:
+ DebugAppender(const DebugAppender &rOther); // Not implemented
+ DebugAppender &operator=(const DebugAppender &rOther); // Not implemented
+
+ public:
+ /*!
+ * The DebugAppended requires a layout. The function returns true.
+ *
+ * \sa setLayout()
+ */
+ virtual bool requiresLayout() const;
+
+ protected:
+ /*!
+ * Appends the specified logging event \a rEvent to the debug output.
+ * The output is formatted using the appender's layout.
+ *
+ * The method is called by the AppenderSkeleton::doAppend() after it
+ * the entry conditions have been tested and it has been found that the
+ * logging event needs to be appended.
+ *
+ * \sa setLayout(), AppenderSkeleton::doAppend(), checkEntryConditions()
+ */
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %DebugAppender(name:"DA" filter:0x3bee6b8 isactive:true isclosed:false
+ * layout:"SL" referencecount:1 threshold:"NULL")
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline DebugAppender::DebugAppender(QObject *pParent) :
+ AppenderSkeleton(pParent)
+ {}
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::DebugAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_DEBUGAPPENDER_H
diff --git a/ext/Log4Qt/src/varia/denyallfilter.cpp b/ext/Log4Qt/src/varia/denyallfilter.cpp
new file mode 100755
index 0000000..2a7bd1f
--- /dev/null
+++ b/ext/Log4Qt/src/varia/denyallfilter.cpp
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: denyallfilter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/denyallfilter.h"
+
+#include <QtCore/QDebug>
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug DenyAllFilter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "DenyAllFilter("
+ << "next:" << next()
+ << "referencecount:" << referenceCount() << " "
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/denyallfilter.h b/ext/Log4Qt/src/varia/denyallfilter.h
new file mode 100755
index 0000000..2106542
--- /dev/null
+++ b/ext/Log4Qt/src/varia/denyallfilter.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: denyallfilter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed a compile error on VS 2008 by using Q_UNUSED(&rEvent)
+ * instead of Q_UNUSED(rEvent)
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_DENYALLFILTER_H
+#define LOG4QT_DENYALLFILTER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "spi/filter.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DenyAllFilter drops all logging events
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT DenyAllFilter : public Filter
+ {
+ Q_OBJECT
+
+ public:
+ DenyAllFilter(QObject *pParent = 0);
+ // DenyAllFilter(const DenyAllFilter &rOther); // Use compiler default
+ // virtual ~DenyAllFilter(); // Use compiler default
+ // DenyAllFilter &operator=(const DenyAllFilter &rOther); // Use compiler default
+
+ virtual Decision decide(const LoggingEvent &rEvent) const;
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %DenyAllFilter(next:QObject(0x0) referencecount:1 )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /*************************************************************************
+ * Operators, Helper
+ *************************************************************************/
+
+
+ /*************************************************************************
+ * Inline
+ *************************************************************************/
+
+ inline DenyAllFilter::DenyAllFilter(QObject *pParent) :
+ Filter(pParent)
+ {}
+
+ inline Filter::Decision DenyAllFilter::decide(const LoggingEvent &rEvent) const
+ { Q_UNUSED(&rEvent); return Filter::DENY; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::DenyAllFilter, Q_MOVABLE_TYPE); // Use default
+
+
+#endif // LOG4QT_DENYALLFILTER_H
diff --git a/ext/Log4Qt/src/varia/levelmatchfilter.cpp b/ext/Log4Qt/src/varia/levelmatchfilter.cpp
new file mode 100755
index 0000000..6b5a815
--- /dev/null
+++ b/ext/Log4Qt/src/varia/levelmatchfilter.cpp
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: levelmatchfilter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/levelmatchfilter.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+
+
+ LevelMatchFilter::LevelMatchFilter(QObject *pParent) :
+ Filter(pParent),
+ mAcceptOnMatch(true),
+ mLevelToMatch(Level::NULL_INT)
+ {}
+
+
+ Filter::Decision LevelMatchFilter::decide(const LoggingEvent &rEvent) const
+ {
+ if (mLevelToMatch == Level::NULL_INT ||
+ rEvent.level() != mLevelToMatch)
+ return Filter::NEUTRAL;
+
+ if (mAcceptOnMatch)
+ return Filter::ACCEPT;
+ else
+ return Filter::DENY;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug LevelMatchFilter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "LevelMatchFilter("
+ << "acceptonmatch:" << mAcceptOnMatch << " "
+ << "leveltomatch:" << mLevelToMatch.toString() << " "
+ << "next:" << next()
+ << "referencecount:" << referenceCount() << " "
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/levelmatchfilter.h b/ext/Log4Qt/src/varia/levelmatchfilter.h
new file mode 100755
index 0000000..f74c64b
--- /dev/null
+++ b/ext/Log4Qt/src/varia/levelmatchfilter.h
@@ -0,0 +1,137 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: levelmatchfilter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LEVELMATCHFILTER_H
+#define LOG4QT_LEVELMATCHFILTER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "spi/filter.h"
+
+#include "level.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class LevelMatchFilter allows logging events with a specified
+ * level.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT LevelMatchFilter : public Filter
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds if an event is accpeted on a match.
+ *
+ * The default is true.
+ *
+ * \sa acceptOnMatch(), setAcceptOnMatch()
+ */
+ Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch)
+
+ /*!
+ * The property holds the level to match for this filter.
+ *
+ * The default is Level::NULL_INT.
+ *
+ * \sa levelToMatch(), setLevelToMatch()
+ */
+ Q_PROPERTY(Log4Qt::Level levelToMatch READ levelToMatch WRITE setLevelToMatch)
+
+ public:
+ LevelMatchFilter(QObject *pParent = 0);
+ // LevelMatchFilter(const LevelMatchFilter &rOther); // Use compiler default
+ // virtual ~LevelMatchFilter(); // Use compiler default
+ // LevelMatchFilter &operator=(const LevelMatchFilter &rOther); // Use compiler default
+
+ bool acceptOnMatch() const;
+ Level levelToMatch() const;
+ void setAcceptOnMatch(bool accept);
+ void setLevelToMatch(Level level);
+
+ virtual Decision decide(const LoggingEvent &rEvent) const;
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %LevelMatchFilter(acceptonmatch:true leveltomatch:"WARN"
+ * next:Log4Qt::DenyAllFilter(0x3bce3a8)
+ * referencecount:1 )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ bool mAcceptOnMatch;
+ Level mLevelToMatch;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool LevelMatchFilter::acceptOnMatch() const
+ { return mAcceptOnMatch; }
+
+ inline Level LevelMatchFilter::levelToMatch() const
+ { return mLevelToMatch; }
+
+ inline void LevelMatchFilter::setAcceptOnMatch(bool accept)
+ { mAcceptOnMatch = accept; }
+
+ inline void LevelMatchFilter::setLevelToMatch(Level level)
+ { mLevelToMatch = level; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LevelMatchFilter, Q_MOVABLE_TYPE); // Use default
+
+
+#endif // LOG4QT_LEVELMATCHFILTER_H
diff --git a/ext/Log4Qt/src/varia/levelrangefilter.cpp b/ext/Log4Qt/src/varia/levelrangefilter.cpp
new file mode 100755
index 0000000..73f42c5
--- /dev/null
+++ b/ext/Log4Qt/src/varia/levelrangefilter.cpp
@@ -0,0 +1,104 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: levelrangefilter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/levelrangefilter.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+
+
+namespace Log4Qt
+{
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * C helper functions
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Class implementation: Filter
+ ******************************************************************************/
+
+
+LevelRangeFilter::LevelRangeFilter(QObject *pParent) :
+ Filter(pParent),
+ mAcceptOnMatch(true),
+ mLevelMin(Level::NULL_INT),
+ mLevelMax(Level::OFF_INT)
+{}
+
+
+Filter::Decision LevelRangeFilter::decide(const LoggingEvent &rEvent) const
+{
+ if (rEvent.level() < mLevelMin)
+ return Filter::DENY;
+
+ if (rEvent.level() > mLevelMax)
+ return Filter::DENY;
+
+ if (mAcceptOnMatch)
+ return Filter::ACCEPT;
+ else
+ return Filter::NEUTRAL;
+}
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug LevelRangeFilter::debug(QDebug &rDebug) const
+{
+ rDebug.nospace() << "LevelRangeFilter("
+ << "acceptonmatch:" << mAcceptOnMatch << " "
+ << "levelmin:" << mLevelMin.toString() << " "
+ << "levelmax:" << mLevelMax.toString() << " "
+ << "next:" << next()
+ << "referencecount:" << referenceCount() << " "
+ << ")";
+ return rDebug.space();
+}
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+/******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/levelrangefilter.h b/ext/Log4Qt/src/varia/levelrangefilter.h
new file mode 100755
index 0000000..e148d9c
--- /dev/null
+++ b/ext/Log4Qt/src/varia/levelrangefilter.h
@@ -0,0 +1,153 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: levelrangefilter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LEVELRANGEFILTER_H
+#define LOG4QT_LEVELRANGEFILTER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "spi/filter.h"
+
+#include "level.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class LevelMatchFilter allows logging events with levels in a
+ * specified range.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT LevelRangeFilter : public Filter
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds if an event is accpeted on a match.
+ *
+ * The default is true.
+ *
+ * \sa acceptOnMatch(), acceptOnMatch()
+ */
+ Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch)
+
+ /*!
+ * The property holds the maximum level of the range for this filter.
+ *
+ * The default is Level::OFF_INT.
+ *
+ * \sa levelMax(), setLevelMax()
+ */
+ Q_PROPERTY(Log4Qt::Level levelMax READ levelMax WRITE setLevelMax)
+
+ /*!
+ * The property holds the minimum level of the range for this filter.
+ *
+ * The default is Level::NULL_INT.
+ *
+ * \sa levelMin(), setLevelMin()
+ */
+ Q_PROPERTY(Log4Qt::Level levelMin READ levelMin WRITE setLevelMin)
+
+ public:
+ LevelRangeFilter(QObject *pParent = 0);
+ // LevelRangeFilter(const LevelRangeFilter &rOther); // Use compiler default
+ // virtual ~LevelRangeFilter(); // Use compiler default
+ // LevelRangeFilter &operator=(const LevelRangeFilter &rOther); // Use compiler default
+
+ bool acceptOnMatch() const;
+ Level levelMax() const;
+ Level levelMin() const;
+ void setAcceptOnMatch(bool accept);
+ void setLevelMax(Level level);
+ void setLevelMin(Level level);
+
+ virtual Decision decide(const LoggingEvent &rEvent) const;
+
+ protected:
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug
+ * and returns the stream.
+ *
+ * <tt>
+ * %LevelRangeFilter(acceptonmatch:true levelmin:"ERROR" levelmax:"FATAL"
+ * next:Log4Qt::LevelMatchFilter(0x3bcd960)
+ * referencecount:1 )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+
+ private:
+ bool mAcceptOnMatch;
+ Level mLevelMin;
+ Level mLevelMax;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool LevelRangeFilter::acceptOnMatch() const
+ { return mAcceptOnMatch; }
+
+ inline Level LevelRangeFilter::levelMax() const
+ { return mLevelMax; }
+
+ inline Level LevelRangeFilter::levelMin() const
+ { return mLevelMin; }
+
+ inline void LevelRangeFilter::setAcceptOnMatch(bool accept)
+ { mAcceptOnMatch = accept; }
+
+ inline void LevelRangeFilter::setLevelMax(Level level)
+ { mLevelMax = level; }
+
+ inline void LevelRangeFilter::setLevelMin(Level level)
+ { mLevelMin = level; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LevelRangeFilter, Q_MOVABLE_TYPE); // Use default
+
+
+#endif // LOG4QT_LEVELRANGEFILTER_H
diff --git a/ext/Log4Qt/src/varia/listappender.cpp b/ext/Log4Qt/src/varia/listappender.cpp
new file mode 100755
index 0000000..6b8aa39
--- /dev/null
+++ b/ext/Log4Qt/src/varia/listappender.cpp
@@ -0,0 +1,153 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: listappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/listappender.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ListAppender
+ **************************************************************************/
+
+
+ ListAppender::ListAppender(QObject *pParent) :
+ AppenderSkeleton(pParent),
+ mConfiguratorList(false),
+ mList(),
+ mMaxCount(0)
+ {
+ }
+
+
+ ListAppender::~ListAppender()
+ {
+ }
+
+
+ QList<LoggingEvent> ListAppender::list() const
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ return mList;
+ }
+
+
+ void ListAppender::setMaxCount(int n)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (n < 0)
+ {
+ logger()->warn("Attempt to set maximum count for appender '%1' to %2. Using zero instead", name(), n);
+ n = 0;
+ }
+ mMaxCount = n;
+ ensureMaxCount();
+ }
+
+
+ QList<LoggingEvent> ListAppender::clearList()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ QList<LoggingEvent> result = mList;
+ mList.clear();
+ return result;
+ }
+
+
+ // bool ListAppender::requiresLayout() const;
+
+
+ void ListAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "ListAppender::append()", "Lock must be held by caller")
+
+ if ((mMaxCount <= 0) || (mList.size() < mMaxCount))
+ mList << rEvent;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug ListAppender::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "ListAppender("
+ << "name:" << name() << " "
+ << "count:" << list().count() << " "
+ << "filter:" << firstFilter() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "maxcount:" << maxCount() << " "
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+ void ListAppender::ensureMaxCount()
+ {
+ // Q_ASSERT_X(, "ListAppender::ensureMaxCount()", "Lock must be held by caller")
+
+ if (mMaxCount <= 0)
+ return;
+
+ while (mList.size() > mMaxCount)
+ mList.removeFirst();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/listappender.h b/ext/Log4Qt/src/varia/listappender.h
new file mode 100755
index 0000000..f5e9df0
--- /dev/null
+++ b/ext/Log4Qt/src/varia/listappender.h
@@ -0,0 +1,174 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: listappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LISTAPPENDER_H
+#define LOG4QT_LISTAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include "loggingevent.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class ListAppender appends logging events to a list for later
+ * processing.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT ListAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds, if the Appender is used by a configurator.
+ *
+ * The default value is false for not being a configurator list.
+ *
+ * \sa configuratorList(), setConfiguratorList()
+ */
+ Q_PROPERTY(bool configuratorList READ configuratorList WRITE setConfiguratorList)
+
+ /*!
+ * The property holds the maximum count used by the appender.
+ *
+ * The default maximum count is -1 for unlimited.
+ *
+ * \sa maxCount(), setMaxCount()
+ */
+ Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount)
+
+ public:
+ ListAppender(QObject *pParent = 0);
+ virtual ~ListAppender();
+ private:
+ ListAppender(const ListAppender &rOther); // Not implemented
+ ListAppender &operator=(const ListAppender &rOther); // Not implemented
+
+ public:
+ /*!
+ * Returns true, if the appender is used by a configurator. Otherweise it returns
+ * false.
+ *
+ * \sa setConfiguratorList()
+ */
+ bool configuratorList() const;
+
+ QList<LoggingEvent> list() const;
+ int maxCount() const;
+
+ /*!
+ * Sets that the appender is used by a configurator. If set to true, the appender
+ * will not be removed from a Logger when Logger::removeAllAppenders()is called.
+ * This way the appender can collect events raised during the configuration process.
+ *
+ * \sa configuratorList(), BasicConfigurator, PropertyConfigurator,
+ * ConfiguratorHelper::configureError()
+ */
+ void setConfiguratorList(bool isConfiguratorList);
+
+ void setMaxCount(int n);
+
+ QList<LoggingEvent> clearList();
+ virtual bool requiresLayout() const;
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %ListAppender(name:"LA" count:1 filter:0x41fa488 isactive:true
+ * isclosed:false maxcount:170 referencecount:1
+ * threshold:"TRACE_SET")
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ /*!
+ * Ensures that the count of events is less or equal then the maxium
+ * count. If the list contains too many items, items are deleted from
+ * the begin of the list.
+ */
+ void ensureMaxCount();
+
+ private:
+ volatile bool mConfiguratorList;
+ QList<LoggingEvent> mList;
+ volatile int mMaxCount;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool ListAppender::configuratorList() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mConfiguratorList; }
+
+ inline int ListAppender::maxCount() const
+ { return mMaxCount; }
+
+ inline void ListAppender::setConfiguratorList(bool isConfiguratorList)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mConfiguratorList = isConfiguratorList; }
+
+ inline bool ListAppender::requiresLayout() const
+ { return false; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::ListAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LISTAPPENDER_H
diff --git a/ext/Log4Qt/src/varia/nullappender.cpp b/ext/Log4Qt/src/varia/nullappender.cpp
new file mode 100755
index 0000000..ed190b6
--- /dev/null
+++ b/ext/Log4Qt/src/varia/nullappender.cpp
@@ -0,0 +1,104 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: nullappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/nullappender.h"
+
+#include <QtCore/QDebug>
+#include "layout.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: NullAppender
+ **************************************************************************/
+
+
+ NullAppender::NullAppender(QObject *pParent) :
+ AppenderSkeleton(false, pParent)
+ {
+ }
+
+
+ NullAppender::~NullAppender()
+ {
+ close();
+ }
+
+
+ void NullAppender::append(const LoggingEvent &rEvent)
+ {
+ Q_UNUSED(rEvent);
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug NullAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+
+ rDebug.nospace() << "NullAppender("
+ << "name:" << name() << " "
+ << "isactive:" << isActive() << " "
+ << "isclosed:" << isClosed() << " "
+ << "layout:" << layout_name << " "
+ << "threshold:" << threshold().toString() << " "
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/nullappender.h b/ext/Log4Qt/src/varia/nullappender.h
new file mode 100755
index 0000000..102f71f
--- /dev/null
+++ b/ext/Log4Qt/src/varia/nullappender.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: nullappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_NULLAPPENDER_H
+#define LOG4QT_NULLAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+/*!
+ * \brief The class NullAppender ignores all requests to append.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \note The ownership and lifetime of objects of this class are managed. See
+ * \ref Ownership "Object ownership" for more details.
+ */
+class LOG4QT_EXPORT NullAppender : public AppenderSkeleton
+{
+ Q_OBJECT
+
+public:
+ NullAppender(QObject *pParent = 0);
+ virtual ~NullAppender();
+private:
+ NullAppender(const NullAppender &rOther); // Not implemented
+ NullAppender &operator=(const NullAppender &rOther); // Not implemented
+
+public:
+ virtual bool requiresLayout() const;
+
+protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %NullAppender()
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+};
+
+
+/******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Inline
+ ******************************************************************************/
+
+inline bool NullAppender::requiresLayout() const
+{ return false; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::NullAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_NULLAPPENDER_H
diff --git a/ext/Log4Qt/src/varia/stringmatchfilter.cpp b/ext/Log4Qt/src/varia/stringmatchfilter.cpp
new file mode 100755
index 0000000..cdc41d0
--- /dev/null
+++ b/ext/Log4Qt/src/varia/stringmatchfilter.cpp
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: stringmatchfilter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "varia/stringmatchfilter.h"
+
+#include <QtCore/QDebug>
+#include "loggingevent.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+
+
+ StringMatchFilter::StringMatchFilter(QObject *pParent) :
+ Filter(pParent),
+ mAcceptOnMatch(true),
+ mStringToMatch()
+ {}
+
+
+ Filter::Decision StringMatchFilter::decide(const LoggingEvent &rEvent) const
+ {
+ if (rEvent.message().isEmpty() ||
+ mStringToMatch.isEmpty() ||
+ rEvent.message().indexOf(mStringToMatch) < 0)
+ return Filter::NEUTRAL;
+
+ if (mAcceptOnMatch)
+ return Filter::ACCEPT;
+ else
+ return Filter::DENY;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug StringMatchFilter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "StringMatchFilter("
+ << "acceptonmatch:" << mAcceptOnMatch << " "
+ << "referencecount:" << referenceCount() << " "
+ << "stringtomatch:" << mStringToMatch << " "
+ << "next:" << next()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/varia/stringmatchfilter.h b/ext/Log4Qt/src/varia/stringmatchfilter.h
new file mode 100755
index 0000000..eb2dac4
--- /dev/null
+++ b/ext/Log4Qt/src/varia/stringmatchfilter.h
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: stringmatchfilter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_STRINGMATCHFILTER_H
+#define LOG4QT_STRINGMATCHFILTER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "spi/filter.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class StringMatchFilter allows logging events with a
+ * specified level.
+ *
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT StringMatchFilter : public Filter
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds if an event is accpeted on a match.
+ *
+ * The default is true.
+ *
+ * \sa acceptOnMatch(), acceptOnMatch()
+ */
+ Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch)
+
+ /*!
+ * The property holds the string to match for this filter.
+ *
+ * \sa stringToMatch(), setStringToMatch()
+ */
+ Q_PROPERTY(QString stringToMatch READ stringToMatch WRITE setStringToMatch)
+
+ public:
+ StringMatchFilter(QObject *pParent = 0);
+ // StringMatchFilter(const StringMatchFilter &rOther); // Use compiler default
+ // virtual ~StringMatchFilter(); // Use compiler default
+ // StringMatchFilter &operator=(const StringMatchFilter &rOther); // Use compiler default
+
+ bool acceptOnMatch() const;
+ QString stringToMatch() const;
+ void setAcceptOnMatch(bool accept);
+ void setStringToMatch(const QString &rString);
+
+ virtual Decision decide(const LoggingEvent &rEvent) const;
+
+ protected:
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %StringMatchFilter(acceptonmatch:true referencecount:1
+ * stringtomatch:"LDAP_STRONG_AUTH_REQUIRED"
+ * next:Log4Qt::LevelMatchFilter(0x3bdd960) )
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ private:
+ bool mAcceptOnMatch;
+ QString mStringToMatch;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline bool StringMatchFilter::acceptOnMatch() const
+ { return mAcceptOnMatch; }
+
+ inline QString StringMatchFilter::stringToMatch() const
+ { return mStringToMatch; }
+
+ inline void StringMatchFilter::setAcceptOnMatch(bool accept)
+ { mAcceptOnMatch = accept; }
+
+ inline void StringMatchFilter::setStringToMatch(const QString &rString)
+ { mStringToMatch = rString; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::StringMatchFilter, Q_MOVABLE_TYPE); // Use default
+
+
+#endif // LOG4QT_STRINGMATCHFILTER_H
diff --git a/ext/Log4Qt/src/writerappender.cpp b/ext/Log4Qt/src/writerappender.cpp
new file mode 100755
index 0000000..adab4b0
--- /dev/null
+++ b/ext/Log4Qt/src/writerappender.cpp
@@ -0,0 +1,288 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: writerappender.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "writerappender.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+#include "layout.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: WriterAppender
+ **************************************************************************/
+
+
+ WriterAppender::WriterAppender(QObject *pParent) :
+ AppenderSkeleton(false, pParent),
+ mpEncoding(0),
+ mpWriter(0),
+ mImmediateFlush(true)
+ {
+ }
+
+
+ WriterAppender::WriterAppender(Layout *pLayout,
+ QObject *pParent) :
+ AppenderSkeleton(false, pParent),
+ mpEncoding(0),
+ mpWriter(0),
+ mImmediateFlush(true)
+ {
+ setLayout(pLayout);
+ }
+
+
+ WriterAppender::WriterAppender(Layout *pLayout,
+ QTextStream *pTextStream,
+ QObject *pParent) :
+ AppenderSkeleton(false, pParent),
+ mpEncoding(0),
+ mpWriter(pTextStream),
+ mImmediateFlush(true)
+ {
+ setLayout(pLayout);
+ }
+
+
+ WriterAppender::~WriterAppender()
+ {
+ close();
+ }
+
+
+ void WriterAppender::setEncoding(QTextCodec *pEncoding)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (mpEncoding == pEncoding)
+ return;
+
+ mpEncoding = pEncoding;
+ if (mpWriter)
+ {
+ if (mpEncoding)
+ mpWriter->setCodec(mpEncoding);
+ else
+ mpWriter->setCodec(QTextCodec::codecForLocale());
+ }
+ }
+
+
+ void WriterAppender::setWriter(QTextStream *pTextStream)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ closeWriter();
+
+ mpWriter = pTextStream;
+ if (mpEncoding && mpWriter)
+ mpWriter->setCodec(mpEncoding);
+ writeHeader();
+ }
+
+
+ void WriterAppender::activateOptions()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!writer())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires writer and has no writer set"),
+ APPENDER_ACTIVATE_MISSING_WRITER_ERROR);
+ e << name();
+ logger()->error(e);
+ return;
+ }
+
+ AppenderSkeleton::activateOptions();
+ }
+
+
+ void WriterAppender::close()
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (isClosed())
+ return;
+
+ AppenderSkeleton::close();
+ closeWriter();
+ }
+
+
+ bool WriterAppender::requiresLayout() const
+ {
+ return true;
+ }
+
+
+ void WriterAppender::append(const LoggingEvent &rEvent)
+ {
+ // Q_ASSERT_X(, "WriterAppender::append()", "Lock must be held by caller");
+ Q_ASSERT_X(layout(), "WriterAppender::append()", "Layout must not be null");
+
+ QString message(layout()->format(rEvent));
+
+ *mpWriter << message;
+ if (handleIoErrors())
+ return;
+
+ if (immediateFlush())
+ {
+ mpWriter->flush();
+ if (handleIoErrors())
+ return;
+ }
+ }
+
+
+ bool WriterAppender::checkEntryConditions() const
+ {
+ // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller")
+
+ if (!writer())
+ {
+ LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a writer set"),
+ APPENDER_USE_MISSING_WRITER_ERROR);
+ e << name();
+ logger()->error(e);
+ return false;
+ }
+
+ return AppenderSkeleton::checkEntryConditions();
+ }
+
+
+ void WriterAppender::closeWriter()
+ {
+ // Q_ASSERT_X(, "WriterAppender::closeWriter()", "Lock must be held by caller")
+
+ if (!mpWriter)
+ return;
+
+ writeFooter();
+ mpWriter = 0;
+ }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug WriterAppender::debug(QDebug &rDebug) const
+ {
+ QString layout_name;
+ if (layout())
+ layout_name = layout()->name();
+ QString codec_name;
+ if (encoding())
+ codec_name = QLatin1String(encoding()->name());
+
+ rDebug.nospace() << "WriterAppender("
+ << "name:" << name() << " "
+ << "encoding:" << codec_name << " "
+ << "filter:" << firstFilter()
+ << "immediateFlush:" << immediateFlush()
+ << "isactive:" << isActive()
+ << "isclosed:" << isClosed()
+ << "layout:" << layout_name
+ << "referencecount:" << referenceCount() << " "
+ << "threshold:" << threshold().toString()
+ << "writer:" << writer()
+ << ")";
+ return rDebug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+ bool WriterAppender::handleIoErrors() const
+ {
+ return false;
+ }
+
+
+ void WriterAppender::writeFooter() const
+ {
+ // Q_ASSERT_X(, "WriterAppender::writeFooter()", "Lock must be held by caller")
+
+ if (!layout() || !mpWriter)
+ return;
+
+ QString footer = layout()->footer();
+ if (footer.isEmpty())
+ return;
+
+ *mpWriter << footer << Layout::endOfLine();
+ if (handleIoErrors())
+ return;
+ }
+
+
+ void WriterAppender::writeHeader() const
+ {
+ // Q_ASSERT_X(, "WriterAppender::writeHeader()", "Lock must be held by caller")
+
+ if (!layout() || !mpWriter)
+ return;
+
+ QString header = layout()->header();
+ if (header.isEmpty())
+ return;
+
+ *mpWriter << header << Layout::endOfLine();
+ if (handleIoErrors())
+ return;
+ }
+
+
+
+ /******************************************************************************
+ * Implementation: Operators, Helper
+ ******************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/writerappender.h b/ext/Log4Qt/src/writerappender.h
new file mode 100755
index 0000000..f5e3ccd
--- /dev/null
+++ b/ext/Log4Qt/src/writerappender.h
@@ -0,0 +1,200 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: writerappender.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_WRITERAPPENDER_H
+#define LOG4QT_WRITERAPPENDER_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "appenderskeleton.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QTextCodec;
+class QTextStream;
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class WriterAppender appends log events to a QTextStream.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ * &nbsp;
+ * \note The ownership and lifetime of objects of this class are managed.
+ * See \ref Ownership "Object ownership" for more details.
+ */
+ class LOG4QT_EXPORT WriterAppender : public AppenderSkeleton
+ {
+ Q_OBJECT
+
+ /*!
+ * The property holds the codec the appender uses.
+ *
+ * The default is null to use the codec the writer has set.
+ *
+ * \sa encoding(), setEncoding()
+ */
+ Q_PROPERTY(QTextCodec* encoding READ encoding WRITE setEncoding)
+
+ /*!
+ * The property holds the writer the appender uses.
+ *
+ * \sa writer(), setWriter()
+ */
+ Q_PROPERTY(QTextStream* writer READ writer WRITE setWriter)
+
+ /*!
+ * The property holds, if the writer flushes after all write operations.
+ *
+ * The default is true for flushing.
+ *
+ * \sa immediateFlush(), setImmediateFlush()
+ */
+ Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush)
+
+ public:
+ WriterAppender(QObject *pParent = 0);
+ WriterAppender(Layout *pLayout,
+ QObject *pParent = 0);
+ WriterAppender(Layout *pLayout,
+ QTextStream *pTextStream,
+ QObject *pParent = 0);
+ virtual ~WriterAppender();
+ private:
+ WriterAppender(const WriterAppender &rOther); // Not implemented
+ WriterAppender &operator=(const WriterAppender &rOther); // Not implemented
+
+ public:
+ virtual bool requiresLayout() const;
+ QTextCodec *encoding() const;
+ bool immediateFlush() const;
+ QTextStream *writer() const;
+
+ /*!
+ * Sets the codec used by the writer to \a pTextCoded.
+ *
+ * If a codec is set with setEncoding, it will overwrite the codec set
+ * in the text stream. A subsequent call with \a pTextCoded equals null
+ * will resets the codec to the default QTextCodec::codecForLocale().
+ *
+ * \sa encoding(), QTextSream::setCodec(), QTextCodec::codecForLocale()
+ */
+ void setEncoding(QTextCodec *pTextCodec);
+ void setImmediateFlush(bool immediateFlush);
+ void setWriter(QTextStream *pTextStream);
+
+ virtual void activateOptions();
+ virtual void close();
+
+ protected:
+ virtual void append(const LoggingEvent &rEvent);
+
+ /*!
+ * Tests if all entry conditions for using append() in this class are
+ * met.
+ *
+ * If a conditions is not met, an error is logged and the function
+ * returns false. Otherwise the result of
+ * AppenderSkeleton::checkEntryConditions() is returned.
+ *
+ * The checked conditions are:
+ * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR)
+ *
+ * The function is called as part of the checkEntryConditions() chain
+ * started by AppenderSkeleton::doAppend().
+ *
+ * \sa AppenderSkeleton::doAppend(),
+ * AppenderSkeleton::checkEntryConditions()
+ */
+ virtual bool checkEntryConditions() const;
+
+ void closeWriter();
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * <tt>
+ * %WriterAppender(name:"WA" encoding:"" immediateFlush:true
+ * isactive:false isclosed:false layout:"TTCC"
+ * referencecount:1 threshold:"NULL"
+ * writer:0x0)
+ * </tt>
+ * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject )
+ */
+ virtual QDebug debug(QDebug &rDebug) const;
+#endif // QT_NO_DEBUG_STREAM
+
+ virtual bool handleIoErrors() const;
+ void writeFooter() const;
+ void writeHeader() const;
+
+ private:
+ QTextCodec *mpEncoding;
+ QTextStream *mpWriter;
+ volatile bool mImmediateFlush;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QTextCodec *WriterAppender::encoding() const
+ { QMutexLocker locker(&mObjectGuard);
+ return mpEncoding; }
+
+ inline bool WriterAppender::immediateFlush() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mImmediateFlush; }
+
+ inline QTextStream *WriterAppender::writer() const
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ return mpWriter; }
+
+ inline void WriterAppender::setImmediateFlush(bool immediateFlush)
+ { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe
+ mImmediateFlush = immediateFlush; }
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::WriterAppender, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_WRITERAPPENDER_H
diff --git a/ext/ext.pro b/ext/ext.pro
new file mode 100644
index 0000000..4ab8424
--- /dev/null
+++ b/ext/ext.pro
@@ -0,0 +1,9 @@
+# Such a project structure allowed for integrating Log4Qt via git subtree
+# Log4Qt folder is pulled right from the remote repository
+TEMPLATE = subdirs
+SUBDIRS = Log4Qt
+
+lib.files += $$OUT_PWD/../../ext/Log4Qt/*.s*
+lib.path = /usr/share/$$TARGET/lib
+
+INSTALLS += lib