仿everything制作搞笑检索设计(是的,我没有打错字)

news/2025/12/9 20:36:35/文章来源:https://www.cnblogs.com/beifengdu/p/19328315

everything的确是一个很好的工具,所以仿照开发一个

# -*- coding: utf-8 -*-import sys
import os
import sqlite3
import threading
from pathlib import Path
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QPushButton, QLineEdit, QListWidget, QLabel, QCheckBox, QProgressBar,QMessageBox, QGridLayout, QGroupBox
)
from PyQt5.QtCore import Qt, pyqtSignal, QObjectclass IndexerSignals(QObject):count_update = pyqtSignal(int)       status = pyqtSignal(str)             current_file = pyqtSignal(str)      finished = pyqtSignal(int)          error = pyqtSignal(str)class FileIndexer(QObject):def __init__(self):super().__init__()self.signals = IndexerSignals()self.stop_requested = Falsedef stop(self):self.stop_requested = Truedef build_index(self, roots):db_path = Path.home() / ".file_searcher_db.sqlite"# 删除旧库,确保干净重建if db_path.exists():try:os.remove(db_path)except:passtry:conn = sqlite3.connect(str(db_path))cur = conn.cursor()cur.execute("""CREATE VIRTUAL TABLE IF NOT EXISTS files USING fts5(name, path UNINDEXED,  -- UNINDEXED 表示该字段存储但不参与全文索引(节省空间且避免误搜)is_dir UNINDEXED,tokenize = 'unicode61');""")conn.commit()processed_count = 0batch = []self.signals.status.emit("正在极速扫描中...")for root in roots:if self.stop_requested:breakfor dirpath, dirnames, filenames in os.walk(root):if self.stop_requested:break# 1. 处理文件夹for dname in dirnames:full_path = os.path.join(dirpath, dname)batch.append((dname, full_path, 1)) # 1 代表文件夹processed_count += 1# 2. 处理文件for fname in filenames:full_path = os.path.join(dirpath, fname)batch.append((fname, full_path, 0)) # 0 代表文件processed_count += 1if len(batch) >= 2000:cur.executemany("INSERT INTO files(name, path, is_dir) VALUES (?, ?, ?)", batch)conn.commit()batch.clear()# 发送信号更新界面self.signals.count_update.emit(processed_count)self.signals.current_file.emit(dirpath) # 显示当前扫描到的目录即可# 写入剩余的数据if batch:cur.executemany("INSERT INTO files(name, path, is_dir) VALUES (?, ?, ?)", batch)conn.commit()conn.close()if not self.stop_requested:self.signals.finished.emit(processed_count)else:self.signals.status.emit("索引已停止")except Exception as e:self.signals.error.emit(str(e))class MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("极速文件搜索器 v3.0 (逻辑修正版)")self.setGeometry(200, 100, 950, 700)self.db_path = Path.home() / ".file_searcher_db.sqlite"self.indexer = FileIndexer()self.thread = Noneself.init_ui()def init_ui(self):central = QWidget()self.setCentralWidget(central)layout = QVBoxLayout(central)# === 1. 盘符选择 ===group_disk = QGroupBox("1. 索引设置")h_disk = QHBoxLayout()self.drives_layout = QGridLayout()self.checkboxes = {}self.refresh_drives() # 初始化盘符btn_refresh = QPushButton("刷新盘符")btn_refresh.clicked.connect(self.refresh_drives)h_disk.addLayout(self.drives_layout)h_disk.addWidget(btn_refresh)group_disk.setLayout(h_disk)# === 2. 控制台与进度 ===group_ctrl = QGroupBox("2. 索引控制")v_ctrl = QVBoxLayout()h_btns = QHBoxLayout()self.btn_update = QPushButton("开始建立索引")self.btn_update.setStyleSheet("background-color: #2E7D32; color: white; font-weight: bold; padding: 8px;")self.btn_update.clicked.connect(self.start_indexing)self.btn_stop = QPushButton("停止")self.btn_stop.setStyleSheet("background-color: #C62828; color: white; padding: 8px;")self.btn_stop.clicked.connect(self.stop_indexing)self.btn_stop.setEnabled(False)h_btns.addWidget(self.btn_update)h_btns.addWidget(self.btn_stop)self.lbl_status = QLabel("准备就绪")self.progress_bar = QProgressBar()self.progress_bar.setTextVisible(False) # 不显示百分比,因为没有总数self.progress_bar.setRange(0, 0)        self.progress_bar.hide()self.lbl_count = QLabel("已收录: 0")self.lbl_current = QLabel("...")self.lbl_current.setStyleSheet("color: gray; font-size: 10px;")v_ctrl.addLayout(h_btns)v_ctrl.addWidget(self.lbl_status)v_ctrl.addWidget(self.progress_bar)h_info = QHBoxLayout()h_info.addWidget(self.lbl_count)h_info.addWidget(self.lbl_current)v_ctrl.addLayout(h_info)group_ctrl.setLayout(v_ctrl)# === 3. 搜索区域 ===group_search = QGroupBox("3. 极速搜索")v_search = QVBoxLayout()h_filter = QHBoxLayout()self.chk_search_file = QCheckBox("搜文件")self.chk_search_file.setChecked(True)self.chk_search_file.stateChanged.connect(lambda: self.on_search(self.edit_search.text()))self.chk_search_dir = QCheckBox("搜文件夹")self.chk_search_dir.setChecked(True)self.chk_search_dir.stateChanged.connect(lambda: self.on_search(self.edit_search.text()))h_filter.addWidget(QLabel("过滤类型:"))h_filter.addWidget(self.chk_search_file)h_filter.addWidget(self.chk_search_dir)h_filter.addStretch()self.edit_search = QLineEdit()self.edit_search.setPlaceholderText("输入文件名关键词(空格隔开表示“与”,例如:合同 2024)...")self.edit_search.setStyleSheet("font-size: 14pt; padding: 6px;")self.edit_search.textChanged.connect(self.on_search)self.list_result = QListWidget()self.list_result.setStyleSheet("font-size: 11pt;")self.list_result.itemDoubleClicked.connect(self.open_item)v_search.addLayout(h_filter)v_search.addWidget(self.edit_search)v_search.addWidget(self.list_result)group_search.setLayout(v_search)# 添加到主布局layout.addWidget(group_disk)layout.addWidget(group_ctrl)layout.addWidget(group_search)def get_drives(self):drives = []for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":d = f"{letter}:\\"if os.path.exists(d):drives.append(d)return drivesdef refresh_drives(self):# 清除旧的for i in reversed(range(self.drives_layout.count())): self.drives_layout.itemAt(i).widget().setParent(None)self.checkboxes.clear()drives = self.get_drives()for i, d in enumerate(drives):cb = QCheckBox(d)# 默认只勾选 C 和 D,避免全部勾选太慢if d.startswith("C") or d.startswith("D"):cb.setChecked(True)self.checkboxes[d] = cbself.drives_layout.addWidget(cb, i // 6, i % 6)def start_indexing(self):roots = [d for d, cb in self.checkboxes.items() if cb.isChecked()]if not roots:QMessageBox.warning(self, "提示", "请至少选择一个盘符!")returnself.btn_update.setEnabled(False)self.btn_stop.setEnabled(True)self.progress_bar.show()self.list_result.clear()self.list_result.addItem("正在建立索引,建立过程中也可以尝试搜索...")self.indexer = FileIndexer()self.thread = threading.Thread(target=self.indexer.build_index, args=(roots,), daemon=True)self.indexer.signals.count_update.connect(lambda n: self.lbl_count.setText(f"已收录: {n:,}"))self.indexer.signals.status.connect(self.lbl_status.setText)self.indexer.signals.current_file.connect(self.lbl_current.setText)self.indexer.signals.finished.connect(self.on_finished)self.thread.start()def stop_indexing(self):self.indexer.stop()self.btn_stop.setEnabled(False)self.lbl_status.setText("正在停止...")def on_finished(self, total):self.progress_bar.hide()self.btn_update.setEnabled(True)self.btn_stop.setEnabled(False)self.lbl_status.setText("索引完成")self.lbl_current.setText("")QMessageBox.information(self, "完成", f"索引更新完毕!\n本次共收录 {total:,} 个项目。")self.list_result.clear()def on_search(self, text):text = text.strip()if not self.db_path.exists():return# 检查过滤条件show_files = self.chk_search_file.isChecked()show_dirs = self.chk_search_dir.isChecked()if not text:self.list_result.clear()returnif not show_files and not show_dirs:self.list_result.clear()self.list_result.addItem("请至少勾选一种类型(文件或文件夹)")returntokens = text.split()fts_query_parts = []for t in tokens:# 加上 * 使得搜索 "con" 能匹配 "config"# 语法:name : "keyword*"fts_query_parts.append(f'name : "{t}*"')fts_query = " AND ".join(fts_query_parts)# 构建类型过滤 SQLtype_filters = []if show_files: type_filters.append(0)if show_dirs: type_filters.append(1)type_sql = ",".join(map(str, type_filters))try:conn = sqlite3.connect(str(self.db_path))cur = conn.cursor()# 核心查询语句sql = f"""SELECT name, path, is_dir FROM files WHERE files MATCH ? AND is_dir IN ({type_sql})ORDER BY rank LIMIT 500"""cur.execute(sql, (fts_query,))rows = cur.fetchall()conn.close()self.list_result.clear()if not rows:self.list_result.addItem("未找到匹配项")returnself.list_result.addItem(f"--- 找到 {len(rows)} 个结果 ---")for name, path, is_dir in rows:icon = "📁" if is_dir else "📄"item_text = f"{icon} {name}  →  {path}"self.list_result.addItem(item_text)except Exception as e:# 输入特殊字符时可能导致 FTS 语法错误,忽略即可passdef open_item(self, item):text = item.text()if "→" in text:path = text.split("→", 1)[1].strip()try:os.startfile(path)except Exception as e:QMessageBox.warning(self, "错误", f"无法打开路径:\n{path}\n错误信息:{e}")if __name__ == "__main__":app = QApplication(sys.argv)win = MainWindow()win.show()sys.exit(app.exec_())

有什么改进思路希望多多指出

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

仿everything制作搞笑检索设计(是的,我没有打错字)

everything的确是一个很好的工具,所以仿照开发一个 # -*- coding: utf-8 -*-import sys import os import sqlite3 import threading from pathlib import Path from PyQt5.QtWidgets import (QApplication, QMainWin…

雅思上岸秘籍!这些封闭班绝了

雅思上岸秘籍!这些封闭班绝了雅思热,封闭班需求涨 近年来,随着全球化进程的加速和留学热潮的持续升温,雅思考试的热度也在不断攀升。越来越多的人意识到,雅思成绩不仅是留学的敲门砖,更是在职场竞争中脱颖而出的…

102302133陈佳昕作业4

作业①: 要求: 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。 候选网站:…

2025年12月哈尔滨艺考培训机构标杆推荐:众艺艺考,播音主持|表演|导演|空乘|舞蹈|个性化教学新标准

随着艺术教育行业规范化发展、教学成果要求提升及考生个性化需求增加,艺考培训已从大城市专属服务逐步覆盖至各省市地区,2025年市场规模预计持续扩大。但市场增长也带来机构教学实力、课程适配性、服务质量参差不齐的…

平面上两点和方位角计算目标交点的算法(应该可用于 MC 末地传送门三角定位)

前言 之前看 MC 视频的时候有个人说了怎么用三角定位来确定末地传送门的位置。 说的是在两个不同的位置扔出末影珍珠,然后记住这两个位置和末影珍珠的方位角,就可以计算出来。 肯定有人已经把算法弄出来了,但是我想…

雅思培训班怎么选?2025高分上岸攻略+避坑指南

雅思培训班怎么选?2025高分上岸攻略+避坑指南备考雅思,就像一场没有硝烟的战争,选对培训机构,无疑是为自己找到了一位强有力的 “军师”。在这鱼龙混杂的培训市场中,如何一眼挑中最适合自己的机构呢?别急,先静下…

【9章】AI训练师 零基础入门与实战

【9章】AI训练师 零基础入门与实战 学习地址:……/s/160v0H2PsGoWnl46efa3Y6w 提取码:8blp 人工智能训练师,这个听起来充满科技感的职业,本质上是一群“数字时代的牧羊人”。他们不像算法工程师那样编写复杂的代码…

2025年杭州翻译服务机构推荐榜:东瑞翻译、杭州翻译服务机构哪家好、杭州翻译服务机构推荐、多领域语言解决方案的可靠选择

随着全球化商业合作深化、跨境交流频繁及企业出海需求激增,专业翻译服务已成为打破语言壁垒、保障跨文化沟通效率的核心支撑。2025 年,杭州翻译市场规模持续扩大,但行业内服务商在专业深度、技术能力、服务覆盖及合…

独占锁和共享锁唤醒机制

目录独占锁和共享锁唤醒机制精确总结独占锁(EXCLUSIVE)共享锁(SHARED)独占锁的正确顺序:共享锁的正确顺序:核心区别可视化独占锁(接力赛)共享锁(广播链)代码验证关键区别表格总结 独占锁和共享锁唤醒机制 精…

个人学习---25.12.9

markdown简单学习这是我markdown的开始,我将把他作为我的ysyx笔记 markdon记录标题使用就表示几级几级,很简单不多说文本格式 ####### 斜体文本 粗体文本 粗斜体文本 分隔线 可以使用---来表示代码块int main6(void)…

大模型完整架构

后端模型:利用ollama平台模型 前端界面:利用streamlit框架搭建用户界面,streamlit是一个简单易用的python库 对话交互:用户通过strealit界面输入文本,聊天机器人基于模型对输入内容处理并恢复展示在界面上 模型调…

iOS 知识点 - 一篇文章带你串通「操作系统 内存模型 文件系统」

本文重点讲解 iOS 操作系统,Linux/Windows 操作系统待到后续新开文章专门讲解。总览 目标:一篇文章理清 iOS 三个紧密相关但层次不同的事物:操作系统(iOS / Darwin):谁在管理 “进程、线程、虚拟内存页、文件描述…

2025年12月天津金蝶软件代理商最新推荐:天津鹏越软件,金蝶云星空、金蝶云星晨、金蝶云星翰、助力企业高效落地ERP系统与全场景管理升级

随着数字经济加速渗透,企业对专业化、定制化管理软件的需求持续攀升,尤其是在生产流程优化、财务精益化管控、多组织协同等核心场景中,优质的数字化解决方案已成为企业提升竞争力的关键。2025 年,天津地区企业数字…

102302114_比山布努尔兰_作业4

作业1 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。 作业代码点击查看代…

2025年12月济南艺考画室最新推荐:济南大道画室,济南艺考画室、济南画室哪家好、济南画室推荐、山东美术艺考培训、山东画室个性化教学新标杆

随着美术艺考竞争日益激烈、教学标准化要求提升及学生个性化发展需求增加,优质画室已从大城市集中逐步扩展至地方深耕,2025年艺考培训市场规模预计持续增长。但市场扩张也带来画室教学水平、师资力量、升学成果参差不…

记一次磁盘占满的问题

说明 之前搭建的lobehub/lobe-chat网页AI问答突然不能用了。 于是重启docker遇到: yangx@ak:~$ docker run 23576ea8e726 docker: Error response from daemon: mkdir /var/lib/docker/overlay2/70e1042a088ffe1a6d26…

Redis提供的原子性命令

目录Redis提供的原子性命令主要类别的原子性命令:1. 字符串(String)原子操作2. 列表(List)原子操作3. 集合(Set)原子操作4. 哈希(Hash)原子操作5. 有序集合(Sorted Set)原子操作6. 位图(Bitmap)原子操作7…

多业态连锁环境管理系统:AI + 机器人闭环,坪效提升 16%

门店环境本是沉默的,却在无声处酿成大祸:高峰无人知地面湿滑,夜间无人见灯闪,雨天无人管玻璃污——2025年,环境设施异常导致的综合损失平均占运营成本19%,保洁+维修双线超支,数据孤岛让决策如盲。全场景痛点全面…

2025年12月室内水上乐园厂家推荐:山东汇川,儿童水上乐园、大型水上乐园、主题水上乐园、室外水上乐园、恒温泳池、室 泳池、全场景适配新标杆

随着文旅产业升级、消费需求多元化及健康理念普及,水上游乐与泳池设备行业迎来快速发展期,2025 年市场规模预计持续扩大。但市场增长也带来厂商产品质量、场景适配性、服务专业性参差不齐的问题,企业及投资者在选购…

2025雅思培训班怎么选?这5家高性价比机构帮你高效提分

2025雅思培训班怎么选?这5家高性价比机构帮你高效提分一、雅思选课三大痛点解析:为什么你总在无效对比? 在雅思备考的漫漫征途中,选对培训班就如同找到了一把开启成功之门的钥匙。然而,面对市场上琳琅满目的雅思培…