CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(StatisticalCode LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
if(ANDROID)
add_library(StatisticalCode SHARED
main.cpp
statistics.cpp
statistics.h
statistics.ui
)
else()
add_executable(StatisticalCode
main.cpp
statistics.cpp
statistics.h
statistics.ui
)
endif()
target_link_libraries(StatisticalCode PRIVATE Qt5::Widgets)
main.cpp
#include "statistics.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
statistics w;
w.setWindowTitle("统计代码行数");
w.show();
return a.exec();
}
statistics.h
#ifndef STATISTICS_H
#define STATISTICS_H
#include <QWidget>
#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include <QDrag>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QMimeData>
QT_BEGIN_NAMESPACE
namespace Ui {
class statistics;
}
QT_END_NAMESPACE
class statistics : public QWidget
{
Q_OBJECT
public:
statistics(QWidget *parent = nullptr);
~statistics();
private slots:
void on_pbn_open_file_clicked();
void on_pbn_open_catalog_clicked();
void on_pbn_clear_result_clicked();
private:
void initForm();
bool checkFile(const QString &file_name);
void countPathFileNumber(const QString &file_path);
void countFileRows(const QStringList &files);
void countCodeRows(const QString &file_name, int &num_line_code,
int &num_line_blank, int &num_line_note);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
private:
Ui::statistics *ui;
private:
QStringList list_files{};
};
#endif
statistics.cpp
#include "statistics.h"
#include "./ui_statistics.h"
statistics::statistics(QWidget *parent)
: QWidget(parent), ui(new Ui::statistics)
{
ui->setupUi(this);
this->setAcceptDrops(true);
on_pbn_clear_result_clicked();
initForm();
}
statistics::~statistics()
{
delete ui;
}
void statistics::initForm()
{
resize(1000, 800);
QStringList head_text;
head_text << "文件名"
<< "类型"
<< "大小"
<< "总行数"
<< "代码行数"
<< "注释行数"
<< "空白行数"
<< "路径";
QList<int> column_width;
column_width << 130 << 50 << 70 << 80 << 70 << 70 << 70 << 150;
int num_column = head_text.size();
ui->tbw_show_message->setColumnCount(num_column);
ui->tbw_show_message->setHorizontalHeaderLabels(head_text);
ui->tbw_show_message->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tbw_show_message->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tbw_show_message->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tbw_show_message->verticalHeader()->setVisible(false);
ui->tbw_show_message->verticalHeader()->setDefaultSectionSize(20);
ui->tbw_show_message->verticalHeader()->setHighlightSections(false);
ui->tbw_show_message->horizontalHeader()->setStretchLastSection(true);
ui->tbw_show_message->horizontalHeader()->setHighlightSections(false);
for (int i = 0; i < num_column; i++) {
ui->tbw_show_message->setColumnWidth(i, column_width.at(i));
}
ui->le_num_file->setStyleSheet("color:#17A086");
ui->le_num_byte->setStyleSheet("color:#17A086");
ui->le_num_line->setStyleSheet("color:#17A086");
ui->le_line_code->setStyleSheet("color:#17A086");
ui->le_line_note->setStyleSheet("color:#17A086");
ui->le_line_blank->setStyleSheet("color:#17A086");
QFont font;
font.setBold(true);
font.setPixelSize(18);
ui->le_num_file->setFont(font);
ui->le_num_byte->setFont(font);
ui->le_num_line->setFont(font);
ui->le_line_code->setFont(font);
ui->le_line_note->setFont(font);
ui->le_line_blank->setFont(font);
ui->le_select_type->setPlaceholderText("例如:*.h *.c *.cpp");
}
bool statistics::checkFile(const QString &file_name)
{
QFileInfo file(file_name);
QString suffix = "*." + file.suffix();
QString filter = ui->le_select_type->text().trimmed();
QStringList filters = filter.split(" ");
return filters.contains(suffix);
}
void statistics::countPathFileNumber(const QString &file_path)
{
QDir dir(file_path);
QFileInfoList files_info = dir.entryInfoList();
foreach (QFileInfo file_info, files_info) {
QString file_name = file_info.fileName();
if (file_info.isFile()) {
if (checkFile(file_name)) {
list_files << file_info.filePath();
}
} else {
if (file_name == "." || file_name == "..") {
continue;
}
countPathFileNumber(file_info.absoluteFilePath());
}
}
}
void statistics::countFileRows(const QStringList &files)
{
int num_code_line;
int num_blank_line;
int num_note_line;
int num_files = files.count();
on_pbn_clear_result_clicked();
ui->tbw_show_message->setRowCount(num_files);
quint32 total_lines = 0;
quint32 total_bytes = 0;
quint32 total_codes = 0;
quint32 total_notes = 0;
quint32 total_blank = 0;
for (int i = 0; i < num_files; i++) {
QFileInfo file_info(files.at(i));
countCodeRows(file_info.filePath(), num_code_line, num_blank_line,
num_note_line);
int num_line_all = num_code_line + num_blank_line + num_note_line;
QTableWidgetItem *item_name = new QTableWidgetItem;
item_name->setText(file_info.fileName());
QTableWidgetItem *item_suffix = new QTableWidgetItem;
item_suffix->setText(file_info.suffix());
QTableWidgetItem *item_size = new QTableWidgetItem;
item_size->setText(QString::number(file_info.size()));
QTableWidgetItem *item_line = new QTableWidgetItem;
item_line->setText(QString::number(num_line_all));
QTableWidgetItem *item_code = new QTableWidgetItem;
item_code->setText(QString::number(num_code_line));
QTableWidgetItem *item_note = new QTableWidgetItem;
item_note->setText(QString::number(num_note_line));
QTableWidgetItem *item_blank = new QTableWidgetItem;
item_blank->setText(QString::number(num_blank_line));
QTableWidgetItem *item_path = new QTableWidgetItem;
item_path->setText(file_info.filePath());
item_name->setTextAlignment(Qt::AlignCenter);
item_suffix->setTextAlignment(Qt::AlignCenter);
item_size->setTextAlignment(Qt::AlignCenter);
item_line->setTextAlignment(Qt::AlignCenter);
item_code->setTextAlignment(Qt::AlignCenter);
item_note->setTextAlignment(Qt::AlignCenter);
item_blank->setTextAlignment(Qt::AlignCenter);
item_path->setTextAlignment(Qt::AlignCenter);
ui->tbw_show_message->setItem(i, 0, item_name);
ui->tbw_show_message->setItem(i, 1, item_suffix);
ui->tbw_show_message->setItem(i, 2, item_size);
ui->tbw_show_message->setItem(i, 3, item_line);
ui->tbw_show_message->setItem(i, 4, item_code);
ui->tbw_show_message->setItem(i, 5, item_note);
ui->tbw_show_message->setItem(i, 6, item_blank);
ui->tbw_show_message->setItem(i, 7, item_path);
total_bytes += file_info.size();
total_lines += num_line_all;
total_codes += num_code_line;
total_notes += num_note_line;
total_blank += num_blank_line;
if (i % 100 == 0) {
qApp->processEvents();
}
}
list_files.clear();
ui->le_num_file->setText(QString::number(num_files));
ui->le_num_line->setText(QString::number(total_lines));
ui->le_line_note->setText(QString::number(total_notes));
ui->le_line_blank->setText(QString::number(total_blank));
QString suf = "Bytes";
if (total_bytes > 1024) {
total_bytes = total_bytes / 1024;
suf = "KB";
}
if (total_bytes > 1024) {
total_bytes = total_bytes / 1024;
suf = "MB";
}
if (total_bytes > 1024) {
total_bytes = total_bytes / 1024;
suf = "GB";
}
ui->le_num_byte->setText(QString::number(total_bytes) + suf);
ui->le_line_code->setText(QString::number(total_codes));
double percent = 0.0;
percent = ((double)total_codes / total_lines) * 100;
ui->lbl_percent_code_row->setText(
QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
percent = ((double)total_blank / total_lines) * 100;
ui->lbl_percent_blank_row->setText(
QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
percent = ((double)total_notes / total_lines) * 100;
ui->lbl_percent_note_row->setText(
QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}
void statistics::countCodeRows(const QString &file_name, int &num_line_code,
int &num_line_blank, int &num_line_note)
{
num_line_code = num_line_blank = num_line_note = 0;
QFile file(file_name);
if (file.open(QFile::ReadOnly)) {
QTextStream in(&file);
QString line;
bool is_note = false;
while (!in.atEnd()) {
line = in.readLine();
if (line.startsWith(" ")) {
line.remove(" ");
}
if (line.startsWith("/*")) {
is_note = true;
}
if (is_note) {
num_line_note++;
} else {
if (line.startsWith("//")) {
num_line_note++;
} else if (line.isEmpty()) {
num_line_blank++;
} else {
num_line_code++;
}
}
if (line.endsWith("*/")) {
is_note = false;
}
}
}
}
void statistics::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void statistics::dropEvent(QDropEvent *event)
{
const QMimeData *mine_data = event->mimeData();
list_files.clear();
if (mine_data->hasUrls()) {
QList<QUrl> url_list = mine_data->urls();
QFileInfo file_info;
for (int i = 0; i < url_list.size(); i++) {
QString file_path = url_list.at(i).toLocalFile();
file_info.setFile(file_path);
if (file_info.isDir()) {
countPathFileNumber(file_path);
} else {
if (checkFile(file_path)) {
list_files << file_path;
}
}
}
}
countFileRows(list_files);
}
void statistics::on_pbn_open_file_clicked()
{
QString filter =
QString("代码后缀(%1)").arg(ui->le_file_name->text().trimmed());
QStringList files =
QFileDialog::getOpenFileNames(this, "选择文件", "./", filter);
if (filter.size() > 0) {
ui->le_file_name->setText(files.join("|"));
countFileRows(files);
}
}
void statistics::on_pbn_open_catalog_clicked()
{
QString path = QFileDialog::getExistingDirectory(
this, "选择目录", "./",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!path.isEmpty()) {
ui->le_catalog_name->setText(path);
list_files.clear();
countPathFileNumber(path);
countFileRows(list_files);
}
}
void statistics::on_pbn_clear_result_clicked()
{
ui->le_num_file->setText("0");
ui->le_num_byte->setText("0");
ui->le_num_line->setText("0");
ui->le_line_code->setText("0");
ui->le_line_note->setText("0");
ui->le_line_blank->setText("0");
ui->tbw_show_message->setRowCount(0);
ui->lbl_percent_code_row->setText("00.00%");
ui->lbl_percent_note_row->setText("00.00%");
ui->lbl_percent_blank_row->setText("00.00%");
}
statistics.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>statistics</class>
<widget class="QWidget" name="statistics">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>statistics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tbw_show_message"/>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="7">
<widget class="QPushButton" name="pbn_open_file">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>打开文件</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_5">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>注释行数</string>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QPushButton" name="pbn_clear_result">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>清空结果</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>代码行数</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_6">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>空白行数</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLineEdit" name="le_file_name">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>文件数</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>字节数</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="label_7">
<property name="minimumSize">
<size>
<width>35</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>35</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>文件</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="le_line_note">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="le_line_code">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QLineEdit" name="le_catalog_name">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QPushButton" name="pbn_open_catalog">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>打开目录</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>总行数</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="le_num_byte">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="le_line_blank">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QLineEdit" name="le_select_type">
<property name="text">
<string>*.h *.cpp *.c</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
<width>35</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>35</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>过滤</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="le_num_file">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="le_num_line">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLabel" name="label_8">
<property name="minimumSize">
<size>
<width>35</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>35</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>目录</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="lbl_percent_code_row">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="lbl_percent_note_row">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="lbl_percent_blank_row">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
效果