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
diff --git a/.github/workflows/log4cxx-ubuntu.yml b/.github/workflows/log4cxx-ubuntu.yml
index ee8ac96..45b2fbf 100644
--- a/.github/workflows/log4cxx-ubuntu.yml
+++ b/.github/workflows/log4cxx-ubuntu.yml
@@ -30,18 +30,30 @@
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 @@
- 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 ea122c8..3de5bc9 100644
--- a/src/cmake/win32_target_environment_path.cmake
+++ b/src/cmake/win32_target_environment_path.cmake
@@ -8,6 +8,9 @@
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 f1cf57d..4508a6e 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 @@
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 0000000..9040c5e
--- /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 fb0a9a5..1933f8f 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 0000000..34d4468
--- /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 0000000..6488908
--- /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 0000000..238199f
--- /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 ef8589f..17654b7 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 @@
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 4d3b9e0..0fd1805 100644
--- a/src/main/cpp/domconfigurator.cpp
+++ b/src/main/cpp/domconfigurator.cpp
@@ -865,7 +865,7 @@
}
#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 @@
}
#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 @@
}
#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 56fe768..88a04a9 100644
--- a/src/main/cpp/file.cpp
+++ b/src/main/cpp/file.cpp
@@ -95,7 +95,7 @@
}
#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 caa45ac..163cda7 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 @@
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 7d794c5..8fb6af1 100644
--- a/src/main/cpp/level.cpp
+++ b/src/main/cpp/level.cpp
@@ -173,7 +173,7 @@
#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 6972dc7..4a546a7 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 @@
#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 2679867..f304ca9 100644
--- a/src/main/cpp/timebasedrollingpolicy.cpp
+++ b/src/main/cpp/timebasedrollingpolicy.cpp
@@ -171,7 +171,11 @@
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 6cbe9f2..7ad9ad2 100644
--- a/src/main/cpp/transcoder.cpp
+++ b/src/main/cpp/transcoder.cpp
@@ -576,7 +576,7 @@
-#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/main/include/log4cxx-qt/logger.h b/src/main/include/log4cxx-qt/logger.h
new file mode 100644
index 0000000..f79d7fd
--- /dev/null
+++ b/src/main/include/log4cxx-qt/logger.h
@@ -0,0 +1,22 @@
+/*
+ * 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_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 0000000..bd4c9b7
--- /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 0000000..71002a2
--- /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 cc669ea..7bd9592 100644
--- a/src/main/include/log4cxx/file.h
+++ b/src/main/include/log4cxx/file.h
@@ -66,7 +66,7 @@
*/
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 8644b81..b0b98d5 100644
--- a/src/main/include/log4cxx/level.h
+++ b/src/main/include/log4cxx/level.h
@@ -126,7 +126,7 @@
*/
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 9f49c69..026fea9 100644
--- a/src/main/include/log4cxx/xml/domconfigurator.h
+++ b/src/main/include/log4cxx/xml/domconfigurator.h
@@ -221,7 +221,7 @@
#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 @@
#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 @@
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 242430b..e860118 100644
--- a/src/site/markdown/development/build-cmake.md
+++ b/src/site/markdown/development/build-cmake.md
@@ -71,6 +71,7 @@
| -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 dfbbb83..72992d8 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 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 @@
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 4f4bbbb..4e3ab35 100644
--- a/src/site/markdown/filters/filters.md
+++ b/src/site/markdown/filters/filters.md
@@ -28,7 +28,7 @@
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 @@
* @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 a324a26..7e0bb13 100644
--- a/src/site/markdown/qt-support.md
+++ b/src/site/markdown/qt-support.md
@@ -26,8 +26,14 @@
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 @@
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.
+