From 93f783e53bd636bf4d89a0ea7cb3b5a71f58db16 Mon Sep 17 00:00:00 2001 From: tianzhendong <1203886034@qq.com> Date: Fri, 17 Jun 2022 11:51:57 +0800 Subject: [PATCH] =?UTF-8?q?20220617,=E5=88=9D=E7=89=88v1.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 84 ++++++++ CMakeLists.txt | 53 +++++ README.md | 8 + favicon.ico | Bin 0 -> 4286 bytes resources/close.png | Bin 0 -> 342 bytes resources/fullscreen3.png | Bin 0 -> 352 bytes resources/fullscreen4.png | Bin 0 -> 357 bytes resources/min.png | Bin 0 -> 150 bytes src/DuplicateFiles.cpp | 75 +++++++ src/DuplicateFiles.h | 40 ++++ src/main.cpp | 10 + src/widget.cpp | 178 ++++++++++++++++ src/widget.h | 68 +++++++ src/widget.ui | 415 ++++++++++++++++++++++++++++++++++++++ 14 files changed, 931 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 favicon.ico create mode 100644 resources/close.png create mode 100644 resources/fullscreen3.png create mode 100644 resources/fullscreen4.png create mode 100644 resources/min.png create mode 100644 src/DuplicateFiles.cpp create mode 100644 src/DuplicateFiles.h create mode 100644 src/main.cpp create mode 100644 src/widget.cpp create mode 100644 src/widget.h create mode 100644 src/widget.ui diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c96e9d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe +build*/ +build-* +build-*/ +build* +!.vscode +debug/ +debug +release/ +release +cmake-build*/ +.idea/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..20b6aaa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.22) +project(DuplicateFilesCheck) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +set(CMAKE_PREFIX_PATH "C:/Qt/Qt5.14.2/5.14.2/mingw73_64") + +find_package(Qt5 COMPONENTS + Core + Gui + Widgets + REQUIRED) + +include_directories(resources) + +add_executable(DuplicateFilesCheck src/main.cpp app_win32.rc src/widget.cpp src/widget.h src/widget.ui src/DuplicateFiles.cpp src/DuplicateFiles.h) +target_link_libraries(DuplicateFilesCheck + Qt5::Core + Qt5::Gui + Qt5::Widgets + ) + +if (WIN32) + set(DEBUG_SUFFIX) + if (MSVC AND CMAKE_BUILD_TYPE MATCHES "Debug") + set(DEBUG_SUFFIX "d") + endif () + set(QT_INSTALL_PATH "${CMAKE_PREFIX_PATH}") + if (NOT EXISTS "${QT_INSTALL_PATH}/bin") + set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..") + if (NOT EXISTS "${QT_INSTALL_PATH}/bin") + set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..") + endif () + endif () + if (EXISTS "${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory + "$/plugins/platforms/") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll" + "$/plugins/platforms/") + endif () + foreach (QT_LIB Core Gui Widgets) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${QT_INSTALL_PATH}/bin/Qt5${QT_LIB}${DEBUG_SUFFIX}.dll" + "$") + endforeach (QT_LIB) +endif () diff --git a/README.md b/README.md new file mode 100644 index 0000000..b0bb339 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# 重复文件检测工具 +## 环境 +- Clion 2022.1.2 +- qt 5.14.2 +## 功能 +- 单个文件计算md5 +- 文件夹内重复文件检测 + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4f497c59a101e9671abae72d53386bdef8f1f12a GIT binary patch literal 4286 zcmcIm2~q12%-jS6hR4sD7zq{C?IR1V2a>E z5Zb86)}YLJvfqo$3KCMRv$qkaAE%;5xO3HIon^UZtjzxV#%fA7EC z3&{8zH45S%yKMm#0B3?C_!2^HZ0xJIHo+w5`9DUZL7Yx!nWWc`N!05-Qk|SeFE0iTz%yTwHo4>Y<18L45-` zKbo9D1=7wLoHL8>p+qqIBhn29w;VUO9$2~; zA6NoJYa9uUlKND%#XLc$lM7I%f_7MNjrL2m+7~FZNYXo5#Ow4zu6)DM(TaQ1pS<#Q z?(T|QH#d2u*UQ)y)jd~t(!DXjd$DGau8Q7jLc*?4H6#hx7pB6s639Xo-l$g1g|u}r z&gVhavK}%YybNh4%%tz>as(R3H>`&2-g@BlO5n=c?%2A@sw05Ni7;zfhk#GB;Um=o zA1;UHPfOt0kOrTl$?!Ru3co!u&>TyKfx3Nbaw_xefs8=lS`NVZQ_ie} zH`jv?mchWa`~M*tF54quAjic0vCtn$!fe_W(wL56UkO?KtG%%UI~D=&F2cZLDVWr} z3Nz`uspOfoI~w+U4&i=4_@^|?7!zPDfPL5&4omuY%8n=)8dqRG`6qMDG3?WFFJ7XL ztcCxV2lURrXEDHi6Z@^)zXZyCu~2>x4+VV>>cy=hz})O{9fuMC+6Kmiyqx>8dK%=v zTL{IUmqJNjDMa2hWdNV_A^z7)0}AMa%5b1+f$7P$A$$TbfBfUT9beNtOm8A@=o=J< z0wu2jHIcxE*{0{NH#$c5{&XDyj2Q(?a02v00V~U{4`z89Dd-*hN%4opT5oR?B%<*gt{O0$-7nQ)5#Qk?oI-81Mf2|Du zpKnFpt#@$z&UUojt;RRR-|tkTrL7V*w8{O!PSg0O;h({EUfu{CSqrBt8?mmX0`V=I z5yWRu>t@8#mddZT0k*YodfK1PcTs(w z@2tL`Z%}_ve3$2}`mA`OT?&0=Q{-=jbe%n3w3PSRjNG}Vq0;-z?Nkh>9lxm0hu7O7 z{rs{#2F7LSR8={8bu&4?Ep$;oDsojzPols@-M+@4S`q1BYq>&ik3v^9Mq76i%sp7; z$2j+>ky-4XD9eC6FT2SFFAWOMHmK6G_3DaTCv|O} zv-%3T|3<$55D#;lRa;WEgVdR{q0D1Q4{TkCUavsr?Z{zh4b&lK zl$|B{&1b)8-3wdyT|?}67M2-f5yx}kz!*F$xbAMpkBx;`)V2-hI`}(38UF>+O<=mF zAHql2B1k;|AwvdqPx3QTE!`$+$q%~$)|lTg-~T0iac(`5nUn8z<`wVk|2Jbcl(r(3 zwfI@IxIkb(&!3&iux9N$A^dQm6q)qTjwksUr&kZH!7$b@DEgjueKJ$3<2m+Qq|(n4 zYuw7uDzLjVzt|V%OODvDxT$?o+2=u#yt`d0HRgm5^YOu%w-7J(qBB3&{>h0vIEt9v zu&~dn`#g~KK%9BQnF~!H7b5ERJNUALpML*=wR@g)%%qNYrDxu%mI4P>!j5ZS$1^sI z`~67p(;tr*3k9s5@_mex{Q1wE+Ndz^b>2_rL(aN9p1F5Qa0?qmecGP^D{)4PxO*Ng zf_KL>p64RAnBS=))>sGr$+NNW{Y+SKPjHE6=ksV|9m#u^cLC-!^WKMkzsnlf%GwmU zF$(g=BGdgxqkbOjz(U5pxKo{22M6ZdKE{0|YmBQ@4=~s9VLsq6`1x=Pt>L~#-LfOu zc=cil{7M(Wf m-$vlS1Vh6{%EnshB+EgPo4e@tdiX$7!jJ)eH%lgX7y1vS o3;mDSHOq+KYJlJDf!=QO08#`ue3H3_7XSbN07*qoM6N<$g0j|&GXMYp literal 0 HcmV?d00001 diff --git a/resources/fullscreen3.png b/resources/fullscreen3.png new file mode 100644 index 0000000000000000000000000000000000000000..466b71181c5a48ea854d4fdb75ad0a74fc9de29e GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fq_xT z)5S3)qw(#myIf5U0Nodt_`?2R*DAfk<)+tPvGuoJJ|~{^IXrdYN;yHsdB*E+{t$S2#_5mt zJY}YkCHEUw7U^AK<7Qv(+cI-$LcY7y-+PsYd!Ap literal 0 HcmV?d00001 diff --git a/resources/fullscreen4.png b/resources/fullscreen4.png new file mode 100644 index 0000000000000000000000000000000000000000..401b0a8f5ac69832dc4cd47e8f6b204dc27654d7 GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fq_xn z)5S3)qw(!5M?S_t0hj+>1YJ_W{i4qC8^sZ9DfTTym(V63F#*GX|<<pOw;vC#QZQbr6}nI{-lELCJ)Fs+TJ0W6@&bC)UHp}zDNW8r$g z8wXZKC$N9HVO=|sNloXP-DJfmz}uP4L6=vO vVXH|B14Q8Q^Z#!W1Mj@!RJrE1ML)0oVNr95C|4LT+!#Dv{an^LB{Ts5i;;`= literal 0 HcmV?d00001 diff --git a/resources/min.png b/resources/min.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd7577319d7d1619456485387aa3ed985e20a17 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DWNDCpto z;uwbP0l+XkKV&N@Q literal 0 HcmV?d00001 diff --git a/src/DuplicateFiles.cpp b/src/DuplicateFiles.cpp new file mode 100644 index 0000000..8d544a6 --- /dev/null +++ b/src/DuplicateFiles.cpp @@ -0,0 +1,75 @@ +// +// Created by 12038 on 2022/6/16. +// +#include "DuplicateFiles.h" + +DuplicateFiles::DuplicateFiles(QObject *) { + +} + +DuplicateFiles::~DuplicateFiles() { + +} + +void DuplicateFiles::calMd5Slot(const QString &filePath) { + QByteArray md5 = calMd5(filePath); + emit md5Signal(md5); +} + +QByteArray DuplicateFiles::calMd5(const QString &filePath) { + QFile file(filePath); + QByteArray md5 = ""; + if(file.open(QIODevice::ReadOnly)){ + QCryptographicHash hash(QCryptographicHash::Md5); + while(!file.atEnd()){ + QByteArray buff = file.read(100 * 1024 * 1024); + hash.addData(buff); + } + md5 = hash.result().toHex(); + file.close(); + } + return md5; +} + +void DuplicateFiles::getFilesSlot(const QString &filesDirPath) { + //获取文件夹下所有的文件 + QStringList files= this->getFiles(filesDirPath); + //计算md5,并存到map中 + QHash md5Results; + for (int i = 0; i < files.count(); i++){ + QString fileName = files.at(i); + QByteArray fileMd5 = calMd5(fileName); + md5Results[fileMd5].append(fileName); + qDebug() <<"file:" << fileName << "md5:"<< fileMd5; + emit process(i + 1, files.count()); + } + //找出map中value大于1的 + for (QHash::iterator itr = md5Results.begin(); itr != md5Results.end(); itr++){ + if(itr.value().count() > 1){ + qDebug()<< "md5:"< fileInfoList = filesDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + for(int i = 0; i < fileInfoList.count(); i++){ + QFileInfo fileInfo = fileInfoList.at(i); + if(fileInfo.isDir()){ + QStringList subFiles= getFiles(fileInfo.absoluteFilePath()); + files.append(subFiles); + } + else{ + QString fileName = fileInfo.absoluteFilePath(); + files.append(fileName); + } + } + return files; +} + diff --git a/src/DuplicateFiles.h b/src/DuplicateFiles.h new file mode 100644 index 0000000..f0e8220 --- /dev/null +++ b/src/DuplicateFiles.h @@ -0,0 +1,40 @@ +// +// Created by 12038 on 2022/6/16. +// + +#ifndef DUPLICATEFILESCHECK_DUPLICATEFILES_H +#define DUPLICATEFILESCHECK_DUPLICATEFILES_H + +#include +#include +#include +#include +#include +#include + +class DuplicateFiles : public QObject{ +Q_OBJECT + +public: + DuplicateFiles(QObject *parent = nullptr); + ~DuplicateFiles(); + +signals: + void md5Signal(const QByteArray &); + void filesSignal(const QStringList &); + void process(const int &, const int &); + void duplicateFilesSignal(const QHash &); + +public slots: + void getFilesSlot(const QString & filesDirPath); + void calMd5Slot(const QString &filePath); + +private: + QByteArray calMd5(const QString &filePath); + QStringList getFiles(const QString &); + QHash duplicateFiles; + +}; + + +#endif //DUPLICATEFILESCHECK_DUPLICATEFILES_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..a20479a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,10 @@ +#include +#include "widget.h" + +int main(int argc, char *argv[]) { + QApplication a(argc, argv); + qRegisterMetaType>("QHash"); + Widget w; + w.show(); + return QApplication::exec(); +} diff --git a/src/widget.cpp b/src/widget.cpp new file mode 100644 index 0000000..cf0455d --- /dev/null +++ b/src/widget.cpp @@ -0,0 +1,178 @@ +// +// Created by 12038 on 2022/6/15. +// + +// You may need to build the project (run Qt uic code generator) to get "ui_Widget.h" resolved + +#include "widget.h" +#include "ui_widget.h" + +Widget::Widget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::Widget) +{ + ui->setupUi(this); + //取消菜单栏 + this->setWindowFlags(Qt::FramelessWindowHint); + + //阴影边框效果 + QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(); + shadow->setBlurRadius(10); + shadow->setColor(Qt::black); + shadow->setOffset(0); + + ui->shadowWidget->setGraphicsEffect(shadow); + + //父窗口透明 + this->setAttribute(Qt::WA_TranslucentBackground); + + //最大化最小化关闭功能实现 + connect(ui->btnMax, SIGNAL(clicked()), this, SLOT(btnMaxClickedSlot())); + connect(ui->btnMin, SIGNAL(clicked()), this, SLOT(btnMinClickedSlot())); + connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(btnCloseClickedSlot())); + + ui->btnMin->setStyleSheet("border-image: url(../resources/min.png)"); + ui->btnMax->setStyleSheet("border-image: url(../resources/fullscreen3.png)"); + ui->btnClose->setStyleSheet("border-image: url(../resources/close.png)"); + + + duplicateFiles = new DuplicateFiles(); + myThread = new QThread(); + duplicateFiles->moveToThread(myThread); + myThread->start(); + connect(duplicateFiles, SIGNAL(destroyed(QObject *)), + myThread, SLOT(deleteLater())); + + ui->labelTitle->setText("文件一致性检测工具"); + connect(ui->btnSelectFile, SIGNAL(clicked(bool)), this, SLOT(calMd5ofFileSlot())); + connect(ui->btnSelectDir, SIGNAL(clicked(bool)), this, SLOT(selectDirSlot())); + connect(this, SIGNAL(calFileMd5Signal(const QString &)), + duplicateFiles, SLOT(calMd5Slot(const QString &))); + connect(duplicateFiles, SIGNAL(md5Signal(const QByteArray &)), + this, SLOT(showFileMd5Slot(const QByteArray &))); + connect(this, SIGNAL(getFilesSignal(const QString &)), + duplicateFiles, SLOT(getFilesSlot(const QString &))); + connect(duplicateFiles, SIGNAL(filesSignal(const QStringList &)), + this, SLOT(filesSlot(const QStringList &))); + + connect(duplicateFiles, SIGNAL(process(const int &, const int &)), + this, SLOT(processSlot(const int &, const int &))); + connect(duplicateFiles, SIGNAL(duplicateFilesSignal(const QHash &)), + this, SLOT(duplicateFilesSlot(const QHash &))); + connect(ui->listWidget, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(currentTextChangedSlot(const QString &))); +} + +Widget::~Widget() +{ + duplicateFiles->deleteLater(); + myThread->exit(); + myThread->wait(10 * 1000); + delete ui; +} + +void Widget::mousePressEvent(QMouseEvent *event) +{ +// QWidget::mousePressEvent(event); + QPoint mouseStartPoint = event->globalPos(); + QPoint windowLeftTopPoint = this->geometry().topLeft(); + this->mousePosInWindow = mouseStartPoint - windowLeftTopPoint; +} + +void Widget::mouseMoveEvent(QMouseEvent *event) +{ +// QWidget::mouseMoveEvent(event); + if(this->mousePosInWindow == QPoint()) return; + QPoint mousePoint = event->globalPos(); + QPoint windowLeftTopPoint = mousePoint - this->mousePosInWindow; + this->move(windowLeftTopPoint); +} + +void Widget::mouseReleaseEvent(QMouseEvent *) +{ + this->mousePosInWindow = QPoint(); +} + +void Widget::closeEvent(QCloseEvent *event) +{ + QMessageBox::StandardButton button; + button=QMessageBox::question(this,tr("退出程序"),QString(tr("确认退出程序?")),QMessageBox::Yes|QMessageBox::No); + if(button==QMessageBox::No) + { + event->ignore(); // 忽略退出信号,程序继续进行 + } + else if(button==QMessageBox::Yes) + { + event->accept(); // 接受退出信号,程序退出 + } +} + +void Widget::btnMaxClickedSlot() +{ + ui->btnMax->setStyleSheet("border-image: url(../resources/fullscreen4.png)"); + if(this->isMaximized()){ + ui->layoutMain->setMargin(9); + ui->btnMax->setStyleSheet("border-image: url(../resources/fullscreen3.png)"); + this->showNormal(); + } + else{ + ui->layoutMain->setMargin(0); + ui->btnMax->setStyleSheet("border-image: url(../resources/fullscreen4.png)"); + this->showMaximized(); + } +} + +void Widget::btnMinClickedSlot() +{ + this->showMinimized(); +} + +void Widget::btnCloseClickedSlot() +{ + this->close(); +} + +void Widget::calMd5ofFileSlot() { + QString path = QFileDialog::getOpenFileName( + this, "选择文件", + "./", + ""); + emit calFileMd5Signal(path); +} + +void Widget::showFileMd5Slot(const QByteArray & md5) { + ui->leMd5Show->setText(""); + ui->leMd5Show->setText(md5); +} + +void Widget::selectDirSlot() { + ui->progressBar->setValue(0); + QString dirPathUrl = QFileDialog::getExistingDirectory(this, "选择文件夹", "./"); + ui->lineDIrShow->setText(dirPathUrl); + emit getFilesSignal(dirPathUrl); +} + +void Widget::filesSlot(const QStringList &files) { + ui->listWidget_2->clear(); + ui->listWidget_2->addItems(files); +} + +void Widget::processSlot(const int &now, const int &total) { + ui->progressBar->setMaximum(total); + ui->progressBar->setValue(now); +} + +void Widget::duplicateFilesSlot(const QHash &duplicateFiles) { + ui->listWidget->clear(); + this->duplicateResults = duplicateFiles; + for(QHash::const_iterator itr = duplicateFiles.begin(); itr != duplicateFiles.end(); itr++){ + ui->listWidget->addItem(itr.key()); + } +} + +void Widget::currentTextChangedSlot(const QString ¤tText) { + ui->listWidget_2->clear(); + ui->listWidget_2->addItems(this->duplicateResults[currentText.toLocal8Bit()]); +} + + diff --git a/src/widget.h b/src/widget.h new file mode 100644 index 0000000..bcaa9cc --- /dev/null +++ b/src/widget.h @@ -0,0 +1,68 @@ +// +// Created by 12038 on 2022/6/15. +// + +#ifndef DUPLICATEFILESCHECK_WIDGET_H +#define DUPLICATEFILESCHECK_WIDGET_H + +#include +#include +#include +#include +#include +#include "DuplicateFiles.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class Widget; } +QT_END_NAMESPACE + +class Widget : public QWidget +{ +Q_OBJECT + +public: + Widget(QWidget *parent = nullptr); + ~Widget(); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + void closeEvent(QCloseEvent *event); + +signals: + void calFileMd5Signal(const QString &path); + void getFilesSignal(const QString &dirPath); + +public slots: + void showFileMd5Slot(const QByteArray &); + void filesSlot(const QStringList &); + void processSlot(const int &, const int &); + void duplicateFilesSlot(const QHash &); + void currentTextChangedSlot(const QString &); + +private slots: + void btnMaxClickedSlot(); + void btnMinClickedSlot(); + void btnCloseClickedSlot(); + void calMd5ofFileSlot(); + void selectDirSlot(); + +private: + Ui::Widget *ui; + DuplicateFiles * duplicateFiles; + QThread *myThread; + + QPoint mousePosInWindow = QPoint(); + QHash duplicateResults; + + +}; + + +#endif //DUPLICATEFILESCHECK_WIDGET_H diff --git a/src/widget.ui b/src/widget.ui new file mode 100644 index 0000000..3363358 --- /dev/null +++ b/src/widget.ui @@ -0,0 +1,415 @@ + + + Widget + + + + 0 + 0 + 800 + 600 + + + + Widget + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + #shadowWidget{ + background-color: rgb(255, 255, 255); + border-radius: 5px; + } + + + + + 9 + + + 9 + + + 9 + + + 0 + + + 0 + + + + + 0 + + + 9 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 微软雅黑 + 14 + + + + windowTitle + + + Qt::AlignCenter + + + + + + + + 36 + 36 + + + + + 36 + 36 + + + + + 14 + 50 + false + + + + QPushButton + { + border:none; + } + + QPushButton:hover + { + background-color: rgb(232, 232, 232); + } + QPushButton:pressed + { + background-color: rgb(162, 162, 162); + } + + + + + + + + + + + + + + false + + + + 30 + 36 + + + + + 30 + 36 + + + + + 14 + 50 + false + + + + QPushButton + { + border:none; + } + + QPushButton:hover + { + background-color: rgb(232, 232, 232); + } + QPushButton:pressed + { + background-color: rgb(162, 162, 162); + } + + + + + + + + + + + + + + + 36 + 36 + + + + + 36 + 36 + + + + + 14 + 50 + false + + + + QPushButton + { + border:none; + } + + QPushButton:hover + { + background-color: rgb(232, 232, 232); + } + QPushButton:pressed + { + background-color: rgb(162, 162, 162); + } + + + + + + + + + + + + + + false + + + + 30 + 36 + + + + + 30 + 36 + + + + + 14 + 50 + false + + + + QPushButton + { + border:none; + } + + QPushButton:hover + { + background-color: rgb(232, 232, 232); + } + QPushButton:pressed + { + background-color: rgb(162, 162, 162); + } + + + + + + + + + + + + + + + 36 + 36 + + + + + 36 + 36 + + + + + 14 + 50 + false + + + + QPushButton + { + border:none; + border-top-right-radius: 5px; + } + + QPushButton:hover + { + background-color: rgb(253, 0, 0); + } + QPushButton:pressed + { + background-color: rgb(211, 0, 0); + } + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + Qt::LeftToRight + + + 文件Md5计算 + + + Qt::AlignCenter + + + + + + 选择文件 + + + + + + + + + + + + + 目录重复文件检测 + + + Qt::AlignCenter + + + + + + + + 选择目录 + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + +