You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2023/08/06 05:37:56 UTC
[logging-log4cxx] 01/01: Allow a QString in a LOG4CXX_ macro when 'Qt support/integration' is ON
This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch qstring_overloads
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
commit 5419017124464677ebfbc145d8a2aa29f2bb979e
Author: Stephen Webb <sw...@gmail.com>
AuthorDate: Sun Aug 6 15:37:05 2023 +1000
Allow a QString in a LOG4CXX_ macro when 'Qt support/integration' is ON
---
src/examples/cpp/CMakeLists.txt | 7 +++
src/examples/cpp/MyApp-qt.cpp | 20 ++++++++
src/examples/cpp/com/foo/bar-qt.cpp | 11 ++++
src/examples/cpp/com/foo/config-qt.cpp | 71 +++++++++++++++++++++++++
src/examples/cpp/com/foo/config-qt.h | 22 ++++++++
src/main/include/log4cxx-qt/logger.h | 77 ++++++++++++++++++++++++++++
src/site/markdown/development/build-cmake.md | 1 +
src/site/markdown/qt-support.md | 11 +++-
8 files changed, 218 insertions(+), 2 deletions(-)
diff --git a/src/examples/cpp/CMakeLists.txt b/src/examples/cpp/CMakeLists.txt
index f1cf57d3..0a6c0a80 100644
--- a/src/examples/cpp/CMakeLists.txt
+++ b/src/examples/cpp/CMakeLists.txt
@@ -16,6 +16,9 @@
#
set(ALL_LOG4CXX_EXAMPLES auto-configured console delayedloop stream trivial 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..3d7ac609
--- /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, "Entering application.");
+ com::foo::Bar bar;
+ bar.doIt();
+ LOG4CXX_INFO(logger, "Exiting application.");
+ }
+ catch(std::exception&) {
+ result = EXIT_FAILURE;
+ }
+ return result;
+}
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..961513df
--- /dev/null
+++ b/src/examples/cpp/com/foo/bar-qt.cpp
@@ -0,0 +1,11 @@
+#include "com/foo/config-qt.h"
+#include "com/foo/bar.h"
+#include <log4cxx-qt/logger.h>
+
+using namespace com::foo;
+
+LoggerPtr Bar::m_logger(getLogger("com.foo.bar"));
+
+void Bar::doIt() {
+ LOG4CXX_DEBUG(m_logger, QString("Did it 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..1faf35b0
--- /dev/null
+++ b/src/examples/cpp/com/foo/config-qt.h
@@ -0,0 +1,22 @@
+#ifndef COM_FOO_CONFIG_H_
+#define COM_FOO_CONFIG_H_
+#include <QString>
+#include <log4cxx/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_H_
diff --git a/src/main/include/log4cxx-qt/logger.h b/src/main/include/log4cxx-qt/logger.h
new file mode 100644
index 00000000..e83d8db9
--- /dev/null
+++ b/src/main/include/log4cxx-qt/logger.h
@@ -0,0 +1,77 @@
+/*
+ * 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 <QString>
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+ log4cxx::LogString var; \
+ log4cxx::helpers::Transcoder::decode((src).toStdString(), var)
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+ QString var = QString::fromStdString(log4cxx::helpers::Transcoder::encode(src))
+#endif // LOG4CXX_LOGCHAR_IS_UTF8
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+ log4cxx::LogString var; \
+ log4cxx::helpers::Transcoder::decode((src).toStdWString(), var)
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+ QString var = QString::fromStdWString(log4cxx::helpers::Transcoder::encode(src))
+#endif // LOG4CXX_LOGCHAR_IS_WCHAR
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+#define LOG4CXX_DECODE_QSTRING(var, src) \
+ log4cxx::LogString var; \
+ log4cxx::helpers::Transcoder::decode((src).utf16(), var)
+
+#define LOG4CXX_ENCODE_QSTRING(var, src) \
+ QString var = QString::fromUtf16(log4cxx::helpers::Transcoder::encode(src.c_str()))
+#endif // LOG4CXX_LOGCHAR_IS_UNICHAR
+
+#if LOG4CXX_UNICHAR_API
+log4cxx::helpers::UniCharMessageBuffer& operator<<(log4cxx::helpers::UniCharMessageBuffer& mb, const QString& msg)
+{
+ return mb << msg.utf16();
+}
+
+log4cxx::helpers::UniCharMessageBuffer& operator<<(log4cxx::helpers::MessageBuffer& mb, const QString& msg)
+{
+ return mb << msg;
+}
+#else // !LOG4CXX_UNICHAR_API
+log4cxx::helpers::CharMessageBuffer& operator<<(log4cxx::helpers::CharMessageBuffer& mb, const QString& msg)
+{
+ LOG4CXX_DECODE_QSTRING(tmp, msg);
+ return mb << tmp;
+}
+
+#if LOG4CXX_WCHAR_T_API
+log4cxx::helpers::CharMessageBuffer& operator<<(log4cxx::helpers::MessageBuffer& mb, const QString& msg)
+{
+ LOG4CXX_DECODE_QSTRING(tmp, msg);
+ return mb << tmp;
+}
+#endif // LOG4CXX_WCHAR_T_API
+
+#endif // !LOG4CXX_UNICHAR_API
+
+#endif // _LOG4CXX_QT_LOGGER_H
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/qt-support.md b/src/site/markdown/qt-support.md
index a324a261..1b7b7cc9 100644
--- a/src/site/markdown/qt-support.md
+++ b/src/site/markdown/qt-support.md
@@ -26,8 +26,11 @@ 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 allows you to use QString values in a logging request.
+Building with LOG4CXX_QT_SUPPORT=ON also adds the log4cxx::qt namespace methods
+for directing Qt messages to Log4cxx and
+using the Qt event loop to process a configuration file change.
To install a message handler that will route the Qt logging messages
through Log4cxx, include the messagehandler.h and call
@@ -43,3 +46,7 @@ qInstallMessageHandler( log4cxx::qt::messageHandler );
Note that by default, this message handler also calls `abort` upon a
fatal message.
+
+To use the Qt event loop to monitor the configuration file
+do your Log4cxx configuration as follows:
+\include com/foo/config-qt.cpp
\ No newline at end of file