Reduced redundancy, logviewer fulll removed , add log_window and menu_bar

This commit is contained in:
2025-08-12 22:44:49 +02:00
parent 80aebe3bab
commit dc51bf6f2c
32 changed files with 1431 additions and 1617 deletions

View File

@@ -7,8 +7,8 @@ from tkinter import ttk
from typing import Optional, TYPE_CHECKING
from shared_libs.message import MessageDialog
from cfd_ui_setup import get_xdg_user_dir
from cfd_app_config import LocaleStrings, _
from .cfd_ui_setup import get_xdg_user_dir
from .cfd_app_config import LocaleStrings
if TYPE_CHECKING:
from custom_file_dialog import CustomFileDialog
@@ -39,9 +39,10 @@ class SearchManager:
"""
if self.dialog.widget_manager.search_animation.running:
if self.dialog.search_thread and self.dialog.search_thread.is_alive():
self.dialog.search_thread.cancelled = True
self.dialog.search_thread.cancelled = True
self.dialog.widget_manager.search_animation.stop()
self.dialog.widget_manager.search_status_label.config(text=LocaleStrings.UI["cancel_search"])
self.dialog.widget_manager.search_status_label.config(
text=LocaleStrings.UI["cancel_search"])
else:
self.execute_search()
@@ -83,10 +84,12 @@ class SearchManager:
if not search_term:
self.hide_search_bar()
return
self.dialog.widget_manager.search_status_label.config(text=f"{LocaleStrings.UI['searching_for']} '{search_term}'...")
self.dialog.widget_manager.search_status_label.config(
text=f"{LocaleStrings.UI['searching_for']} '{search_term}'...")
self.dialog.widget_manager.search_animation.start(pulse=False)
self.dialog.update_idletasks()
self.dialog.search_thread = threading.Thread(target=self._perform_search_in_thread, args=(search_term,))
self.dialog.search_thread = threading.Thread(
target=self._perform_search_in_thread, args=(search_term,))
self.dialog.search_thread.start()
def _perform_search_in_thread(self, search_term: str) -> None:
@@ -104,13 +107,16 @@ class SearchManager:
search_dirs = [self.dialog.current_dir]
home_dir = os.path.expanduser("~")
if os.path.abspath(self.dialog.current_dir) == os.path.abspath(home_dir):
xdg_dirs = [get_xdg_user_dir(d, f) for d, f in [("XDG_DOWNLOAD_DIR", "Downloads"), ("XDG_DOCUMENTS_DIR", "Documents"), ("XDG_PICTURES_DIR", "Pictures"), ("XDG_MUSIC_DIR", "Music"), ("XDG_VIDEO_DIR", "Videos")]]
search_dirs.extend([d for d in xdg_dirs if os.path.exists(d) and os.path.abspath(d) != home_dir and d not in search_dirs])
xdg_dirs = [get_xdg_user_dir(d, f) for d, f in [("XDG_DOWNLOAD_DIR", "Downloads"), ("XDG_DOCUMENTS_DIR", "Documents"), (
"XDG_PICTURES_DIR", "Pictures"), ("XDG_MUSIC_DIR", "Music"), ("XDG_VIDEO_DIR", "Videos")]]
search_dirs.extend([d for d in xdg_dirs if os.path.exists(
d) and os.path.abspath(d) != home_dir and d not in search_dirs])
try:
all_files = []
is_recursive = self.dialog.settings.get("recursive_search", True)
search_hidden = self.dialog.settings.get("search_hidden_files", False)
search_hidden = self.dialog.settings.get(
"search_hidden_files", False)
search_term_lower = search_term.lower()
for search_dir in search_dirs:
@@ -125,10 +131,12 @@ class SearchManager:
if is_recursive:
for root, dirs, files in os.walk(search_dir, followlinks=follow_links):
if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
raise InterruptedError(
LocaleStrings.UI["search_cancelled_by_user"])
if not search_hidden:
dirs[:] = [d for d in dirs if not d.startswith('.')]
dirs[:] = [
d for d in dirs if not d.startswith('.')]
files = [f for f in files if not f.startswith('.')]
for name in files:
@@ -140,11 +148,12 @@ class SearchManager:
else:
for name in os.listdir(search_dir):
if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
raise InterruptedError(
LocaleStrings.UI["search_cancelled_by_user"])
if not search_hidden and name.startswith('.'):
continue
path = os.path.join(search_dir, name)
is_dir = os.path.isdir(path)
@@ -158,15 +167,18 @@ class SearchManager:
break
if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
raise InterruptedError(
LocaleStrings.UI["search_cancelled_by_user"])
seen = set()
self.dialog.search_results = [x for x in all_files if not (x in seen or seen.add(x))]
self.dialog.search_results = [
x for x in all_files if not (x in seen or seen.add(x))]
def update_ui() -> None:
if self.dialog.search_results:
self.show_search_results_treeview()
folder_count = sum(1 for p in self.dialog.search_results if os.path.isdir(p))
folder_count = sum(
1 for p in self.dialog.search_results if os.path.isdir(p))
file_count = len(self.dialog.search_results) - folder_count
self.dialog.widget_manager.search_status_label.config(
text=f"{folder_count} {LocaleStrings.UI['folders_and']} {file_count} {LocaleStrings.UI['files_found']}")
@@ -177,12 +189,14 @@ class SearchManager:
except (Exception, InterruptedError) as e:
if isinstance(e, (InterruptedError, subprocess.SubprocessError)):
self.dialog.after(0, lambda: self.dialog.widget_manager.search_status_label.config(text=LocaleStrings.UI["cancel_search"]))
self.dialog.after(0, lambda: self.dialog.widget_manager.search_status_label.config(
text=LocaleStrings.UI["cancel_search"]))
else:
self.dialog.after(0, lambda: MessageDialog(
message_type="error", text=f"{LocaleStrings.UI['error_during_search']}: {e}", title=LocaleStrings.UI["search_error"], master=self.dialog).show())
finally:
self.dialog.after(0, self.dialog.widget_manager.search_animation.stop)
self.dialog.after(
0, self.dialog.widget_manager.search_animation.stop)
self.dialog.search_process = None
def show_search_results_treeview(self) -> None:
@@ -199,13 +213,17 @@ class SearchManager:
search_tree = ttk.Treeview(
tree_frame, columns=columns, show="tree headings")
search_tree.heading("#0", text=LocaleStrings.VIEW["filename"], anchor="w")
search_tree.heading(
"#0", text=LocaleStrings.VIEW["filename"], anchor="w")
search_tree.column("#0", anchor="w", width=200, stretch=True)
search_tree.heading("path", text=LocaleStrings.VIEW["path"], anchor="w")
search_tree.heading(
"path", text=LocaleStrings.VIEW["path"], anchor="w")
search_tree.column("path", anchor="w", width=300, stretch=True)
search_tree.heading("size", text=LocaleStrings.VIEW["size"], anchor="e")
search_tree.heading(
"size", text=LocaleStrings.VIEW["size"], anchor="e")
search_tree.column("size", anchor="e", width=100, stretch=False)
search_tree.heading("modified", text=LocaleStrings.VIEW["date_modified"], anchor="w")
search_tree.heading(
"modified", text=LocaleStrings.VIEW["date_modified"], anchor="w")
search_tree.column("modified", anchor="w", width=160, stretch=False)
v_scrollbar = ttk.Scrollbar(
@@ -266,9 +284,10 @@ class SearchManager:
item = search_tree.item(selection[0])
filename = item['text'].strip()
directory = item['values'][0]
self.hide_search_bar()
self.dialog.navigation_manager.navigate_to(directory, file_to_select=filename)
self.dialog.navigation_manager.navigate_to(
directory, file_to_select=filename)
search_tree.bind("<Double-1>", on_search_double_click)
@@ -304,4 +323,5 @@ class SearchManager:
self.hide_search_bar()
self.dialog.navigation_manager.navigate_to(directory)
self.dialog.after(100, lambda: self.dialog.view_manager._select_file_in_view(filename))
self.dialog.after(
100, lambda: self.dialog.view_manager._select_file_in_view(filename))