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
_ = Translate.setup_translations("custom_file_fialog")
_ = Translate.setup_translations("custom_file_dialog")
class CfdConfigManager:
@@ -104,13 +104,152 @@ class CfdConfigManager:
print(f"Error saving settings: {e}")
class Msg:
STR: Dict[str, str] = {
# Strings for messages
class LocaleStrings:
# Strings from custom_file_dialog.py
CFD = {
"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
from shared_libs.message import MessageDialog
from cfd_app_config import LocaleStrings, _
class FileOperationsManager:
@@ -25,14 +26,14 @@ class FileOperationsManager:
"use_trash", False) and SEND2TRASH_AVAILABLE
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)
if not confirm:
dialog = MessageDialog(
master=self.dialog,
title="Bestätigung erforderlich",
text=f"Möchten Sie '{item_name}' wirklich {action_text}?",
title=LocaleStrings.FILE["confirm_delete_title"],
text=f"{LocaleStrings.FILE['are_you_sure']} '{item_name}' {action_text}?",
message_type="question"
)
if not dialog.show():
@@ -49,13 +50,13 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files()
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:
MessageDialog(
master=self.dialog,
title="Fehler",
text=f"Fehler beim Entfernen von '{item_name}':\n{e}",
title=LocaleStrings.FILE["error_title"],
text=f"{LocaleStrings.FILE['error_removing']} '{item_name}':\n{e}",
message_type="error"
).show()
@@ -66,7 +67,7 @@ class FileOperationsManager:
self._create_new_item(is_folder=False)
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_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)
except Exception as e:
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):
name, ext = os.path.splitext(base_name)
@@ -93,7 +94,7 @@ class FileOperationsManager:
self.dialog.clipboard_clear()
self.dialog.clipboard_append(data)
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):
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,
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)))
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_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)
return "break"
@@ -152,7 +153,6 @@ class FileOperationsManager:
entry = ttk.Entry(item_frame)
entry.insert(0, os.path.basename(item_path))
entry.select_range(0, tk.END)
entry.pack(fill="x", expand=True, padx=5, pady=5)
entry.focus_set()
def finish_rename(event):
@@ -161,7 +161,7 @@ class FileOperationsManager:
if new_name and new_path != item_path:
if os.path.exists(new_path):
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=os.path.basename(item_path))
return
@@ -170,7 +170,7 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files(item_to_select=new_name)
except Exception as e:
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()
else:
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 os.path.exists(new_path):
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)
else:
try:
@@ -217,7 +217,7 @@ class FileOperationsManager:
self.dialog.view_manager.populate_files(item_to_select=new_name)
except Exception as e:
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()
else:
self.dialog.populate_files(item_to_select=item_text)
@@ -229,3 +229,4 @@ class FileOperationsManager:
entry.bind("<Return>", finish_rename)
entry.bind("<FocusOut>", finish_rename)
entry.bind("<Escape>", cancel_rename)

View File

@@ -1,5 +1,6 @@
import os
import tkinter as tk
from cfd_app_config import LocaleStrings, _
class NavigationManager:
def __init__(self, dialog):
@@ -17,7 +18,7 @@ class NavigationManager:
self.navigate_to(directory, file_to_select=filename)
else:
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):
try:
@@ -25,11 +26,11 @@ class NavigationManager:
os.path.abspath(os.path.expanduser(path)))
if not os.path.isdir(real_path):
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
if not os.access(real_path, os.R_OK):
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
self.dialog.current_dir = real_path
if self.dialog.history_pos < len(self.dialog.history) - 1:
@@ -45,7 +46,7 @@ class NavigationManager:
self.dialog.update_status_bar()
self.dialog.update_action_buttons_state()
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):
if self.dialog.history_pos > 0:

View File

@@ -6,6 +6,7 @@ import tkinter as tk
from tkinter import ttk
from shared_libs.message import MessageDialog
from cfd_ui_setup import get_xdg_user_dir
from cfd_app_config import LocaleStrings, _
class SearchManager:
def __init__(self, dialog):
@@ -22,7 +23,7 @@ class SearchManager:
if self.dialog.search_thread and self.dialog.search_thread.is_alive():
self.dialog.search_thread.cancelled = True
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:
self.execute_search()
@@ -50,7 +51,7 @@ class SearchManager:
if not search_term:
self.hide_search_bar()
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.update_idletasks()
self.dialog.search_thread = threading.Thread(target=self._perform_search_in_thread, args=(search_term,))
@@ -82,7 +83,7 @@ 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("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('.')]
@@ -97,7 +98,7 @@ 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("Search cancelled by user")
raise InterruptedError(LocaleStrings.UI["search_cancelled_by_user"])
if not search_hidden and name.startswith('.'):
continue
@@ -115,7 +116,7 @@ class SearchManager:
break
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()
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))
file_count = len(self.dialog.search_results) - folder_count
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:
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)
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="Suche abgebrochen."))
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"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:
self.dialog.after(0, self.dialog.widget_manager.search_animation.stop)
self.dialog.search_process = None
@@ -155,13 +156,13 @@ class SearchManager:
search_tree = ttk.Treeview(
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.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.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.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)
v_scrollbar = ttk.Scrollbar(
@@ -206,10 +207,10 @@ class SearchManager:
stat = os.stat(full_path)
size_str = self.dialog._format_size(stat.st_size)
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):
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.insert(0, filename)

View File

@@ -1,7 +1,7 @@
import tkinter as tk
from tkinter import ttk
from cfd_app_config import CfdConfigManager
from cfd_animated_icon import PIL_AVAILABLE
from cfd_app_config import CfdConfigManager, LocaleStrings, _
from animated_icon import PIL_AVAILABLE
try:
import send2trash
@@ -15,7 +15,7 @@ class SettingsDialog(tk.Toplevel):
super().__init__(parent)
self.transient(parent)
self.grab_set()
self.title("Einstellungen")
self.title(LocaleStrings.SET["title"])
self.settings = CfdConfigManager.load()
self.dialog_mode = dialog_mode
@@ -48,16 +48,16 @@ class SettingsDialog(tk.Toplevel):
# Button Box Position
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)
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)
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)
# Window Size
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)
sizes = ["1050x850", "850x650", "650x450"]
size_combo = ttk.Combobox(
@@ -66,70 +66,70 @@ class SettingsDialog(tk.Toplevel):
# Default View Mode
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)
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)
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)
# Search Hidden Files
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)
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")
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")
# Deletion Settings
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)
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)
self.use_trash_checkbutton.pack(anchor="w")
if not SEND2TRASH_AVAILABLE:
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))
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)
self.confirm_delete_checkbutton.pack(anchor="w")
# Pillow Animation
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)
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)
self.use_pillow_animation_checkbutton.pack(anchor="w")
if not PIL_AVAILABLE:
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))
# Animation Type
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)
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)
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)
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)
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)
# Disable deletion options in "open" mode
if not self.dialog_mode == "save":
self.use_trash_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"))
info_label.pack(anchor="w", padx=(20, 0))
@@ -137,11 +137,11 @@ class SettingsDialog(tk.Toplevel):
button_frame = ttk.Frame(main_frame)
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)
ttk.Button(button_frame, text="Speichern",
ttk.Button(button_frame, text=LocaleStrings.SET["save_button"],
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")
def save_settings(self):

View File

@@ -3,7 +3,8 @@ import shutil
import tkinter as tk
from tkinter import ttk
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):
@@ -129,22 +130,22 @@ class WidgetManager:
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")
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(
'forward'), command=self.dialog.navigation_manager.go_forward, state=tk.DISABLED, style="Header.TButton.Borderless.Round")
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(
'up'), command=self.dialog.navigation_manager.go_up_level, style="Header.TButton.Borderless.Round")
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(
'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))
Tooltip(self.home_button, "Home")
Tooltip(self.home_button, LocaleStrings.UI["home"])
# Path and search
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(
'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)
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(
'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)
Tooltip(self.new_file_button, "Neues Dokument erstellen")
Tooltip(self.new_file_button, LocaleStrings.UI["new_document"])
if self.dialog.dialog_mode == "open":
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(
'icon_view'), command=self.dialog.view_manager.set_icon_view, style="Header.TButton.Active.Round")
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(
'list_view'), command=self.dialog.view_manager.set_list_view, style="Header.TButton.Borderless.Round")
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(
'hide'), command=self.dialog.view_manager.toggle_hidden_files, style="Header.TButton.Borderless.Round")
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="...",
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.grid(row=0, column=0, sticky="nsew")
sidebar_buttons_config = [
{'name': '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': 'Dokumente', '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': 'Musik', '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["computer"], 'icon': self.dialog.icon_manager.get_icon('computer_small'), 'path': '/'},
{'name': LocaleStrings.NAV["downloads"], 'icon': self.dialog.icon_manager.get_icon('downloads_small'), 'path': get_xdg_user_dir("XDG_DOWNLOAD_DIR", "Downloads")},
{'name': LocaleStrings.NAV["documents"], 'icon': self.dialog.icon_manager.get_icon('documents_small'), 'path': get_xdg_user_dir("XDG_DOCUMENTS_DIR", "Documents")},
{'name': LocaleStrings.NAV["pictures"], 'icon': self.dialog.icon_manager.get_icon('pictures_small'), 'path': get_xdg_user_dir("XDG_PICTURES_DIR", "Pictures")},
{'name': LocaleStrings.NAV["music"], 'icon': self.dialog.icon_manager.get_icon('music_small'), 'path': get_xdg_user_dir("XDG_MUSIC_DIR", "Music")},
{'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 = []
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_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))
self.devices_canvas = tk.Canvas(
@@ -327,7 +328,7 @@ class WidgetManager:
def _setup_sidebar_storage(self, sidebar_frame):
storage_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame")
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_bar = ttk.Progressbar(storage_frame, orient="horizontal", length=100, mode="determinate")
self.storage_bar.pack(fill="x", pady=(2, 5), padx=15)
@@ -371,9 +372,9 @@ class WidgetManager:
if self.dialog.dialog_mode == "save":
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")
Tooltip(self.trash_button, "Ausgewähltes Element löschen/verschieben")
self.save_button = ttk.Button(self.action_status_frame, text="Speichern", command=self.dialog.on_save)
self.cancel_button = ttk.Button(self.action_status_frame, text="Abbrechen", command=self.dialog.on_cancel)
Tooltip(self.trash_button, LocaleStrings.UI["delete_move"])
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=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.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change)
self.filter_combobox.set(self.dialog.filetypes[0][0])
@@ -383,8 +384,8 @@ class WidgetManager:
self._layout_bottom_buttons(button_box_pos)
else: # Open mode
self.open_button = ttk.Button(self.action_status_frame, text="Öffnen", command=self.dialog.on_open)
self.cancel_button = ttk.Button(self.action_status_frame, text="Abbrechen", command=self.dialog.on_cancel)
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=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.bind("<<ComboboxSelected>>", self.dialog.view_manager.on_filter_change)
self.filter_combobox.set(self.dialog.filetypes[0][0])
@@ -426,9 +427,6 @@ class WidgetManager:
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.search_status_label.grid(row=0, column=0, sticky="w", pady=(5, 0), padx=(5, 0))
def setup_widgets(self):
# Main container

View File

@@ -3,7 +3,7 @@ import tkinter as tk
from tkinter import ttk
from datetime import datetime
from shared_libs.common_tools import Tooltip
from cfd_app_config import AppConfig
from cfd_app_config import AppConfig, LocaleStrings, _
class ViewManager:
def __init__(self, dialog):
@@ -29,7 +29,7 @@ class ViewManager:
num_items = len(items)
warning_message = None
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]
dirs = sorted([d for d in items if os.path.isdir(
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)
return (dirs + files, None, warning_message)
except PermissionError:
return ([], "Zugriff verweigert.", None)
return ([], LocaleStrings.CFD["access_denied"], None)
except FileNotFoundError:
return ([], "Verzeichnis nicht gefunden.", None)
return ([], LocaleStrings.CFD["directory_not_found"], None)
def _get_folder_content_count(self, folder_path):
try:
@@ -232,13 +232,13 @@ class ViewManager:
self.dialog.tree = ttk.Treeview(
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.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.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.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)
v_scrollbar = ttk.Scrollbar(
@@ -294,10 +294,10 @@ class ViewManager:
stat.st_mtime).strftime('%d.%m.%Y %H:%M')
if is_dir:
icon, file_type, size = self.dialog.icon_manager.get_icon(
'folder_small'), "Ordner", ""
'folder_small'), LocaleStrings.FILE["folder"], ""
else:
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=(
size, file_type, modified_time))
if name == item_to_rename:
@@ -446,12 +446,12 @@ class ViewManager:
self.dialog.widget_manager.hidden_files_button.config(
image=self.dialog.icon_manager.get_icon('unhide'))
Tooltip(self.dialog.widget_manager.hidden_files_button,
"Versteckte Dateien ausblenden")
LocaleStrings.UI["hide_hidden_files"])
else:
self.dialog.widget_manager.hidden_files_button.config(
image=self.dialog.icon_manager.get_icon('hide'))
Tooltip(self.dialog.widget_manager.hidden_files_button,
"Versteckte Dateien anzeigen")
LocaleStrings.UI["show_hidden_files"])
self.populate_files()
def on_filter_change(self, event):

View File

@@ -8,9 +8,9 @@ import json
import threading
from shared_libs.message import MessageDialog
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_animated_icon import AnimatedIcon, PIL_AVAILABLE
from animated_icon import AnimatedIcon, PIL_AVAILABLE
from cfd_settings_dialog import SettingsDialog
from cfd_file_operations import FileOperationsManager
from cfd_search_manager import SearchManager
@@ -18,7 +18,7 @@ from cfd_navigation_manager import NavigationManager
from cfd_view_manager import ViewManager
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)
self.my_tool_tip = None
@@ -43,7 +43,7 @@ class CustomFileDialog(tk.Toplevel):
self.selected_file = None
self.current_dir = os.path.abspath(
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.history = []
self.history_pos = -1
@@ -228,18 +228,18 @@ class CustomFileDialog(tk.Toplevel):
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
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)
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)
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')
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')
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(
'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,
@@ -296,7 +296,7 @@ class CustomFileDialog(tk.Toplevel):
total, used, free = shutil.disk_usage(self.current_dir)
free_str = self._format_size(free)
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
status_text = ""
@@ -305,19 +305,19 @@ class CustomFileDialog(tk.Toplevel):
content_count = self.view_manager._get_folder_content_count(
selected_path)
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:
status_text = f"'{os.path.basename(selected_path)}'"
else:
size = os.path.getsize(selected_path)
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)
except FileNotFoundError:
self.widget_manager.search_status_label.config(
text="Verzeichnis nicht gefunden")
text=LocaleStrings.CFD["directory_not_found"])
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
def on_open(self):
@@ -435,7 +435,7 @@ class CustomFileDialog(tk.Toplevel):
if hasattr(self, 'tooltip_window') and self.tooltip_window.winfo_exists():
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
y = self.widget_manager.search_animation.winfo_rooty() + 25

View File

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