Adds q2 repos to migrate
This commit is contained in:
1 parent
ad1f62c4ee
commit
17f1c61c9e
991 files changed
+178451
No files matched your search
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(ngldb)
|
||||
ADD_SUBDIRECTORY(tcpserver)
|
||||
ADD_SUBDIRECTORY(QtSingleApplication)
|
||||
ADD_SUBDIRECTORY(WMS_Interface)
|
||||
ADD_SUBDIRECTORY(nglapplication)
|
||||
ADD_SUBDIRECTORY(nglcompression)
|
||||
ADD_SUBDIRECTORY(nglsettings)
|
||||
ADD_SUBDIRECTORY(ngltranslator)
|
||||
ADD_SUBDIRECTORY(ngltools)
|
||||
ADD_SUBDIRECTORY(nglwidgets)
|
||||
ADD_SUBDIRECTORY(NGLLogger)
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
|
||||
FIND_PACKAGE(Log4Qt REQUIRED)
|
||||
|
||||
# Sourcen
|
||||
SET(NGLLogger_SRCS
|
||||
MurmurHash2.cpp
|
||||
MurmurHash2.h
|
||||
INGLLogger.h
|
||||
|
||||
NGLLogger_export.h
|
||||
NGLLoggerBootstrap.cpp
|
||||
NGLLoggerBootstrap.h
|
||||
NGLLogger.cpp
|
||||
NGLLogger.h
|
||||
)
|
||||
|
||||
# Header
|
||||
SET(NGLLogger_HDRS
|
||||
)
|
||||
|
||||
# Make sure NGLLogger.h compiles ..
|
||||
ADD_DEFINITIONS(-DBUILDING_NGLLOGGER)
|
||||
NGL_ADD_LIBRARY(ALL NGLLogger SHARED ${NGLLogger_SRCS} ${NGLLogger_HDRS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(NGLLogger
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(NGLLogger
|
||||
PRIVATE
|
||||
Log4Qt::log4qt
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(NGLLogger)
|
||||
|
||||
#
|
||||
# test_ngllogger
|
||||
#
|
||||
IF(BUILD_TESTING AND TARGET NGLLogger)
|
||||
ADD_EXECUTABLE(test_ngllogger test_ngllogger.cpp)
|
||||
TARGET_LINK_LIBRARIES(test_ngllogger NGLLogger)
|
||||
TARGET_LINK_LIBRARIES(test_ngllogger
|
||||
Log4Qt::log4qt
|
||||
ngltools
|
||||
)
|
||||
ADD_TEST(NAME test_ngllogger COMMAND $<TARGET_FILE:test_ngllogger>)
|
||||
ENDIF(BUILD_TESTING AND TARGET NGLLogger)
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/log4cxx.props ${CMAKE_BINARY_DIR}/log4cxx.props COPYONLY)
|
||||
Executable
+306
@@ -0,0 +1,306 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <QString>
|
||||
#include <QPointF>
|
||||
#include <QSize>
|
||||
#include <QRect>
|
||||
#include <QRectF>
|
||||
#include <QList>
|
||||
#include "NGLLogger_export.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
|
||||
enum class LogLevel
|
||||
{
|
||||
Undefined = 0,
|
||||
Trace = 64,
|
||||
Debug = 96,
|
||||
Info = 128,
|
||||
Warning = 150,
|
||||
Error = 182,
|
||||
Fatal = 214,
|
||||
};
|
||||
|
||||
class LogStreamHelper
|
||||
{
|
||||
public:
|
||||
inline LogStreamHelper(INGLLogger &logger, LogLevel level, const char *const file, int line, const char *const function)
|
||||
: m_logger(logger)
|
||||
, m_level(level)
|
||||
, m_line(line)
|
||||
, m_file(file)
|
||||
, m_func(function)
|
||||
{}
|
||||
inline ~LogStreamHelper();
|
||||
|
||||
template<typename T>
|
||||
inline LogStreamHelper &operator<<(const T &val);
|
||||
|
||||
private:
|
||||
std::ostringstream m_buffer;
|
||||
NGL::INGLLogger &m_logger;
|
||||
const LogLevel m_level;
|
||||
const int m_line;
|
||||
const char *const m_file;
|
||||
const char *const m_func;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class INGLLogger
|
||||
{
|
||||
public:
|
||||
INGLLogger(const INGLLogger &) = delete;
|
||||
INGLLogger &operator=(const INGLLogger &) = delete;
|
||||
INGLLogger() = default;
|
||||
virtual ~INGLLogger() = default;
|
||||
|
||||
using String = std::string;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual INGLLogger &getNGLLogger(const char *fullqualifiedname) = 0;
|
||||
virtual INGLLogger &getNGLLogger(const std::string &fullqualifiedname) = 0;
|
||||
|
||||
|
||||
|
||||
virtual bool isTraceEnabled() const = 0;
|
||||
virtual bool isDebugEnabled() const = 0;
|
||||
virtual bool isInfoEnabled() const = 0;
|
||||
virtual bool isWarningEnabled() const = 0;
|
||||
virtual bool isErrorEnabled() const = 0;
|
||||
virtual bool isFatalEnabled() const = 0;
|
||||
virtual bool isLevelEnabled(LogLevel level) const = 0;
|
||||
|
||||
|
||||
|
||||
virtual void log(LogLevel level, const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
|
||||
virtual void logTrace(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logDebug(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logInfo(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logWarning(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logError(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logFatal(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
|
||||
|
||||
|
||||
virtual void logStartup(const char *file, int line, const char *function = nullptr) = 0;
|
||||
|
||||
virtual void logShutdown(const char *file, int line, const char *function = nullptr) = 0;
|
||||
|
||||
|
||||
virtual std::string getLoggerName() const = 0;
|
||||
|
||||
virtual void setNoSpace(bool bNoSpace) = 0;
|
||||
virtual bool noSpace() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline LogStreamHelper::~LogStreamHelper()
|
||||
{
|
||||
m_logger.log(m_level, m_buffer.str(), m_file, m_line, m_func);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline LogStreamHelper &LogStreamHelper::operator<<(const T &val)
|
||||
{
|
||||
m_buffer << val;
|
||||
if (!m_logger.noSpace())
|
||||
m_buffer << " ";
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const QByteArray &str)
|
||||
{
|
||||
stream << std::string(str.data(), str.size());
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream,
|
||||
const QPointF &value)
|
||||
{
|
||||
stream << "QPointF(" << QString::number(value.x(), 'f', 6).toStdString() << "#" << QString::number(value.y(), 'f', 6).toStdString() << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QPoint &value)
|
||||
{
|
||||
stream << "QPoint(" << value.x() << "#" << value.y() << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QSize &value)
|
||||
{
|
||||
stream << "QSize(w=" << value.width() << ";h=" << value.height() << ")";
|
||||
return stream;
|
||||
}
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QSizeF &value)
|
||||
{
|
||||
stream << "QSize(w="
|
||||
<< QString::number(value.width(), 'f', 6).toStdString() << ";h="
|
||||
<< QString::number(value.height(), 'f', 6).toStdString()
|
||||
<< ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QRect &value)
|
||||
{
|
||||
stream << "QRect(center=" << value.center()
|
||||
<< " w=" << value.width()
|
||||
<< ";h=" << value.height()
|
||||
<< " bottomLeft=" << value.bottomLeft()
|
||||
<< " topRight=" << value.topRight()
|
||||
<< ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QRectF &value)
|
||||
{
|
||||
stream << "QRectF(center=" << value.center()
|
||||
<< " w=" << QString::number(value.width(), 'f', 3).toStdString()
|
||||
<< ";h=" << QString::number(value.height(), 'f', 3).toStdString()
|
||||
<< " bottomLeft=" << value.bottomLeft()
|
||||
<< " topRight=" << value.topRight()
|
||||
<< ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QList<int> &value)
|
||||
{
|
||||
stream << "QList<int>(" << value.size() << "): ";
|
||||
for (int i : value)
|
||||
stream << i << ";";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream &operator<< (std::ostream &stream,
|
||||
const QList<QPointF> &value)
|
||||
{
|
||||
stream << "QList<QPointF>(" << value.size() << "): ";
|
||||
for (const QPointF &item : value)
|
||||
stream << item << ";";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const QString &str)
|
||||
{
|
||||
return stream << str.toUtf8();
|
||||
}
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
namespace NGLLoggerHelper
|
||||
{
|
||||
NGLLOGGER_EXPORT void hexDumpHelper(NGL::INGLLogger &logger,
|
||||
NGL::LogLevel level,
|
||||
const void *a_data,
|
||||
const unsigned int a_size);
|
||||
inline void hexDumpHelper(NGL::INGLLogger &logger,
|
||||
NGL::LogLevel level,
|
||||
const QByteArray &data)
|
||||
{
|
||||
return hexDumpHelper(logger, level, data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
NGLLOGGER_EXPORT NGL::INGLLogger& getMemoryLogger();
|
||||
NGLLOGGER_EXPORT std::string getMemoryData();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define LOGFUNCTION Q_FUNC_INFO
|
||||
|
||||
|
||||
#define NOTICE_LOG(logger) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
#define TRACE_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isTraceEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
#else
|
||||
#define TRACE_LOG(logger) \
|
||||
for ( ; false; ) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
#endif
|
||||
|
||||
#define DEBUG_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isDebugEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Debug, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#define INFO_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#define WARNING_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isWarningEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Warning, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#define ERROR_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isErrorEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Error, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#define FATAL_LOG(logger) \
|
||||
for (bool log_level_enabled = (logger).isFatalEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(logger, NGL::LogLevel::Fatal, __FILE__,__LINE__, Q_FUNC_INFO)
|
||||
|
||||
#define STARTUP_LOG(logger) { (logger).logStartup(__FILE__, __LINE__, Q_FUNC_INFO); }
|
||||
#define SHUTDOWN_LOG(logger) { (logger).logShutdown(__FILE__, __LINE__, Q_FUNC_INFO); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define MEMORY_LOG() \
|
||||
for (bool log_level_enabled = (NGL::getMemoryLogger()).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \
|
||||
NGL::LogStreamHelper(NGL::getMemoryLogger(), NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO) << NGL::getMemoryData()
|
||||
|
||||
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "MurmurHash2.h"
|
||||
#include <QtCore/qcompilerdetection.h>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed )
|
||||
{
|
||||
|
||||
|
||||
|
||||
const unsigned int m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
|
||||
|
||||
|
||||
unsigned int h = seed ^ len;
|
||||
|
||||
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
unsigned int k = *(reinterpret_cast<const unsigned int *>(data));
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h *= m;
|
||||
h ^= k;
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
Q_FALLTHROUGH();
|
||||
case 2: h ^= data[1] << 8;
|
||||
Q_FALLTHROUGH();
|
||||
case 1: h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed = 0 );
|
||||
}
|
||||
Executable
+446
@@ -0,0 +1,446 @@
|
||||
|
||||
|
||||
|
||||
#include "NGLLogger.h"
|
||||
#include "MurmurHash2.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <log4qt/logger.h>
|
||||
#include <log4qt/logmanager.h>
|
||||
#include <log4qt/loggerrepository.h>
|
||||
#include <log4qt/propertyconfigurator.h>
|
||||
#include <log4qt/rollingfileappender.h>
|
||||
#include <log4qt/helpers/configuratorhelper.h>
|
||||
#include <log4qt/helpers/properties.h>
|
||||
#include <log4qt/helpers/factory.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
void LtsRollingFileAppender::setLtsLogfileName(const QString <sLogfileName)
|
||||
{
|
||||
m_ltsLogfileName = ltsLogfileName;
|
||||
}
|
||||
|
||||
void LtsRollingFileAppender::activateOptions()
|
||||
{
|
||||
if (!m_ltsLogfileName.isEmpty())
|
||||
setFile(m_ltsLogfileName);
|
||||
Log4Qt::RollingFileAppender::activateOptions();
|
||||
}
|
||||
|
||||
QString LtsRollingFileAppender::m_ltsLogfileName;
|
||||
static Log4Qt::Appender *createLtsRollingFileAppender()
|
||||
{
|
||||
auto ret = new LtsRollingFileAppender;
|
||||
ret->setAppendFile(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CleanupHelper final
|
||||
{
|
||||
public:
|
||||
CleanupHelper() = default;
|
||||
~CleanupHelper();
|
||||
std::mutex &getLoggerMapMutex();
|
||||
|
||||
std::unordered_map<unsigned int, NGL::NGLLogger *> m_loggermap;
|
||||
protected:
|
||||
std::mutex m_loggermapmutex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::NGLLogger *NGL::NGLLogger::rootlogger_ptr = nullptr;
|
||||
|
||||
NGL::CleanupHelper NGL::NGLLogger::s_cleanup;
|
||||
|
||||
|
||||
|
||||
|
||||
CleanupHelper::~CleanupHelper()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_loggermapmutex);
|
||||
|
||||
for (auto it : m_loggermap)
|
||||
delete it.second;
|
||||
m_loggermap.clear();
|
||||
|
||||
delete NGL::NGLLogger::rootlogger_ptr;
|
||||
NGL::NGLLogger::rootlogger_ptr = nullptr;
|
||||
}
|
||||
|
||||
std::mutex &CleanupHelper::getLoggerMapMutex()
|
||||
{
|
||||
return m_loggermapmutex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::NGLLogger::NGLLogger(const std::string &fullqualifiedname)
|
||||
: name(fullqualifiedname)
|
||||
, currentLevel(LogLevel::Undefined)
|
||||
, m_bNoSpace(true)
|
||||
{
|
||||
if (!fullqualifiedname.empty())
|
||||
{
|
||||
logger_ptr = Log4Qt::LogManager::loggerRepository()->logger(QString::fromStdString(name));
|
||||
s_cleanup.m_loggermap[MurmurHash2(fullqualifiedname.c_str(), fullqualifiedname.size())] = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger_ptr = Log4Qt::LogManager::loggerRepository()->rootLogger();
|
||||
|
||||
}
|
||||
|
||||
|
||||
configChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &NGL::NGLLogger::getNGLLogger(const char *fullqualifiedname)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_cleanup.getLoggerMapMutex());
|
||||
auto it = s_cleanup.m_loggermap.find(MurmurHash2(fullqualifiedname, strlen(fullqualifiedname)));
|
||||
if (it != s_cleanup.m_loggermap.end())
|
||||
return *(*it).second;
|
||||
|
||||
return *(new NGLLogger(fullqualifiedname));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &NGL::NGLLogger::getNGLLogger(const std::string &fullqualifiedname)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_cleanup.getLoggerMapMutex());
|
||||
auto it = s_cleanup.m_loggermap.find(MurmurHash2(fullqualifiedname.c_str(), fullqualifiedname.size()));
|
||||
if (it != s_cleanup.m_loggermap.end())
|
||||
return *(*it).second;
|
||||
|
||||
return *(new NGLLogger(fullqualifiedname));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::log(LogLevel level, const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
logger_ptr->logWithLocation(static_cast<Log4Qt::Level::Value>(level), file, line, function, QString::fromStdString(message));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logTrace(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
if (currentLevel >= LogLevel::Trace)
|
||||
log(LogLevel::Trace, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logDebug(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
if (currentLevel >= LogLevel::Debug)
|
||||
log(LogLevel::Debug, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logInfo(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
if (currentLevel >= LogLevel::Info)
|
||||
log(LogLevel::Info, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logWarning(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
if (currentLevel >= LogLevel::Warning)
|
||||
log(LogLevel::Warning, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logError(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
if (currentLevel >= LogLevel::Error)
|
||||
log(LogLevel::Error, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logFatal(const INGLLogger::String &message, const char *file, int line, const char *function)
|
||||
{
|
||||
log(LogLevel::Fatal, message, file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef LTS_VERSION_MAJOR
|
||||
#define LTS_VERSION_MAJOR "undefined"
|
||||
#endif
|
||||
#ifndef LTS_VERSION_MINOR
|
||||
#define LTS_VERSION_MINOR "undefined"
|
||||
#endif
|
||||
#ifndef LTS_VERSION_PATCH
|
||||
#define LTS_VERSION_PATCH "undefined"
|
||||
#endif
|
||||
#ifndef LTS_VERSION_DATE
|
||||
#define LTS_VERSION_DATE "undefined"
|
||||
#endif
|
||||
#ifndef JENKINS_BUILD_NUMBER
|
||||
#define JENKINS_BUILD_NUMBER "unknown"
|
||||
#endif
|
||||
static const char ver_major[] = LTS_VERSION_MAJOR;
|
||||
static const char ver_minor[] = LTS_VERSION_MINOR;
|
||||
static const char ver_patch[] = LTS_VERSION_PATCH;
|
||||
static const char ver_date[] = LTS_VERSION_DATE;
|
||||
static const char ver_jenkins[] = JENKINS_BUILD_NUMBER;
|
||||
|
||||
void NGL::NGLLogger::logStartup(const char *file, int line, const char *function)
|
||||
{
|
||||
log(LogLevel::Info, QStringLiteral("Application is started (%1.%2-%3 rev%4 from %5)")
|
||||
.arg(QString::fromLatin1(ver_major),
|
||||
QString::fromLatin1(ver_minor),
|
||||
QString::fromLatin1(ver_jenkins),
|
||||
QString::fromLatin1(ver_patch),
|
||||
QString::fromLatin1(ver_date)).toUtf8().constData(), file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void NGL::NGLLogger::logShutdown(const char *file, int line, const char *function)
|
||||
{
|
||||
log(LogLevel::Info, QStringLiteral("Application is shut down (%1.%2-%3 rev%4 from %5)")
|
||||
.arg(QString::fromLatin1(ver_major),
|
||||
QString::fromLatin1(ver_minor),
|
||||
QString::fromLatin1(ver_jenkins),
|
||||
QString::fromLatin1(ver_patch),
|
||||
QString::fromLatin1(ver_date)).toUtf8().constData(), file, line, function);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::NGLLogger &NGL::NGLLogger::getNGLRootLogger()
|
||||
{
|
||||
if (!rootlogger_ptr) throw NotCreatedError();
|
||||
return *rootlogger_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static QString findConfigFile(const QString &configfilename)
|
||||
{
|
||||
if (configfilename.isEmpty())
|
||||
return QString();
|
||||
|
||||
|
||||
QFileInfo fi(configfilename);
|
||||
if (fi.isFile() && fi.isReadable())
|
||||
return fi.absoluteFilePath();
|
||||
|
||||
|
||||
QString p = QCoreApplication::applicationDirPath() + QLatin1Char('/') + configfilename;
|
||||
fi.setFile(p);
|
||||
if (fi.isFile() && fi.isReadable())
|
||||
return fi.absoluteFilePath();
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::NGLLogger &NGL::NGLLogger::createNGLRootLogger(const QString &configfilename,
|
||||
bool ignorealreadycreated,
|
||||
const QString &logOutputName,
|
||||
bool quiet)
|
||||
{
|
||||
if (rootlogger_ptr)
|
||||
{
|
||||
if (!ignorealreadycreated) throw AlreadyCreatedError();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4Qt::Factory::registerAppender("Lts::RollingFileAppender", createLtsRollingFileAppender);
|
||||
LtsRollingFileAppender::setLtsLogfileName(logOutputName);
|
||||
|
||||
rootlogger_ptr = new NGLLogger(std::string());
|
||||
const QString filename = findConfigFile(configfilename);
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
Log4Qt::PropertyConfigurator::configureAndWatch(filename);
|
||||
QObject::connect(Log4Qt::ConfiguratorHelper::instance(), &Log4Qt::ConfiguratorHelper::configurationFileChanged,
|
||||
[]() { configurationFileChanged(); });
|
||||
const auto l = Log4Qt::ConfiguratorHelper::instance()->configureError();
|
||||
for (const auto &t : l)
|
||||
std::cerr << t.message().toUtf8().data() << std::endl;
|
||||
if (!l.isEmpty())
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!quiet)
|
||||
std::cerr << "Could not find log4cxx configuration file " << configfilename << std::endl
|
||||
<< "Using default logging to stdout" << std::endl;
|
||||
|
||||
|
||||
Log4Qt::Properties props;
|
||||
props.setProperty(QLatin1String("log4j.rootLogger"),
|
||||
QLatin1String("WARN, stdout"));
|
||||
props.setProperty(QLatin1String("log4j.appender.stdout"),
|
||||
QLatin1String("org.apache.log4j.ConsoleAppender"));
|
||||
props.setProperty(QLatin1String("log4j.appender.stdout.layout"),
|
||||
QLatin1String("org.apache.log4j.PatternLayout"));
|
||||
props.setProperty(QLatin1String("log4j.appender.stdout.layout.ConversionPattern"),
|
||||
QLatin1String("%d %-5p %c |#| %m (%.50F:%L) %n"));
|
||||
Log4Qt::PropertyConfigurator::configure(props);
|
||||
}
|
||||
rootlogger_ptr->configChanged();
|
||||
}
|
||||
return *rootlogger_ptr;
|
||||
}
|
||||
|
||||
void NGL::NGLLogger::configurationFileChanged()
|
||||
{
|
||||
for (auto ptr : s_cleanup.m_loggermap)
|
||||
ptr.second->configChanged();
|
||||
}
|
||||
|
||||
void NGL::NGLLogger::configChanged()
|
||||
{
|
||||
if (logger_ptr->isTraceEnabled())
|
||||
currentLevel = LogLevel::Trace;
|
||||
else if (logger_ptr->isDebugEnabled())
|
||||
currentLevel = LogLevel::Debug;
|
||||
else if (logger_ptr->isInfoEnabled())
|
||||
currentLevel = LogLevel::Info;
|
||||
else if (logger_ptr->isWarnEnabled())
|
||||
currentLevel = LogLevel::Warning;
|
||||
else if (logger_ptr->isErrorEnabled())
|
||||
currentLevel = LogLevel::Error;
|
||||
else
|
||||
currentLevel = LogLevel::Fatal;
|
||||
}
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
namespace NGLLoggerHelper
|
||||
{
|
||||
|
||||
void hexDumpHelper(NGL::INGLLogger &logger, NGL::LogLevel level,
|
||||
const void *a_data, const unsigned int a_size)
|
||||
{
|
||||
if (!logger.isLevelEnabled(level) || !a_data)
|
||||
return;
|
||||
|
||||
unsigned char *data = (unsigned char *)a_data;
|
||||
QByteArray baBuf;
|
||||
for (unsigned int i = 0; i < a_size; i++)
|
||||
{
|
||||
if (0 == (i % 8))
|
||||
baBuf = QByteArray::number(i, 16).rightJustified(8, '0').toUpper();
|
||||
baBuf += " " + QByteArray::number(data[i], 16).rightJustified(2, '0').toUpper();
|
||||
if (7 == (i % 8))
|
||||
logger.log(level, baBuf.constData(), __FILE__, __LINE__);
|
||||
}
|
||||
if (a_size % 8)
|
||||
logger.log(level, baBuf.constData(), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NGL::INGLLogger& getMemoryLogger()
|
||||
{
|
||||
try
|
||||
{
|
||||
return NGLLogger::getNGLRootLogger().getNGLLogger("memorystate");
|
||||
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int parseLine(char* line){
|
||||
|
||||
int i = strlen(line);
|
||||
const char* p = line;
|
||||
while (*p <'0' || *p > '9') p++;
|
||||
line[i-3] = '\0';
|
||||
i = atoi(p);
|
||||
return i;
|
||||
}
|
||||
|
||||
int getMemoryValue()
|
||||
{
|
||||
|
||||
FILE* file = fopen("/proc/self/status", "r");
|
||||
int result = -1;
|
||||
char line[128];
|
||||
|
||||
while (fgets(line, 128, file) != NULL){
|
||||
|
||||
if (strncmp(line, "VmRSS:", 6) == 0){
|
||||
result = parseLine(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getMemoryData()
|
||||
{
|
||||
return QStringLiteral("VmRSS: %1 kB #").arg(QString::number(getMemoryValue())).toStdString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef BUILDING_NGLLOGGER
|
||||
#error Do not include me outside NGLLogger library - only use INGLLogger.h!
|
||||
#endif
|
||||
|
||||
#include "INGLLogger.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <log4qt/logger.h>
|
||||
#include <log4qt/rollingfileappender.h>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
class CleanupHelper;
|
||||
|
||||
class LtsRollingFileAppender final : public Log4Qt::RollingFileAppender
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using Log4Qt::RollingFileAppender::RollingFileAppender;
|
||||
static void setLtsLogfileName(const QString <sLogfileName);
|
||||
void activateOptions() override;
|
||||
private:
|
||||
static QString m_ltsLogfileName;
|
||||
};
|
||||
|
||||
class NGLLogger final : public INGLLogger
|
||||
{
|
||||
explicit NGLLogger(const std::string &fullqualifiedname);
|
||||
public:
|
||||
|
||||
class NotCreatedError {};
|
||||
class AlreadyCreatedError {};
|
||||
|
||||
INGLLogger &getNGLLogger(const char *fullqualifiedname) override;
|
||||
INGLLogger &getNGLLogger(const std::string &fullqualifiedname) override;
|
||||
|
||||
inline bool isTraceEnabled() const override { return currentLevel <= LogLevel::Trace; }
|
||||
inline bool isDebugEnabled() const override { return currentLevel <= LogLevel::Debug; }
|
||||
inline bool isInfoEnabled() const override { return currentLevel <= LogLevel::Info; }
|
||||
inline bool isWarningEnabled() const override { return currentLevel <= LogLevel::Warning; }
|
||||
inline bool isErrorEnabled() const override { return currentLevel <= LogLevel::Error; }
|
||||
inline bool isFatalEnabled() const override { return currentLevel <= LogLevel::Fatal; }
|
||||
inline bool isLevelEnabled(LogLevel level) const override { return currentLevel <= level; }
|
||||
|
||||
void log(LogLevel level, const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logTrace(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logDebug(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logInfo(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logWarning(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logError(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
void logFatal(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) override;
|
||||
|
||||
void logStartup(const char *file, int line, const char *function = nullptr) override;
|
||||
void logShutdown(const char *file, int line, const char *function = nullptr) override;
|
||||
|
||||
inline void setNoSpace(bool bNoSpace) override { m_bNoSpace = bNoSpace; }
|
||||
inline bool noSpace() const override { return m_bNoSpace; }
|
||||
|
||||
inline std::string getLoggerName() const override { return name; }
|
||||
|
||||
static NGLLogger &getNGLRootLogger();
|
||||
static NGLLogger &createNGLRootLogger(const QString &configfilename,
|
||||
bool ignorealreadycreated,
|
||||
const QString &logOutputName = QString(),
|
||||
bool quiet = false);
|
||||
|
||||
Log4Qt::Logger *log4qtLogger() { return logger_ptr; }
|
||||
protected:
|
||||
static void configurationFileChanged();
|
||||
void configChanged();
|
||||
|
||||
private:
|
||||
|
||||
Log4Qt::Logger *logger_ptr;
|
||||
const std::string name;
|
||||
LogLevel currentLevel;
|
||||
bool m_bNoSpace;
|
||||
|
||||
static NGLLogger *rootlogger_ptr;
|
||||
|
||||
friend class CleanupHelper;
|
||||
static CleanupHelper s_cleanup;
|
||||
|
||||
friend class XMLWatchdog;
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
|
||||
#include "NGLLoggerBootstrap.h"
|
||||
#include "NGLLogger.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger & NGL::NGLLoggerBootstrap::getNGLRootLogger()
|
||||
{
|
||||
return NGL::NGLLogger::getNGLRootLogger();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger & NGL::NGLLoggerBootstrap::createNGLRootLogger(const QString &configfilename,
|
||||
bool ignorealreadycreated,
|
||||
const QString &logOutputName,
|
||||
bool quiet)
|
||||
{
|
||||
return NGL::NGLLogger::createNGLRootLogger(configfilename, ignorealreadycreated, logOutputName, quiet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
|
||||
|
||||
|
||||
#ifndef NGLLOGGERBOOTSTRAP_H
|
||||
#define NGLLOGGERBOOTSTRAP_H
|
||||
|
||||
#include "INGLLogger.h"
|
||||
#include "NGLLogger_export.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
namespace NGLLoggerBootstrap
|
||||
{
|
||||
class AlreadyCreatedError final : public std::exception
|
||||
{
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "NGLLogger rootlogger already created!";
|
||||
}
|
||||
};
|
||||
|
||||
class NotCreatedError final : public std::exception
|
||||
{
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "NGLLogger rootlogger not yet created!";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
NGLLOGGER_EXPORT INGLLogger &getNGLRootLogger();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NGLLOGGER_EXPORT INGLLogger &createNGLRootLogger(const QString &configfilename,
|
||||
bool ignorealreadycreated,
|
||||
const QString &logOutputName = QString(),
|
||||
bool quiet = false);
|
||||
inline INGLLogger &createNGLRootLogger(const char *configfilename,
|
||||
bool ignorealreadycreated,
|
||||
const QString &logOutputName = QString())
|
||||
{
|
||||
return createNGLRootLogger(QString::fromUtf8(configfilename), ignorealreadycreated, logOutputName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
#ifndef NGLLOGGER_EXPORT_H
|
||||
#define NGLLOGGER_EXPORT_H
|
||||
|
||||
#ifndef NGLLOGGER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLLOGGER_EXPORT
|
||||
# else
|
||||
# ifdef WIN32
|
||||
# ifdef MAKE_NGLLOGGER_LIB
|
||||
# define NGLLOGGER_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define NGLLOGGER_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define NGLLOGGER_EXPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=ERROR, stdout
|
||||
|
||||
log4j.logger.Gui=TRACE, console
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%p %d %t %c{1} - %F:%L %m%n
|
||||
|
||||
|
||||
log4j.logger.ngs=FATAL, stdout
|
||||
log4j.logger.ngs.Application_1=INFO, file
|
||||
log4j.logger.ngs.Application_2=ERROR
|
||||
log4j.logger.ngs.Application_3=ERROR
|
||||
|
||||
log4j.logger.libsymbol.SymbolTable=WARN, stdout
|
||||
log4j.logger.libsymbol.SymbolReader=WARN, stdout
|
||||
log4j.logger.libngldb=INFO, stdout
|
||||
|
||||
log4j.logger.NGL.main=INFO, stdout, file
|
||||
log4j.logger.NGL.MainWindow=INFO, stdout, file
|
||||
log4j.logger.NGL.zwmsqt=INFO, stdout, file
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=#ngs# %r %p %d %t %c %c{1} - %F:%L %m%n
|
||||
|
||||
log4j.appender.file=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.file.MaxFileSize=1MB
|
||||
log4j.appender.file.MaxBackupIndex=9
|
||||
log4j.appender.file.file=log.out
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=#ngs# %r %p %d %t %c %c{1} - %F:%L %m%n
|
||||
|
||||
log4j.appender.syslog=org.apache.log4j.SyslogAppender
|
||||
log4j.appender.syslog.Threshold=WARN
|
||||
log4j.appender.syslog.SysLogHost=localhost
|
||||
log4j.appender.syslog.Facility=LOCAL7
|
||||
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
|
||||
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#include "INGLLogger.h"
|
||||
#include "NGLLoggerBootstrap.h"
|
||||
#include <QCoreApplication>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx.props", false);
|
||||
|
||||
NGL::INGLLogger &l = NGL::NGLLoggerBootstrap::getNGLRootLogger(). getNGLLogger( "Gui" );
|
||||
|
||||
STARTUP_LOG(l);
|
||||
SHUTDOWN_LOG(l);
|
||||
NOTICE_LOG(l) << "Gui - NOTICE";
|
||||
TRACE_LOG(l) << "Gui - TRACE";
|
||||
DEBUG_LOG(l) << "Gui - DEBUG";
|
||||
INFO_LOG(l) << "Gui - INFO";
|
||||
WARNING_LOG(l) << "Gui - WARNING";
|
||||
ERROR_LOG(l) << "Gui - ERROR";
|
||||
FATAL_LOG(l) << "Gui - FATAL";
|
||||
|
||||
NGL::INGLLogger &l2 = NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger( "Gui.AES" );
|
||||
NOTICE_LOG(l2) << "Gui.AES - NOTICE";
|
||||
TRACE_LOG(l2) << "Gui.AES - TRACE";
|
||||
DEBUG_LOG(l2) << "Gui.AES - DEBUG";
|
||||
INFO_LOG(l2) << "Gui.AES - INFO";
|
||||
WARNING_LOG(l2) << "Gui.AES - WARNING";
|
||||
ERROR_LOG(l2) << "Gui.AES - ERROR";
|
||||
FATAL_LOG(l2) << "Gui.AES - FATAL";
|
||||
SHUTDOWN_LOG(l2)
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
# QtSingleApplication solution from
|
||||
# http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication
|
||||
# LGPL
|
||||
|
||||
SET(qtsapp_common_SRCS
|
||||
qtlocalpeer.cpp
|
||||
qtlocalpeer.h
|
||||
)
|
||||
QT5_WRAP_CPP(qtsapp_common_SRCS qtlockedfile.h)
|
||||
NGL_ADD_LIBRARY(WS AAR SV qtsa_common STATIC ${qtsapp_common_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(qtsa_common
|
||||
PUBLIC
|
||||
Qt5::Network
|
||||
Qt5::Core
|
||||
)
|
||||
|
||||
SET(qtsapp_SRCS
|
||||
qtsingleapplication.cpp
|
||||
qtsingleapplication.h
|
||||
|
||||
)
|
||||
NGL_ADD_LIBRARY(WS qtsingleapplication SHARED ${qtsapp_SRCS})
|
||||
NGL_INSTALL_TARGET(qtsingleapplication)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(qtsingleapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(qtsingleapplication
|
||||
PRIVATE
|
||||
qtsa_common
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
)
|
||||
|
||||
SET(qtscoreapp_SRCS
|
||||
qtsinglecoreapplication.h
|
||||
qtsinglecoreapplication.cpp
|
||||
)
|
||||
NGL_ADD_LIBRARY(AAR SV qtsinglecoreapplication SHARED ${qtscoreapp_SRCS})
|
||||
NGL_INSTALL_TARGET(qtsinglecoreapplication)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(qtsinglecoreapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(qtsinglecoreapplication
|
||||
PRIVATE
|
||||
qtsa_common
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
#include "qtlockedfile.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "qtsingleapplication.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "qtsinglecoreapplication.h"
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "qtlocalpeer.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QTime>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <QLibrary>
|
||||
#include <qt_windows.h>
|
||||
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
|
||||
static PProcessIdToSessionId pProcessIdToSessionId = 0;
|
||||
#endif
|
||||
#if defined(Q_OS_UNIX)
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace QtLP_Private {
|
||||
#include "qtlockedfile.cpp"
|
||||
#if defined(Q_OS_WIN)
|
||||
#include "qtlockedfile_win.cpp"
|
||||
#else
|
||||
#include "qtlockedfile_unix.cpp"
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* QtLocalPeer::ack = "ack";
|
||||
|
||||
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
|
||||
: QObject(parent), id(appId)
|
||||
{
|
||||
QString prefix = id;
|
||||
if (id.isEmpty()) {
|
||||
id = QCoreApplication::applicationFilePath();
|
||||
#if defined(Q_OS_WIN)
|
||||
id = id.toLower();
|
||||
#endif
|
||||
prefix = id.section(QLatin1Char('/'), -1);
|
||||
}
|
||||
prefix.remove(QRegExp(QLatin1String("[^a-zA-Z]")));
|
||||
prefix.truncate(6);
|
||||
|
||||
QByteArray idc = id.toUtf8();
|
||||
quint16 idNum = qChecksum(idc.constData(), idc.size());
|
||||
socketName = QLatin1String("qtsingleapp-") + prefix
|
||||
+ QLatin1Char('-') + QString::number(idNum, 16);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
if (!pProcessIdToSessionId) {
|
||||
QLibrary lib(QLatin1String("kernel32"));
|
||||
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
|
||||
}
|
||||
if (pProcessIdToSessionId) {
|
||||
DWORD sessionId = 0;
|
||||
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
|
||||
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
|
||||
}
|
||||
#else
|
||||
socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
|
||||
#endif
|
||||
|
||||
server = new QLocalServer(this);
|
||||
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
||||
+ QLatin1Char('/') + socketName
|
||||
+ QLatin1String("-lockfile");
|
||||
lockFile.setFileName(lockName);
|
||||
lockFile.open(QIODevice::ReadWrite);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool QtLocalPeer::isClient()
|
||||
{
|
||||
if (lockFile.isLocked())
|
||||
return false;
|
||||
|
||||
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
|
||||
return true;
|
||||
|
||||
bool res = server->listen(socketName);
|
||||
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
|
||||
|
||||
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
|
||||
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
|
||||
res = server->listen(socketName);
|
||||
}
|
||||
#endif
|
||||
if (!res)
|
||||
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
|
||||
QObject::connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
|
||||
{
|
||||
if (!isClient())
|
||||
return false;
|
||||
|
||||
QLocalSocket socket;
|
||||
bool connOk = false;
|
||||
for(int i = 0; i < 2; i++) {
|
||||
|
||||
socket.connectToServer(socketName);
|
||||
connOk = socket.waitForConnected(timeout/2);
|
||||
if (connOk || i)
|
||||
break;
|
||||
int ms = 250;
|
||||
#if defined(Q_OS_WIN)
|
||||
Sleep(DWORD(ms));
|
||||
#else
|
||||
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
|
||||
nanosleep(&ts, nullptr);
|
||||
#endif
|
||||
}
|
||||
if (!connOk)
|
||||
return false;
|
||||
|
||||
QByteArray uMsg(message.toUtf8());
|
||||
QDataStream ds(&socket);
|
||||
ds.writeBytes(uMsg.constData(), uMsg.size());
|
||||
bool res = socket.waitForBytesWritten(timeout);
|
||||
if (res) {
|
||||
res &= socket.waitForReadyRead(timeout);
|
||||
if (res)
|
||||
res &= (socket.read(qstrlen(ack)) == ack);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void QtLocalPeer::receiveConnection()
|
||||
{
|
||||
QLocalSocket* socket = server->nextPendingConnection();
|
||||
if (!socket)
|
||||
return;
|
||||
|
||||
while (socket->bytesAvailable() < (int)sizeof(quint32))
|
||||
socket->waitForReadyRead();
|
||||
QDataStream ds(socket);
|
||||
QByteArray uMsg;
|
||||
quint32 remaining;
|
||||
ds >> remaining;
|
||||
uMsg.resize(remaining);
|
||||
int got = 0;
|
||||
char* uMsgBuf = uMsg.data();
|
||||
do {
|
||||
got = ds.readRawData(uMsgBuf, remaining);
|
||||
remaining -= got;
|
||||
uMsgBuf += got;
|
||||
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
|
||||
if (got < 0) {
|
||||
qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
|
||||
delete socket;
|
||||
return;
|
||||
}
|
||||
QString message(QString::fromUtf8(uMsg));
|
||||
socket->write(ack, qstrlen(ack));
|
||||
socket->waitForBytesWritten(1000);
|
||||
socket->waitForDisconnected(1000);
|
||||
delete socket;
|
||||
emit messageReceived(message);
|
||||
}
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
#ifndef QTLOCALPEER_H
|
||||
#define QTLOCALPEER_H
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QDir>
|
||||
|
||||
#include "qtlockedfile.h"
|
||||
|
||||
class QtLocalPeer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtLocalPeer(QObject *parent = nullptr, const QString &appId = QString());
|
||||
bool isClient();
|
||||
bool sendMessage(const QString &message, int timeout);
|
||||
QString applicationId() const
|
||||
{ return id; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QString &message);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void receiveConnection();
|
||||
|
||||
protected:
|
||||
QString id;
|
||||
QString socketName;
|
||||
QLocalServer* server;
|
||||
QtLP_Private::QtLockedFile lockFile;
|
||||
|
||||
private:
|
||||
static const char* ack;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
|
||||
#include "qtlockedfile.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QtLockedFile::QtLockedFile()
|
||||
: QFile()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
wmutex = 0;
|
||||
rmutex = 0;
|
||||
#endif
|
||||
m_lock_mode = NoLock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QtLockedFile::QtLockedFile(const QString &name)
|
||||
: QFile(name)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
wmutex = 0;
|
||||
rmutex = 0;
|
||||
#endif
|
||||
m_lock_mode = NoLock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool QtLockedFile::open(OpenMode mode)
|
||||
{
|
||||
if (mode & QIODevice::Truncate) {
|
||||
qWarning("QtLockedFile::open(): Truncate mode not allowed.");
|
||||
return false;
|
||||
}
|
||||
return QFile::open(mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool QtLockedFile::isLocked() const
|
||||
{
|
||||
return m_lock_mode != NoLock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QtLockedFile::LockMode QtLockedFile::lockMode() const
|
||||
{
|
||||
return m_lock_mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
|
||||
|
||||
|
||||
#ifndef QTLOCKEDFILE_H
|
||||
#define QTLOCKEDFILE_H
|
||||
|
||||
#include <QFile>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
|
||||
# define QT_QTLOCKEDFILE_EXPORT
|
||||
# elif defined(QT_QTLOCKEDFILE_IMPORT)
|
||||
# if defined(QT_QTLOCKEDFILE_EXPORT)
|
||||
# undef QT_QTLOCKEDFILE_EXPORT
|
||||
# endif
|
||||
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
|
||||
# elif defined(QT_QTLOCKEDFILE_EXPORT)
|
||||
# undef QT_QTLOCKEDFILE_EXPORT
|
||||
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
|
||||
# endif
|
||||
#else
|
||||
# define QT_QTLOCKEDFILE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace QtLP_Private {
|
||||
|
||||
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum LockMode { NoLock = 0, ReadLock, WriteLock };
|
||||
|
||||
QtLockedFile();
|
||||
explicit QtLockedFile(const QString &name);
|
||||
~QtLockedFile();
|
||||
|
||||
bool open(OpenMode mode);
|
||||
|
||||
bool lock(LockMode mode, bool block = true);
|
||||
bool unlock();
|
||||
bool isLocked() const;
|
||||
LockMode lockMode() const;
|
||||
|
||||
private:
|
||||
#ifdef Q_OS_WIN
|
||||
Qt::HANDLE wmutex;
|
||||
Qt::HANDLE rmutex;
|
||||
QVector<Qt::HANDLE> rmutexes;
|
||||
QString mutexname;
|
||||
|
||||
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
|
||||
bool waitMutex(Qt::HANDLE mutex, bool doBlock);
|
||||
|
||||
#endif
|
||||
LockMode m_lock_mode;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "qtlockedfile.h"
|
||||
|
||||
bool QtLockedFile::lock(LockMode mode, bool block)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
qWarning("QtLockedFile::lock(): file is not opened");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == NoLock)
|
||||
return unlock();
|
||||
|
||||
if (mode == m_lock_mode)
|
||||
return true;
|
||||
|
||||
if (m_lock_mode != NoLock)
|
||||
unlock();
|
||||
|
||||
struct flock fl;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
|
||||
int cmd = block ? F_SETLKW : F_SETLK;
|
||||
int ret = fcntl(handle(), cmd, &fl);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_lock_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool QtLockedFile::unlock()
|
||||
{
|
||||
if (!isOpen()) {
|
||||
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isLocked())
|
||||
return true;
|
||||
|
||||
struct flock fl;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_type = F_UNLCK;
|
||||
int ret = fcntl(handle(), F_SETLKW, &fl);
|
||||
|
||||
if (ret == -1) {
|
||||
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lock_mode = NoLock;
|
||||
return true;
|
||||
}
|
||||
|
||||
QtLockedFile::~QtLockedFile()
|
||||
{
|
||||
if (isOpen())
|
||||
unlock();
|
||||
}
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
|
||||
|
||||
|
||||
#include "qtlockedfile.h"
|
||||
#include <qt_windows.h>
|
||||
#include <QFileInfo>
|
||||
|
||||
#define MUTEX_PREFIX "QtLockedFile mutex "
|
||||
|
||||
#define MAX_READERS MAXIMUM_WAIT_OBJECTS
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#define QT_WA(unicode, ansi) unicode
|
||||
#endif
|
||||
|
||||
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
||||
{
|
||||
if (mutexname.isEmpty()) {
|
||||
QFileInfo fi(*this);
|
||||
mutexname = QString::fromLatin1(MUTEX_PREFIX)
|
||||
+ fi.absoluteFilePath().toLower();
|
||||
}
|
||||
QString mname(mutexname);
|
||||
if (idx >= 0)
|
||||
mname += QString::number(idx);
|
||||
|
||||
Qt::HANDLE mutex;
|
||||
if (doCreate) {
|
||||
QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
|
||||
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
|
||||
if (!mutex) {
|
||||
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
|
||||
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
|
||||
if (!mutex) {
|
||||
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return mutex;
|
||||
}
|
||||
|
||||
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
|
||||
{
|
||||
Q_ASSERT(mutex);
|
||||
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
|
||||
switch (res) {
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED:
|
||||
return true;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
break;
|
||||
default:
|
||||
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool QtLockedFile::lock(LockMode mode, bool block)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
qWarning("QtLockedFile::lock(): file is not opened");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == NoLock)
|
||||
return unlock();
|
||||
|
||||
if (mode == m_lock_mode)
|
||||
return true;
|
||||
|
||||
if (m_lock_mode != NoLock)
|
||||
unlock();
|
||||
|
||||
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
|
||||
return false;
|
||||
|
||||
if (!waitMutex(wmutex, block))
|
||||
return false;
|
||||
|
||||
if (mode == ReadLock) {
|
||||
int idx = 0;
|
||||
for (; idx < MAX_READERS; idx++) {
|
||||
rmutex = getMutexHandle(idx, false);
|
||||
if (!rmutex || waitMutex(rmutex, false))
|
||||
break;
|
||||
CloseHandle(rmutex);
|
||||
}
|
||||
bool ok = true;
|
||||
if (idx >= MAX_READERS) {
|
||||
qWarning("QtLockedFile::lock(): too many readers");
|
||||
rmutex = 0;
|
||||
ok = false;
|
||||
}
|
||||
else if (!rmutex) {
|
||||
rmutex = getMutexHandle(idx, true);
|
||||
if (!rmutex || !waitMutex(rmutex, false))
|
||||
ok = false;
|
||||
}
|
||||
if (!ok && rmutex) {
|
||||
CloseHandle(rmutex);
|
||||
rmutex = 0;
|
||||
}
|
||||
ReleaseMutex(wmutex);
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
Q_ASSERT(rmutexes.isEmpty());
|
||||
for (int i = 0; i < MAX_READERS; i++) {
|
||||
Qt::HANDLE mutex = getMutexHandle(i, false);
|
||||
if (mutex)
|
||||
rmutexes.append(mutex);
|
||||
}
|
||||
if (rmutexes.size()) {
|
||||
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
|
||||
TRUE, block ? INFINITE : 0);
|
||||
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
|
||||
if (res != WAIT_TIMEOUT)
|
||||
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
|
||||
m_lock_mode = WriteLock;
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lock_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtLockedFile::unlock()
|
||||
{
|
||||
if (!isOpen()) {
|
||||
qWarning("QtLockedFile::unlock(): file is not opened");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isLocked())
|
||||
return true;
|
||||
|
||||
if (m_lock_mode == ReadLock) {
|
||||
ReleaseMutex(rmutex);
|
||||
CloseHandle(rmutex);
|
||||
rmutex = 0;
|
||||
}
|
||||
else {
|
||||
for (Qt::HANDLE mutex : qAsConst(rmutexes)) {
|
||||
ReleaseMutex(mutex);
|
||||
CloseHandle(mutex);
|
||||
}
|
||||
rmutexes.clear();
|
||||
ReleaseMutex(wmutex);
|
||||
}
|
||||
|
||||
m_lock_mode = QtLockedFile::NoLock;
|
||||
return true;
|
||||
}
|
||||
|
||||
QtLockedFile::~QtLockedFile()
|
||||
{
|
||||
if (isOpen())
|
||||
unlock();
|
||||
if (wmutex)
|
||||
CloseHandle(wmutex);
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "qtsingleapplication.h"
|
||||
#include "qtlocalpeer.h"
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void QtSingleApplication::sysInit(const QString &appId)
|
||||
{
|
||||
actWin = nullptr;
|
||||
peer = new QtLocalPeer(this, appId);
|
||||
connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
|
||||
: QApplication(argc, argv, GUIenabled)
|
||||
{
|
||||
sysInit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
|
||||
: QApplication(argc, argv)
|
||||
{
|
||||
sysInit(appId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool QtSingleApplication::isRunning()
|
||||
{
|
||||
return peer->isClient();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool QtSingleApplication::sendMessage(const QString &message, int timeout)
|
||||
{
|
||||
return peer->sendMessage(message, timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString QtSingleApplication::id() const
|
||||
{
|
||||
return peer->applicationId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
|
||||
{
|
||||
actWin = aw;
|
||||
if (activateOnMessage)
|
||||
connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow);
|
||||
else
|
||||
disconnect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QWidget* QtSingleApplication::activationWindow() const
|
||||
{
|
||||
return actWin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void QtSingleApplication::activateWindow()
|
||||
{
|
||||
if (actWin) {
|
||||
actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
|
||||
actWin->raise();
|
||||
actWin->activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
|
||||
#ifndef QTSINGLEAPPLICATION_H
|
||||
#define QTSINGLEAPPLICATION_H
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
class QtLocalPeer;
|
||||
|
||||
#ifndef QTSINGLEAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define QTSINGLEAPPLICATION_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_QTSINGLEAPPLICATION_LIB)
|
||||
# define QTSINGLEAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QTSINGLEAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
class QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
|
||||
QtSingleApplication(const QString &appId, int &argc, char **argv);
|
||||
|
||||
bool isRunning();
|
||||
QString id() const;
|
||||
|
||||
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
|
||||
QWidget* activationWindow() const;
|
||||
|
||||
|
||||
void initialize(bool dummy = true)
|
||||
{ isRunning(); Q_UNUSED(dummy) }
|
||||
|
||||
public Q_SLOTS:
|
||||
bool sendMessage(const QString &message, int timeout = 5000);
|
||||
void activateWindow();
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QString &message);
|
||||
|
||||
|
||||
private:
|
||||
void sysInit(const QString &appId = QString());
|
||||
QtLocalPeer *peer;
|
||||
QWidget *actWin;
|
||||
};
|
||||
|
||||
#endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "qtsinglecoreapplication.h"
|
||||
#include "qtlocalpeer.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
|
||||
: QCoreApplication(argc, argv)
|
||||
{
|
||||
peer = new QtLocalPeer(this);
|
||||
connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv)
|
||||
: QCoreApplication(argc, argv)
|
||||
{
|
||||
peer = new QtLocalPeer(this, appId);
|
||||
connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool QtSingleCoreApplication::isRunning()
|
||||
{
|
||||
return peer->isClient();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout)
|
||||
{
|
||||
return peer->sendMessage(message, timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QString QtSingleCoreApplication::id() const
|
||||
{
|
||||
return peer->applicationId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
|
||||
#ifndef QTSINGLECOREAPPLICATION_H
|
||||
#define QTSINGLECOREAPPLICATION_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
class QtLocalPeer;
|
||||
|
||||
#ifndef QTSINGLECOREAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define QTSINGLEAPPLICATION_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_QTSINGLECOREAPPLICATION_LIB)
|
||||
# define QTSINGLECOREAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QTSINGLECOREAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
class QTSINGLECOREAPPLICATION_EXPORT QtSingleCoreApplication : public QCoreApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtSingleCoreApplication(int &argc, char **argv);
|
||||
QtSingleCoreApplication(const QString &appId, int &argc, char **argv);
|
||||
|
||||
bool isRunning();
|
||||
QString id() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
bool sendMessage(const QString &message, int timeout = 5000);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QString &message);
|
||||
|
||||
|
||||
private:
|
||||
QtLocalPeer* peer;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
|
||||
SET(wms_ds_SRCS
|
||||
IECC2WMS.h
|
||||
IWMS2ECC.h
|
||||
wms_ecc_equipmenttypes.cpp
|
||||
wms_ecc_equipmenttypes.h
|
||||
wms_ecc_equipRequirements.cpp
|
||||
wms_ecc_equipRequirements.h
|
||||
wms_ecc_exercises.cpp
|
||||
wms_ecc_exercises.h
|
||||
wms_ecc_ibase.h
|
||||
wms_ecc_playerInfo.cpp
|
||||
wms_ecc_playerInfo.h
|
||||
wms_ecc_registration.cpp
|
||||
wms_ecc_registration.h
|
||||
wms_ecc_unregister.cpp
|
||||
wms_ecc_unregister.h
|
||||
json_keys.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(AAR SV wms_json_ds SHARED ${wms_ds_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(wms_json_ds
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(wms_json_ds
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace WmsJson
|
||||
{
|
||||
class IECC2WMS
|
||||
{
|
||||
|
||||
public:
|
||||
IECC2WMS() = default;
|
||||
virtual ~IECC2WMS() = default;
|
||||
|
||||
|
||||
virtual void playerChanged(int playerId, int exerciseId) = 0;
|
||||
virtual void exerciseDataChanged(int exerciseId, int betrZustand) = 0;
|
||||
|
||||
};
|
||||
}
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QMetaType>
|
||||
|
||||
class IWMS2ECC
|
||||
{
|
||||
|
||||
public:
|
||||
IWMS2ECC() = default;
|
||||
virtual ~IWMS2ECC() = default;
|
||||
|
||||
enum RegisterReturnValue
|
||||
{
|
||||
RegistrationOk = 0,
|
||||
PlayerNotFound = 1,
|
||||
PlayerDeleted = 2,
|
||||
AssignmentIncorrect = 3,
|
||||
EquipNoAlreadyAssigned = 4,
|
||||
RegistrationFailed = 5
|
||||
};
|
||||
|
||||
enum UnregisterReturnValue
|
||||
{
|
||||
UnregisterOk = 0,
|
||||
EquipNoNotFound = 1,
|
||||
UnregisterFailed = 2
|
||||
};
|
||||
|
||||
enum PlayerState
|
||||
{
|
||||
NOT_FOUND = 0,
|
||||
FOUND = 1,
|
||||
DELETED = 2
|
||||
};
|
||||
|
||||
enum PlayerAssignState
|
||||
{
|
||||
UNDEFINED = -2,
|
||||
NOT_ASSIGNED = -1,
|
||||
ASSIGNED = 0,
|
||||
HANDOUT_EXCON = 1,
|
||||
HANDOUT_WMS = 2,
|
||||
HANDOUT_EXCON_OVERRULED_WMS = 3
|
||||
};
|
||||
static inline PlayerAssignState int2PlayerAssignState(int s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case UNDEFINED:
|
||||
case NOT_ASSIGNED:
|
||||
case ASSIGNED:
|
||||
case HANDOUT_EXCON:
|
||||
case HANDOUT_WMS:
|
||||
case HANDOUT_EXCON_OVERRULED_WMS:
|
||||
return static_cast<PlayerAssignState>(s);
|
||||
}
|
||||
Q_ASSERT(false);
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
struct PlayerInfo
|
||||
{
|
||||
PlayerState playerState = NOT_FOUND;
|
||||
int playerId = -1;
|
||||
int parentPlayerId = -1;
|
||||
int equipNo = -1;
|
||||
PlayerAssignState assignState = UNDEFINED;
|
||||
int exerciseId = -1;
|
||||
int forceId = -1;
|
||||
int typeId = -1;
|
||||
int equipTypeId = -1;
|
||||
int typeClassId = -1;
|
||||
int symbolColor = -1;
|
||||
bool isDeleted = false;
|
||||
QByteArray symbolPNG;
|
||||
QString hierarchy;
|
||||
QString designator;
|
||||
QString tactIdent;
|
||||
QString info;
|
||||
QString alias;
|
||||
QString forceName;
|
||||
};
|
||||
|
||||
struct Exercise
|
||||
{
|
||||
int id = -1;
|
||||
int actExercise = 0;
|
||||
time_t start = 0;
|
||||
time_t end = 0;
|
||||
QString name;
|
||||
QString stateAsString;
|
||||
};
|
||||
using exerciseMap = QMap<int, Exercise>;
|
||||
|
||||
struct EquipmentType
|
||||
{
|
||||
QString name;
|
||||
int id = 0;
|
||||
int specialType = 0;
|
||||
int minEquipNo = 0;
|
||||
int maxEquipNo = 0;
|
||||
int taVulnerabilityModelId = 0;
|
||||
int taPlayerTypeId = 0;
|
||||
bool deletedInWMS = false;
|
||||
};
|
||||
using equipTypeMap = QMap<int, EquipmentType>;
|
||||
|
||||
|
||||
virtual RegisterReturnValue registerPlayer(int playerId, int equipNo, const PlayerAssignState &zuordnung, const QString &alias,
|
||||
const QString &info, int exerciseId) = 0;
|
||||
|
||||
virtual UnregisterReturnValue unregister(int equipNo, int exerciseId) = 0;
|
||||
virtual PlayerInfo getPlayerInfo(int playerId, int exerciseId) = 0;
|
||||
|
||||
virtual exerciseMap getExercises() const = 0;
|
||||
virtual Exercise getActualExercise() const = 0;
|
||||
|
||||
|
||||
virtual QMap<int, int> getEquipRequirements(int exerciseId) const = 0;
|
||||
|
||||
virtual QMap<int, PlayerInfo> getAllPlayers(int exerciseId) const = 0;
|
||||
virtual QMap<int, PlayerInfo> getAllVehicles(int exerciseId) const = 0;
|
||||
|
||||
virtual int getPlayerId(int equipNo, int exerciseId) const = 0;
|
||||
virtual int getEquipNo(int playerId, int exerciseId) const = 0;
|
||||
|
||||
virtual int getTypeClassId(int equipTypeId) const = 0;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(IWMS2ECC::Exercise)
|
||||
Q_DECLARE_METATYPE(IWMS2ECC::EquipmentType)
|
||||
Q_DECLARE_METATYPE(IWMS2ECC::RegisterReturnValue)
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
|
||||
|
||||
namespace JsonKeys
|
||||
{
|
||||
|
||||
inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); }
|
||||
inline QString DATA_MODIFICATION() { return QStringLiteral("dataModification"); }
|
||||
inline QString PARTICIPANT_ID() { return QStringLiteral("participantId"); }
|
||||
inline QString REGISTRATION_RETURN_VALUE() { return QStringLiteral("registrationReturnValue"); }
|
||||
|
||||
|
||||
inline QString EQUIPMENT_TYPES_REQUEST() { return QStringLiteral("equipmentTypesRequest"); }
|
||||
|
||||
|
||||
inline QString EQUIPMENT_TYPES_REPLY() { return QStringLiteral("equipmentTypesReply"); }
|
||||
|
||||
|
||||
inline QString EXERCISES_REQUEST() { return QStringLiteral("exercisesRequest"); }
|
||||
|
||||
|
||||
inline QString EXERCISES_REPLY() { return QStringLiteral("exercisesReply"); }
|
||||
|
||||
|
||||
inline QString EXERCISE_UPDATE() { return QStringLiteral("exercisesUpdate"); }
|
||||
|
||||
|
||||
inline QString PARTICIPANTS_REQUEST() { return QStringLiteral("participantsRequest"); }
|
||||
|
||||
|
||||
inline QString PARTICIPANTS_REPLY() { return QStringLiteral("participantsReply"); }
|
||||
|
||||
|
||||
inline QString PARTICIPANTS_UPDATE() { return QStringLiteral("participantsUpdate"); }
|
||||
|
||||
|
||||
inline QString PARTICIPANT_REGISTER_IN_EXCON_REQUEST() { return QStringLiteral("participantRegisterInEXCONRequest");}
|
||||
|
||||
|
||||
inline QString PARTICIPANT_REGISTER_IN_EXCON_REPLY() { return QStringLiteral("participantRegisterInEXCONReply");}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_equipRequirements.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
QJsonObject EquipRequirements::toJson() const
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (QMap<int, int>::ConstIterator it = m_equipRequire.begin(); it != m_equipRequire.end(); ++it)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QLatin1String("key")] = it.key();
|
||||
obj[QLatin1String("value")] = it.value();
|
||||
arr.append(obj);
|
||||
}
|
||||
|
||||
QJsonObject retMap;
|
||||
retMap[QLatin1String("equipMap")] = arr;
|
||||
retMap[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
EquipRequirements EquipRequirements::fromJson(const QJsonObject &map)
|
||||
{
|
||||
EquipRequirements eq;
|
||||
|
||||
const QJsonArray arr = map[QLatin1String("equipMap")].toArray();
|
||||
for (const auto &ele : arr)
|
||||
{
|
||||
const QJsonObject obj = ele.toObject();
|
||||
int equipmentTypeId = obj[QLatin1String("key")].toInt();
|
||||
int amount = obj[QLatin1String("value")].toInt();
|
||||
eq.m_equipRequire.insert(equipmentTypeId, amount);
|
||||
}
|
||||
|
||||
eq.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
QVariantMap EquipRequirements::toVariantMap() const
|
||||
{
|
||||
QVariantMap viMap;
|
||||
for (QMap<int, int>::ConstIterator it = m_equipRequire.begin(); it != m_equipRequire.end(); ++it)
|
||||
viMap.insert(QString::number(it.key()), QVariant(it.value()));
|
||||
|
||||
QVariantMap retMap;
|
||||
retMap[QLatin1String("equipMap")] = QVariant(viMap);
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
EquipRequirements EquipRequirements::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
EquipRequirements eq;
|
||||
|
||||
const QVariantMap viMap = map[QLatin1String("equipMap")].toMap();
|
||||
for (QVariantMap::ConstIterator it = viMap.begin(); it != viMap.end(); ++it)
|
||||
{
|
||||
const int key = it.key().toInt();
|
||||
eq.m_equipRequire.insert(key, it.value().toInt());
|
||||
}
|
||||
|
||||
eq.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return eq;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
#include "IWMS2ECC.h"
|
||||
|
||||
#include <QtCore/QVariantMap>
|
||||
|
||||
class WMS_JSON_DS_EXPORT EquipRequirements : public IBase
|
||||
{
|
||||
public:
|
||||
QJsonObject toJson() const;
|
||||
static EquipRequirements fromJson(const QJsonObject &map);
|
||||
|
||||
QVariantMap toVariantMap() const;
|
||||
static EquipRequirements fromVariantMap(const QVariantMap &map);
|
||||
|
||||
|
||||
QMap<int, int> getEquipRequirements() const { return m_equipRequire; }
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setEquipRequirements(const QMap<int, int> &equip) { m_equipRequire = equip; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
QMap<int, int> m_equipRequire;
|
||||
bool m_ok = false;
|
||||
};
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_equipmenttypes.h"
|
||||
#include <QJsonArray>
|
||||
|
||||
QJsonObject EquipmentTypes::toJson(const IWMS2ECC::EquipmentType &et)
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
obj[QLatin1String("id")] = et.id;
|
||||
obj[QLatin1String("name")] = et.name;
|
||||
obj[QLatin1String("minEquipNo")] = et.minEquipNo;
|
||||
obj[QLatin1String("maxEquipNo")] = et.maxEquipNo;
|
||||
obj[QLatin1String("specialType")] = et.specialType;
|
||||
obj[QLatin1String("taVulnerabilityModelId")] = et.taVulnerabilityModelId;
|
||||
obj[QLatin1String("taPlayerTypeId")] = et.taPlayerTypeId;
|
||||
obj[QLatin1String("deletedInWMS")] = et.deletedInWMS;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
IWMS2ECC::EquipmentType EquipmentTypes::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
IWMS2ECC::EquipmentType et;
|
||||
|
||||
et.id = obj[QLatin1String("id")].toInt();
|
||||
et.name = obj[QLatin1String("name")].toString();
|
||||
et.minEquipNo = obj[QLatin1String("minEquipNo")].toInt();
|
||||
et.maxEquipNo = obj[QLatin1String("maxEquipNo")].toInt();
|
||||
et.specialType = obj[QLatin1String("specialType")].toInt();
|
||||
et.taVulnerabilityModelId = obj[QLatin1String("taVulnerabilityModelId")].toInt();
|
||||
et.taPlayerTypeId = obj[QLatin1String("taPlayerTypeId")].toInt();
|
||||
et.deletedInWMS = obj[QLatin1String("deletedInWMS")].toBool();
|
||||
|
||||
return et;
|
||||
}
|
||||
|
||||
QJsonObject EquipmentTypes::toJsonAll() const
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const IWMS2ECC::EquipmentType &et : m_equipmentTypes)
|
||||
arr.append(toJson(et));
|
||||
|
||||
QJsonObject retMap;
|
||||
retMap[QLatin1String("etMap")] = arr;
|
||||
retMap[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
EquipmentTypes EquipmentTypes::fromJsonAll(const QJsonObject &map)
|
||||
{
|
||||
EquipmentTypes ets;
|
||||
|
||||
const QJsonArray arr = map[QLatin1String("etMap")].toArray();
|
||||
for (const auto &ele : arr)
|
||||
{
|
||||
const IWMS2ECC::EquipmentType val = fromJson(ele.toObject());
|
||||
ets.m_equipmentTypes.insert(val.id, val);
|
||||
}
|
||||
|
||||
ets.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ets;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap EquipmentTypes::toVariantMap() const
|
||||
{
|
||||
QVariantMap vMap;
|
||||
|
||||
vMap[QLatin1String("id")] = QVariant(m_equipmentType.id);
|
||||
vMap[QLatin1String("name")] = m_equipmentType.name;
|
||||
vMap[QLatin1String("minEquipNo")] = QVariant((int)m_equipmentType.minEquipNo);
|
||||
vMap[QLatin1String("maxEquipNo")] = QVariant((int)m_equipmentType.maxEquipNo);
|
||||
vMap[QLatin1String("specialType")] = QVariant(m_equipmentType.specialType);
|
||||
vMap[QLatin1String("deletedInWMS")] = QVariant(m_equipmentType.deletedInWMS);
|
||||
|
||||
vMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return vMap;
|
||||
}
|
||||
|
||||
EquipmentTypes EquipmentTypes::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
EquipmentTypes ets;
|
||||
|
||||
ets.m_equipmentType.id = map[QLatin1String("id")].toInt();
|
||||
ets.m_equipmentType.name = map[QLatin1String("name")].toString();
|
||||
ets.m_equipmentType.minEquipNo = map[QLatin1String("minEquipNo")].toInt();
|
||||
ets.m_equipmentType.maxEquipNo = map[QLatin1String("maxEquipNo")].toInt();
|
||||
ets.m_equipmentType.specialType = map[QLatin1String("specialType")].toInt();
|
||||
ets.m_equipmentType.deletedInWMS = map[QLatin1String("deletedInWMS")].toBool();
|
||||
|
||||
ets.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ets;
|
||||
}
|
||||
|
||||
QVariantMap EquipmentTypes::toVariantMapAll() const
|
||||
{
|
||||
QVariantMap vMap;
|
||||
for (IWMS2ECC::equipTypeMap::ConstIterator it = m_equipmentTypes.begin(); it != m_equipmentTypes.end(); ++it)
|
||||
{
|
||||
m_equipmentType = it.value();
|
||||
vMap.insert(QString::number(it.key()), QVariant(toVariantMap()));
|
||||
}
|
||||
|
||||
QVariantMap retMap;
|
||||
retMap[QLatin1String("etMap")] = QVariant(vMap);
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
EquipmentTypes EquipmentTypes::fromVariantMapAll(const QVariantMap &map)
|
||||
{
|
||||
EquipmentTypes ets;
|
||||
|
||||
const QVariantMap vMap = map[QLatin1String("etMap")].toMap();
|
||||
for (QVariantMap::ConstIterator it = vMap.begin(); it != vMap.end(); ++it)
|
||||
{
|
||||
int key = it.key().toInt();
|
||||
IWMS2ECC::EquipmentType et = EquipmentTypes::fromVariantMap(it.value().toMap()).m_equipmentType;
|
||||
ets.m_equipmentTypes.insert(key, et);
|
||||
}
|
||||
|
||||
ets.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ets;
|
||||
}
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
#include "IWMS2ECC.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class WMS_JSON_DS_EXPORT EquipmentTypes : public IBase
|
||||
{
|
||||
public:
|
||||
QJsonObject toJsonAll() const;
|
||||
static EquipmentTypes fromJsonAll(const QJsonObject &map);
|
||||
static QJsonObject toJson(const IWMS2ECC::EquipmentType &et);
|
||||
static IWMS2ECC::EquipmentType fromJson(const QJsonObject &obj);
|
||||
|
||||
QVariantMap toVariantMapAll() const;
|
||||
static EquipmentTypes fromVariantMapAll(const QVariantMap &map);
|
||||
QVariantMap toVariantMap() const;
|
||||
static EquipmentTypes fromVariantMap(const QVariantMap &map);
|
||||
|
||||
IWMS2ECC::EquipmentType getEquipmentType() const { return m_equipmentType; }
|
||||
IWMS2ECC::equipTypeMap getEquipmentTypes() const { return m_equipmentTypes; }
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setEquipmentType(const IWMS2ECC::EquipmentType &et) { m_equipmentType = et; }
|
||||
void setEquipmentTypes(const IWMS2ECC::equipTypeMap &map) { m_equipmentTypes = map; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
IWMS2ECC::equipTypeMap m_equipmentTypes;
|
||||
mutable IWMS2ECC::EquipmentType m_equipmentType;
|
||||
bool m_ok = false;
|
||||
};
|
||||
Executable
+135
@@ -0,0 +1,135 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_exercises.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace EXCON
|
||||
{
|
||||
|
||||
QJsonObject Exercises::toJson(const IWMS2ECC::Exercise &ex) const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
obj[QLatin1String("id")] = ex.id;
|
||||
obj[QLatin1String("actExercise")] = ex.actExercise;
|
||||
obj[QLatin1String("start")] = static_cast<qint64>(ex.start);
|
||||
obj[QLatin1String("end")] = static_cast<qint64>(ex.end);
|
||||
obj[QLatin1String("name")] = ex.name;
|
||||
obj[QLatin1String("state")] = ex.stateAsString;
|
||||
|
||||
obj[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
IWMS2ECC::Exercise Exercises::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
IWMS2ECC::Exercise ex;
|
||||
|
||||
ex.id = obj[QLatin1String("id")].toInt();
|
||||
ex.actExercise = obj[QLatin1String("actExercise")].toInt();
|
||||
ex.start = static_cast<time_t>(obj[QLatin1String("start")].toInt());
|
||||
ex.end = static_cast<time_t>(obj[QLatin1String("end")].toInt());
|
||||
ex.name = obj[QLatin1String("name")].toString();
|
||||
ex.stateAsString = obj[QLatin1String("state")].toString();
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
QJsonObject Exercises::toJsonAll() const
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const IWMS2ECC::Exercise &ex : m_exercises)
|
||||
arr.append(toJson(ex));
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QLatin1String("exMap")] = arr;
|
||||
obj[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Exercises Exercises::fromJsonAll(const QJsonObject &map)
|
||||
{
|
||||
Exercises ex;
|
||||
|
||||
const QJsonArray arr = map[QLatin1String("exMap")].toArray();
|
||||
for (const QJsonValue &val : arr)
|
||||
{
|
||||
const IWMS2ECC::Exercise exinfo = fromJson(val.toObject());
|
||||
ex.m_exercises.insert(exinfo.id, exinfo);
|
||||
}
|
||||
|
||||
ex.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap Exercises::toVariantMap() const
|
||||
{
|
||||
QVariantMap vMap;
|
||||
|
||||
vMap[QLatin1String("id")] = QVariant(m_exercise.id);
|
||||
vMap[QLatin1String("name")] = m_exercise.name;
|
||||
vMap[QLatin1String("start")] = QVariant(static_cast<qint64>(m_exercise.start));
|
||||
vMap[QLatin1String("end")] = QVariant(static_cast<qint64>(m_exercise.end));
|
||||
vMap[QLatin1String("state")] = m_exercise.stateAsString;
|
||||
|
||||
vMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return vMap;
|
||||
}
|
||||
|
||||
Exercises Exercises::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
Exercises ex;
|
||||
|
||||
ex.m_exercise.id = map[QLatin1String("id")].toInt();
|
||||
ex.m_exercise.name = map[QLatin1String("name")].toString();
|
||||
ex.m_exercise.start = map[QLatin1String("start")].toLongLong();
|
||||
ex.m_exercise.end = map[QLatin1String("end")].toLongLong();
|
||||
ex.m_exercise.stateAsString = map[QLatin1String("state")].toString();
|
||||
|
||||
ex.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
QVariantMap Exercises::toVariantMapAll() const
|
||||
{
|
||||
QVariantMap vMap;
|
||||
for (IWMS2ECC::exerciseMap::ConstIterator it = m_exercises.begin(); it != m_exercises.end(); ++it)
|
||||
{
|
||||
m_exercise = it.value();
|
||||
vMap.insert(QString::number(it.key()), QVariant(toVariantMap()));
|
||||
}
|
||||
|
||||
QVariantMap retMap;
|
||||
retMap[QLatin1String("exeMap")] = QVariant(vMap);
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
Exercises Exercises::fromVariantMapAll(const QVariantMap &map)
|
||||
{
|
||||
Exercises ex;
|
||||
|
||||
const QVariantMap vMap = map[QLatin1String("exeMap")].toMap();
|
||||
for (QVariantMap::ConstIterator it = vMap.begin(); it != vMap.end(); ++it)
|
||||
{
|
||||
|
||||
int key = it.key().toInt();
|
||||
IWMS2ECC::Exercise e = Exercises::fromVariantMap(it.value().toMap()).m_exercise;
|
||||
ex.m_exercises.insert(key, e);
|
||||
}
|
||||
|
||||
ex.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
#include "IWMS2ECC.h"
|
||||
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace EXCON
|
||||
{
|
||||
|
||||
class WMS_JSON_DS_EXPORT Exercises : public IBase
|
||||
{
|
||||
public:
|
||||
QJsonObject toJsonAll() const;
|
||||
static Exercises fromJsonAll(const QJsonObject &map);
|
||||
QJsonObject toJson(const IWMS2ECC::Exercise &ex) const;
|
||||
static IWMS2ECC::Exercise fromJson(const QJsonObject &obj);
|
||||
|
||||
QVariantMap toVariantMapAll() const;
|
||||
static Exercises fromVariantMapAll(const QVariantMap &map);
|
||||
QVariantMap toVariantMap() const;
|
||||
static Exercises fromVariantMap(const QVariantMap &map);
|
||||
|
||||
IWMS2ECC::Exercise getExercise() const { return m_exercise; }
|
||||
IWMS2ECC::exerciseMap getExercises() const { return m_exercises; }
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setExercise(const IWMS2ECC::Exercise &exe) { m_exercise = exe; }
|
||||
void setExercises(const IWMS2ECC::exerciseMap &exe) { m_exercises = exe; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
IWMS2ECC::exerciseMap m_exercises;
|
||||
mutable IWMS2ECC::Exercise m_exercise;
|
||||
bool m_ok = false;
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WMS_Interface/wms_json_ds_export.h>
|
||||
|
||||
class WMS_JSON_DS_EXPORT IBase
|
||||
{
|
||||
public:
|
||||
IBase() = default;
|
||||
virtual ~IBase() = default;
|
||||
|
||||
};
|
||||
|
||||
Executable
+176
@@ -0,0 +1,176 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_playerInfo.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
QJsonObject PlayerInfo::toJson(const IWMS2ECC::PlayerInfo &pi)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QLatin1String("playerState")] = pi.playerState;
|
||||
obj[QLatin1String("playerId")] = pi.playerId;
|
||||
obj[QLatin1String("parentPlayerId")] = pi.parentPlayerId;
|
||||
obj[QLatin1String("equipNo")] = pi.equipNo;
|
||||
obj[QLatin1String("assignState")] = pi.assignState;
|
||||
obj[QLatin1String("exerciseId")] = pi.exerciseId;
|
||||
obj[QLatin1String("forceId")] = pi.forceId;
|
||||
obj[QLatin1String("typeId")] = pi.typeId;
|
||||
obj[QLatin1String("isDeleted")] = pi.isDeleted;
|
||||
obj[QLatin1String("equipTypeId")] = pi.equipTypeId;
|
||||
obj[QLatin1String("typeClassId")] = pi.typeClassId;
|
||||
obj[QLatin1String("symbolColor")] = pi.symbolColor;
|
||||
obj[QLatin1String("symbolPNG")] = QString::fromLatin1(pi.symbolPNG.toBase64());
|
||||
obj[QLatin1String("hierarchy")] = pi.hierarchy;
|
||||
obj[QLatin1String("designator")] = pi.designator;
|
||||
obj[QLatin1String("tactIdent")] = pi.tactIdent;
|
||||
obj[QLatin1String("info")] = pi.info;
|
||||
obj[QLatin1String("alias")] = pi.alias;
|
||||
obj[QLatin1String("forceName")] = pi.forceName;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
IWMS2ECC::PlayerInfo PlayerInfo::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
IWMS2ECC::PlayerInfo pi;
|
||||
|
||||
pi.playerState = static_cast<IWMS2ECC::PlayerState>(obj[QLatin1String("playerState")].toInt());
|
||||
pi.playerId = obj[QLatin1String("playerId")].toInt();
|
||||
pi.parentPlayerId = obj[QLatin1String("parentPlayerId")].toInt();
|
||||
pi.equipNo = obj[QLatin1String("equipNo")].toInt();
|
||||
pi.assignState = static_cast<IWMS2ECC::PlayerAssignState>(obj[QLatin1String("assignState")].toInt());
|
||||
pi.exerciseId = obj[QLatin1String("exerciseId")].toInt();
|
||||
pi.forceId = obj[QLatin1String("forceId")].toInt();
|
||||
pi.typeId = obj[QLatin1String("typeId")].toInt();
|
||||
pi.isDeleted = obj[QLatin1String("isDeleted")].toBool();
|
||||
pi.equipTypeId = obj[QLatin1String("equipTypeId")].toInt();
|
||||
pi.typeClassId = obj[QLatin1String("typeClassId")].toInt();
|
||||
pi.symbolColor = obj[QLatin1String("symbolColor")].toInt();
|
||||
pi.symbolPNG = QByteArray::fromBase64(obj[QLatin1String("symbolPNG")].toString().toLatin1());
|
||||
pi.hierarchy = obj[QLatin1String("hierarchy")].toString();
|
||||
pi.designator = obj[QLatin1String("designator")].toString();
|
||||
pi.tactIdent = obj[QLatin1String("tactIdent")].toString();
|
||||
pi.info = obj[QLatin1String("info")].toString();
|
||||
pi.alias = obj[QLatin1String("alias")].toString();
|
||||
pi.forceName = obj[QLatin1String("forceName")].toString();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
QJsonObject PlayerInfo::toJsonAll() const
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const IWMS2ECC::PlayerInfo &pi : m_allPlayerInfo)
|
||||
arr.append(toJson(pi));
|
||||
|
||||
QJsonObject retMap;
|
||||
retMap[QLatin1String("piMap")] = arr;
|
||||
retMap[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
PlayerInfo PlayerInfo::fromJsonAll(const QJsonObject &map)
|
||||
{
|
||||
PlayerInfo pi;
|
||||
|
||||
const QJsonArray arr = map[QLatin1String("piMap")].toArray();
|
||||
for (const QJsonValue &val : arr)
|
||||
{
|
||||
const IWMS2ECC::PlayerInfo player = fromJson(val.toObject());
|
||||
|
||||
pi.m_allPlayerInfo.insert(player.playerId, player);
|
||||
}
|
||||
|
||||
pi.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
QVariantMap PlayerInfo::toVariantMap() const
|
||||
{
|
||||
QVariantMap retMap;
|
||||
retMap[QLatin1String("playerId")] = QVariant(m_playerInfo.playerId);
|
||||
retMap[QLatin1String("parentPlayerId")] = QVariant(m_playerInfo.parentPlayerId);
|
||||
retMap[QLatin1String("equipNo")] = QVariant(m_playerInfo.equipNo);
|
||||
retMap[QLatin1String("equipTypeId")] = QVariant(m_playerInfo.equipTypeId);
|
||||
retMap[QLatin1String("typeClassId")] = QVariant(m_playerInfo.typeClassId);
|
||||
retMap[QLatin1String("forceId")] = QVariant(m_playerInfo.forceId);
|
||||
retMap[QLatin1String("designator")] = m_playerInfo.designator;
|
||||
retMap[QLatin1String("tactIdent")] = m_playerInfo.tactIdent;
|
||||
retMap[QLatin1String("hierarchy")] = m_playerInfo.hierarchy;
|
||||
retMap[QLatin1String("forceName")] = m_playerInfo.forceName;
|
||||
retMap[QLatin1String("info")] = m_playerInfo.info;
|
||||
retMap[QLatin1String("alias")] = m_playerInfo.alias;
|
||||
retMap[QLatin1String("symbolPNG")] = QVariant(m_playerInfo.symbolPNG);
|
||||
retMap[QLatin1String("symbolColor")] = QVariant(m_playerInfo.symbolColor);
|
||||
|
||||
retMap[QLatin1String("assignState")] = QVariant(m_playerInfo.assignState);
|
||||
retMap[QLatin1String("playerState")] = QVariant(m_playerInfo.playerState);
|
||||
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
PlayerInfo PlayerInfo::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
PlayerInfo pi;
|
||||
|
||||
pi.m_playerInfo.playerId = map[QLatin1String("playerId")].toInt();
|
||||
pi.m_playerInfo.parentPlayerId = map[QLatin1String("parentPlayerId")].toInt();
|
||||
pi.m_playerInfo.equipNo = map[QLatin1String("equipNo")].toInt();
|
||||
pi.m_playerInfo.forceId = map[QLatin1String("forceId")].toInt();
|
||||
pi.m_playerInfo.equipTypeId = map[QLatin1String("equipTypeId")].toInt();
|
||||
pi.m_playerInfo.typeClassId = map[QLatin1String("typeClassId")].toInt();
|
||||
pi.m_playerInfo.designator = map[QLatin1String("designator")].toString();
|
||||
pi.m_playerInfo.tactIdent = map[QLatin1String("tactIdent")].toString();
|
||||
pi.m_playerInfo.hierarchy = map[QLatin1String("hierarchy")].toString();
|
||||
pi.m_playerInfo.forceName = map[QLatin1String("forceName")].toString();
|
||||
pi.m_playerInfo.info = map[QLatin1String("info")].toString();
|
||||
pi.m_playerInfo.alias = map[QLatin1String("alias")].toString();
|
||||
pi.m_playerInfo.symbolPNG = map[QLatin1String("symbolPNG")].toByteArray();
|
||||
pi.m_playerInfo.symbolColor = map[QLatin1String("symbolColor")].toInt();
|
||||
pi.m_playerInfo.assignState = (IWMS2ECC::PlayerAssignState) map[QLatin1String("assignState")].toInt();
|
||||
pi.m_playerInfo.playerState = (IWMS2ECC::PlayerState) map[QLatin1String("playerState")].toInt();
|
||||
|
||||
pi.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
QVariantMap PlayerInfo::toVariantMapAll() const
|
||||
{
|
||||
QVariantMap vMap;
|
||||
for (const IWMS2ECC::PlayerInfo &pi : m_allPlayerInfo)
|
||||
{
|
||||
m_playerInfo = pi;
|
||||
vMap.insert(QString::number(pi.playerId), QVariant(toVariantMap()));
|
||||
}
|
||||
|
||||
QVariantMap retMap;
|
||||
retMap[QLatin1String("plMap")] = QVariant(vMap);
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
PlayerInfo PlayerInfo::fromVariantMapAll(const QVariantMap &map)
|
||||
{
|
||||
PlayerInfo players;
|
||||
|
||||
const QVariantMap vMap = map[QLatin1String("plMap")].toMap();
|
||||
for (const QVariant &data : vMap)
|
||||
{
|
||||
PlayerInfo player = PlayerInfo::fromVariantMap(data.toMap());
|
||||
IWMS2ECC::PlayerInfo pi = player.getPlayerInfo();
|
||||
players.m_allPlayerInfo.insert(pi.playerId, pi);
|
||||
}
|
||||
|
||||
players.m_ok = vMap[QLatin1String("ok")].toBool();
|
||||
return players;
|
||||
}
|
||||
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
#include "IWMS2ECC.h"
|
||||
|
||||
#include <QtCore/QVariantMap>
|
||||
|
||||
|
||||
class WMS_JSON_DS_EXPORT PlayerInfo : public IBase
|
||||
{
|
||||
public:
|
||||
static QJsonObject toJson(const IWMS2ECC::PlayerInfo &pi);
|
||||
static IWMS2ECC::PlayerInfo fromJson(const QJsonObject &obj);
|
||||
|
||||
QJsonObject toJsonAll() const;
|
||||
static PlayerInfo fromJsonAll(const QJsonObject &map);
|
||||
|
||||
QVariantMap toVariantMap() const;
|
||||
static PlayerInfo fromVariantMap(const QVariantMap &map);
|
||||
|
||||
QVariantMap toVariantMapAll() const;
|
||||
static PlayerInfo fromVariantMapAll(const QVariantMap &map);
|
||||
|
||||
IWMS2ECC::PlayerInfo getPlayerInfo() const { return m_playerInfo; }
|
||||
QMap<int, IWMS2ECC::PlayerInfo> getAllPlayerInfo() const { return m_allPlayerInfo; }
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setPlayerInfo(const IWMS2ECC::PlayerInfo &info) { m_playerInfo = info; }
|
||||
void setAllPlayerInfo(const QMap<int, IWMS2ECC::PlayerInfo> &pi) { m_allPlayerInfo = pi; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
QMap<int, IWMS2ECC::PlayerInfo> m_allPlayerInfo;
|
||||
mutable IWMS2ECC::PlayerInfo m_playerInfo;
|
||||
bool m_ok = false;
|
||||
};
|
||||
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_registration.h"
|
||||
#include <QJsonObject>
|
||||
|
||||
QJsonObject Registration::toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
obj[QLatin1String("playerId")] = m_playerId;
|
||||
obj[QLatin1String("assignment")] = m_assignment;
|
||||
obj[QLatin1String("exerciseId")] = m_exerciseId;
|
||||
obj[QLatin1String("ok")] = m_ok;
|
||||
|
||||
if (m_bEquipNoIsSet)
|
||||
obj[QLatin1String("equipNo")] = m_equipNo;
|
||||
if (m_bAliasIsSet)
|
||||
obj[QLatin1String("alias")] = m_alias;
|
||||
if (m_bInfoIsSet)
|
||||
obj[QLatin1String("info")] = m_info;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Registration Registration::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
Registration rg;
|
||||
|
||||
rg.m_playerId = obj[QLatin1String("playerId")].toInt();
|
||||
rg.m_assignment = IWMS2ECC::int2PlayerAssignState(obj[QLatin1String("assignment")].toInt());
|
||||
rg.m_exerciseId = obj[QLatin1String("exerciseId")].toInt();
|
||||
|
||||
rg.m_bEquipNoIsSet = obj.contains(QLatin1String("equipNo"));
|
||||
if (rg.m_bEquipNoIsSet)
|
||||
rg.m_equipNo = obj[QLatin1String("equipNo")].toInt();
|
||||
rg.m_bAliasIsSet = obj.contains(QLatin1String("alias"));
|
||||
if (rg.m_bAliasIsSet)
|
||||
rg.m_alias = obj[QLatin1String("alias")].toString();
|
||||
rg.m_bInfoIsSet = obj.contains(QLatin1String("info"));
|
||||
if (rg.m_bInfoIsSet)
|
||||
rg.m_info = obj[QLatin1String("info")].toString();
|
||||
rg.m_ok = obj[QLatin1String("ok")].toBool();
|
||||
|
||||
return rg;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap Registration::toVariantMap() const
|
||||
{
|
||||
QVariantMap retMap;
|
||||
|
||||
retMap[QLatin1String("playerId")] = QVariant(m_playerId);
|
||||
retMap[QLatin1String("assignment")] = QVariant(m_assignment);
|
||||
retMap[QLatin1String("exerciseId")] = QVariant(m_exerciseId);
|
||||
|
||||
if (m_bEquipNoIsSet)
|
||||
retMap[QLatin1String("equipNo")] = QVariant(m_equipNo);
|
||||
if (m_bAliasIsSet)
|
||||
retMap[QLatin1String("alias")] = m_alias;
|
||||
if (m_bInfoIsSet)
|
||||
retMap[QLatin1String("info")] = m_info;
|
||||
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
Registration Registration::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
Registration rg;
|
||||
|
||||
rg.m_playerId = map[QLatin1String("playerId")].toInt();
|
||||
rg.m_assignment = IWMS2ECC::int2PlayerAssignState(map[QLatin1String("assignment")].toInt());
|
||||
rg.m_exerciseId = map[QLatin1String("exerciseId")].toInt();
|
||||
rg.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
rg.m_bEquipNoIsSet = map.contains(QLatin1String("equipNo"));
|
||||
if (rg.m_bEquipNoIsSet)
|
||||
rg.m_equipNo = map[QLatin1String("equipNo")].toInt();
|
||||
rg.m_bAliasIsSet = map.contains(QLatin1String("alias"));
|
||||
if (rg.m_bAliasIsSet)
|
||||
rg.m_alias = map[QLatin1String("alias")].toString();
|
||||
rg.m_bInfoIsSet = map.contains(QLatin1String("info"));
|
||||
if (rg.m_bInfoIsSet)
|
||||
rg.m_info = map[QLatin1String("info")].toString();
|
||||
|
||||
return rg;
|
||||
}
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
#include "IWMS2ECC.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariantMap>
|
||||
|
||||
|
||||
class WMS_JSON_DS_EXPORT Registration : public IBase
|
||||
{
|
||||
public:
|
||||
QJsonObject toJson() const;
|
||||
static Registration fromJson(const QJsonObject &obj);
|
||||
|
||||
QVariantMap toVariantMap() const;
|
||||
static Registration fromVariantMap(const QVariantMap &map);
|
||||
|
||||
int getPlayerId() const { return m_playerId; }
|
||||
int getEquipNo() const { return m_equipNo; }
|
||||
int getExerciseId() const { return m_exerciseId; }
|
||||
QString getAlias() const { return m_alias; }
|
||||
QString getInfo() const { return m_info; }
|
||||
bool isEquipNoSet() const { return m_bEquipNoIsSet; }
|
||||
bool isAliasSet() const { return m_bAliasIsSet; }
|
||||
bool isInfoSet() const { return m_bInfoIsSet; }
|
||||
|
||||
IWMS2ECC::PlayerAssignState getAssignment() const { return m_assignment; }
|
||||
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setPlayerId(int playerId) { m_playerId = playerId; }
|
||||
void setEquipNo(int equipNo) { m_equipNo = equipNo; m_bEquipNoIsSet = true; }
|
||||
void setAssignment(IWMS2ECC::PlayerAssignState assignment) { m_assignment = assignment; }
|
||||
void setExerciseId(int exerciseId) { m_exerciseId = exerciseId; }
|
||||
void setAlias(const QString &alias) { m_alias = alias; m_bAliasIsSet = true; }
|
||||
void setInfo(const QString &info) { m_info = info; m_bInfoIsSet = true; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
QString m_alias;
|
||||
QString m_info;
|
||||
IWMS2ECC::PlayerAssignState m_assignment = IWMS2ECC::UNDEFINED;
|
||||
int m_playerId = 0;
|
||||
int m_equipNo = 0;
|
||||
int m_exerciseId = -1;
|
||||
bool m_bEquipNoIsSet = false;
|
||||
bool m_bAliasIsSet = false;
|
||||
bool m_bInfoIsSet = false;
|
||||
bool m_ok = false;
|
||||
};
|
||||
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
|
||||
#include "wms_ecc_unregister.h"
|
||||
#include <QJsonObject>
|
||||
|
||||
QJsonObject Unregister::toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
obj[QLatin1String("equipNo")] = m_equipNo;
|
||||
obj[QLatin1String("exerciseId")] = m_exerciseId;
|
||||
obj[QLatin1String("ok")] = m_ok;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Unregister Unregister::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
Unregister ur;
|
||||
|
||||
ur.m_equipNo = obj[QLatin1String("equipNo")].toInt();
|
||||
ur.m_exerciseId = obj[QLatin1String("exerciseId")].toInt();
|
||||
ur.m_ok = obj[QLatin1String("ok")].toBool();
|
||||
|
||||
return ur;
|
||||
}
|
||||
|
||||
QVariantMap Unregister::toVariantMap() const
|
||||
{
|
||||
QVariantMap retMap;
|
||||
|
||||
retMap[QLatin1String("equipNo")] = QVariant(m_equipNo);
|
||||
retMap[QLatin1String("exerciseId")] = QVariant(m_exerciseId);
|
||||
retMap[QLatin1String("ok")] = QVariant(m_ok);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
Unregister Unregister::fromVariantMap(const QVariantMap &map)
|
||||
{
|
||||
Unregister ur;
|
||||
|
||||
ur.m_equipNo = map[QLatin1String("equipNo")].toInt();
|
||||
ur.m_exerciseId = map[QLatin1String("exerciseId")].toInt();
|
||||
ur.m_ok = map[QLatin1String("ok")].toBool();
|
||||
|
||||
return ur;
|
||||
}
|
||||
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wms_ecc_ibase.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariantMap>
|
||||
|
||||
class WMS_JSON_DS_EXPORT Unregister : public IBase
|
||||
{
|
||||
public:
|
||||
QJsonObject toJson() const;
|
||||
static Unregister fromJson(const QJsonObject &obj);
|
||||
|
||||
QVariantMap toVariantMap() const;
|
||||
static Unregister fromVariantMap(const QVariantMap &map);
|
||||
|
||||
int getEquipNo() const { return m_equipNo; }
|
||||
int getExerciseId() const { return m_exerciseId; }
|
||||
bool getOk() const { return m_ok; }
|
||||
|
||||
void setEquipNo(int equipNo) { m_equipNo = equipNo; }
|
||||
void setExerciseId(int exerciseId) { m_exerciseId = exerciseId; }
|
||||
void setOk(bool ok) { m_ok = ok; }
|
||||
|
||||
private:
|
||||
int m_equipNo = 0;
|
||||
int m_exerciseId = -1;
|
||||
bool m_ok = false;
|
||||
};
|
||||
Executable
+134
@@ -0,0 +1,134 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
#
|
||||
# nglapplication
|
||||
#
|
||||
SET(nglapplication_SRCS
|
||||
nglapplication.cpp
|
||||
nglapplication.h
|
||||
nglloggerhandler.cpp
|
||||
nglloggerhandler.h
|
||||
ngl_qt_msg_handler.inc
|
||||
ngl_signal_handler.inc
|
||||
)
|
||||
NGL_ADD_LIBRARY(WS AAR SV HLA nglapplication SHARED ${nglapplication_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(nglapplication
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglapplication)
|
||||
|
||||
#
|
||||
# nglsingleapplication
|
||||
#
|
||||
SET(nglsingleapplication_SRCS
|
||||
nglsingleapplication.cpp
|
||||
nglsingleapplication.h
|
||||
nglloggerhandler.cpp
|
||||
nglloggerhandler.h
|
||||
ngl_qt_msg_handler.inc
|
||||
ngl_signal_handler.inc
|
||||
)
|
||||
NGL_ADD_LIBRARY(WS nglsingleapplication SHARED ${nglsingleapplication_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglsingleapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(nglsingleapplication
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PUBLIC
|
||||
qtsingleapplication
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglsingleapplication)
|
||||
|
||||
#
|
||||
# nglcoreapplication
|
||||
#
|
||||
SET(nglcoreapplication_SRCS
|
||||
nglcoreapplication.cpp
|
||||
nglcoreapplication.h
|
||||
nglloggerhandler.cpp
|
||||
nglloggerhandler.h
|
||||
ngl_qt_msg_handler.inc
|
||||
ngl_signal_handler.inc
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(ALL nglcoreapplication SHARED ${nglcoreapplication_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglcoreapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(nglcoreapplication
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglcoreapplication)
|
||||
|
||||
#
|
||||
# nglsinglecoreapplication
|
||||
#
|
||||
SET(nglsinglecoreapplication_SRCS
|
||||
nglsinglecoreapplication.cpp
|
||||
nglsinglecoreapplication.h
|
||||
nglloggerhandler.cpp
|
||||
nglloggerhandler.h
|
||||
ngl_qt_msg_handler.inc
|
||||
ngl_signal_handler.inc
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV nglsinglecoreapplication SHARED ${nglsinglecoreapplication_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglsinglecoreapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(nglsinglecoreapplication
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PUBLIC
|
||||
qtsinglecoreapplication
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglsinglecoreapplication)
|
||||
|
||||
#
|
||||
# nglguiapplication
|
||||
#
|
||||
SET(nglguiapplication_SRCS
|
||||
nglguiapplication.cpp
|
||||
nglguiapplication.h
|
||||
nglloggerhandler.cpp
|
||||
nglloggerhandler.h
|
||||
ngl_qt_msg_handler.inc
|
||||
ngl_signal_handler.inc
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(ALL nglguiapplication SHARED ${nglguiapplication_SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglguiapplication
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(nglguiapplication
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
PUBLIC
|
||||
Qt5::Gui
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglguiapplication)
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* callback to catch qt log messages
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
static void qtMsgHandler(QtMsgType type, const QMessageLogContext &, const QString &msg)
|
||||
{
|
||||
// pulse audio connect errors are important but can be very annoying - so only print it ONE time only and also as an error
|
||||
static bool pulseAudioMessageSent = false;
|
||||
static QString pulseAudioMessage = QStringLiteral("PulseAudioService: pa_context_connect() failed");
|
||||
if (msg.startsWith(pulseAudioMessage))
|
||||
{
|
||||
if (pulseAudioMessageSent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
type = QtCriticalMsg;
|
||||
pulseAudioMessageSent = true;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
NGL::INGLLogger &l = NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger( "NGL.Qt" );
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
DEBUG_LOG(l) << msg ;
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
INFO_LOG(l) << msg ;
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
WARNING_LOG(l) << msg ;
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
ERROR_LOG(l) << msg ;
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
FATAL_LOG(l) << msg ;
|
||||
break;
|
||||
}
|
||||
} catch (...) {
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
case QtInfoMsg:
|
||||
fputs(qPrintable(msg), stdout);
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
case QtCriticalMsg:
|
||||
case QtFatalMsg:
|
||||
fputs(qPrintable(msg), stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* small stub to catch SIGTERM for proper shutdown
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtCore/QAbstractNativeEventFilter>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
class MyEventFilter final : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
const MSG *msg = reinterpret_cast<const MSG*>(message);
|
||||
if (msg->message == WM_CLOSE && msg->hwnd == nullptr)
|
||||
QCoreApplication::quit();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef SIGTERM
|
||||
# define SIGTERM 15
|
||||
#endif
|
||||
static void signalHandler(int signal_number)
|
||||
{
|
||||
if(signal_number != SIGTERM)
|
||||
return;
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
|
||||
#include "nglapplication.h"
|
||||
#include "ngl_signal_handler.inc"
|
||||
|
||||
|
||||
NGLApplication::NGLApplication(int &argc, char **argv)
|
||||
: QApplication(argc, argv)
|
||||
{
|
||||
|
||||
signal(SIGTERM, &signalHandler);
|
||||
#ifdef Q_OS_WIN
|
||||
installNativeEventFilter(new MyEventFilter);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool NGLApplication::notify(QObject *o, QEvent *e)
|
||||
{
|
||||
bool bRet = false;
|
||||
try
|
||||
{
|
||||
bRet = QApplication::notify(o, e);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "exception %s\n", e.what());
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QApplication>
|
||||
#include "nglloggerhandler.h"
|
||||
|
||||
#ifndef NGLAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLAPPLICATION_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLAPPLICATION_LIB
|
||||
# define NGLAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
class NGLAPPLICATION_EXPORT NGLApplication : public QApplication, public NGL::LoggerHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NGLApplication(int &argc, char **argv);
|
||||
|
||||
protected:
|
||||
bool notify(QObject *o, QEvent *e) override;
|
||||
};
|
||||
|
||||
#define nglApp static_cast<NGLApplication*>(NGLApplication::instance())
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
#include "nglcoreapplication.h"
|
||||
|
||||
#include "ngl_signal_handler.inc"
|
||||
|
||||
|
||||
NGLCoreApplication::NGLCoreApplication(int &argc, char **argv)
|
||||
: QCoreApplication(argc, argv)
|
||||
{
|
||||
|
||||
signal(SIGTERM, &signalHandler);
|
||||
#ifdef Q_OS_WIN
|
||||
installNativeEventFilter(new MyEventFilter);
|
||||
#endif
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include "nglloggerhandler.h"
|
||||
|
||||
#ifndef NGLCOREAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLCOREAPPLICATION_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLCOREAPPLICATION_LIB
|
||||
# define NGLCOREAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLCOREAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
class NGLCOREAPPLICATION_EXPORT NGLCoreApplication : public QCoreApplication, public NGL::LoggerHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NGLCoreApplication(int &argc, char **argv);
|
||||
};
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
#include "nglguiapplication.h"
|
||||
|
||||
#include "ngl_signal_handler.inc"
|
||||
|
||||
|
||||
NGLGuiApplication::NGLGuiApplication(int &argc, char **argv)
|
||||
: QGuiApplication(argc, argv)
|
||||
{
|
||||
|
||||
signal(SIGTERM, &signalHandler);
|
||||
#ifdef Q_OS_WIN
|
||||
installNativeEventFilter(new MyEventFilter);
|
||||
#endif
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include "nglloggerhandler.h"
|
||||
|
||||
#ifndef NGLGUIAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLGUIAPPLICATION_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLGUIAPPLICATION_LIB
|
||||
# define NGLGUIAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLGUIAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
class NGLGUIAPPLICATION_EXPORT NGLGuiApplication : public QGuiApplication, public NGL::LoggerHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NGLGuiApplication(int &argc, char **argv);
|
||||
};
|
||||
|
||||
#define nglGuiApp static_cast<NGLGuiApplication*>(NGLGuiApplication::instance())
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
|
||||
|
||||
|
||||
#include "nglloggerhandler.h"
|
||||
#include "ngl_qt_msg_handler.inc"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
#include <nglcoreapplication.h>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
static QByteArray username()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return qgetenv("USERNAME");
|
||||
#else
|
||||
return qgetenv("USER");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setEnvVars()
|
||||
{
|
||||
|
||||
const QString logPath = NGL::Settings::logPath();
|
||||
qputenv("LOG4QT_LOGDIR", logPath.toLocal8Bit());
|
||||
qputenv("LOG4QT_USER", username());
|
||||
}
|
||||
|
||||
|
||||
void LoggerHandler::createLogger(const QByteArray &baseName, const char *configFileName, bool quiet)
|
||||
{
|
||||
setEnvVars();
|
||||
m_baseLoggerName = baseName;
|
||||
|
||||
const QString bnStr(QString::fromLatin1(baseName.toLower()));
|
||||
const QString logPath = NGL::Settings::logPath();
|
||||
m_loggerFilenamePostfix = logPath + QLatin1Char('/') + QString::fromLocal8Bit(username()) + QLatin1Char('_') + bnStr;
|
||||
m_loggerFilenamePrefix = QLatin1String(".log");
|
||||
|
||||
const QString logOutputName = m_loggerFilenamePostfix + m_loggerFilenamePrefix;
|
||||
NGL::NGLLoggerBootstrap::createNGLRootLogger(QString::fromLatin1(configFileName), false, logOutputName, quiet);
|
||||
|
||||
|
||||
qInstallMessageHandler(&qtMsgHandler);
|
||||
}
|
||||
|
||||
|
||||
void LoggerHandler::createLogger(const QByteArray &baseName, int exerciseId, int additionalId, bool quiet)
|
||||
{
|
||||
setEnvVars();
|
||||
|
||||
const QString bnStr(QString::fromLatin1(baseName.toLower()));
|
||||
const QString configFileName = QLatin1String("log4cxx_") + bnStr + QLatin1String(".props");
|
||||
const QString logPath = NGL::Settings::logPath();
|
||||
m_loggerFilenamePostfix = logPath + QLatin1Char('/') + QString::fromLocal8Bit(username()) + QLatin1Char('_') + bnStr;
|
||||
if (exerciseId > 0)
|
||||
m_loggerFilenamePostfix += QLatin1Char('_') + QString::number(exerciseId);
|
||||
if (additionalId > 0)
|
||||
m_loggerFilenamePostfix += QLatin1Char('_') + QString::number(additionalId);
|
||||
|
||||
m_loggerFilenamePrefix = QLatin1String(".log");
|
||||
m_baseLoggerName = baseName + QByteArray(".main");
|
||||
|
||||
const QString logOutputName = m_loggerFilenamePostfix + m_loggerFilenamePrefix;
|
||||
NGL::NGLLoggerBootstrap::createNGLRootLogger(configFileName, false, logOutputName, quiet);
|
||||
|
||||
|
||||
qInstallMessageHandler(&qtMsgHandler);
|
||||
}
|
||||
|
||||
|
||||
NGL::INGLLogger &LoggerHandler::baseLogger() const
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(m_baseLoggerName.data());
|
||||
}
|
||||
|
||||
|
||||
NGL::INGLLogger &LoggerHandler::logger(const char *loggerName) const
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName);
|
||||
}
|
||||
|
||||
|
||||
LoggerHandler *LoggerHandler::getLoggerHandler()
|
||||
{
|
||||
return dynamic_cast<LoggerHandler*>(QCoreApplication::instance());
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
#ifndef LOGGERHANDLER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define LOGGERHANDLER_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_NGLCOREAPPLICATION_LIB) || defined(MAKE_NGLGUIAPPLICATION_LIB) || defined(MAKE_NGLAPPLICATION_LIB) || defined(MAKE_NGLSINGLECOREAPPLICATION_LIB) || defined(MAKE_NGLSINGLEAPPLICATION_LIB)
|
||||
# define LOGGERHANDLER_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define LOGGERHANDLER_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
|
||||
class LOGGERHANDLER_EXPORT LoggerHandler
|
||||
{
|
||||
public:
|
||||
LoggerHandler() = default;
|
||||
~LoggerHandler() = default;
|
||||
|
||||
|
||||
|
||||
void createLogger(const QByteArray &baseName,
|
||||
const char *configFileName,
|
||||
bool quiet = false);
|
||||
|
||||
|
||||
|
||||
void createLogger(const QByteArray &baseName,
|
||||
int exerciseId = 0,
|
||||
int additionalId = 0,
|
||||
bool quiet = false);
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &baseLogger() const;
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &logger(const char *loggerName) const;
|
||||
|
||||
|
||||
|
||||
QString loggerNamePostfix() const { return m_loggerFilenamePostfix; }
|
||||
|
||||
|
||||
|
||||
QString loggerNamePrefix() const { return m_loggerFilenamePrefix; }
|
||||
|
||||
|
||||
|
||||
static LoggerHandler *getLoggerHandler();
|
||||
private:
|
||||
QByteArray m_baseLoggerName;
|
||||
QString m_loggerFilenamePostfix;
|
||||
QString m_loggerFilenamePrefix;
|
||||
};
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
|
||||
#include "nglsingleapplication.h"
|
||||
|
||||
#include "ngl_signal_handler.inc"
|
||||
|
||||
|
||||
NGLSingleApplication::NGLSingleApplication(int &argc, char **argv)
|
||||
: QtSingleApplication(argc, argv)
|
||||
{
|
||||
|
||||
signal(SIGTERM, &signalHandler);
|
||||
#ifdef Q_OS_WIN
|
||||
installNativeEventFilter(new MyEventFilter);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool NGLSingleApplication::notify(QObject *o, QEvent *e)
|
||||
{
|
||||
bool bRet = false;
|
||||
try
|
||||
{
|
||||
bRet = QtSingleApplication::notify(o, e);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "exception %s\n", e.what());
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtSingleApplication/QtSingleApplication>
|
||||
#include "nglloggerhandler.h"
|
||||
|
||||
#ifndef NGLSINGLEAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLSINGLEAPPLICATION_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLSINGLEAPPLICATION_LIB
|
||||
# define NGLSINGLEAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLSINGLEAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
class NGLSINGLEAPPLICATION_EXPORT NGLSingleApplication : public QtSingleApplication, public NGL::LoggerHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NGLSingleApplication(int &argc, char **argv);
|
||||
|
||||
protected:
|
||||
bool notify(QObject *o, QEvent *e) override;
|
||||
};
|
||||
|
||||
#define nglApp static_cast<NGLSingleApplication*>(NGLSingleApplication::instance())
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
#include "nglsinglecoreapplication.h"
|
||||
|
||||
#include "ngl_signal_handler.inc"
|
||||
|
||||
|
||||
NGLSingleCoreApplication::NGLSingleCoreApplication(int &argc, char **argv)
|
||||
: QtSingleCoreApplication(argc, argv)
|
||||
{
|
||||
|
||||
signal(SIGTERM, &signalHandler);
|
||||
#ifdef Q_OS_WIN
|
||||
installNativeEventFilter(new MyEventFilter);
|
||||
#endif
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtSingleApplication/QtSingleCoreApplication>
|
||||
#include "nglloggerhandler.h"
|
||||
|
||||
#ifndef NGLSINGLECOREAPPLICATION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLSINGLECOREAPPLICATION_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLSINGLECOREAPPLICATION_LIB
|
||||
# define NGLSINGLECOREAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLSINGLECOREAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
class NGLSINGLECOREAPPLICATION_EXPORT NGLSingleCoreApplication : public QtSingleCoreApplication, public NGL::LoggerHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NGLSingleCoreApplication(int &argc, char **argv);
|
||||
};
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# CMake Script
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
FIND_PACKAGE(BZip2 REQUIRED)
|
||||
SET(nglcomp_SRCS
|
||||
nglcomp_bzip2iodevice.cpp
|
||||
nglcomp_bzip2iodevice.h
|
||||
nglcomp_compress.cpp
|
||||
nglcomp_compress.h
|
||||
nglcomp_export.h
|
||||
nglcomp_tarfilter.cpp
|
||||
nglcomp_tarfilter.h
|
||||
)
|
||||
NGL_ADD_LIBRARY(WS nglcompression SHARED ${nglcomp_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(nglcompression
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
PRIVATE
|
||||
Qt5::Concurrent
|
||||
NGLLogger
|
||||
${BZIP2_LIBRARIES}
|
||||
# BZip2::BZip2 # not available with cmake 3.5
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglcompression
|
||||
PRIVATE
|
||||
${BZIP2_INCLUDE_DIR}
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglcompression)
|
||||
|
||||
IF(BUILD_WS AND BUILD_TESTING)
|
||||
REMOVE_DEFINITIONS(-DQT_GUI_LIB)
|
||||
ADD_EXECUTABLE(nglcomp_test nglcomp_test.cpp nglcomp_test.h)
|
||||
|
||||
TARGET_LINK_LIBRARIES(nglcomp_test
|
||||
NGLLogger
|
||||
nglcoreapplication
|
||||
ngltools
|
||||
nglcompression
|
||||
Qt5::Test
|
||||
)
|
||||
|
||||
ADD_TEST(NAME nglcomp_test COMMAND $<TARGET_FILE:nglcomp_test>)
|
||||
ENDIF()
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "nglcomp_bzip2iodevice.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
|
||||
#include <bzlib.h>
|
||||
|
||||
|
||||
|
||||
|
||||
class BZip2IODevice::Private
|
||||
{
|
||||
public:
|
||||
Private(BZip2IODevice *parent_, QIODevice *dev, int bs)
|
||||
: parent(parent_)
|
||||
, device(dev)
|
||||
, iCurPos(0)
|
||||
, iMaxBufSize(1024 * 1024)
|
||||
, blocksize(bs)
|
||||
, initialized(false)
|
||||
, decomressStreamEnd(false)
|
||||
{
|
||||
buffer.resize(iMaxBufSize);
|
||||
}
|
||||
|
||||
bool initializeCompress();
|
||||
qint64 doCompress(const char *in, qint64 iMaxLen);
|
||||
bool finishCompress();
|
||||
bool initializeDecompress();
|
||||
qint64 doDecompress(char *out, qint64 iMaxLen);
|
||||
bool finishDecompress();
|
||||
static QString bzipError2String(int errCode);
|
||||
|
||||
QAtomicInt aborted { 0 };
|
||||
BZip2IODevice *parent;
|
||||
QIODevice *device;
|
||||
unsigned int iCurPos;
|
||||
unsigned int iMaxBufSize;
|
||||
unsigned int blocksize;
|
||||
bool initialized;
|
||||
bool decomressStreamEnd;
|
||||
QByteArray buffer;
|
||||
bz_stream stream;
|
||||
};
|
||||
|
||||
bool BZip2IODevice::Private::initializeCompress()
|
||||
{
|
||||
if (initialized)
|
||||
return true;
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
int blockSize = (blocksize > 0 && blocksize < 10) ? blocksize : 10;
|
||||
int ret = BZ2_bzCompressInit(&stream, blockSize, 0, 0);
|
||||
if (ret != BZ_OK)
|
||||
{
|
||||
parent->setErrorString(QStringLiteral("Error initializing bzip2 %1").arg(bzipError2String(ret)));
|
||||
initialized = false;
|
||||
}
|
||||
else
|
||||
initialized = true;
|
||||
|
||||
return initialized;
|
||||
}
|
||||
|
||||
qint64 BZip2IODevice::Private::doCompress(const char *in, qint64 iMaxLen)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
if (parent->errorString().isEmpty())
|
||||
parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
|
||||
finishCompress();
|
||||
return -1;
|
||||
}
|
||||
if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream.next_in = const_cast<char *>(in);
|
||||
stream.avail_in = iMaxLen;
|
||||
|
||||
do
|
||||
{
|
||||
if (aborted) return 0;
|
||||
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
|
||||
const int ret = BZ2_bzCompress(&stream, BZ_RUN);
|
||||
if (ret != BZ_RUN_OK)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
|
||||
return -1;
|
||||
}
|
||||
int iBytesToWrite = buffer.size() - stream.avail_out;
|
||||
if (iBytesToWrite)
|
||||
{
|
||||
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (stream.avail_in != 0);
|
||||
|
||||
return stream.next_in - in;
|
||||
}
|
||||
|
||||
bool BZip2IODevice::Private::finishCompress()
|
||||
{
|
||||
if (!initialized || aborted)
|
||||
return true;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
do
|
||||
{
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
ret = BZ2_bzCompress(&stream, BZ_FINISH);
|
||||
if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
|
||||
return false;
|
||||
}
|
||||
int iBytesToWrite = buffer.size() - stream.avail_out;
|
||||
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ret != BZ_STREAM_END);
|
||||
BZ2_bzCompressEnd(&stream);
|
||||
|
||||
initialized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BZip2IODevice::Private::initializeDecompress()
|
||||
{
|
||||
if (initialized)
|
||||
return true;
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
int ret = BZ2_bzDecompressInit(&stream, 0, 0);
|
||||
if (ret != BZ_OK)
|
||||
{
|
||||
parent->setErrorString(QStringLiteral("Error initializing bzip2: %1").arg(bzipError2String(ret)));
|
||||
initialized = false;
|
||||
}
|
||||
else
|
||||
initialized = true;
|
||||
decomressStreamEnd = false;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
qint64 BZip2IODevice::Private::doDecompress(char *out, qint64 iMaxLen)
|
||||
{
|
||||
int ret = -1;
|
||||
if (!initialized)
|
||||
{
|
||||
if (parent->errorString().isEmpty())
|
||||
parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
|
||||
finishDecompress();
|
||||
return -1;
|
||||
}
|
||||
if (decomressStreamEnd)
|
||||
return 0;
|
||||
|
||||
if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
|
||||
{
|
||||
finishCompress();
|
||||
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream.next_out = out;
|
||||
stream.avail_out = iMaxLen;
|
||||
|
||||
do
|
||||
{
|
||||
if (ret != BZ_STREAM_END && stream.avail_in == 0)
|
||||
{
|
||||
qint64 iReadCnt = device->read(buffer.data(), buffer.size());
|
||||
if (iReadCnt <= 0)
|
||||
return -1;
|
||||
stream.next_in = buffer.data();
|
||||
stream.avail_in = iReadCnt;
|
||||
}
|
||||
|
||||
ret = BZ2_bzDecompress(&stream);
|
||||
if (ret != BZ_OK && ret != BZ_STREAM_END)
|
||||
{
|
||||
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
|
||||
finishDecompress();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
while (stream.avail_out != 0 && ret != BZ_STREAM_END);
|
||||
decomressStreamEnd = (ret == BZ_STREAM_END);
|
||||
return stream.next_out - out;
|
||||
}
|
||||
|
||||
bool BZip2IODevice::Private::finishDecompress()
|
||||
{
|
||||
if (!initialized)
|
||||
return true;
|
||||
BZ2_bzDecompressEnd(&stream);
|
||||
|
||||
initialized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString BZip2IODevice::Private::bzipError2String(int errCode)
|
||||
{
|
||||
switch (errCode)
|
||||
{
|
||||
case BZ_SEQUENCE_ERROR:
|
||||
return QLatin1String("Sequence error");
|
||||
case BZ_PARAM_ERROR:
|
||||
return QLatin1String("Parameter not correct");
|
||||
case BZ_MEM_ERROR:
|
||||
return QLatin1String("Memory allocation error");
|
||||
case BZ_DATA_ERROR:
|
||||
return QLatin1String("Invalid input data");
|
||||
case BZ_DATA_ERROR_MAGIC:
|
||||
return QLatin1String("Not a bzip2 file");
|
||||
case BZ_IO_ERROR:
|
||||
return QLatin1String("I/O error");
|
||||
case BZ_UNEXPECTED_EOF:
|
||||
return QLatin1String("Unexpected end of file");
|
||||
case BZ_OUTBUFF_FULL:
|
||||
return QLatin1String("Output buffer full");
|
||||
case BZ_CONFIG_ERROR:
|
||||
return QLatin1String("Wrong config parameter");
|
||||
};
|
||||
return QString::number(errCode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BZip2IODevice::BZip2IODevice(QIODevice *dev, int blocksize)
|
||||
: d(new Private(this, dev, blocksize))
|
||||
{}
|
||||
|
||||
BZip2IODevice::~BZip2IODevice()
|
||||
{
|
||||
close();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void BZip2IODevice::setBufferSize(unsigned int size)
|
||||
{
|
||||
d->iMaxBufSize = size > 1024 ? size : 1024;
|
||||
d->buffer.resize(d->iMaxBufSize);
|
||||
}
|
||||
|
||||
void BZip2IODevice::setBlockSize(unsigned int size)
|
||||
{
|
||||
if (isOpen())
|
||||
return;
|
||||
d->blocksize = size;
|
||||
}
|
||||
|
||||
bool BZip2IODevice::isSequential() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BZip2IODevice::open(OpenMode mode)
|
||||
{
|
||||
if ((mode & QIODevice::ReadWrite) == 0)
|
||||
{
|
||||
setErrorString(QStringLiteral("Unsupported OpenMode %1").arg(mode));
|
||||
return false;
|
||||
}
|
||||
if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite)
|
||||
{
|
||||
setErrorString(QLatin1String("Can't read and write simultaniously"));
|
||||
return false;
|
||||
}
|
||||
if ((mode & QIODevice::ReadOnly) == QIODevice::ReadOnly)
|
||||
{
|
||||
if (!d->device)
|
||||
{
|
||||
setErrorString(QLatin1String("No QIODevice for reading available"));
|
||||
return false;
|
||||
}
|
||||
if ((d->device->openMode() & QIODevice::ReadOnly) == 0)
|
||||
{
|
||||
setErrorString(QLatin1String("QIODevice not opened for reading"));
|
||||
return false;
|
||||
}
|
||||
if (!d->initializeDecompress())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!d->device)
|
||||
{
|
||||
setErrorString(QLatin1String("No QIODevice for writing available"));
|
||||
return false;
|
||||
}
|
||||
if ((d->device->openMode() & QIODevice::WriteOnly) == 0)
|
||||
{
|
||||
setErrorString(QLatin1String("QIODevice not opened for writing"));
|
||||
return false;
|
||||
}
|
||||
if (!d->initializeCompress())
|
||||
return false;
|
||||
}
|
||||
setErrorString(QString());
|
||||
setOpenMode(mode);
|
||||
return QIODevice::open(mode);
|
||||
}
|
||||
|
||||
void BZip2IODevice::abort()
|
||||
{
|
||||
d->aborted = 1;
|
||||
}
|
||||
|
||||
void BZip2IODevice::close()
|
||||
{
|
||||
if (!isOpen())
|
||||
return;
|
||||
if ((openMode() & QIODevice::ReadOnly) == QIODevice::ReadOnly)
|
||||
d->finishDecompress();
|
||||
else
|
||||
d->finishCompress();
|
||||
QIODevice::close();
|
||||
}
|
||||
|
||||
bool BZip2IODevice::atEnd() const
|
||||
{
|
||||
if (!d->device)
|
||||
return true;
|
||||
return d->device->atEnd() && d->decomressStreamEnd && QIODevice::atEnd();
|
||||
}
|
||||
|
||||
qint64 BZip2IODevice::readData(char *data, qint64 maxSize)
|
||||
{
|
||||
return d->doDecompress(data, maxSize);
|
||||
}
|
||||
|
||||
qint64 BZip2IODevice::writeData(const char *data, qint64 maxSize)
|
||||
{
|
||||
return d->doCompress(data, maxSize);
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef BZIP2IODEVICE_H
|
||||
#define BZIP2IODEVICE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QIODevice>
|
||||
|
||||
|
||||
|
||||
class BZip2IODevice : public QIODevice
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
BZip2IODevice(QIODevice *dev, int blocksize = 5);
|
||||
virtual ~BZip2IODevice();
|
||||
|
||||
void abort();
|
||||
void setBufferSize(unsigned int size);
|
||||
void setBlockSize(unsigned int size);
|
||||
|
||||
|
||||
virtual bool isSequential() const;
|
||||
virtual bool open(OpenMode mode);
|
||||
virtual void close();
|
||||
virtual bool atEnd() const;
|
||||
protected:
|
||||
virtual qint64 readData(char *data, qint64 maxSize);
|
||||
virtual qint64 writeData(const char *data, qint64 maxSize);
|
||||
private:
|
||||
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+566
@@ -0,0 +1,566 @@
|
||||
|
||||
|
||||
#include "nglcomp_compress.h"
|
||||
#include "nglcomp_bzip2iodevice.h"
|
||||
#include "nglcomp_tarfilter.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QtConcurrent>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFutureWatcher>
|
||||
#include <QIODevice>
|
||||
#include <QStringList>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
Compress::Compress(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_u2_memFiles()
|
||||
, m_aborted(0)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("nglcompress"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "c_tor";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QTimer *t = new QTimer(this);
|
||||
t->setInterval(1000);
|
||||
connect(t, &QTimer::timeout, this, [](){qWarning() << "still alive ...";});
|
||||
t->start();
|
||||
}
|
||||
|
||||
Compress::~Compress()
|
||||
{
|
||||
qWarning() << "## COMPRESS DTOR!!!!";
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "~";
|
||||
|
||||
abort();
|
||||
m_future.waitForFinished();
|
||||
DEBUG_LOG(m_logger) << "~ finished";
|
||||
}
|
||||
|
||||
void Compress::abort()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ABORT";
|
||||
|
||||
m_aborted = 1;
|
||||
m_lastError = tr("Aborted");
|
||||
|
||||
if (m_currentTarFilter != nullptr)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "aborting tar";
|
||||
m_currentTarFilter->abort();
|
||||
}
|
||||
|
||||
if (m_currentBzipDevice != nullptr)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "aborting bzip";
|
||||
m_currentBzipDevice->abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Compress::compress(QIODevice *out,
|
||||
const QString &filesRootDir,
|
||||
const QVector<FileInformations> &files,
|
||||
const QVector<FileInformations> &memFiles,
|
||||
const QString &destRootDir)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "compress #2";
|
||||
reset();
|
||||
setupFutureWatcher(QtConcurrent::run(this, &Compress::_compress, out, filesRootDir, files, memFiles, destRootDir));
|
||||
}
|
||||
|
||||
void Compress::compress(QIODevice *out, const QString &sourceDir, const QString &destRootDir)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "compress #1 source dir: " << sourceDir << ", destRootDir: " << destRootDir;
|
||||
reset();
|
||||
|
||||
QVector<Compress::FileInformations> inFiles = directoryFileList(sourceDir, true);
|
||||
|
||||
|
||||
int len = sourceDir.length();
|
||||
if (!sourceDir.endsWith(QLatin1Char('/')))
|
||||
len += 1;
|
||||
for (auto &fi : inFiles)
|
||||
{
|
||||
fi.inputFileName = fi.inputFileName.mid(len);
|
||||
fi.bAbsInputPath = false;
|
||||
DEBUG_LOG(m_logger) << "fi: ifm = " << fi.inputFileName << ", abs = " << fi.bAbsInputPath;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "FI list size: " << inFiles.count();
|
||||
|
||||
compress(out, sourceDir, inFiles, {}, destRootDir);
|
||||
}
|
||||
|
||||
bool Compress::_compress(QIODevice *output,
|
||||
const QString &filesRootDir,
|
||||
const QVector<FileInformations> &files,
|
||||
const QVector<FileInformations> &memFiles,
|
||||
const QString &_destRootDir)
|
||||
{
|
||||
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #1";
|
||||
m_currentTarFilter = nullptr;
|
||||
m_currentBzipDevice = nullptr;
|
||||
});
|
||||
(void)invalidatePointersOnScopeLeave;
|
||||
|
||||
|
||||
if (!output || !output->isWritable())
|
||||
{
|
||||
m_lastError = tr("Device is not writeable");
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString destRootDir = _destRootDir.endsWith(QLatin1Char('/')) ?
|
||||
_destRootDir : _destRootDir + QLatin1Char('/');
|
||||
|
||||
const qint64 maxCount = files.count() + memFiles.count();
|
||||
qint64 count = 0;
|
||||
|
||||
DEBUG_LOG(m_logger) << "destRootDir = " << destRootDir << ", maxCount = " << maxCount << ", count = " << count;
|
||||
|
||||
BZip2IODevice bzip2(output, 9);
|
||||
m_currentBzipDevice = &bzip2;
|
||||
|
||||
if (!bzip2.open(QIODevice::WriteOnly))
|
||||
{
|
||||
m_lastError = bzip2.errorString();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
qint64 bytesTotal = 0;
|
||||
for (const FileInformations &file : qAsConst(files))
|
||||
{
|
||||
if (m_aborted) return false;
|
||||
|
||||
const QString in = file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName;
|
||||
const QFileInfo fi(in);
|
||||
|
||||
bytesTotal += fi.size();
|
||||
}
|
||||
|
||||
|
||||
qint64 currentFileSize = 0;
|
||||
QString currentFileName;
|
||||
auto readCallback = [this, &maxCount, &count, ¤tFileSize, ¤tFileName, &bytesTotal](const qint64 iSize)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "readCallback: maxCount = " << maxCount << ", count = " << count
|
||||
<< ", currentFileSize = " << currentFileSize << ", currentFileName = " << currentFileName << ", iSize = " << iSize;
|
||||
emit compressInfoEx(maxCount, count, currentFileSize, (currentFileSize - iSize), currentFileName, bytesTotal);
|
||||
};
|
||||
|
||||
|
||||
TarFilter tf(&bzip2, nullptr, readCallback);
|
||||
m_currentTarFilter = &tf;
|
||||
const QVector<QStringRef> paths = destRootDir.splitRef(QLatin1Char('/'), QString::SkipEmptyParts);
|
||||
QString curPath;
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "prepairing tar filter";
|
||||
for (const QStringRef &path : paths)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "path = " << path.toString();
|
||||
if (m_aborted) return false;
|
||||
|
||||
if (curPath.isEmpty())
|
||||
curPath = path + QLatin1Char('/');
|
||||
else
|
||||
curPath += path + QLatin1Char('/');
|
||||
|
||||
DEBUG_LOG(m_logger) << "curPath = " << curPath << ", filesRootDir.isEmpty() = " << filesRootDir.isEmpty();
|
||||
|
||||
if (filesRootDir.isEmpty())
|
||||
{
|
||||
if (!tf.addData(curPath, QByteArray(), true))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tf.addFile(filesRootDir, curPath))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_c_sizeInfo.realSize = 0;
|
||||
for (const FileInformations &file : qAsConst(files))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "file = " << file.inputFileName;
|
||||
emit compressInfo(maxCount, ++count, file.inputFileName);
|
||||
|
||||
if (m_aborted) return false;
|
||||
|
||||
QString in = file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName;
|
||||
QString out = destRootDir + (file.outputFileName.isEmpty() ? file.inputFileName : file.outputFileName);
|
||||
|
||||
DEBUG_LOG(m_logger) << "in = " << in << ", out = " << out;
|
||||
|
||||
QFileInfo fi(in);
|
||||
|
||||
currentFileName = fi.fileName();
|
||||
currentFileSize = fi.size();
|
||||
m_c_sizeInfo.realSize += currentFileSize;
|
||||
|
||||
DEBUG_LOG(m_logger) << "currentFileName = " << currentFileName << ", currentFileSize = " << currentFileSize << "m_c_sizeInfo.realSize" << m_c_sizeInfo.realSize;
|
||||
|
||||
if (!tf.addFile(in, out))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const FileInformations &file : qAsConst(memFiles))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "(mem) file = " << file.inputFileName;
|
||||
emit compressInfo(maxCount, ++count, file.inputFileName);
|
||||
|
||||
if (m_aborted) return false;
|
||||
|
||||
currentFileName = file.inputFileName;
|
||||
currentFileSize = file.fileData.size();
|
||||
m_c_sizeInfo.compressedSize += currentFileSize;
|
||||
|
||||
DEBUG_LOG(m_logger) << "(mem) currentFileName = " << currentFileName << ", currentFileSize = " << currentFileSize << "m_c_sizeInfo.realSize" << m_c_sizeInfo.realSize;
|
||||
|
||||
if (!tf.addData(file.inputFileName, file.fileData))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "writing eos";
|
||||
tf.writeEOS();
|
||||
|
||||
DEBUG_LOG(m_logger) << "closing bzip";
|
||||
bzip2.close();
|
||||
|
||||
m_c_sizeInfo.compressedSize = output->size();
|
||||
DEBUG_LOG(m_logger) << "m_c_sizeInfo.compressedSize = " << m_c_sizeInfo.compressedSize;
|
||||
|
||||
m_success = true;
|
||||
|
||||
DEBUG_LOG(m_logger) << "DONE!";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compress::uncompress(QIODevice *in, const QString &outDir)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "uncompress #1";
|
||||
reset();
|
||||
setupFutureWatcher(QtConcurrent::run(this, &Compress::_uncompressDirectory, in, outDir));
|
||||
}
|
||||
|
||||
bool Compress::_uncompressDirectory(QIODevice *input, const QString &outDir)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "_uncompressDirectory";
|
||||
|
||||
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2";
|
||||
m_currentTarFilter = nullptr;
|
||||
m_currentBzipDevice = nullptr;
|
||||
});
|
||||
(void)invalidatePointersOnScopeLeave;
|
||||
|
||||
|
||||
if (!input || !input->isReadable())
|
||||
{
|
||||
m_lastError = tr("Device is not readable");
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BZip2IODevice bzip2(input, 9);
|
||||
m_currentBzipDevice = &bzip2;
|
||||
if (!bzip2.open(QIODevice::ReadOnly))
|
||||
{
|
||||
m_lastError = bzip2.errorString();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TarFilter tf(&bzip2);
|
||||
m_currentTarFilter = &tf;
|
||||
TarFilter::FileInformations tfi;
|
||||
QDir dir(outDir);
|
||||
|
||||
DEBUG_LOG(m_logger) << "dir = " << dir.path();
|
||||
|
||||
while (tf.getData(tfi))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
|
||||
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
|
||||
if (m_aborted) return false;
|
||||
|
||||
QString path = outDir + QLatin1Char('/') + tfi.fileName;
|
||||
DEBUG_LOG(m_logger) << "path = " << path;
|
||||
if (tfi.fileType == TarFilter::directory)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "tfi.fileType == TarFilter::directory";
|
||||
if (!dir.exists(path) && !dir.mkpath(path))
|
||||
{
|
||||
m_lastError = tr("Error creating directory %1").arg(outDir);
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
QString pathName = QFileInfo(path).absolutePath();
|
||||
if (!dir.exists(pathName) && !dir.mkpath(pathName))
|
||||
{
|
||||
m_lastError = tr("Error creating directory %1").arg(pathName);
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
{
|
||||
m_lastError = tr("Error opening %1 for writing (%2)").arg(path, f.errorString());
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!tf.getData(&f))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "uncompress done!";
|
||||
m_success = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compress::uncompress(QIODevice *in)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "uncompress #2!";
|
||||
reset();
|
||||
setupFutureWatcher(QtConcurrent::run(this, &Compress::_uncompressBuffer, in));
|
||||
}
|
||||
|
||||
bool Compress::_uncompressBuffer(QIODevice *input)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "uncompressBuffer";
|
||||
|
||||
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2";
|
||||
m_currentTarFilter = nullptr;
|
||||
m_currentBzipDevice = nullptr;
|
||||
});
|
||||
(void)invalidatePointersOnScopeLeave;
|
||||
|
||||
|
||||
if (!input->isReadable())
|
||||
{
|
||||
m_lastError = tr("Device is not readable");
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BZip2IODevice bzip2(input, 9);
|
||||
m_currentBzipDevice = &bzip2;
|
||||
if (!bzip2.open(QIODevice::ReadOnly))
|
||||
{
|
||||
m_lastError = bzip2.errorString();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TarFilter tf(&bzip2);
|
||||
m_currentTarFilter = &tf;
|
||||
TarFilter::FileInformations tfi;
|
||||
while (tf.getData(tfi))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
|
||||
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
|
||||
if (m_aborted) return false;
|
||||
|
||||
FileInformations fi;
|
||||
fi.outputFileName = tfi.fileName;
|
||||
|
||||
DEBUG_LOG(m_logger) << "fi.outputFileName = " << fi.outputFileName;
|
||||
|
||||
if (tfi.fileType == TarFilter::directory)
|
||||
{
|
||||
fi.outputFileName += QLatin1Char('/');
|
||||
DEBUG_LOG(m_logger) << "> fi.outputFileName = " << fi.outputFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "stuff";
|
||||
|
||||
QBuffer buf(&fi.fileData);
|
||||
if (!buf.open(QIODevice::WriteOnly))
|
||||
{
|
||||
m_lastError = tr("Error opening buffer for writing (%1)").arg(buf.errorString());
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!tf.getData(&buf))
|
||||
{
|
||||
m_lastError = tf.lastError();
|
||||
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fi.bAbsInputPath = fi.outputFileName.startsWith(QLatin1Char('/'));
|
||||
DEBUG_LOG(m_logger) << "added fi.bAbsInputPath = " << fi.bAbsInputPath;
|
||||
m_u2_memFiles += fi;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Compress::success() const
|
||||
{
|
||||
|
||||
ERROR_LOG(m_logger) << "success? " << (m_future.isFinished() && !m_future.isCanceled() && m_success);
|
||||
ERROR_LOG(m_logger) << "success details: "
|
||||
<< "success m_future.isFinished() = " << (m_future.isFinished())
|
||||
<< " !m_future.isCanceled() = " << !m_future.isCanceled()
|
||||
<< " m_success = " << m_success;
|
||||
return (m_future.isFinished() && !m_future.isCanceled() && m_success);
|
||||
}
|
||||
|
||||
bool Compress::waitForFinished()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "waitForFinished...";
|
||||
m_future.waitForFinished();
|
||||
DEBUG_LOG(m_logger) << "waitForFinished... done!";
|
||||
return success();
|
||||
}
|
||||
|
||||
QVector<Compress::FileInformations> Compress::directoryFileList(const QString &dir, bool recursive)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "directoryFileList";
|
||||
|
||||
QVector<FileInformations> sl_absolute;
|
||||
QDir d(dir);
|
||||
|
||||
if (d.exists())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "exists";
|
||||
const auto entries = d.entryList(QDir::Files);
|
||||
sl_absolute.reserve(sl_absolute.size() + entries.size());
|
||||
for (const QString &entry : entries)
|
||||
sl_absolute << FileInformations(QFileInfo(d, entry).absoluteFilePath(), true);
|
||||
}
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "recursive";
|
||||
const auto entries = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
sl_absolute.reserve(sl_absolute.size() + entries.size());
|
||||
for (const QString &s : entries)
|
||||
sl_absolute << directoryFileList(dir + QLatin1Char('/') + s, true);
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "done";
|
||||
return sl_absolute;
|
||||
}
|
||||
|
||||
void Compress::reset()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "reset";
|
||||
m_u2_memFiles.clear();
|
||||
|
||||
m_lastError.clear();
|
||||
|
||||
m_c_sizeInfo.realSize = 0;
|
||||
m_c_sizeInfo.compressedSize = 0;
|
||||
|
||||
m_success = false;
|
||||
}
|
||||
|
||||
void Compress::setupFutureWatcher(const QFuture<bool> &future)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "setupFutureWatcher";
|
||||
m_future = future;
|
||||
QFutureWatcher<bool> *fw = new QFutureWatcher<bool>(this);
|
||||
QObject::connect(fw, &QObject::destroyed, this, [this]() { DEBUG_LOG(m_logger) << "Future Watcher destroyed"; });
|
||||
QObject::connect(fw, &QFutureWatcher<bool>::finished, this, &Compress::finished);
|
||||
QObject::connect(fw, &QFutureWatcher<bool>::finished, fw, &QObject::deleteLater);
|
||||
QObject::connect(fw, &QFutureWatcher<bool>::finished, fw, [this]() { DEBUG_LOG(m_logger) << "Future Watcher about to be deleted"; });
|
||||
fw->setFuture(m_future);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+140
@@ -0,0 +1,140 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nglcomp_export.h"
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class QIODevice;
|
||||
class TarFilter;
|
||||
class BZip2IODevice;
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class NGLCOMPRESSION_EXPORT Compress : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct FileInformations
|
||||
{
|
||||
QString inputFileName;
|
||||
QString outputFileName;
|
||||
QByteArray fileData;
|
||||
bool bAbsInputPath = true;
|
||||
FileInformations() = default;
|
||||
|
||||
FileInformations(const QString &name, bool isAbsolute)
|
||||
: inputFileName(name)
|
||||
, bAbsInputPath(isAbsolute)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct FileSizeInfo
|
||||
{
|
||||
qint64 realSize = 0;
|
||||
qint64 compressedSize = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
explicit Compress(QObject *parent = nullptr);
|
||||
|
||||
~Compress();
|
||||
|
||||
|
||||
|
||||
QVector<FileInformations> getMemFiles() const { return m_u2_memFiles; }
|
||||
|
||||
|
||||
FileSizeInfo getFileSizeInfo() const { return m_c_sizeInfo; }
|
||||
|
||||
|
||||
bool success() const;
|
||||
|
||||
|
||||
|
||||
void compress(QIODevice *out,
|
||||
const QString &sourceRootDir,
|
||||
const QVector<FileInformations> &files,
|
||||
const QVector<FileInformations> &memFiles,
|
||||
const QString &destRootDir);
|
||||
|
||||
|
||||
|
||||
void compress(QIODevice *out,
|
||||
const QString &sourceDir,
|
||||
const QString &destRootDir);
|
||||
|
||||
|
||||
void uncompress(QIODevice *in,
|
||||
const QString &outDir);
|
||||
|
||||
|
||||
void uncompress(QIODevice *in);
|
||||
|
||||
|
||||
QString lastError() const { return m_lastError; }
|
||||
|
||||
|
||||
|
||||
bool waitForFinished();
|
||||
|
||||
public Q_SLOTS:
|
||||
void abort();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
|
||||
void uncompressInfo(qint64 totalSize, qint64 curPos, const QString &curName);
|
||||
|
||||
|
||||
void compressInfo(qint64 totalFiles, qint64 curFile, const QString &curName);
|
||||
void compressInfoEx(qint64 totalFiles, qint64 curFile, qint64 totalSize, qint64 curPos, const QString &curName, const qint64 bytesTotal);
|
||||
|
||||
|
||||
|
||||
void error(const QString &errorString);
|
||||
|
||||
|
||||
|
||||
void finished();
|
||||
private:
|
||||
|
||||
bool _compress(QIODevice *output,
|
||||
const QString &filesRootDir,
|
||||
const QVector<FileInformations> &files,
|
||||
const QVector<FileInformations> &memFiles,
|
||||
const QString &_destRootDir);
|
||||
bool _uncompressDirectory(QIODevice *input, const QString &outDir);
|
||||
bool _uncompressBuffer(QIODevice *input);
|
||||
|
||||
void reset();
|
||||
void setupFutureWatcher(const QFuture<bool> &future);
|
||||
|
||||
QVector<FileInformations> directoryFileList(const QString &dir, bool recursive = false);
|
||||
|
||||
FileSizeInfo m_c_sizeInfo;
|
||||
QVector<FileInformations> m_u2_memFiles;
|
||||
|
||||
QString m_lastError;
|
||||
QAtomicInt m_aborted;
|
||||
|
||||
TarFilter *m_currentTarFilter { nullptr };
|
||||
BZip2IODevice *m_currentBzipDevice { nullptr };
|
||||
|
||||
QFuture<bool> m_future;
|
||||
bool m_success { false };
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
Q_DECLARE_TYPEINFO(NGL::Compress::FileInformations, Q_MOVABLE_TYPE);
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef NGLCOMPRESSION_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLCOMPRESSION_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_NGLCOMPRESSION_LIB)
|
||||
# define NGLCOMPRESSION_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLCOMPRESSION_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
Executable
+525
@@ -0,0 +1,525 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
#include <QIODevice>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "nglcomp_tarfilter.h"
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TarFilter::Private
|
||||
{
|
||||
public:
|
||||
Private(QIODevice *dev, QTextCodec *c)
|
||||
: device(dev)
|
||||
, codec(c ? c : QTextCodec::codecForLocale())
|
||||
, iBufSize(1024 * 1024)
|
||||
, nextChunkSize(-1)
|
||||
{}
|
||||
|
||||
struct tar_posix_header
|
||||
{
|
||||
char name[100];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag;
|
||||
char linkname[100];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char uname[32];
|
||||
char gname[32];
|
||||
char devmajor[8];
|
||||
char devminor[8];
|
||||
char prefix[155];
|
||||
char unused[12];
|
||||
};
|
||||
bool fi2tph(const FileInformations &infos);
|
||||
bool addHeader(const FileInformations &infos);
|
||||
|
||||
bool tph2fi(FileInformations &infos);
|
||||
bool getHeader(FileInformations &infos);
|
||||
bool checkDevice(QIODevice *in, QIODevice *out);
|
||||
bool copyData(QIODevice *in, QIODevice *out, qint64 iSize);
|
||||
|
||||
QIODevice *device;
|
||||
QTextCodec *codec;
|
||||
QString lastError;
|
||||
unsigned int iBufSize;
|
||||
qint64 nextChunkSize;
|
||||
QAtomicInt aborted { 0 };
|
||||
std::function<void(qint64)> readCallback;
|
||||
};
|
||||
|
||||
bool TarFilter::Private::fi2tph(const FileInformations &infos)
|
||||
{
|
||||
QByteArray fn = codec->fromUnicode(infos.fileName);
|
||||
#ifdef Q_OS_WIN
|
||||
if (fn.size() > 3 && fn[1] == ':' && (fn[2] == '\\' || fn[2] == '/'))
|
||||
fn = fn.mid(3);
|
||||
#endif
|
||||
if (fn.startsWith('/'))
|
||||
fn = fn.mid(1);
|
||||
|
||||
long unsigned int fileSize = infos.fileType == directory ? 0 : infos.fileSize;
|
||||
long unsigned int mtime = infos.mtime != -1 ? infos.mtime : time(nullptr);
|
||||
tar_posix_header hdr;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
QByteArray fn_part1 = fn.left(sizeof(hdr.name));
|
||||
memcpy(hdr.name, fn_part1.constData(), fn_part1.size());
|
||||
sprintf(hdr.mode, "%07x", 0x0fff & infos.mode);
|
||||
sprintf(hdr.uid, "%07o", infos.uid);
|
||||
sprintf(hdr.gid, "%07o", infos.gid);
|
||||
sprintf(hdr.size, "%011lo", fileSize);
|
||||
sprintf(hdr.mtime, "%011lo", mtime);
|
||||
memset(hdr.chksum, ' ', sizeof(hdr.chksum));
|
||||
hdr.typeflag = infos.fileType;
|
||||
|
||||
memcpy(hdr.magic, "ustar ",sizeof(hdr.magic) + sizeof(hdr.version));
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
|
||||
#else
|
||||
qstrncpy(hdr.uname, codec->fromUnicode(infos.uname).constData(), sizeof(hdr.uname));
|
||||
qstrncpy(hdr.gname, codec->fromUnicode(infos.gname).constData(), sizeof(hdr.gname));
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int checksum = 0;
|
||||
const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&hdr);
|
||||
for (unsigned i = 0; i < sizeof(hdr); i++)
|
||||
checksum += ptr[i];
|
||||
constexpr int octalMax = 01000000;
|
||||
while (checksum > octalMax)
|
||||
checksum -= octalMax;
|
||||
sprintf(hdr.chksum, "%06o", checksum);
|
||||
|
||||
if (!device->write((const char *)&hdr, sizeof(hdr)))
|
||||
{
|
||||
lastError = QLatin1String("Error writing to QIODevice");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::Private::addHeader(const FileInformations &infos)
|
||||
{
|
||||
|
||||
|
||||
QByteArray fn = codec->fromUnicode(infos.fileName);
|
||||
#ifdef Q_OS_WIN
|
||||
if (fn.size() > 3 && fn[1] == ':' && (fn[2] == '\\' || fn[2] == '/'))
|
||||
fn = fn.mid(3);
|
||||
#endif
|
||||
if (fn.startsWith('/'))
|
||||
fn = fn.mid(1);
|
||||
if (fn.size() > 512)
|
||||
{
|
||||
lastError = QLatin1String("Can't handle filenames with more then 512 bytes");
|
||||
return false;
|
||||
}
|
||||
if (fn.size() > 100)
|
||||
{
|
||||
FileInformations longlink;
|
||||
longlink.fileName = QLatin1String("././@LongLink");
|
||||
longlink.fileType = gnu_longname;
|
||||
longlink.fileSize = strlen(fn.constData()) + 1;
|
||||
longlink.mtime = 0;
|
||||
longlink.uid = 0;
|
||||
longlink.gid = 0;
|
||||
#ifndef Q_OS_WIN
|
||||
struct passwd *p = getpwuid(longlink.uid);
|
||||
if (p)
|
||||
longlink.uname = codec->toUnicode(p->pw_name);
|
||||
struct group *g = getgrgid(longlink.gid);
|
||||
if (g)
|
||||
longlink.gname = codec->toUnicode(g->gr_name);
|
||||
#endif
|
||||
fi2tph(longlink);
|
||||
QByteArray ba(512, '\0');
|
||||
qstrncpy(ba.data(), fn.constData(), ba.size());
|
||||
if (!device->write(ba.constData(), ba.size()))
|
||||
{
|
||||
lastError = QLatin1String("Error writing to QIODevice");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!fi2tph(infos))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::Private::tph2fi(FileInformations &infos)
|
||||
{
|
||||
Private::tar_posix_header hdr;
|
||||
do
|
||||
{
|
||||
int iBytesRead = device->read((char *)&hdr, sizeof(hdr));
|
||||
if (iBytesRead != sizeof(hdr))
|
||||
{
|
||||
if (iBytesRead == 0 && device->atEnd())
|
||||
{
|
||||
lastError = QString();
|
||||
return false;
|
||||
}
|
||||
lastError = QStringLiteral("Error reading from QIODevice! needed: %1, got: %2").arg(sizeof(hdr)).arg(iBytesRead);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (memcmp(hdr.magic, "\0\0\0\0\0\0", sizeof(hdr.magic)) == 0);
|
||||
if (memcmp(hdr.magic, "ustar ", sizeof(hdr.magic)))
|
||||
{
|
||||
lastError = QLatin1String("The archive is not supported");
|
||||
return false;
|
||||
}
|
||||
int checksum = QByteArray(hdr.chksum, sizeof(hdr.chksum)).toUInt(nullptr, 8);
|
||||
memset(hdr.chksum, ' ', sizeof(hdr.chksum));
|
||||
int realChecksum = 0;
|
||||
const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&hdr);
|
||||
for (unsigned i = 0; i < sizeof(hdr); i++)
|
||||
realChecksum += ptr[i];
|
||||
if (checksum != realChecksum)
|
||||
{
|
||||
lastError = QStringLiteral("Checksum does not match! needed: %1, got: %2").arg(checksum).arg(realChecksum);
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray ba(hdr.name, sizeof(hdr.name));
|
||||
ba.resize(qstrlen(ba.constData()));
|
||||
infos.fileName = codec->toUnicode(ba);
|
||||
infos.fileSize = QByteArray(hdr.size, sizeof(hdr.size)).toUInt(nullptr, 8);
|
||||
infos.mode = static_cast<QFile::Permissions>(QByteArray(hdr.mode, sizeof(hdr.mode)).toUInt(nullptr, 16));
|
||||
infos.uid = QByteArray(hdr.uid, sizeof(hdr.uid)).toUInt(nullptr, 8);
|
||||
infos.gid = QByteArray(hdr.gid, sizeof(hdr.gid)).toUInt(nullptr, 8);
|
||||
infos.mtime = QByteArray(hdr.mtime, sizeof(hdr.mtime)).toUInt(nullptr, 8);
|
||||
infos.fileType = (FileType)hdr.typeflag;
|
||||
infos.uname = codec->toUnicode(hdr.uname, sizeof(hdr.uname));
|
||||
infos.gname = codec->toUnicode(hdr.gname, sizeof(hdr.gname));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::Private::getHeader(FileInformations &infos)
|
||||
{
|
||||
if (!tph2fi(infos))
|
||||
return false;
|
||||
switch (infos.fileType)
|
||||
{
|
||||
case regular:
|
||||
case regular2:
|
||||
case directory:
|
||||
case gnu_longname:
|
||||
break;
|
||||
default:
|
||||
lastError = QStringLiteral("Unsupported fileType %1").arg(infos.fileType);
|
||||
return false;
|
||||
}
|
||||
if (infos.fileType == gnu_longname)
|
||||
{
|
||||
const QByteArray fn = device->read(512);
|
||||
if (fn.size() != 512)
|
||||
{
|
||||
lastError = QLatin1String("Unexpected end of inputstream");
|
||||
return false;
|
||||
}
|
||||
if (!tph2fi(infos))
|
||||
return false;
|
||||
const int len = qstrlen(fn.constData());
|
||||
infos.fileName = codec->toUnicode(fn.constData(), len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::Private::checkDevice(QIODevice *in, QIODevice *out)
|
||||
{
|
||||
if (!in)
|
||||
{
|
||||
lastError = QLatin1String("No QIODevice for reading available");
|
||||
return false;
|
||||
}
|
||||
if ((in->openMode() & QIODevice::ReadOnly) == 0)
|
||||
{
|
||||
lastError = QLatin1String("QIODevice not opened for reading");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!out)
|
||||
{
|
||||
lastError = QLatin1String("No QIODevice for writing available");
|
||||
return false;
|
||||
}
|
||||
if ((out->openMode() & QIODevice::WriteOnly) == 0)
|
||||
{
|
||||
lastError = QLatin1String("QIODevice not opened for writing");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::Private::copyData(QIODevice *in, QIODevice *out, qint64 iSize)
|
||||
{
|
||||
if (iSize <= 0)
|
||||
return true;
|
||||
|
||||
while (iSize > 0)
|
||||
{
|
||||
if (aborted) return false;
|
||||
|
||||
const qint64 iBytesToRead = iSize > iBufSize ? iBufSize : iSize;
|
||||
const QByteArray ba = in->read(iBytesToRead);
|
||||
|
||||
if (aborted) return false;
|
||||
|
||||
if (ba.size() == 0)
|
||||
{
|
||||
lastError = QStringLiteral("Could not read %1 bytes from QIODevice").arg(iBytesToRead);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out->write(ba) != ba.size())
|
||||
{
|
||||
lastError = QStringLiteral("Could not write %1 bytes to QIODevice").arg(ba.size());
|
||||
return false;
|
||||
}
|
||||
iSize -= ba.size();
|
||||
|
||||
if (readCallback)
|
||||
readCallback(iSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TarFilter::TarFilter(QIODevice *dev, QTextCodec *codec, const std::function<void(qint64)> &readCallback)
|
||||
: d(new Private(dev, codec))
|
||||
{
|
||||
d->readCallback = readCallback;
|
||||
}
|
||||
|
||||
TarFilter::~TarFilter()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TarFilter::abort()
|
||||
{
|
||||
d->aborted = 1;
|
||||
}
|
||||
|
||||
void TarFilter::setLocaleCodec(QTextCodec *codec)
|
||||
{
|
||||
d->codec = codec ? codec : QTextCodec::codecForLocale();
|
||||
}
|
||||
|
||||
void TarFilter::setBufferSize(unsigned int size)
|
||||
{
|
||||
d->iBufSize = size > 1024 ? size : 1024;
|
||||
}
|
||||
|
||||
bool TarFilter::error() const
|
||||
{
|
||||
return !d->lastError.isEmpty();
|
||||
}
|
||||
|
||||
QString TarFilter::lastError() const
|
||||
{
|
||||
return d->lastError;
|
||||
}
|
||||
|
||||
bool TarFilter::addFile(const QString &filename, const QString &filenameInArchive)
|
||||
{
|
||||
QFileInfo fi(filename);
|
||||
if (!fi.exists())
|
||||
{
|
||||
d->lastError = QStringLiteral("File %1 does not exist").arg(filename);
|
||||
return false;
|
||||
}
|
||||
if (!(fi.isDir() || fi.isFile()))
|
||||
{
|
||||
d->lastError = QStringLiteral("%1 isn't a directory or a regular file").arg(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInformations fInfos;
|
||||
fInfos.fileName = (filenameInArchive.isEmpty() ? filename : filenameInArchive);
|
||||
fInfos.fileSize = fi.isDir() ? 0 : fi.size();
|
||||
fInfos.mode = fi.permissions() & 0x0fff;
|
||||
#ifdef Q_OS_WIN
|
||||
fInfos.uid = 1000;
|
||||
fInfos.gid = 100;
|
||||
#else
|
||||
fInfos.uid = fi.ownerId();
|
||||
fInfos.gid = fi.groupId();
|
||||
fInfos.uname = fi.owner();
|
||||
fInfos.gname = fi.group();
|
||||
#endif
|
||||
fInfos.mtime = fi.lastModified().toSecsSinceEpoch();
|
||||
fInfos.fileType = fi.isDir() ? directory : regular;
|
||||
|
||||
if (fi.isDir())
|
||||
{
|
||||
QBuffer buf;
|
||||
buf.open(QIODevice::ReadOnly);
|
||||
return addData(fInfos, &buf);
|
||||
}
|
||||
QFile f(filename);
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
{
|
||||
d->lastError = QStringLiteral("Error opening %1 for reading").arg(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d->aborted) return false;
|
||||
|
||||
return addData(fInfos, &f);
|
||||
}
|
||||
|
||||
bool TarFilter::addData(const QString &filename, const QByteArray &data, bool bIsDir)
|
||||
{
|
||||
if (d->aborted) return false;
|
||||
|
||||
FileInformations fi;
|
||||
fi.fileName = filename;
|
||||
fi.fileSize = bIsDir ? 0 : data.size();
|
||||
fi.mode = static_cast<QFile::Permissions>(bIsDir ? 0x0755 : 0x0644);
|
||||
fi.fileType = bIsDir ? directory : regular;
|
||||
#ifndef Q_OS_WIN
|
||||
fi.uid = getuid();
|
||||
fi.gid = getgid();
|
||||
char name[256];
|
||||
struct passwd *p_ptr = nullptr;
|
||||
struct passwd p;
|
||||
getpwuid_r(fi.uid, &p, name, sizeof(name) - 1, &p_ptr);
|
||||
if (p_ptr)
|
||||
fi.uname = d->codec->toUnicode(p_ptr->pw_name);
|
||||
struct group *g_ptr;
|
||||
struct group g;
|
||||
getgrgid_r(fi.gid, &g, name, sizeof(name) - 1, &g_ptr);
|
||||
if (g_ptr)
|
||||
fi.gname = d->codec->toUnicode(g_ptr->gr_name);
|
||||
#endif
|
||||
|
||||
QBuffer buf(const_cast<QByteArray *>(&data));
|
||||
if (!buf.open(QIODevice::ReadOnly))
|
||||
{
|
||||
d->lastError = QLatin1String("Internal Error - can't open QBuffer for reading!");
|
||||
return false;
|
||||
}
|
||||
return addData(fi, &buf);
|
||||
}
|
||||
|
||||
bool TarFilter::addData(const FileInformations &fi, QIODevice *in)
|
||||
{
|
||||
if (d->aborted) return false;
|
||||
|
||||
if (!d->checkDevice(in, d->device))
|
||||
return false;
|
||||
|
||||
if (!d->addHeader(fi))
|
||||
return false;
|
||||
|
||||
if (fi.fileSize)
|
||||
{
|
||||
if (!d->copyData(in, d->device, fi.fileSize))
|
||||
return false;
|
||||
|
||||
int align = fi.fileSize % 512;
|
||||
if (align)
|
||||
{
|
||||
align = 512 - align;
|
||||
QByteArray ba2(align, '\0');
|
||||
d->device->write(ba2.constData(), align);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::writeEOS()
|
||||
{
|
||||
|
||||
const int size = sizeof(TarFilter::Private::tar_posix_header) * 2;
|
||||
QByteArray ba(size, '\0');
|
||||
return (d->device->write(ba) == size);
|
||||
}
|
||||
|
||||
bool TarFilter::getData(FileInformations &fi)
|
||||
{
|
||||
if (d->aborted) return false;
|
||||
|
||||
d->nextChunkSize = -1;
|
||||
if (!d->getHeader(fi))
|
||||
return false;
|
||||
d->nextChunkSize = fi.fileSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::getData(QIODevice *out)
|
||||
{
|
||||
if (d->aborted) return false;
|
||||
|
||||
if (!d->checkDevice(d->device, out))
|
||||
return false;
|
||||
|
||||
if (d->nextChunkSize < 0)
|
||||
{
|
||||
d->lastError = QLatin1String("No informations about next chunk size. Did you call getData(FileInformations &fi) before?");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!d->copyData(d->device, out, d->nextChunkSize))
|
||||
return false;
|
||||
|
||||
int align = d->nextChunkSize % 512;
|
||||
if (align)
|
||||
d->device->read(512 - align);
|
||||
|
||||
d->nextChunkSize = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TarFilter::getData(FileInformations &fi, QByteArray &data)
|
||||
{
|
||||
if (!getData(fi))
|
||||
return false;
|
||||
|
||||
QBuffer buf(&data);
|
||||
buf.open(QIODevice::WriteOnly);
|
||||
return getData(&buf);
|
||||
}
|
||||
|
||||
bool TarFilter::getData(FileInformations &fi, QIODevice *out)
|
||||
{
|
||||
if (!getData(fi))
|
||||
return false;
|
||||
|
||||
return getData(out);
|
||||
}
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef TARFILTER_H
|
||||
#define TARFILTER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <functional>
|
||||
|
||||
class QIODevice;
|
||||
class QTextCodec;
|
||||
class QByteArray;
|
||||
|
||||
|
||||
|
||||
class TarFilter
|
||||
{
|
||||
public:
|
||||
Q_DISABLE_COPY(TarFilter)
|
||||
|
||||
enum FileType
|
||||
{
|
||||
regular = '0',
|
||||
regular2 = '\0',
|
||||
link = '1',
|
||||
reserved = '2',
|
||||
charType = '3',
|
||||
block = '4',
|
||||
directory = '5',
|
||||
fifo = '6',
|
||||
reserved2 = '7',
|
||||
gnu_longLink = 'K',
|
||||
gnu_longname = 'L',
|
||||
};
|
||||
struct FileInformations
|
||||
{
|
||||
QString fileName;
|
||||
qint64 fileSize = 0;
|
||||
int uid = 1000;
|
||||
int gid = 100;
|
||||
QString uname;
|
||||
QString gname;
|
||||
time_t mtime = -1;
|
||||
FileType fileType = regular;
|
||||
QFile::Permissions mode = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::ReadOther;
|
||||
};
|
||||
|
||||
|
||||
|
||||
TarFilter(QIODevice *dev, QTextCodec *codec = nullptr, const std::function<void(qint64)> &readCallback = nullptr);
|
||||
~TarFilter();
|
||||
|
||||
void abort();
|
||||
void setLocaleCodec(QTextCodec *codec);
|
||||
void setBufferSize(unsigned int size);
|
||||
bool error() const;
|
||||
QString lastError() const;
|
||||
|
||||
|
||||
bool addData(const FileInformations &fi, QIODevice *in);
|
||||
|
||||
bool addFile(const QString &filename, const QString &filenameInArchive = QString());
|
||||
bool addData(const QString &filename, const QByteArray &data = QByteArray(), bool bIsDir = false);
|
||||
|
||||
bool writeEOS();
|
||||
|
||||
|
||||
bool getData(FileInformations &fi, QIODevice *out);
|
||||
|
||||
bool getData(FileInformations &fi);
|
||||
bool getData(QIODevice *out);
|
||||
bool getData(FileInformations &fi, QByteArray &data);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+175
@@ -0,0 +1,175 @@
|
||||
|
||||
|
||||
#include "nglcomp_test.h"
|
||||
|
||||
#include "nglcomp_compress.h"
|
||||
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#include <nglapplication/nglcoreapplication.h>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
|
||||
|
||||
void nglcomp_test::initTestCase()
|
||||
{
|
||||
m_tempDirIn.setAutoRemove(true);
|
||||
m_tempDirOut.setAutoRemove(true);
|
||||
QVERIFY(m_tempDirIn.isValid());
|
||||
QVERIFY(m_tempDirOut.isValid());
|
||||
QVERIFY(m_tf.open());
|
||||
m_tf.setAutoRemove(true);
|
||||
|
||||
m_fileContent[QLatin1String("1.txt")] = "111111111111111111111111";
|
||||
m_fileContent[QLatin1String("sub1/s1.txt")] = "222222222222222222222222";
|
||||
m_fileContent[QLatin1String("sub1/sub11/s11.txt")] = "333333333333333333333333";
|
||||
m_fileContent[QLatin1String("sub1/sub12/s12.txt")] = "444444444444444444444444";
|
||||
m_fileContent[QLatin1String("sub2/2.txt")] = "555555555555555555555555";
|
||||
}
|
||||
|
||||
|
||||
void nglcomp_test::testCompressFile()
|
||||
{
|
||||
QDir dir;
|
||||
const auto directories = {
|
||||
QLatin1String("sub1"),
|
||||
QLatin1String("sub1/sub11"),
|
||||
QLatin1String("sub1/sub12"),
|
||||
QLatin1String("sub2")
|
||||
};
|
||||
for (const QLatin1String &directory : directories)
|
||||
QVERIFY(dir.mkdir(subPathIn(directory)));
|
||||
|
||||
for (auto it = m_fileContent.cbegin(); it != m_fileContent.cend(); ++it)
|
||||
writeTestFile(it.key(), it.value());
|
||||
|
||||
NGL::Compress c;
|
||||
c.compress(&m_tf, subPathIn(QString()), QLatin1String("out"));
|
||||
QVERIFY(c.waitForFinished());
|
||||
}
|
||||
|
||||
|
||||
void nglcomp_test::testCompressMemory()
|
||||
{
|
||||
QBuffer f(&m_ba);
|
||||
QVERIFY(f.open(QIODevice::WriteOnly));
|
||||
QVector<NGL::Compress::FileInformations> fi1;
|
||||
QVector<NGL::Compress::FileInformations> fi2;
|
||||
NGL::Compress::FileInformations fi;
|
||||
|
||||
fi.inputFileName = QLatin1String("chris.txt");
|
||||
fi.fileData = QByteArray("dumdidum\n");
|
||||
fi2 += fi;
|
||||
|
||||
fi.inputFileName = QLatin1String("blub/chris.txt");
|
||||
fi.fileData = QByteArray("dumdidum im Verzeichnis blub\n");
|
||||
fi2 += fi;
|
||||
|
||||
fi.inputFileName = QLatin1String("blub/blub/chris2.txt");
|
||||
fi.fileData = QByteArray("dumdidum im Verzeichnis blub/blub\n");
|
||||
fi2 += fi;
|
||||
|
||||
NGL::Compress c;
|
||||
c.compress(&f, QString(), fi1, fi2, QLatin1String("blub"));
|
||||
QVERIFY(c.waitForFinished());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void nglcomp_test::testUncompressMemory()
|
||||
{
|
||||
QBuffer f(&m_ba);
|
||||
QVERIFY(f.open(QIODevice::ReadOnly));
|
||||
NGL::Compress c;
|
||||
c.uncompress(&f, subPathIn(QString()));
|
||||
QVERIFY(c.waitForFinished());
|
||||
f.close();
|
||||
|
||||
QVERIFY(f.open(QIODevice::ReadOnly));
|
||||
c.uncompress(&f);
|
||||
QVERIFY(c.waitForFinished());
|
||||
QVector<NGL::Compress::FileInformations> fi1 = c.getMemFiles();
|
||||
QVERIFY(fi1.count() == 4);
|
||||
f.close();
|
||||
}
|
||||
|
||||
void nglcomp_test::testUncompressFile()
|
||||
{
|
||||
NGL::Compress c;
|
||||
m_tf.seek(0);
|
||||
c.uncompress(&m_tf, subPathOut(QString()));
|
||||
QVERIFY(c.waitForFinished());
|
||||
|
||||
for (auto it = m_fileContent.cbegin(); it != m_fileContent.cend(); ++it)
|
||||
checkContent(it.key(), it.value());
|
||||
}
|
||||
|
||||
void nglcomp_test::cleanupTestCase()
|
||||
{
|
||||
m_tf.close();
|
||||
m_tempDirIn.remove();
|
||||
m_tempDirOut.remove();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nglcomp_test::writeTestFile(const QString &fn, const QByteArray &content) const
|
||||
{
|
||||
QFile f(subPathIn(fn));
|
||||
QVERIFY(f.open(QIODevice::WriteOnly));
|
||||
QVERIFY(f.write(content) == content.size());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void nglcomp_test::checkContent(const QString &fn, const QByteArray &content) const
|
||||
{
|
||||
QFile f(subPathOut(QLatin1String("out/") + fn));
|
||||
QVERIFY(f.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(f.readAll(), content);
|
||||
}
|
||||
|
||||
QString nglcomp_test::subPathIn(const QString &p) const
|
||||
{
|
||||
return m_tempDirIn.path() + QLatin1Char('/') + p;
|
||||
}
|
||||
|
||||
QString nglcomp_test::subPathOut(const QString &p) const
|
||||
{
|
||||
return m_tempDirOut.path() + QLatin1Char('/') + p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
NGLCoreApplication app(argc, argv);
|
||||
|
||||
app.createLogger("nglcomp_test", "log4cxx_nglcomp_test.props");
|
||||
nglcomp_test tc;
|
||||
return QTest::qExec(&tc, argc, argv);
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
class nglcomp_test : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
nglcomp_test() = default;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testCompressFile();
|
||||
void testCompressMemory();
|
||||
void testUncompressFile();
|
||||
void testUncompressMemory();
|
||||
void cleanupTestCase();
|
||||
private:
|
||||
void writeTestFile(const QString &fn, const QByteArray &content) const;
|
||||
void checkContent(const QString &fn, const QByteArray &content) const;
|
||||
QString subPathIn(const QString &p) const;
|
||||
QString subPathOut(const QString &p) const;
|
||||
private:
|
||||
QHash<QString, QByteArray> m_fileContent;
|
||||
QByteArray m_ba;
|
||||
QTemporaryFile m_tf;
|
||||
QTemporaryDir m_tempDirIn;
|
||||
QTemporaryDir m_tempDirOut;
|
||||
};
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
# NGLDB
|
||||
FIND_PACKAGE(PostgreSQL REQUIRED)
|
||||
|
||||
OPTION(ENABLE_DB_TRACING "Enable trace output for NGLDB library" OFF)
|
||||
IF(ENABLE_DB_TRACING)
|
||||
add_compile_definitions(NGLDB_ENABLE_TRACE)
|
||||
ENDIF(ENABLE_DB_TRACING)
|
||||
|
||||
#
|
||||
# NGL Database Library
|
||||
#
|
||||
SET(ngldb_SRCS
|
||||
dbcommon.h
|
||||
dbconnection.cpp
|
||||
dbconnection.h
|
||||
db_service_handler.h
|
||||
dbtransaction.cpp
|
||||
dbtransaction.h
|
||||
ngldb_export.h
|
||||
ngldb_logger.cpp
|
||||
ngldb_logger.h
|
||||
nsqlquery.cpp
|
||||
nsqlquery.h
|
||||
sql_query_janitor.cpp
|
||||
sql_query_janitor.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV HLA WS ngldb SHARED ${ngldb_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(ngldb
|
||||
PRIVATE
|
||||
NGLLogger
|
||||
nglsettings
|
||||
${PostgreSQL_LIBRARIES}
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Sql
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(ngldb
|
||||
PRIVATE
|
||||
${PostgreSQL_INCLUDE_DIR}
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(ngldb)
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
#include <memory>
|
||||
|
||||
class QSqlDatabase;
|
||||
namespace NGLDB
|
||||
{
|
||||
template<typename DB>
|
||||
class DbServiceHandler
|
||||
{
|
||||
public:
|
||||
DbServiceHandler() = default;
|
||||
~DbServiceHandler() = default;
|
||||
|
||||
|
||||
bool init(int exerciseId, NGL::Settings *settings)
|
||||
{
|
||||
if (m_dbInterface)
|
||||
return true;
|
||||
|
||||
m_dbInterface = DB::create(exerciseId);
|
||||
|
||||
if (!m_dbInterface->init(m_dbInterface->dbUser(),
|
||||
settings->databasePassword(m_dbInterface->dbUser()),
|
||||
settings->databaseDriver(),
|
||||
settings->databaseHostname(),
|
||||
settings->databaseName()))
|
||||
{
|
||||
m_dbInterface = nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init(int exerciseId, const QSqlDatabase &db)
|
||||
{
|
||||
if (m_dbInterface)
|
||||
return true;
|
||||
|
||||
m_dbInterface = DB::create(exerciseId);
|
||||
|
||||
if (!m_dbInterface->init(db))
|
||||
{
|
||||
m_dbInterface = nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<DB> db() const { return m_dbInterface; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<DB> m_dbInterface;
|
||||
};
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngldb_export.h"
|
||||
#include <QString>
|
||||
|
||||
|
||||
|
||||
namespace DBCommon
|
||||
{
|
||||
|
||||
enum class eDatabaseSchema
|
||||
{
|
||||
Exercise
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline QString getExerciseSchemaName(int exerciseId)
|
||||
{
|
||||
return QLatin1String("ex_") + QString::number(exerciseId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline QString getTableName(const QString &tableName, const QString &schemaName)
|
||||
{
|
||||
if (schemaName.isEmpty())
|
||||
return tableName;
|
||||
return schemaName + QLatin1Char('.') + tableName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline QString getExerciseTableName(const QString &tableName, int exerciseId)
|
||||
{
|
||||
return getTableName(tableName, getExerciseSchemaName(exerciseId));
|
||||
}
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
#include "dbconnection.h"
|
||||
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QtSql/QSqlError>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include "nsqlquery.h"
|
||||
|
||||
namespace DBConnection
|
||||
{
|
||||
|
||||
QSqlDatabase open(NGL::INGLLogger &logger,
|
||||
const QString &dbUser,
|
||||
const QString &dbPasswd,
|
||||
const QString &dbDriver,
|
||||
const QString &dbHost,
|
||||
const QString &dbName,
|
||||
const QString &schemaName,
|
||||
const QString &connectionName)
|
||||
{
|
||||
|
||||
|
||||
|
||||
DEBUG_LOG(logger) << "host: " << dbHost << " database: " << dbName;
|
||||
QString realConnectionName(connectionName);
|
||||
if (connectionName.isEmpty())
|
||||
{
|
||||
realConnectionName = dbHost + QLatin1Char('_') + dbName;
|
||||
if (!schemaName.isEmpty())
|
||||
realConnectionName += QLatin1Char('_') + schemaName;
|
||||
}
|
||||
|
||||
auto dbConnection = QSqlDatabase::addDatabase(dbDriver, realConnectionName);
|
||||
dbConnection.setHostName(dbHost);
|
||||
dbConnection.setDatabaseName(dbName);
|
||||
dbConnection.setUserName(dbUser);
|
||||
dbConnection.setPassword(dbPasswd);
|
||||
|
||||
if (!dbConnection.open())
|
||||
{
|
||||
const QString err = dbConnection.lastError().nativeErrorCode();
|
||||
FATAL_LOG(logger) << "Error opening database " << dbHost
|
||||
<< ":" << dbName << " as user " << dbUser;
|
||||
FATAL_LOG(logger) << dbConnection.lastError().driverText() << " "
|
||||
<< dbConnection.lastError().databaseText() << " " << err;
|
||||
return dbConnection;
|
||||
}
|
||||
|
||||
DEBUG_LOG(logger) << "Database Initialisation successful -> DB: " << dbName << ", con: " << realConnectionName;
|
||||
|
||||
if (!schemaName.isEmpty())
|
||||
{
|
||||
const QString stmt = QLatin1String("SET SEARCH_PATH TO ") + schemaName + QLatin1String(", PUBLIC");
|
||||
|
||||
NSqlQuery q(dbConnection);
|
||||
if (!q.exec(stmt))
|
||||
{
|
||||
ERROR_LOG(logger) << "Set SEARCH_PATH to " << schemaName << " failed!";
|
||||
dbConnection.close();
|
||||
}
|
||||
}
|
||||
|
||||
return dbConnection;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtSql/QSqlDatabase>
|
||||
|
||||
#include "ngldb_export.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
namespace DBConnection
|
||||
{
|
||||
NGLDB_EXPORT QSqlDatabase open(NGL::INGLLogger &logger,
|
||||
const QString &dbUser,
|
||||
const QString &dbPasswd,
|
||||
const QString &dbDriver,
|
||||
const QString &dbHost,
|
||||
const QString &dbName,
|
||||
const QString &schemaName = QString(),
|
||||
const QString &connectionName = QString());
|
||||
}
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
|
||||
|
||||
|
||||
#include "dbtransaction.h"
|
||||
#include "ngldb_logger.h"
|
||||
#include <QtSql/QSqlError>
|
||||
|
||||
thread_local int s_refCounter = 0;
|
||||
|
||||
DBTransaction::DBTransaction(const QSqlDatabase &db)
|
||||
: m_db(db)
|
||||
, m_bCommitted(true)
|
||||
, mLogger(NGLDB::getLogger("DBTransaction"))
|
||||
{
|
||||
++s_refCounter;
|
||||
if (s_refCounter == 1)
|
||||
begin();
|
||||
}
|
||||
|
||||
DBTransaction::~DBTransaction()
|
||||
{
|
||||
if (s_refCounter == 1)
|
||||
{
|
||||
if (!m_bCommitted)
|
||||
rollback();
|
||||
}
|
||||
--s_refCounter;
|
||||
}
|
||||
|
||||
bool DBTransaction::begin()
|
||||
{
|
||||
if (!m_bCommitted)
|
||||
return setState(false);
|
||||
if (!m_db.transaction())
|
||||
{
|
||||
ERROR_LOG(mLogger) << "Error starting a transaction: " << m_db.lastError().driverText();
|
||||
return setState(false);
|
||||
}
|
||||
m_bCommitted = false;
|
||||
return setState(true);
|
||||
}
|
||||
|
||||
bool DBTransaction::commit()
|
||||
{
|
||||
if (s_refCounter == 1)
|
||||
{
|
||||
if (!m_db.commit())
|
||||
{
|
||||
ERROR_LOG(mLogger) << "Error committing a transaction: " << m_db.lastError().driverText();
|
||||
return setState(false);
|
||||
}
|
||||
m_bCommitted = true;
|
||||
return setState(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBTransaction::rollback()
|
||||
{
|
||||
if (s_refCounter == 1)
|
||||
{
|
||||
if (!m_db.rollback())
|
||||
{
|
||||
ERROR_LOG(mLogger) << "Error rolling back a transaction" << m_db.lastError().driverText();
|
||||
return setState(false);
|
||||
}
|
||||
m_bCommitted = true;
|
||||
return setState(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBTransaction::state() const
|
||||
{
|
||||
return m_lastState;
|
||||
}
|
||||
|
||||
bool DBTransaction::setState(bool bState)
|
||||
{
|
||||
m_lastState = bState;
|
||||
return m_lastState;
|
||||
}
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtSql/QSqlDatabase>
|
||||
|
||||
#include "ngldb_export.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
class NGLDB_EXPORT DBTransaction
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
explicit DBTransaction(const QSqlDatabase &db);
|
||||
|
||||
|
||||
|
||||
~DBTransaction();
|
||||
|
||||
|
||||
|
||||
bool begin();
|
||||
|
||||
|
||||
bool commit();
|
||||
|
||||
|
||||
bool rollback();
|
||||
|
||||
|
||||
bool state() const;
|
||||
|
||||
private:
|
||||
bool setState(bool bState);
|
||||
|
||||
QSqlDatabase m_db;
|
||||
bool m_bCommitted;
|
||||
bool m_lastState;
|
||||
NGL::INGLLogger &mLogger;
|
||||
};
|
||||
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef NGLDB_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLDB_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_NGLDB_LIB)
|
||||
# define NGLDB_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLDB_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
|
||||
#include "ngldb_logger.h"
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
NGLDB::LOGGER_T NGLDB::getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "NGLDB.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try {
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger( loggerName );
|
||||
} catch ( const std::exception &ex )
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#ifdef Q_CC_GNU
|
||||
#define DB_TRACE_FUNCTION __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define DB_TRACE_FUNCTION __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef NGLDB_ENABLE_TRACE
|
||||
#define DB_TRACE { TRACE_LOG(mLogger) << DB_TRACE_FUNCTION }
|
||||
#define DB_TRACE2(x) { TRACE_LOG(mLogger) << DB_TRACE_FUNCTION << x }
|
||||
#else
|
||||
#define DB_TRACE
|
||||
#define DB_TRACE2(x)
|
||||
#endif
|
||||
|
||||
namespace NGLDB
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
Executable
+457
@@ -0,0 +1,457 @@
|
||||
|
||||
|
||||
#include "nsqlquery.h"
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtSql/QSqlDriver>
|
||||
#include <QtSql/QSqlError>
|
||||
#include <QtSql/QSqlRecord>
|
||||
#include <QtSql/QSqlResult>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QJsonValue>
|
||||
|
||||
#include "ngldb_logger.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
static QString getSqlErrorString(const QSqlError &error)
|
||||
{
|
||||
return error.driverText() + QLatin1Char(' ') +
|
||||
error.databaseText() + QLatin1Char(' ') +
|
||||
error.nativeErrorCode();
|
||||
}
|
||||
|
||||
NSqlQuery::NSqlQuery(const QSqlDatabase &db)
|
||||
: QSqlQuery(db)
|
||||
, m_db(db)
|
||||
, mLogger(NGLDB::getLogger("NSqlQuery"))
|
||||
{
|
||||
DB_TRACE
|
||||
setForwardOnly(true);
|
||||
}
|
||||
|
||||
NSqlQuery::NSqlQuery(const QSqlDatabase &db, NGL::INGLLogger &logger)
|
||||
: QSqlQuery(db)
|
||||
, m_db(db)
|
||||
, mLogger(logger)
|
||||
{
|
||||
DB_TRACE
|
||||
setForwardOnly(true);
|
||||
}
|
||||
|
||||
NSqlQuery::NSqlQuery(const QString &query, const QSqlDatabase &db)
|
||||
: QSqlQuery(query, db)
|
||||
, m_db(db)
|
||||
, mLogger(NGLDB::getLogger("NSqlQuery"))
|
||||
{
|
||||
DB_TRACE
|
||||
setForwardOnly(true);
|
||||
}
|
||||
|
||||
NSqlQuery::NSqlQuery(const QString &query, const QSqlDatabase &db, NGL::INGLLogger &logger)
|
||||
: QSqlQuery(query, db)
|
||||
, m_db(db)
|
||||
, mLogger(logger)
|
||||
{
|
||||
DB_TRACE
|
||||
setForwardOnly(true);
|
||||
}
|
||||
|
||||
void NSqlQuery::addBindValue(const QVariant &val, QSql::ParamType paramType)
|
||||
{
|
||||
DB_TRACE;
|
||||
DEBUG_LOG(mLogger) << "type: " << val.type() << " paramType: " << paramType;
|
||||
QSqlQuery::addBindValue(val, paramType);
|
||||
}
|
||||
|
||||
int NSqlQuery::at() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::at();
|
||||
}
|
||||
|
||||
void NSqlQuery::bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType)
|
||||
{
|
||||
DB_TRACE;
|
||||
TRACE_LOG(mLogger) << "placeholder: " << placeholder << " type: " << val.type() << " paramType: " << paramType;
|
||||
QSqlQuery::bindValue(placeholder, val, paramType);
|
||||
}
|
||||
|
||||
void NSqlQuery::bindValue(int pos, const QVariant &val, QSql::ParamType paramType)
|
||||
{
|
||||
DB_TRACE;
|
||||
TRACE_LOG(mLogger) << "pos: " << pos << " type: " << val.type() << " paramType: " << paramType;
|
||||
QSqlQuery::bindValue(pos, val, paramType);
|
||||
}
|
||||
|
||||
QVariant NSqlQuery::boundValue(const QString &placeholder) const
|
||||
{
|
||||
DB_TRACE
|
||||
TRACE_LOG(mLogger) << "placeholder: " << placeholder;
|
||||
return QSqlQuery::boundValue(placeholder);
|
||||
}
|
||||
|
||||
QVariant NSqlQuery::boundValue(int pos) const
|
||||
{
|
||||
DB_TRACE
|
||||
TRACE_LOG(mLogger) << "pos: " << pos;
|
||||
return QSqlQuery::boundValue(pos);
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> NSqlQuery::boundValues() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::boundValues();
|
||||
}
|
||||
|
||||
void NSqlQuery::clear()
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::clear();
|
||||
}
|
||||
|
||||
const QSqlDriver *NSqlQuery::driver() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::driver();
|
||||
}
|
||||
|
||||
bool NSqlQuery::exec(const QString &query, bool bEmitMessageOnError)
|
||||
{
|
||||
DB_TRACE;
|
||||
DEBUG_LOG(mLogger) << "query: " << query;
|
||||
if (QSqlQuery::exec(query))
|
||||
return true;
|
||||
if (bEmitMessageOnError)
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NSqlQuery::exec(bool bEmitMessageOnError)
|
||||
{
|
||||
DB_TRACE
|
||||
DEBUG_LOG(mLogger) << "query: " << lastQuery();
|
||||
|
||||
if (mLogger.isDebugEnabled())
|
||||
{
|
||||
const QMap<QString, QVariant> &boundValuesMap = boundValues();
|
||||
for (auto it=boundValuesMap.begin(); it != boundValuesMap.end(); ++it)
|
||||
{
|
||||
if ( it.value().canConvert<QString>())
|
||||
DEBUG_LOG(mLogger) << "key='" << it.key() << "' value='" << it.value().toString() << "'";
|
||||
else
|
||||
DEBUG_LOG(mLogger) << "key='" << it.key() << "' value cant Convert to string'";
|
||||
}
|
||||
}
|
||||
if (QSqlQuery::exec())
|
||||
return true;
|
||||
if (bEmitMessageOnError)
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NSqlQuery::execAndFetch()
|
||||
{
|
||||
DB_TRACE
|
||||
if (!exec())
|
||||
return false;
|
||||
return (next());
|
||||
}
|
||||
|
||||
bool NSqlQuery::execAndFetch(const QString &query)
|
||||
{
|
||||
DB_TRACE
|
||||
if (!exec(query))
|
||||
return false;
|
||||
return (next());
|
||||
}
|
||||
|
||||
bool NSqlQuery::execBatch(BatchExecutionMode mode)
|
||||
{
|
||||
DB_TRACE2("mode: " << mode)
|
||||
DEBUG_LOG(mLogger) << "mode: " << mode;
|
||||
if (QSqlQuery::execBatch(mode))
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString NSqlQuery::executedQuery() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::executedQuery();
|
||||
}
|
||||
|
||||
void NSqlQuery::finish()
|
||||
{
|
||||
DB_TRACE
|
||||
QSqlQuery::finish();
|
||||
}
|
||||
|
||||
bool NSqlQuery::first()
|
||||
{
|
||||
DB_TRACE
|
||||
if (QSqlQuery::first())
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NSqlQuery::isActive() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::isActive();
|
||||
}
|
||||
|
||||
bool NSqlQuery::isForwardOnly() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::isForwardOnly();
|
||||
}
|
||||
|
||||
bool NSqlQuery::isNull(int field) const
|
||||
{
|
||||
DB_TRACE2("field: " << field)
|
||||
return QSqlQuery::isNull(field);
|
||||
}
|
||||
|
||||
bool NSqlQuery::isSelect() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::isSelect();
|
||||
}
|
||||
|
||||
bool NSqlQuery::isValid() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::isValid();
|
||||
}
|
||||
|
||||
bool NSqlQuery::last()
|
||||
{
|
||||
DB_TRACE
|
||||
if (QSqlQuery::last())
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlError NSqlQuery::lastError() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::lastError();
|
||||
}
|
||||
|
||||
QString NSqlQuery::sqlstate()
|
||||
{
|
||||
const QVariant resultHandle = this->result()->handle();
|
||||
|
||||
|
||||
|
||||
|
||||
if (resultHandle.isValid() && (qstrcmp(resultHandle.typeName(), "PGresult*") == 0))
|
||||
{
|
||||
|
||||
const PGresult *pgresHandle = *static_cast<const PGresult * const *>(resultHandle.data());
|
||||
|
||||
if (pgresHandle != nullptr)
|
||||
{
|
||||
|
||||
return QString::fromLocal8Bit(PQresultErrorField(pgresHandle, PG_DIAG_SQLSTATE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return QStringLiteral("58000");
|
||||
}
|
||||
|
||||
QVariant NSqlQuery::lastInsertId()
|
||||
{
|
||||
DB_TRACE
|
||||
|
||||
QVariant ret;
|
||||
|
||||
if (this->driver()->hasFeature(QSqlDriver::LastInsertId))
|
||||
ret = QSqlQuery::lastInsertId();
|
||||
|
||||
if (!ret.isValid())
|
||||
{
|
||||
NSqlQuery q(m_db);
|
||||
if (q.execAndFetch(QLatin1String("SELECT LASTVAL()")))
|
||||
ret = q.value(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString NSqlQuery::lastQuery() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::lastQuery();
|
||||
}
|
||||
|
||||
bool NSqlQuery::next()
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::next();
|
||||
}
|
||||
|
||||
bool NSqlQuery::nextResult()
|
||||
{
|
||||
DB_TRACE
|
||||
if (QSqlQuery::nextResult())
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
int NSqlQuery::numRowsAffected() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::numRowsAffected();
|
||||
}
|
||||
|
||||
QSql::NumericalPrecisionPolicy NSqlQuery::numericalPrecisionPolicy() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::numericalPrecisionPolicy();
|
||||
}
|
||||
|
||||
bool NSqlQuery::prepare(const QString &query)
|
||||
{
|
||||
DB_TRACE2("query: " << query)
|
||||
if (QSqlQuery::prepare(query))
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NSqlQuery::previous()
|
||||
{
|
||||
DB_TRACE
|
||||
if (QSqlQuery::previous())
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlRecord NSqlQuery::record() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::record();
|
||||
}
|
||||
|
||||
const QSqlResult *NSqlQuery::result() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::result();
|
||||
}
|
||||
|
||||
bool NSqlQuery::seek(int index, bool relative)
|
||||
{
|
||||
DB_TRACE2("index: " << index << " relative: " << relative);
|
||||
if (QSqlQuery::seek(index, relative))
|
||||
return true;
|
||||
printLastSqlError();
|
||||
return false;
|
||||
}
|
||||
|
||||
void NSqlQuery::setForwardOnly(bool forward)
|
||||
{
|
||||
DB_TRACE2("forward: " << forward);
|
||||
QSqlQuery::setForwardOnly(forward);
|
||||
}
|
||||
|
||||
void NSqlQuery::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
|
||||
{
|
||||
DB_TRACE2("precisionPolicy: " << precisionPolicy);
|
||||
QSqlQuery::setNumericalPrecisionPolicy(precisionPolicy);
|
||||
}
|
||||
|
||||
int NSqlQuery::size() const
|
||||
{
|
||||
DB_TRACE
|
||||
return QSqlQuery::size();
|
||||
}
|
||||
|
||||
QVariant NSqlQuery::value(int index) const
|
||||
{
|
||||
DB_TRACE2("index: " << index)
|
||||
return QSqlQuery::value(index);
|
||||
}
|
||||
|
||||
NSqlQuery &NSqlQuery::operator= (const NSqlQuery &other)
|
||||
{
|
||||
DB_TRACE
|
||||
QSqlQuery::operator= (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool NSqlQuery::export2CSV(const QString &filename)
|
||||
{
|
||||
DB_TRACE2("export csv to file: " << filename)
|
||||
QFile data(filename);
|
||||
QTextStream output(&data);
|
||||
if (data.open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
if (isSelect() && isActive())
|
||||
{
|
||||
bool isHeaderWritten = false;
|
||||
while (next())
|
||||
{
|
||||
QSqlRecord rec = record();
|
||||
if (!isHeaderWritten)
|
||||
{
|
||||
for (int i = 0; i < rec.count(); ++i)
|
||||
output << QLatin1Char('\"') + rec.fieldName(i) + QLatin1String("\",");
|
||||
output << QLatin1Char('\n');
|
||||
isHeaderWritten = true;
|
||||
}
|
||||
for (int i = 0; i < rec.count(); ++i)
|
||||
output << QLatin1Char('\"') + rec.value(i).toString() + QLatin1String("\",");
|
||||
output << QLatin1Char('\n');
|
||||
}
|
||||
}
|
||||
data.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant NSqlQuery::qDateTimeToQVariant(const QDateTime &dt)
|
||||
{
|
||||
if (dt.isValid())
|
||||
return dt.toMSecsSinceEpoch();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QDateTime NSqlQuery::qVariantToQDateTime(const QVariant &var)
|
||||
{
|
||||
if (var.isNull())
|
||||
return QDateTime();
|
||||
return QDateTime::fromMSecsSinceEpoch(var.toLongLong());
|
||||
}
|
||||
|
||||
QString NSqlQuery::qVariantToJsonString(const QVariant &value)
|
||||
{
|
||||
if (value.isNull())
|
||||
return QStringLiteral("{}");
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
QString NSqlQuery::jsonValueToJsonString(const QJsonValue &value)
|
||||
{
|
||||
if (value.isNull())
|
||||
return QStringLiteral("{}");
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
void NSqlQuery::printLastSqlError()
|
||||
{
|
||||
ERROR_LOG(mLogger) << getSqlErrorString(lastError()) << " " << lastQuery();
|
||||
}
|
||||
|
||||
QString NSqlQuery::getLastSqlError()
|
||||
{
|
||||
return (getSqlErrorString(lastError()) + QLatin1Char(' ') + lastQuery());
|
||||
}
|
||||
Executable
+222
@@ -0,0 +1,222 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtSql/QSqlQuery>
|
||||
|
||||
#include "ngldb_export.h"
|
||||
#include "dbcommon.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
class QDateTime;
|
||||
class QJsonValue;
|
||||
|
||||
|
||||
|
||||
class NGLDB_EXPORT NSqlQuery final : public QSqlQuery
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
explicit NSqlQuery(const QSqlDatabase &db);
|
||||
explicit NSqlQuery(const QSqlDatabase &db, NGL::INGLLogger &logger);
|
||||
explicit NSqlQuery(const QString &query, const QSqlDatabase &db);
|
||||
explicit NSqlQuery(const QString &query, const QSqlDatabase &db, NGL::INGLLogger &logger);
|
||||
|
||||
|
||||
|
||||
NSqlQuery(const NSqlQuery &other) = default;
|
||||
|
||||
|
||||
|
||||
~NSqlQuery() = default;
|
||||
|
||||
|
||||
|
||||
void addBindValue(const QVariant &val, QSql::ParamType paramType = QSql::In);
|
||||
|
||||
|
||||
|
||||
int at() const;
|
||||
|
||||
|
||||
|
||||
void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In);
|
||||
|
||||
|
||||
|
||||
void bindValue(int pos, const QVariant &val, QSql::ParamType paramType = QSql::In);
|
||||
|
||||
|
||||
|
||||
QVariant boundValue(const QString &placeholder) const;
|
||||
|
||||
|
||||
|
||||
QVariant boundValue(int pos) const;
|
||||
|
||||
|
||||
|
||||
QMap<QString, QVariant> boundValues() const;
|
||||
|
||||
|
||||
|
||||
void clear();
|
||||
|
||||
|
||||
|
||||
const QSqlDriver *driver() const;
|
||||
|
||||
|
||||
|
||||
bool exec(const QString &query, bool bEmitMessageOnError = true);
|
||||
|
||||
|
||||
|
||||
bool exec(bool bEmitMessageOnError = true);
|
||||
|
||||
|
||||
|
||||
bool execAndFetch();
|
||||
|
||||
|
||||
|
||||
bool execAndFetch(const QString &query);
|
||||
|
||||
|
||||
|
||||
bool execBatch(BatchExecutionMode mode = ValuesAsRows);
|
||||
|
||||
|
||||
|
||||
QString executedQuery() const;
|
||||
|
||||
|
||||
|
||||
void finish();
|
||||
|
||||
|
||||
|
||||
bool first();
|
||||
|
||||
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
|
||||
|
||||
bool isForwardOnly() const;
|
||||
|
||||
|
||||
|
||||
bool isNull(int field) const;
|
||||
|
||||
|
||||
|
||||
bool isSelect() const;
|
||||
|
||||
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
|
||||
|
||||
bool last();
|
||||
|
||||
|
||||
|
||||
QSqlError lastError() const;
|
||||
|
||||
QString sqlstate();
|
||||
|
||||
|
||||
QVariant lastInsertId();
|
||||
|
||||
|
||||
|
||||
QString lastQuery() const;
|
||||
|
||||
|
||||
|
||||
bool next();
|
||||
|
||||
|
||||
|
||||
bool nextResult();
|
||||
|
||||
|
||||
|
||||
int numRowsAffected() const;
|
||||
|
||||
|
||||
|
||||
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
|
||||
|
||||
|
||||
|
||||
bool prepare(const QString &query);
|
||||
|
||||
|
||||
|
||||
bool previous();
|
||||
|
||||
|
||||
|
||||
QSqlRecord record() const;
|
||||
|
||||
|
||||
|
||||
const QSqlResult *result() const;
|
||||
|
||||
|
||||
|
||||
bool seek(int index, bool relative = false);
|
||||
|
||||
|
||||
|
||||
void setForwardOnly(bool forward);
|
||||
|
||||
|
||||
|
||||
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy);
|
||||
|
||||
|
||||
|
||||
int size() const;
|
||||
|
||||
|
||||
|
||||
QVariant value(int index) const;
|
||||
|
||||
|
||||
|
||||
NSqlQuery &operator= (const NSqlQuery &other);
|
||||
|
||||
bool export2CSV(const QString &filename);
|
||||
|
||||
|
||||
|
||||
static QVariant qDateTimeToQVariant(const QDateTime &dt);
|
||||
|
||||
|
||||
static QDateTime qVariantToQDateTime(const QVariant &var);
|
||||
|
||||
|
||||
static QString qVariantToJsonString(const QVariant &value);
|
||||
|
||||
|
||||
static QString jsonValueToJsonString(const QJsonValue &value);
|
||||
|
||||
static inline QString fixupEmptyJsonString(const QString &str) { return str.isEmpty() ? QLatin1String("{}") : str; }
|
||||
|
||||
QString getLastSqlError();
|
||||
|
||||
private:
|
||||
void printLastSqlError();
|
||||
QSqlDatabase m_db;
|
||||
NGL::INGLLogger &mLogger;
|
||||
};
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
|
||||
#include "sql_query_janitor.h"
|
||||
#include "nsqlquery.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
|
||||
SqlQueryJanitor::SqlQueryJanitor(NSqlQuery *query)
|
||||
: m_query(query)
|
||||
{
|
||||
Q_ASSERT(m_query);
|
||||
Q_ASSERT(!m_query->isActive());
|
||||
}
|
||||
|
||||
SqlQueryJanitor::SqlQueryJanitor(const std::unique_ptr<NSqlQuery> &query)
|
||||
: SqlQueryJanitor(query.get())
|
||||
{
|
||||
}
|
||||
|
||||
SqlQueryJanitor::~SqlQueryJanitor()
|
||||
{
|
||||
m_query->finish();
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngldb_export.h"
|
||||
#include <memory>
|
||||
|
||||
class NSqlQuery;
|
||||
|
||||
|
||||
|
||||
class NGLDB_EXPORT SqlQueryJanitor
|
||||
{
|
||||
public:
|
||||
explicit SqlQueryJanitor(NSqlQuery *query);
|
||||
explicit SqlQueryJanitor(const std::unique_ptr<NSqlQuery> &query);
|
||||
~SqlQueryJanitor();
|
||||
|
||||
private:
|
||||
NSqlQuery *m_query;
|
||||
};
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# CMake Script für nglsettings
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(nglsettings_SRCS
|
||||
nglsettings_connections.cpp
|
||||
nglsettings_settings.cpp
|
||||
)
|
||||
|
||||
SET(nglsettings_HDRS
|
||||
nglsettings_connections.h
|
||||
nglsettings_export.h
|
||||
nglsettings_settings.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(ALL nglsettings SHARED ${nglsettings_SRCS} ${nglsettings_HDRS})
|
||||
NGL_TARGET_LINK_LIBRARIES(nglsettings
|
||||
PRIVATE
|
||||
ngltools
|
||||
Qt5::Network
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(nglsettings
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_INSTALL_TARGET(nglsettings)
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
|
||||
|
||||
#include "nglsettings_connections.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
#include <QSettings>
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
namespace Connections
|
||||
{
|
||||
enum class eHostConfig
|
||||
{
|
||||
public_local,
|
||||
localhost,
|
||||
server,
|
||||
server_avs
|
||||
};
|
||||
struct configStruct
|
||||
{
|
||||
eHostConfig host;
|
||||
unsigned short port;
|
||||
QString name;
|
||||
};
|
||||
|
||||
static QMap<eConnection, configStruct> *s_config = nullptr;
|
||||
static QSettings *s_settings = nullptr;
|
||||
static unsigned short s_portOffset = 9000;
|
||||
static QString *s_serverHostname = nullptr;
|
||||
|
||||
static void cleanupSettings()
|
||||
{
|
||||
delete s_settings;
|
||||
s_settings = nullptr;
|
||||
delete s_serverHostname;
|
||||
s_serverHostname = nullptr;
|
||||
delete s_config;
|
||||
s_config = nullptr;
|
||||
}
|
||||
|
||||
static void insertConfig(eConnection conn, eHostConfig host, unsigned short port, const char *name)
|
||||
{
|
||||
if (!s_config)
|
||||
s_config = new QMap<eConnection, configStruct>();
|
||||
configStruct s;
|
||||
s.host = host;
|
||||
s.port = port;
|
||||
s.name = QString::fromLatin1(name);
|
||||
s_config->insert(conn, s);
|
||||
}
|
||||
|
||||
static void initConfig()
|
||||
{
|
||||
if (s_config && !s_config->isEmpty())
|
||||
return;
|
||||
|
||||
insertConfig(eConnection::AVS_WORKSTATION, eHostConfig::localhost, 6370, "AVS_WORKSTATION");
|
||||
insertConfig(eConnection::AVS_WORKSTATION_VD, eHostConfig::localhost, 6380, "AVS_WORKSTATION_VD");
|
||||
insertConfig(eConnection::AVS_ROOT, eHostConfig::server_avs, 6350, "AVS_ROOT");
|
||||
insertConfig(eConnection::AVS_FM, eHostConfig::server_avs, 6360, "AVS_FM");
|
||||
insertConfig(eConnection::AVS_MOTION_RECORDER, eHostConfig::server_avs, 6390, "AVS_MOTION_RECORDER");
|
||||
insertConfig(eConnection::AVS_AVA, eHostConfig::server_avs, 6391, "AVS_AVA");
|
||||
|
||||
insertConfig(eConnection::PWS_WEBSOCKET, eHostConfig::server, 5701, "PWS_WEBSOCKET");
|
||||
insertConfig(eConnection::SCM_WEBSOCKET, eHostConfig::server, 7300, "SCM_WEBSOCKET");
|
||||
insertConfig(eConnection::ISM_WEBSOCKET, eHostConfig::server, 2080, "ISM_WEBSOCKET");
|
||||
insertConfig(eConnection::FLM_THP_SERVER, eHostConfig::server, 2090, "FLM_THP_SERVER");
|
||||
insertConfig(eConnection::FLM_PDF_SERVER, eHostConfig::server, 3000, "FLM_PDF_SERVER");
|
||||
|
||||
insertConfig(eConnection::LVS, eHostConfig::server, 94, "LVS");
|
||||
insertConfig(eConnection::ZWLVSV, eHostConfig::server, 95, "ZWLVSV");
|
||||
insertConfig(eConnection::ZWLVWCS, eHostConfig::server, 97, "ZWLVWCS");
|
||||
insertConfig(eConnection::ZWLVWMS, eHostConfig::server, 98, "ZWLVWMS");
|
||||
insertConfig(eConnection::ZSLV, eHostConfig::server, 99, "ZSLV");
|
||||
}
|
||||
|
||||
void setIniFile(const QString &iniFileName)
|
||||
{
|
||||
if (!s_settings)
|
||||
qAddPostRoutine(cleanupSettings);
|
||||
delete s_settings;
|
||||
s_settings = new QSettings(iniFileName, QSettings::IniFormat);
|
||||
}
|
||||
|
||||
QString iniFile()
|
||||
{
|
||||
return s_settings ? s_settings->fileName() : QString();
|
||||
}
|
||||
|
||||
unsigned short portOffset()
|
||||
{
|
||||
return s_portOffset;
|
||||
}
|
||||
|
||||
void setPortOffset(unsigned short portOffset)
|
||||
{
|
||||
s_portOffset = portOffset;
|
||||
}
|
||||
|
||||
unsigned short port(eConnection connection)
|
||||
{
|
||||
initConfig();
|
||||
unsigned short port = s_config->value(connection).port;
|
||||
|
||||
if (s_settings)
|
||||
{
|
||||
bool bOk;
|
||||
QString key = s_config->value(connection).name + QLatin1String("/port");
|
||||
unsigned short port2 = s_settings->value(key, port).toString().toUShort(&bOk);
|
||||
if (bOk)
|
||||
port = port2;
|
||||
}
|
||||
if (port < 100)
|
||||
return portOffset() + port;
|
||||
return port;
|
||||
}
|
||||
|
||||
QString hostName(eConnection connection)
|
||||
{
|
||||
initConfig();
|
||||
|
||||
QString host;
|
||||
switch (s_config->value(connection).host)
|
||||
{
|
||||
case eHostConfig::public_local:
|
||||
host = QString::fromLocal8Bit(qgetenv("HOST"));
|
||||
break;
|
||||
case eHostConfig::localhost:
|
||||
host = QLatin1String("127.0.0.1");
|
||||
break;
|
||||
case eHostConfig::server:
|
||||
if (s_serverHostname)
|
||||
host = *s_serverHostname;
|
||||
if (host.isEmpty())
|
||||
host = QLatin1String("EXCTDS01");
|
||||
break;
|
||||
case eHostConfig::server_avs:
|
||||
host = QStringLiteral("EXCAVS01");
|
||||
break;
|
||||
}
|
||||
if (s_settings)
|
||||
{
|
||||
QString key = s_config->value(connection).name + QLatin1String("/host");
|
||||
QString host2 = s_settings->value(key, host).toString();
|
||||
if (!host2.isEmpty())
|
||||
host = host2;
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
void setServerHostname(const QString &serverHostName)
|
||||
{
|
||||
if (!s_serverHostname)
|
||||
s_serverHostname = new QString(serverHostName);
|
||||
else
|
||||
*s_serverHostname = serverHostName;
|
||||
}
|
||||
|
||||
QString connectionName(eConnection connection)
|
||||
{
|
||||
if (s_config)
|
||||
{
|
||||
auto it = s_config->constFind(connection);
|
||||
if (it != s_config->constEnd())
|
||||
return it.value().name;
|
||||
}
|
||||
return QString::number((int)connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include "nglsettings_export.h"
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
|
||||
namespace Connections
|
||||
{
|
||||
|
||||
|
||||
enum class eConnection
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
AVS_WORKSTATION,
|
||||
AVS_WORKSTATION_VD,
|
||||
AVS_ROOT,
|
||||
AVS_FM,
|
||||
AVS_MOTION_RECORDER,
|
||||
AVS_AVA,
|
||||
ZWLVSV,
|
||||
ZSLV,
|
||||
ZWLVWCS,
|
||||
ZWLVWMS,
|
||||
PWS_WEBSOCKET,
|
||||
SCM_WEBSOCKET,
|
||||
ISM_WEBSOCKET,
|
||||
FLM_THP_SERVER,
|
||||
FLM_PDF_SERVER,
|
||||
LVS ,
|
||||
};
|
||||
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT void setIniFile(const QString &iniFileName);
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT QString iniFile();
|
||||
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT unsigned short portOffset();
|
||||
void setPortOffset(unsigned short portOffset);
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT unsigned short port(eConnection connection);
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT QString hostName(eConnection connection);
|
||||
void setServerHostname(const QString &serverHostName);
|
||||
|
||||
|
||||
NGLSETTINGS_EXPORT QString connectionName(eConnection connection);
|
||||
}
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef NGLSETTINGS_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLSETTINGS_EXPORT
|
||||
# else
|
||||
# ifdef MAKE_NGLSETTINGS_LIB
|
||||
# define NGLSETTINGS_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define NGLSETTINGS_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
Executable
+320
@@ -0,0 +1,320 @@
|
||||
|
||||
|
||||
#include "nglsettings_settings.h"
|
||||
#include "nglsettings_connections.h"
|
||||
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QSize>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
QSettings *Settings::s_globalSettings = nullptr;
|
||||
|
||||
Settings::Settings(const QString &iniFile_)
|
||||
: m_settings(nullptr)
|
||||
{
|
||||
QString iniFile = iniFile_;
|
||||
if(iniFile == QLatin1String("gfs_ws.ini")) {
|
||||
const QByteArray defUser = qgetenv("USER");
|
||||
if( defUser == "ctc_aar" || defUser == "ctc_rbf" ) {
|
||||
QByteArray home = qgetenv("HOME");
|
||||
if(!home.isEmpty()) {
|
||||
QString fn = QString::fromLocal8Bit(home) +
|
||||
QLatin1String("/gfs_") +
|
||||
QString::fromLocal8Bit(defUser.mid(4)) +
|
||||
QLatin1String(".ini");
|
||||
QFileInfo fi(fn);
|
||||
if(fi.exists() && fi.isFile() && fi.isReadable()) {
|
||||
iniFile = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initializeGlobalSettings();
|
||||
|
||||
initPre();
|
||||
if(!iniFile.isEmpty()) {
|
||||
if(QFileInfo(iniFile).isAbsolute())
|
||||
m_settings = new QSettings(iniFile, QSettings::IniFormat);
|
||||
else
|
||||
m_settings = new QSettings(basePath() + iniFile, QSettings::IniFormat);
|
||||
initPost();
|
||||
}
|
||||
|
||||
if (!m_settings)
|
||||
m_settings = new QSettings(QLatin1String("RDE"));
|
||||
}
|
||||
|
||||
Settings::Settings(const QString &organization, const QString &application)
|
||||
: m_settings(new QSettings(organization, application))
|
||||
{
|
||||
initPre();
|
||||
initPost();
|
||||
}
|
||||
|
||||
Settings::~Settings()
|
||||
{
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
void Settings::initializeGlobalSettings()
|
||||
{
|
||||
if (s_globalSettings)
|
||||
return;
|
||||
|
||||
if (!s_globalSettings)
|
||||
{
|
||||
QString globalSettingsFile = NGL::findProjectConfigFile();
|
||||
|
||||
|
||||
if (!globalSettingsFile.isEmpty())
|
||||
s_globalSettings = new QSettings(globalSettingsFile, QSettings::IniFormat);
|
||||
}
|
||||
if (!s_globalSettings)
|
||||
s_globalSettings = new QSettings(QLatin1String("RDE"), QLatin1String("LTS-CC"));
|
||||
Connections::setPortOffset(portOffset());
|
||||
Connections::setServerHostname(serverHostname());
|
||||
}
|
||||
|
||||
QString Settings::globalSectionName()
|
||||
{
|
||||
QString secName = QLatin1String("Global");
|
||||
static const char envGlobSecName[] = "LTS_CONF_GLOBAL_SECTION_NAME";
|
||||
if (qEnvironmentVariableIsSet(envGlobSecName))
|
||||
secName = QString::fromLocal8Bit(qgetenv(envGlobSecName));
|
||||
|
||||
return secName;
|
||||
}
|
||||
|
||||
QString Settings::basePath() const
|
||||
{
|
||||
return m_paths["GFS_PATH"];
|
||||
}
|
||||
|
||||
QString Settings::tempPath() const
|
||||
{
|
||||
return m_paths["TMP_PATH"];
|
||||
}
|
||||
|
||||
QString Settings::printPath()
|
||||
{
|
||||
return getDirectory("PDF", tempPath());
|
||||
}
|
||||
|
||||
QString Settings::logoProject()
|
||||
{
|
||||
return QLatin1String(":project/logo.png");
|
||||
}
|
||||
|
||||
QString Settings::bitmapPath()
|
||||
{
|
||||
return getDirectory("BITMAPS", basePath() + QLatin1String("DATA"));
|
||||
}
|
||||
|
||||
QString Settings::zsks_rxPath()
|
||||
{
|
||||
return getDirectory("ZSKS_RX", tempPath());
|
||||
}
|
||||
|
||||
QString Settings::zsks_txPath()
|
||||
{
|
||||
return getDirectory("ZSKS_TX", tempPath());
|
||||
}
|
||||
|
||||
QString Settings::aarServerPath(int exerciseId)
|
||||
{
|
||||
return getDirectory(QByteArray::number(exerciseId), QString::fromLocal8Bit("/data/aar/"));
|
||||
}
|
||||
|
||||
bool Settings::isDatabaseConnectionLocal()
|
||||
{
|
||||
return (databaseHostname() == QStringLiteral("localhost"));
|
||||
}
|
||||
|
||||
QString Settings::databaseName()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
|
||||
return s_globalSettings->value(globalSectionName()+ QLatin1String("/DatabaseName"), QLatin1String("lts_ets_pro")).toString();
|
||||
}
|
||||
|
||||
QString Settings::databaseHostname()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
return s_globalSettings->value(QLatin1String("Global/DatabaseHostname"), QLatin1String("EXCDBS01")).toString();
|
||||
}
|
||||
|
||||
QString Settings::databaseUser()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QByteArray defUser = qgetenv("USERNAME");
|
||||
#else
|
||||
QByteArray defUser = qgetenv("USER");
|
||||
#endif
|
||||
QString ret = m_settings->value(QLatin1String("db/user"), QString::fromLocal8Bit(defUser)).toString();
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Settings::databasePassword(const QString &databaseUser)
|
||||
{
|
||||
QString defaultPw = QStringLiteral("ctc11de");
|
||||
if (!databaseUser.isEmpty())
|
||||
{
|
||||
const QVector<QStringRef> &sl = databaseUser.splitRef(QLatin1Char('_'));
|
||||
if (sl.size() > 1)
|
||||
defaultPw = sl.at(0).toString() + QStringLiteral("11de");
|
||||
}
|
||||
return m_settings->value(QLatin1String("db/passwd"), defaultPw).toString();
|
||||
}
|
||||
|
||||
QString Settings::databaseDriver()
|
||||
{
|
||||
return m_settings->value(QLatin1String("db/driver"), QLatin1String("QPSQL")).toString();
|
||||
}
|
||||
|
||||
int Settings::avsKeepAliveTimeout()
|
||||
{
|
||||
return m_settings->value(QLatin1String("avs/keepalivetimeout"), 20000).toInt();
|
||||
}
|
||||
|
||||
QString Settings::avsServerHost()
|
||||
{
|
||||
return m_settings->value(QLatin1String("avs/serverhost"), QLatin1String("EXCAVS01")).toString();
|
||||
}
|
||||
|
||||
quint16 Settings::avsServerPortAVE()
|
||||
{
|
||||
static const quint16 defaultPort = 6350;
|
||||
bool bOk;
|
||||
quint16 ret = m_settings->value(QLatin1String("avs/serverport_ave"), defaultPort).toUInt(&bOk);
|
||||
return bOk ? ret : defaultPort;
|
||||
}
|
||||
|
||||
QSettings *Settings::settings()
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
const QSettings *Settings::settings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
QString Settings::fixupPath(const QString &_path) const
|
||||
{
|
||||
QString path = QDir::fromNativeSeparators(_path);
|
||||
if(!QDir::isAbsolutePath(path))
|
||||
path = basePath() + path;
|
||||
path = QDir::cleanPath(path);
|
||||
if(!path.endsWith(QLatin1Char('/')))
|
||||
path += QLatin1Char('/');
|
||||
return path;
|
||||
}
|
||||
|
||||
QString Settings::getDirectory(const QByteArray &_dir, const QString &defPrefix, bool bPathLowercase)
|
||||
{
|
||||
if(m_paths[_dir].isEmpty()) {
|
||||
const QString lowerDir = QString::fromLatin1(_dir.toLower());
|
||||
const QString dir = bPathLowercase ? lowerDir : QString::fromLatin1(_dir);
|
||||
QString def = defPrefix + QLatin1Char('/') + dir + QLatin1Char('/');
|
||||
m_paths[_dir] = fixupPath(m_settings->value(QLatin1String("paths/") + lowerDir, def).toString());
|
||||
QDir d(m_paths[_dir]);
|
||||
if(!d.exists())
|
||||
d.mkpath(d.absolutePath());
|
||||
}
|
||||
return m_paths[_dir];
|
||||
}
|
||||
|
||||
void Settings::initPre()
|
||||
{
|
||||
#ifdef WIN32
|
||||
QString path = QString::fromLocal8Bit(qgetenv("GFS_PATH"));
|
||||
if(path.isEmpty())
|
||||
path = QCoreApplication::applicationDirPath();
|
||||
m_paths["GFS_PATH"] = fixupPath(path);
|
||||
#else
|
||||
QByteArray path = qgetenv("GFS_PATH");
|
||||
if(path.isEmpty())
|
||||
path = qgetenv("HOME");
|
||||
m_paths["GFS_PATH"] = fixupPath(QString::fromLocal8Bit(path));
|
||||
#endif
|
||||
|
||||
QByteArray tmppath = qgetenv("TMP_PATH");
|
||||
if(tmppath.isEmpty())
|
||||
tmppath = qgetenv("TMP");
|
||||
if (tmppath.isEmpty())
|
||||
tmppath = QDir::tempPath().toLocal8Bit();
|
||||
m_paths["TMP_PATH"] = fixupPath(QString::fromLocal8Bit(tmppath));
|
||||
}
|
||||
|
||||
void Settings::initPost()
|
||||
{
|
||||
NGL::Connections::setIniFile(m_settings->fileName());
|
||||
}
|
||||
|
||||
int Settings::getInteger(const QString &key, int defVal) const
|
||||
{
|
||||
bool bOk;
|
||||
int ret = m_settings->value(key, defVal).toInt(&bOk);
|
||||
return bOk ? ret : defVal;
|
||||
}
|
||||
|
||||
float Settings::getFloat(const QString &key, float defVal) const
|
||||
{
|
||||
bool bOk;
|
||||
float ret = m_settings->value(key, defVal).toFloat(&bOk);
|
||||
return bOk ? ret : defVal;
|
||||
}
|
||||
|
||||
double Settings::getDouble(const QString &key, double defVal) const
|
||||
{
|
||||
bool bOk;
|
||||
double ret = m_settings->value(key, defVal).toDouble(&bOk);
|
||||
return bOk ? ret : defVal;
|
||||
}
|
||||
|
||||
bool Settings::getBoolean(const QString &key, bool defVal) const
|
||||
{
|
||||
return m_settings->value(key, defVal).toBool();
|
||||
}
|
||||
|
||||
QString Settings::getString(const QString &key, const QString &defVal) const
|
||||
{
|
||||
return m_settings->value(key, defVal).toString();
|
||||
}
|
||||
|
||||
unsigned short Settings::domainId()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
return s_globalSettings->value(QLatin1String("Global/DomainId"), 0).toUInt();
|
||||
}
|
||||
|
||||
unsigned short Settings::portOffset()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
return s_globalSettings->value(QLatin1String("Global/PortOffset"), 9000).toUInt();
|
||||
}
|
||||
|
||||
QString Settings::serverHostname()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
return s_globalSettings->value(QLatin1String("Global/ServerHostname"), QLatin1String("EXCTDS01")).toString();
|
||||
}
|
||||
|
||||
QString Settings::logPath()
|
||||
{
|
||||
initializeGlobalSettings();
|
||||
#ifdef WIN32
|
||||
return s_globalSettings->value(QLatin1String("Global/LogPath"), QStandardPaths::writableLocation(QStandardPaths::TempLocation)).toString();
|
||||
#else
|
||||
return s_globalSettings->value(QLatin1String("Global/LogPath"), QLatin1String("/shd/CTC/LOG")).toString();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+142
@@ -0,0 +1,142 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QHash>
|
||||
#include "nglsettings_export.h"
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace NGL {
|
||||
|
||||
|
||||
class NGLSETTINGS_EXPORT Settings {
|
||||
public:
|
||||
|
||||
|
||||
explicit Settings(const QString &iniFile);
|
||||
|
||||
|
||||
|
||||
explicit Settings(const QString &organization, const QString &application);
|
||||
|
||||
Settings(const Settings&) = delete;
|
||||
Settings &operator=(const Settings&) = delete;
|
||||
|
||||
|
||||
|
||||
virtual ~Settings();
|
||||
|
||||
|
||||
static void initializeGlobalSettings();
|
||||
|
||||
|
||||
QString basePath() const;
|
||||
|
||||
QString tempPath() const;
|
||||
|
||||
QString printPath();
|
||||
|
||||
QString logoProject();
|
||||
|
||||
QString bitmapPath();
|
||||
|
||||
|
||||
|
||||
QString zsks_rxPath();
|
||||
|
||||
QString zsks_txPath();
|
||||
|
||||
|
||||
|
||||
static QString databaseName();
|
||||
|
||||
static QString databaseHostname();
|
||||
|
||||
QString databaseUser();
|
||||
|
||||
QString databasePassword(const QString &databaseUser = QString());
|
||||
|
||||
QString databaseDriver();
|
||||
|
||||
|
||||
|
||||
QString aarServerPath(int exerciseId);
|
||||
bool isDatabaseConnectionLocal();
|
||||
|
||||
|
||||
int avsKeepAliveTimeout();
|
||||
QString avsServerHost();
|
||||
quint16 avsServerPortAVE();
|
||||
|
||||
|
||||
QSettings *settings();
|
||||
|
||||
const QSettings *settings() const;
|
||||
|
||||
|
||||
int getInteger(const QString &key, int defVal) const;
|
||||
|
||||
|
||||
int getInteger(const QString &group, const QString &key, int defVal) const
|
||||
{
|
||||
return getInteger(group + QLatin1Char('/') + key, defVal);
|
||||
}
|
||||
|
||||
|
||||
float getFloat(const QString &key, float defVal) const;
|
||||
|
||||
|
||||
float getFloat(const QString &group, const QString &key, float defVal) const
|
||||
{
|
||||
return getFloat(group + QLatin1Char('/') + key, defVal);
|
||||
}
|
||||
|
||||
|
||||
double getDouble(const QString &key, double defVal) const;
|
||||
|
||||
|
||||
double getDouble(const QString &group, const QString &key, double defVal) const
|
||||
{
|
||||
return getDouble(group + QLatin1Char('/') + key, defVal);
|
||||
}
|
||||
|
||||
|
||||
bool getBoolean(const QString &key, bool defVal) const;
|
||||
|
||||
|
||||
bool getBoolean(const QString &group, const QString &key, bool defVal) const
|
||||
{
|
||||
return getBoolean(group + QLatin1Char('/') + key, defVal);
|
||||
}
|
||||
|
||||
|
||||
QString getString(const QString &key, const QString &defVal) const;
|
||||
|
||||
|
||||
QString getString(const QString &group, const QString &key, const QString &defVal) const
|
||||
{
|
||||
return getString(group + QLatin1Char('/') + key, defVal);
|
||||
}
|
||||
|
||||
static unsigned short portOffset();
|
||||
static unsigned short domainId();
|
||||
static QString serverHostname();
|
||||
static QString logPath();
|
||||
static QString globalSectionName();
|
||||
|
||||
private:
|
||||
|
||||
QString fixupPath(const QString &path) const;
|
||||
|
||||
|
||||
QString getDirectory(const QByteArray &dir, const QString &defPrefix, bool bPathLowercase = false);
|
||||
private:
|
||||
void initPre();
|
||||
void initPost();
|
||||
QSettings *m_settings;
|
||||
static QSettings *s_globalSettings;
|
||||
QHash<QByteArray, QString> m_paths;
|
||||
};
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# CMake Script für ngltools
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(ngltools_SRCS
|
||||
ngltools_bitset.h
|
||||
ngltools_convert.cpp
|
||||
ngltools_convert.h
|
||||
ngltools_dtg.cpp
|
||||
ngltools_dtg.h
|
||||
ngltools_export.h
|
||||
ngltools_filesystem.cpp
|
||||
ngltools_filesystem.h
|
||||
ngltools_helpevent.cpp
|
||||
ngltools_helpevent.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(ALL ngltools SHARED ${ngltools_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(ngltools
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
NGL_TARGET_COMPILE_DEFINITIONS(ngltools PUBLIC BUILD_BASE_PATH="${CMAKE_BINARY_DIR}")
|
||||
NGL_TARGET_COMPILE_DEFINITIONS(ngltools PUBLIC INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(ngltools
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_INSTALL_TARGET(ngltools)
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace NGL {
|
||||
template<class T>
|
||||
class BitSet {
|
||||
public:
|
||||
BitSet(T bitset = T())
|
||||
: mBitSet(bitset)
|
||||
, mSize(sizeof(T)*8)
|
||||
{}
|
||||
BitSet(const BitSet<T> &other)
|
||||
: mBitSet(other.mBitSet)
|
||||
, mSize(other.mSize)
|
||||
{}
|
||||
BitSet &operator=(const BitSet<T> &other)
|
||||
{
|
||||
if(this == &other)
|
||||
return *this;
|
||||
mBitSet = other.mBitSet;
|
||||
mSize = other.mSize;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const BitSet<T> &other) const
|
||||
{
|
||||
return (mBitSet == other.mBitSet && mSize == other.mSize);
|
||||
}
|
||||
bool setBit(unsigned int bitNum)
|
||||
{
|
||||
if(bitNum >= mSize)
|
||||
return false;
|
||||
mBitSet |= getBit(bitNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clearBit(unsigned int bitNum)
|
||||
{
|
||||
if(bitNum >= mSize)
|
||||
return false;
|
||||
mBitSet &= ~(getBit(bitNum));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool at(unsigned int bitNum) const
|
||||
{
|
||||
if(bitNum >= sizeof(T) * 8)
|
||||
return false;
|
||||
T compVal = getBit(bitNum);
|
||||
return ((mBitSet & compVal) == compVal);
|
||||
}
|
||||
|
||||
bool operator[] (unsigned int bitNum) const
|
||||
{
|
||||
return at(bitNum);
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
bool resize(size_t newSize)
|
||||
{
|
||||
if(newSize >= sizeof(T) * 8)
|
||||
return false;
|
||||
for(unsigned int i = mSize; i < newSize; ++i)
|
||||
clearBit(i);
|
||||
mSize = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
fill(false);
|
||||
}
|
||||
|
||||
void fill(bool bBitsSet)
|
||||
{
|
||||
if(bBitsSet)
|
||||
mBitSet = ~T();
|
||||
else
|
||||
mBitSet = T();
|
||||
}
|
||||
|
||||
T operator()() const { return mBitSet; }
|
||||
|
||||
protected:
|
||||
static T getBit(unsigned int bitNum_)
|
||||
{
|
||||
T bitNum = bitNum_;
|
||||
const T one = 1;
|
||||
return (one << bitNum);
|
||||
}
|
||||
|
||||
T mBitSet;
|
||||
size_t mSize;
|
||||
};
|
||||
}
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#include "ngltools_convert.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
QByteArray quoteForTelnet(const QVector<QString> &sl)
|
||||
{
|
||||
QVector<QByteArray> tmp;
|
||||
tmp.reserve(sl.size());
|
||||
for (const QString &s : sl)
|
||||
tmp += s.toUtf8();
|
||||
return quoteForTelnet(tmp);
|
||||
}
|
||||
|
||||
QByteArray quoteForTelnet(const QVector<QByteArray> &sl)
|
||||
{
|
||||
QByteArray cmd;
|
||||
for (QByteArray s : sl)
|
||||
{
|
||||
s.replace('\"', "\\\"");
|
||||
if (s.contains(' '))
|
||||
s = '"' + s + '"';
|
||||
if (s.isEmpty())
|
||||
s = "\"\"";
|
||||
cmd += s + ' ';
|
||||
}
|
||||
cmd += '\n';
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
QVector<QByteArray> parseFromTelnet(const QByteArray &ba, const int iStart)
|
||||
{
|
||||
QVector<QByteArray> ret;
|
||||
const char *p = ba.constData() + iStart;
|
||||
const int iLen = ba.length();
|
||||
const char *p_end = ba.constData() + iLen;
|
||||
if (iLen <= iStart)
|
||||
return ret;
|
||||
char quoteEndChar = '"';
|
||||
|
||||
while (p < p_end && *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
++p;
|
||||
if (*p && p < p_end)
|
||||
{
|
||||
bool escaped = false;
|
||||
bool bQuoted = (*p == '\"') || (*p == '{');
|
||||
if (bQuoted)
|
||||
{
|
||||
quoteEndChar = (*p == '\"') ? '\"' : '}';
|
||||
++p;
|
||||
}
|
||||
const char *start = p;
|
||||
while (true)
|
||||
{
|
||||
while (p < p_end && *p != (bQuoted ? quoteEndChar : ' '))
|
||||
++p;
|
||||
if (bQuoted)
|
||||
{
|
||||
|
||||
if (* (p - 1) == '\\')
|
||||
{
|
||||
++p;
|
||||
escaped = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
QByteArray result = QByteArray(start, p - start).trimmed();
|
||||
if (escaped)
|
||||
{
|
||||
if (quoteEndChar == '}')
|
||||
{
|
||||
result = result.replace("\\{", "{");
|
||||
result = result.replace("\\}", "}");
|
||||
}
|
||||
else
|
||||
result = result.replace("\\\"", "\"");
|
||||
}
|
||||
ret += result;
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngltools_export.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
NGLTOOLS_EXPORT QByteArray quoteForTelnet(const QVector<QString> &sl);
|
||||
NGLTOOLS_EXPORT QByteArray quoteForTelnet(const QVector<QByteArray> &sl);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QVector<QByteArray> parseFromTelnet(const QByteArray &ba, const int iStart = 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+372
@@ -0,0 +1,372 @@
|
||||
#include "ngltools_dtg.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace DTG
|
||||
{
|
||||
|
||||
static char s_timezone = 'Z';
|
||||
static char s_userDefinedTimezone = s_timezone;
|
||||
static char s_exerciseDefaultTimezone = s_timezone;
|
||||
int timezone2Hours(char tz, bool *bOk)
|
||||
{
|
||||
if (!isTimezoneValid(tz))
|
||||
{
|
||||
if (bOk)
|
||||
*bOk = false;
|
||||
return 0;
|
||||
}
|
||||
if (bOk)
|
||||
*bOk = true;
|
||||
if (tz < 'J')
|
||||
return tz - 'A' + 1;
|
||||
if (tz < 'N')
|
||||
return tz - 'A';
|
||||
if (tz < 'Z')
|
||||
return 'Z' - tz - 13;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timezone2Secs(char tz, bool *bOk)
|
||||
{
|
||||
return 3600 * timezone2Hours(tz, bOk) ;
|
||||
}
|
||||
|
||||
|
||||
bool setTimezone(char tz, bool bUserDefinedZone)
|
||||
{
|
||||
if (!isTimezoneValid(tz))
|
||||
{
|
||||
|
||||
if (!(tz == 0 && bUserDefinedZone))
|
||||
return false;
|
||||
}
|
||||
if (bUserDefinedZone)
|
||||
s_userDefinedTimezone = tz;
|
||||
else
|
||||
s_exerciseDefaultTimezone = tz;
|
||||
|
||||
s_timezone = s_userDefinedTimezone != 0 ? s_userDefinedTimezone : s_exerciseDefaultTimezone;
|
||||
return true;
|
||||
}
|
||||
|
||||
char timezone()
|
||||
{
|
||||
return s_timezone;
|
||||
}
|
||||
char timezoneUserDefined()
|
||||
{
|
||||
return s_userDefinedTimezone;
|
||||
}
|
||||
char timezoneExerciseDefault()
|
||||
{
|
||||
return s_exerciseDefaultTimezone;
|
||||
}
|
||||
|
||||
bool isTimezoneValid(char tz)
|
||||
{
|
||||
tz = toupper(tz);
|
||||
return !(tz < 'A' || tz == 'J' || tz > 'Z');
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DateTimeType s_dateTimeType = DDMMYYYY_Z_HHMMSS;
|
||||
static DisplayFormat s_defaultDisplayFormat = Long;
|
||||
|
||||
|
||||
void setDateTimeType(DateTimeType dtType)
|
||||
{
|
||||
s_dateTimeType = dtType;
|
||||
}
|
||||
|
||||
DateTimeType dateTimeType()
|
||||
{
|
||||
return s_dateTimeType;
|
||||
}
|
||||
|
||||
void setDefaultDisplayFormat(DisplayFormat dtFormat)
|
||||
{
|
||||
s_defaultDisplayFormat = dtFormat;
|
||||
}
|
||||
|
||||
DisplayFormat defaultDisplayFormat()
|
||||
{
|
||||
return s_defaultDisplayFormat;
|
||||
}
|
||||
|
||||
QString toString(const QDateTime &dt, DisplayFormat format, DateTimeType type)
|
||||
{
|
||||
if (format == Default)
|
||||
format = s_defaultDisplayFormat;
|
||||
static const QDateTime dtNull = QDateTime::fromSecsSinceEpoch(0);
|
||||
if (!dt.isValid() || dt == dtNull)
|
||||
return QString();
|
||||
|
||||
const QDateTime dateTime = dt.toUTC().addSecs(timezone2Hours(s_timezone) * 3600);
|
||||
QString ret;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DTG:
|
||||
{
|
||||
|
||||
|
||||
|
||||
QString str1;
|
||||
|
||||
if (format == Long)
|
||||
str1 = dateTime.toString(QLatin1String("dd hhmmss"));
|
||||
else if (format == TurboLong)
|
||||
str1 = dateTime.toString(QLatin1String("dd hhmmss.z"));
|
||||
else
|
||||
{
|
||||
ret = dateTime.toString(QLatin1String("ddhhmm")) + QLatin1Char(s_timezone);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const int month = dateTime.date().month() - 1;
|
||||
const int year = dateTime.date().year() - 2000;
|
||||
ret = QStringLiteral("%1 %2 %3 %4")
|
||||
.arg(str1)
|
||||
.arg(QLatin1Char(s_timezone))
|
||||
.arg(months().at(month))
|
||||
.arg(year, 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
break;
|
||||
case DDMMYYYY_HHMMSS_Z:
|
||||
{
|
||||
if (format == Long)
|
||||
ret = dateTime.toString(QLatin1String("dd.MM.yyyy HH:mm:ss")) + QLatin1Char(s_timezone);
|
||||
else
|
||||
ret = dateTime.toString(QLatin1String("dd.MM HH:mm")) + QLatin1Char(s_timezone);
|
||||
|
||||
}
|
||||
break;
|
||||
case DDMMYYYY_Z_HHMMSS:
|
||||
if (format == Long)
|
||||
ret = dateTime.toString(QLatin1String("dd.MM.yyyy "))
|
||||
+ QLatin1Char(s_timezone)
|
||||
+ dateTime.toString(QLatin1String(" HH:mm:ss"));
|
||||
else
|
||||
ret = dateTime.toString(QLatin1String("dd.MM "))
|
||||
+ QLatin1Char(s_timezone)
|
||||
+ dateTime.toString(QLatin1String(" HH:mm"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString toStringMSec(qint64 msecSinceEpoch, DisplayFormat format)
|
||||
{
|
||||
if (msecSinceEpoch <= 0)
|
||||
return QString();
|
||||
return toString(QDateTime::fromMSecsSinceEpoch(msecSinceEpoch), format);
|
||||
}
|
||||
|
||||
|
||||
static bool check24(const QChar *input, int *output)
|
||||
{
|
||||
const int i1 = input[0].unicode() - '0';
|
||||
const int i2 = input[1].unicode() - '0';
|
||||
if (i1 > 2)
|
||||
return false;
|
||||
if (i1 == 2 && i2 > 5)
|
||||
return false;
|
||||
if (output)
|
||||
*output = i1 * 10 + i2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check31(const QChar *input, int *output = nullptr)
|
||||
{
|
||||
const int i1 = input[0].unicode() - '0';
|
||||
const int i2 = input[1].unicode() - '0';
|
||||
if (i1 > 3)
|
||||
return false;
|
||||
if (i1 == 3 && i2 > 1)
|
||||
return false;
|
||||
if (output)
|
||||
*output = i1 * 10 + i2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check60(const QChar *input, int *output)
|
||||
{
|
||||
const int i1 = input[0].unicode() - '0';
|
||||
const int i2 = input[1].unicode() - '0';
|
||||
if (i1 > 5)
|
||||
return false;
|
||||
if (output)
|
||||
*output = i1 * 10 + i2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static DTGValidation validate18(const QString &input, QDateTime &dt)
|
||||
{
|
||||
int hh, mm, ss;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (!input[i].isDigit())
|
||||
return Invalid;
|
||||
}
|
||||
if (!check31(&input.data() [0]))
|
||||
return Invalid;
|
||||
|
||||
if (input[2] != QLatin1Char(' '))
|
||||
return Invalid;
|
||||
|
||||
if (input.length() == 7)
|
||||
{
|
||||
for (int i = 3; i < 7; ++i)
|
||||
{
|
||||
if (!input[i].isDigit())
|
||||
return Invalid;
|
||||
}
|
||||
return Intermediate;
|
||||
}
|
||||
for (int i = 3; i < 9; ++i)
|
||||
{
|
||||
if (!input[i].isDigit())
|
||||
return Invalid;
|
||||
}
|
||||
if (!check24(&input.data() [3], &hh))
|
||||
return Invalid;
|
||||
if (!check60(&input.data() [5], &mm))
|
||||
return Invalid;
|
||||
if (!check60(&input.data() [7], &ss))
|
||||
return Invalid;
|
||||
|
||||
if (input[9] != QLatin1Char(' '))
|
||||
return Invalid;
|
||||
|
||||
const QChar c = input[10];
|
||||
if (c < QLatin1Char('A') || c > QLatin1Char('Z'))
|
||||
return Invalid;
|
||||
if (c == QLatin1Char('J'))
|
||||
{
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
const QString mon = input.mid(12, 3);
|
||||
int month = months().indexOf(mon);
|
||||
if (month < 0)
|
||||
{
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
for (int i = 16; i < 18; ++i)
|
||||
{
|
||||
if (!input[i].isDigit())
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
|
||||
const int day = input.leftRef(2).toInt();
|
||||
const int year = input.midRef(16, 2).toInt() + 2000;
|
||||
dt = QDateTime(QDate(year, month + 1, day), QTime(hh, mm, ss), Qt::UTC);
|
||||
if (!dt.isValid())
|
||||
{
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
dt = dt.addSecs(-timezone2Hours(c.toLatin1()) * 3600);
|
||||
|
||||
|
||||
return Acceptable;
|
||||
}
|
||||
|
||||
static DTGValidation validate7(const QString &input, QDateTime &dt)
|
||||
{
|
||||
int hh, mm;
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
if (!input[i].isDigit())
|
||||
return Invalid;
|
||||
}
|
||||
if (!check31(&input.data() [0]))
|
||||
return Invalid;
|
||||
if (!check24(&input.data() [2], &hh))
|
||||
return Invalid;
|
||||
if (!check60(&input.data() [4], &mm))
|
||||
return Invalid;
|
||||
|
||||
|
||||
const QChar c = input[6];
|
||||
if (c < QLatin1Char('A') || c > QLatin1Char('Z'))
|
||||
return Invalid;
|
||||
if (c == QLatin1Char('J'))
|
||||
{
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
|
||||
const int day = input.leftRef(2).toInt();
|
||||
const QDate curDate = QDate::currentDate();
|
||||
dt = QDateTime(QDate(curDate.year(), curDate.month(), day), QTime(hh, mm), Qt::UTC);
|
||||
if (!dt.isValid())
|
||||
{
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
dt = dt.addSecs(-timezone2Hours(c.toLatin1()) * 3600);
|
||||
|
||||
|
||||
return Acceptable;
|
||||
}
|
||||
|
||||
QDateTime fromDTGString(const QString &str, bool *bOk)
|
||||
{
|
||||
if (bOk)
|
||||
*bOk = false;
|
||||
|
||||
QDateTime dt;
|
||||
if (str.length() == 7)
|
||||
{
|
||||
DTGValidation state = validate7(str, dt);
|
||||
if (state == Acceptable && bOk)
|
||||
*bOk = true;
|
||||
}
|
||||
else if (str.length() == 18)
|
||||
{
|
||||
DTGValidation state = validate18(str, dt);
|
||||
if (state == Acceptable && bOk)
|
||||
*bOk = true;
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
DTGValidation validateString(const QString &str, QDateTime &dt)
|
||||
{
|
||||
const int len = str.length();
|
||||
if (len == 7 || len == 18)
|
||||
{
|
||||
|
||||
if (len == 18 || (str[2] == QLatin1Char(' ')))
|
||||
return validate18(str, dt);
|
||||
return validate7(str, dt);
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
QStringList months()
|
||||
{
|
||||
return {
|
||||
QLatin1String("jan"), QLatin1String("feb"), QLatin1String("mar"),
|
||||
QLatin1String("apr"), QLatin1String("may"), QLatin1String("jun"),
|
||||
QLatin1String("jul"), QLatin1String("aug"), QLatin1String("sep"),
|
||||
QLatin1String("oct"), QLatin1String("nov"), QLatin1String("dec")
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <QStringList>
|
||||
#include "ngltools_export.h"
|
||||
|
||||
class QDateTime;
|
||||
|
||||
|
||||
namespace DTG
|
||||
{
|
||||
|
||||
|
||||
|
||||
enum DateTimeType
|
||||
{
|
||||
DTG = 1,
|
||||
DDMMYYYY_HHMMSS_Z = 2,
|
||||
DDMMYYYY_Z_HHMMSS = 4
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
enum DisplayFormat
|
||||
{
|
||||
Short,
|
||||
Long,
|
||||
TurboLong,
|
||||
Default
|
||||
};
|
||||
|
||||
enum DTGValidation
|
||||
{
|
||||
Invalid,
|
||||
Intermediate,
|
||||
Acceptable
|
||||
};
|
||||
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT void setDateTimeType(DateTimeType dtType);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT DateTimeType dateTimeType();
|
||||
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT void setDefaultDisplayFormat(DisplayFormat dtFormat);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT DisplayFormat defaultDisplayFormat();
|
||||
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QString toString(const QDateTime &dt, DisplayFormat format = Default, DateTimeType = dateTimeType());
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QString toStringMSec(qint64 msecSinceEpoch, DisplayFormat format = Default);
|
||||
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QDateTime fromDTGString(const QString &str, bool *bOk = nullptr);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT DTGValidation validateString(const QString &str, QDateTime &dt);
|
||||
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT bool setTimezone(char tz, bool bUserDefinedZone);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT char timezone();
|
||||
NGLTOOLS_EXPORT char timezoneUserDefined();
|
||||
NGLTOOLS_EXPORT char timezoneExerciseDefault();
|
||||
|
||||
NGLTOOLS_EXPORT bool isTimezoneValid(char tz);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT int timezone2Hours(char tz, bool *bOk = nullptr);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT int timezone2Secs(char tz, bool *bOk = nullptr);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QStringList months();
|
||||
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NGLTOOLS_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define NGLTOOLS_EXPORT
|
||||
# else
|
||||
# ifdef WIN32
|
||||
# ifdef MAKE_NGLTOOLS_LIB
|
||||
# define NGLTOOLS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define NGLTOOLS_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define NGLTOOLS_EXPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
Executable
+289
@@ -0,0 +1,289 @@
|
||||
|
||||
|
||||
|
||||
#include "ngltools_filesystem.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
|
||||
bool removeDirContentsRecursively(const QString &d, bool bAlsoDeleteBaseDir)
|
||||
{
|
||||
|
||||
QDir dir(d);
|
||||
if (!dir.exists())
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
const QFileInfoList list = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries);
|
||||
for (const QFileInfo &fi : list)
|
||||
{
|
||||
bool ret = false;
|
||||
if (fi.isDir())
|
||||
{
|
||||
ret = removeDirContentsRecursively(fi.absoluteFilePath());
|
||||
if (!ret)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = dir.rmdir(fi.absoluteFilePath());
|
||||
if (!ret)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (fi.isFile() || fi.isSymLink())
|
||||
{
|
||||
ret = dir.remove(fi.fileName());
|
||||
if (!ret)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
success &= ret;
|
||||
}
|
||||
if (bAlsoDeleteBaseDir)
|
||||
success &= dir.rmpath(d);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool copyDirContentsToDir(const QString &source, const QString &destination, bool sourceIsRelative)
|
||||
{
|
||||
QString srcPath(source);
|
||||
|
||||
if (sourceIsRelative)
|
||||
{
|
||||
QVector<QString> pathsToSearch = directories(FileType::ConfigFile);
|
||||
pathsToSearch.append(directories(FileType::ProjectConfigFile));
|
||||
for (const QString &basePath : qAsConst(pathsToSearch))
|
||||
{
|
||||
QString absolutePath = basePath + QLatin1Char('/') + source;
|
||||
if (QDir(absolutePath).exists())
|
||||
{
|
||||
srcPath = absolutePath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (srcPath.isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir srcDir(srcPath);
|
||||
QDir dstDir(destination);
|
||||
|
||||
if (!dstDir.exists())
|
||||
{
|
||||
bool succ = dstDir.mkdir(destination);
|
||||
if (!succ)
|
||||
return false;
|
||||
}
|
||||
|
||||
const QFileInfoList dirList = srcDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
for (const QFileInfo &fi : dirList)
|
||||
{
|
||||
|
||||
if (!dstDir.exists())
|
||||
{
|
||||
bool succ = dstDir.mkdir(fi.fileName());
|
||||
if (!succ)
|
||||
return false;
|
||||
}
|
||||
bool succ = copyDirContentsToDir(fi.filePath(), dstDir.absolutePath() + QLatin1Char('/') + fi.fileName());
|
||||
if (!succ)
|
||||
return false;
|
||||
}
|
||||
|
||||
const QFileInfoList fileList = srcDir.entryInfoList(QDir::Files | QDir::Hidden);
|
||||
for (const QFileInfo &fi : fileList)
|
||||
{
|
||||
QString targetFileName = dstDir.absolutePath() + QLatin1Char('/') + fi.fileName();
|
||||
QFile targetFile(targetFileName);
|
||||
if (targetFile.exists())
|
||||
targetFile.remove();
|
||||
bool succ = QFile::copy(fi.absoluteFilePath(), targetFileName);
|
||||
if (!succ)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 getDirectorySize(const QString &dir)
|
||||
{
|
||||
QDir d(dir);
|
||||
qint64 ret = QFileInfo(dir).size();
|
||||
|
||||
const QFileInfoList dirList = d.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
const QFileInfoList fileList = d.entryInfoList(QDir::Files | QDir::Hidden);
|
||||
|
||||
for (const QFileInfo &fi : dirList)
|
||||
ret += getDirectorySize(fi.absoluteFilePath());
|
||||
|
||||
for (const QFileInfo &fi : fileList)
|
||||
ret += fi.size();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isAppInBuildBasePath()
|
||||
{
|
||||
bool ret = false;
|
||||
#ifdef BUILD_BASE_PATH
|
||||
const QString bbp(QString::fromLocal8Bit(BUILD_BASE_PATH));
|
||||
if (!bbp.isEmpty())
|
||||
ret = QCoreApplication::applicationDirPath().startsWith(bbp);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString projectConfigFileName()
|
||||
{
|
||||
return QLatin1String("lts-cc.conf");
|
||||
}
|
||||
|
||||
QString findProjectConfigFile()
|
||||
{
|
||||
return findFile(FileType::ProjectConfigFile, projectConfigFileName());
|
||||
}
|
||||
|
||||
static QString searchFileInDir(const QString &path, const QString &filename, bool bRecursive)
|
||||
{
|
||||
if (QFile::exists(path + QLatin1Char('/') + filename))
|
||||
return path + QLatin1Char('/') + filename;
|
||||
|
||||
if (!bRecursive)
|
||||
return QString();
|
||||
|
||||
const QDir d(path);
|
||||
const QStringList entryList = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
|
||||
for (const QString &entry : entryList)
|
||||
{
|
||||
const QString foundPath = searchFileInDir(path + QLatin1Char('/') + entry, filename, bRecursive);
|
||||
if (!foundPath.isEmpty())
|
||||
return foundPath;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString findFile(FileType fileType, const QString &filename)
|
||||
{
|
||||
const QFileInfo fi(filename);
|
||||
if (fi.isAbsolute())
|
||||
return fi.exists() ? filename : QString();
|
||||
const bool bRecursive = (fileType == FileType::ConfigFile);
|
||||
const QVector<QString> pathsToSearch = directories(fileType);
|
||||
for (const QString &path : pathsToSearch)
|
||||
{
|
||||
const QString foundPath = searchFileInDir(path, filename, bRecursive);
|
||||
if (!foundPath.isEmpty())
|
||||
return foundPath;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QVector<QString> directories(FileType fileType)
|
||||
{
|
||||
QVector<QString> pathsToSearch;
|
||||
switch (fileType)
|
||||
{
|
||||
case FileType::ProjectConfigFile:
|
||||
{
|
||||
#ifdef BUILD_BASE_PATH
|
||||
const QString bbp(QString::fromLocal8Bit(BUILD_BASE_PATH));
|
||||
if (!bbp.isEmpty())
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (QCoreApplication::applicationDirPath().startsWith(bbp))
|
||||
pathsToSearch += bbp;
|
||||
}
|
||||
#endif
|
||||
pathsToSearch += QDir::homePath();
|
||||
#ifdef Q_OS_UNIX
|
||||
pathsToSearch += QLatin1String("/etc");
|
||||
#else
|
||||
pathsToSearch += QStringLiteral("C:/Rheinmetall/Lts/");
|
||||
pathsToSearch += QCoreApplication::applicationDirPath();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case FileType::ConfigFile:
|
||||
{
|
||||
#ifdef BUILD_BASE_PATH
|
||||
const QString bbp(QString::fromLocal8Bit(BUILD_BASE_PATH));
|
||||
if (!bbp.isEmpty())
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (QCoreApplication::applicationDirPath().startsWith(bbp))
|
||||
pathsToSearch += bbp + QLatin1String("/share/Lts");
|
||||
}
|
||||
#endif
|
||||
pathsToSearch += QCoreApplication::applicationDirPath() + QLatin1String("/share/Lts");
|
||||
pathsToSearch += QCoreApplication::applicationDirPath() + QLatin1String("/../share/Lts");
|
||||
pathsToSearch += QDir::homePath() + QLatin1String("/share/Lts");
|
||||
#ifdef INSTALL_PREFIX
|
||||
pathsToSearch += QString::fromLocal8Bit(INSTALL_PREFIX) + QLatin1String("/share/Lts");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pathsToSearch;
|
||||
}
|
||||
QString findServiceXmlFile(const QString &serviceShortName)
|
||||
{
|
||||
return findFile(FileType::ConfigFile, serviceShortName + QLatin1String(".xml"));
|
||||
}
|
||||
|
||||
QString directory(FileType fileType, const QString &subdir)
|
||||
{
|
||||
const QVector<QString> pathsToSearch = directories(fileType);
|
||||
QFileInfo fi;
|
||||
for (const QString &path : pathsToSearch)
|
||||
{
|
||||
fi.setFile(path + QLatin1Char('/') + subdir);
|
||||
if (fi.isDir() && fi.exists() && fi.isReadable())
|
||||
return fi.absoluteFilePath() + QLatin1Char('/');
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString postgresExecutablePath(const QString &psqlProgram, QString &errStr)
|
||||
{
|
||||
errStr.clear();
|
||||
#ifdef Q_OS_LINUX
|
||||
return QStringLiteral("/usr/bin/") + psqlProgram;
|
||||
#else
|
||||
static QString s_postgresBinariesPath;
|
||||
if (s_postgresBinariesPath.isEmpty())
|
||||
{
|
||||
QSettings s(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations"), QSettings::NativeFormat);
|
||||
const QStringList installations = s.childGroups();
|
||||
if (installations.isEmpty())
|
||||
{
|
||||
errStr = QStringLiteral("Could not find a valid PostgreSQL windows installation...");
|
||||
return psqlProgram;
|
||||
}
|
||||
if (installations.size() > 1)
|
||||
errStr = QStringLiteral("More than one PostgreSQL windows installation found - using the first one: %1").arg(installations.first());
|
||||
s.beginGroup(installations.first());
|
||||
const QString baseDir = s.value(QStringLiteral("Base Directory")).toString();
|
||||
if (baseDir.isEmpty() || !QDir(baseDir).exists())
|
||||
{
|
||||
errStr = QStringLiteral("Could not find a valid PostgreSQL windows installation... - Base Directory is empty or does not exist (%1)").arg(baseDir);
|
||||
return psqlProgram;
|
||||
}
|
||||
s_postgresBinariesPath = baseDir + QStringLiteral("/bin/");
|
||||
}
|
||||
return s_postgresBinariesPath + psqlProgram + QStringLiteral(".exe");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngltools_export.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
NGLTOOLS_EXPORT bool removeDirContentsRecursively(const QString &d, bool bAlsoDeleteBaseDir = false);
|
||||
NGLTOOLS_EXPORT bool copyDirContentsToDir(const QString &source, const QString &destination, bool sourceIsRelative = false);
|
||||
NGLTOOLS_EXPORT qint64 getDirectorySize(const QString &dir);
|
||||
|
||||
|
||||
enum class FileType
|
||||
{
|
||||
ProjectConfigFile,
|
||||
ConfigFile
|
||||
};
|
||||
|
||||
NGLTOOLS_EXPORT bool isAppInBuildBasePath();
|
||||
NGLTOOLS_EXPORT QString projectConfigFileName();
|
||||
NGLTOOLS_EXPORT QString findProjectConfigFile();
|
||||
NGLTOOLS_EXPORT QString findFile(FileType fileType, const QString &filename);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QString findServiceXmlFile(const QString &serviceShortName);
|
||||
|
||||
NGLTOOLS_EXPORT QVector<QString> directories(FileType fileType);
|
||||
|
||||
NGLTOOLS_EXPORT QString directory(FileType fileType, const QString &subdir);
|
||||
|
||||
|
||||
NGLTOOLS_EXPORT QString postgresExecutablePath(const QString &psqlProgram, QString &errStr);
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
#include "ngltools_helpevent.h"
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
QEvent::Type NGLHelpEvent::sHelpEventId = (QEvent::Type)(-1);
|
||||
|
||||
void NGLHelpEvent::sendHelpEvent(const QString &helpContext)
|
||||
{
|
||||
NGLHelpEvent he(helpContext);
|
||||
QCoreApplication::sendEvent(qApp, &he);
|
||||
}
|
||||
|
||||
QEvent::Type NGLHelpEvent::helpEventId()
|
||||
{
|
||||
if(sHelpEventId < 0)
|
||||
sHelpEventId = (QEvent::Type)(QEvent::registerEventType());
|
||||
return sHelpEventId;
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
#include <QtCore/QString>
|
||||
#include "ngltools_export.h"
|
||||
|
||||
|
||||
|
||||
class NGLTOOLS_EXPORT NGLHelpEvent : public QEvent
|
||||
{
|
||||
protected:
|
||||
|
||||
|
||||
explicit NGLHelpEvent(const QString &helpContext)
|
||||
: QEvent(helpEventId())
|
||||
, mHelpContext(helpContext)
|
||||
{}
|
||||
public:
|
||||
|
||||
|
||||
QString helpContext() const { return mHelpContext; }
|
||||
|
||||
|
||||
static void sendHelpEvent(const QString &helpContext);
|
||||
|
||||
|
||||
static QEvent::Type helpEventId();
|
||||
|
||||
protected:
|
||||
QString mHelpContext;
|
||||
static QEvent::Type sHelpEventId;
|
||||
};
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# ngltranslator lib
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
SET(my_SRCS
|
||||
ngltranslator.cpp
|
||||
ngltranslator.h
|
||||
ngltranslator_export.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(ALL ngltranslator SHARED ${my_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(ngltranslator
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(ngltranslator
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
)
|
||||
NGL_INSTALL_TARGET(ngltranslator)
|
||||
Loaded 100 of 991 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user