Mercurial > public > ostc_companion
view Utils/Log.cpp @ 1:0b3630a29ad8
Initial version based on previous repository.
Project was ported to QT6 and in now cmake based.
| author | Ideenmodellierer <tiefenrauscher@web.de> |
|---|---|
| date | Thu, 27 Nov 2025 18:40:28 +0100 |
| parents | |
| children |
line wrap: on
line source
////////////////////////////////////////////////////////////////////////////// /// \file Log.cpp /// \brief Basic logging tool /// \author JD Gascuel. /// \copyright (c) 2011-2016 JD Gascuel. All rights reserved. /// $Id$ ////////////////////////////////////////////////////////////////////////////// // // BSD 2-Clause License: // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // ////////////////////////////////////////////////////////////////////////////// #include "Utils/Log.h" #include "Utils/Exception.h" #include "Utils/LogConsole.h" #include "Utils/LogFile.h" #include "Utils/LogAppender.h" #include <QDir> #include <QStringList> #include <QRegularExpression> // 2013-08-30 jDG: Because of Linux compile, // we need to keep some minimal Qt4.8 compatibility... #if !defined(NO_WIDGETS) && QT_VERSION > 0x050100 # include <QWindow> #endif // Will be automaticallt set more verbose by File or Console appender, // if needed. Log::Level Log::minLevel = Log::LEVEL_WARNING; QString Log::_applicationPath; QString Log::_applicationName; ////////////////////////////////////////////////////////////////////////////// static QtMessageHandler forwarder = 0; static void Qt5Error(QtMsgType type, const QMessageLogContext &ctx, const QString &msg) { // Spurious error from Qt 5.4.1, when we DO NOT USE any SSL socket... if( ctx.category && strcmp(ctx.category, "qt.network.ssl") == 0 ) return; switch(type) { case QtDebugMsg: LogAction(Log::LEVEL_DEBUG, ctx.file, ctx.line, ctx.function) << msg; break; case QtInfoMsg: LogAction(Log::LEVEL_TRACE, ctx.file, ctx.line, ctx.function) << msg; break; case QtWarningMsg: LogAction(Log::LEVEL_WARNING, ctx.file, ctx.line, ctx.function) << msg; break; case QtCriticalMsg: LogAction(Log::LEVEL_ERROR, ctx.file, ctx.line, ctx.function) << msg; break; case QtFatalMsg: LogAction(Log::LEVEL_ERROR, ctx.file, ctx.line, ctx.function) << msg; break; } } ////////////////////////////////////////////////////////////////////////////// void Log::init(int& argc, char* argv[]) { minLevel = Log::LEVEL_WARNING; //---- Get the current application name ---------------------------------- if( argc > 0 && _applicationPath.isEmpty() ) { _applicationPath = QDir::current().absoluteFilePath( QString::fromLatin1(argv[0]) .replace('\\', '/')); _applicationName = _applicationPath.section('/', -1); _applicationPath = _applicationPath.section('/', 0, -2); #ifdef Q_OS_WIN32 if( _applicationName.endsWith(".exe") ) _applicationName = _applicationName.section('.', 0, -2); #elif defined(Q_OS_MACX) if( _applicationPath.endsWith("/MacOS") ) _applicationPath = _applicationPath.section('/', 0, -2); #elif defined(Q_OS_LINUX) // Nothing special, yet. #else # error Unknown OS not yet implemented #endif // Pop "/build/kitName" tail added by the QtCreator build process: if( _applicationPath.section('/', -2, -2) == "build" ) _applicationPath = _applicationPath.section('/', 0, -3); if( _applicationPath.section('/', -1, -1) == "build" ) _applicationPath = _applicationPath.section('/', 0, -2); // Pop /debug or /release tail too (Unix, Visual): // QRegExp tail("[.]?(debug|release)", Qt::CaseInsensitive); QRegularExpression tail( R"([.]?(debug|release))", QRegularExpression::CaseInsensitiveOption ); // if( tail.exactMatch(_applicationPath.section('/', -1, -1)) ) QRegularExpressionMatch match = tail.match(_applicationPath.section('/', -1, -1)); if (match.hasMatch()) _applicationPath = _applicationPath.section('/', 0, -2); if( _applicationName.endsWith(" DEBUG", Qt::CaseInsensitive) ) _applicationName = _applicationName.left(_applicationName.length()-6); // Pop "/bin/" tail added by the configured build process: if( _applicationPath.section('/', -1) == "bin" ) _applicationPath = _applicationPath.section('/', 0, -2); if( _applicationName.isEmpty() ) _applicationName = "log"; } //---- Forward Qt's messages --------------------------------------------- forwarder = qInstallMessageHandler(Qt5Error); //---- Instanciate 2 appenders ------------------------------------------- new LogConsole(argc, argv); new LogFile(argc, argv); } ////////////////////////////////////////////////////////////////////////////// void Log::close() { LOG_TRACE("Closing logs."); foreach(LogAppender* i, LogAppender::list()) delete i; } ////////////////////////////////////////////////////////////////////////////// Log::Log(Level level, const char *f, int line, const char *function) : level(level), line(line), function(function) { // Skip trailing "../" in file name (due to QtCreator build dir): while( f && f[0] == '.' && f[1] == '.' && (f[2] == '\\' || f[2] == '/') ) f += 3; const_cast<QString&>(file) = QString::fromLatin1(f).replace('\\', '/'); } LogAction::LogAction(Level level, const char *file, int line, const char *function) : Log(level, file, line, function) {} ////////////////////////////////////////////////////////////////////////////// LogAction::~LogAction() { LogAppender::all(*this); } ////////////////////////////////////////////////////////////////////////////// LogAction &LogAction::operator<<(char msg) { if( message.length() < (LOG_MAX_MESSAGE_LENGTH-1) ) message += QChar(msg); // UTF-8 by default. return *this; } LogAction &LogAction::operator<<(unsigned char msg) { if( message.length() < (LOG_MAX_MESSAGE_LENGTH-1) ) message += QChar(msg); // UTF-8 by default. return *this; } LogAction& LogAction::operator<<(const char* msg) { if( message.length()+strlen(msg) < (LOG_MAX_MESSAGE_LENGTH) ) message += QString::fromUtf8(msg); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction& LogAction::operator<<(const QString& msg) { if( message.length()+msg.length() < (LOG_MAX_MESSAGE_LENGTH) ) message += msg; return *this; } LogAction &LogAction::operator <<(const QStringList& list) { *this << "{"; for(int i=0; i<list.count(); ++i) { if( i > 0 ) *this << ", "; *this << list[i]; } *this << "}"; return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction& LogAction::operator<<(const QByteArray& msg) { operator<<(QString::fromUtf8(msg)); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction& LogAction::operator<<(double value) { operator<<(QString::number(value)); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction& LogAction::operator<<(int value) { operator<<(QString::number(value)); return *this; } LogAction& LogAction::operator<<(unsigned int value) { operator<<(QString::number(value)); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction &LogAction::operator <<(unsigned long value) { operator<<(QString::number((qulonglong)value)); return *this; } LogAction &LogAction::operator <<(long value) { operator<<(QString::number((qlonglong)value)); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction &LogAction::operator <<(unsigned long long value) { operator<<(QString::number(value)); return *this; } LogAction &LogAction::operator <<(long long value) { operator<<(QString::number(value)); return *this; } ////////////////////////////////////////////////////////////////////////////// LogAction &LogAction::operator <<(const void *ptr) { operator<<("0x"); operator<<(QString::number((qulonglong)ptr, 16)); return *this; }
