《QT实用小工具·六》代码行数统计工具

1、概述
源码放在文章末尾

该项目实现了对不同编程语言文件的代码行数的统计
统计的内容包含:
1、代码行数
2、注释行数
3、空白行数

下面是demo演示:
在这里插入图片描述

项目部分代码如下所示:

#pragma execution_character_set("utf-8")

#include "frmcountcode.h"
#include "ui_frmcountcode.h"
#include "qfile.h"
#include "qtextstream.h"
#include "qfiledialog.h"
#include "qfileinfo.h"
#include "qdebug.h"

frmCountCode::frmCountCode(QWidget *parent) : QWidget(parent), ui(new Ui::frmCountCode)
{
    ui->setupUi(this);
    this->initForm();
    on_btnClear_clicked();
}

frmCountCode::~frmCountCode()
{
    delete ui;
}

void frmCountCode::initForm()
{
    QStringList headText;
    headText << "文件名" << "类型" << "大小" << "总行数" << "代码行数" << "注释行数" << "空白行数" << "路径";
    QList<int> columnWidth;
    columnWidth << 130 << 50 << 70 << 80 << 70 << 70 << 70 << 150;

    int columnCount = headText.count();
    ui->tableWidget->setColumnCount(columnCount);
    ui->tableWidget->setHorizontalHeaderLabels(headText);
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->horizontalHeader()->setHighlightSections(false);
    ui->tableWidget->verticalHeader()->setDefaultSectionSize(20);
    ui->tableWidget->verticalHeader()->setHighlightSections(false);

    for (int i = 0; i < columnCount; i++) {
        ui->tableWidget->setColumnWidth(i, columnWidth.at(i));
    }

    //设置前景色
    ui->txtCount->setStyleSheet("color:#17A086;");
    ui->txtSize->setStyleSheet("color:#CA5AA6;");
    ui->txtRow->setStyleSheet("color:#CD1B19;");
    ui->txtCode->setStyleSheet("color:#22A3A9;");
    ui->txtNote->setStyleSheet("color:#D64D54;");
    ui->txtBlank->setStyleSheet("color:#A279C5;");

    //设置字体加粗
    QFont font;
    font.setBold(true);
    if (font.pointSize() > 0) {
        font.setPointSize(font.pointSize() + 1);
    } else {
        font.setPixelSize(font.pixelSize() + 2);
    }

    ui->txtCount->setFont(font);
    ui->txtSize->setFont(font);
    ui->txtRow->setFont(font);
    ui->txtCode->setFont(font);
    ui->txtNote->setFont(font);
    ui->txtBlank->setFont(font);

#if (QT_VERSION > QT_VERSION_CHECK(4,7,0))
    ui->txtFilter->setPlaceholderText("中间空格隔开,例如 *.h *.cpp *.c");
#endif
}

bool frmCountCode::checkFile(const QString &fileName)
{
    if (fileName.startsWith("moc_") || fileName.startsWith("ui_") || fileName.startsWith("qrc_")) {
        return false;
    }

    QFileInfo file(fileName);
    QString suffix = "*." + file.suffix();
    QString filter = ui->txtFilter->text().trimmed();
    QStringList filters = filter.split(" ");
    return filters.contains(suffix);
}

void frmCountCode::countCode(const QString &filePath)
{
    QDir dir(filePath);
    QFileInfoList fileInfos = dir.entryInfoList();
    foreach (QFileInfo fileInfo, fileInfos) {
        QString fileName = fileInfo.fileName();
        if (fileInfo.isFile()) {
            if (checkFile(fileName)) {
                listFile << fileInfo.filePath();
            }
        } else {
            if (fileName == "." || fileName == "..") {
                continue;
            }

            //递归找出文件
            countCode(fileInfo.absoluteFilePath());
        }
    }
}

void frmCountCode::countCode(const QStringList &files)
{
    int lineCode;
    int lineBlank;
    int lineNotes;
    int count = files.count();
    on_btnClear_clicked();
    ui->tableWidget->setRowCount(count);

    quint32 totalLines = 0;
    quint32 totalBytes = 0;
    quint32 totalCodes = 0;
    quint32 totalNotes = 0;
    quint32 totalBlanks = 0;

    for (int i = 0; i < count; i++) {
        QFileInfo fileInfo(files.at(i));
        countCode(fileInfo.filePath(), lineCode, lineBlank, lineNotes);
        int lineAll = lineCode + lineBlank + lineNotes;

        QTableWidgetItem *itemName = new QTableWidgetItem;
        itemName->setText(fileInfo.fileName());

        QTableWidgetItem *itemSuffix = new QTableWidgetItem;
        itemSuffix->setText(fileInfo.suffix());

        QTableWidgetItem *itemSize = new QTableWidgetItem;
        itemSize->setText(QString::number(fileInfo.size()));

        QTableWidgetItem *itemLine = new QTableWidgetItem;
        itemLine->setText(QString::number(lineAll));

        QTableWidgetItem *itemCode = new QTableWidgetItem;
        itemCode->setText(QString::number(lineCode));

        QTableWidgetItem *itemNote = new QTableWidgetItem;
        itemNote->setText(QString::number(lineNotes));

        QTableWidgetItem *itemBlank = new QTableWidgetItem;
        itemBlank->setText(QString::number(lineBlank));

        QTableWidgetItem *itemPath = new QTableWidgetItem;
        itemPath->setText(fileInfo.filePath());

        itemSuffix->setTextAlignment(Qt::AlignCenter);
        itemSize->setTextAlignment(Qt::AlignCenter);
        itemLine->setTextAlignment(Qt::AlignCenter);
        itemCode->setTextAlignment(Qt::AlignCenter);
        itemNote->setTextAlignment(Qt::AlignCenter);
        itemBlank->setTextAlignment(Qt::AlignCenter);

        ui->tableWidget->setItem(i, 0, itemName);
        ui->tableWidget->setItem(i, 1, itemSuffix);
        ui->tableWidget->setItem(i, 2, itemSize);
        ui->tableWidget->setItem(i, 3, itemLine);
        ui->tableWidget->setItem(i, 4, itemCode);
        ui->tableWidget->setItem(i, 5, itemNote);
        ui->tableWidget->setItem(i, 6, itemBlank);
        ui->tableWidget->setItem(i, 7, itemPath);

        totalBytes  += fileInfo.size();
        totalLines  += lineAll;
        totalCodes  += lineCode;
        totalNotes  += lineNotes;
        totalBlanks += lineBlank;

        if (i % 100 == 0) {
            qApp->processEvents();
        }
    }

    //显示统计结果
    listFile.clear();
    ui->txtCount->setText(QString::number(count));
    ui->txtSize->setText(QString::number(totalBytes));
    ui->txtRow->setText(QString::number(totalLines));
    ui->txtCode->setText(QString::number(totalCodes));
    ui->txtNote->setText(QString::number(totalNotes));
    ui->txtBlank->setText(QString::number(totalBlanks));

    //计算百分比
    double percent = 0.0;
    //代码行所占百分比
    percent = ((double)totalCodes / totalLines) * 100;
    ui->labPercentCode->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //注释行所占百分比
    percent = ((double)totalNotes / totalLines) * 100;
    ui->labPercentNote->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //空行所占百分比
    percent = ((double)totalBlanks / totalLines) * 100;
    ui->labPercentBlank->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}

void frmCountCode::countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes)
{
    lineCode = lineBlank = lineNotes = 0;
    QFile file(fileName);
    if (file.open(QFile::ReadOnly)) {
        QTextStream out(&file);
        QString line;
        bool isNote = false;
        while (!out.atEnd()) {
            line = out.readLine();

            //移除前面的空行
            if (line.startsWith(" ")) {
                line.remove(" ");
            }

            //判断当前行是否是注释
            if (line.startsWith("/*")) {
                isNote = true;
            }

            //注释部分
            if (isNote) {
                lineNotes++;
            } else {
                if (line.startsWith("//")) {    //注释行
                    lineNotes++;
                } else if (line.isEmpty()) {    //空白行
                    lineBlank++;
                } else {                        //代码行
                    lineCode++;
                }
            }

            //注释结束
            if (line.endsWith("*/")) {
                isNote = false;
            }
        }
    }
}

void frmCountCode::on_btnOpenFile_clicked()
{
    QString filter = QString("代码文件(%1)").arg(ui->txtFilter->text().trimmed());
    QStringList files = QFileDialog::getOpenFileNames(this, "选择文件", "./", filter);
    if (files.size() > 0) {
        ui->txtFile->setText(files.join("|"));
        countCode(files);
    }
}

void frmCountCode::on_btnOpenPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this, "选择目录", "./",  QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (!path.isEmpty()) {
        ui->txtPath->setText(path);
        listFile.clear();
        countCode(path);
        countCode(listFile);
    }
}

void frmCountCode::on_btnClear_clicked()
{
    ui->txtCount->setText("0");
    ui->txtSize->setText("0");
    ui->txtRow->setText("0");

    ui->txtCode->setText("0");
    ui->txtNote->setText("0");
    ui->txtBlank->setText("0");

    ui->labPercentCode->setText("0%");
    ui->labPercentNote->setText("0%");
    ui->labPercentBlank->setText("0%");
    ui->tableWidget->setRowCount(0);
}

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506591.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

区块链食品溯源案例实现(一)

引言&#xff1a; 食品安全问题一直是社会关注的热点&#xff0c;而食品溯源作为解决食品安全问题的重要手段&#xff0c;其重要性不言而喻。传统的食品溯源系统往往存在数据易被篡改、信息不透明等问题&#xff0c;而区块链技术的引入&#xff0c;为食品溯源带来了革命性的变革…

【ProComponents】解决 ProTable 中 params 参数改变,request 函数未触发问题

文章目录 先建议自查下官方文档&#xff0c;了解params和request直接的关系 确定params绑定的参数是否改变&#xff0c;例如 user_name 参数 import { ProTable, WxIcon } from /components; import { getSearchParams } from ice; import { useEffect, useMemo, useRef, useS…

智慧公厕是什么?智慧公厕的主要功能、特点?

智慧公厕&#xff0c;顾名思义&#xff0c;是指应用了智能科技的公共厕所&#xff0c;旨在提供更加便捷、舒适、智能化的卫生服务。相比传统的公厕&#xff0c;智慧公厕不仅拥有更加智能化的设备&#xff0c;还配备了远程监控与管理系统&#xff0c;以及节能环保技术&#xff0…

优化页面加载时间:改善用户体验的关键

✨✨ 祝屏幕前的您天天开心&#xff0c;每天都有好运相伴。我们一起加油&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一、为什么页面加载时间重要&#xff1f; 二、如何减少页面加载时间&#xff1f; …

SiLM824x系列SiLM8244 配置为高、低边驱动 支持死区可编程,隔离双通道门级驱动器

SiLM824x系列SiLM8244是一款具有不同配置的隔离双通道门极驱动器。SiLM8244配置为高、低边驱动&#xff0c;SiLM8244可提供4A的输出源电流和6A的灌电流能力&#xff0c;并且其驱动输出电压可以支持到33V。支持死区可编程&#xff0c;通过调整DT脚外部的电阻大小&#xff0c;调整…

基于单片机汽车超声波防盗系统设计

**单片机设计介绍&#xff0c;基于单片机汽车超声波防盗系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机汽车超声波防盗系统设计概要主要涉及利用超声波传感器和单片机技术来实现汽车的安全防盗功能。以下是对…

注册接口和前置SQL及数据生成及封装

注册接口 演示注册接口的三步操作&#xff1a;【注册流程逻辑】 第一步&#xff1a;发送注册短信验证码接口请求 请求方法&#xff1a; put 请求地址&#xff1a;http://shop.lemonban.com:8107/user/sendRegisterSms 请求参数&#xff1a;{“mobile”:“13422337766”} 请求头…

【面试专题】Mybatis高频面试题

一、介绍下MyBatis中的工作原理 1。介绍MyBatis的基本情况&#xff1a;ORM 2。原理&#xff1a; MyBatis框架的初始化操作处理SQL请求的流程 1.系统启动的时候会加载解析全局配置文件和对应映射文件。加载解析的相关信息存储在 Configuration 对象 Testpublic void test1(…

C++算法补充---STL

这里写目录标题 CSTL容器字符串函数(string容器函数)字符串转字符 算法交换函数拿到容器或者数组的第一个最大&#xff08;小&#xff09;值元素的下标或者值排序函数求字符数组的有效长度atoi函数&#xff08;将字符串类型的数字转为真正的int型数字&#xff09;string转字符 …

STM32八种I/O口模式

STM32八种I/O口模式 文章目录 STM32八种I/O口模式前言一、stm32八种I/O类型二、区别1.模拟输入2.浮空输入3.上拉输入4.下拉输入5.推挽输出6.开漏输出7.复用推挽输出8.复用推挽输出 总结 前言 作为两年嵌入式软件攻城狮&#xff0c;还没仔细去理解过STM32的GPIO的八种使用模式&…

企业招聘,应用MBTI来做人才测评招聘测评

每年的校招季都是企业争抢优秀应届毕业生人才的忙碌季。只有精准识人用人&#xff0c;才能不断为企业注入新鲜活力和青春智慧。但是随着毕业生数量越来越多&#xff0c;企业如何在招聘中精准发现自己最需要的人才&#xff0c;成为摆在人力资源部门的大难题。人才测评是各企业都…

springboot在线学习做题答题统计系统-可视化分析系统

系统阐述的是使用可视化的学习系统的设计与实现&#xff0c;对于java、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了 springboot框架和MySql数据库技术搭建系统的整体架构。…

【分析教程】unity游戏修改so文件

基础知识 0x1.apk安装后在手机中的目录 apk安装后会在两个包下生成相关包&#xff1a;data/data/、data/app/。 这里拿网易云音乐的安装目录举例。Data/App目录下通常会有三个文件&#xff1a; lib文件夹&#xff08;包含so库文件&#xff09;、 ‚oat文件夹&#xff08;O…

算法系列--递归,回溯,剪枝的综合应用(2)

&#x1f495;"对相爱的人来说&#xff0c;对方的心意&#xff0c;才是最好的房子。"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–递归,回溯,剪枝的综合应用(2) 大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(2) 一.括号…

揭秘阿里面试必问:Tomcat类加载机制解析

各位小米的小伙伴们,大家好呀!今天小米要和大家聊聊一个很有趣的话题——阿里巴巴面试题:Tomcat的类加载机制。作为一个技术爱好者,小米深知技术分享的重要性,希望通过这篇文章与大家一起深入了解Tomcat的类加载机制,加深对Java Web开发的理解,也希望能够帮助到正在准备…

五款常用在线JavaScript加密混淆工具详解:jscrambler、JShaman、jsfack、ipaguard和jjencode

摘要 本篇技术博客将介绍五款常用且好用的在线JavaScript加密混淆工具&#xff0c;包括 jscrambler、JShaman、jsfack、freejsobfuscator 和 jjencode。通过对这些工具的功能及使用方法进行详细解析&#xff0c;帮助开发人员更好地保护和加密其 JavaScript 代码&#xff0c;提…

希亦、洁盟、大宇超声波清洗机好用吗?比拼谁是性价比之王

在追求高效生活品质的今天&#xff0c;超声波清洗机以其独特的清洁技术和便捷的操作方式&#xff0c;成为了家用和商用清洁领域的新宠。尤其对于眼镜用户而言&#xff0c;一台高效的超声波清洗机不仅能够轻松去除镜片上的污渍和细菌&#xff0c;更能保护镜片不受损伤&#xff0…

一款完全免费无广告的浏览器插件

界面上的图标都支持拖拽移动位置 一、官网 官方网站 www.brtab.top 二、功能 精美的小组件 天气组件&#xff1a;可以查看不同城市的当前以及未来7天的天气变化&#xff0c;并了解当前的所有天气指数 日历组件&#xff1a;可以显示当前的日期&#xff0c;包含农历日期&…

不可不知的,数字孪生在智慧城市中的八大应用。

数字孪生是一种将物理世界和数字世界相结合的技术&#xff0c;其在新型智慧城市建设中有着广泛的应用&#xff0c;主要包括以下几个方面&#xff1a; 城市规划和设计&#xff1a; 数字孪生技术可以将城市的三维数据模型与实际场景相结合&#xff0c;帮助城市规划师和设计师更…

ROS2从入门到精通1-2:详解ROS2服务通信机制与自定义服务

目录 0 专栏介绍1 服务通信模型2 服务模型实现(C)3 服务模型实现(Python)4 自定义服务5 话题、服务通信的异同 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌握ROS2底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。…