当前位置: 首页 > article >正文

QT:QDEBUG输出重定向和命令行参数QCommandLineParser

qInstallMessageHandler函数简介 

QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

        qInstallMessageHandler 是 Qt 框架中的一个函数,用于安装一个全局的消息处理函数,以替代默认的消息输出机制。这个函数允许开发者自定义 Qt 应用程序中所有调试消息、信息消息、警告消息、严重错误消息和致命错误消息的处理方式。

        当 Qt 应用程序中的任何地方调用 qDebug(), qInfo(), qWarning(), qCritical() 或 qFatal() 函数时,如果已经通过 qInstallMessageHandler 安装了一个自定义的消息处理函数,那么这个函数就会被调用,而不是将消息输出到标准输出、标准错误或其他默认位置。

自定义的消息处理函数通常具有以下签名:

void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);

type参数:

enum QtMsgType;

 实验代码

#include <QApplication>
#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QCommandLineParser>
#include <QDateTime>

static QMutex qml_logfile_mutex;
static int log_level = QtInfoMsg;
static bool g_enable_debug_time = false;
static enum QtMsgType debug_log_level = QtWarningMsg;
#define FORBID_LOG_OUTPUT_LEVEL (QtInfoMsg + 1)
#define NO_QDEBUG_LEVEL ((enum QtMsgType)(QtDebugMsg + 1))
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
    static int file_index = 0;
    if(type < log_level){
        return;
    }
    if(type < debug_log_level){
        return;
    }
    QMutexLocker lock(&qml_logfile_mutex);

    QString filename = "";
    while (context.file != nullptr) {
        QStringList dirList;
        filename = context.file;
        if (filename.length() < 1) {
            break;
        }
        dirList = filename.split(QDir::separator());
        if (dirList.size() > 0) {
            filename = dirList[dirList.size() - 1];
        }
        if (filename.contains("/")) {
            dirList = filename.split("/");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        if (filename.contains("\\")) {
            dirList = filename.split("\\");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        break;
    };

    QString logFileFullName;
    logFileFullName = qApp->applicationDirPath();
    logFileFullName.append(QString("\\log\\console_%1.log").arg(file_index));
    QFile file(logFileFullName);
    do{
        if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            return;
        }
        if(file.pos() > 1024 * 1024){
            file.close();
            file_index++;
            QString new_file_name;
            new_file_name = qApp->applicationDirPath();
            new_file_name.append(QString("\\log\\console_%1.log").arg(file_index));
            file.setFileName(new_file_name);
            continue;
        }
        break;
    }while(1);

    QTextStream text_stream(&file);
    QString output_text;
    if(g_enable_debug_time){
        QString currentDateTime =
                QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss-zzz");
        output_text.append("[");
        output_text.append(currentDateTime);
        output_text.append("] ");
    }
    output_text.append("[");
    if (filename.length() > 0) {
        output_text.append(QString("%1").arg(type));
    }
    if (filename.length() > 0) {
        output_text.append(QString("|%1").arg(filename));
    }
    if (context.function != nullptr && strlen(context.function) > 0) {
        output_text.append(QString("|%1").arg(context.function));
    }

    if (context.line > 0) {
        output_text.append(QString("|%1").arg(context.line));
    }
    output_text.append(QString("] -- [ %1 ]").arg(msg));
    text_stream << output_text << Qt::endl;
}
void check_and_mkdir(){
    QString log_path = qApp->applicationDirPath();
    log_path.append("/log");
    QDir log_dir(log_path);
    if(!log_dir.exists()){
        qDebug() << log_path << " not exists";
        qDebug() << log_dir.mkdir(".");
    }else{
        qDebug() << log_path << " exists";
    }
}
void parse_commond_line(QApplication &app){
    QCommandLineParser parser;
    parser.setApplicationDescription("Example application");
    app.setApplicationVersion("version 0.1");
    //添加帮助选项
    QCommandLineOption helpOption = parser.addHelpOption();
    //添加版本选项
    QCommandLineOption versionOption = parser.addVersionOption();
    // 添加 --log 选项,这是一个没有值的开关选项
    QCommandLineOption logOption(QStringList() << "log",
        QCoreApplication::translate("main", "enable log functionality."));

    // 添加 --time 选项,这是一个没有值的开关选项
    QCommandLineOption timeOption(QStringList() << "time",
        QCoreApplication::translate("main", "enable show log time."));

    // 添加 --level 选项,这是一个带有值的选项
    QCommandLineOption levelOption(QStringList() << "level",
        QCoreApplication::translate("main", "set log level"),
        QCoreApplication::translate("main", "level"),  // 默认值(可选)
        "5");  // 值名称,用于解析 --level=VALUE

    QCommandLineOption debugOption(QStringList() << "debug",
        QCoreApplication::translate("main", "set log debug"),
        QCoreApplication::translate("main", "debug"),  // 默认值(可选)
        "2");  // 值名称,用于解析 --level=VALUE
    // 将选项添加到解析器
    parser.addOptions({ logOption, timeOption, levelOption, debugOption});

    // 解析命令行参数
    bool parseOk = parser.parse(QCoreApplication::arguments());
    qDebug() << "parseOk:" << parseOk;
    // 检查是否请求了帮助
    if (parser.isSet(helpOption)) {
        parser.showHelp();
        qDebug() << "-----------------------";
        qDebug() << parser.helpText(); // 输出帮助信息
        qDebug() << "-----------------------";
        exit(0);
    }
    // 检查是否请求了版本
    if (parser.isSet(versionOption)) {
        parser.showVersion(); // 输出帮助信息
        qDebug() << "after showVersion";
        app.processEvents();
        exit(0);
    }
    // 检查 --time 选项是否被设置
    bool timeEnabled = parser.isSet(timeOption);
    g_enable_debug_time = timeEnabled;
    // 检查 --log 选项是否被设置
    bool logEnabled = parser.isSet(logOption);
    qDebug() << "Log enabled:" << logEnabled;
    if(logEnabled){
        check_and_mkdir();
        // 检查 --level 选项的值
        bool hasLevel = parser.isSet(levelOption);
        if(hasLevel){
            QString levelQStringValue = parser.value(levelOption);
            bool isInt = false;
            int levelValue = levelQStringValue.toInt(&isInt,10);
            if(isInt){
                if(levelValue < 0){
                    levelValue = FORBID_LOG_OUTPUT_LEVEL;
                }
                log_level = levelValue;
            }else{
                log_level = FORBID_LOG_OUTPUT_LEVEL;
            }
        }else{
            log_level = FORBID_LOG_OUTPUT_LEVEL;
        }

        bool hasDebug = parser.isSet(debugOption);
        qDebug() << "hasDebug = " << hasDebug;
        if(hasDebug){
            QString debugQStringValue = parser.value(debugOption);
            bool isInt = false;
            int debugValue = debugQStringValue.toInt(&isInt,10);
            qDebug() << debugValue;
            if(isInt){
                if(debugValue < 0){
                    debugValue = NO_QDEBUG_LEVEL;
                }
                debug_log_level = (enum QtMsgType)debugValue;
            }else{
                debug_log_level = NO_QDEBUG_LEVEL;
            }
        }else{
            debug_log_level = NO_QDEBUG_LEVEL;
        }
        qInstallMessageHandler(myMessageOutput);
    }
}
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    parse_commond_line(app);
    int count = 0;
    while(count < 10000){
        count++;
        qDebug() << "count = " << count;
        qDebug() << "qDebug:hello log file";
        qInfo() << "qInfo:hello log file";
        qWarning() << "qWarning:hello log file";
        qCritical() << "QtCriticalMsg:hello log file";
    }
    qFatal("qFatal:hello log file");
    return app.exec();
}

测试结果:

运行后,会生成log文件夹,并生成文件console.log,内容如下:由执行结果可知函数会导致程序退出。

命令行参数 

#include <QApplication>
#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QCommandLineParser>
#include <QDateTime>

static QMutex qml_logfile_mutex;
static int log_level = QtInfoMsg;
static bool g_enable_debug_time = false;
static enum QtMsgType debug_log_level = QtWarningMsg;
#define FORBID_LOG_OUTPUT_LEVEL (QtInfoMsg + 1)
#define NO_QDEBUG_LEVEL ((enum QtMsgType)(QtDebugMsg + 1))
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
    static int file_index = 0;
    if(type < log_level){
        return;
    }
    if(type < debug_log_level){
        return;
    }
    QMutexLocker lock(&qml_logfile_mutex);

    QString filename = "";
    while (context.file != nullptr) {
        QStringList dirList;
        filename = context.file;
        if (filename.length() < 1) {
            break;
        }
        dirList = filename.split(QDir::separator());
        if (dirList.size() > 0) {
            filename = dirList[dirList.size() - 1];
        }
        if (filename.contains("/")) {
            dirList = filename.split("/");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        if (filename.contains("\\")) {
            dirList = filename.split("\\");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        break;
    };

    QString logFileFullName;
    logFileFullName = qApp->applicationDirPath();
    logFileFullName.append(QString("\\log\\console_%1.log").arg(file_index));
    QFile file(logFileFullName);
    do{
        if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            return;
        }
        if(file.pos() > 1024 * 1024){
            file.close();
            file_index++;
            QString new_file_name;
            new_file_name = qApp->applicationDirPath();
            new_file_name.append(QString("\\log\\console_%1.log").arg(file_index));
            file.setFileName(new_file_name);
            continue;
        }
        break;
    }while(1);

    QTextStream text_stream(&file);
    QString output_text;
    if(g_enable_debug_time){
        QString currentDateTime =
                QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss-zzz");
        output_text.append("[");
        output_text.append(currentDateTime);
        output_text.append("] ");
    }
    output_text.append("[");
    if (filename.length() > 0) {
        output_text.append(QString("%1").arg(type));
    }
    if (filename.length() > 0) {
        output_text.append(QString("|%1").arg(filename));
    }
    if (context.function != nullptr && strlen(context.function) > 0) {
        output_text.append(QString("|%1").arg(context.function));
    }

    if (context.line > 0) {
        output_text.append(QString("|%1").arg(context.line));
    }
    output_text.append(QString("] -- [ %1 ]").arg(msg));
    text_stream << output_text << Qt::endl;
}
void check_and_mkdir(){
    QString log_path = qApp->applicationDirPath();
    log_path.append("/log");
    QDir log_dir(log_path);
    if(!log_dir.exists()){
        qDebug() << log_path << " not exists";
        qDebug() << log_dir.mkdir(".");
    }else{
        qDebug() << log_path << " exists";
    }
}
void parse_commond_line(QApplication &app){
    QCommandLineParser parser;
    parser.setApplicationDescription("Example application");
    app.setApplicationVersion("version 0.1");
    //添加帮助选项
    QCommandLineOption helpOption = parser.addHelpOption();
    //添加版本选项
    QCommandLineOption versionOption = parser.addVersionOption();
    // 添加 --log 选项,这是一个没有值的开关选项
    QCommandLineOption logOption(QStringList() << "log",
        QCoreApplication::translate("main", "enable log functionality."));

    // 添加 --time 选项,这是一个没有值的开关选项
    QCommandLineOption timeOption(QStringList() << "time",
        QCoreApplication::translate("main", "enable show log time."));

    // 添加 --level 选项,这是一个带有值的选项
    QCommandLineOption levelOption(QStringList() << "level",
        QCoreApplication::translate("main", "set log level"),
        QCoreApplication::translate("main", "level"),  // 默认值(可选)
        "5");  // 值名称,用于解析 --level=VALUE

    QCommandLineOption debugOption(QStringList() << "debug",
        QCoreApplication::translate("main", "set log debug"),
        QCoreApplication::translate("main", "debug"),  // 默认值(可选)
        "2");  // 值名称,用于解析 --level=VALUE
    // 将选项添加到解析器
    parser.addOptions({ logOption, timeOption, levelOption, debugOption});

    // 解析命令行参数
    bool parseOk = parser.parse(QCoreApplication::arguments());
    qDebug() << "parseOk:" << parseOk;
    // 检查是否请求了帮助
    if (parser.isSet(helpOption)) {
        parser.showHelp();
        qDebug() << "-----------------------";
        qDebug() << parser.helpText(); // 输出帮助信息
        qDebug() << "-----------------------";
        exit(0);
    }
    // 检查是否请求了版本
    if (parser.isSet(versionOption)) {
        parser.showVersion(); // 输出帮助信息
        qDebug() << "after showVersion";
        app.processEvents();
        exit(0);
    }
    // 检查 --time 选项是否被设置
    bool timeEnabled = parser.isSet(timeOption);
    g_enable_debug_time = timeEnabled;
    // 检查 --log 选项是否被设置
    bool logEnabled = parser.isSet(logOption);
    qDebug() << "Log enabled:" << logEnabled;
    if(logEnabled){
        check_and_mkdir();
        // 检查 --level 选项的值
        bool hasLevel = parser.isSet(levelOption);
        if(hasLevel){
            QString levelQStringValue = parser.value(levelOption);
            bool isInt = false;
            int levelValue = levelQStringValue.toInt(&isInt,10);
            if(isInt){
                if(levelValue < 0){
                    levelValue = FORBID_LOG_OUTPUT_LEVEL;
                }
                log_level = levelValue;
            }else{
                log_level = FORBID_LOG_OUTPUT_LEVEL;
            }
        }else{
            log_level = FORBID_LOG_OUTPUT_LEVEL;
        }

        bool hasDebug = parser.isSet(debugOption);
        qDebug() << "hasDebug = " << hasDebug;
        if(hasDebug){
            QString debugQStringValue = parser.value(debugOption);
            bool isInt = false;
            int debugValue = debugQStringValue.toInt(&isInt,10);
            qDebug() << debugValue;
            if(isInt){
                if(debugValue < 0){
                    debugValue = NO_QDEBUG_LEVEL;
                }
                debug_log_level = (enum QtMsgType)debugValue;
            }else{
                debug_log_level = NO_QDEBUG_LEVEL;
            }
        }else{
            debug_log_level = NO_QDEBUG_LEVEL;
        }
        qInstallMessageHandler(myMessageOutput);
    }
}
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    parse_commond_line(app);
    int count = 0;
    while(count < 10000){
        count++;
        qDebug() << "count = " << count;
        qDebug() << "qDebug:hello log file";
        qInfo() << "qInfo:hello log file";
        qWarning() << "qWarning:hello log file";
        qCritical() << "QtCriticalMsg:hello log file";
    }
    qFatal("qFatal:hello log file");
    return app.exec();
}

测试

帮助信息测试:--help

输出的帮助信息

版本测试--version

 调试信息重定向测试--log --level=0

显示时间--log --level=0 --time

 小结


http://www.kler.cn/a/444672.html

相关文章:

  • uni-app开发商品详情页面实现
  • springboot452当代中国获奖的知名作家信息管理系统的设计与实现(论文+源码)_kaic
  • 一篇文章掌握WebService服务、工作原理、核心组件、主流框架
  • 如何裁剪图片多余部分?裁剪图片的几种简单尺寸方法
  • OpenCV相机标定与3D重建(23)用于在图像上绘制世界坐标系的三条轴函数drawFrameAxes()的使用
  • 由学习率跟batch size 关系 引起的海塞矩阵和梯度计算在训练过程中的应用思考
  • 浅谈文生图Stable Diffusion(SD)相关模型基础
  • 大屏项目使用css混合实现光源扫描高亮效果
  • 【docker】如何打包前端并运行
  • 点击数字层级从 admin.vue 跳转到 inviter-list.vue 组件
  • HCIA-Access V2.5_4_1_1路由协议基础_IP路由表
  • PLE网络中跷跷板现象和负迁移现象说明及其对应的解决方法
  • VUE小数位问题:JS当中toFixed()方法5不进位问题的处理
  • 物联网关:机床设备管理的智能变革“利器”
  • WebSocket vs SSE:实时通信技术的对比与选择
  • Vue2/3 生命周期详细对比与使用指南
  • 2009 ~ 2019 年 408【计算机网络】大题解析
  • 深度学习-74-大语言模型LLM之基于API与llama.cpp启动的模型进行交互
  • 如何对 Node.js更好的理解?都有哪些优缺点?哪些应用场景?
  • 智能客户服务:AI与大数据的革新力量