#ifndef LOGTHREAD_H
#define LOGTHREAD_H
#include <QThread>
#include <QMutex>
#include <QQueue>
#define DEFAULT_PATH_SAVE_LOG "./data.log"
// 基于 C++11 的线程安全的单例模板类
template<typename T>
class Singleton
{
public:
static T& instance()
{
static T instance;
return instance;
}
protected:
Singleton() {}
virtual ~Singleton() {}
private:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
namespace QTLOG {
class LogThread : public QThread, public Singleton<LogThread>
{
public:
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
/**
* @brief 日志信息输出函数
* @param type 参数,日志信息的级别
* @param msg 参数,日志信息的内容
*/
static void outputMessage(QtMsgType type, const char *msg);
#else
static void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg);
#endif
void SetLogSavePath(const QString &path);
protected:
void run() override;
private:
friend class Singleton<LogThread>;
// 将构造函数和析构函数设为私有,防止在类外实例化
LogThread();
~LogThread();
static QString getLevelString(QtMsgType type);
private:
//保存日志信息的路径
QString logPath_ { DEFAULT_PATH_SAVE_LOG };
static QQueue<QByteArray> logQueue_;
static QMutex msgMutex_;
};
}
#endif // LOGTHREAD_H
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDebug>
#include "logthread.h"
using namespace QTLOG;
QQueue<QByteArray> LogThread::logQueue_;
QMutex LogThread::msgMutex_;
LogThread::LogThread()
{
qDebug() << "current id :" << QThread::currentThreadId();
}
LogThread::~LogThread()
{
}
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
void LogThread::outputMessage(QtMsgType type, const char *msg)
{
QString context_info = QString("File:(%1) Line:(%2)").arg(__FILE__).arg(__LINE__);
QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QString message = QString("%1 %2 %3 %4")
.arg(getLevelString(type))
.arg(current_date_time)
.arg(context_info)
.arg(msg);
QMutexLocker locker(&msgMutex_);
logQueue_.enqueue(message.toUtf8() + "\n");
}
#else
void LogThread::outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray log;
QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
log.append(QString("%1 : DateTime:%2 ThreadId:%3 Message:%4 File:%5:%6(%7)")
.arg(getLevelString(type))
.arg(qPrintable(strDateTime))
.arg(QString::number(quintptr(QThread::currentThreadId())))
.arg(qPrintable(msg))
.arg(context.file)
.arg(context.line)
.arg(context.function)
.toUtf8());
QMutexLocker locker(&msgMutex_);
logQueue_.enqueue(log + "\n");
}
#endif
void LogThread::SetLogSavePath(const QString &path)
{
QMutexLocker locker(&msgMutex_);
logPath_ = path;
}
void LogThread::run()
{
qInstallMessageHandler(LogThread::outputMessage);
while(true){
if(!logQueue_.isEmpty())
{
QString message;
{
QMutexLocker queueLocker(&msgMutex_);
message = logQueue_.dequeue();
}
{
// 获取互斥量保护 logPath_
QMutexLocker pathLocker(&msgMutex_);
QFile file(logPath_);
if (file.open(QIODevice::Text | QIODevice::ReadWrite | QIODevice::Append)) {
QTextStream st(&file);
st << message;
st.flush();
file.close();
}
}
}
}
// exec();
}
QString LogThread::getLevelString(QtMsgType type)
{
switch (type) {
case QtDebugMsg:
return "Debug";
case QtInfoMsg:
return "Info";
case QtWarningMsg:
return "Warning";
case QtCriticalMsg:
return "Critical";
case QtFatalMsg:
return "Fatal";
default:
return "";
}
}
#include "unistd.h"
#include "mainwindow.h"
#include <QApplication>
#include <QSplashScreen>
#include <QLabel>
#include <QMovie>
#include <QTranslator>
#include "log/logthread.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
translator.load(NULL);
a.installTranslator(&translator);
QTLOG::LogThread::instance().SetLogSavePath("C:/work/log.txt");
QTLOG::LogThread::instance().start();
QPixmap pixmap(":/myImage/images/loading.gif");
QSplashScreen splash(pixmap);
QLabel label(&splash);
QMovie mv(":/myImage/images/loading.gif");
label.setMovie(&mv);
mv.start();
splash.show();
splash.setCursor(Qt::BlankCursor);
for(int i=0; i<5000; i+=mv.speed())
{
QCoreApplication::processEvents();
usleep(500*static_cast<useconds_t>(mv.speed()));
}
MainWindow w;
w.setWindowTitle(QObject::tr("图像视频处理工具"));
w.show();
splash.finish(&w);
// 等待LogThread线程结束,并退出应用程序
QTLOG::LogThread::instance().wait();
return a.exec();
}