diff --git a/SpaceSniffer.py b/SpaceSniffer.py index 9941218..a3ffd26 100644 --- a/SpaceSniffer.py +++ b/SpaceSniffer.py @@ -1,10 +1,22 @@ import os +import webbrowser import threading import tkinter as tk from tkinter import ttk, filedialog, messagebox from queue import Queue from send2trash import send2trash import subprocess +import logging +import requests + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s", + handlers=[ + logging.FileHandler("scanner.log", encoding="utf-8"), + logging.StreamHandler(), + ], +) class FolderScanner(threading.Thread): @@ -16,28 +28,32 @@ class FolderScanner(threading.Thread): self.total_items = 0 # 总共扫描的文件/目录数量 def run(self): # 扫描文件/目录 + logging.info(f"开始扫描目录: {self.start_path}") self.total_items = sum( [len(files) + len(dirs) for r, dirs, files in os.walk(self.start_path)] ) # 计算总共扫描的文件/目录数量 self.scan_folder(self.start_path) # 扫描文件/目录 self.queue.put(None) # 扫描结束 + logging.info(f"扫描完成: {self.start_path}") - def scan_folder(self, folder): # 扫描文件/目录 - scanned_items = 0 # 已扫描的文件/目录数量 - for dirpath, dirnames, filenames in os.walk(folder): # 遍历文件/目录 - for dirname in dirnames: # 遍历目录 + def scan_folder(self, folder): + scanned_items = 0 + for dirpath, dirnames, filenames in os.walk(folder): + for dirname in dirnames: folder_path = os.path.join(dirpath, dirname) size = self.get_size(folder_path) self.queue.put((folder_path, size, dirpath, "folder")) scanned_items += 1 self.update_progress(scanned_items, folder_path) + logging.info(f"扫描目录: {folder_path} 大小: {size} 字节") - for filename in filenames: # 遍历文件 + for filename in filenames: file_path = os.path.join(dirpath, filename) size = os.path.getsize(file_path) self.queue.put((file_path, size, dirpath, "file")) scanned_items += 1 self.update_progress(scanned_items, file_path) + logging.info(f"扫描文件: {file_path} 大小: {size} 字节") def get_size(self, path): # 获取文件/目录大小 total_size = 0 @@ -58,7 +74,7 @@ class App(tk.Tk): def __init__(self, start_path): # 初始化 super().__init__() self.withdraw() - self.title("目录扫描器 V1.3") + self.title("目录扫描器 V1.4") self.start_path = start_path self.queue = Queue() self.progress_queue = Queue() @@ -135,6 +151,8 @@ class App(tk.Tk): menu_bar.add_cascade(label="帮助", menu=help_menu) help_menu.add_command(label="帮助", command=self.show_help) help_menu.add_command(label="更新日志", command=self.show_update_log) + help_menu.add_command(label="扫描日志", command=self.show_log) + help_menu.add_command(label="检查更新", command=self.check_updates) help_menu.add_command(label="关于", command=self.show_about) def show_help(self): @@ -150,17 +168,58 @@ class App(tk.Tk): def show_update_log(self): messagebox.showinfo( "更新日志", - "V1.0 实现了目录扫描功能,文件/目录大小统计功能\n", + "V1.0 实现了基本的目录扫描、文件/目录大小统计功能\n", "\n", - "V1.1 实现了重新选择目录扫描功能,新增了进度条显示\n", + "V1.1 新增了重新选择目录扫描功能,新增了进度条显示\n", "\n", - "V1.2 实现了双击打开目录、文件的功能,实现了右键菜单\n", + "V1.2 新增了双击打开目录、文件的功能,实现了右键菜单\n", "\n", "V1.3 优化了界面UI\n", + "\n", + "V1.4 新增了扫描日志、检查更新功能\n", ) + def show_log(self): + log_content = self.read_log_file() # 从日志文件中读取日志内容 + log_window = tk.Toplevel(self) + log_window.title("扫描日志") + log_window.geometry("1000x400") + + text_widget = tk.Text(log_window, wrap=tk.WORD) + text_widget.pack(expand=True, fill=tk.BOTH) + + scrollbar = tk.Scrollbar(text_widget) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y) + text_widget.config(yscrollcommand=scrollbar.set) + scrollbar.config(command=text_widget.yview) + + text_widget.insert(tk.END, log_content) + text_widget.config(state=tk.DISABLED) + + def read_log_file(self): + log_file_path = "scanner.log" # 日志文件路径 + if os.path.exists(log_file_path): + try: + with open(log_file_path, "r", encoding="utf-8") as log_file: + return log_file.read() + except UnicodeDecodeError: + return "日志文件编码错误,无法解析。" + else: + return "日志文件不存在。" + + def check_updates(self): + # 创建一个新的 UpdateManager 实例,不销毁程序 + update_manager = UpdateManager(self) + update_manager.check_latest_release() + def show_about(self): - messagebox.showinfo("关于", "目录扫描器 V1.3\n作者: ahdoawhfo") + messagebox.showinfo( + "关于", + "一款开源的文件/目录扫描工具\n", + "可以直观地展示目录的文件结构以及文件大小\n", + "软件版本 V1.4\n", + "作者 ahdoawhfo\n", + ) def on_double_click(self, event): # V1.2 Update:当双击的是文件时,打开文件 item = self.tree.identify_row(event.y) @@ -452,9 +511,74 @@ class ProgressWindow(tk.Toplevel): # 进度窗口 pass # 禁止关闭进度窗口 +class UpdateManager: + def __init__(self, root): + self.root = root + + def check_latest_release(self): + # Gitea 仓库信息和当前软件版本 + repo_owner = "ahdoawhfo" + repo_name = "SpaceSniffer" + base_url = "https://git.a6.wiki/api/v1/repos" + current_version = "1.4" # 替换成你的当前软件版本 + + try: + # 发送 GET 请求获取最新的 Release + response = requests.get( + f"{base_url}/{repo_owner}/{repo_name}/releases/latest" + ) + + if response.status_code == 200: + release_info = response.json() + latest_version = release_info["tag_name"] + release_notes = release_info["body"] + + # 比较最新版本和当前软件版本 + if latest_version > current_version: + # 提示用户更新 + choice = self.prompt_update(latest_version, release_notes) + if choice: + # 打开浏览器到 release 页面 + release_url = release_info["html_url"] + webbrowser.open_new(release_url) + if self.root: + self.destroy() + root.destroy() + else: + self.show_message("检查更新", "当前版本已经是最新版本") + else: + self.show_message( + "检查更新", + f"获取最新 Release 失败:{response.status_code}", + ) + except requests.RequestException as e: + self.show_message("检查更新", f"请求最新 Release 时发生错误:{e}") + + def prompt_update(self, latest_version, release_notes): + prompt_message = f"检查更新: {latest_version}\n\n更新说明:\n{release_notes}\n\n是否立即更新?" + choice = messagebox.askyesno("更新提示", prompt_message) + return choice + + def show_message(self, title, message): + messagebox.showinfo(title, message) + + +def clear_log_file(): + log_file = "scanner.log" + try: + with open(log_file, "w", encoding="utf-8") as f: + f.truncate(0) # 清空文件内容 + print(f"已清空日志文件 {log_file} 的内容") + except Exception as e: + print(f"清空日志文件内容时发生错误: {e}") + + if __name__ == "__main__": + clear_log_file() root = tk.Tk() root.withdraw() + app = UpdateManager(root) + app.check_latest_release() start_path = filedialog.askdirectory() if start_path: app = App(start_path)