Ai
1 Star 0 Fork 0

Notepad-- Community/filesearch

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
filesearchwin.cpp 16.13 KB
一键复制 编辑 原始数据 按行查看 历史
爬山虎 提交于 2023-12-16 15:15 +08:00 . 提交全部代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
#include "filesearchwin.h"
#include "searchfiledata.h"
#include "progresswin.h"
#include "QTreeWidgetSortItem.h"
#include "../global/rcglobal.h"
#include <QFileInfo>
#include <QFileDialog>
#include <QMessageBox>
#include <QTreeWidgetItem>
#include <QDateTime>
#include <QMenu>
#include <QProcess>
#include <QSettings>
#include <QClipboard>
static const QString FILE_NAME_REGULAR = "namere";
static const QString FILE_SUFFIX_TYPE = "suffix";
QStringList FileSearchWin::s_fileNameReHistroy;
QStringList FileSearchWin::s_fileSuffixHistroy;
extern std::function<bool(QWidget*, int, void*)> s_invokeMainFun;
FileSearchWin::FileSearchWin(QWidget *parent)
: QMainWindow(parent), m_workThread(nullptr), m_fileSearchDataThread(nullptr), m_loadFileProcessWin(nullptr),
m_searchDirFinished(false), m_menu(nullptr)
{
ui.setupUi(this);
ui.treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui.treeWidget->setAlternatingRowColors(true);
connect(ui.treeWidget, &QTreeWidget::itemPressed, this, &FileSearchWin::on_itemClicked);
ui.fileNameRe->setCompleter(nullptr);
ui.fileSuffixType->setCompleter(nullptr);
QHeaderView* headView = ui.treeWidget->header();
//禁用自定义排序,点击手动去排序
ui.treeWidget->setSortingEnabled(false);
headView->setSortIndicatorShown(true);
headView->setSectionsClickable(true);
connect(headView, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(on_sort(int, Qt::SortOrder)));
createWorkThread();
readHistory();
s_invokeMainFun(parent, 7, nullptr);
}
FileSearchWin::~FileSearchWin()
{
if (m_workThread != nullptr)
{
m_workThread->quit();
m_workThread->wait();
delete m_workThread;
m_workThread = nullptr;
}
saveHistory();
}
void FileSearchWin::on_sort(int logicalIndex, Qt::SortOrder order)
{
QTreeWidgetSortItem::setSortColumn(logicalIndex);
disconnect(ui.treeWidget->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(on_sort(int, Qt::SortOrder)));
ui.treeWidget->sortItems(logicalIndex, order);
connect(ui.treeWidget->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(on_sort(int, Qt::SortOrder)));
}
#if 0
//引用global
void showFileInExplorer(QString path)
{
QString cmd;
#ifdef _WIN32
path = path.replace("/", "\\");
cmd = QString("explorer.exe /select,\"%1\"").arg(path);
#endif
#ifdef ubu
path = path.replace("\\", "/");
cmd = QString("nautilus %1").arg(path);
#endif
#ifdef uos
path = path.replace("\\", "/");
cmd = QString("dde-file-manager %1").arg(path);
#endif
#if defined(Q_OS_MAC)
path = path.replace("\\", "/");
cmd = QString("open -R %1").arg(path);
#endif
QProcess process;
process.startDetached(cmd);
}
#endif
struct Item_info {
QString filePath;
QTreeWidgetItem* pItem;
Item_info()
{
}
Item_info(QString filePath_, QTreeWidgetItem* pItem_):filePath(filePath_), pItem(pItem_)
{
}
};
void FileSearchWin::on_delSelectedFiles()
{
QTreeWidgetItemIterator it(ui.treeWidget);
QVector<Item_info> delList;
delList.reserve(100);
while (*it)
{
if (Qt::Checked == (*it)->checkState(0))
{
Item_info v((*it)->toolTip(0), *it);
delList.append(v);
}
++it;
}
if (delList.size() == 0)
{
QMessageBox::information(this, tr("Error"), tr("Please check and select file first !"));
return;
}
int failTimes = 0;
if (QMessageBox::Yes == QMessageBox::question(this, tr("Delete this files ?"), tr("Do you want to delete these %1 files").arg(delList.size())))
{
for (int i = 0; i < delList.size(); ++i)
{
bool ok = QFile::remove(delList.at(i).filePath);
if (!ok)
{
++failTimes;
delList.at(i).pItem->setText(4, tr("del failed "));
}
else
{
delList.at(i).pItem->setText(4, tr("del success "));
}
QCoreApplication::processEvents();
}
ui.statusBar->showMessage(tr("Select %1 files, Delete %2 files, failed %3 files .").arg(delList.size()).arg(delList.size() - failTimes).arg(failTimes));
}
}
//右键菜单
void FileSearchWin::on_itemClicked(QTreeWidgetItem* item, int /*column*/)
{
if ((item != nullptr) && (Qt::RightButton == QGuiApplication::mouseButtons() || Qt::NoButton == QGuiApplication::mouseButtons()))
{
if (m_menu == nullptr)
{
m_menu = new QMenu(this);
m_menu->addAction(tr("&Select All"), this, &FileSearchWin::on_selectAll);
m_menu->addAction(tr("&Select None"), this, &FileSearchWin::on_selectNone);
m_menu->addAction(tr("&Copy FilePath"), this, [&]() {
QTreeWidgetItem* it = ui.treeWidget->currentItem();
QString path = QString("%1").arg(it->data(0, Qt::ToolTipRole).toString());
QClipboard* clipboard = QGuiApplication::clipboard();
clipboard->setText(path);
});
m_menu->addAction(tr("&Show File in Explorer..."), this, [&]() {
QString path, cmd;
QTreeWidgetItem* it = ui.treeWidget->currentItem();
if (it == nullptr)
{
return;
}
path = QString("%1").arg(it->data(0, Qt::ToolTipRole).toString());
showFileInExplorer(path);
});
m_menu->addSeparator();
m_menu->addAction(tr("&Delete Selected Files"), this, &FileSearchWin::on_delSelectedFiles);
}
m_menu->move(QCursor::pos());
m_menu->show();
}
else
{
QTreeWidgetItem* it = ui.treeWidget->currentItem();
if (it == nullptr)
{
return;
}
QString path = QString("%1").arg(it->data(0, Qt::ToolTipRole).toString());
ui.statusBar->showMessage(path);
}
}
void FileSearchWin::on_clear()
{
ui.treeWidget->clear();
}
void FileSearchWin::on_selectAll()
{
QTreeWidgetItemIterator it(ui.treeWidget);
while (*it)
{
if (Qt::Unchecked == (*it)->checkState(0))
{
(*it)->setCheckState(0, Qt::Checked);
}
++it;
}
}
void FileSearchWin::on_selectNone()
{
QTreeWidgetItemIterator it(ui.treeWidget);
while (*it)
{
if (Qt::Checked == (*it)->checkState(0))
{
(*it)->setCheckState(0, Qt::Unchecked);
}
++it;
}
}
//开始查找。
void FileSearchWin::on_search()
{
assert(m_fileSearchDataThread != nullptr);
m_fileSearchDataThread->setCancel(false);
m_fileSearchDataThread->setIsDone(false);
m_searchDirFinished = false;
QString searchPath = ui.searchDirLineEdit->text();
if (searchPath.isEmpty())
{
QApplication::beep();
QMessageBox::warning(this, tr("Error"), tr("Please select search Dir filepath !"));
return;
}
int maxResultNum = ui.maxResultNum->value();
bool isFileNameRe = ui.isFileNameRegularMatch->isChecked();
QString fileNameRe = ui.fileNameRe->currentText();
if (isFileNameRe)
{
QRegularExpression re(fileNameRe);
if (!re.isValid())
{
QApplication::beep();
QMessageBox::warning(this, tr("Error"), tr("FileName Regular Match invalid, please check !"));
return;
}
//增加历史记录
addFileNameReHistory(fileNameRe);
}
bool isFileSuffixType = ui.isFileSuffixType->isChecked();
QString fileSuffixTypeStr = ui.fileSuffixType->currentText();
QStringList fileSuffixType;
if (isFileSuffixType)
{
fileSuffixType = fileSuffixTypeStr.split('|');
//增加历史记录
addSuffixHistory(fileSuffixTypeStr);
}
bool isFileSize = ui.isFileSizeGreaterThan->isChecked();
qint64 fileSizeLimit = ui.fileSizeGreaterThan->value() * 1024 * 1024;
bool isFileCreateTimeLater = ui.isFileCreateTimeLater->isChecked();
QDateTime createTimeLater = ui.createLaterDateTime->dateTime();
bool isFileCreateTimeEarlier = ui.isFileCreateTimeEarlier->isChecked();
QDateTime createTimeEarlier = ui.createEarlierDateTime->dateTime();
bool isFileModifyLater = ui.isFileModifyTimeLater->isChecked();
QDateTime modifyTimeLater = ui.modifyLaterDateTime->dateTime();
bool isFileModifyEarlier = ui.isFileModifyTimeEarlier->isChecked();
QDateTime modifyTimeEarlier = ui.modifyEarlierDateTime->dateTime();
//如果条件一个都没有,则不执行,必须要有一个条件
if (!isFileNameRe && !isFileSuffixType && !isFileSize && !isFileCreateTimeLater && !isFileCreateTimeEarlier \
&& !isFileModifyLater && !isFileModifyEarlier)
{
QApplication::beep();
QMessageBox::warning(this, tr("Error"), tr("Please enter at least one search criteria !"));
return;
}
if (m_loadFileProcessWin == nullptr)
{
m_loadFileProcessWin = new ProgressWin(this);
}
m_loadFileProcessWin->setWindowModality(Qt::WindowModal);
m_loadFileProcessWin->info(tr("search dir file tree in progress, please wait ..."));
m_loadFileProcessWin->show();
m_loadDirCancel = false;
m_searchDirFinished = false;
ui.treeWidget->clear();
emit s_walkFile(searchPath, maxResultNum, ui.isNoSymlink->isChecked(), isFileNameRe, fileNameRe, isFileSuffixType, fileSuffixType, \
isFileSize, fileSizeLimit, isFileCreateTimeLater, createTimeLater, isFileCreateTimeEarlier, createTimeEarlier, \
isFileModifyLater, modifyTimeLater, isFileModifyEarlier, modifyTimeEarlier);
while (!m_searchDirFinished)
{
QCoreApplication::processEvents();
if (m_loadFileProcessWin->isCancel())
{
m_fileSearchDataThread->setCancel(true);
m_loadDirCancel = true;
}
}
if (m_loadFileProcessWin != nullptr)
{
delete m_loadFileProcessWin;
m_loadFileProcessWin = nullptr;
}
if (m_loadDirCancel)
{
ui.statusBar->showMessage(tr("User cancel ..."));
}
else
{
int foundTime = m_fileSearchDataThread->getFileNums();
ui.statusBar->showMessage(tr("Found %1 files .").arg(foundTime));
}
}
void FileSearchWin::on_selectDir()
{
QFileInfo fi(m_lastFileDir);
QString searchDir = QFileDialog::getExistingDirectory(this, tr("Select Search Directory"),
fi.absolutePath(), QFileDialog::ShowDirsOnly);
if (!searchDir.isEmpty())
{
ui.searchDirLineEdit->setText(searchDir);
}
}
void FileSearchWin::on_childThreadMsg(int type, QString msg, qint64 value)
{
if (m_loadFileProcessWin != nullptr)
{
switch (type)
{
case PROGRESS_INFO:
m_loadFileProcessWin->info(msg);
break;
case SET_PROGRESS_TOTAL_STEPS:
m_loadFileProcessWin->setTotalSteps(value);
break;
case PROGRESS_STEP:
m_loadFileProcessWin->moveStep();
break;
default:
break;
}
}
}
#if 0
const int M_SIZE = 1024 * 1024;
const int G_SIZE = 1024 * 1024 * 1024;
//把字节大小文件,转换为M 或 G 单位
QString tranFileSize(qint64 fileSize)
{
float num = 0.0f;
QString unit;
if (fileSize >= G_SIZE)
{
num = double(fileSize) / G_SIZE;
unit = "GB";
}
else if (fileSize >= M_SIZE)
{
num = double(fileSize) / M_SIZE;
unit = "MB";
}
else if (fileSize > 1024)
{
num = float(fileSize) / 1024;
unit = "KB";
}
else
{
return QString("%1").arg(fileSize);
}
return QString("%1 %2").arg(num, 0, 'f', 2).arg(unit);
}
#endif
QString getShortFilePath(const QString& filePath)
{
if (filePath.size() > 80)
{
//省去中间的字符
//前面取10个,后面取70个
return QString("%1 ... %2").arg(filePath.left(15)).arg(filePath.right(60));
}
return filePath;
}
const int FILE_SIZE = Qt::UserRole + 1;
//增加文件或文件夹节点
void FileSearchWin::on_foundFile(CmpWalkFileInfo* nodeInfo)
{
//最后一个节点槽函数执行完毕后,此时才能认定为加载完毕。
if(-1 == nodeInfo->fileSize)
{
m_searchDirFinished = true;
}
else
{
QStringList items;
items << getShortFilePath(nodeInfo->filePath) << tranFileSize(nodeInfo->fileSize) << nodeInfo->createTime << nodeInfo->modifyTime;
QTreeWidgetItem* pItem = new QTreeWidgetSortItem(items, 1000);
pItem->setData(0, Qt::ToolTipRole, nodeInfo->filePath);
pItem->setData(1, FILE_SIZE, nodeInfo->fileSize);
pItem->setCheckState(0, Qt::Unchecked);
ui.treeWidget->addTopLevelItem(pItem);
}
delete nodeInfo;
}
void FileSearchWin::createWorkThread()
{
//保证只执行一次
if (m_workThread == nullptr)
{
m_workThread = new QThread(this);
m_workThread->start();
//这里不能给parent,否则会导致父子对象不在同一个线程的错误
m_fileSearchDataThread = new SearchFileData(nullptr);
m_fileSearchDataThread->moveToThread(m_workThread);
//下面槽函数会在workThread删除的时候执行
//启动一个工作线程,后面加载目录,在工作线程中执行,分担主界面的工作,避免卡顿。
//m_cmpDataThread 不需要手动释放,在线程退出时,会自动释放该对象。
QObject::connect(m_workThread, &QThread::finished, m_fileSearchDataThread, [&]() {
m_fileSearchDataThread->deleteLater();
m_fileSearchDataThread = nullptr;
});
connect(this, &FileSearchWin::s_walkFile, m_fileSearchDataThread, &SearchFileData::on_walkFile, Qt::QueuedConnection);
connect(m_fileSearchDataThread, &SearchFileData::outMsg, this, &FileSearchWin::on_childThreadMsg, Qt::QueuedConnection);
connect(m_fileSearchDataThread, &SearchFileData::s_foundFile, this, &FileSearchWin::on_foundFile, Qt::QueuedConnection);
}
}
bool FileSearchWin::readHistory()
{
QString settingDir = QString("notepad/filesearch");
QSettings qs(QSettings::IniFormat, QSettings::UserScope, settingDir);
qs.setIniCodec("UTF-8");
if (qs.contains(FILE_NAME_REGULAR))
{
QVariant history = qs.value(FILE_NAME_REGULAR, "");
s_fileNameReHistroy = history.toStringList();
if (!s_fileNameReHistroy.isEmpty())
{
ui.fileNameRe->addItems(s_fileNameReHistroy);
}
}
if (qs.contains(FILE_SUFFIX_TYPE))
{
QVariant suffixHistory = qs.value(FILE_SUFFIX_TYPE, "");
s_fileSuffixHistroy = suffixHistory.toStringList();
if (!s_fileSuffixHistroy.isEmpty())
{
ui.fileSuffixType->addItems(s_fileSuffixHistroy);
}
}
return true;
}
void FileSearchWin::addSuffixHistory(QString& text)
{
//太长会导致看起来很杂乱,也不记录
if (text.isEmpty() || text.size() >= 128)
{
return;
}
int index = s_fileSuffixHistroy.indexOf(text, 0);
//已经是最上面一个了,直接返回
if (0 == index)
{
return;
}
//没有直接添加到最前面。不做查找删除重复,一是慢,而是删除会引起信号逻辑时许有误
if (-1 == index)
{
s_fileSuffixHistroy.push_front(text);
ui.fileSuffixType->insertItem(0, text);
}
else
{
//有了怎么办,删除旧的,加新的
s_fileSuffixHistroy.removeAt(index);
s_fileSuffixHistroy.push_front(text);
//发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。
ui.fileSuffixType->removeItem(index);
ui.fileSuffixType->insertItem(0, text);
//发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。
//必须重新设置一下,否则查找框里面字段乱跳到下一个去了
ui.fileSuffixType->setCurrentIndex(0);
}
if (s_fileSuffixHistroy.size() > 15)
{
s_fileSuffixHistroy.takeLast();
}
}
void FileSearchWin::addFileNameReHistory(QString& text)
{
//太长会导致看起来很杂乱,也不记录
if (text.isEmpty() || text.size() >= 128)
{
return;
}
int index = s_fileNameReHistroy.indexOf(text, 0);
//已经是最上面一个了,直接返回
if (0 == index)
{
return;
}
//没有直接添加到最前面。不做查找删除重复,一是慢,而是删除会引起信号逻辑时许有误
if (-1 == index)
{
s_fileNameReHistroy.push_front(text);
ui.fileNameRe->insertItem(0, text);
}
else
{
//有了怎么办,删除旧的,加新的
s_fileNameReHistroy.removeAt(index);
s_fileNameReHistroy.push_front(text);
//发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。
ui.fileNameRe->removeItem(index);
ui.fileNameRe->insertItem(0, text);
//发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。
//必须重新设置一下,否则查找框里面字段乱跳到下一个去了
ui.fileNameRe->setCurrentIndex(0);
}
if (s_fileNameReHistroy.size() > 15)
{
s_fileNameReHistroy.takeLast();
}
}
const int MAX_RECORE_NUMS = 15;
bool FileSearchWin::saveHistory()
{
QString settingDir = QString("notepad/filesearch");
QSettings qs(QSettings::IniFormat, QSettings::UserScope, settingDir);
qs.setIniCodec("UTF-8");
QStringList fileNameReHistroy = s_fileNameReHistroy;
if (fileNameReHistroy.count() > MAX_RECORE_NUMS)
{
fileNameReHistroy = fileNameReHistroy.mid(0, MAX_RECORE_NUMS);
}
qs.setValue(FILE_NAME_REGULAR, fileNameReHistroy);
QStringList fileSuffixHistroy = s_fileSuffixHistroy;
if (fileSuffixHistroy.count() > MAX_RECORE_NUMS)
{
fileSuffixHistroy = fileSuffixHistroy.mid(0, MAX_RECORE_NUMS);
}
qs.setValue(FILE_SUFFIX_TYPE, fileSuffixHistroy);
qs.sync();
return true;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/ndd-community/filesearch.git
git@gitee.com:ndd-community/filesearch.git
ndd-community
filesearch
filesearch
master

搜索帮助