commit 40
This commit is contained in:
Binary file not shown.
Binary file not shown.
131
cfd_ui_setup.py
131
cfd_ui_setup.py
@@ -2,60 +2,7 @@ import os
|
||||
import shutil
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import subprocess
|
||||
import json
|
||||
from shared_libs.common_tools import Tooltip, LxTools
|
||||
|
||||
|
||||
class InputDialog(tk.Toplevel):
|
||||
def __init__(self, parent, title, prompt):
|
||||
super().__init__(parent)
|
||||
self.title(title)
|
||||
self.prompt = prompt
|
||||
self.result = None
|
||||
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
|
||||
self.setup_widgets()
|
||||
LxTools.center_window_cross_platform(self, 300, 120)
|
||||
self.entry.focus_set()
|
||||
|
||||
self.bind("<Return>", self.on_ok)
|
||||
self.bind("<Escape>", self.on_cancel)
|
||||
|
||||
self.protocol("WM_DELETE_WINDOW", self.on_cancel)
|
||||
self.wait_window(self)
|
||||
|
||||
def setup_widgets(self):
|
||||
main_frame = ttk.Frame(self, padding=10)
|
||||
main_frame.pack(fill="both", expand=True)
|
||||
|
||||
ttk.Label(main_frame, text=self.prompt).pack(pady=5)
|
||||
|
||||
self.entry = ttk.Entry(main_frame, width=40)
|
||||
self.entry.pack(pady=5, padx=5)
|
||||
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
ok_button = ttk.Button(button_frame, text="OK", command=self.on_ok)
|
||||
ok_button.pack(side="left", padx=5)
|
||||
|
||||
cancel_button = ttk.Button(
|
||||
button_frame, text="Abbrechen", command=self.on_cancel)
|
||||
cancel_button.pack(side="left", padx=5)
|
||||
|
||||
def on_ok(self, event=None):
|
||||
self.result = self.entry.get()
|
||||
self.destroy()
|
||||
|
||||
def on_cancel(self, event=None):
|
||||
self.result = None
|
||||
self.destroy()
|
||||
|
||||
def get_input(self):
|
||||
return self.result
|
||||
from shared_libs.common_tools import Tooltip
|
||||
|
||||
|
||||
def get_xdg_user_dir(dir_key, fallback_name):
|
||||
@@ -178,12 +125,12 @@ class WidgetManager:
|
||||
|
||||
self.back_button = ttk.Button(nav_buttons_container, image=self.dialog.icon_manager.get_icon(
|
||||
'back'), command=self.dialog.go_back, state=tk.DISABLED, style="Header.TButton.Borderless.Round")
|
||||
self.back_button.pack(side="left", padx=10)
|
||||
self.back_button.pack(side="left", padx=20)
|
||||
Tooltip(self.back_button, "Zurück")
|
||||
|
||||
self.forward_button = ttk.Button(nav_buttons_container, image=self.dialog.icon_manager.get_icon(
|
||||
'forward'), command=self.dialog.go_forward, state=tk.DISABLED, style="Header.TButton.Borderless.Round")
|
||||
self.forward_button.pack(side="left")
|
||||
self.forward_button.pack(side="left", padx=(0, 20))
|
||||
Tooltip(self.forward_button, "Vorwärts")
|
||||
|
||||
self.home_button = ttk.Button(nav_buttons_container, image=self.dialog.icon_manager.get_icon(
|
||||
@@ -201,16 +148,6 @@ class WidgetManager:
|
||||
right_top_bar_frame = ttk.Frame(top_bar, style='Accent.TFrame')
|
||||
right_top_bar_frame.grid(row=0, column=2, sticky="e")
|
||||
|
||||
self.new_folder_button = ttk.Button(right_top_bar_frame, image=self.dialog.icon_manager.get_icon(
|
||||
'new_folder_small'), command=self.dialog.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")
|
||||
|
||||
self.new_file_button = ttk.Button(right_top_bar_frame, image=self.dialog.icon_manager.get_icon(
|
||||
'new_document_small'), command=self.dialog.create_new_file, style="Header.TButton.Borderless.Round")
|
||||
self.new_file_button.pack(side="left", padx=(0, 10))
|
||||
Tooltip(self.new_file_button, "Neues Dokument erstellen")
|
||||
|
||||
# Search button and options container
|
||||
search_container = ttk.Frame(
|
||||
right_top_bar_frame, style='Accent.TFrame')
|
||||
@@ -232,13 +169,23 @@ class WidgetManager:
|
||||
self.recursive_button.pack(side="left", padx=2)
|
||||
Tooltip(self.recursive_button, "Rekursive Suche ein/ausschalten")
|
||||
|
||||
self.new_folder_button = ttk.Button(right_top_bar_frame, image=self.dialog.icon_manager.get_icon(
|
||||
'new_folder_small'), command=self.dialog.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")
|
||||
|
||||
self.new_file_button = ttk.Button(right_top_bar_frame, image=self.dialog.icon_manager.get_icon(
|
||||
'new_document_small'), command=self.dialog.create_new_file, style="Header.TButton.Borderless.Round")
|
||||
self.new_file_button.pack(side="left", padx=(0, 10))
|
||||
Tooltip(self.new_file_button, "Neues Dokument erstellen")
|
||||
|
||||
view_switch = ttk.Frame(right_top_bar_frame,
|
||||
padding=(5, 0), style='Accent.TFrame')
|
||||
view_switch.pack(side="left")
|
||||
|
||||
self.icon_view_button = ttk.Button(view_switch, image=self.dialog.icon_manager.get_icon(
|
||||
'icon_view'), command=self.dialog.set_icon_view, style="Header.TButton.Active.Round")
|
||||
self.icon_view_button.pack(side="left", padx=(50, 10))
|
||||
self.icon_view_button.pack(side="left", padx=(5, 10))
|
||||
Tooltip(self.icon_view_button, "Kachelansicht")
|
||||
|
||||
self.list_view_button = ttk.Button(view_switch, image=self.dialog.icon_manager.get_icon(
|
||||
@@ -257,7 +204,8 @@ class WidgetManager:
|
||||
row=1, column=0, columnspan=2, sticky="ew")
|
||||
|
||||
# PanedWindow for resizable sidebar and content
|
||||
paned_window = ttk.PanedWindow(main_frame, orient=tk.HORIZONTAL)
|
||||
paned_window = ttk.PanedWindow(
|
||||
main_frame, orient=tk.HORIZONTAL, style="Sidebar.TFrame")
|
||||
paned_window.grid(row=2, column=0, columnspan=2, sticky="nsew")
|
||||
|
||||
# Sidebar
|
||||
@@ -415,42 +363,35 @@ class WidgetManager:
|
||||
# Status bar (top-left in the bottom area)
|
||||
self.status_bar = ttk.Label(
|
||||
bottom_controls_frame, text="", anchor="w", style="AccentBottom.TLabel")
|
||||
self.status_bar.grid(row=0, column=0, columnspan=2,
|
||||
self.status_bar.grid(row=0, column=1, columnspan=2,
|
||||
sticky="w", padx=10, pady=5)
|
||||
|
||||
# New folder/file buttons (top-right in the bottom area)
|
||||
right_top_buttons = ttk.Frame(
|
||||
bottom_controls_frame, style="AccentBottom.TFrame")
|
||||
right_top_buttons.grid(row=0, column=2, sticky="e")
|
||||
|
||||
self.new_folder_button = ttk.Button(right_top_buttons, image=self.dialog.icon_manager.get_icon(
|
||||
'new_folder_small'), command=self.dialog.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")
|
||||
|
||||
self.new_file_button = ttk.Button(right_top_buttons, image=self.dialog.icon_manager.get_icon(
|
||||
'new_document_small'), command=self.dialog.create_new_file, style="Header.TButton.Borderless.Round")
|
||||
self.new_file_button.pack(side="left", padx=(0, 10))
|
||||
Tooltip(self.new_file_button, "Neues Dokument erstellen")
|
||||
|
||||
# Main action buttons (bottom-left)
|
||||
left_bottom_buttons = ttk.Frame(bottom_controls_frame, style="AccentBottom.TFrame")
|
||||
left_bottom_buttons.grid(row=1, column=0, sticky="w", pady=(5, 10))
|
||||
left_bottom_buttons = ttk.Frame(
|
||||
bottom_controls_frame, style="AccentBottom.TFrame")
|
||||
left_bottom_buttons.grid(row=0, column=0, sticky="w", pady=(5, 10))
|
||||
|
||||
if self.dialog.dialog_mode == "save":
|
||||
self.filename_entry = ttk.Entry(left_bottom_buttons, width=50)
|
||||
self.filename_entry.grid(row=0, column=0, padx=(10,5), pady=5, sticky="ew")
|
||||
self.filename_entry.grid(
|
||||
row=0, column=1, padx=(5, 5), pady=5, sticky="ew")
|
||||
left_bottom_buttons.grid_columnconfigure(0, weight=1)
|
||||
|
||||
ttk.Button(left_bottom_buttons, text="Speichern", command=self.dialog.on_save).grid(row=0, column=1, padx=5)
|
||||
ttk.Button(left_bottom_buttons, text="Abbrechen", command=self.dialog.on_cancel).grid(row=0, column=2, padx=5)
|
||||
ttk.Button(left_bottom_buttons, text="Speichern",
|
||||
command=self.dialog.on_save).grid(row=0, column=0, padx=(10, 5), pady=10)
|
||||
ttk.Button(left_bottom_buttons, text="Abbrechen",
|
||||
command=self.dialog.on_cancel).grid(row=1, column=0, padx=(10, 5))
|
||||
else:
|
||||
ttk.Button(left_bottom_buttons, text="Öffnen", command=self.dialog.on_open).grid(row=0, column=0, padx=(10, 5))
|
||||
ttk.Button(left_bottom_buttons, text="Abbrechen", command=self.dialog.on_cancel).grid(row=0, column=1, padx=5)
|
||||
|
||||
ttk.Button(left_bottom_buttons, text="Öffnen", command=self.dialog.on_open).grid(
|
||||
row=0, column=0, padx=(10, 5), pady=10)
|
||||
ttk.Button(left_bottom_buttons, text="Abbrechen",
|
||||
command=self.dialog.on_cancel).grid(row=1, column=0, padx=(10, 5))
|
||||
|
||||
# Filter combobox (bottom-right)
|
||||
self.filter_combobox = ttk.Combobox(bottom_controls_frame, values=[ft[0] for ft in self.dialog.filetypes], state="readonly")
|
||||
self.filter_combobox.grid(row=1, column=2, sticky="e", padx=(0, 10), pady=(5, 10))
|
||||
self.filter_combobox.bind("<<ComboboxSelected>>", self.dialog.on_filter_change)
|
||||
self.filter_combobox = ttk.Combobox(left_bottom_buttons, values=[
|
||||
ft[0] for ft in self.dialog.filetypes], state="readonly")
|
||||
self.filter_combobox.grid(
|
||||
row=1, column=1, sticky="w", padx=(5, 10))
|
||||
self.filter_combobox.bind(
|
||||
"<<ComboboxSelected>>", self.dialog.on_filter_change)
|
||||
self.filter_combobox.set(self.dialog.filetypes[0][0])
|
||||
|
@@ -8,7 +8,7 @@ import json
|
||||
from shared_libs.message import MessageDialog
|
||||
from shared_libs.common_tools import IconManager, Tooltip, ConfigManager, LxTools, ThemeManager
|
||||
from cfd_app_config import AppConfig
|
||||
from cfd_ui_setup import StyleManager, WidgetManager, get_xdg_user_dir, InputDialog
|
||||
from cfd_ui_setup import StyleManager, WidgetManager, get_xdg_user_dir
|
||||
|
||||
|
||||
# Helper to make icon paths robust, so the script can be run from anywhere
|
||||
@@ -88,11 +88,13 @@ class CustomFileDialog(tk.Toplevel):
|
||||
if self.show_hidden_files.get():
|
||||
self.widget_manager.hidden_files_button.config(
|
||||
image=self.icon_manager.get_icon('unhide'))
|
||||
Tooltip(self.widget_manager.hidden_files_button, "Versteckte Dateien ausblenden")
|
||||
Tooltip(self.widget_manager.hidden_files_button,
|
||||
"Versteckte Dateien ausblenden")
|
||||
else:
|
||||
self.widget_manager.hidden_files_button.config(
|
||||
image=self.icon_manager.get_icon('hide'))
|
||||
Tooltip(self.widget_manager.hidden_files_button, "Versteckte Dateien anzeigen")
|
||||
Tooltip(self.widget_manager.hidden_files_button,
|
||||
"Versteckte Dateien anzeigen")
|
||||
self.populate_files()
|
||||
|
||||
def on_window_resize(self, event):
|
||||
@@ -123,7 +125,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
|
||||
def _on_devices_enter(self, event):
|
||||
"""Show scrollbar when mouse enters devices area"""
|
||||
self.widget_manager.devices_scrollbar.grid(row=1, column=1, sticky="ns")
|
||||
self.widget_manager.devices_scrollbar.grid(
|
||||
row=1, column=1, sticky="ns")
|
||||
|
||||
def _on_devices_leave(self, event):
|
||||
"""Hide scrollbar when mouse leaves devices area"""
|
||||
@@ -148,11 +151,14 @@ class CustomFileDialog(tk.Toplevel):
|
||||
self.original_path_text = self.widget_manager.path_entry.get()
|
||||
self.widget_manager.path_entry.delete(0, tk.END)
|
||||
self.widget_manager.path_entry.insert(0, "Suchbegriff eingeben...")
|
||||
self.widget_manager.path_entry.bind("<Return>", self.execute_search)
|
||||
self.widget_manager.path_entry.bind("<FocusIn>", self.clear_search_placeholder)
|
||||
self.widget_manager.path_entry.bind(
|
||||
"<Return>", self.execute_search)
|
||||
self.widget_manager.path_entry.bind(
|
||||
"<FocusIn>", self.clear_search_placeholder)
|
||||
|
||||
# Show search options
|
||||
self.widget_manager.search_options_frame.pack(side="left", padx=(5, 0))
|
||||
self.widget_manager.search_options_frame.pack(
|
||||
side="left", padx=(5, 0))
|
||||
else:
|
||||
# Exit search mode
|
||||
self.search_mode = False
|
||||
@@ -170,7 +176,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
|
||||
def toggle_recursive_search(self):
|
||||
"""Toggle recursive search on/off and update button style"""
|
||||
self.widget_manager.recursive_search.set(not self.widget_manager.recursive_search.get())
|
||||
self.widget_manager.recursive_search.set(
|
||||
not self.widget_manager.recursive_search.get())
|
||||
if self.widget_manager.recursive_search.get():
|
||||
self.widget_manager.recursive_button.configure(
|
||||
style="Header.TButton.Active.Round")
|
||||
@@ -181,7 +188,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
def set_icon_view(self):
|
||||
"""Set icon view and update button styles"""
|
||||
self.view_mode.set("icons")
|
||||
self.widget_manager.icon_view_button.configure(style="Header.TButton.Active.Round")
|
||||
self.widget_manager.icon_view_button.configure(
|
||||
style="Header.TButton.Active.Round")
|
||||
self.widget_manager.list_view_button.configure(
|
||||
style="Header.TButton.Borderless.Round")
|
||||
self.populate_files()
|
||||
@@ -189,7 +197,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
def set_list_view(self):
|
||||
"""Set list view and update button styles"""
|
||||
self.view_mode.set("list")
|
||||
self.widget_manager.list_view_button.configure(style="Header.TButton.Active.Round")
|
||||
self.widget_manager.list_view_button.configure(
|
||||
style="Header.TButton.Active.Round")
|
||||
self.widget_manager.icon_view_button.configure(
|
||||
style="Header.TButton.Borderless.Round")
|
||||
self.populate_files()
|
||||
@@ -473,7 +482,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
else:
|
||||
icon = self.icon_manager.get_icon('folder_large') if is_dir else self.get_file_icon(
|
||||
name, 'large')
|
||||
icon_label = ttk.Label(item_frame, image=icon, style="Icon.TLabel")
|
||||
icon_label = ttk.Label(
|
||||
item_frame, image=icon, style="Icon.TLabel")
|
||||
icon_label.pack(pady=(10, 5))
|
||||
name_label = ttk.Label(item_frame, text=self.shorten_text(
|
||||
name, 14), anchor="center", style="Item.TLabel")
|
||||
@@ -488,7 +498,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
widget.bind("<MouseWheel>", _on_mouse_wheel)
|
||||
widget.bind("<Button-4>", _on_mouse_wheel)
|
||||
widget.bind("<Button-5>", _on_mouse_wheel)
|
||||
widget.bind("<F2>", lambda e, p=path, f=item_frame: self.on_rename_request(e, p, f))
|
||||
widget.bind("<F2>", lambda e, p=path,
|
||||
f=item_frame: self.on_rename_request(e, p, f))
|
||||
|
||||
col = (col + 1) % col_count
|
||||
if col == 0:
|
||||
@@ -598,9 +609,10 @@ class CustomFileDialog(tk.Toplevel):
|
||||
if not self.tree.selection():
|
||||
return
|
||||
item_id = self.tree.selection()[0]
|
||||
item_path = os.path.join(self.current_dir, self.tree.item(item_id, "text").strip())
|
||||
item_path = os.path.join(
|
||||
self.current_dir, self.tree.item(item_id, "text").strip())
|
||||
self.start_rename(item_id, item_path)
|
||||
else: # icon view
|
||||
else: # icon view
|
||||
if item_path and item_frame:
|
||||
self.start_rename(item_frame, item_path)
|
||||
|
||||
@@ -693,7 +705,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
try:
|
||||
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}")
|
||||
self.widget_manager.storage_label.config(
|
||||
text=f"Freier Speicher: {free_str}")
|
||||
self.widget_manager.storage_bar['value'] = (used / total) * 100
|
||||
|
||||
status_text = ""
|
||||
@@ -703,8 +716,10 @@ class CustomFileDialog(tk.Toplevel):
|
||||
status_text = f"'{os.path.basename(self.selected_file)}' Größe: {size_str}"
|
||||
self.widget_manager.status_bar.config(text=status_text)
|
||||
except FileNotFoundError:
|
||||
self.widget_manager.status_bar.config(text="Verzeichnis nicht gefunden")
|
||||
self.widget_manager.storage_label.config(text="Freier Speicher: Unbekannt")
|
||||
self.widget_manager.status_bar.config(
|
||||
text="Verzeichnis nicht gefunden")
|
||||
self.widget_manager.storage_label.config(
|
||||
text="Freier Speicher: Unbekannt")
|
||||
self.widget_manager.storage_bar['value'] = 0
|
||||
|
||||
def on_open(self):
|
||||
@@ -744,7 +759,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
open(new_path, 'a').close()
|
||||
self.populate_files(item_to_rename=new_name)
|
||||
except Exception as e:
|
||||
self.widget_manager.status_bar.config(text=f"Fehler beim Erstellen: {e}")
|
||||
self.widget_manager.status_bar.config(
|
||||
text=f"Fehler beim Erstellen: {e}")
|
||||
|
||||
def _get_unique_name(self, base_name):
|
||||
name, ext = os.path.splitext(base_name)
|
||||
@@ -758,8 +774,8 @@ class CustomFileDialog(tk.Toplevel):
|
||||
def start_rename(self, item_widget, item_path):
|
||||
if self.view_mode.get() == "icons":
|
||||
self._start_rename_icon_view(item_widget, item_path)
|
||||
else: # list view
|
||||
self._start_rename_list_view(item_widget) # item_widget is item_id
|
||||
else: # list view
|
||||
self._start_rename_list_view(item_widget) # item_widget is item_id
|
||||
|
||||
def _start_rename_icon_view(self, item_frame, item_path):
|
||||
for child in item_frame.winfo_children():
|
||||
@@ -776,13 +792,15 @@ class CustomFileDialog(tk.Toplevel):
|
||||
new_path = os.path.join(self.current_dir, new_name)
|
||||
if new_name and new_path != item_path:
|
||||
if os.path.exists(new_path):
|
||||
self.widget_manager.status_bar.config(text=f"'{new_name}' existiert bereits.")
|
||||
self.widget_manager.status_bar.config(
|
||||
text=f"'{new_name}' existiert bereits.")
|
||||
self.populate_files()
|
||||
return
|
||||
try:
|
||||
os.rename(item_path, new_path)
|
||||
except Exception as e:
|
||||
self.widget_manager.status_bar.config(text=f"Fehler beim Umbenennen: {e}")
|
||||
self.widget_manager.status_bar.config(
|
||||
text=f"Fehler beim Umbenennen: {e}")
|
||||
self.populate_files()
|
||||
|
||||
def cancel_rename(event):
|
||||
@@ -809,12 +827,14 @@ class CustomFileDialog(tk.Toplevel):
|
||||
|
||||
if new_name and new_path != old_path:
|
||||
if os.path.exists(new_path):
|
||||
self.widget_manager.status_bar.config(text=f"'{new_name}' existiert bereits.")
|
||||
self.widget_manager.status_bar.config(
|
||||
text=f"'{new_name}' existiert bereits.")
|
||||
else:
|
||||
try:
|
||||
os.rename(old_path, new_path)
|
||||
except Exception as e:
|
||||
self.widget_manager.status_bar.config(text=f"Fehler beim Umbenennen: {e}")
|
||||
self.widget_manager.status_bar.config(
|
||||
text=f"Fehler beim Umbenennen: {e}")
|
||||
entry.destroy()
|
||||
self.populate_files()
|
||||
|
||||
@@ -842,8 +862,6 @@ class CustomFileDialog(tk.Toplevel):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def _format_size(self, size_bytes):
|
||||
if size_bytes is None:
|
||||
return ""
|
||||
|
@@ -55,7 +55,7 @@ if __name__ == "__main__":
|
||||
style = ttk.Style(root)
|
||||
root.tk.call('source', f"{theme_path}/water.tcl")
|
||||
try:
|
||||
root.tk.call('set_theme', 'light')
|
||||
root.tk.call('set_theme', 'dark')
|
||||
except tk.TclError:
|
||||
pass
|
||||
root.mainloop()
|
||||
|
Reference in New Issue
Block a user