From 5cd7c534aa9449fbc326fb3aaf3a8720fd246a3d Mon Sep 17 00:00:00 2001
From: Lesacm <1500309685@qq.com>
Date: Thu, 9 Oct 2025 11:22:50 +0800
Subject: [PATCH 01/11] 123
---
src/settings/settings_manager.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/settings/settings_manager.py b/src/settings/settings_manager.py
index e5fdd76..c08d2da 100644
--- a/src/settings/settings_manager.py
+++ b/src/settings/settings_manager.py
@@ -7,7 +7,7 @@ class SettingsManager:
def __init__(self, config_file: str = "config.json"):
"""
初始化设置管理器
- - 指定配置文件路径
+ - 指定配置文件路径123
- 加载现有配置或创建默认配置
"""
# TODO: 实现构造函数逻辑
--
2.34.1
From 9b4036a69e1cb41d57a4dd7666a47bafdf1dcfba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=9F=B3=E5=85=B4=E9=9C=96?= <3189844089@qq.com>
Date: Thu, 9 Oct 2025 11:26:04 +0800
Subject: [PATCH 02/11] 111
---
src/file_manager/file_operations.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/file_manager/file_operations.py b/src/file_manager/file_operations.py
index 603cb8e..4478393 100644
--- a/src/file_manager/file_operations.py
+++ b/src/file_manager/file_operations.py
@@ -8,7 +8,7 @@ class FileManager:
def __init__(self):
"""
初始化文件管理器
- - 设置工作目录
+ - 设置工作目录1234
- 初始化文件缓存
"""
# TODO: 实现构造函数逻辑
--
2.34.1
From 8a07ae41013d3276db79ad7ad4feef2d9b827e6e Mon Sep 17 00:00:00 2001
From: mamingyi <80972090@qq.com>
Date: Thu, 9 Oct 2025 11:38:00 +0800
Subject: [PATCH 03/11] 1111
---
src/utils/helper_functions.py | 47 ++++++++++++++++++++++++++----
src/utils/test_helper_functions.py | 29 ++++++++++++++++++
2 files changed, 70 insertions(+), 6 deletions(-)
create mode 100644 src/utils/test_helper_functions.py
diff --git a/src/utils/helper_functions.py b/src/utils/helper_functions.py
index af3cb2f..db80af9 100644
--- a/src/utils/helper_functions.py
+++ b/src/utils/helper_functions.py
@@ -11,8 +11,21 @@ class Utils:
- 尝试多种编码格式
- 返回最可能的编码
"""
- # TODO: 实现编码检测逻辑
- pass
+ import chardet
+
+ # 读取文件的前1024字节用于编码检测
+ with open(file_path, 'rb') as f:
+ raw_data = f.read(1024)
+
+ # 使用chardet检测编码
+ result = chardet.detect(raw_data)
+ encoding = result['encoding']
+
+ # 如果chardet无法确定编码,则默认使用utf-8
+ if encoding is None:
+ encoding = 'utf-8'
+
+ return encoding
@staticmethod
def format_file_size(size_bytes: int) -> str:
@@ -20,9 +33,25 @@ class Utils:
格式化文件大小
- 将字节数转换为可读格式
- 返回格式化字符串
+ 参数:
+ size_bytes (int): 需要格式化的文件大小,单位为字节
+ 返回:
+ str: 格式化后的文件大小字符串,如 "1.5 MB"
"""
- # TODO: 实现文件大小格式化逻辑
- pass
+ # 如果文件大小为0字节,直接返回 "0 B"
+ if size_bytes == 0:
+ return "0 B"
+
+ # 定义文件大小单位列表
+ size_names = ["B", "KB", "MB", "GB", "TB"]
+ i = 0
+ # 当文件大小大于等于1024且未到达最大单位时,循环除以1024
+ while size_bytes >= 1024.0 and i < len(size_names) - 1:
+ size_bytes /= 1024.0
+ i += 1
+
+ # 返回格式化后的字符串,保留一位小数
+ return f"{size_bytes:.1f} {size_names[i]}"
@staticmethod
def calculate_file_hash(file_path: str) -> str:
@@ -31,5 +60,11 @@ class Utils:
- 使用SHA256算法
- 返回哈希字符串
"""
- # TODO: 实现文件哈希计算逻辑
- pass
\ No newline at end of file
+ sha256_hash = hashlib.sha256()
+
+ # 分块读取文件以避免大文件占用过多内存
+ with open(file_path, "rb") as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ sha256_hash.update(chunk)
+
+ return sha256_hash.hexdigest()
\ No newline at end of file
diff --git a/src/utils/test_helper_functions.py b/src/utils/test_helper_functions.py
new file mode 100644
index 0000000..e73ec07
--- /dev/null
+++ b/src/utils/test_helper_functions.py
@@ -0,0 +1,29 @@
+# test_helper_functions.py
+import os
+from helper_functions import Utils
+
+# 创建一个测试文件
+test_content = "这是一个测试文件,用于验证工具函数。\nThis is a test file to verify utility functions."
+test_file_path = "test_file.txt"
+
+# 写入测试文件
+with open(test_file_path, "w", encoding="utf-8") as f:
+ f.write(test_content)
+
+# 测试文件大小格式化
+file_size = os.path.getsize(test_file_path)
+formatted_size = Utils.format_file_size(file_size)
+print(f"文件大小: {file_size} 字节")
+print(f"格式化大小: {formatted_size}")
+
+# 测试文件编码检测
+detected_encoding = Utils.detect_encoding(test_file_path)
+print(f"检测到的编码: {detected_encoding}")
+
+# 测试文件哈希计算
+file_hash = Utils.calculate_file_hash(test_file_path)
+print(f"文件哈希值: {file_hash}")
+
+# 清理测试文件
+os.remove(test_file_path)
+print("测试完成,临时文件已清理。")
\ No newline at end of file
--
2.34.1
From 8a56312ba9ed63d7c12cee2c2087c8c56436556d Mon Sep 17 00:00:00 2001
From: mamingyi <80972090@qq.com>
Date: Sat, 11 Oct 2025 18:22:36 +0800
Subject: [PATCH 04/11] =?UTF-8?q?=E9=A9=AC=E6=98=8E=E4=B9=89=E5=AE=8C?=
=?UTF-8?q?=E6=AF=95=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
requirements.txt | 2 +-
src/file_parser.py | 156 +++++++++++++++++++++--------
src/utils/test_helper_functions.py | 29 ------
3 files changed, 118 insertions(+), 69 deletions(-)
delete mode 100644 src/utils/test_helper_functions.py
diff --git a/requirements.txt b/requirements.txt
index 96c661b..17e7112 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,4 +5,4 @@ PyQt5>=5.15.0
requests>=2.25.1
beautifulsoup4>=4.11.0
pillow>=9.0.0
-chardet>=4.0.0
\ No newline at end of file
+chardet>=4.0.0
diff --git a/src/file_parser.py b/src/file_parser.py
index 84b3c04..fc44729 100644
--- a/src/file_parser.py
+++ b/src/file_parser.py
@@ -4,54 +4,132 @@ from typing import Union
class FileParser:
@staticmethod
def parse_file(file_path: str) -> str:
- """
- 主解析函数,根据文件扩展名路由到具体解析器
- - 调用validate_file_path(file_path)验证路径
- - 根据扩展名调用对应解析函数
- - 统一异常处理
- """
- # TODO: 实现主解析函数逻辑
- pass
+
+ # 验证文件路径
+ if not FileParser.validate_file_path(file_path):
+ raise ValueError(f"Invalid file path: {file_path}")
+
+ # 获取文件扩展名
+ _, ext = os.path.splitext(file_path)
+ ext = ext.lower()
+
+ # 根据扩展名调用对应的解析函数
+ try:
+ if ext == '.txt':
+ return FileParser.parse_txt(file_path)
+ elif ext == '.docx':
+ return FileParser.parse_docx(file_path)
+ elif ext == '.pdf':
+ return FileParser.parse_pdf(file_path)
+ else:
+ raise ValueError(f"Unsupported file format: {ext}")
+ except Exception as e:
+ # 统一异常处理
+ raise Exception(f"Error parsing file {file_path}: {str(e)}")
@staticmethod
def parse_txt(file_path: str) -> str:
- """
- 解析纯文本文件
- - 自动检测编码(utf-8, gbk等)
- - 处理不同换行符
- - 返回纯文本内容
- """
- # TODO: 实现实现txt文件解析逻辑
- pass
+ # 验证文件路径
+ if not FileParser.validate_file_path(file_path):
+ raise ValueError(f"Invalid file path: {file_path}")
+
+ # 导入工具函数来检测编码
+ try:
+ from utils.helper_functions import Utils
+ except ImportError:
+ # 如果无法导入,使用默认方法检测编码
+ import chardet
+ with open(file_path, 'rb') as f:
+ raw_data = f.read(1024)
+ encoding = chardet.detect(raw_data)['encoding'] or 'utf-8'
+ else:
+ # 使用工具函数检测编码
+ encoding = Utils.detect_encoding(file_path)
+
+ # 读取文件内容
+ with open(file_path, 'r', encoding=encoding, errors='ignore') as f:
+ content = f.read()
+
+ # 统一换行符为\n
+ content = content.replace('\r\n', '\n').replace('\r', '\n')
+
+ return content
@staticmethod
def parse_docx(file_path: str) -> str:
- """
- 解析Word文档
- - 提取所有段落文本
- - 保留基本格式(换行)
- - 忽略图片、表格等非文本元素
- """
- # TODO: 实现docx文件解析逻辑
- pass
+
+ # 验证文件路径
+ if not FileParser.validate_file_path(file_path):
+ raise ValueError(f"Invalid file path: {file_path}")
+
+ # 尝试导入python-docx库
+ try:
+ from docx import Document
+ except ImportError:
+ raise ImportError("python-docx library is required for parsing .docx files. Please install it using 'pip install python-docx'")
+
+ # 打开并解析docx文件
+ try:
+ doc = Document(file_path)
+
+ # 提取所有段落文本
+ paragraphs = []
+ for paragraph in doc.paragraphs:
+ paragraphs.append(paragraph.text)
+
+ # 用换行符连接所有段落
+ content = '\n'.join(paragraphs)
+
+ return content
+ except Exception as e:
+ raise Exception(f"Error parsing docx file {file_path}: {str(e)}")
@staticmethod
def parse_pdf(file_path: str) -> str:
- """
- 解析PDF文档
- - 提取文本内容
- - 保留基本格式(换行)
- """
- # TODO: 实现PDF文件解析逻辑
- pass
+
+ # 验证文件路径
+ if not FileParser.validate_file_path(file_path):
+ raise ValueError(f"Invalid file path: {file_path}")
+
+ # 尝试导入PyPDF2库
+ try:
+ import PyPDF2
+ except ImportError:
+ raise ImportError("PyPDF2 library is required for parsing .pdf files. Please install it using 'pip install PyPDF2'")
+
+ # 打开并解析pdf文件
+ try:
+ content = ""
+ with open(file_path, 'rb') as file:
+ pdf_reader = PyPDF2.PdfReader(file)
+
+ # 提取每一页的文本
+ for page in pdf_reader.pages:
+ content += page.extract_text()
+ content += "\n"
+
+ return content
+ except Exception as e:
+ raise Exception(f"Error parsing pdf file {file_path}: {str(e)}")
@staticmethod
def validate_file_path(file_path: str) -> bool:
- """
- 验证文件路径的有效性
- - 检查文件是否存在
- - 检查文件是否可读
- - 检查文件大小是否合理
- """
- # TODO: 实现文件路径验证逻辑
- pass
\ No newline at end of file
+
+ # 检查文件是否存在
+ if not os.path.exists(file_path):
+ return False
+
+ # 检查是否为文件(而非目录)
+ if not os.path.isfile(file_path):
+ return False
+
+ # 检查文件是否可读
+ if not os.access(file_path, os.R_OK):
+ return False
+
+ # 检查文件大小是否合理(小于10MB)
+ file_size = os.path.getsize(file_path)
+ if file_size > 10 * 1024 * 1024: # 10MB
+ return False
+
+ return True
\ No newline at end of file
diff --git a/src/utils/test_helper_functions.py b/src/utils/test_helper_functions.py
deleted file mode 100644
index e73ec07..0000000
--- a/src/utils/test_helper_functions.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# test_helper_functions.py
-import os
-from helper_functions import Utils
-
-# 创建一个测试文件
-test_content = "这是一个测试文件,用于验证工具函数。\nThis is a test file to verify utility functions."
-test_file_path = "test_file.txt"
-
-# 写入测试文件
-with open(test_file_path, "w", encoding="utf-8") as f:
- f.write(test_content)
-
-# 测试文件大小格式化
-file_size = os.path.getsize(test_file_path)
-formatted_size = Utils.format_file_size(file_size)
-print(f"文件大小: {file_size} 字节")
-print(f"格式化大小: {formatted_size}")
-
-# 测试文件编码检测
-detected_encoding = Utils.detect_encoding(test_file_path)
-print(f"检测到的编码: {detected_encoding}")
-
-# 测试文件哈希计算
-file_hash = Utils.calculate_file_hash(test_file_path)
-print(f"文件哈希值: {file_hash}")
-
-# 清理测试文件
-os.remove(test_file_path)
-print("测试完成,临时文件已清理。")
\ No newline at end of file
--
2.34.1
From 50fad30bcf6b8896c24a37895e3c841c1a9f8395 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=9F=B3=E5=85=B4=E9=9C=96?= <3189844089@qq.com>
Date: Sat, 11 Oct 2025 18:33:50 +0800
Subject: [PATCH 05/11] =?UTF-8?q?shixinglin=E7=AC=AC=E4=B8=80=E6=AC=A1?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/file_manager/file_operations.py | 225 ++++++++++++++++++++++-----
src/input_handler/input_processor.py | 94 ++++++++---
src/services/network_service.py | 224 +++++++++++++++++++++-----
3 files changed, 452 insertions(+), 91 deletions(-)
diff --git a/src/file_manager/file_operations.py b/src/file_manager/file_operations.py
index 4478393..a835e35 100644
--- a/src/file_manager/file_operations.py
+++ b/src/file_manager/file_operations.py
@@ -8,12 +8,14 @@ class FileManager:
def __init__(self):
"""
初始化文件管理器
- - 设置工作目录1234
+ - 设置工作目录
- 初始化文件缓存
"""
- # TODO: 实现构造函数逻辑
+ # 实现构造函数逻辑
# 1. 设置默认工作目录
+ self.working_directory = Path.cwd()
# 2. 初始化文件缓存
+ self.file_cache = {}
# 3. 创建必要的目录结构
pass
@@ -24,12 +26,26 @@ class FileManager:
- 根据扩展名过滤文件(如果提供)
- 返回文件路径列表
"""
- # TODO: 实现文件列表逻辑
+ # 实现文件列表逻辑
# 1. 检查目录是否存在
+ if not os.path.exists(directory):
+ raise FileNotFoundError(f"目录 {directory} 不存在")
+
# 2. 遍历目录中的所有文件
- # 3. 根据扩展名过滤文件(如果提供)
+ file_list = []
+ for root, _, files in os.walk(directory):
+ for file in files:
+ file_path = os.path.join(root, file)
+ # 3. 根据扩展名过滤文件(如果提供)
+ if extensions:
+ _, ext = os.path.splitext(file)
+ if ext.lower() in [e.lower() for e in extensions]:
+ file_list.append(file_path)
+ else:
+ file_list.append(file_path)
+
# 4. 返回文件路径列表
- pass
+ return file_list
def copy_file(self, source: str, destination: str) -> bool:
"""
@@ -37,13 +53,27 @@ class FileManager:
- 将文件从源路径复制到目标路径
- 返回操作结果
"""
- # TODO: 实现文件复制逻辑
+ # 实现文件复制逻辑
# 1. 检查源文件是否存在
- # 2. 创建目标目录(如果不存在)
- # 3. 执行文件复制操作
- # 4. 处理异常情况
+ if not os.path.exists(source):
+ print(f"源文件 {source} 不存在")
+ return False
+
+ try:
+ # 2. 创建目标目录(如果不存在)
+ dest_dir = os.path.dirname(destination)
+ if dest_dir and not os.path.exists(dest_dir):
+ os.makedirs(dest_dir)
+
+ # 3. 执行文件复制操作
+ shutil.copy2(source, destination)
+ # 4. 处理异常情况
+ except Exception as e:
+ print(f"复制文件时出错: {e}")
+ return False
+
# 5. 返回操作结果
- pass
+ return True
def move_file(self, source: str, destination: str) -> bool:
"""
@@ -51,13 +81,27 @@ class FileManager:
- 将文件从源路径移动到目标路径
- 返回操作结果
"""
- # TODO: 实现文件移动逻辑
+ # 实现文件移动逻辑
# 1. 检查源文件是否存在
- # 2. 创建目标目录(如果不存在)
- # 3. 执行文件移动操作
- # 4. 处理异常情况
+ if not os.path.exists(source):
+ print(f"源文件 {source} 不存在")
+ return False
+
+ try:
+ # 2. 创建目标目录(如果不存在)
+ dest_dir = os.path.dirname(destination)
+ if dest_dir and not os.path.exists(dest_dir):
+ os.makedirs(dest_dir)
+
+ # 3. 执行文件移动操作
+ shutil.move(source, destination)
+ # 4. 处理异常情况
+ except Exception as e:
+ print(f"移动文件时出错: {e}")
+ return False
+
# 5. 返回操作结果
- pass
+ return True
def delete_file(self, file_path: str) -> bool:
"""
@@ -65,12 +109,25 @@ class FileManager:
- 删除指定路径的文件
- 返回操作结果
"""
- # TODO: 实现文件删除逻辑
+ # 实现文件删除逻辑
# 1. 检查文件是否存在
- # 2. 执行文件删除操作
- # 3. 处理异常情况(如权限不足)
+ if not os.path.exists(file_path):
+ print(f"文件 {file_path} 不存在")
+ return False
+
+ try:
+ # 2. 执行文件删除操作
+ os.remove(file_path)
+ # 3. 处理异常情况(如权限不足)
+ except PermissionError:
+ print(f"没有权限删除文件 {file_path}")
+ return False
+ except Exception as e:
+ print(f"删除文件时出错: {e}")
+ return False
+
# 4. 返回操作结果
- pass
+ return True
def get_file_info(self, file_path: str) -> Optional[Dict[str, Any]]:
"""
@@ -78,12 +135,33 @@ class FileManager:
- 获取文件大小、修改时间等信息
- 返回信息字典
"""
- # TODO: 实现文件信息获取逻辑
+ # 实现文件信息获取逻辑
# 1. 检查文件是否存在
- # 2. 获取文件基本信息(大小、修改时间等)
- # 3. 获取文件扩展名和类型
- # 4. 返回信息字典
- pass
+ if not os.path.exists(file_path):
+ print(f"文件 {file_path} 不存在")
+ return None
+
+ try:
+ # 2. 获取文件基本信息(大小、修改时间等)
+ stat_info = os.stat(file_path)
+ file_size = stat_info.st_size
+ modification_time = stat_info.st_mtime
+
+ # 3. 获取文件扩展名和类型
+ _, ext = os.path.splitext(file_path)
+
+ # 4. 返回信息字典
+ file_info = {
+ "path": file_path,
+ "size": file_size,
+ "modification_time": modification_time,
+ "extension": ext.lower(),
+ "name": os.path.basename(file_path)
+ }
+ return file_info
+ except Exception as e:
+ print(f"获取文件信息时出错: {e}")
+ return None
class DocumentOrganizer:
def __init__(self):
@@ -92,9 +170,17 @@ class DocumentOrganizer:
- 设置分类规则
- 初始化标签系统
"""
- # TODO: 实现构造函数逻辑
+ # 实现构造函数逻辑
# 1. 设置默认分类规则
+ self.categorization_rules = {
+ "images": [".jpg", ".jpeg", ".png", ".gif", ".bmp"],
+ "documents": [".pdf", ".doc", ".docx", ".txt", ".md"],
+ "videos": [".mp4", ".avi", ".mkv", ".mov"],
+ "audio": [".mp3", ".wav", ".flac"],
+ "archives": [".zip", ".rar", ".7z", ".tar"]
+ }
# 2. 初始化标签系统
+ self.tags = {}
# 3. 创建必要的目录结构
pass
@@ -104,11 +190,35 @@ class DocumentOrganizer:
- 根据预设规则对文档进行分类
- 返回分类结果字典
"""
- # TODO: 实现文档分类逻辑
+ # 实现文档分类逻辑
# 1. 遍历目录中的所有文件
+ if not os.path.exists(directory):
+ raise FileNotFoundError(f"目录 {directory} 不存在")
+
# 2. 根据文件类型或内容特征进行分类
+ categorized_files = {category: [] for category in self.categorization_rules}
+ uncategorized = []
+
+ for root, _, files in os.walk(directory):
+ for file in files:
+ file_path = os.path.join(root, file)
+ _, ext = os.path.splitext(file)
+
+ # 根据扩展名分类
+ categorized = False
+ for category, extensions in self.categorization_rules.items():
+ if ext.lower() in extensions:
+ categorized_files[category].append(file_path)
+ categorized = True
+ break
+
+ if not categorized:
+ uncategorized.append(file_path)
+
+ categorized_files["uncategorized"] = uncategorized
+
# 3. 返回分类结果字典 {类别: [文件列表]}
- pass
+ return categorized_files
def add_tag_to_file(self, file_path: str, tag: str) -> bool:
"""
@@ -116,13 +226,23 @@ class DocumentOrganizer:
- 在文件元数据中添加标签信息
- 返回操作结果
"""
- # TODO: 实现标签添加逻辑
+ # 实现标签添加逻辑
# 1. 检查文件是否存在
+ if not os.path.exists(file_path):
+ print(f"文件 {file_path} 不存在")
+ return False
+
# 2. 读取文件元数据
# 3. 添加新标签
+ if file_path not in self.tags:
+ self.tags[file_path] = []
+
+ if tag not in self.tags[file_path]:
+ self.tags[file_path].append(tag)
+
# 4. 保存更新后的元数据
# 5. 返回操作结果
- pass
+ return True
def search_files_by_tag(self, tag: str) -> List[str]:
"""
@@ -130,11 +250,16 @@ class DocumentOrganizer:
- 查找具有指定标签的所有文件
- 返回文件路径列表
"""
- # TODO: 实现标签搜索逻辑
+ # 实现标签搜索逻辑
# 1. 遍历文件数据库或目录
# 2. 查找包含指定标签的文件
+ matching_files = []
+ for file_path, tags in self.tags.items():
+ if tag in tags:
+ matching_files.append(file_path)
+
# 3. 返回文件路径列表
- pass
+ return matching_files
def backup_documents(self, source_dir: str, backup_dir: str) -> bool:
"""
@@ -142,10 +267,38 @@ class DocumentOrganizer:
- 将源目录中的文档备份到备份目录
- 返回操作结果
"""
- # TODO: 实现文档备份逻辑
+ # 实现文档备份逻辑
# 1. 创建备份目录(如果不存在)
+ if not os.path.exists(backup_dir):
+ os.makedirs(backup_dir)
+
# 2. 遍历源目录中的所有文件
- # 3. 复制文件到备份目录
- # 4. 处理异常情况
- # 5. 返回操作结果
- pass
\ No newline at end of file
+ if not os.path.exists(source_dir):
+ print(f"源目录 {source_dir} 不存在")
+ return False
+
+ try:
+ # 使用shutil.copytree进行目录复制
+ # 如果备份目录已存在且不为空,需要先清空或使用其他方法
+ for root, dirs, files in os.walk(source_dir):
+ # 计算相对路径
+ rel_path = os.path.relpath(root, source_dir)
+ dest_path = os.path.join(backup_dir, rel_path) if rel_path != '.' else backup_dir
+
+ # 创建目标目录
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+
+ # 复制文件
+ for file in files:
+ src_file = os.path.join(root, file)
+ dest_file = os.path.join(dest_path, file)
+ shutil.copy2(src_file, dest_file)
+
+ # 3. 处理异常情况
+ except Exception as e:
+ print(f"备份文档时出错: {e}")
+ return False
+
+ # 4. 返回操作结果
+ return True
\ No newline at end of file
diff --git a/src/input_handler/input_processor.py b/src/input_handler/input_processor.py
index d60790a..04e232a 100644
--- a/src/input_handler/input_processor.py
+++ b/src/input_handler/input_processor.py
@@ -15,11 +15,14 @@ class InputProcessor(QObject):
- 初始化输入缓冲区
"""
super().__init__()
- # TODO: 实现构造函数逻辑
+ # 实现构造函数逻辑
# 1. 初始化输入缓冲区
+ self.input_buffer = ""
# 2. 设置初始状态
+ self.is_input_active = False
# 3. 初始化相关属性
- pass
+ self.expected_text = ""
+ self.current_position = 0
def process_key_event(self, key: str) -> bool:
"""
@@ -29,23 +32,34 @@ class InputProcessor(QObject):
- 发送相关信号
- 返回处理结果
"""
- # TODO: 实现按键事件处理逻辑
+ # 实现按键事件处理逻辑
# 1. 检查按键是否有效
+ if not key:
+ return False
+
# 2. 根据按键类型处理(字符、功能键等)
# 3. 更新输入缓冲区
+ self.input_buffer += key
+ self.current_position += 1
+
# 4. 发送text_changed信号
+ self.text_changed.emit(key)
+
# 5. 检查是否完成输入,如是则发送input_completed信号
+ if self.expected_text and self.input_buffer == self.expected_text:
+ self.input_completed.emit()
+
# 6. 返回处理结果
- pass
+ return True
def get_current_input(self) -> str:
"""
获取当前输入
- 返回输入缓冲区内容
"""
- # TODO: 实现获取当前输入逻辑
+ # 实现获取当前输入逻辑
# 1. 返回输入缓冲区内容
- pass
+ return self.input_buffer
def reset_input(self):
"""
@@ -53,21 +67,26 @@ class InputProcessor(QObject):
- 清空输入缓冲区
- 重置相关状态
"""
- # TODO: 实现输入重置逻辑
+ # 实现输入重置逻辑
# 1. 清空输入缓冲区
+ self.input_buffer = ""
# 2. 重置相关状态变量
+ self.current_position = 0
+ self.is_input_active = False
# 3. 发送重置信号(如需要)
- pass
def set_expected_text(self, text: str):
"""
设置期望文本
- 用于后续输入验证
"""
- # TODO: 实现设置期望文本逻辑
+ # 实现设置期望文本逻辑
# 1. 保存期望文本
+ self.expected_text = text
# 2. 初始化匹配相关状态
- pass
+ self.current_position = 0
+ self.input_buffer = ""
+ self.is_input_active = True
class InputValidator:
def __init__(self):
@@ -75,10 +94,11 @@ class InputValidator:
初始化输入验证器
- 设置验证规则
"""
- # TODO: 实现构造函数逻辑
+ # 实现构造函数逻辑
# 1. 初始化验证规则
+ self.case_sensitive = True
# 2. 设置默认验证参数
- pass
+ self.min_accuracy = 0.0
def validate_character(self, input_char: str, expected_char: str) -> bool:
"""
@@ -86,11 +106,14 @@ class InputValidator:
- 比较输入字符与期望字符
- 返回验证结果
"""
- # TODO: 实现字符验证逻辑
+ # 实现字符验证逻辑
# 1. 比较输入字符与期望字符
# 2. 考虑大小写敏感性设置
+ if self.case_sensitive:
+ return input_char == expected_char
+ else:
+ return input_char.lower() == expected_char.lower()
# 3. 返回验证结果
- pass
def validate_word(self, input_word: str, expected_word: str) -> dict:
"""
@@ -98,12 +121,32 @@ class InputValidator:
- 比较输入单词与期望单词
- 返回详细验证结果(正确字符数、错误字符数等)
"""
- # TODO: 实现单词验证逻辑
+ # 实现单词验证逻辑
# 1. 逐字符比较输入单词与期望单词
+ correct_count = 0
+ incorrect_count = 0
+ total_chars = max(len(input_word), len(expected_word))
+
# 2. 统计正确/错误字符数
+ for i in range(total_chars):
+ input_char = input_word[i] if i < len(input_word) else ""
+ expected_char = expected_word[i] if i < len(expected_word) else ""
+
+ if self.validate_character(input_char, expected_char):
+ correct_count += 1
+ else:
+ incorrect_count += 1
+
# 3. 计算准确率
+ accuracy = correct_count / total_chars if total_chars > 0 else 0.0
+
# 4. 返回验证结果字典
- pass
+ return {
+ "correct_count": correct_count,
+ "incorrect_count": incorrect_count,
+ "total_chars": total_chars,
+ "accuracy": accuracy
+ }
def calculate_accuracy(self, input_text: str, expected_text: str) -> float:
"""
@@ -111,9 +154,24 @@ class InputValidator:
- 比较输入文本与期望文本
- 返回准确率百分比
"""
- # TODO: 实现准确率计算逻辑
+ # 实现准确率计算逻辑
# 1. 比较输入文本与期望文本
# 2. 统计正确字符数
+ correct_count = 0
+ total_chars = max(len(input_text), len(expected_text))
+
+ if total_chars == 0:
+ return 1.0 # 两个空字符串认为是完全匹配
+
+ for i in range(total_chars):
+ input_char = input_text[i] if i < len(input_text) else ""
+ expected_char = expected_text[i] if i < len(expected_text) else ""
+
+ if self.validate_character(input_char, expected_char):
+ correct_count += 1
+
# 3. 计算准确率百分比
+ accuracy = correct_count / total_chars
+
# 4. 返回准确率
- pass
\ No newline at end of file
+ return accuracy
\ No newline at end of file
diff --git a/src/services/network_service.py b/src/services/network_service.py
index 76095ea..07171bf 100644
--- a/src/services/network_service.py
+++ b/src/services/network_service.py
@@ -1,6 +1,7 @@
# services/network_service.py
import requests
import json
+import os
from typing import Optional, Dict, Any
class NetworkService:
@@ -10,8 +11,10 @@ class NetworkService:
- 设置API密钥
- 初始化缓存
"""
- # TODO: 实现构造函数逻辑
- pass
+ # 实现构造函数逻辑
+ self.api_key = None
+ self.cache = {}
+ self.session = requests.Session()
def get_weather_info(self) -> Optional[Dict[str, Any]]:
"""
@@ -20,13 +23,54 @@ class NetworkService:
- 解析返回数据
- 返回格式化的天气信息
"""
- # TODO: 实现天气信息获取逻辑
+ # 实现天气信息获取逻辑
# 1. 获取用户IP地址
- # 2. 根据IP获取地理位置
- # 3. 调用天气API获取天气数据
- # 4. 解析并格式化数据
- # 5. 返回天气信息字典
- pass
+ try:
+ ip_response = self.session.get("https://httpbin.org/ip", timeout=5)
+ ip_data = ip_response.json()
+ ip = ip_data.get("origin", "")
+
+ # 2. 根据IP获取地理位置
+ # 注意:这里使用免费的IP地理位置API,实际应用中可能需要更精确的服务
+ location_response = self.session.get(f"http://ip-api.com/json/{ip}", timeout=5)
+ location_data = location_response.json()
+
+ if location_data.get("status") != "success":
+ return None
+
+ city = location_data.get("city", "Unknown")
+
+ # 3. 调用天气API获取天气数据
+ # 注意:这里使用OpenWeatherMap API作为示例,需要API密钥
+ # 在实际应用中,需要设置有效的API密钥
+ if self.api_key:
+ weather_url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={self.api_key}&units=metric&lang=zh_cn"
+ weather_response = self.session.get(weather_url, timeout=5)
+ weather_data = weather_response.json()
+
+ # 4. 解析并格式化数据
+ if weather_response.status_code == 200:
+ formatted_weather = {
+ "city": city,
+ "temperature": weather_data["main"]["temp"],
+ "description": weather_data["weather"][0]["description"],
+ "humidity": weather_data["main"]["humidity"],
+ "wind_speed": weather_data["wind"]["speed"]
+ }
+ # 5. 返回天气信息字典
+ return formatted_weather
+ else:
+ # 模拟天气数据(无API密钥时)
+ return {
+ "city": city,
+ "temperature": 20,
+ "description": "晴天",
+ "humidity": 60,
+ "wind_speed": 3.5
+ }
+ except Exception as e:
+ print(f"获取天气信息时出错: {e}")
+ return None
def get_daily_quote(self) -> Optional[str]:
"""
@@ -34,54 +78,160 @@ class NetworkService:
- 调用名言API
- 返回格式化的名言
"""
- # TODO: 实现每日一句获取逻辑
+ # 实现每日一句获取逻辑
# 1. 调用名言API
- # 2. 解析返回的名言数据
- # 3. 格式化名言文本
- # 4. 返回名言字符串
- pass
+ try:
+ # 使用一个免费的名言API
+ response = self.session.get("https://api.quotable.io/random", timeout=5)
+
+ # 2. 解析返回的名言数据
+ if response.status_code == 200:
+ quote_data = response.json()
+ content = quote_data.get("content", "")
+ author = quote_data.get("author", "")
+
+ # 3. 格式化名言文本
+ formatted_quote = f'"{content}" - {author}'
+
+ # 4. 返回名言字符串
+ return formatted_quote
+ else:
+ # 如果API调用失败,返回默认名言
+ return "书山有路勤为径,学海无涯苦作舟。"
+ except Exception as e:
+ print(f"获取每日一句时出错: {e}")
+ # 出错时返回默认名言
+ return "书山有路勤为径,学海无涯苦作舟。"
def download_image(self, url: str) -> Optional[bytes]:
"""
下载图片
- - 从指定URL下载图片
- - 返回图片二进制数据
+ - 发送HTTP请求获取图片
+ - 返回图片的二进制数据
"""
- # TODO: 实现图片下载逻辑
- # 1. 发送HTTP GET请求获取图片
- # 2. 检查响应状态码
- # 3. 返回图片二进制数据
- pass
+ # 实现图片下载逻辑
+ # 1. 发送GET请求下载图片
+ try:
+ response = self.session.get(url, timeout=10)
+
+ # 2. 检查响应状态码
+ if response.status_code == 200:
+ # 3. 返回图片的二进制数据
+ return response.content
+ else:
+ print(f"下载图片失败,状态码: {response.status_code}")
+ return None
+ except Exception as e:
+ print(f"下载图片时出错: {e}")
+ return None
class ImageService:
def __init__(self):
"""
初始化图片服务
+ - 设置支持的图片格式
+ - 初始化图片缓存
"""
- # TODO: 实现构造函数逻辑
- pass
+ # 实现构造函数逻辑
+ self.supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif'}
+ self.image_cache = {}
+ self.max_cache_size = 100 # 最大缓存图片数量
def extract_images_from_document(self, file_path: str) -> list:
"""
从文档中提取图片
- - 解析文档中的图片
- - 返回图片列表
+ - 解析文档格式
+ - 提取所有嵌入的图片
+ - 返回图片数据列表
"""
- # TODO: 实现图片提取逻辑
- # 1. 根据文件类型选择解析方法
- # 2. 提取文档中的图片数据
- # 3. 返回图片信息列表
- pass
+ # 实现从文档提取图片逻辑
+ # 1. 检查文件是否存在
+ if not os.path.exists(file_path):
+ print(f"文件不存在: {file_path}")
+ return []
+
+ # 2. 检查文件扩展名
+ _, ext = os.path.splitext(file_path)
+ ext = ext.lower()
+
+ # 3. 根据不同文档类型提取图片
+ images = []
+
+ try:
+ # 简化实现:仅处理PDF文件
+ if ext == '.pdf':
+ # 注意:这需要安装PyMuPDF或pdfplumber库
+ # 示例使用PyMuPDF (fitz)
+ try:
+ import fitz # PyMuPDF
+ pdf_document = fitz.open(file_path)
+
+ for page_num in range(len(pdf_document)):
+ page = pdf_document[page_num]
+ image_list = page.get_images()
+
+ for img_index, img in enumerate(image_list):
+ xref = img[0]
+ base_image = pdf_document.extract_image(xref)
+ image_bytes = base_image["image"]
+ images.append(image_bytes)
+
+ pdf_document.close()
+ except ImportError:
+ print("需要安装PyMuPDF库: pip install PyMuPDF")
+ return []
+ else:
+ print(f"不支持的文件格式: {ext}")
+ return []
+
+ # 4. 返回提取的图片数据列表
+ return images
+
+ except Exception as e:
+ print(f"从文档提取图片时出错: {e}")
+ return []
def display_image_at_position(self, image_data: bytes, position: int) -> bool:
"""
在指定位置显示图片
- - 将图片插入到文本中的指定位置
- - 返回操作结果
+ - 解析图片数据
+ - 在界面指定位置渲染图片
"""
- # TODO: 实现图片显示逻辑
- # 1. 创建图片对象
- # 2. 在指定位置插入图片
- # 3. 更新UI显示
- # 4. 返回操作结果
- pass
\ No newline at end of file
+ # 实现图片显示逻辑
+ # 1. 验证图片数据
+ if not image_data:
+ print("无效的图片数据")
+ return False
+
+ # 2. 验证位置参数
+ if position < 0:
+ print("无效的位置参数")
+ return False
+
+ # 3. 尝试解析图片数据
+ try:
+ # 使用PIL库处理图片
+ try:
+ from PIL import Image
+ from io import BytesIO
+ image = Image.open(BytesIO(image_data))
+
+ # 4. 缓存图片(如果需要)
+ if len(self.image_cache) >= self.max_cache_size:
+ # 移除最旧的缓存项
+ oldest_key = next(iter(self.image_cache))
+ del self.image_cache[oldest_key]
+
+ self.image_cache[position] = image_data
+
+ # 5. 显示图片(简化实现,实际应用中需要与UI框架集成)
+ print(f"图片已缓存到位置 {position},尺寸: {image.size},格式: {image.format}")
+ # 在实际应用中,这里会调用UI框架的相关方法在指定位置显示图片
+
+ return True
+ except ImportError:
+ print("需要安装Pillow库: pip install Pillow")
+ return False
+ except Exception as e:
+ print(f"解析或显示图片时出错: {e}")
+ return False
\ No newline at end of file
--
2.34.1
From 96c269db45064cb3c36ebd6735a1e15d201b7d95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=9F=B3=E5=85=B4=E9=9C=96?= <3189844089@qq.com>
Date: Sat, 11 Oct 2025 18:37:44 +0800
Subject: [PATCH 06/11] 1112
---
src/file_manager/file_operations.py | 68 +++++-----------------------
src/input_handler/input_processor.py | 53 ++++------------------
src/services/network_service.py | 44 +++---------------
3 files changed, 27 insertions(+), 138 deletions(-)
diff --git a/src/file_manager/file_operations.py b/src/file_manager/file_operations.py
index a835e35..f7c8351 100644
--- a/src/file_manager/file_operations.py
+++ b/src/file_manager/file_operations.py
@@ -6,11 +6,7 @@ from pathlib import Path
class FileManager:
def __init__(self):
- """
- 初始化文件管理器
- - 设置工作目录
- - 初始化文件缓存
- """
+
# 实现构造函数逻辑
# 1. 设置默认工作目录
self.working_directory = Path.cwd()
@@ -20,12 +16,7 @@ class FileManager:
pass
def list_files(self, directory: str, extensions: Optional[List[str]] = None) -> List[str]:
- """
- 列出目录中的文件
- - 遍历指定目录
- - 根据扩展名过滤文件(如果提供)
- - 返回文件路径列表
- """
+
# 实现文件列表逻辑
# 1. 检查目录是否存在
if not os.path.exists(directory):
@@ -48,11 +39,7 @@ class FileManager:
return file_list
def copy_file(self, source: str, destination: str) -> bool:
- """
- 复制文件
- - 将文件从源路径复制到目标路径
- - 返回操作结果
- """
+
# 实现文件复制逻辑
# 1. 检查源文件是否存在
if not os.path.exists(source):
@@ -76,11 +63,7 @@ class FileManager:
return True
def move_file(self, source: str, destination: str) -> bool:
- """
- 移动文件
- - 将文件从源路径移动到目标路径
- - 返回操作结果
- """
+
# 实现文件移动逻辑
# 1. 检查源文件是否存在
if not os.path.exists(source):
@@ -104,11 +87,7 @@ class FileManager:
return True
def delete_file(self, file_path: str) -> bool:
- """
- 删除文件
- - 删除指定路径的文件
- - 返回操作结果
- """
+
# 实现文件删除逻辑
# 1. 检查文件是否存在
if not os.path.exists(file_path):
@@ -130,11 +109,7 @@ class FileManager:
return True
def get_file_info(self, file_path: str) -> Optional[Dict[str, Any]]:
- """
- 获取文件信息
- - 获取文件大小、修改时间等信息
- - 返回信息字典
- """
+
# 实现文件信息获取逻辑
# 1. 检查文件是否存在
if not os.path.exists(file_path):
@@ -165,11 +140,7 @@ class FileManager:
class DocumentOrganizer:
def __init__(self):
- """
- 初始化文档整理器
- - 设置分类规则
- - 初始化标签系统
- """
+
# 实现构造函数逻辑
# 1. 设置默认分类规则
self.categorization_rules = {
@@ -185,12 +156,7 @@ class DocumentOrganizer:
pass
def categorize_documents(self, directory: str) -> Dict[str, List[str]]:
- """
- 分类文档
- - 根据预设规则对文档进行分类
- - 返回分类结果字典
- """
- # 实现文档分类逻辑
+
# 1. 遍历目录中的所有文件
if not os.path.exists(directory):
raise FileNotFoundError(f"目录 {directory} 不存在")
@@ -221,11 +187,7 @@ class DocumentOrganizer:
return categorized_files
def add_tag_to_file(self, file_path: str, tag: str) -> bool:
- """
- 为文件添加标签
- - 在文件元数据中添加标签信息
- - 返回操作结果
- """
+
# 实现标签添加逻辑
# 1. 检查文件是否存在
if not os.path.exists(file_path):
@@ -245,11 +207,7 @@ class DocumentOrganizer:
return True
def search_files_by_tag(self, tag: str) -> List[str]:
- """
- 根据标签搜索文件
- - 查找具有指定标签的所有文件
- - 返回文件路径列表
- """
+
# 实现标签搜索逻辑
# 1. 遍历文件数据库或目录
# 2. 查找包含指定标签的文件
@@ -262,11 +220,7 @@ class DocumentOrganizer:
return matching_files
def backup_documents(self, source_dir: str, backup_dir: str) -> bool:
- """
- 备份文档
- - 将源目录中的文档备份到备份目录
- - 返回操作结果
- """
+
# 实现文档备份逻辑
# 1. 创建备份目录(如果不存在)
if not os.path.exists(backup_dir):
diff --git a/src/input_handler/input_processor.py b/src/input_handler/input_processor.py
index 04e232a..542bc0d 100644
--- a/src/input_handler/input_processor.py
+++ b/src/input_handler/input_processor.py
@@ -9,11 +9,7 @@ class InputProcessor(QObject):
input_completed = pyqtSignal() # 输入完成信号
def __init__(self):
- """
- 初始化输入处理器
- - 设置初始状态
- - 初始化输入缓冲区
- """
+
super().__init__()
# 实现构造函数逻辑
# 1. 初始化输入缓冲区
@@ -25,13 +21,7 @@ class InputProcessor(QObject):
self.current_position = 0
def process_key_event(self, key: str) -> bool:
- """
- 处理按键事件
- - 检查按键有效性
- - 更新输入缓冲区
- - 发送相关信号
- - 返回处理结果
- """
+
# 实现按键事件处理逻辑
# 1. 检查按键是否有效
if not key:
@@ -53,20 +43,13 @@ class InputProcessor(QObject):
return True
def get_current_input(self) -> str:
- """
- 获取当前输入
- - 返回输入缓冲区内容
- """
+
# 实现获取当前输入逻辑
# 1. 返回输入缓冲区内容
return self.input_buffer
def reset_input(self):
- """
- 重置输入
- - 清空输入缓冲区
- - 重置相关状态
- """
+
# 实现输入重置逻辑
# 1. 清空输入缓冲区
self.input_buffer = ""
@@ -76,10 +59,7 @@ class InputProcessor(QObject):
# 3. 发送重置信号(如需要)
def set_expected_text(self, text: str):
- """
- 设置期望文本
- - 用于后续输入验证
- """
+
# 实现设置期望文本逻辑
# 1. 保存期望文本
self.expected_text = text
@@ -90,10 +70,7 @@ class InputProcessor(QObject):
class InputValidator:
def __init__(self):
- """
- 初始化输入验证器
- - 设置验证规则
- """
+
# 实现构造函数逻辑
# 1. 初始化验证规则
self.case_sensitive = True
@@ -101,11 +78,7 @@ class InputValidator:
self.min_accuracy = 0.0
def validate_character(self, input_char: str, expected_char: str) -> bool:
- """
- 验证字符输入
- - 比较输入字符与期望字符
- - 返回验证结果
- """
+
# 实现字符验证逻辑
# 1. 比较输入字符与期望字符
# 2. 考虑大小写敏感性设置
@@ -116,11 +89,7 @@ class InputValidator:
# 3. 返回验证结果
def validate_word(self, input_word: str, expected_word: str) -> dict:
- """
- 验证单词输入
- - 比较输入单词与期望单词
- - 返回详细验证结果(正确字符数、错误字符数等)
- """
+
# 实现单词验证逻辑
# 1. 逐字符比较输入单词与期望单词
correct_count = 0
@@ -149,11 +118,7 @@ class InputValidator:
}
def calculate_accuracy(self, input_text: str, expected_text: str) -> float:
- """
- 计算输入准确率
- - 比较输入文本与期望文本
- - 返回准确率百分比
- """
+
# 实现准确率计算逻辑
# 1. 比较输入文本与期望文本
# 2. 统计正确字符数
diff --git a/src/services/network_service.py b/src/services/network_service.py
index 07171bf..e8ee040 100644
--- a/src/services/network_service.py
+++ b/src/services/network_service.py
@@ -6,23 +6,14 @@ from typing import Optional, Dict, Any
class NetworkService:
def __init__(self):
- """
- 初始化网络服务
- - 设置API密钥
- - 初始化缓存
- """
+
# 实现构造函数逻辑
self.api_key = None
self.cache = {}
self.session = requests.Session()
def get_weather_info(self) -> Optional[Dict[str, Any]]:
- """
- 获取天气信息
- - 调用天气API
- - 解析返回数据
- - 返回格式化的天气信息
- """
+
# 实现天气信息获取逻辑
# 1. 获取用户IP地址
try:
@@ -73,11 +64,7 @@ class NetworkService:
return None
def get_daily_quote(self) -> Optional[str]:
- """
- 获取每日一句
- - 调用名言API
- - 返回格式化的名言
- """
+
# 实现每日一句获取逻辑
# 1. 调用名言API
try:
@@ -104,11 +91,7 @@ class NetworkService:
return "书山有路勤为径,学海无涯苦作舟。"
def download_image(self, url: str) -> Optional[bytes]:
- """
- 下载图片
- - 发送HTTP请求获取图片
- - 返回图片的二进制数据
- """
+
# 实现图片下载逻辑
# 1. 发送GET请求下载图片
try:
@@ -127,23 +110,14 @@ class NetworkService:
class ImageService:
def __init__(self):
- """
- 初始化图片服务
- - 设置支持的图片格式
- - 初始化图片缓存
- """
+
# 实现构造函数逻辑
self.supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif'}
self.image_cache = {}
self.max_cache_size = 100 # 最大缓存图片数量
def extract_images_from_document(self, file_path: str) -> list:
- """
- 从文档中提取图片
- - 解析文档格式
- - 提取所有嵌入的图片
- - 返回图片数据列表
- """
+
# 实现从文档提取图片逻辑
# 1. 检查文件是否存在
if not os.path.exists(file_path):
@@ -192,11 +166,7 @@ class ImageService:
return []
def display_image_at_position(self, image_data: bytes, position: int) -> bool:
- """
- 在指定位置显示图片
- - 解析图片数据
- - 在界面指定位置渲染图片
- """
+
# 实现图片显示逻辑
# 1. 验证图片数据
if not image_data:
--
2.34.1
From 29147dab62665ed48848a98cd8f9e86dc60b45ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=9F=B3=E5=85=B4=E9=9C=96?= <3189844089@qq.com>
Date: Sat, 11 Oct 2025 18:39:40 +0800
Subject: [PATCH 07/11] file_manager/file_operations.py
---
src/file_manager/file_operations.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/file_manager/file_operations.py b/src/file_manager/file_operations.py
index f7c8351..17c67e3 100644
--- a/src/file_manager/file_operations.py
+++ b/src/file_manager/file_operations.py
@@ -7,7 +7,7 @@ from pathlib import Path
class FileManager:
def __init__(self):
- # 实现构造函数逻辑
+ # 实现构造函数逻辑123
# 1. 设置默认工作目录
self.working_directory = Path.cwd()
# 2. 初始化文件缓存
--
2.34.1
From 7baac7d920e95e39e0a61c818b53d5eeee75bf6f Mon Sep 17 00:00:00 2001
From: Lesacm <1500309685@qq.com>
Date: Sat, 11 Oct 2025 19:32:10 +0800
Subject: [PATCH 08/11] 0.1
---
.../resources/config/test_config.json | 45 +++
src/settings/settings_manager.py | 117 ++++++-
src/ui/components.py | 315 ++++++++++++++----
3 files changed, 397 insertions(+), 80 deletions(-)
create mode 100644 src/settings/resources/config/test_config.json
diff --git a/src/settings/resources/config/test_config.json b/src/settings/resources/config/test_config.json
new file mode 100644
index 0000000..9f16c30
--- /dev/null
+++ b/src/settings/resources/config/test_config.json
@@ -0,0 +1,45 @@
+{
+ "application": {
+ "name": "MagicWord",
+ "version": "2.0.0",
+ "author": "MagicWord Team",
+ "description": "隐私学习软件"
+ },
+ "window": {
+ "default_size": {
+ "width": 800,
+ "height": 600
+ },
+ "minimum_size": {
+ "width": 600,
+ "height": 400
+ },
+ "title": "MagicWord - 隐私学习软件"
+ },
+ "typing": {
+ "default_time_limit": 300,
+ "show_progress_bar": true,
+ "highlight_current_line": true,
+ "auto_save_progress": true
+ },
+ "files": {
+ "supported_formats": [
+ ".txt",
+ ".docx"
+ ],
+ "auto_backup_enabled": true,
+ "backup_interval_minutes": 30
+ },
+ "network": {
+ "weather_api_key": "YOUR_WEATHER_API_KEY",
+ "quote_api_url": "https://api.quotable.io/random",
+ "timeout_seconds": 10
+ },
+ "appearance": {
+ "theme": "light",
+ "font_family": "Arial",
+ "font_size": 12,
+ "text_color": "#000000",
+ "background_color": "#FFFFFF"
+ }
+}
\ No newline at end of file
diff --git a/src/settings/settings_manager.py b/src/settings/settings_manager.py
index c08d2da..9f647ef 100644
--- a/src/settings/settings_manager.py
+++ b/src/settings/settings_manager.py
@@ -7,11 +7,66 @@ class SettingsManager:
def __init__(self, config_file: str = "config.json"):
"""
初始化设置管理器
- - 指定配置文件路径123
+ - 指定配置文件路径
- 加载现有配置或创建默认配置
"""
- # TODO: 实现构造函数逻辑
- pass
+ # 指定配置文件路径
+ self.config_file = config_file
+ self.config_path = os.path.join("resources", "config", config_file)
+
+ # 加载现有配置或创建默认配置
+ self.settings = self.load_settings()
+ if not self.settings:
+ self.settings = self._create_default_settings()
+ self.save_settings(self.settings)
+
+ def _create_default_settings(self) -> Dict[str, Any]:
+ """
+ 创建默认配置
+ - 返回包含默认设置的字典
+ """
+ return {
+ "application": {
+ "name": "MagicWord",
+ "version": "1.0.0",
+ "author": "MagicWord Team",
+ "description": "隐私学习软件"
+ },
+ "window": {
+ "default_size": {
+ "width": 800,
+ "height": 600
+ },
+ "minimum_size": {
+ "width": 600,
+ "height": 400
+ },
+ "title": "MagicWord - 隐私学习软件"
+ },
+ "typing": {
+ "default_time_limit": 300,
+ "show_progress_bar": True,
+ "highlight_current_line": True,
+ "auto_save_progress": True
+ },
+ "files": {
+ "supported_formats": [".txt", ".docx"],
+ "auto_backup_enabled": True,
+ "backup_interval_minutes": 30
+ },
+ "network": {
+ "weather_api_key": "YOUR_WEATHER_API_KEY",
+ "quote_api_url": "https://api.quotable.io/random",
+ "timeout_seconds": 10
+ },
+ "appearance": {
+ "theme": "light",
+ "font_family": "Arial",
+ "font_size": 12,
+ "text_color": "#000000",
+ "background_color": "#FFFFFF"
+ }
+ }
def load_settings(self) -> Dict[str, Any]:
"""
@@ -19,8 +74,15 @@ class SettingsManager:
- 从配置文件读取设置
- 返回设置字典
"""
- # TODO: 实现设置加载逻辑
- pass
+ try:
+ if os.path.exists(self.config_path):
+ with open(self.config_path, 'r', encoding='utf-8') as f:
+ return json.load(f)
+ else:
+ return {}
+ except (json.JSONDecodeError, IOError) as e:
+ print(f"加载配置文件时出错: {e}")
+ return {}
def save_settings(self, settings: Dict[str, Any]) -> bool:
"""
@@ -28,8 +90,19 @@ class SettingsManager:
- 将设置保存到配置文件
- 返回保存结果
"""
- # TODO: 实现设置保存逻辑
- pass
+ try:
+ # 确保目录存在
+ config_dir = os.path.dirname(self.config_path)
+ if not os.path.exists(config_dir):
+ os.makedirs(config_dir)
+
+ # 保存设置到文件
+ with open(self.config_path, 'w', encoding='utf-8') as f:
+ json.dump(settings, f, ensure_ascii=False, indent=4)
+ return True
+ except (IOError, TypeError) as e:
+ print(f"保存配置文件时出错: {e}")
+ return False
def get_setting(self, key: str, default: Any = None) -> Any:
"""
@@ -37,8 +110,14 @@ class SettingsManager:
- 根据键名获取设置值
- 如果不存在返回默认值
"""
- # TODO: 实现获取设置项逻辑
- pass
+ keys = key.split('.')
+ value = self.settings
+ try:
+ for k in keys:
+ value = value[k]
+ return value
+ except (KeyError, TypeError):
+ return default
def set_setting(self, key: str, value: Any) -> bool:
"""
@@ -46,5 +125,21 @@ class SettingsManager:
- 设置指定键的值
- 保存到配置文件
"""
- # TODO: 实现设置设置项逻辑
- pass
\ No newline at end of file
+ keys = key.split('.')
+ setting_dict = self.settings
+
+ # 导航到倒数第二个键
+ try:
+ for k in keys[:-1]:
+ if k not in setting_dict:
+ setting_dict[k] = {}
+ setting_dict = setting_dict[k]
+
+ # 设置最后一个键的值
+ setting_dict[keys[-1]] = value
+
+ # 保存到配置文件
+ return self.save_settings(self.settings)
+ except (KeyError, TypeError) as e:
+ print(f"设置配置项时出错: {e}")
+ return False
\ No newline at end of file
diff --git a/src/ui/components.py b/src/ui/components.py
index 2763f93..948839f 100644
--- a/src/ui/components.py
+++ b/src/ui/components.py
@@ -10,12 +10,8 @@ class CustomTitleBar(QWidget):
- 添加窗口控制按钮
"""
super().__init__(parent)
- # TODO: 实现标题栏UI
- # 1. 创建标题标签
- # 2. 创建最小化、最大化、关闭按钮
- # 3. 设置布局和样式
- # 4. 连接按钮事件
- pass
+ self.parent = parent
+ self.setup_ui()
def setup_ui(self):
"""
@@ -23,42 +19,92 @@ class CustomTitleBar(QWidget):
- 初始化所有UI组件
- 设置组件属性和样式
"""
- # TODO: 实现UI设置逻辑
- # 1. 创建水平布局
- # 2. 添加标题标签和控制按钮
- # 3. 设置组件样式
- pass
+ # 创建水平布局
+ layout = QHBoxLayout()
+ layout.setContentsMargins(10, 5, 10, 5)
+ layout.setSpacing(10)
+
+ # 创建标题标签
+ self.title_label = QLabel("MagicWord")
+ self.title_label.setStyleSheet("color: #333333; font-size: 12px; font-weight: normal;")
+
+ # 创建控制按钮
+ self.minimize_button = QPushButton("—")
+ self.maximize_button = QPushButton("□")
+ self.close_button = QPushButton("×")
+
+ # 设置按钮样式
+ button_style = """
+ QPushButton {
+ background-color: transparent;
+ border: none;
+ color: #333333;
+ font-size: 12px;
+ font-weight: normal;
+ width: 30px;
+ height: 30px;
+ }
+ QPushButton:hover {
+ background-color: #d0d0d0;
+ }
+ """
+
+ self.minimize_button.setStyleSheet(button_style)
+ self.maximize_button.setStyleSheet(button_style)
+ self.close_button.setStyleSheet(button_style + "QPushButton:hover { background-color: #ff5555; color: white; }")
+
+ # 添加组件到布局
+ layout.addWidget(self.title_label)
+ layout.addStretch()
+ layout.addWidget(self.minimize_button)
+ layout.addWidget(self.maximize_button)
+ layout.addWidget(self.close_button)
+
+ self.setLayout(layout)
+
+ # 连接按钮事件
+ self.minimize_button.clicked.connect(self.minimize_window)
+ self.maximize_button.clicked.connect(self.maximize_window)
+ self.close_button.clicked.connect(self.close_window)
+
+ # 设置标题栏样式
+ self.setStyleSheet("""
+ CustomTitleBar {
+ background-color: #f0f0f0;
+ border-top-left-radius: 0px;
+ border-top-right-radius: 0px;
+ border-bottom: 1px solid #d0d0d0;
+ }
+ """)
def minimize_window(self):
"""
最小化窗口
- 触发窗口最小化事件
"""
- # TODO: 实现窗口最小化逻辑
- # 1. 获取父窗口
- # 2. 调用窗口最小化方法
- pass
+ if self.parent:
+ self.parent.showMinimized()
def maximize_window(self):
"""
最大化窗口
- 切换窗口最大化状态
"""
- # TODO: 实现窗口最大化逻辑
- # 1. 获取父窗口
- # 2. 检查当前窗口状态
- # 3. 切换最大化/还原状态
- pass
+ if self.parent:
+ if self.parent.isMaximized():
+ self.parent.showNormal()
+ self.maximize_button.setText("□")
+ else:
+ self.parent.showMaximized()
+ self.maximize_button.setText("❐")
def close_window(self):
"""
关闭窗口
- 触发窗口关闭事件
"""
- # TODO: 实现窗口关闭逻辑
- # 1. 获取父窗口
- # 2. 调用窗口关闭方法
- pass
+ if self.parent:
+ self.parent.close()
class ProgressBarWidget(QWidget):
def __init__(self, parent=None):
@@ -68,11 +114,69 @@ class ProgressBarWidget(QWidget):
- 显示统计信息
"""
super().__init__(parent)
- # TODO: 实现进度条组件初始化
- # 1. 创建进度条UI元素
- # 2. 创建统计信息标签
- # 3. 设置布局
- pass
+ self.setup_ui()
+
+ def setup_ui(self):
+ """
+ 设置进度条UI
+ - 初始化所有UI组件
+ - 设置组件属性和样式
+ """
+ # 创建垂直布局
+ layout = QVBoxLayout()
+ layout.setContentsMargins(10, 10, 10, 10)
+ layout.setSpacing(5)
+
+ # 导入需要的模块
+ from PyQt5.QtWidgets import QProgressBar, QHBoxLayout
+
+ # 创建水平布局用于统计信息
+ stats_layout = QHBoxLayout()
+ stats_layout.setSpacing(15)
+
+ # 创建统计信息标签
+ self.wpm_label = QLabel("WPM: 0")
+ self.accuracy_label = QLabel("准确率: 0%")
+ self.time_label = QLabel("用时: 0s")
+
+ # 设置标签样式
+ label_style = "font-size: 12px; font-weight: normal; color: #333333;"
+ self.wpm_label.setStyleSheet(label_style)
+ self.accuracy_label.setStyleSheet(label_style)
+ self.time_label.setStyleSheet(label_style)
+
+ # 添加标签到统计布局
+ stats_layout.addWidget(self.wpm_label)
+ stats_layout.addWidget(self.accuracy_label)
+ stats_layout.addWidget(self.time_label)
+ stats_layout.addStretch()
+
+ # 创建进度条
+ self.progress_bar = QProgressBar()
+ self.progress_bar.setRange(0, 100)
+ self.progress_bar.setValue(0)
+ self.progress_bar.setTextVisible(True)
+ self.progress_bar.setFormat("进度: %p%")
+
+ # 设置进度条样式
+ self.progress_bar.setStyleSheet("""
+ QProgressBar {
+ border: 1px solid #c0c0c0;
+ border-radius: 0px;
+ text-align: center;
+ background-color: #f0f0f0;
+ }
+ QProgressBar::chunk {
+ background-color: #0078d7;
+ border-radius: 0px;
+ }
+ """)
+
+ # 添加组件到主布局
+ layout.addLayout(stats_layout)
+ layout.addWidget(self.progress_bar)
+
+ self.setLayout(layout)
def update_progress(self, progress: float):
"""
@@ -80,21 +184,18 @@ class ProgressBarWidget(QWidget):
- 设置进度值
- 更新显示
"""
- # TODO: 实现进度更新逻辑
- # 1. 更新进度条数值
- # 2. 刷新UI显示
- pass
+ self.progress_bar.setValue(int(progress))
def update_stats(self, wpm: int, accuracy: float, time_elapsed: int):
"""
更新统计信息
- - 显示WPM、准确率、用时等信息
+ - wpm: 每分钟字数
+ - accuracy: 准确率(%)
+ - time_elapsed: 用时(秒)
"""
- # TODO: 实现统计信息更新逻辑
- # 1. 更新WPM标签
- # 2. 更新准确率标签
- # 3. 更新用时标签
- pass
+ self.wpm_label.setText(f"WPM: {wpm}")
+ self.accuracy_label.setText(f"准确率: {accuracy:.1f}%")
+ self.time_label.setText(f"用时: {time_elapsed}s")
class TextDisplayWidget(QWidget):
def __init__(self, parent=None):
@@ -102,47 +203,123 @@ class TextDisplayWidget(QWidget):
文本显示组件
- 显示待练习文本
- 高亮当前字符
- - 显示用户输入
+ - 显示用户输入反馈
"""
super().__init__(parent)
- # TODO: 实现文本显示组件初始化
- # 1. 创建文本显示区域
- # 2. 设置文本样式
- # 3. 初始化高亮相关属性
- pass
+ self.text_content = ""
+ self.current_index = 0
+ self.setup_ui()
+
+ def setup_ui(self):
+ """
+ 设置文本显示UI
+ - 初始化文本显示区域
+ - 设置样式和布局
+ """
+ # 创建垂直布局
+ layout = QVBoxLayout()
+ layout.setContentsMargins(20, 20, 20, 20)
+
+ # 导入需要的模块
+ from PyQt5.QtWidgets import QTextEdit
+ from PyQt5.QtCore import Qt
+
+ # 创建文本显示区域
+ self.text_display = QTextEdit()
+ self.text_display.setReadOnly(True)
+ self.text_display.setLineWrapMode(QTextEdit.WidgetWidth)
+
+ # 设置文本显示样式
+ self.text_display.setStyleSheet("""
+ QTextEdit {
+ font-family: 'Calibri', 'Segoe UI', 'Microsoft YaHei', sans-serif;
+ font-size: 12pt;
+ border: 1px solid #d0d0d0;
+ border-radius: 0px;
+ padding: 15px;
+ background-color: white;
+ color: black;
+ }
+ """)
+
+ # 添加组件到布局
+ layout.addWidget(self.text_display)
+ self.setLayout(layout)
def set_text(self, text: str):
"""
设置显示文本
- - 更新显示内容
- - 重置高亮状态
- """
- # TODO: 实现文本设置逻辑
- # 1. 更新内部文本内容
- # 2. 重置高亮位置
- # 3. 刷新UI显示
- pass
+ - text: 要显示的文本内容
+ """
+ self.text_content = text
+ self.current_index = 0
+ self._update_display()
def highlight_character(self, position: int):
"""
- 高亮指定位置字符
- - 更新高亮位置
- - 刷新显示
+ 高亮指定位置的字符
+ - position: 字符位置索引
"""
- # TODO: 实现字符高亮逻辑
- # 1. 计算高亮范围
- # 2. 应用高亮样式
- # 3. 滚动到高亮位置
- pass
+ if 0 <= position < len(self.text_content):
+ self.current_index = position
+ self._update_display()
+ def _update_display(self, user_input: str = ""):
+ """
+ 更新文本显示
+ - user_input: 用户输入文本(可选)
+ """
+ # 导入需要的模块
+ from PyQt5.QtGui import QTextCursor
+ import sys
+ import os
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+ from constants import COLOR_CORRECT, COLOR_WRONG, COLOR_HIGHLIGHT
+
+ if not self.text_content:
+ self.text_display.clear()
+ return
+
+ # 创建带格式的HTML文本
+ formatted_text = ""
+
+ # 如果有用户输入,对比显示
+ if user_input:
+ for i, char in enumerate(self.text_content):
+ if i < len(user_input):
+ if char == user_input[i]:
+ # 正确字符
+ formatted_text += f'{char}'
+ else:
+ # 错误字符
+ formatted_text += f'{char}'
+ elif i == len(user_input):
+ # 当前字符
+ formatted_text += f'{char}'
+ else:
+ # 未到达的字符
+ formatted_text += char
+ else:
+ # 没有用户输入,只显示原文和当前高亮字符
+ for i, char in enumerate(self.text_content):
+ if i == self.current_index:
+ # 当前字符高亮
+ formatted_text += f'{char}'
+ else:
+ formatted_text += char
+
+ # 更新文本显示
+ self.text_display.setHtml(formatted_text)
+
+ # 滚动到当前高亮字符位置
+ cursor = self.text_display.textCursor()
+ cursor.setPosition(min(self.current_index + 5, len(self.text_content)))
+ self.text_display.setTextCursor(cursor)
+ self.text_display.ensureCursorVisible()
+
def show_user_input(self, input_text: str):
"""
- 显示用户输入
- - 在文本下方显示用户输入
- - 高亮正确/错误字符
+ 显示用户输入反馈
+ - input_text: 用户输入的文本
"""
- # TODO: 实现用户输入显示逻辑
- # 1. 对比用户输入与原文
- # 2. 分别高亮正确和错误字符
- # 3. 更新输入显示区域
- pass
\ No newline at end of file
+ self._update_display(input_text)
\ No newline at end of file
--
2.34.1
From b54919423c80b41123f40d65c7b2a649d67e62d0 Mon Sep 17 00:00:00 2001
From: Lesacm <1500309685@qq.com>
Date: Sat, 11 Oct 2025 19:37:35 +0800
Subject: [PATCH 09/11] 0.1.1
---
src/settings/settings_manager.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/settings/settings_manager.py b/src/settings/settings_manager.py
index 9f647ef..d26a64a 100644
--- a/src/settings/settings_manager.py
+++ b/src/settings/settings_manager.py
@@ -30,7 +30,7 @@ class SettingsManager:
"name": "MagicWord",
"version": "1.0.0",
"author": "MagicWord Team",
- "description": "隐私学习软件"
+ "description": "好东西"
},
"window": {
"default_size": {
@@ -41,7 +41,7 @@ class SettingsManager:
"width": 600,
"height": 400
},
- "title": "MagicWord - 隐私学习软件"
+ "title": "MagicWord"
},
"typing": {
"default_time_limit": 300,
--
2.34.1
From 239ff80ae3adfdd12cd667c187b5be0bf9b9baff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E4=BF=8A=E6=BA=90?= <997724925@qq.com>
Date: Sat, 11 Oct 2025 21:04:17 +0800
Subject: [PATCH 10/11] =?UTF-8?q?=E5=86=99=E4=BA=86=E4=B8=AA=E5=8F=A5?=
=?UTF-8?q?=E5=8F=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/typing_logic.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/typing_logic.py b/src/typing_logic.py
index 6bf0a83..498e123 100644
--- a/src/typing_logic.py
+++ b/src/typing_logic.py
@@ -1,7 +1,7 @@
class TypingLogic:
def __init__(self, learning_content: str):
"""
- 初始化打字逻辑状态
+ 初始化打字逻辑状态。。。。
- 存储学习材料
- 初始化当前索引为0
- 初始化错误计数为0
--
2.34.1
From c76674752d87963c42b6b17cfffdad7e925f111b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E4=BF=8A=E6=BA=90?= <997724925@qq.com>
Date: Sun, 12 Oct 2025 19:32:03 +0800
Subject: [PATCH 11/11] =?UTF-8?q?=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main.py | 34 ++++++--
src/main_window.py | 189 +++++++++++++++++++++++++++++++++++++++-----
src/typing_logic.py | 93 +++++++++++++++++++---
3 files changed, 280 insertions(+), 36 deletions(-)
diff --git a/src/main.py b/src/main.py
index 40e96f8..177583a 100644
--- a/src/main.py
+++ b/src/main.py
@@ -1,22 +1,46 @@
# main.py
import sys
+import traceback
from PyQt5.QtWidgets import QApplication
+from PyQt5.QtCore import Qt
from src.main_window import MainWindow
def main():
"""
应用程序主入口点
- 创建QApplication实例
+ - 设置应用程序属性
- 创建MainWindow实例
- 显示窗口
- 启动事件循环
- 返回退出码
"""
- # TODO: 实现主函数逻辑
- app = QApplication(sys.argv)
- window = MainWindow()
- window.show()
- sys.exit(app.exec_())
+ try:
+ # 创建QApplication实例
+ app = QApplication(sys.argv)
+
+ # 设置应用程序属性
+ app.setApplicationName("隐私学习软件")
+ app.setApplicationVersion("1.0")
+ app.setOrganizationName("个人开发者")
+
+ # 设置高DPI支持
+ app.setAttribute(Qt.AA_EnableHighDpiScaling, True)
+ app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
+
+ # 创建主窗口
+ window = MainWindow()
+ window.show()
+
+ # 启动事件循环并返回退出码
+ exit_code = app.exec_()
+ sys.exit(exit_code)
+
+ except Exception as e:
+ # 打印详细的错误信息
+ print(f"应用程序发生未捕获的异常: {e}")
+ traceback.print_exc()
+ sys.exit(1)
if __name__ == "__main__":
main()
\ No newline at end of file
diff --git a/src/main_window.py b/src/main_window.py
index 2459aa2..918e808 100644
--- a/src/main_window.py
+++ b/src/main_window.py
@@ -1,8 +1,10 @@
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTextEdit, QAction,
- QFileDialog, QVBoxLayout, QWidget, QLabel, QStatusBar)
-from PyQt5.QtGui import QFont, QTextCharFormat, QColor
+ QFileDialog, QVBoxLayout, QWidget, QLabel, QStatusBar, QMessageBox)
+from PyQt5.QtGui import QFont, QTextCharFormat, QColor, QTextCursor
from PyQt5.QtCore import Qt
+from src.file_parser import FileParser
+from src.typing_logic import TypingLogic
class MainWindow(QMainWindow):
def __init__(self):
@@ -14,8 +16,13 @@ class MainWindow(QMainWindow):
- 初始化当前输入位置
- 调用initUI()方法
"""
- # TODO: 实现构造函数逻辑
- pass
+ super().__init__()
+ self.learning_content = ""
+ self.current_position = 0
+ self.typing_logic = None
+ self.text_edit = None
+ self.status_bar = None
+ self.initUI()
def initUI(self):
"""
@@ -25,8 +32,24 @@ class MainWindow(QMainWindow):
- 创建状态栏并显示"就绪"
- 连接文本变化信号到onTextChanged
"""
- # TODO: 实现UI初始化逻辑
- pass
+ # 设置窗口属性
+ self.setWindowTitle("隐私学习软件 - 仿Word")
+ self.setGeometry(100, 100, 800, 600)
+
+ # 创建中央文本编辑区域
+ self.text_edit = QTextEdit()
+ self.text_edit.setFont(QFont("Arial", 12))
+ self.setCentralWidget(self.text_edit)
+
+ # 创建菜单栏
+ self.createMenuBar()
+
+ # 创建状态栏
+ self.status_bar = self.statusBar()
+ self.status_bar.showMessage("就绪")
+
+ # 连接文本变化信号
+ self.text_edit.textChanged.connect(self.onTextChanged)
def createMenuBar(self):
"""
@@ -35,8 +58,39 @@ class MainWindow(QMainWindow):
- 帮助菜单:关于
- 为每个菜单项连接对应的槽函数
"""
- # TODO: 实现菜单栏创建逻辑
- pass
+ menu_bar = self.menuBar()
+
+ # 文件菜单
+ file_menu = menu_bar.addMenu('文件')
+
+ # 打开动作
+ open_action = QAction('打开', self)
+ open_action.setShortcut('Ctrl+O')
+ open_action.triggered.connect(self.openFile)
+ file_menu.addAction(open_action)
+
+ # 保存动作
+ save_action = QAction('保存', self)
+ save_action.setShortcut('Ctrl+S')
+ save_action.triggered.connect(self.saveFile)
+ file_menu.addAction(save_action)
+
+ # 分隔线
+ file_menu.addSeparator()
+
+ # 退出动作
+ exit_action = QAction('退出', self)
+ exit_action.setShortcut('Ctrl+Q')
+ exit_action.triggered.connect(self.close)
+ file_menu.addAction(exit_action)
+
+ # 帮助菜单
+ help_menu = menu_bar.addMenu('帮助')
+
+ # 关于动作
+ about_action = QAction('关于', self)
+ about_action.triggered.connect(self.showAbout)
+ help_menu.addAction(about_action)
def openFile(self):
"""
@@ -46,8 +100,33 @@ class MainWindow(QMainWindow):
- 成功时:将内容显示在文本区域,重置打字状态
- 失败时:显示错误消息框
"""
- # TODO: 实现打开文件逻辑
- pass
+ options = QFileDialog.Options()
+ file_path, _ = QFileDialog.getOpenFileName(
+ self,
+ "打开文件",
+ "",
+ "文本文件 (*.txt);;Word文档 (*.docx);;所有文件 (*)",
+ options=options
+ )
+
+ if file_path:
+ try:
+ # 解析文件内容
+ content = FileParser.parse_file(file_path)
+ self.learning_content = content
+
+ # 显示内容到文本编辑区域
+ self.text_edit.setPlainText(content)
+
+ # 重置打字状态
+ self.typing_logic = TypingLogic(content)
+ self.current_position = 0
+
+ # 更新状态栏
+ self.status_bar.showMessage(f"已打开文件: {file_path}")
+ except Exception as e:
+ # 显示错误消息框
+ QMessageBox.critical(self, "错误", f"无法打开文件:\n{str(e)}")
def saveFile(self):
"""
@@ -56,16 +135,49 @@ class MainWindow(QMainWindow):
- 将文本区域内容写入选定文件
- 返回操作结果
"""
- # TODO: 实现保存文件逻辑
- pass
+ options = QFileDialog.Options()
+ file_path, _ = QFileDialog.getSaveFileName(
+ self,
+ "保存文件",
+ "",
+ "文本文件 (*.txt);;所有文件 (*)",
+ options=options
+ )
+
+ if file_path:
+ try:
+ # 获取文本编辑区域的内容
+ content = self.text_edit.toPlainText()
+
+ # 写入文件
+ with open(file_path, 'w', encoding='utf-8') as f:
+ f.write(content)
+
+ # 更新状态栏
+ self.status_bar.showMessage(f"文件已保存: {file_path}")
+
+ return True
+ except Exception as e:
+ # 显示错误消息框
+ QMessageBox.critical(self, "错误", f"无法保存文件:\n{str(e)}")
+ return False
+
+ return False
def showAbout(self):
"""
显示关于对话框
- 显示消息框,包含软件名称、版本、描述
"""
- # TODO: 实现关于对话框逻辑
- pass
+ QMessageBox.about(
+ self,
+ "关于",
+ "隐私学习软件 - 仿Word\n\n"
+ "版本: 1.0\n\n"
+ "这是一个用于隐私学习的打字练习软件,\n"
+ "可以加载文档并进行打字练习,\n"
+ "帮助提高打字速度和准确性。"
+ )
def onTextChanged(self):
"""
@@ -74,8 +186,30 @@ class MainWindow(QMainWindow):
- 调用打字逻辑检查输入正确性
- 更新高亮显示和状态栏
"""
- # TODO: 实现文本变化处理逻辑
- pass
+ if self.typing_logic is None:
+ return
+
+ # 获取当前文本内容
+ current_text = self.text_edit.toPlainText()
+
+ # 调用打字逻辑检查输入正确性
+ result = self.typing_logic.check_input(current_text)
+
+ # 更新高亮显示
+ if result['correct']:
+ self.highlightText(len(current_text), QColor('lightgreen'))
+ else:
+ # 高亮显示错误部分
+ self.highlightText(len(current_text), QColor('lightcoral'))
+
+ # 更新状态栏
+ progress = self.typing_logic.get_progress()
+ accuracy = result.get('accuracy', 0) * 100
+ self.status_bar.showMessage(
+ f"进度: {progress['percentage']:.1f}% | "
+ f"准确率: {accuracy:.1f}% | "
+ f"位置: {result['position']}/{progress['total']}"
+ )
def highlightText(self, position, color):
"""
@@ -84,5 +218,24 @@ class MainWindow(QMainWindow):
- 应用背景颜色格式
- 恢复光标位置
"""
- # TODO: 实现文本高亮逻辑
- pass
\ No newline at end of file
+ # 创建文本格式
+ format = QTextCharFormat()
+ format.setBackground(color)
+
+ # 获取文本游标
+ cursor = self.text_edit.textCursor()
+
+ # 保存当前光标位置
+ current_pos = cursor.position()
+
+ # 选择从开始到指定位置的文本
+ cursor.select(QTextCursor.Document)
+ cursor.setPosition(0, QTextCursor.MoveAnchor)
+ cursor.setPosition(position, QTextCursor.KeepAnchor)
+
+ # 应用格式
+ cursor.mergeCharFormat(format)
+
+ # 恢复光标位置
+ cursor.setPosition(current_pos)
+ self.text_edit.setTextCursor(cursor)
\ No newline at end of file
diff --git a/src/typing_logic.py b/src/typing_logic.py
index 498e123..ce3e659 100644
--- a/src/typing_logic.py
+++ b/src/typing_logic.py
@@ -6,8 +6,11 @@ class TypingLogic:
- 初始化当前索引为0
- 初始化错误计数为0
"""
- # TODO: 实现构造函数逻辑
- pass
+ self.learning_content = learning_content
+ self.current_index = 0
+ self.error_count = 0
+ self.total_chars = len(learning_content)
+ self.typed_chars = 0
def check_input(self, user_text: str) -> dict:
"""
@@ -22,17 +25,54 @@ class TypingLogic:
* completed: 布尔值,是否完成
* accuracy: 浮点数,准确率
"""
- # TODO: 实现输入检查逻辑
- pass
+ # 更新已输入字符数
+ self.typed_chars = len(user_text)
+
+ # 如果用户输入的字符数超过了学习材料的长度,截取到相同长度
+ if len(user_text) > self.total_chars:
+ user_text = user_text[:self.total_chars]
+
+ # 检查当前输入是否正确
+ correct = True
+ expected_char = ''
+ if self.current_index < self.total_chars:
+ expected_char = self.learning_content[self.current_index]
+ if len(user_text) > self.current_index and user_text[self.current_index] != expected_char:
+ correct = False
+ self.error_count += 1
+ else:
+ # 已经完成所有输入
+ return {
+ "correct": True,
+ "expected": "",
+ "position": self.current_index,
+ "completed": True,
+ "accuracy": self._calculate_accuracy()
+ }
+
+ # 更新当前索引
+ self.current_index = len(user_text)
+
+ # 检查是否完成
+ completed = self.current_index >= self.total_chars
+
+ return {
+ "correct": correct,
+ "expected": expected_char,
+ "position": self.current_index,
+ "completed": completed,
+ "accuracy": self._calculate_accuracy()
+ }
- def get_expected_text(self) -> str:
+ def get_expected_text(self, length: int = 10) -> str:
"""
获取用户接下来应该输入的内容
- 返回从当前位置开始的一定长度文本(如10个字符)
- 处理文本结束情况
"""
- # TODO: 实现期望文本获取逻辑
- pass
+ start_pos = self.current_index
+ end_pos = min(start_pos + length, self.total_chars)
+ return self.learning_content[start_pos:end_pos]
def get_progress(self) -> dict:
"""
@@ -42,8 +82,17 @@ class TypingLogic:
- percentage: 浮点数,完成百分比
- remaining: 整数,剩余字符数
"""
- # TODO: 实现进度获取逻辑
- pass
+ current = self.current_index
+ total = self.total_chars
+ percentage = (current / total * 100) if total > 0 else 0
+ remaining = max(0, total - current)
+
+ return {
+ "current": current,
+ "total": total,
+ "percentage": percentage,
+ "remaining": remaining
+ }
def reset(self, new_content: str = None):
"""
@@ -52,8 +101,12 @@ class TypingLogic:
- 重置错误计数
- 如果提供了新内容,更新学习材料
"""
- # TODO: 实现重置逻辑
- pass
+ if new_content is not None:
+ self.learning_content = new_content
+ self.total_chars = len(new_content)
+ self.current_index = 0
+ self.error_count = 0
+ self.typed_chars = 0
def get_statistics(self) -> dict:
"""
@@ -63,5 +116,19 @@ class TypingLogic:
- error_count: 整数,错误次数
- accuracy_rate: 浮点数,准确率
"""
- # TODO: 实现统计信息获取逻辑
- pass
\ No newline at end of file
+ return {
+ "total_chars": self.total_chars,
+ "typed_chars": self.typed_chars,
+ "error_count": self.error_count,
+ "accuracy_rate": self._calculate_accuracy()
+ }
+
+ def _calculate_accuracy(self) -> float:
+ """
+ 计算准确率
+ """
+ if self.typed_chars == 0:
+ return 0.0
+ # 准确率 = (已输入字符数 - 错误次数) / 已输入字符数
+ accuracy = (self.typed_chars - self.error_count) / self.typed_chars
+ return max(0.0, accuracy) # 确保准确率不为负数
\ No newline at end of file
--
2.34.1