一个线程方法实现Qt4/5日志重定向

4 篇文章 0 订阅
#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();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值