This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


The following commit(s) were added to refs/heads/master by this push:
     new 78d8e82a Allow a QString in a LOG4CXX_ macro when 'Qt 
support/integration' is ON (#247)
78d8e82a is described below

commit 78d8e82a375940e82967923117bd026582d1dda8
Author: Stephen Webb <[email protected]>
AuthorDate: Wed Aug 9 14:48:13 2023 +1000

    Allow a QString in a LOG4CXX_ macro when 'Qt support/integration' is ON 
(#247)
    
    * Update Qt support documentation
    
    * Change configuration examples to links
    
    * Fix NDC example file name
    
    * Improve example code
---
 .github/workflows/log4cxx-ubuntu.yml               | 19 +++++-
 src/cmake/win32_target_environment_path.cmake      |  3 +
 src/examples/cpp/CMakeLists.txt                    |  9 ++-
 src/examples/cpp/MyApp-qt.cpp                      | 20 ++++++
 src/examples/cpp/auto-configured.cpp               |  4 +-
 src/examples/cpp/com/foo/bar-qt.cpp                | 10 +++
 src/examples/cpp/com/foo/config-qt.cpp             | 71 +++++++++++++++++++++
 src/examples/cpp/com/foo/config-qt.h               | 21 ++++++
 src/examples/cpp/{trivial.cpp => ndc-example.cpp}  |  0
 src/main/cpp-qt/configuration.cpp                  |  9 +--
 src/main/cpp/domconfigurator.cpp                   |  6 +-
 src/main/cpp/file.cpp                              |  2 +-
 src/main/cpp/hexdump.cpp                           | 10 ++-
 src/main/cpp/level.cpp                             |  2 +-
 src/main/cpp/messagebuffer.cpp                     |  4 +-
 src/main/cpp/timebasedrollingpolicy.cpp            |  4 ++
 src/main/cpp/transcoder.cpp                        |  2 +-
 .../include/log4cxx-qt/logger.h}                   | 18 ++----
 src/main/include/log4cxx-qt/messagebuffer.h        | 74 ++++++++++++++++++++++
 src/main/include/log4cxx-qt/transcoder.h           | 47 ++++++++++++++
 src/main/include/log4cxx/file.h                    |  2 +-
 src/main/include/log4cxx/level.h                   |  2 +-
 src/main/include/log4cxx/xml/domconfigurator.h     |  6 +-
 src/site/markdown/development/build-cmake.md       |  1 +
 src/site/markdown/example-programs.md              | 13 ++--
 src/site/markdown/filters/filters.md               |  4 +-
 src/site/markdown/qt-support.md                    | 27 +++++++-
 27 files changed, 345 insertions(+), 45 deletions(-)

diff --git a/.github/workflows/log4cxx-ubuntu.yml 
b/.github/workflows/log4cxx-ubuntu.yml
index ee8ac96c..45b2fbfc 100644
--- a/.github/workflows/log4cxx-ubuntu.yml
+++ b/.github/workflows/log4cxx-ubuntu.yml
@@ -30,18 +30,30 @@ jobs:
             os: ubuntu-20.04
             cxx: g++
             cc: gcc
+            fmt: OFF
+            qt: ON
+            odbc: OFF
           - name: ubuntu20-clang
             os: ubuntu-20.04
             cxx: clang++
             cc: clang
+            fmt: ON
+            qt: OFF
+            odbc: ON
           - name: ubuntu22-gcc
             os: ubuntu-22.04
             cxx: g++
             cc: gcc
+            fmt: OFF
+            qt: OFF
+            odbc: OFF
           - name: ubuntu22-clang
             os: ubuntu-22.04
             cxx: clang++
             cc: clang
+            fmt: ON
+            qt: OFF
+            odbc: OFF
 
     steps:
     - uses: actions/checkout@v3
@@ -51,14 +63,17 @@ jobs:
     - name: 'Configure Dependencies'
       run: |
         sudo apt-get update
-        sudo apt-get install -y libapr1-dev libaprutil1-dev libfmt-dev 
unixodbc-dev
+        sudo apt-get install -y libapr1-dev libaprutil1-dev
+        if [ ${{ matrix.fmt }} == ON ]; then sudo apt-get install -y 
libfmt-dev; fi
+        if [ ${{ matrix.odbc }} == ON ]; then sudo apt-get install -y 
unixodbc-dev; fi
+        if [ ${{ matrix.qt }} == ON ]; then sudo apt-get install -y 
qtbase5-dev; fi
 
     - name: 'run cmake - posix'
       run: |
         cd main
         mkdir build
         cd build
-        cmake -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} -DCMAKE_C_COMPILER=${{ 
matrix.cc }} -DLOG4CXX_ENABLE_ODBC=ON ..
+        cmake -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} -DCMAKE_C_COMPILER=${{ 
matrix.cc }} -DLOG4CXX_ENABLE_ODBC=${{ matrix.odbc }} -DLOG4CXX_QT_SUPPORT=${{ 
matrix.qt }} ..
         cmake --build .
 
     - name: run unit tests
diff --git a/src/cmake/win32_target_environment_path.cmake 
b/src/cmake/win32_target_environment_path.cmake
index ea122c89..3de5bc94 100644
--- a/src/cmake/win32_target_environment_path.cmake
+++ b/src/cmake/win32_target_environment_path.cmake
@@ -8,6 +8,9 @@ function(get_target_environment_path varName)
   set(EXPAT_DLL_DIR "${EXPAT_LIB_DIR}/../bin")
   set(LOG4CXX_DLL_DIR "$<SHELL_PATH:$<TARGET_FILE_DIR:log4cxx>>;")
   set(PATH_FOR_TESTS 
${CMAKE_PROGRAM_PATH};${APR_DLL_DIR};${APR_UTIL_DLL_DIR};${LOG4CXX_DLL_DIR};${EXPAT_DLL_DIR}\;)
+  if(LOG4CXX_QT_SUPPORT)
+    list(APPEND PATH_FOR_TESTS "$<SHELL_PATH:$<TARGET_FILE_DIR:log4cxx-qt>>\;")
+  endif(LOG4CXX_QT_SUPPORT)
   list(REMOVE_DUPLICATES PATH_FOR_TESTS)
 
   # Note: we need to include the APR DLLs on our path so that the tests will 
run.
diff --git a/src/examples/cpp/CMakeLists.txt b/src/examples/cpp/CMakeLists.txt
index f1cf57d3..4508a6ec 100644
--- a/src/examples/cpp/CMakeLists.txt
+++ b/src/examples/cpp/CMakeLists.txt
@@ -15,7 +15,10 @@
 # limitations under the License.
 #
 
-set(ALL_LOG4CXX_EXAMPLES auto-configured console delayedloop stream trivial 
custom-appender MyApp1 MyApp2)
+set(ALL_LOG4CXX_EXAMPLES auto-configured console delayedloop stream 
ndc-example custom-appender MyApp1 MyApp2)
+if(LOG4CXX_QT_SUPPORT)
+  list(APPEND ALL_LOG4CXX_EXAMPLES MyApp-qt)
+endif(LOG4CXX_QT_SUPPORT)
 if( WIN32 )
     include(win32_target_environment_path)
     get_target_environment_path(ESCAPED_PATH)
@@ -34,6 +37,10 @@ foreach(exampleName IN LISTS ALL_LOG4CXX_EXAMPLES)
     if(${exampleName} STREQUAL MyApp2)
         target_sources(${PROGRAM_NAME} PRIVATE com/foo/config2.cpp 
com/foo/bar.cpp)
     endif()
+    if(${exampleName} STREQUAL MyApp-qt)
+        target_sources(${PROGRAM_NAME} PRIVATE com/foo/config-qt.cpp 
com/foo/bar-qt.cpp)
+        target_link_libraries(${PROGRAM_NAME} PRIVATE log4cxx-qt)
+    endif()
     if(${exampleName} STREQUAL auto-configured)
         target_sources(${PROGRAM_NAME} PRIVATE com/foo/config3.cpp )
     endif()
diff --git a/src/examples/cpp/MyApp-qt.cpp b/src/examples/cpp/MyApp-qt.cpp
new file mode 100644
index 00000000..9040c5eb
--- /dev/null
+++ b/src/examples/cpp/MyApp-qt.cpp
@@ -0,0 +1,20 @@
+#include <QCoreApplication>
+#include "com/foo/config-qt.h"
+#include "com/foo/bar.h"
+
+int main(int argc, char **argv) {
+       int result = EXIT_SUCCESS;
+       QCoreApplication app(argc, argv);
+       com::foo::ConfigureLogging();
+       try {
+               auto logger = com::foo::getLogger("MyApp");
+               LOG4CXX_INFO(logger, QString("Message %1").arg(1));
+               com::foo::Bar bar;
+               bar.doIt();
+               LOG4CXX_INFO(logger, QString("Message %1").arg(2));
+       }
+       catch(std::exception&) {
+               result = EXIT_FAILURE;
+       }
+       return result;
+}
diff --git a/src/examples/cpp/auto-configured.cpp 
b/src/examples/cpp/auto-configured.cpp
index fb0a9a5d..1933f8f7 100644
--- a/src/examples/cpp/auto-configured.cpp
+++ b/src/examples/cpp/auto-configured.cpp
@@ -16,9 +16,9 @@
  */
 #include "com/foo/config.h"
 
-extern auto rootLogger = com::foo::getLogger();
+auto rootLogger = com::foo::getLogger();
 
-static struct ExampleStaticData {
+struct ExampleStaticData {
        ExampleStaticData()     {
                LOG4CXX_DEBUG(rootLogger, "static initializer message");
        }
diff --git a/src/examples/cpp/com/foo/bar-qt.cpp 
b/src/examples/cpp/com/foo/bar-qt.cpp
new file mode 100644
index 00000000..34d44681
--- /dev/null
+++ b/src/examples/cpp/com/foo/bar-qt.cpp
@@ -0,0 +1,10 @@
+#include "com/foo/bar.h"
+#include "com/foo/config-qt.h"
+
+using namespace com::foo;
+
+LoggerPtr Bar::m_logger(getLogger("com.foo.bar"));
+
+void Bar::doIt() {
+       LOG4CXX_DEBUG(m_logger, QString("Did it again!") << QString(" - 
again!"));
+}
diff --git a/src/examples/cpp/com/foo/config-qt.cpp 
b/src/examples/cpp/com/foo/config-qt.cpp
new file mode 100644
index 00000000..64889087
--- /dev/null
+++ b/src/examples/cpp/com/foo/config-qt.cpp
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 "config-qt.h"
+#include <log4cxx/logmanager.h>
+#include <log4cxx-qt/configuration.h>
+#include <log4cxx/helpers/loglog.h>
+#include <QCoreApplication>
+#include <QVector>
+#include <QFileInfo>
+#include <QDir>
+
+namespace com { namespace foo {
+
+// Provide the name of the configuration file to Log4cxx.
+// Reload the configuration on a QFileSystemWatcher::fileChanged event.
+void ConfigureLogging() {
+       static struct log4cxx_finalizer {
+               ~log4cxx_finalizer() {
+                       log4cxx::LogManager::shutdown();
+               }
+       } finaliser;
+       QFileInfo app{QCoreApplication::applicationFilePath()};
+       QString basename{app.baseName()};
+       QVector<QString> paths =
+               { QString(".")
+               , app.absoluteDir().absolutePath()
+               };
+       QVector<QString> names =
+               { QString(basename + ".xml")
+               , QString(basename + ".properties")
+               , QString("MyApp.properties")
+               , QString("log4cxx.xml")
+               , QString("log4cxx.properties")
+               , QString("log4j.xml")
+               , QString("log4j.properties")
+       };
+#if defined(_DEBUG)
+       log4cxx::helpers::LogLog::setInternalDebugging(true);
+#endif
+       log4cxx::qt::Configuration::configureFromFileAndWatch(paths, names);
+}
+
+// Retrieve the \c name logger pointer.
+auto getLogger(const QString& name) -> LoggerPtr {
+       return name.isEmpty()
+               ? log4cxx::LogManager::getRootLogger()
+               : log4cxx::LogManager::getLogger(name.toStdString());
+}
+
+// Retrieve the \c name logger pointer.
+auto getLogger(const char* name) -> LoggerPtr {
+       return name
+               ? log4cxx::LogManager::getLogger(name)
+               : log4cxx::LogManager::getRootLogger();
+}
+
+} } // namespace com::foo
diff --git a/src/examples/cpp/com/foo/config-qt.h 
b/src/examples/cpp/com/foo/config-qt.h
new file mode 100644
index 00000000..238199ff
--- /dev/null
+++ b/src/examples/cpp/com/foo/config-qt.h
@@ -0,0 +1,21 @@
+#ifndef COM_FOO_CONFIG_QT_H_
+#define COM_FOO_CONFIG_QT_H_
+#include <log4cxx-qt/logger.h>
+
+/// Methods specific to foo.com
+namespace com { namespace foo {
+
+// Provide the name of the configuration file to Log4cxx.
+void ConfigureLogging();
+
+/// The logger pointer we use
+using LoggerPtr = log4cxx::LoggerPtr;
+
+/// Retrieve the \c name logger pointer.
+extern auto getLogger(const QString& name) -> LoggerPtr;
+
+/// Retrieve the \c name logger pointer.
+extern auto getLogger(const char* name = NULL) -> LoggerPtr;
+
+} } // namespace com::foo
+#endif // COM_FOO_CONFIG_QT_H_
diff --git a/src/examples/cpp/trivial.cpp b/src/examples/cpp/ndc-example.cpp
similarity index 100%
rename from src/examples/cpp/trivial.cpp
rename to src/examples/cpp/ndc-example.cpp
diff --git a/src/main/cpp-qt/configuration.cpp 
b/src/main/cpp-qt/configuration.cpp
index ef8589fe..17654b71 100644
--- a/src/main/cpp-qt/configuration.cpp
+++ b/src/main/cpp-qt/configuration.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 #include <log4cxx-qt/configuration.h>
+#include <log4cxx-qt/transcoder.h>
 #include <log4cxx/helpers/loglog.h>
 #include <log4cxx/xml/domconfigurator.h>
 #include <log4cxx/propertyconfigurator.h>
@@ -107,16 +108,16 @@ Configuration::configureFromFileAndWatch(const 
QVector<QString>& directories,
                        QString canidate_str = dir + "/" + fname;
                        QFile candidate(canidate_str);
 
-                       QString debugMsg = LOG4CXX_STR("Checking file ");
-                       debugMsg.append(canidate_str);
-                       LogLog::debug(debugMsg.toStdString());
+                       LOG4CXX_DECODE_QSTRING(msg, "Checking file " + 
canidate_str);
+                       LogLog::debug(msg);
                        if (candidate.exists())
                        {
                                log4cxx::spi::ConfigurationStatus configStatus 
= tryLoadFile(canidate_str);
                                if( configStatus == 
log4cxx::spi::ConfigurationStatus::Configured ){
                                        return {configStatus, canidate_str};
                                }
-                               LogLog::debug("Unable to load file: trying 
next");
+                               LOG4CXX_DECODE_QSTRING(failmsg, "Unable to load 
 " + canidate_str + ": trying next");
+                               LogLog::debug(failmsg);
                        }
                }
        }
diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp
index 4d3b9e03..0fd1805e 100644
--- a/src/main/cpp/domconfigurator.cpp
+++ b/src/main/cpp/domconfigurator.cpp
@@ -865,7 +865,7 @@ spi::ConfigurationStatus DOMConfigurator::configure(const 
std::wstring& filename
 }
 #endif
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 spi::ConfigurationStatus DOMConfigurator::configure(const 
std::basic_string<UniChar>& filename)
 {
        File file(filename);
@@ -894,7 +894,7 @@ spi::ConfigurationStatus 
DOMConfigurator::configureAndWatch(const std::wstring&
 }
 #endif
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 spi::ConfigurationStatus DOMConfigurator::configureAndWatch(const 
std::basic_string<UniChar>& filename)
 {
        return configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
@@ -958,7 +958,7 @@ spi::ConfigurationStatus 
DOMConfigurator::configureAndWatch(const std::wstring&
 }
 #endif
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 spi::ConfigurationStatus DOMConfigurator::configureAndWatch(const 
std::basic_string<UniChar>& filename, long delay)
 {
        File file(filename);
diff --git a/src/main/cpp/file.cpp b/src/main/cpp/file.cpp
index 56fe7682..88a04a9b 100644
--- a/src/main/cpp/file.cpp
+++ b/src/main/cpp/file.cpp
@@ -95,7 +95,7 @@ File::File(const wchar_t* name1)
 }
 #endif
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 File::File(const std::basic_string<UniChar>& name1)
        : m_priv(std::make_unique<FilePrivate>(decodeLS(name1)))
 {
diff --git a/src/main/cpp/hexdump.cpp b/src/main/cpp/hexdump.cpp
index caa45ac3..163cda79 100644
--- a/src/main/cpp/hexdump.cpp
+++ b/src/main/cpp/hexdump.cpp
@@ -14,6 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#include <log4cxx/log4cxx.h>
+/* Prevent error C2491: 'std::numpunct<_Elem>::id': definition of dllimport 
static data member not allowed */
+#if defined(_MSC_VER) && (LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR)
+#define __FORCE_INSTANCE
+#endif
 #include <log4cxx/hexdump.h>
 #include <log4cxx/log4cxx.h>
 #include <sstream>
@@ -32,8 +38,8 @@ LogString log4cxx::hexdump(const void* bytes, uint32_t len, 
HexdumpFlags flags){
        const wchar_t fill_char = L'0';
        const wchar_t space_fill_char = L' ';
 #else
-       const char fill_char = '0';
-       const char space_fill_char = ' ';
+       const logchar fill_char = '0';
+       const logchar space_fill_char = ' ';
 #endif
 
        if(flags & HexdumpFlags::AddStartingNewline){
diff --git a/src/main/cpp/level.cpp b/src/main/cpp/level.cpp
index 7d794c51..8fb6af19 100644
--- a/src/main/cpp/level.cpp
+++ b/src/main/cpp/level.cpp
@@ -173,7 +173,7 @@ void Level::toString(std::wstring& dst) const
 
 #endif
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 LevelPtr Level::toLevel(const std::basic_string<UniChar>& sArg)
 {
        return toLevel(sArg, Level::getDebug());
diff --git a/src/main/cpp/messagebuffer.cpp b/src/main/cpp/messagebuffer.cpp
index 6972dc70..4a546a7c 100644
--- a/src/main/cpp/messagebuffer.cpp
+++ b/src/main/cpp/messagebuffer.cpp
@@ -17,7 +17,7 @@
 
 #include <log4cxx/log4cxx.h>
 /* Prevent error C2491: 'std::numpunct<_Elem>::id': definition of dllimport 
static data member not allowed */
-#if defined(_MSC_VER) && LOG4CXX_UNICHAR_API
+#if defined(_MSC_VER) && (LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR)
 #define __FORCE_INSTANCE
 #endif
 #include <log4cxx/helpers/messagebuffer.h>
@@ -587,7 +587,7 @@ const std::basic_string<log4cxx::UniChar>& 
MessageBuffer::str(std::basic_ostream
 
 #endif // LOG4CXX_WCHAR_T_API
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 struct UniCharMessageBuffer::UniCharMessageBufferPrivate : public 
StringOrStream<UniChar> {};
 
 UniCharMessageBuffer::UniCharMessageBuffer() :
diff --git a/src/main/cpp/timebasedrollingpolicy.cpp 
b/src/main/cpp/timebasedrollingpolicy.cpp
index 26798677..f304ca9b 100644
--- a/src/main/cpp/timebasedrollingpolicy.cpp
+++ b/src/main/cpp/timebasedrollingpolicy.cpp
@@ -171,7 +171,11 @@ const std::string TimeBasedRollingPolicy::createFile(const 
std::string& fileName
 
        if (stat == APR_SUCCESS)
        {
+#ifdef WIN32
+               snprintf(szUid, MAX_FILE_LEN, "%p", uid);
+#else
                snprintf(szUid, MAX_FILE_LEN, "%u", uid);
+#endif
        }
 
        log4cxx::filesystem::path path(fileName);
diff --git a/src/main/cpp/transcoder.cpp b/src/main/cpp/transcoder.cpp
index 6cbe9f26..7ad9ad27 100644
--- a/src/main/cpp/transcoder.cpp
+++ b/src/main/cpp/transcoder.cpp
@@ -576,7 +576,7 @@ void Transcoder::encode(unsigned int sv, std::wstring& dst)
 
 
 
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
 void Transcoder::decode(const std::basic_string<UniChar>& src, LogString& dst)
 {
 #if LOG4CXX_LOGCHAR_IS_UNICHAR
diff --git a/src/examples/cpp/auto-configured.cpp 
b/src/main/include/log4cxx-qt/logger.h
similarity index 72%
copy from src/examples/cpp/auto-configured.cpp
copy to src/main/include/log4cxx-qt/logger.h
index fb0a9a5d..f79d7fdb 100644
--- a/src/examples/cpp/auto-configured.cpp
+++ b/src/main/include/log4cxx-qt/logger.h
@@ -14,17 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "com/foo/config.h"
 
-extern auto rootLogger = com::foo::getLogger();
-
-static struct ExampleStaticData {
-       ExampleStaticData()     {
-               LOG4CXX_DEBUG(rootLogger, "static initializer message");
-       }
-} static_object;
-
-int main() {
-       LOG4CXX_INFO(rootLogger, "main function message");
-       return EXIT_SUCCESS;
-}
+#ifndef _LOG4CXX_QT_LOGGER_H
+#define _LOG4CXX_QT_LOGGER_H
+#include <log4cxx/logger.h>
+#include <log4cxx-qt/messagebuffer.h>
+#endif // _LOG4CXX_QT_LOGGER_H
diff --git a/src/main/include/log4cxx-qt/messagebuffer.h 
b/src/main/include/log4cxx-qt/messagebuffer.h
new file mode 100644
index 00000000..bd4c9b76
--- /dev/null
+++ b/src/main/include/log4cxx-qt/messagebuffer.h
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 _LOG4CXX_QT_MESSAGE_BUFFER_H
+#define _LOG4CXX_QT_MESSAGE_BUFFER_H
+#include <log4cxx-qt/transcoder.h>
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
+       inline log4cxx::helpers::UniCharMessageBuffer&
+operator<<(log4cxx::helpers::UniCharMessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.utf16();
+}
+
+#if LOG4CXX_WCHAR_T_API
+       inline log4cxx::helpers::WideMessageBuffer&
+operator<<(log4cxx::helpers::WideMessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.toStdWString();
+}
+
+       inline log4cxx::helpers::WideMessageBuffer&
+operator<<(log4cxx::helpers::MessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.toStdWString();
+}
+#else // !LOG4CXX_WCHAR_T_API
+       inline log4cxx::helpers::UniCharMessageBuffer&
+operator<<(log4cxx::helpers::MessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.utf16();
+}
+#endif // !LOG4CXX_WCHAR_T_API
+
+#else // !(LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR)
+
+#if LOG4CXX_WCHAR_T_API
+       inline log4cxx::helpers::WideMessageBuffer&
+operator<<(log4cxx::helpers::WideMessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.toStdWString();
+}
+
+       inline log4cxx::helpers::WideMessageBuffer&
+operator<<(log4cxx::helpers::MessageBuffer& mb, const QString& msg)
+{
+       return mb << msg.toStdWString();
+}
+#else // !LOG4CXX_WCHAR_T_API
+       inline log4cxx::helpers::CharMessageBuffer&
+operator<<(log4cxx::helpers::CharMessageBuffer& mb, const QString& msg)
+{
+       LOG4CXX_DECODE_QSTRING(tmp, msg);
+       return mb << tmp;
+}
+#endif // !LOG4CXX_WCHAR_T_API
+
+#endif // !(LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR)
+
+#endif // _LOG4CXX_QT_MESSAGE_BUFFER_H
diff --git a/src/main/include/log4cxx-qt/transcoder.h 
b/src/main/include/log4cxx-qt/transcoder.h
new file mode 100644
index 00000000..71002a2c
--- /dev/null
+++ b/src/main/include/log4cxx-qt/transcoder.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 _LOG4CXX_QT_TRANSCODER_H
+#define _LOG4CXX_QT_TRANSCODER_H
+#include <log4cxx/logstring.h>
+#include <QString>
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+       log4cxx::LogString var = (src).toStdString()
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+       QString var = QString::fromStdString(src)
+#endif // LOG4CXX_LOGCHAR_IS_UTF8
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+       log4cxx::LogString var = (src).toStdWString()
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+       QString var = QString::fromStdWString(src)
+#endif // LOG4CXX_LOGCHAR_IS_WCHAR
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+       log4cxx::LogString var = (src).utf16()
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+       QString var = QString::fromUtf16((char16_t*)src.c_str())
+#endif // LOG4CXX_LOGCHAR_IS_UNICHAR
+
+#endif // _LOG4CXX_QT_TRANSCODER_H
diff --git a/src/main/include/log4cxx/file.h b/src/main/include/log4cxx/file.h
index cc669eaf..7bd9592a 100644
--- a/src/main/include/log4cxx/file.h
+++ b/src/main/include/log4cxx/file.h
@@ -66,7 +66,7 @@ class LOG4CXX_EXPORT File
                */
                File(const std::wstring& path);
 #endif
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
                /**
                *   Construct a new instance.  Use setPath to specify path 
using a LogString.
                * @param path file path.
diff --git a/src/main/include/log4cxx/level.h b/src/main/include/log4cxx/level.h
index 8644b81b..b0b98d5b 100644
--- a/src/main/include/log4cxx/level.h
+++ b/src/main/include/log4cxx/level.h
@@ -126,7 +126,7 @@ class LOG4CXX_EXPORT Level : public helpers::Object
                 */
                void toString(std::wstring& name) const;
 #endif
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
                /**
                Convert the string passed as argument to a level. If the
                conversion fails, then this method returns DEBUG.
diff --git a/src/main/include/log4cxx/xml/domconfigurator.h 
b/src/main/include/log4cxx/xml/domconfigurator.h
index 9f49c69c..026fea95 100644
--- a/src/main/include/log4cxx/xml/domconfigurator.h
+++ b/src/main/include/log4cxx/xml/domconfigurator.h
@@ -221,7 +221,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
 #if LOG4CXX_WCHAR_T_API
                static spi::ConfigurationStatus configure(const std::wstring& 
filename);
 #endif
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
                static spi::ConfigurationStatus configure(const 
std::basic_string<UniChar>& filename);
 #endif
 #if LOG4CXX_CFSTRING_API
@@ -237,7 +237,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
 #if LOG4CXX_WCHAR_T_API
                static spi::ConfigurationStatus configureAndWatch(const 
std::wstring& configFilename);
 #endif
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
                static spi::ConfigurationStatus configureAndWatch(const 
std::basic_string<UniChar>& configFilename);
 #endif
 #if LOG4CXX_CFSTRING_API
@@ -260,7 +260,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
                static spi::ConfigurationStatus configureAndWatch(const 
std::wstring& configFilename,
                        long delay);
 #endif
-#if LOG4CXX_UNICHAR_API
+#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
                static spi::ConfigurationStatus configureAndWatch(const 
std::basic_string<UniChar>& configFilename,
                        long delay);
 #endif
diff --git a/src/site/markdown/development/build-cmake.md 
b/src/site/markdown/development/build-cmake.md
index 242430b9..e8601183 100644
--- a/src/site/markdown/development/build-cmake.md
+++ b/src/site/markdown/development/build-cmake.md
@@ -71,6 +71,7 @@ $ cmake --build buildtrees/Log4cxx --target install --config 
Release
 | -DAPR_STATIC=yes       | Link to the APR static library. By default, the 
Log4cxx shared library is linked to the APR shared library. If 
BUILD_SHARED_LIBS=off, the static APR library is always used.        |
 |-DLOG4CXX_TEST_PROGRAM_PATH=path| An extra path to prepend to the PATH for 
test programs.  Log4cxx requires zip, sed, and grep on the PATH in order for 
the tests to work properly.                          |
 | -DPREFER_BOOST=on      | Prefer the Boost version of dependent libraries 
over standard library |
+| -DLOG4CXX_QT_SUPPORT=ON | Enable QString API and log4cxx::qt namespace 
methods, requires QtCore, choice of ON, OFF (default).                   |
 
 ## A note on C++ version and Boost
 
diff --git a/src/site/markdown/example-programs.md 
b/src/site/markdown/example-programs.md
index dfbbb83e..72992d80 100644
--- a/src/site/markdown/example-programs.md
+++ b/src/site/markdown/example-programs.md
@@ -72,15 +72,14 @@ The *com::foo::Bar* class is defined in header file 
*com/foo/bar.h*.
 The *com::foo::Bar* class is implemented in the file *com/foo/bar.cpp*.
 \include com/foo/bar.cpp
 
-The header file *com/foo/config.h* defines the com::foo::getLogger() function
+The header file \ref com/foo/config.h defines the com::foo::getLogger() 
function
 and a *LoggerPtr* type for convenience.
-\include com/foo/config.h
 
-The file *com/foo/config.cpp* which implements the com::foo::getLogger() 
function
+
+The file \ref com/foo/config1.cpp implements the com::foo::getLogger() function
 defines *initAndShutdown* as a *static struct* so its constructor
 is invoked on the first call to the com::foo::getLogger() function
 and its destructor is automatically called during application exit.
-\include com/foo/config1.cpp
 
 The invocation of the
 [BasicConfigurator::configure](@ref log4cxx.BasicConfigurator.configure)
@@ -189,5 +188,11 @@ forwarded logging events to a remote Log4cxx server, which 
would log
 according to local server policy, for example by forwarding the log
 event to a second Log4cxx server.
 
+\example com/foo/config.h
+This header file is for encapsulating Log4cxx configuration.
+
+\example com/foo/config1.cpp
+This file is a simplified example of encapsulated Log4cxx configuration.
+
 \example com/foo/config3.cpp
 This file is an example of how to use the current module name to select the 
Log4cxx configuration file.
diff --git a/src/site/markdown/filters/filters.md 
b/src/site/markdown/filters/filters.md
index 4f4bbbb2..4e3ab354 100644
--- a/src/site/markdown/filters/filters.md
+++ b/src/site/markdown/filters/filters.md
@@ -28,7 +28,7 @@ To uniquely stamp each request to relate it to a particular 
source,
 you can push contextual information
 into the *Nested Diagnostic Context* (NDC) using the *log4cxx::NDC* class
 or the *Mapped Diagnostic Context* provided by *log4cxx::MDC* class.
-For an example using log4cxx::NDC refer to \ref trivial.cpp.
+For an example using log4cxx::NDC refer to \ref ndc-example.cpp.
 
 The NDC is managed per thread as a *stack* of contextual information.
 When the layout specifies that the NDC is to be included,
@@ -93,5 +93,5 @@ The following pages have information on specific filters:
 * @subpage map-filter
 * @subpage location-info-filter
 
-\example trivial.cpp
+\example ndc-example.cpp
 This example shows how to add a context string to each logging message using 
the NDC.
diff --git a/src/site/markdown/qt-support.md b/src/site/markdown/qt-support.md
index a324a261..7e0bb13e 100644
--- a/src/site/markdown/qt-support.md
+++ b/src/site/markdown/qt-support.md
@@ -26,8 +26,14 @@ may use the `QDebug` classes.  By default, this will print 
to stderr,
 thus bypassing the logger entirely.  In order to have these messages
 routed to Log4cxx, a message handler for Qt must be installed.
 
-Log4cxx provides a separate library, log4cxx-qt, which contains useful
-utilities for working with Qt.
+Log4cxx provides a cmake build option `LOG4CXX_QT_SUPPORT=ON`
+which adds the log4cxx::qt namespace methods
+for directing Qt messages to Log4cxx and
+using the Qt event loop to process a configuration file change.
+Use the target `log4cxx-qt` instead of `log4cxx`
+in your `target_link_libraries` cmake directive.
+Also, including `log4cxx-qt/logger.h` allows you to use QString values
+in the LOG4CXX_WARN, LOG4CXX_INFO, LOG4CXX_DEBUG etc. macros.
 
 To install a message handler that will route the Qt logging messages
 through Log4cxx, include the messagehandler.h and call
@@ -43,3 +49,20 @@ qInstallMessageHandler( log4cxx::qt::messageHandler );
 
 Note that by default, this message handler also calls `abort` upon a
 fatal message.
+
+For how to use the Qt event loop to monitor the configuration file,
+see the \ref com/foo/config-qt.h and \ref com/foo/config-qt.cpp example files.
+
+Note that when using the above technique
+you *must* configure Log4cxx after creating your QCoreApplication instance
+(see the \ref MyApp-qt.cpp file for an example of this).
+
+\example MyApp-qt.cpp
+This file is an example of how to configure Log4cxx in a Qt application.
+
+\example com/foo/config-qt.h
+This header file is for Log4cxx configuration in a Qt application.
+
+\example com/foo/config-qt.cpp
+This file is an example of how to use the Qt event loop to monitor the Log4cxx 
configuration file.
+

Reply via email to