translate strings place in cfd_app_config and replace unhide with new size

This commit is contained in:
2025-08-10 01:26:57 +02:00
parent b8d46fb547
commit b18bf7fe85
20 changed files with 267 additions and 127 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -46,7 +46,7 @@ class AppConfig:
# here is initializing the class for translation strings # here is initializing the class for translation strings
_ = Translate.setup_translations("custom_file_fialog") _ = Translate.setup_translations("custom_file_dialog")
class CfdConfigManager: class CfdConfigManager:
@@ -104,13 +104,152 @@ class CfdConfigManager:
print(f"Error saving settings: {e}") print(f"Error saving settings: {e}")
class Msg: class LocaleStrings:
# Strings from custom_file_dialog.py
STR: Dict[str, str] = { CFD = {
# Strings for messages "title": _("Custom File Dialog"),
"select_file": _("Select a file"),
"open": _("Open"),
"cancel": _("Cancel"),
"file_label": _("File:"),
"no_file_selected": _("No file selected"),
"error_title": _("Error"),
"select_file_error": _("Please select a file."),
"all_files": _("All Files"),
"free_space": _("Free Space"),
"entries": _("entries"),
"directory_not_found": _("Directory not found"),
"unknown": _("Unknown"),
"showing": _("Showing"),
"of": _("of"),
"access_denied": _("Access denied."),
"path_not_found": _("Path not found"),
"directory": _("Directory"),
"not_found": _("not found."),
"access_to": _("Access to"),
"denied": _("denied."),
} }
TTIP: Dict[str, str] = {
# Strings for Tooltips
# Strings from cfd_view_manager.py
VIEW = {
"name": _("Name"),
"date_modified": _("Date Modified"),
"type": _("Type"),
"size": _("Size"),
"view_mode": _("View Mode"),
"icon_view": _("Icon View"),
"list_view": _("List View"),
"filename": _("Filename"),
"path": _("Path"),
} }
# Strings from cfd_ui_setup.py
UI = {
"search": _("Search"),
"go": _("Go"),
"up": _("Up"),
"back": _("Back"),
"forward": _("Forward"),
"home": _("Home"),
"new_folder": _("New Folder"),
"delete": _("Delete"),
"settings": _("Settings"),
"show_hidden_files": _("Show Hidden Files"),
"places": _("Places"),
"devices": _("Devices"),
"bookmarks": _("Bookmarks"),
"new_document": _("New Document"),
"hide_hidden_files": _("Hide Hidden Files"),
"start_search": _("Start Search"),
"cancel_search": _("Cancel Search"),
"delete_move": _("Delete/Move selected item"),
"copy_filename_to_clipboard": _("Copy Filename to Clipboard"),
"copy_path_to_clipboard": _("Copy Path to Clipboard"),
"open_file_location": _("Open File Location"),
"searching_for": _("Searching for"),
"search_cancelled_by_user": _("Search cancelled by user"),
"folders_and": _("folders and"),
"files_found": _("files found."),
"no_results_for": _("No results for"),
"error_during_search": _("Error during search"),
"search_error": _("Search Error"),
}
# Strings from cfd_settings_dialog.py
SET = {
"title": _("Settings"),
"search_icon_pos_label": _("Search Icon Position"),
"left_radio": _("Left"),
"right_radio": _("Right"),
"button_box_pos_label": _("Button Box Position"),
"window_size_label": _("Window Size"),
"default_view_mode_label": _("Default View Mode"),
"icons_radio": _("Icons"),
"list_radio": _("List"),
"search_hidden_check": _("Search hidden files"),
"use_trash_check": _("Use trash for deletion"),
"confirm_delete_check": _("Confirm file deletion"),
"recursive_search_check": _("Recursive search"),
"use_pillow_check": _("Use Pillow animation"),
"save_button": _("Save"),
"cancel_button": _("Cancel"),
"search_settings": _("Search Settings"),
"deletion_settings": _("Deletion Settings"),
"recommended": _("recommended"),
"send2trash_not_found": _("send2trash library not found"),
"animation_settings": _("Animation Settings"),
"pillow": _("Pillow"),
"pillow_not_found": _("Pillow library not found"),
"animation_type": _("Animation Type"),
"counter_arc": _("Counter Arc"),
"double_arc": _("Double Arc"),
"line": _("Line"),
"blink": _("Blink"),
"deletion_options_info": _("Deletion options are only available in save mode"),
"reset_to_default": _("Reset to Default"),
}
# Strings from cfd_file_operations.py
FILE = {
"new_folder_title": _("New Folder"),
"enter_folder_name_label": _("Enter folder name:"),
"untitled_folder": _("Untitled Folder"),
"error_title": _("Error"),
"folder_exists_error": _("Folder already exists."),
"create_folder_error": _("Could not create folder."),
"confirm_delete_title": _("Confirm Deletion"),
"confirm_delete_file_message": _("Are you sure you want to permanently delete this file?"),
"confirm_delete_files_message": _("Are you sure you want to permanently delete these files?"),
"delete_button": _("Delete"),
"cancel_button": _("Cancel"),
"file_not_found_error": _("File not found."),
"trash_error": _("Could not move file to trash."),
"delete_error": _("Could not delete file."),
"folder": _("Folder"),
"file": _("File"),
"move_to_trash": _("move to trash"),
"delete_permanently": _("delete permanently"),
"are_you_sure": _("Are you sure you want to"),
"was_successfully_removed": _("was successfully removed."),
"error_removing": _("Error removing"),
"new_document_txt": _("New Document.txt"),
"error_creating": _("Error creating"),
"copied_to_clipboard": _("copied to clipboard."),
"error_renaming": _("Error renaming"),
"not_accessible": _("not accessible"),
}
# Strings from cfd_navigation_manager.py
NAV = {
"home": _("Home"),
"trash": _("Trash"),
"desktop": _("Desktop"),
"documents": _("Documents"),
"downloads": _("Downloads"),
"music": _("Music"),
"pictures": _("Pictures"),
"videos": _("Videos"),
"computer": _("Computer"),
}

View File

@@ -10,6 +10,7 @@ except ImportError:
SEND2TRASH_AVAILABLE = False SEND2TRASH_AVAILABLE = False
from shared_libs.message import MessageDialog from shared_libs.message import MessageDialog
from cfd_app_config import LocaleStrings, _
class FileOperationsManager: class FileOperationsManager:
@@ -25,14 +26,14 @@ class FileOperationsManager:
"use_trash", False) and SEND2TRASH_AVAILABLE "use_trash", False) and SEND2TRASH_AVAILABLE
confirm = self.dialog.settings.get("confirm_delete", False) confirm = self.dialog.settings.get("confirm_delete", False)
action_text = "in den Papierkorb verschieben" if use_trash else "endgültig löschen" action_text = LocaleStrings.FILE["move_to_trash"] if use_trash else LocaleStrings.FILE["delete_permanently"]
item_name = os.path.basename(self.dialog.selected_file) item_name = os.path.basename(self.dialog.selected_file)
if not confirm: if not confirm:
dialog = MessageDialog( dialog = MessageDialog(
master=self.dialog, master=self.dialog,
title="Bestätigung erforderlich", title=LocaleStrings.FILE["confirm_delete_title"],
text=f"Möchten Sie '{item_name}' wirklich {action_text}?", text=f"{LocaleStrings.FILE['are_you_sure']} '{item_name}' {action_text}?",
message_type="question" message_type="question"
) )
if not dialog.show(): if not dialog.show():
@@ -49,13 +50,13 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files() self.dialog.view_manager.populate_files()
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{item_name}' wurde erfolgreich entfernt.") text=f"'{item_name}' {LocaleStrings.FILE['was_successfully_removed']}")
except Exception as e: except Exception as e:
MessageDialog( MessageDialog(
master=self.dialog, master=self.dialog,
title="Fehler", title=LocaleStrings.FILE["error_title"],
text=f"Fehler beim Entfernen von '{item_name}':\n{e}", text=f"{LocaleStrings.FILE['error_removing']} '{item_name}':\n{e}",
message_type="error" message_type="error"
).show() ).show()
@@ -66,7 +67,7 @@ class FileOperationsManager:
self._create_new_item(is_folder=False) self._create_new_item(is_folder=False)
def _create_new_item(self, is_folder): def _create_new_item(self, is_folder):
base_name = "Neuer Ordner" if is_folder else "Neues Dokument.txt" base_name = LocaleStrings.FILE["new_folder_title"] if is_folder else LocaleStrings.FILE["new_document_txt"]
new_name = self._get_unique_name(base_name) new_name = self._get_unique_name(base_name)
new_path = os.path.join(self.dialog.current_dir, new_name) new_path = os.path.join(self.dialog.current_dir, new_name)
@@ -78,7 +79,7 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files(item_to_rename=new_name) self.dialog.view_manager.populate_files(item_to_rename=new_name)
except Exception as e: except Exception as e:
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Fehler beim Erstellen: {e}") text=f"{LocaleStrings.FILE['error_creating']}: {e}")
def _get_unique_name(self, base_name): def _get_unique_name(self, base_name):
name, ext = os.path.splitext(base_name) name, ext = os.path.splitext(base_name)
@@ -93,7 +94,7 @@ class FileOperationsManager:
self.dialog.clipboard_clear() self.dialog.clipboard_clear()
self.dialog.clipboard_append(data) self.dialog.clipboard_append(data)
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{self.dialog.shorten_text(data, 50)}' in Zwischenablage kopiert.") text=f"'{self.dialog.shorten_text(data, 50)}' {LocaleStrings.FILE['copied_to_clipboard']}")
def _show_context_menu(self, event, item_path): def _show_context_menu(self, event, item_path):
if not item_path: if not item_path:
@@ -105,14 +106,14 @@ class FileOperationsManager:
self.dialog.context_menu = tk.Menu(self.dialog, tearoff=0, background=self.dialog.style_manager.header, foreground=self.dialog.style_manager.color_foreground, self.dialog.context_menu = tk.Menu(self.dialog, tearoff=0, background=self.dialog.style_manager.header, foreground=self.dialog.style_manager.color_foreground,
activebackground=self.dialog.style_manager.selection_color, activeforeground=self.dialog.style_manager.color_foreground, relief='flat', borderwidth=0) activebackground=self.dialog.style_manager.selection_color, activeforeground=self.dialog.style_manager.color_foreground, relief='flat', borderwidth=0)
self.dialog.context_menu.add_command(label="Dateiname in Zwischenablage", self.dialog.context_menu.add_command(label=LocaleStrings.UI["copy_filename_to_clipboard"],
command=lambda: self._copy_to_clipboard(os.path.basename(item_path))) command=lambda: self._copy_to_clipboard(os.path.basename(item_path)))
self.dialog.context_menu.add_command( self.dialog.context_menu.add_command(
label="Pfad in Zwischenablage", command=lambda: self._copy_to_clipboard(item_path)) label=LocaleStrings.UI["copy_path_to_clipboard"], command=lambda: self._copy_to_clipboard(item_path))
self.dialog.context_menu.add_separator() self.dialog.context_menu.add_separator()
self.dialog.context_menu.add_command( self.dialog.context_menu.add_command(
label="Speicherort öffnen", command=lambda: self._open_file_location_from_context(item_path)) label=LocaleStrings.UI["open_file_location"], command=lambda: self._open_file_location_from_context(item_path))
self.dialog.context_menu.tk_popup(event.x_root, event.y_root) self.dialog.context_menu.tk_popup(event.x_root, event.y_root)
return "break" return "break"
@@ -152,7 +153,6 @@ class FileOperationsManager:
entry = ttk.Entry(item_frame) entry = ttk.Entry(item_frame)
entry.insert(0, os.path.basename(item_path)) entry.insert(0, os.path.basename(item_path))
entry.select_range(0, tk.END) entry.select_range(0, tk.END)
entry.pack(fill="x", expand=True, padx=5, pady=5)
entry.focus_set() entry.focus_set()
def finish_rename(event): def finish_rename(event):
@@ -161,7 +161,7 @@ class FileOperationsManager:
if new_name and new_path != item_path: if new_name and new_path != item_path:
if os.path.exists(new_path): if os.path.exists(new_path):
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{new_name}' existiert bereits.") text=f"'{new_name}' {LocaleStrings.FILE['folder_exists_error']}")
self.dialog.view_manager.populate_files( self.dialog.view_manager.populate_files(
item_to_select=os.path.basename(item_path)) item_to_select=os.path.basename(item_path))
return return
@@ -170,7 +170,7 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files(item_to_select=new_name) self.dialog.view_manager.populate_files(item_to_select=new_name)
except Exception as e: except Exception as e:
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Fehler beim Umbenennen: {e}") text=f"{LocaleStrings.FILE['error_renaming']}: {e}")
self.dialog.view_manager.populate_files() self.dialog.view_manager.populate_files()
else: else:
self.dialog.populate_files(item_to_select=os.path.basename(item_path)) self.dialog.populate_files(item_to_select=os.path.basename(item_path))
@@ -209,7 +209,7 @@ class FileOperationsManager:
if new_name and new_path != old_path: if new_name and new_path != old_path:
if os.path.exists(new_path): if os.path.exists(new_path):
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{new_name}' existiert bereits.") text=f"'{new_name}' {LocaleStrings.FILE['folder_exists_error']}")
self.dialog.view_manager.populate_files(item_to_select=item_text) self.dialog.view_manager.populate_files(item_to_select=item_text)
else: else:
try: try:
@@ -217,7 +217,7 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files(item_to_select=new_name) self.dialog.view_manager.populate_files(item_to_select=new_name)
except Exception as e: except Exception as e:
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Fehler beim Umbenennen: {e}") text=f"{LocaleStrings.FILE['error_renaming']}: {e}")
self.dialog.view_manager.populate_files() self.dialog.view_manager.populate_files()
else: else:
self.dialog.populate_files(item_to_select=item_text) self.dialog.populate_files(item_to_select=item_text)
@@ -229,3 +229,4 @@ class FileOperationsManager:
entry.bind("<Return>", finish_rename) entry.bind("<Return>", finish_rename)
entry.bind("<FocusOut>", finish_rename) entry.bind("<FocusOut>", finish_rename)
entry.bind("<Escape>", cancel_rename) entry.bind("<Escape>", cancel_rename)

View File

@@ -1,5 +1,6 @@
import os import os
import tkinter as tk import tkinter as tk
from cfd_app_config import LocaleStrings, _
class NavigationManager: class NavigationManager:
def __init__(self, dialog): def __init__(self, dialog):
@@ -17,7 +18,7 @@ class NavigationManager:
self.navigate_to(directory, file_to_select=filename) self.navigate_to(directory, file_to_select=filename)
else: else:
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Pfad nicht gefunden: {self.dialog.shorten_text(path_text, 50)}") text=f"{LocaleStrings.CFD['path_not_found']}: {self.dialog.shorten_text(path_text, 50)}")
def navigate_to(self, path, file_to_select=None): def navigate_to(self, path, file_to_select=None):
try: try:
@@ -25,11 +26,11 @@ class NavigationManager:
os.path.abspath(os.path.expanduser(path))) os.path.abspath(os.path.expanduser(path)))
if not os.path.isdir(real_path): if not os.path.isdir(real_path):
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Fehler: Verzeichnis '{os.path.basename(path)}' nicht gefunden.") text=f"{LocaleStrings.CFD['error_title']}: {LocaleStrings.CFD['directory']} '{os.path.basename(path)}' {LocaleStrings.CFD['not_found']}")
return return
if not os.access(real_path, os.R_OK): if not os.access(real_path, os.R_OK):
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Zugriff auf '{os.path.basename(path)}' verweigert.") text=f"{LocaleStrings.CFD['access_to']} '{os.path.basename(path)}' {LocaleStrings.CFD['denied']}")
return return
self.dialog.current_dir = real_path self.dialog.current_dir = real_path
if self.dialog.history_pos < len(self.dialog.history) - 1: if self.dialog.history_pos < len(self.dialog.history) - 1:
@@ -45,7 +46,7 @@ class NavigationManager:
self.dialog.update_status_bar() self.dialog.update_status_bar()
self.dialog.update_action_buttons_state() self.dialog.update_action_buttons_state()
except Exception as e: except Exception as e:
self.dialog.widget_manager.search_status_label.config(text=f"Fehler: {e}") self.dialog.widget_manager.search_status_label.config(text=f"{LocaleStrings.CFD['error_title']}: {e}")
def go_back(self): def go_back(self):
if self.dialog.history_pos > 0: if self.dialog.history_pos > 0:

View File

@@ -6,6 +6,7 @@ import tkinter as tk
from tkinter import ttk from tkinter import ttk
from shared_libs.message import MessageDialog from shared_libs.message import MessageDialog
from cfd_ui_setup import get_xdg_user_dir from cfd_ui_setup import get_xdg_user_dir
from cfd_app_config import LocaleStrings, _
class SearchManager: class SearchManager:
def __init__(self, dialog): def __init__(self, dialog):
@@ -22,7 +23,7 @@ class SearchManager:
if self.dialog.search_thread and self.dialog.search_thread.is_alive(): 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_animation.stop()
self.dialog.widget_manager.search_status_label.config(text="Suche abgebrochen.") self.dialog.widget_manager.search_status_label.config(text=LocaleStrings.UI["cancel_search"])
else: else:
self.execute_search() self.execute_search()
@@ -50,7 +51,7 @@ class SearchManager:
if not search_term: if not search_term:
self.hide_search_bar() self.hide_search_bar()
return return
self.dialog.widget_manager.search_status_label.config(text=f"Suche nach '{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.widget_manager.search_animation.start(pulse=False)
self.dialog.update_idletasks() 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,))
@@ -82,7 +83,7 @@ class SearchManager:
if is_recursive: if is_recursive:
for root, dirs, files in os.walk(search_dir, followlinks=follow_links): 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()): if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError("Search cancelled by user") raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
if not search_hidden: if not search_hidden:
dirs[:] = [d for d in dirs if not d.startswith('.')] dirs[:] = [d for d in dirs if not d.startswith('.')]
@@ -97,7 +98,7 @@ class SearchManager:
else: else:
for name in os.listdir(search_dir): for name in os.listdir(search_dir):
if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()): if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError("Search cancelled by user") raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
if not search_hidden and name.startswith('.'): if not search_hidden and name.startswith('.'):
continue continue
@@ -115,7 +116,7 @@ class SearchManager:
break break
if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()): if not (self.dialog.search_thread and self.dialog.search_thread.is_alive()):
raise InterruptedError("Search cancelled by user") raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
seen = set() 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))]
@@ -126,18 +127,18 @@ class SearchManager:
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 file_count = len(self.dialog.search_results) - folder_count
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"{folder_count} Ordner und {file_count} Dateien gefunden.") text=f"{folder_count} {LocaleStrings.UI['folders_and']} {file_count} {LocaleStrings.UI['files_found']}")
else: else:
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"Keine Ergebnisse für '{search_term}'.") text=f"{LocaleStrings.UI['no_results_for']} '{search_term}'.")
self.dialog.after(0, update_ui) self.dialog.after(0, update_ui)
except (Exception, InterruptedError) as e: except (Exception, InterruptedError) as e:
if isinstance(e, (InterruptedError, subprocess.SubprocessError)): if isinstance(e, (InterruptedError, subprocess.SubprocessError)):
self.dialog.after(0, lambda: self.dialog.widget_manager.search_status_label.config(text="Suche abgebrochen.")) self.dialog.after(0, lambda: self.dialog.widget_manager.search_status_label.config(text=LocaleStrings.UI["cancel_search"]))
else: else:
self.dialog.after(0, lambda: MessageDialog( self.dialog.after(0, lambda: MessageDialog(
message_type="error", text=f"Fehler bei der Suche: {e}", title="Suchfehler", master=self.dialog).show()) message_type="error", text=f"{LocaleStrings.UI['error_during_search']}: {e}", title=LocaleStrings.UI["search_error"], master=self.dialog).show())
finally: 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 self.dialog.search_process = None
@@ -155,13 +156,13 @@ class SearchManager:
search_tree = ttk.Treeview( search_tree = ttk.Treeview(
tree_frame, columns=columns, show="tree headings") tree_frame, columns=columns, show="tree headings")
search_tree.heading("#0", text="Dateiname", anchor="w") search_tree.heading("#0", text=LocaleStrings.VIEW["filename"], anchor="w")
search_tree.column("#0", anchor="w", width=200, stretch=True) search_tree.column("#0", anchor="w", width=200, stretch=True)
search_tree.heading("path", text="Pfad", anchor="w") search_tree.heading("path", text=LocaleStrings.VIEW["path"], anchor="w")
search_tree.column("path", anchor="w", width=300, stretch=True) search_tree.column("path", anchor="w", width=300, stretch=True)
search_tree.heading("size", text="Größe", anchor="e") search_tree.heading("size", text=LocaleStrings.VIEW["size"], anchor="e")
search_tree.column("size", anchor="e", width=100, stretch=False) search_tree.column("size", anchor="e", width=100, stretch=False)
search_tree.heading("modified", text="Geändert am", anchor="w") search_tree.heading("modified", text=LocaleStrings.VIEW["date_modified"], anchor="w")
search_tree.column("modified", anchor="w", width=160, stretch=False) search_tree.column("modified", anchor="w", width=160, stretch=False)
v_scrollbar = ttk.Scrollbar( v_scrollbar = ttk.Scrollbar(
@@ -206,10 +207,10 @@ class SearchManager:
stat = os.stat(full_path) stat = os.stat(full_path)
size_str = self.dialog._format_size(stat.st_size) size_str = self.dialog._format_size(stat.st_size)
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{filename}' Größe: {size_str}") text=f"'{filename}' {LocaleStrings.VIEW['size']}: {size_str}")
except (FileNotFoundError, PermissionError): except (FileNotFoundError, PermissionError):
self.dialog.widget_manager.search_status_label.config( self.dialog.widget_manager.search_status_label.config(
text=f"'{filename}' nicht zugänglich") text=f"'{filename}' {LocaleStrings.FILE['not_accessible']}")
self.dialog.widget_manager.filename_entry.delete(0, tk.END) self.dialog.widget_manager.filename_entry.delete(0, tk.END)
self.dialog.widget_manager.filename_entry.insert(0, filename) self.dialog.widget_manager.filename_entry.insert(0, filename)

View File

@@ -1,7 +1,7 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from cfd_app_config import CfdConfigManager from cfd_app_config import CfdConfigManager, LocaleStrings, _
from cfd_animated_icon import PIL_AVAILABLE from animated_icon import PIL_AVAILABLE
try: try:
import send2trash import send2trash
@@ -15,7 +15,7 @@ class SettingsDialog(tk.Toplevel):
super().__init__(parent) super().__init__(parent)
self.transient(parent) self.transient(parent)
self.grab_set() self.grab_set()
self.title("Einstellungen") self.title(LocaleStrings.SET["title"])
self.settings = CfdConfigManager.load() self.settings = CfdConfigManager.load()
self.dialog_mode = dialog_mode self.dialog_mode = dialog_mode
@@ -48,16 +48,16 @@ class SettingsDialog(tk.Toplevel):
# Button Box Position # Button Box Position
button_box_frame = ttk.LabelFrame( button_box_frame = ttk.LabelFrame(
main_frame, text="Position der Dialog-Buttons", padding=10) main_frame, text=LocaleStrings.SET["button_box_pos_label"], padding=10)
button_box_frame.pack(fill="x", pady=5) button_box_frame.pack(fill="x", pady=5)
ttk.Radiobutton(button_box_frame, text="Links", ttk.Radiobutton(button_box_frame, text=LocaleStrings.SET["left_radio"],
variable=self.button_box_pos, value="left").pack(side="left", padx=5) variable=self.button_box_pos, value="left").pack(side="left", padx=5)
ttk.Radiobutton(button_box_frame, text="Rechts", ttk.Radiobutton(button_box_frame, text=LocaleStrings.SET["right_radio"],
variable=self.button_box_pos, value="right").pack(side="left", padx=5) variable=self.button_box_pos, value="right").pack(side="left", padx=5)
# Window Size # Window Size
size_frame = ttk.LabelFrame( size_frame = ttk.LabelFrame(
main_frame, text="Fenstergröße", padding=10) main_frame, text=LocaleStrings.SET["window_size_label"], padding=10)
size_frame.pack(fill="x", pady=5) size_frame.pack(fill="x", pady=5)
sizes = ["1050x850", "850x650", "650x450"] sizes = ["1050x850", "850x650", "650x450"]
size_combo = ttk.Combobox( size_combo = ttk.Combobox(
@@ -66,70 +66,70 @@ class SettingsDialog(tk.Toplevel):
# Default View Mode # Default View Mode
view_mode_frame = ttk.LabelFrame( view_mode_frame = ttk.LabelFrame(
main_frame, text="Standardansicht", padding=10) main_frame, text=LocaleStrings.SET["default_view_mode_label"], padding=10)
view_mode_frame.pack(fill="x", pady=5) view_mode_frame.pack(fill="x", pady=5)
ttk.Radiobutton(view_mode_frame, text="Kacheln", ttk.Radiobutton(view_mode_frame, text=LocaleStrings.SET["icons_radio"],
variable=self.default_view_mode, value="icons").pack(side="left", padx=5) variable=self.default_view_mode, value="icons").pack(side="left", padx=5)
ttk.Radiobutton(view_mode_frame, text="Liste", ttk.Radiobutton(view_mode_frame, text=LocaleStrings.SET["list_radio"],
variable=self.default_view_mode, value="list").pack(side="left", padx=5) variable=self.default_view_mode, value="list").pack(side="left", padx=5)
# Search Hidden Files # Search Hidden Files
search_hidden_frame = ttk.LabelFrame( search_hidden_frame = ttk.LabelFrame(
main_frame, text="Sucheinstellungen", padding=10) main_frame, text=LocaleStrings.SET["search_settings"], padding=10)
search_hidden_frame.pack(fill="x", pady=5) search_hidden_frame.pack(fill="x", pady=5)
ttk.Checkbutton(search_hidden_frame, text="Versteckte Dateien und Ordner durchsuchen", ttk.Checkbutton(search_hidden_frame, text=LocaleStrings.SET["search_hidden_check"],
variable=self.search_hidden_files).pack(anchor="w") variable=self.search_hidden_files).pack(anchor="w")
ttk.Checkbutton(search_hidden_frame, text="Rekursiv suchen", ttk.Checkbutton(search_hidden_frame, text=LocaleStrings.SET["recursive_search_check"],
variable=self.recursive_search).pack(anchor="w") variable=self.recursive_search).pack(anchor="w")
# Deletion Settings # Deletion Settings
delete_frame = ttk.LabelFrame( delete_frame = ttk.LabelFrame(
main_frame, text="Löscheinstellungen", padding=10) main_frame, text=LocaleStrings.SET["deletion_settings"], padding=10)
delete_frame.pack(fill="x", pady=5) delete_frame.pack(fill="x", pady=5)
self.use_trash_checkbutton = ttk.Checkbutton(delete_frame, text="Dateien in den Papierkorb verschieben (empfohlen)", self.use_trash_checkbutton = ttk.Checkbutton(delete_frame, text=f"{LocaleStrings.SET['use_trash_check']} ({LocaleStrings.SET['recommended']})",
variable=self.use_trash) variable=self.use_trash)
self.use_trash_checkbutton.pack(anchor="w") self.use_trash_checkbutton.pack(anchor="w")
if not SEND2TRASH_AVAILABLE: if not SEND2TRASH_AVAILABLE:
self.use_trash_checkbutton.config(state=tk.DISABLED) self.use_trash_checkbutton.config(state=tk.DISABLED)
ttk.Label(delete_frame, text="(send2trash-Bibliothek nicht gefunden)", ttk.Label(delete_frame, text=f"({LocaleStrings.SET['send2trash_not_found']})",
font=("TkDefaultFont", 9, "italic")).pack(anchor="w", padx=(20, 0)) font=("TkDefaultFont", 9, "italic")).pack(anchor="w", padx=(20, 0))
self.confirm_delete_checkbutton = ttk.Checkbutton(delete_frame, text="Löschen/Verschieben ohne Bestätigung", self.confirm_delete_checkbutton = ttk.Checkbutton(delete_frame, text=LocaleStrings.SET["confirm_delete_check"],
variable=self.confirm_delete) variable=self.confirm_delete)
self.confirm_delete_checkbutton.pack(anchor="w") self.confirm_delete_checkbutton.pack(anchor="w")
# Pillow Animation # Pillow Animation
pillow_frame = ttk.LabelFrame( pillow_frame = ttk.LabelFrame(
main_frame, text="Animationseinstellungen", padding=10) main_frame, text=LocaleStrings.SET["animation_settings"], padding=10)
pillow_frame.pack(fill="x", pady=5) pillow_frame.pack(fill="x", pady=5)
self.use_pillow_animation_checkbutton = ttk.Checkbutton(pillow_frame, text="Hochauflösende Animation verwenden (Pillow)", self.use_pillow_animation_checkbutton = ttk.Checkbutton(pillow_frame, text=f"{LocaleStrings.SET['use_pillow_check']} ({LocaleStrings.SET['pillow']})",
variable=self.use_pillow_animation) variable=self.use_pillow_animation)
self.use_pillow_animation_checkbutton.pack(anchor="w") self.use_pillow_animation_checkbutton.pack(anchor="w")
if not PIL_AVAILABLE: if not PIL_AVAILABLE:
self.use_pillow_animation_checkbutton.config(state=tk.DISABLED) self.use_pillow_animation_checkbutton.config(state=tk.DISABLED)
ttk.Label(pillow_frame, text="(Pillow-Bibliothek nicht gefunden)", ttk.Label(pillow_frame, text=f"({LocaleStrings.SET['pillow_not_found']})",
font=("TkDefaultFont", 9, "italic")).pack(anchor="w", padx=(20, 0)) font=("TkDefaultFont", 9, "italic")).pack(anchor="w", padx=(20, 0))
# Animation Type # Animation Type
anim_type_frame = ttk.LabelFrame( anim_type_frame = ttk.LabelFrame(
main_frame, text="Animationstyp", padding=10) main_frame, text=LocaleStrings.SET["animation_type"], padding=10)
anim_type_frame.pack(fill="x", pady=5) anim_type_frame.pack(fill="x", pady=5)
ttk.Radiobutton(anim_type_frame, text="Gegenläufige Bogen", variable=self.animation_type, ttk.Radiobutton(anim_type_frame, text=LocaleStrings.SET["counter_arc"], variable=self.animation_type,
value="counter_arc").pack(side="left", padx=5) value="counter_arc").pack(side="left", padx=5)
ttk.Radiobutton(anim_type_frame, text="Doppelbogen", variable=self.animation_type, ttk.Radiobutton(anim_type_frame, text=LocaleStrings.SET["double_arc"], variable=self.animation_type,
value="double_arc").pack(side="left", padx=5) value="double_arc").pack(side="left", padx=5)
ttk.Radiobutton(anim_type_frame, text="Linie", variable=self.animation_type, ttk.Radiobutton(anim_type_frame, text=LocaleStrings.SET["line"], variable=self.animation_type,
value="line").pack(side="left", padx=5) value="line").pack(side="left", padx=5)
ttk.Radiobutton(anim_type_frame, text="Blinken", variable=self.animation_type, ttk.Radiobutton(anim_type_frame, text=LocaleStrings.SET["blink"], variable=self.animation_type,
value="blink").pack(side="left", padx=5) value="blink").pack(side="left", padx=5)
# Disable deletion options in "open" mode # Disable deletion options in "open" mode
if not self.dialog_mode == "save": if not self.dialog_mode == "save":
self.use_trash_checkbutton.config(state=tk.DISABLED) self.use_trash_checkbutton.config(state=tk.DISABLED)
self.confirm_delete_checkbutton.config(state=tk.DISABLED) self.confirm_delete_checkbutton.config(state=tk.DISABLED)
info_label = ttk.Label(delete_frame, text="(Löschoptionen sind nur im Speichern-Modus verfügbar)", info_label = ttk.Label(delete_frame, text=f"({LocaleStrings.SET['deletion_options_info']})",
font=("TkDefaultFont", 9, "italic")) font=("TkDefaultFont", 9, "italic"))
info_label.pack(anchor="w", padx=(20, 0)) info_label.pack(anchor="w", padx=(20, 0))
@@ -137,11 +137,11 @@ class SettingsDialog(tk.Toplevel):
button_frame = ttk.Frame(main_frame) button_frame = ttk.Frame(main_frame)
button_frame.pack(fill="x", pady=(10, 0)) button_frame.pack(fill="x", pady=(10, 0))
ttk.Button(button_frame, text="Auf Standard zurücksetzen", ttk.Button(button_frame, text=LocaleStrings.SET["reset_to_default"],
command=self.reset_to_defaults).pack(side="left", padx=5) command=self.reset_to_defaults).pack(side="left", padx=5)
ttk.Button(button_frame, text="Speichern", ttk.Button(button_frame, text=LocaleStrings.SET["save_button"],
command=self.save_settings).pack(side="right", padx=5) command=self.save_settings).pack(side="right", padx=5)
ttk.Button(button_frame, text="Abbrechen", ttk.Button(button_frame, text=LocaleStrings.SET["cancel_button"],
command=self.destroy).pack(side="right") command=self.destroy).pack(side="right")
def save_settings(self): def save_settings(self):

View File

@@ -3,7 +3,8 @@ import shutil
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from shared_libs.common_tools import Tooltip from shared_libs.common_tools import Tooltip
from cfd_animated_icon import AnimatedIcon from animated_icon import AnimatedIcon
from cfd_app_config import LocaleStrings, _
def get_xdg_user_dir(dir_key, fallback_name): def get_xdg_user_dir(dir_key, fallback_name):
@@ -129,22 +130,22 @@ class WidgetManager:
self.back_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon( self.back_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon(
'back'), command=self.dialog.navigation_manager.go_back, state=tk.DISABLED, style="Header.TButton.Borderless.Round") 'back'), command=self.dialog.navigation_manager.go_back, state=tk.DISABLED, style="Header.TButton.Borderless.Round")
self.back_button.pack(side="left", padx=(10, 5)) self.back_button.pack(side="left", padx=(10, 5))
Tooltip(self.back_button, "Zurück") Tooltip(self.back_button, LocaleStrings.UI["back"])
self.forward_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon( self.forward_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon(
'forward'), command=self.dialog.navigation_manager.go_forward, state=tk.DISABLED, style="Header.TButton.Borderless.Round") 'forward'), command=self.dialog.navigation_manager.go_forward, state=tk.DISABLED, style="Header.TButton.Borderless.Round")
self.forward_button.pack(side="left", padx=5) self.forward_button.pack(side="left", padx=5)
Tooltip(self.forward_button, "Vorwärts") Tooltip(self.forward_button, LocaleStrings.UI["forward"])
self.up_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon( self.up_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon(
'up'), command=self.dialog.navigation_manager.go_up_level, style="Header.TButton.Borderless.Round") 'up'), command=self.dialog.navigation_manager.go_up_level, style="Header.TButton.Borderless.Round")
self.up_button.pack(side="left", padx=5) self.up_button.pack(side="left", padx=5)
Tooltip(self.up_button, "Eine Ebene höher") Tooltip(self.up_button, LocaleStrings.UI["up"])
self.home_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon( self.home_button = ttk.Button(left_nav_container, image=self.dialog.icon_manager.get_icon(
'home'), command=lambda: self.dialog.navigation_manager.navigate_to(os.path.expanduser("~")), style="Header.TButton.Borderless.Round") 'home'), command=lambda: self.dialog.navigation_manager.navigate_to(os.path.expanduser("~")), style="Header.TButton.Borderless.Round")
self.home_button.pack(side="left", padx=(5, 10)) self.home_button.pack(side="left", padx=(5, 10))
Tooltip(self.home_button, "Home") Tooltip(self.home_button, LocaleStrings.UI["home"])
# Path and search # Path and search
path_search_container = ttk.Frame(top_bar, style='Accent.TFrame') path_search_container = ttk.Frame(top_bar, style='Accent.TFrame')
@@ -169,12 +170,12 @@ class WidgetManager:
self.new_folder_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon( self.new_folder_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon(
'new_folder_small'), command=self.dialog.file_op_manager.create_new_folder, style="Header.TButton.Borderless.Round") 'new_folder_small'), command=self.dialog.file_op_manager.create_new_folder, style="Header.TButton.Borderless.Round")
self.new_folder_button.pack(side="left", padx=5) self.new_folder_button.pack(side="left", padx=5)
Tooltip(self.new_folder_button, "Neuen Ordner erstellen") Tooltip(self.new_folder_button, LocaleStrings.UI["new_folder"])
self.new_file_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon( self.new_file_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon(
'new_document_small'), command=self.dialog.file_op_manager.create_new_file, style="Header.TButton.Borderless.Round") 'new_document_small'), command=self.dialog.file_op_manager.create_new_file, style="Header.TButton.Borderless.Round")
self.new_file_button.pack(side="left", padx=5) self.new_file_button.pack(side="left", padx=5)
Tooltip(self.new_file_button, "Neues Dokument erstellen") Tooltip(self.new_file_button, LocaleStrings.UI["new_document"])
if self.dialog.dialog_mode == "open": if self.dialog.dialog_mode == "open":
self.new_folder_button.config(state=tk.DISABLED) self.new_folder_button.config(state=tk.DISABLED)
@@ -185,17 +186,17 @@ class WidgetManager:
self.icon_view_button = ttk.Button(self.view_switch, image=self.dialog.icon_manager.get_icon( self.icon_view_button = ttk.Button(self.view_switch, image=self.dialog.icon_manager.get_icon(
'icon_view'), command=self.dialog.view_manager.set_icon_view, style="Header.TButton.Active.Round") 'icon_view'), command=self.dialog.view_manager.set_icon_view, style="Header.TButton.Active.Round")
self.icon_view_button.pack(side="left", padx=5) self.icon_view_button.pack(side="left", padx=5)
Tooltip(self.icon_view_button, "Kachelansicht") Tooltip(self.icon_view_button, LocaleStrings.VIEW["icon_view"])
self.list_view_button = ttk.Button(self.view_switch, image=self.dialog.icon_manager.get_icon( self.list_view_button = ttk.Button(self.view_switch, image=self.dialog.icon_manager.get_icon(
'list_view'), command=self.dialog.view_manager.set_list_view, style="Header.TButton.Borderless.Round") 'list_view'), command=self.dialog.view_manager.set_list_view, style="Header.TButton.Borderless.Round")
self.list_view_button.pack(side="left") self.list_view_button.pack(side="left")
Tooltip(self.list_view_button, "Listenansicht") Tooltip(self.list_view_button, LocaleStrings.VIEW["list_view"])
self.hidden_files_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon( self.hidden_files_button = ttk.Button(self.responsive_buttons_container, image=self.dialog.icon_manager.get_icon(
'hide'), command=self.dialog.view_manager.toggle_hidden_files, style="Header.TButton.Borderless.Round") 'hide'), command=self.dialog.view_manager.toggle_hidden_files, style="Header.TButton.Borderless.Round")
self.hidden_files_button.pack(side="left", padx=10) self.hidden_files_button.pack(side="left", padx=10)
Tooltip(self.hidden_files_button, "Versteckte Dateien anzeigen") Tooltip(self.hidden_files_button, LocaleStrings.UI["show_hidden_files"])
self.more_button = ttk.Button(right_controls_container, text="...", self.more_button = ttk.Button(right_controls_container, text="...",
command=self.dialog.show_more_menu, style="Header.TButton.Borderless.Round", width=3) command=self.dialog.show_more_menu, style="Header.TButton.Borderless.Round", width=3)
@@ -222,12 +223,12 @@ class WidgetManager:
sidebar_buttons_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame", padding=(0, 15, 0, 0)) sidebar_buttons_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame", padding=(0, 15, 0, 0))
sidebar_buttons_frame.grid(row=0, column=0, sticky="nsew") sidebar_buttons_frame.grid(row=0, column=0, sticky="nsew")
sidebar_buttons_config = [ sidebar_buttons_config = [
{'name': 'Computer', 'icon': self.dialog.icon_manager.get_icon('computer_small'), 'path': '/'}, {'name': LocaleStrings.NAV["computer"], 'icon': self.dialog.icon_manager.get_icon('computer_small'), 'path': '/'},
{'name': 'Downloads', 'icon': self.dialog.icon_manager.get_icon('downloads_small'), 'path': get_xdg_user_dir("XDG_DOWNLOAD_DIR", "Downloads")}, {'name': LocaleStrings.NAV["downloads"], 'icon': self.dialog.icon_manager.get_icon('downloads_small'), 'path': get_xdg_user_dir("XDG_DOWNLOAD_DIR", "Downloads")},
{'name': 'Dokumente', 'icon': self.dialog.icon_manager.get_icon('documents_small'), 'path': get_xdg_user_dir("XDG_DOCUMENTS_DIR", "Documents")}, {'name': LocaleStrings.NAV["documents"], 'icon': self.dialog.icon_manager.get_icon('documents_small'), 'path': get_xdg_user_dir("XDG_DOCUMENTS_DIR", "Documents")},
{'name': 'Bilder', 'icon': self.dialog.icon_manager.get_icon('pictures_small'), 'path': get_xdg_user_dir("XDG_PICTURES_DIR", "Pictures")}, {'name': LocaleStrings.NAV["pictures"], 'icon': self.dialog.icon_manager.get_icon('pictures_small'), 'path': get_xdg_user_dir("XDG_PICTURES_DIR", "Pictures")},
{'name': 'Musik', 'icon': self.dialog.icon_manager.get_icon('music_small'), 'path': get_xdg_user_dir("XDG_MUSIC_DIR", "Music")}, {'name': LocaleStrings.NAV["music"], 'icon': self.dialog.icon_manager.get_icon('music_small'), 'path': get_xdg_user_dir("XDG_MUSIC_DIR", "Music")},
{'name': 'Videos', 'icon': self.dialog.icon_manager.get_icon('video_small'), 'path': get_xdg_user_dir("XDG_VIDEO_DIR", "Videos")}, {'name': LocaleStrings.NAV["videos"], 'icon': self.dialog.icon_manager.get_icon('video_small'), 'path': get_xdg_user_dir("XDG_VIDEO_DIR", "Videos")},
] ]
self.sidebar_buttons = [] self.sidebar_buttons = []
for config in sidebar_buttons_config: for config in sidebar_buttons_config:
@@ -241,7 +242,7 @@ class WidgetManager:
mounted_devices_frame.grid(row=2, column=0, sticky="nsew", padx=10) mounted_devices_frame.grid(row=2, column=0, sticky="nsew", padx=10)
mounted_devices_frame.grid_columnconfigure(0, weight=1) mounted_devices_frame.grid_columnconfigure(0, weight=1)
ttk.Label(mounted_devices_frame, text="Geräte:", background=self.style_manager.sidebar_color, ttk.Label(mounted_devices_frame, text=LocaleStrings.UI["devices"], background=self.style_manager.sidebar_color,
foreground=self.style_manager.color_foreground).grid(row=0, column=0, sticky="ew", padx=10, pady=(5, 0)) foreground=self.style_manager.color_foreground).grid(row=0, column=0, sticky="ew", padx=10, pady=(5, 0))
self.devices_canvas = tk.Canvas( self.devices_canvas = tk.Canvas(
@@ -327,7 +328,7 @@ class WidgetManager:
def _setup_sidebar_storage(self, sidebar_frame): def _setup_sidebar_storage(self, sidebar_frame):
storage_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame") storage_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame")
storage_frame.grid(row=5, column=0, sticky="sew", padx=10, pady=10) storage_frame.grid(row=5, column=0, sticky="sew", padx=10, pady=10)
self.storage_label = ttk.Label(storage_frame, text="Freier Speicher:", background=self.style_manager.freespace_background) self.storage_label = ttk.Label(storage_frame, text=f"{LocaleStrings.CFD["free_space"]}:", background=self.style_manager.freespace_background)
self.storage_label.pack(fill="x", padx=10) self.storage_label.pack(fill="x", padx=10)
self.storage_bar = ttk.Progressbar(storage_frame, orient="horizontal", length=100, mode="determinate") self.storage_bar = ttk.Progressbar(storage_frame, orient="horizontal", length=100, mode="determinate")
self.storage_bar.pack(fill="x", pady=(2, 5), padx=15) self.storage_bar.pack(fill="x", pady=(2, 5), padx=15)
@@ -371,9 +372,9 @@ class WidgetManager:
if self.dialog.dialog_mode == "save": if self.dialog.dialog_mode == "save":
self.trash_button = ttk.Button(self.action_status_frame, image=self.dialog.icon_manager.get_icon('trash_small2'), self.trash_button = ttk.Button(self.action_status_frame, image=self.dialog.icon_manager.get_icon('trash_small2'),
command=self.dialog.file_op_manager.delete_selected_item, style="Bottom.TButton.Borderless.Round") command=self.dialog.file_op_manager.delete_selected_item, style="Bottom.TButton.Borderless.Round")
Tooltip(self.trash_button, "Ausgewähltes Element löschen/verschieben") Tooltip(self.trash_button, LocaleStrings.UI["delete_move"])
self.save_button = ttk.Button(self.action_status_frame, text="Speichern", command=self.dialog.on_save) self.save_button = ttk.Button(self.action_status_frame, text=LocaleStrings.SET["save_button"], command=self.dialog.on_save)
self.cancel_button = ttk.Button(self.action_status_frame, text="Abbrechen", command=self.dialog.on_cancel) self.cancel_button = ttk.Button(self.action_status_frame, text=LocaleStrings.SET["cancel_button"], command=self.dialog.on_cancel)
self.filter_combobox = ttk.Combobox(self.center_container, values=[ft[0] for ft in self.dialog.filetypes], state="readonly") self.filter_combobox = ttk.Combobox(self.center_container, values=[ft[0] for ft in self.dialog.filetypes], state="readonly")
self.filter_combobox.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change) self.filter_combobox.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change)
self.filter_combobox.set(self.dialog.filetypes[0][0]) self.filter_combobox.set(self.dialog.filetypes[0][0])
@@ -383,8 +384,8 @@ class WidgetManager:
self._layout_bottom_buttons(button_box_pos) self._layout_bottom_buttons(button_box_pos)
else: # Open mode else: # Open mode
self.open_button = ttk.Button(self.action_status_frame, text="Öffnen", command=self.dialog.on_open) self.open_button = ttk.Button(self.action_status_frame, text=LocaleStrings.CFD["open"], command=self.dialog.on_open)
self.cancel_button = ttk.Button(self.action_status_frame, text="Abbrechen", command=self.dialog.on_cancel) self.cancel_button = ttk.Button(self.action_status_frame, text=LocaleStrings.CFD["cancel"], command=self.dialog.on_cancel)
self.filter_combobox = ttk.Combobox(self.center_container, values=[ft[0] for ft in self.dialog.filetypes], state="readonly") self.filter_combobox = ttk.Combobox(self.center_container, values=[ft[0] for ft in self.dialog.filetypes], state="readonly")
self.filter_combobox.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change) self.filter_combobox.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change)
self.filter_combobox.set(self.dialog.filetypes[0][0]) self.filter_combobox.set(self.dialog.filetypes[0][0])
@@ -426,9 +427,6 @@ class WidgetManager:
self.center_container.grid_columnconfigure(1, weight=1) self.center_container.grid_columnconfigure(1, weight=1)
self.filter_combobox.grid(in_=self.center_container, row=1, column=1, sticky="e", pady=(5, 0)) self.filter_combobox.grid(in_=self.center_container, row=1, column=1, sticky="e", pady=(5, 0))
#self.search_status_label.grid(row=0, column=0, sticky="w", pady=(5, 0), padx=(5, 0))
def setup_widgets(self): def setup_widgets(self):
# Main container # Main container

View File

@@ -3,7 +3,7 @@ import tkinter as tk
from tkinter import ttk from tkinter import ttk
from datetime import datetime from datetime import datetime
from shared_libs.common_tools import Tooltip from shared_libs.common_tools import Tooltip
from cfd_app_config import AppConfig from cfd_app_config import AppConfig, LocaleStrings, _
class ViewManager: class ViewManager:
def __init__(self, dialog): def __init__(self, dialog):
@@ -29,7 +29,7 @@ class ViewManager:
num_items = len(items) num_items = len(items)
warning_message = None warning_message = None
if num_items > AppConfig.MAX_ITEMS_TO_DISPLAY: if num_items > AppConfig.MAX_ITEMS_TO_DISPLAY:
warning_message = f"Zeige {AppConfig.MAX_ITEMS_TO_DISPLAY} von {num_items} Einträgen." warning_message = f"{LocaleStrings.CFD['showing']} {AppConfig.MAX_ITEMS_TO_DISPLAY} {LocaleStrings.CFD['of']} {num_items} {LocaleStrings.CFD['entries']}."
items = items[:AppConfig.MAX_ITEMS_TO_DISPLAY] items = items[:AppConfig.MAX_ITEMS_TO_DISPLAY]
dirs = sorted([d for d in items if os.path.isdir( dirs = sorted([d for d in items if os.path.isdir(
os.path.join(self.dialog.current_dir, d))], key=str.lower) os.path.join(self.dialog.current_dir, d))], key=str.lower)
@@ -37,9 +37,9 @@ class ViewManager:
os.path.join(self.dialog.current_dir, f))], key=str.lower) os.path.join(self.dialog.current_dir, f))], key=str.lower)
return (dirs + files, None, warning_message) return (dirs + files, None, warning_message)
except PermissionError: except PermissionError:
return ([], "Zugriff verweigert.", None) return ([], LocaleStrings.CFD["access_denied"], None)
except FileNotFoundError: except FileNotFoundError:
return ([], "Verzeichnis nicht gefunden.", None) return ([], LocaleStrings.CFD["directory_not_found"], None)
def _get_folder_content_count(self, folder_path): def _get_folder_content_count(self, folder_path):
try: try:
@@ -232,13 +232,13 @@ class ViewManager:
self.dialog.tree = ttk.Treeview( self.dialog.tree = ttk.Treeview(
tree_frame, columns=columns, show="tree headings") tree_frame, columns=columns, show="tree headings")
self.dialog.tree.heading("#0", text="Name", anchor="w") self.dialog.tree.heading("#0", text=LocaleStrings.VIEW["name"], anchor="w")
self.dialog.tree.column("#0", anchor="w", width=250, stretch=True) self.dialog.tree.column("#0", anchor="w", width=250, stretch=True)
self.dialog.tree.heading("size", text="Größe", anchor="e") self.dialog.tree.heading("size", text=LocaleStrings.VIEW["size"], anchor="e")
self.dialog.tree.column("size", anchor="e", width=120, stretch=False) self.dialog.tree.column("size", anchor="e", width=120, stretch=False)
self.dialog.tree.heading("type", text="Typ", anchor="w") self.dialog.tree.heading("type", text=LocaleStrings.VIEW["type"], anchor="w")
self.dialog.tree.column("type", anchor="w", width=120, stretch=False) self.dialog.tree.column("type", anchor="w", width=120, stretch=False)
self.dialog.tree.heading("modified", text="Geändert am", anchor="w") self.dialog.tree.heading("modified", text=LocaleStrings.VIEW["date_modified"], anchor="w")
self.dialog.tree.column("modified", anchor="w", width=160, stretch=False) self.dialog.tree.column("modified", anchor="w", width=160, stretch=False)
v_scrollbar = ttk.Scrollbar( v_scrollbar = ttk.Scrollbar(
@@ -294,10 +294,10 @@ class ViewManager:
stat.st_mtime).strftime('%d.%m.%Y %H:%M') stat.st_mtime).strftime('%d.%m.%Y %H:%M')
if is_dir: if is_dir:
icon, file_type, size = self.dialog.icon_manager.get_icon( icon, file_type, size = self.dialog.icon_manager.get_icon(
'folder_small'), "Ordner", "" 'folder_small'), LocaleStrings.FILE["folder"], ""
else: else:
icon, file_type, size = self.dialog.get_file_icon( icon, file_type, size = self.dialog.get_file_icon(
name, 'small'), "Datei", self.dialog._format_size(stat.st_size) name, 'small'), LocaleStrings.FILE["file"], self.dialog._format_size(stat.st_size)
item_id = self.dialog.tree.insert("", "end", text=f" {name}", image=icon, values=( item_id = self.dialog.tree.insert("", "end", text=f" {name}", image=icon, values=(
size, file_type, modified_time)) size, file_type, modified_time))
if name == item_to_rename: if name == item_to_rename:
@@ -446,12 +446,12 @@ class ViewManager:
self.dialog.widget_manager.hidden_files_button.config( self.dialog.widget_manager.hidden_files_button.config(
image=self.dialog.icon_manager.get_icon('unhide')) image=self.dialog.icon_manager.get_icon('unhide'))
Tooltip(self.dialog.widget_manager.hidden_files_button, Tooltip(self.dialog.widget_manager.hidden_files_button,
"Versteckte Dateien ausblenden") LocaleStrings.UI["hide_hidden_files"])
else: else:
self.dialog.widget_manager.hidden_files_button.config( self.dialog.widget_manager.hidden_files_button.config(
image=self.dialog.icon_manager.get_icon('hide')) image=self.dialog.icon_manager.get_icon('hide'))
Tooltip(self.dialog.widget_manager.hidden_files_button, Tooltip(self.dialog.widget_manager.hidden_files_button,
"Versteckte Dateien anzeigen") LocaleStrings.UI["show_hidden_files"])
self.populate_files() self.populate_files()
def on_filter_change(self, event): def on_filter_change(self, event):

View File

@@ -8,9 +8,9 @@ import json
import threading import threading
from shared_libs.message import MessageDialog from shared_libs.message import MessageDialog
from shared_libs.common_tools import IconManager, Tooltip, ConfigManager, LxTools from shared_libs.common_tools import IconManager, Tooltip, ConfigManager, LxTools
from cfd_app_config import AppConfig, CfdConfigManager from cfd_app_config import AppConfig, CfdConfigManager, LocaleStrings, _
from cfd_ui_setup import StyleManager, WidgetManager, get_xdg_user_dir from cfd_ui_setup import StyleManager, WidgetManager, get_xdg_user_dir
from cfd_animated_icon import AnimatedIcon, PIL_AVAILABLE from animated_icon import AnimatedIcon, PIL_AVAILABLE
from cfd_settings_dialog import SettingsDialog from cfd_settings_dialog import SettingsDialog
from cfd_file_operations import FileOperationsManager from cfd_file_operations import FileOperationsManager
from cfd_search_manager import SearchManager from cfd_search_manager import SearchManager
@@ -18,7 +18,7 @@ from cfd_navigation_manager import NavigationManager
from cfd_view_manager import ViewManager from cfd_view_manager import ViewManager
class CustomFileDialog(tk.Toplevel): class CustomFileDialog(tk.Toplevel):
def __init__(self, parent, initial_dir=None, filetypes=None, dialog_mode="open", title="File Dialog"): def __init__(self, parent, initial_dir=None, filetypes=None, dialog_mode="open", title=LocaleStrings.CFD["title"]):
super().__init__(parent) super().__init__(parent)
self.my_tool_tip = None self.my_tool_tip = None
@@ -43,7 +43,7 @@ class CustomFileDialog(tk.Toplevel):
self.selected_file = None self.selected_file = None
self.current_dir = os.path.abspath( self.current_dir = os.path.abspath(
initial_dir) if initial_dir else os.path.expanduser("~") initial_dir) if initial_dir else os.path.expanduser("~")
self.filetypes = filetypes if filetypes else [("Alle Dateien", "*.* ")] self.filetypes = filetypes if filetypes else [(LocaleStrings.CFD["all_files"], "*.* ")]
self.current_filter_pattern = self.filetypes[0][1] self.current_filter_pattern = self.filetypes[0][1]
self.history = [] self.history = []
self.history_pos = -1 self.history_pos = -1
@@ -228,18 +228,18 @@ class CustomFileDialog(tk.Toplevel):
is_writable = os.access(self.current_dir, os.W_OK) is_writable = os.access(self.current_dir, os.W_OK)
creation_state = tk.NORMAL if is_writable and self.dialog_mode != "open" else tk.DISABLED creation_state = tk.NORMAL if is_writable and self.dialog_mode != "open" else tk.DISABLED
more_menu.add_command(label="Neuer Ordner", command=self.file_op_manager.create_new_folder, more_menu.add_command(label=LocaleStrings.UI["new_folder"], command=self.file_op_manager.create_new_folder,
image=self.icon_manager.get_icon('new_folder_small'), compound='left', state=creation_state) image=self.icon_manager.get_icon('new_folder_small'), compound='left', state=creation_state)
more_menu.add_command(label="Neues Dokument", command=self.file_op_manager.create_new_file, more_menu.add_command(label=LocaleStrings.UI["new_document"], command=self.file_op_manager.create_new_file,
image=self.icon_manager.get_icon('new_document_small'), compound='left', state=creation_state) image=self.icon_manager.get_icon('new_document_small'), compound='left', state=creation_state)
more_menu.add_separator() more_menu.add_separator()
more_menu.add_command(label="Kachelansicht", command=self.view_manager.set_icon_view, more_menu.add_command(label=LocaleStrings.VIEW["icon_view"], command=self.view_manager.set_icon_view,
image=self.icon_manager.get_icon('icon_view'), compound='left') image=self.icon_manager.get_icon('icon_view'), compound='left')
more_menu.add_command(label="Listenansicht", command=self.view_manager.set_list_view, more_menu.add_command(label=LocaleStrings.VIEW["list_view"], command=self.view_manager.set_list_view,
image=self.icon_manager.get_icon('list_view'), compound='left') image=self.icon_manager.get_icon('list_view'), compound='left')
more_menu.add_separator() more_menu.add_separator()
hidden_files_label = "Versteckte Dateien ausblenden" if self.show_hidden_files.get() else "Versteckte Dateien anzeigen" hidden_files_label = LocaleStrings.UI["hide_hidden_files"] if self.show_hidden_files.get() else LocaleStrings.UI["show_hidden_files"]
hidden_files_icon = self.icon_manager.get_icon( hidden_files_icon = self.icon_manager.get_icon(
'unhide') if self.show_hidden_files.get() else self.icon_manager.get_icon('hide') 'unhide') if self.show_hidden_files.get() else self.icon_manager.get_icon('hide')
more_menu.add_command(label=hidden_files_label, command=self.view_manager.toggle_hidden_files, more_menu.add_command(label=hidden_files_label, command=self.view_manager.toggle_hidden_files,
@@ -296,7 +296,7 @@ class CustomFileDialog(tk.Toplevel):
total, used, free = shutil.disk_usage(self.current_dir) total, used, free = shutil.disk_usage(self.current_dir)
free_str = self._format_size(free) free_str = self._format_size(free)
self.widget_manager.storage_label.config( self.widget_manager.storage_label.config(
text=f"Freier Speicher: {free_str}") text=f"{LocaleStrings.CFD["free_space"]}: {free_str}")
self.widget_manager.storage_bar['value'] = (used / total) * 100 self.widget_manager.storage_bar['value'] = (used / total) * 100
status_text = "" status_text = ""
@@ -305,19 +305,19 @@ class CustomFileDialog(tk.Toplevel):
content_count = self.view_manager._get_folder_content_count( content_count = self.view_manager._get_folder_content_count(
selected_path) selected_path)
if content_count is not None: if content_count is not None:
status_text = f"'{os.path.basename(selected_path)}' ({content_count} Einträge)" status_text = f"'{os.path.basename(selected_path)}' ({content_count} {LocaleStrings.CFD["entries"]})"
else: else:
status_text = f"'{os.path.basename(selected_path)}'" status_text = f"'{os.path.basename(selected_path)}'"
else: else:
size = os.path.getsize(selected_path) size = os.path.getsize(selected_path)
size_str = self._format_size(size) size_str = self._format_size(size)
status_text = f"'{os.path.basename(selected_path)}' Größe: {size_str}" status_text = f"'{os.path.basename(selected_path)}' {LocaleStrings.VIEW["size"]}: {size_str}"
self.widget_manager.search_status_label.config(text=status_text) self.widget_manager.search_status_label.config(text=status_text)
except FileNotFoundError: except FileNotFoundError:
self.widget_manager.search_status_label.config( self.widget_manager.search_status_label.config(
text="Verzeichnis nicht gefunden") text=LocaleStrings.CFD["directory_not_found"])
self.widget_manager.storage_label.config( self.widget_manager.storage_label.config(
text="Freier Speicher: Unbekannt") text=f"{LocaleStrings.CFD["free_space"]}: {LocaleStrings.CFD["unknown"]}")
self.widget_manager.storage_bar['value'] = 0 self.widget_manager.storage_bar['value'] = 0
def on_open(self): def on_open(self):
@@ -435,7 +435,7 @@ class CustomFileDialog(tk.Toplevel):
if hasattr(self, 'tooltip_window') and self.tooltip_window.winfo_exists(): if hasattr(self, 'tooltip_window') and self.tooltip_window.winfo_exists():
return return
tooltip_text = "Suche starten" if not self.widget_manager.search_animation.running else "Suche abbrechen" tooltip_text = LocaleStrings.UI["start_search"] if not self.widget_manager.search_animation.running else LocaleStrings.UI["cancel_search"]
x = self.widget_manager.search_animation.winfo_rootx() + 25 x = self.widget_manager.search_animation.winfo_rootx() + 25
y = self.widget_manager.search_animation.winfo_rooty() + 25 y = self.widget_manager.search_animation.winfo_rooty() + 25

View File

@@ -34,7 +34,7 @@ class GlotzMol(tk.Tk):
initial_dir=os.path.expanduser("~"), initial_dir=os.path.expanduser("~"),
filetypes=[("All Files", "*.*"), filetypes=[("All Files", "*.*"),
("Wireguard config Files", "*.conf") ("Wireguard config Files", "*.conf")
]) ], dialog_mode="save")
# This is the crucial part: wait for the dialog to be closed # This is the crucial part: wait for the dialog to be closed
self.wait_window(dialog) self.wait_window(dialog)