move app to examples
@ -4,4 +4,6 @@ TaoQuick_BUILD_TREE = $$PWD/build
|
|||||||
|
|
||||||
TaoQuick_RUN_TREE = $$PWD/bin
|
TaoQuick_RUN_TREE = $$PWD/bin
|
||||||
|
|
||||||
|
TaoQuick_3RDPARTY_TREE = $$PWD/3rdparty
|
||||||
|
|
||||||
TaoQuick_VERSION_MAJOR = 0.3
|
TaoQuick_VERSION_MAJOR = 0.3
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include "Logger/logger.h"
|
||||||
namespace TaoCommon
|
namespace TaoCommon
|
||||||
{
|
{
|
||||||
static bool readFile(const QString &filePath, QByteArray &content)
|
static bool readFile(const QString &filePath, QByteArray &content)
|
||||||
@ -12,7 +13,7 @@ namespace TaoCommon
|
|||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
if (!file.open(QFile::ReadOnly))
|
if (!file.open(QFile::ReadOnly))
|
||||||
{
|
{
|
||||||
qWarning() << "open file " << filePath << "failed:" << file.errorString();
|
LOG_WARN << "open file " << filePath << "failed:" << file.errorString();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
content = file.readAll();
|
content = file.readAll();
|
||||||
@ -25,7 +26,7 @@ namespace TaoCommon
|
|||||||
doc = QJsonDocument::fromJson(data, &err);
|
doc = QJsonDocument::fromJson(data, &err);
|
||||||
if (doc.isNull())
|
if (doc.isNull())
|
||||||
{
|
{
|
||||||
qWarning() << "parse json failed:" << err.errorString();
|
LOG_WARN << "parse json failed:" << err.errorString();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -83,7 +84,7 @@ namespace TaoCommon
|
|||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
if (!file.open(QFile::WriteOnly))
|
if (!file.open(QFile::WriteOnly))
|
||||||
{
|
{
|
||||||
qWarning() << "open file " << filePath << "failed:" << file.errorString();
|
LOG_WARN << "open file " << filePath << "failed:" << file.errorString();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.write(content);
|
file.write(content);
|
125
3rdparty/TaoCommon/Common/objectmap.h
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <unordered_map>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
|
||||||
|
//对象存储器
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
class ObjectMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ObjectMap()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
void setObj(const Key &key, const Value &obj)
|
||||||
|
{
|
||||||
|
m_objMap[key] = obj;
|
||||||
|
}
|
||||||
|
Value getObj(const Key &key) const
|
||||||
|
{
|
||||||
|
auto itor = m_objMap.find(key);
|
||||||
|
if (itor == m_objMap.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return itor->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_objMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unordered_map<Key, Value> m_objMap;
|
||||||
|
};
|
||||||
|
//智能对象存储器。自动生成key,自动管理对象。
|
||||||
|
template <typename ObjectType>
|
||||||
|
class CObjectMap : public ObjectMap<std::type_index, std::shared_ptr<ObjectType>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename DeriveObjectType>
|
||||||
|
DeriveObjectType *getObject() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<ObjectType, DeriveObjectType>::value, "DeriveObjectType must be derive from ObjectType");
|
||||||
|
auto objPtr = getObj(std::type_index(typeid(std::shared_ptr<DeriveObjectType>)));
|
||||||
|
return std::static_pointer_cast<DeriveObjectType>(objPtr).get();
|
||||||
|
}
|
||||||
|
template <typename DeriveObjectType, typename... Args>
|
||||||
|
void setObject(Args &&... args)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<ObjectType, DeriveObjectType>::value, "DeriveObjectType must be derive from ObjectType");
|
||||||
|
auto obj = std::make_shared<DeriveObjectType>(std::forward(args...));
|
||||||
|
setObj(std::type_index(typeid(obj)), std::static_pointer_cast<ObjectType>(obj));
|
||||||
|
}
|
||||||
|
void forEach(const std::function<void(ObjectType *)> &callback) const
|
||||||
|
{
|
||||||
|
for (const auto &pair : m_objMap)
|
||||||
|
{
|
||||||
|
callback(pair.second.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//优先级对象存储器。自动生成key,自动管理对象。支持按优先级处理
|
||||||
|
template <typename ObjectType>
|
||||||
|
class CLevelObjectMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~CLevelObjectMap()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
template <typename DeriveObjectType>
|
||||||
|
DeriveObjectType *getObject() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<ObjectType, DeriveObjectType>::value, "DeriveObjectType must be derive from ObjectType");
|
||||||
|
auto index = std::type_index(typeid(std::shared_ptr<DeriveObjectType>));
|
||||||
|
|
||||||
|
for (const auto &mainPair : m_map)
|
||||||
|
{
|
||||||
|
const std::unordered_map<std::type_index, std::shared_ptr<ObjectType>> &subMap = mainPair.second;
|
||||||
|
|
||||||
|
auto itor = subMap.find(index);
|
||||||
|
if (itor != subMap.end())
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<DeriveObjectType>(itor->second).get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
template <typename DeriveObjectType, typename... Args>
|
||||||
|
void setObject(uint32_t level, Args &&... args)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<ObjectType, DeriveObjectType>::value, "DeriveObjectType must be derive from ObjectType");
|
||||||
|
auto obj = std::make_shared<DeriveObjectType>(args...);
|
||||||
|
m_map[level][std::type_index(typeid(obj))] = std::static_pointer_cast<ObjectType>(obj);
|
||||||
|
}
|
||||||
|
void forEach(const std::function<void(ObjectType *)> &callback) const
|
||||||
|
{
|
||||||
|
for (const auto &mainPair : m_map)
|
||||||
|
{
|
||||||
|
const std::unordered_map<std::type_index, std::shared_ptr<ObjectType>> &subMap = mainPair.second;
|
||||||
|
for (const auto &subPair : subMap)
|
||||||
|
{
|
||||||
|
callback(subPair.second.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<uint32_t, std::unordered_map<std::type_index, std::shared_ptr<ObjectType>>> m_map;
|
||||||
|
};
|
||||||
|
} // namespace TaoCommon
|
42
3rdparty/TaoCommon/Common/singleton.h
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
//单例模板
|
||||||
|
template <typename T>
|
||||||
|
class Singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static T &instance()
|
||||||
|
{
|
||||||
|
static T t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
virtual ~Singleton() {}
|
||||||
|
|
||||||
|
Singleton(const Singleton &) = delete;
|
||||||
|
Singleton &operator=(const Singleton &) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Singleton() {}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
使用示例:
|
||||||
|
|
||||||
|
定义:
|
||||||
|
class DataManager : public Singleton<DataManager>
|
||||||
|
{
|
||||||
|
friend class Singleton<DataManager>;
|
||||||
|
public:
|
||||||
|
void loadData();
|
||||||
|
protected:
|
||||||
|
DataManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
调用:
|
||||||
|
DataManager::instance().loadData();
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace TaoCommon
|
116
3rdparty/TaoCommon/Common/subject.h
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
//观察者模式,Subject-Observer。
|
||||||
|
//Subject 事件或消息的主体。模板参数为观察者类型
|
||||||
|
template <typename ObserverType>
|
||||||
|
class Subject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Subject()
|
||||||
|
{
|
||||||
|
m_obsList.clear();
|
||||||
|
}
|
||||||
|
//订阅
|
||||||
|
void subscibe(ObserverType *obs)
|
||||||
|
{
|
||||||
|
auto itor = std::find(m_obsList.begin(), m_obsList.end(), obs);
|
||||||
|
if (m_obsList.end() == itor)
|
||||||
|
{
|
||||||
|
m_obsList.push_back(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//取消订阅
|
||||||
|
void unSubscibe(ObserverType *obs)
|
||||||
|
{
|
||||||
|
m_obsList.erase(std::remove(m_obsList.begin(), m_obsList.end(), obs));
|
||||||
|
}
|
||||||
|
//发布。这里的模板参数为函数类型。
|
||||||
|
template <typename FuncType>
|
||||||
|
void publish(FuncType func)
|
||||||
|
{
|
||||||
|
for (auto obs : m_obsList)
|
||||||
|
{
|
||||||
|
//调用回调函数,将obs作为第一个参数传递
|
||||||
|
func(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//发布。支持过滤观察者。通常用在 观察者触发消息发布时,过滤观察者自己。
|
||||||
|
template <typename FuncType>
|
||||||
|
void publish(FuncType func, ObserverType *exceptObs)
|
||||||
|
{
|
||||||
|
for (auto obs : m_obsList)
|
||||||
|
{
|
||||||
|
//调用回调函数,将obs作为第一个参数传递
|
||||||
|
if (obs != exceptObs)
|
||||||
|
{
|
||||||
|
func(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ObserverType *> m_obsList;
|
||||||
|
};
|
||||||
|
|
||||||
|
//优先级观察者模式,Subject-Observer。
|
||||||
|
template <typename ObserverType>
|
||||||
|
class LevelSubject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~LevelSubject()
|
||||||
|
{
|
||||||
|
m_obsMap.clear();
|
||||||
|
}
|
||||||
|
//订阅
|
||||||
|
void subscibe(ObserverType *obs, uint32_t level)
|
||||||
|
{
|
||||||
|
auto &vec = m_obsMap[level];
|
||||||
|
auto itor = std::find(vec.begin(), vec.end(), obs);
|
||||||
|
if (vec.end() == itor)
|
||||||
|
{
|
||||||
|
vec.push_back(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//取消订阅
|
||||||
|
void unSubscibe(ObserverType *obs)
|
||||||
|
{
|
||||||
|
for (auto &obsPair : m_obsMap)
|
||||||
|
{
|
||||||
|
obsPair.second.erase(std::remove(obsPair.second.begin(), obsPair.second.end(), obs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//发布。这里的模板参数为函数类型。
|
||||||
|
template <typename FuncType>
|
||||||
|
void publish(FuncType func)
|
||||||
|
{
|
||||||
|
for (const auto &obsPair : m_obsMap)
|
||||||
|
{
|
||||||
|
for (const auto &obs : obsPair.second)
|
||||||
|
{
|
||||||
|
func(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename FuncType>
|
||||||
|
void publish(FuncType func, ObserverType *exceptObs)
|
||||||
|
{
|
||||||
|
for (const auto &obsPair : m_obsMap)
|
||||||
|
{
|
||||||
|
for (const auto &obs : obsPair.second)
|
||||||
|
{
|
||||||
|
if (obs != exceptObs)
|
||||||
|
{
|
||||||
|
func(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<uint32_t, std::vector<ObserverType *>> m_obsMap;
|
||||||
|
};
|
||||||
|
} // namespace TaoCommon
|
145
3rdparty/TaoCommon/Logger/logger.cpp
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
#include "loggertemplate.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
|
#include <cstdio>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Logger
|
||||||
|
{
|
||||||
|
static QString gLogDir;
|
||||||
|
static int gLogMaxCount;
|
||||||
|
|
||||||
|
static void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||||
|
static void outputMessageAsync(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
||||||
|
|
||||||
|
void initLog(const QString &logPath, int logMaxCount, bool async)
|
||||||
|
{
|
||||||
|
if (async)
|
||||||
|
{
|
||||||
|
qInstallMessageHandler(outputMessageAsync);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qInstallMessageHandler(outputMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
gLogDir = QCoreApplication::applicationDirPath() + QStringLiteral("/") + logPath;
|
||||||
|
gLogMaxCount = logMaxCount;
|
||||||
|
QDir dir(gLogDir);
|
||||||
|
if (!dir.exists())
|
||||||
|
{
|
||||||
|
dir.mkpath(dir.absolutePath());
|
||||||
|
}
|
||||||
|
QStringList infoList = dir.entryList(QDir::Files, QDir::Name);
|
||||||
|
while (infoList.size() > gLogMaxCount)
|
||||||
|
{
|
||||||
|
dir.remove(infoList.first());
|
||||||
|
infoList.removeFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void outputMessageAsync(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
|
{
|
||||||
|
static const QString messageTemp = QStringLiteral("<div class=\"%1\">%2</div>\r\n");
|
||||||
|
static const char typeList[] = { 'd', 'w', 'c', 'f', 'i' };
|
||||||
|
static QMutex mutex;
|
||||||
|
static QFile file;
|
||||||
|
static QTextStream textStream;
|
||||||
|
static uint count = 0;
|
||||||
|
static const uint maxCount = 512;
|
||||||
|
Q_UNUSED(context)
|
||||||
|
QDateTime dt = QDateTime::currentDateTime();
|
||||||
|
|
||||||
|
//每小时一个文件
|
||||||
|
QString fileNameDt = dt.toString(QStringLiteral("yyyy-MM-dd_hh"));
|
||||||
|
|
||||||
|
//每分钟一个文件
|
||||||
|
//QString fileNameDt = dt.toString("yyyy-MM-dd_hh_mm");
|
||||||
|
|
||||||
|
QString contentDt = dt.toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"));
|
||||||
|
QString message = QStringLiteral("%1 %2").arg(contentDt).arg(msg);
|
||||||
|
QString htmlMessage = messageTemp.arg(typeList[static_cast<int>(type)]).arg(message);
|
||||||
|
QString newfileName = QStringLiteral("%1/%2_log.html").arg(gLogDir).arg(fileNameDt);
|
||||||
|
mutex.lock();
|
||||||
|
if (file.fileName() != newfileName)
|
||||||
|
{
|
||||||
|
if (file.isOpen())
|
||||||
|
{
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
file.setFileName(newfileName);
|
||||||
|
bool exist = file.exists();
|
||||||
|
file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
|
textStream.setDevice(&file);
|
||||||
|
textStream.setCodec("UTF-8");
|
||||||
|
if (!exist)
|
||||||
|
{
|
||||||
|
textStream << logTemplate << "\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textStream << htmlMessage;
|
||||||
|
textStream.flush();
|
||||||
|
count += htmlMessage.length();
|
||||||
|
if (count >= maxCount)
|
||||||
|
{
|
||||||
|
file.close();
|
||||||
|
file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
|
}
|
||||||
|
mutex.unlock();
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
::OutputDebugString(message.toStdWString().data());
|
||||||
|
::OutputDebugString(L"\r\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, message.toStdString().data());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static void outputMessage(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||||
|
{
|
||||||
|
static const QString messageTemp = QStringLiteral("<div class=\"%1\">%2</div>\r\n");
|
||||||
|
static const char typeList[] = { 'd', 'w', 'c', 'f', 'i' };
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
Q_UNUSED(context)
|
||||||
|
QDateTime dt = QDateTime::currentDateTime();
|
||||||
|
|
||||||
|
//每小时一个文件
|
||||||
|
QString fileNameDt = dt.toString(QStringLiteral("yyyy-MM-dd_hh"));
|
||||||
|
|
||||||
|
//每分钟一个文件
|
||||||
|
//QString fileNameDt = dt.toString("yyyy-MM-dd_hh_mm");
|
||||||
|
|
||||||
|
QString contentDt = dt.toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"));
|
||||||
|
QString message = QStringLiteral("%1 %2").arg(contentDt).arg(msg);
|
||||||
|
QString htmlMessage = messageTemp.arg(typeList[static_cast<int>(type)]).arg(message);
|
||||||
|
QFile file(QStringLiteral("%1/%2_log.html").arg(gLogDir).arg(fileNameDt));
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
bool exist = file.exists();
|
||||||
|
file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
|
QTextStream textStream(&file);
|
||||||
|
textStream.setCodec("UTF-8");
|
||||||
|
if (!exist)
|
||||||
|
{
|
||||||
|
textStream << logTemplate << "\r\n";
|
||||||
|
}
|
||||||
|
textStream << htmlMessage;
|
||||||
|
file.close();
|
||||||
|
mutex.unlock();
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
::OutputDebugString(message.toStdWString().data());
|
||||||
|
::OutputDebugString(L"\r\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, message.toStdString().data());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} // namespace Logger
|
23
3rdparty/TaoCommon/Logger/logger.h
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "taocommonglobal.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QDebug>
|
||||||
|
namespace Logger
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define LOG_DEBUG qDebug() << __FILE__ << __LINE__
|
||||||
|
#define LOG_INFO qInfo() << __FILE__ << __LINE__
|
||||||
|
#define LOG_WARN qWarning() << __FILE__ << __LINE__
|
||||||
|
#define LOG_CRIT qCritical() << __FILE__ << __LINE__
|
||||||
|
#else
|
||||||
|
#define LOG_DEBUG qDebug()
|
||||||
|
#define LOG_INFO qInfo()
|
||||||
|
#define LOG_WARN qWarning()
|
||||||
|
#define LOG_CRIT qCritical()
|
||||||
|
#endif
|
||||||
|
// 初始化Log存储。包括创建Log文件夹、删除超过最大数的log(仅初始化时删除,运行过程中不删除)。
|
||||||
|
// logPath 存储路径
|
||||||
|
// logMaxCount 最大数
|
||||||
|
// async 是否异步存储 默认异步存储。异步存储会缓存log,达到一定数量、或者软件退出时才写入文件。
|
||||||
|
void TAO_API initLog(const QString &logPath = QStringLiteral("Log"), int logMaxCount = 1024, bool async = true);
|
||||||
|
} // namespace Logger
|
@ -3,13 +3,13 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
namespace Logger
|
namespace Logger
|
||||||
{
|
{
|
||||||
const static QString logTemplate = u8R"logTemplate(
|
const static auto logTemplate = QString::fromUtf8(u8R"logTemplate(
|
||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>TaoLogger</title>
|
<title>Lubansoft log file</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<style type="text/css" id="logCss">
|
<style type="text/css" id="logCss">
|
||||||
body {
|
body {
|
||||||
@ -86,7 +86,7 @@ namespace Logger
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1><a href="https://jaredtao.github.io">TaoLogger</a> 日志文件</h1>
|
<h1><a href="http://jaredtao.github.io/">TaoLogger</a> 日志文件</h1>
|
||||||
<script type="text/JavaScript">
|
<script type="text/JavaScript">
|
||||||
function objHide(obj) {
|
function objHide(obj) {
|
||||||
obj.style.display="none"
|
obj.style.display="none"
|
||||||
@ -122,5 +122,5 @@ namespace Logger
|
|||||||
<option value='c'>Critical</option>
|
<option value='c'>Critical</option>
|
||||||
<option value='f'>Fatal</option>
|
<option value='f'>Fatal</option>
|
||||||
</select>
|
</select>
|
||||||
)logTemplate";
|
)logTemplate");
|
||||||
}
|
}
|
25
3rdparty/TaoCommon/TaoCommon.pri
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
!build_TaoCommon_lib:{
|
||||||
|
DEFINES +=TaoCommon_NO_LIB
|
||||||
|
}
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD \
|
||||||
|
$$PWD/Common \
|
||||||
|
$$PWD/Logger \
|
||||||
|
$$PWD/Thread
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/Common/filereadwrite.h \
|
||||||
|
$$PWD/Common/objectmap.h \
|
||||||
|
$$PWD/Common/singleton.h \
|
||||||
|
$$PWD/Common/subject.h \
|
||||||
|
$$PWD/Logger/loggertemplate.h \
|
||||||
|
$$PWD/Logger/logger.h \
|
||||||
|
$$PWD/Thread/threadcommon.h \
|
||||||
|
$$PWD/Thread/threadpool.h \
|
||||||
|
$$PWD/Thread/threadworkercontroller.h \
|
||||||
|
$$PWD/taocommonglobal.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/Logger/logger.cpp \
|
||||||
|
$$PWD/Thread/threadpool.cpp
|
||||||
|
|
14
3rdparty/TaoCommon/TaoCommon.pro
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
TARGET = TaoCommon
|
||||||
|
|
||||||
|
load(qt_module)
|
||||||
|
|
||||||
|
QT += core
|
||||||
|
QMAKE_TARGET_COMPANY = "jaredtao.github.io"
|
||||||
|
QMAKE_TARGET_COPYRIGHT = "Copyright (C) 2019-2022 JaredTao <jared2020@163.com>"
|
||||||
|
QMAKE_TARGET_PRODUCT = "TaoCommon"
|
||||||
|
QMAKE_TARGET_DESCRIPTION = "common use code for Qt."
|
||||||
|
|
||||||
|
CONFIG += build_TaoCommon_lib
|
||||||
|
DEFINES += TaoCommon_Library
|
||||||
|
|
||||||
|
include(TaoCommon.pri)
|
10
3rdparty/TaoCommon/Thread/threadcommon.h
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <functional>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
using WorkCallback = std::function<bool()>;
|
||||||
|
using WorkResultCallback = std::function<void(bool)>;
|
||||||
|
}
|
||||||
|
Q_DECLARE_METATYPE(TaoCommon::WorkCallback);
|
||||||
|
Q_DECLARE_METATYPE(TaoCommon::WorkResultCallback);
|
22
3rdparty/TaoCommon/Thread/threadpool.cpp
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "threadpool.h"
|
||||||
|
|
||||||
|
#include <QThreadPool>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
ThreadObject::ThreadObject(const WorkCallback& work) : m_workCall(work) {}
|
||||||
|
void ThreadObject::run()
|
||||||
|
{
|
||||||
|
bool ok = m_workCall();
|
||||||
|
emit readyResult(ok);
|
||||||
|
}
|
||||||
|
//workCall in sub thread, resultCall in main thread
|
||||||
|
void ThreadPool::work(const WorkCallback& workCall, const WorkResultCallback& resultCall)
|
||||||
|
{
|
||||||
|
ThreadObject* obj = new ThreadObject(workCall);
|
||||||
|
obj->setAutoDelete(true);
|
||||||
|
connect(obj, &ThreadObject::readyResult, this, resultCall);
|
||||||
|
QThreadPool::globalInstance()->start(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
41
3rdparty/TaoCommon/Thread/threadpool.h
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "taocommonglobal.h"
|
||||||
|
#include "threadcommon.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QRunnable>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
// 对Qt线程池的简单封装,适合一次性执行的任务。
|
||||||
|
// 用法: ThreadPool::getInstance()->work(workCall, resultCall)
|
||||||
|
// workCall是在新线程中执行的任务,resultCall是任务执行完成后,回到调用线程中用来处理执行结果。
|
||||||
|
// 不支持任务取消、暂停。
|
||||||
|
|
||||||
|
class ThreadObject
|
||||||
|
: public QObject
|
||||||
|
, public QRunnable
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ThreadObject(const WorkCallback& work);
|
||||||
|
void run() override;
|
||||||
|
signals:
|
||||||
|
void readyResult(bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkCallback m_workCall;
|
||||||
|
};
|
||||||
|
class TAO_API ThreadPool : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static ThreadPool* getInstance()
|
||||||
|
{
|
||||||
|
static ThreadPool poll;
|
||||||
|
return &poll;
|
||||||
|
}
|
||||||
|
//workCall in sub thread, resultCall in main thread
|
||||||
|
void work(const WorkCallback& workCall, const WorkResultCallback& resultCall);
|
||||||
|
private:
|
||||||
|
ThreadPool() {}
|
||||||
|
};
|
||||||
|
} // namespace TaoCommon
|
129
3rdparty/TaoCommon/Thread/threadworkercontroller.h
vendored
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "taocommonglobal.h"
|
||||||
|
#include "threadcommon.h"
|
||||||
|
#include <QMap>
|
||||||
|
#include <QThread>
|
||||||
|
namespace TaoCommon
|
||||||
|
{
|
||||||
|
// 对Qt Worker-Controller 线程模型的简单封装,适合精确控制的任务。
|
||||||
|
// 用法: ThreadController::getInstance()->work(workCall, resultCall)
|
||||||
|
// workCall是在新线程中执行的任务,resultCall是任务执行完成后,回到调用线程中用来处理执行结果。
|
||||||
|
// work函数返回值为任务id。
|
||||||
|
// 取消任务用ThreadController::getInstance()->cancle(id)函数。
|
||||||
|
class ThreadWorker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ThreadWorker(uint64_t id, const WorkCallback &workCall, QObject *parent = nullptr) : QObject(parent), m_id(id), m_workCall(workCall) {}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void workFinished(bool, uint64_t);
|
||||||
|
public slots:
|
||||||
|
void doWork()
|
||||||
|
{
|
||||||
|
bool ret = m_workCall();
|
||||||
|
emit workFinished(ret, m_id);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const uint64_t m_id;
|
||||||
|
WorkCallback m_workCall;
|
||||||
|
};
|
||||||
|
class TAO_API ThreadController : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static ThreadController *getInstance()
|
||||||
|
{
|
||||||
|
static ThreadController controller;
|
||||||
|
return &controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ThreadController()
|
||||||
|
{
|
||||||
|
for (auto k : m_threadMap.uniqueKeys())
|
||||||
|
{
|
||||||
|
if (m_threadMap.value(k)->isRunning())
|
||||||
|
{
|
||||||
|
m_threadMap.value(k)->quit();
|
||||||
|
m_threadMap.value(k)->wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDeleteAll(m_threadMap);
|
||||||
|
m_threadMap.clear();
|
||||||
|
m_resultCallback.clear();
|
||||||
|
}
|
||||||
|
uint64_t work(const WorkCallback &workCall, const WorkResultCallback &resultCall)
|
||||||
|
{
|
||||||
|
QThread *thread = new QThread;
|
||||||
|
m_rollId++;
|
||||||
|
ThreadWorker *obj = new ThreadWorker(m_rollId, workCall);
|
||||||
|
m_threadMap[m_rollId] = thread;
|
||||||
|
m_resultCallback[m_rollId] = resultCall;
|
||||||
|
obj->moveToThread(thread);
|
||||||
|
|
||||||
|
connect(thread, &QThread::finished, obj, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::started, obj, &ThreadWorker::doWork);
|
||||||
|
connect(obj, &ThreadWorker::workFinished, this, &ThreadController::onWorkFinished, Qt::QueuedConnection);
|
||||||
|
thread->start();
|
||||||
|
return m_rollId;
|
||||||
|
}
|
||||||
|
void cancle(uint64_t id)
|
||||||
|
{
|
||||||
|
auto it = m_threadMap.find(id);
|
||||||
|
if (it != m_threadMap.end())
|
||||||
|
{
|
||||||
|
if ((*it)->isRunning())
|
||||||
|
{
|
||||||
|
(*it)->terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_resultCallback.remove(id);
|
||||||
|
}
|
||||||
|
void quit(uint64_t id)
|
||||||
|
{
|
||||||
|
auto it = m_threadMap.find(id);
|
||||||
|
if (it != m_threadMap.end())
|
||||||
|
{
|
||||||
|
if ((*it)->isRunning())
|
||||||
|
{
|
||||||
|
(*it)->quit();
|
||||||
|
(*it)->wait();
|
||||||
|
(*it)->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_resultCallback.remove(id);
|
||||||
|
}
|
||||||
|
QList<uint64_t> getAllWorkId() const
|
||||||
|
{
|
||||||
|
return m_threadMap.uniqueKeys();
|
||||||
|
}
|
||||||
|
protected slots :
|
||||||
|
void onWorkFinished(bool ok, uint64_t id)
|
||||||
|
{
|
||||||
|
auto it = m_threadMap.find(id);
|
||||||
|
if (it != m_threadMap.end())
|
||||||
|
{
|
||||||
|
if ((*it)->isRunning())
|
||||||
|
{
|
||||||
|
(*it)->quit();
|
||||||
|
(*it)->wait();
|
||||||
|
(*it)->deleteLater();
|
||||||
|
}
|
||||||
|
m_threadMap.remove(id);
|
||||||
|
}
|
||||||
|
auto caller = m_resultCallback.find(id);
|
||||||
|
if (caller != m_resultCallback.end())
|
||||||
|
{
|
||||||
|
(*caller)(ok);
|
||||||
|
m_resultCallback.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
ThreadController(QObject *parent = nullptr) : QObject(parent) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_rollId = 0;
|
||||||
|
QMap<uint64_t, QThread *> m_threadMap;
|
||||||
|
QMap<uint64_t, WorkResultCallback> m_resultCallback;
|
||||||
|
};
|
||||||
|
} // namespace LCIM
|
12
3rdparty/TaoCommon/taocommonglobal.h
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QtCore/QtGlobal>
|
||||||
|
|
||||||
|
#if !defined(BUILD_STATIC) && !defined(TaoCommon_NO_LIB)
|
||||||
|
#if defined(TaoCommon_Library)
|
||||||
|
#define TAO_API Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
#define TAO_API Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define TAO_API
|
||||||
|
#endif
|
@ -7,7 +7,9 @@ lessThan(QT_MAJOR_VERSION, 5) {
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
src
|
src \
|
||||||
|
examples
|
||||||
|
CONFIG+= ordered
|
||||||
|
|
||||||
OTHER_FILES += *.md \
|
OTHER_FILES += *.md \
|
||||||
LICENSE \
|
LICENSE \
|
||||||
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 833 B After Width: | Height: | Size: 833 B |
Before Width: | Height: | Size: 870 B After Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 447 B |
Before Width: | Height: | Size: 410 B After Width: | Height: | Size: 410 B |
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 972 B After Width: | Height: | Size: 972 B |
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 217 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 180 B |