Skip to content

Commit 26bd5b7

Browse files
DiamondBothgmzhn
authored andcommitted
fix: 修复编辑器视图文件夹树显示问题,添加空文件夹自动删除功能
- 编辑器视图文件夹结构与主页视图保持一致 - 文件夹内文件全部删除后自动移除空文件夹 - 使用自然排序显示文件夹
1 parent f08612f commit 26bd5b7

3 files changed

Lines changed: 508 additions & 162 deletions

File tree

desktop_qt_ui/editor/editor_logic.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class EditorLogic(QObject):
1414
Handles the business logic for the editor view, including file list management.
1515
"""
1616
file_list_changed = pyqtSignal(list)
17+
file_list_with_tree_changed = pyqtSignal(list, dict) # (files, folder_map)
1718

1819
def __init__(self, controller, parent=None):
1920
super().__init__(parent)
@@ -77,16 +78,27 @@ def add_folder(self, folder_path: str):
7778
if not folder_path or not os.path.isdir(folder_path):
7879
return
7980

80-
image_extensions = {'.png', '.jpg', '.jpeg', '.bmp', '.webp'}
81-
try:
82-
files_in_folder = [
83-
os.path.join(folder_path, f)
84-
for f in os.listdir(folder_path)
85-
if os.path.splitext(f)[1].lower() in image_extensions
86-
]
87-
self.add_files(files_in_folder)
88-
except OSError as e:
89-
print(f"Error reading folder {folder_path}: {e}")
81+
# 检查是否是第一次添加文件(列表为空)
82+
is_first_add = len(self.source_files) == 0
83+
84+
# 添加文件夹路径到source_files,让FileListView创建树形结构
85+
if folder_path not in self.source_files:
86+
self.source_files.append(folder_path)
87+
self.file_list_changed.emit(self.source_files)
88+
89+
# 如果是第一次添加,自动加载第一个图片
90+
if is_first_add:
91+
# 获取文件夹中的第一个图片
92+
image_extensions = {'.png', '.jpg', '.jpeg', '.bmp', '.webp'}
93+
try:
94+
for root, dirs, files in os.walk(folder_path):
95+
for f in sorted(files):
96+
if os.path.splitext(f)[1].lower() in image_extensions:
97+
first_image = os.path.join(root, f)
98+
self.load_image_into_editor(first_image)
99+
return
100+
except OSError as e:
101+
print(f"Error reading folder {folder_path}: {e}")
90102

91103
@pyqtSlot(list)
92104
def add_files_from_paths(self, paths: List[str]):
@@ -192,41 +204,32 @@ def clear_list(self):
192204
def load_file_lists(self, source_files: List[str], translated_files: List[str], folder_map: dict = None):
193205
"""
194206
Receives the file lists from the coordinator to populate the editor.
195-
folder_map: 文件到文件夹的映射,用于支持文件夹分组显示
207+
folder_map: 文件到文件夹的映射,用于支持文件夹分组显示(key是源文件路径)
196208
"""
209+
print(f"[DEBUG editor_logic] load_file_lists called")
210+
print(f"[DEBUG editor_logic] source_files: {source_files}")
211+
print(f"[DEBUG editor_logic] translated_files: {translated_files}")
212+
print(f"[DEBUG editor_logic] folder_map: {folder_map}")
213+
197214
self.source_files = source_files
198215
self.translated_files = translated_files
199216
self.translation_map_cache.clear() # Clear cache when lists change
200217

201-
# 如果提供了folder_map,将文件按文件夹分组
202-
files_to_show = self.translated_files if self.translated_files else self.source_files
218+
# 选择要显示的文件列表
219+
# 如果有翻译后的文件,显示源文件列表(但实际加载翻译后的文件)
220+
# 这样文件夹结构和主页视图保持一致
221+
files_to_show = self.source_files
222+
223+
print(f"[DEBUG editor_logic] files_to_show: {files_to_show}")
224+
print(f"[DEBUG editor_logic] Has folder_map: {bool(folder_map)}")
203225

226+
# 如果有folder_map,使用树形结构显示
204227
if folder_map:
205-
# 按文件夹分组
206-
folder_groups = {}
207-
single_files = []
208-
209-
for file_path in files_to_show:
210-
folder = folder_map.get(file_path)
211-
if folder:
212-
if folder not in folder_groups:
213-
folder_groups[folder] = []
214-
folder_groups[folder].append(file_path)
215-
else:
216-
single_files.append(file_path)
217-
218-
# 构建文件列表:按文件夹分组,但只添加文件,不添加文件夹路径
219-
# 这样可以保持文件夹分组的顺序,但不会让FileListView重新展开文件夹
220-
grouped_list = []
221-
for folder, files in sorted(folder_groups.items()):
222-
# 只添加文件,不添加文件夹路径
223-
# 文件会按文件夹分组显示,但不会重新展开文件夹
224-
grouped_list.extend(files)
225-
grouped_list.extend(single_files) # 添加单独的文件
226-
227-
self.file_list_changed.emit(grouped_list)
228+
print(f"[DEBUG editor_logic] Emitting file_list_with_tree_changed signal")
229+
self.file_list_with_tree_changed.emit(files_to_show, folder_map)
228230
else:
229-
# 发射翻译后的文件列表,而不是源文件列表
231+
# 否则使用平铺列表
232+
print(f"[DEBUG editor_logic] Emitting file_list_changed signal")
230233
self.file_list_changed.emit(files_to_show)
231234

232235
@pyqtSlot(str)

desktop_qt_ui/main_window.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,45 @@ def enter_editor_mode(self, file_to_load: str = None, files_to_load: list = None
406406
# 使用app_logic的_resolve_input_files来获取正确的文件列表
407407
# 这样可以正确处理文件夹展开和文件移除
408408
expanded_files = self.app_logic._resolve_input_files()
409-
folder_map = self.app_logic.file_to_folder_map.copy()
409+
410+
# 构建 folder_map,映射到用户添加的顶层文件夹
411+
# 同时收集所有中间文件夹,以便构建完整的树结构
412+
folder_map = {}
413+
all_intermediate_folders = set() # 存储所有中间文件夹
414+
415+
for file_path in expanded_files:
416+
# 查找文件所属的顶层文件夹(用户添加的文件夹)
417+
top_folder = None
418+
for source_path in self.app_logic.source_files:
419+
if os.path.isdir(source_path):
420+
# 检查文件是否在这个文件夹下
421+
norm_source = os.path.normpath(source_path)
422+
norm_file = os.path.normpath(file_path)
423+
if norm_file.startswith(norm_source + os.sep):
424+
top_folder = norm_source
425+
426+
# 收集从顶层文件夹到文件之间的所有中间文件夹
427+
current_path = os.path.dirname(norm_file)
428+
while current_path != norm_source and current_path:
429+
all_intermediate_folders.add(current_path)
430+
current_path = os.path.dirname(current_path)
431+
all_intermediate_folders.add(norm_source)
432+
break
433+
434+
# 如果找到顶层文件夹,映射到它;否则映射到直接父文件夹
435+
if top_folder:
436+
folder_map[file_path] = top_folder
437+
else:
438+
# 单独添加的文件,映射到其父文件夹
439+
parent_dir = os.path.dirname(file_path)
440+
folder_map[file_path] = parent_dir
441+
all_intermediate_folders.add(parent_dir)
442+
443+
# DEBUG: 打印 folder_map 和中间文件夹
444+
self.logger.debug(f"[DEBUG main_window] folder_map content:")
445+
for file_path, folder in folder_map.items():
446+
self.logger.debug(f" {file_path} -> {folder}")
447+
self.logger.debug(f"[DEBUG main_window] all_intermediate_folders: {all_intermediate_folders}")
410448

411449
self.logger.info(f"Entering editor mode: {len(expanded_files)} files from source_files")
412450
self.logger.debug(f"Source files: {self.app_logic.source_files}")
@@ -429,22 +467,23 @@ def enter_editor_mode(self, file_to_load: str = None, files_to_load: list = None
429467

430468
if os.path.exists(translated_file):
431469
translated_files.append(translated_file)
432-
translated_folder_map[translated_file] = final_output_folder # 记录翻译后文件所属文件夹
470+
# 映射到翻译后文件的直接父文件夹(输出目录中的文件夹)
471+
translated_folder_map[translated_file] = final_output_folder
433472
else:
434473
# 单独添加的文件
435474
output_folder = self.app_logic.config_service.get_config().app.last_output_path
436475
translated_file = os.path.join(output_folder, os.path.basename(source_file))
437476

438477
if os.path.exists(translated_file):
439478
translated_files.append(translated_file)
440-
translated_folder_map[translated_file] = None
479+
translated_folder_map[translated_file] = output_folder
441480

442-
# 传递文件列表和文件夹映射
443-
# folder_map只包含实际存在的文件,不会导致重新展开
481+
# 始终使用源文件的 folder_map,这样编辑器视图和主页视图显示相同的文件夹结构
482+
# 编辑器视图显示的是源文件列表,所以应该使用源文件的文件夹映射
444483
self.editor_logic.load_file_lists(
445484
source_files=expanded_files,
446485
translated_files=translated_files,
447-
folder_map=translated_folder_map if translated_files else folder_map
486+
folder_map=folder_map
448487
)
449488

450489
# 如果指定了要加载的文件,加载第一个翻译后的文件

0 commit comments

Comments
 (0)