From 11f8d0e2fd661556d2d048713e1393b052291d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9sir=C3=A9=20Werner=20Menrath?= Date: Sun, 27 Jul 2025 21:02:22 +0200 Subject: [PATCH] commit 11 --- .../custom_file_dialog.cpython-312.pyc | Bin 43545 -> 48240 bytes custom_file_dialog.py | 177 +++++++++++++----- mainwindow.py | 4 +- 3 files changed, 131 insertions(+), 50 deletions(-) diff --git a/__pycache__/custom_file_dialog.cpython-312.pyc b/__pycache__/custom_file_dialog.cpython-312.pyc index bfe6bd65f6b132818fff7f42c555a8107d79b62e..e8312d5ce7a9a414cfd9776ffa6b0a88af463ff2 100644 GIT binary patch delta 10960 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 delta 7741 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", lambda e: self.navigate_to(self.path_entry.get())) - self.hidden_files_button = ttk.Checkbutton( - top_bar, text="Versteckte Dateien", variable=self.show_hidden_files, command=self.populate_files) - self.hidden_files_button.grid(row=0, column=1, padx=5) + view_switch = ttk.Frame(top_bar, padding=(5, 0)) - view_switch.grid(row=0, column=2) - ttk.Radiobutton(view_switch, text="Kacheln", variable=self.view_mode, - value="icons", command=self.populate_files).pack(side="left") - ttk.Radiobutton(view_switch, text="Liste", variable=self.view_mode, - value="list", command=self.populate_files).pack(side="left") - self.filter_combobox = ttk.Combobox( - top_bar, values=[ft[0] for ft in self.filetypes], state="readonly", width=20) - self.filter_combobox.grid(row=0, column=3, padx=5) - self.filter_combobox.bind( - "<>", self.on_filter_change) - self.filter_combobox.set(self.filetypes[0][0]) + view_switch.grid(row=0, column=1) + self.icon_view_button = ttk.Button(view_switch, image=self.icons['icon_view'], command=lambda: ( + self.view_mode.set("icons"), self.populate_files()), style="Toolbutton.TButton") + self.icon_view_button.pack(side="left") + Tooltip(self.icon_view_button, "Kachelansicht") + self.list_view_button = ttk.Button(view_switch, image=self.icons['list_view'], command=lambda: ( + self.view_mode.set("list"), self.populate_files()), style="Toolbutton.TButton") + self.list_view_button.pack(side="left") + Tooltip(self.list_view_button, "Listenansicht") + + self.hidden_files_button = ttk.Button( + top_bar, image=self.icons['hide'], command=self.toggle_hidden_files, style="Toolbutton.TButton") + self.hidden_files_button.grid(row=0, column=2, padx=5) + Tooltip(self.hidden_files_button, "Versteckte Dateien anzeigen") ttk.Separator(content_frame, orient='horizontal').grid( row=1, column=0, sticky="ew", pady=5) @@ -276,17 +317,40 @@ class CustomFileDialog(tk.Toplevel): self.file_list_frame.grid(row=2, column=0, sticky="nsew") self.bind("", self.on_window_resize) - bottom_frame = ttk.Frame(content_frame) - bottom_frame.grid(row=3, column=0, sticky="ew", pady=(5, 0)) - bottom_frame.grid_columnconfigure(0, weight=1) - self.status_bar = ttk.Label(bottom_frame, text="", anchor="w") + bottom_controls_frame = ttk.Frame(content_frame) + bottom_controls_frame.grid(row=3, column=0, sticky="ew", pady=(5, 0)) + bottom_controls_frame.grid_columnconfigure(0, weight=1) + + self.status_bar = ttk.Label(bottom_controls_frame, text="", anchor="w") self.status_bar.grid(row=0, column=0, sticky="ew") - action_buttons_frame = ttk.Frame(bottom_frame) - action_buttons_frame.grid(row=0, column=1) + + right_side_buttons_frame = ttk.Frame(bottom_controls_frame) + right_side_buttons_frame.grid(row=0, column=1, sticky="e") + + self.filter_combobox = ttk.Combobox( + right_side_buttons_frame, values=[ft[0] for ft in self.filetypes], state="readonly", width=20) + self.filter_combobox.pack(anchor="e", pady=(0, 5)) + self.filter_combobox.bind( + "<>", self.on_filter_change) + self.filter_combobox.set(self.filetypes[0][0]) + + action_buttons_frame = ttk.Frame(right_side_buttons_frame) + action_buttons_frame.pack(anchor="e", pady=(0, 10)) + ttk.Button(action_buttons_frame, text="Öffnen", command=self.on_open).pack(side="right") ttk.Button(action_buttons_frame, text="Abbrechen", - command=self.on_cancel).pack(side="right", padx=5, pady=15) + command=self.on_cancel).pack(side="right", padx=5) + + def toggle_hidden_files(self): + self.show_hidden_files.set(not self.show_hidden_files.get()) + if self.show_hidden_files.get(): + self.hidden_files_button.config(image=self.icons['unhide']) + Tooltip(self.hidden_files_button, "Versteckte Dateien ausblenden") + else: + self.hidden_files_button.config(image=self.icons['hide']) + Tooltip(self.hidden_files_button, "Versteckte Dateien anzeigen") + self.populate_files() def on_window_resize(self, event): new_width = self.file_list_frame.winfo_width() @@ -311,9 +375,7 @@ class CustomFileDialog(tk.Toplevel): self.path_entry.delete(0, tk.END) self.path_entry.insert(0, self.current_dir) self.selected_file = None - current_status = self.status_bar.cget("text") - if not current_status.startswith("Zeige"): - self.update_status_bar() + self.update_status_bar() if self.view_mode.get() == "list": self.populate_list_view() else: @@ -400,25 +462,36 @@ class CustomFileDialog(tk.Toplevel): def populate_list_view(self): tree_frame = ttk.Frame(self.file_list_frame) tree_frame.pack(fill='both', expand=True) - columns = ("name", "size", "type", "modified") - self.tree = ttk.Treeview(tree_frame, columns=columns, show="headings") - self.tree.heading("name", text="Name", anchor="w") - self.tree.column("name", anchor="w", width=300, stretch=True) + tree_frame.grid_rowconfigure(0, weight=1) + tree_frame.grid_columnconfigure(0, weight=1) + + columns = ("size", "type", "modified") + self.tree = ttk.Treeview( + tree_frame, columns=columns, show="tree headings") + + # Tree Column (#0) + self.tree.heading("#0", text="Name", anchor="w") + self.tree.column("#0", anchor="w", width=250, stretch=True) + + # Other Columns self.tree.heading("size", text="Größe", anchor="e") self.tree.column("size", anchor="e", width=120, stretch=False) self.tree.heading("type", text="Typ", anchor="w") self.tree.column("type", anchor="w", width=120, stretch=False) self.tree.heading("modified", text="Geändert am", anchor="w") self.tree.column("modified", anchor="w", width=160, stretch=False) + v_scrollbar = ttk.Scrollbar( tree_frame, orient="vertical", command=self.tree.yview) h_scrollbar = ttk.Scrollbar( tree_frame, orient="horizontal", command=self.tree.xview) self.tree.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set) - self.tree.pack(side="left", fill="both", expand=True) - v_scrollbar.pack(side="right", fill="y") - h_scrollbar.pack(side="bottom", fill="x") + + self.tree.grid(row=0, column=0, sticky='nsew') + v_scrollbar.grid(row=0, column=1, sticky='ns') + h_scrollbar.grid(row=1, column=0, sticky='ew') + self.tree.bind("", self.on_list_double_click) self.tree.bind("<>", self.on_list_select) @@ -426,7 +499,7 @@ class CustomFileDialog(tk.Toplevel): if warning: self.status_bar.config(text=warning) if error: - self.tree.insert("", "end", values=(error,)) + self.tree.insert("", "end", text=error, values=()) return for name in items: @@ -446,7 +519,7 @@ class CustomFileDialog(tk.Toplevel): icon, file_type, size = self.get_file_icon( name, 'small'), "Datei", self._format_size(stat.st_size) self.tree.insert("", "end", text=name, image=icon, values=( - name, size, file_type, modified_time)) + size, file_type, modified_time)) except (FileNotFoundError, PermissionError): continue @@ -468,7 +541,7 @@ class CustomFileDialog(tk.Toplevel): if not self.tree.selection(): return item_id = self.tree.selection()[0] - item_text = self.tree.item(item_id, 'values')[0] + item_text = self.tree.item(item_id, 'text') self.selected_file = os.path.join(self.current_dir, item_text) self.update_status_bar() @@ -492,7 +565,7 @@ class CustomFileDialog(tk.Toplevel): if not self.tree.selection(): return item_id = self.tree.selection()[0] - item_text = self.tree.item(item_id, 'values')[0] + item_text = self.tree.item(item_id, 'text') path = os.path.join(self.current_dir, item_text) if self._handle_unsupported_file(path): return @@ -530,6 +603,7 @@ class CustomFileDialog(tk.Toplevel): self.history_pos = len(self.history) - 1 self.populate_files() self.update_nav_buttons() + self.update_status_bar() except Exception as e: self.status_bar.config(text=f"Fehler: {e}") @@ -539,6 +613,7 @@ class CustomFileDialog(tk.Toplevel): self.current_dir = self.history[self.history_pos] self.populate_files() self.update_nav_buttons() + self.update_status_bar() def go_forward(self): if self.history_pos < len(self.history) - 1: @@ -546,6 +621,7 @@ class CustomFileDialog(tk.Toplevel): self.current_dir = self.history[self.history_pos] self.populate_files() self.update_nav_buttons() + self.update_status_bar() def update_nav_buttons(self): self.back_button.config( @@ -555,16 +631,21 @@ class CustomFileDialog(tk.Toplevel): def update_status_bar(self): try: - _, _, free = shutil.disk_usage(self.current_dir) + total, used, free = shutil.disk_usage(self.current_dir) free_str = self._format_size(free) - status_text = f"Freier Speicher: {free_str}" + self.storage_label.config(text=f"Freier Speicher: {free_str}") + self.storage_bar['value'] = (used / total) * 100 + + status_text = "" if self.selected_file and os.path.exists(self.selected_file) and not os.path.isdir(self.selected_file): size = os.path.getsize(self.selected_file) size_str = self._format_size(size) - status_text += f" | '{os.path.basename(self.selected_file)}' Größe: {size_str}" + status_text = f"'{os.path.basename(self.selected_file)}' Größe: {size_str}" self.status_bar.config(text=status_text) except FileNotFoundError: self.status_bar.config(text="Verzeichnis nicht gefunden") + self.storage_label.config(text="Freier Speicher: Unbekannt") + self.storage_bar['value'] = 0 def on_open(self): if self.selected_file and os.path.isfile(self.selected_file): diff --git a/mainwindow.py b/mainwindow.py index 00ce153..0610908 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -13,7 +13,7 @@ class GlotzMol(tk.Tk): self.title("Custom File Dialog Test") container = ttk.Frame(self, padding=10) - container.pack(fill="both", expand=True) + container.pack(fill="x", anchor="n") ttk.Label(container, text="Ausgewählte Datei:").grid( row=0, column=0, sticky="w") @@ -58,7 +58,7 @@ if __name__ == "__main__": style = ttk.Style(root) root.tk.call('source', f"{theme_path}/water.tcl") try: - root.tk.call('set_theme', 'dark') + root.tk.call('set_theme', 'light') except tk.TclError: pass root.mainloop()