From 4e7ef8d3482309443644e5938a12c8e7bc23c546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9sir=C3=A9=20Werner=20Menrath?= Date: Sun, 10 Aug 2025 11:33:19 +0200 Subject: [PATCH] add docstring in cfd_ui_setup, cfd_view_manager --- __pycache__/cfd_ui_setup.cpython-312.pyc | Bin 37757 -> 39099 bytes __pycache__/cfd_view_manager.cpython-312.pyc | Bin 38005 -> 41734 bytes cfd_ui_setup.py | 38 ++++++- cfd_view_manager.py | 111 +++++++++++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) diff --git a/__pycache__/cfd_ui_setup.cpython-312.pyc b/__pycache__/cfd_ui_setup.cpython-312.pyc index 9b2aa40fa74ceb15e0b87cb2455ecf7d0f206f6d..31a38bc054866055a97374f9280d8c7521b106ad 100644 GIT binary patch delta 5188 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 delta 3715 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 delta 6040 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", self.dialog.on_sidebar_resize) @@ -220,6 +251,7 @@ class WidgetManager: self._setup_sidebar_storage(sidebar_frame) def _setup_sidebar_bookmarks(self, sidebar_frame): + """Sets up the bookmark buttons in the sidebar.""" 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 = [ @@ -238,6 +270,7 @@ class WidgetManager: self.sidebar_buttons.append((btn, f" {config['name']}")) def _setup_sidebar_devices(self, sidebar_frame): + """Sets up the mounted devices section in the sidebar.""" mounted_devices_frame = ttk.Frame(sidebar_frame, style="Sidebar.TFrame") mounted_devices_frame.grid(row=2, column=0, sticky="nsew", padx=10) mounted_devices_frame.grid_columnconfigure(0, weight=1) @@ -326,6 +359,7 @@ class WidgetManager: pass def _setup_sidebar_storage(self, sidebar_frame): + """Sets up the storage indicator in the sidebar.""" 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=f"{LocaleStrings.CFD["free_space"]}:", background=self.style_manager.freespace_background) @@ -334,7 +368,7 @@ class WidgetManager: self.storage_bar.pack(fill="x", pady=(2, 5), padx=15) def _setup_bottom_bar(self): - """Sets up the bottom bar including containers and widgets based on dialog mode.""" + """Sets up the bottom bar including filename entry, action buttons, and status info.""" self.action_status_frame = ttk.Frame(self.content_frame, style="AccentBottom.TFrame") self.action_status_frame.grid(row=1, column=0, sticky="ew", pady=(5, 5), padx=10) self.status_container = ttk.Frame(self.action_status_frame, style="AccentBottom.TFrame") @@ -396,6 +430,7 @@ class WidgetManager: self._layout_bottom_buttons(button_box_pos) def _layout_bottom_buttons(self, button_box_pos): + """Lays out the bottom action buttons based on user settings.""" # Configure container weights self.left_container.grid_rowconfigure(0, weight=1) self.right_container.grid_rowconfigure(0, weight=1) @@ -429,6 +464,7 @@ class WidgetManager: def setup_widgets(self): + """Creates and arranges all widgets in the main dialog window.""" # Main container main_frame = ttk.Frame(self.dialog, style='Accent.TFrame') main_frame.pack(fill="both", expand=True) diff --git a/cfd_view_manager.py b/cfd_view_manager.py index c408889..14fd8ff 100644 --- a/cfd_view_manager.py +++ b/cfd_view_manager.py @@ -6,10 +6,29 @@ from shared_libs.common_tools import Tooltip from cfd_app_config import AppConfig, LocaleStrings, _ class ViewManager: + """Manages the display of files and folders in list and icon views.""" def __init__(self, dialog): + """ + Initializes the ViewManager. + + Args: + dialog: The main CustomFileDialog instance. + """ self.dialog = dialog def populate_files(self, item_to_rename=None, item_to_select=None): + """ + Populates the main file display area. + + This method clears the current view and then calls the appropriate + method to populate either the list or icon view. + + Args: + item_to_rename (str, optional): The name of an item to immediately + put into rename mode. Defaults to None. + item_to_select (str, optional): The name of an item to select + after populating. Defaults to None. + """ self._unbind_mouse_wheel_events() for widget in self.dialog.widget_manager.file_list_frame.winfo_children(): @@ -24,6 +43,12 @@ class ViewManager: self.populate_icon_view(item_to_rename, item_to_select) def _get_sorted_items(self): + """ + Gets a sorted list of items from the current directory. + + Returns: + tuple: A tuple containing (list of items, error message, warning message). + """ try: items = os.listdir(self.dialog.current_dir) num_items = len(items) @@ -42,6 +67,15 @@ class ViewManager: return ([], LocaleStrings.CFD["directory_not_found"], None) def _get_folder_content_count(self, folder_path): + """ + Counts the number of items in a given folder. + + Args: + folder_path (str): The path to the folder. + + Returns: + int or None: The number of items, or None if an error occurs. + """ try: if not os.path.isdir(folder_path) or not os.access(folder_path, os.R_OK): return None @@ -56,11 +90,21 @@ class ViewManager: return None def _get_item_path_from_widget(self, widget): + """ + Traverses up the widget hierarchy to find the item_path attribute. + + Args: + widget: The widget to start from. + + Returns: + str or None: The associated file path, or None if not found. + """ while widget and not hasattr(widget, 'item_path'): widget = widget.master return getattr(widget, 'item_path', None) def _handle_icon_click(self, event): + """Handles a single click on an icon view item.""" item_path = self._get_item_path_from_widget(event.widget) if item_path: item_frame = event.widget @@ -69,16 +113,19 @@ class ViewManager: self.on_item_select(item_path, item_frame) def _handle_icon_double_click(self, event): + """Handles a double click on an icon view item.""" item_path = self._get_item_path_from_widget(event.widget) if item_path: self.on_item_double_click(item_path) def _handle_icon_context_menu(self, event): + """Handles a context menu request on an icon view item.""" item_path = self._get_item_path_from_widget(event.widget) if item_path: self.dialog.file_op_manager._show_context_menu(event, item_path) def _handle_icon_rename_request(self, event): + """Handles a rename request on an icon view item.""" item_path = self._get_item_path_from_widget(event.widget) if item_path: item_frame = event.widget @@ -87,6 +134,13 @@ class ViewManager: self.dialog.file_op_manager.on_rename_request(event, item_path, item_frame) def populate_icon_view(self, item_to_rename=None, item_to_select=None): + """ + Populates the file display with items in an icon grid layout. + + Args: + item_to_rename (str, optional): Item to enter rename mode. + item_to_select (str, optional): Item to select. + """ self.dialog.all_items, error, warning = self._get_sorted_items() self.dialog.currently_loaded_count = 0 @@ -154,6 +208,18 @@ class ViewManager: self.dialog.after(100, scroll_to_widget) def _load_more_items_icon_view(self, container, scroll_handler, item_to_rename=None, item_to_select=None): + """ + Loads a batch of items into the icon view. + + Args: + container: The parent widget for the items. + scroll_handler: The function to handle mouse wheel events. + item_to_rename (str, optional): Item to enter rename mode. + item_to_select (str, optional): Item to select. + + Returns: + The widget that was focused (renamed or selected), or None. + """ start_index = self.dialog.currently_loaded_count end_index = min(len(self.dialog.all_items), start_index + self.dialog.items_to_load_per_batch) @@ -228,6 +294,13 @@ class ViewManager: return widget_to_focus def populate_list_view(self, item_to_rename=None, item_to_select=None): + """ + Populates the file display with items in a list (Treeview) layout. + + Args: + item_to_rename (str, optional): Item to enter rename mode. + item_to_select (str, optional): Item to select. + """ self.dialog.all_items, error, warning = self._get_sorted_items() self.dialog.currently_loaded_count = 0 @@ -286,6 +359,16 @@ class ViewManager: break def _load_more_items_list_view(self, item_to_rename=None, item_to_select=None): + """ + Loads a batch of items into the list view. + + Args: + item_to_rename (str, optional): Item to enter rename mode. + item_to_select (str, optional): Item to select. + + Returns: + bool: True if the item to rename/select was found and processed. + """ start_index = self.dialog.currently_loaded_count end_index = min(len(self.dialog.all_items), start_index + self.dialog.items_to_load_per_batch) @@ -332,6 +415,13 @@ class ViewManager: return item_found def on_item_select(self, path, item_frame): + """ + Handles the selection of an item in the icon view. + + Args: + path (str): The path of the selected item. + item_frame: The widget frame of the selected item. + """ if hasattr(self.dialog, 'selected_item_frame') and self.dialog.selected_item_frame.winfo_exists(): self.dialog.selected_item_frame.state(['!selected']) for child in self.dialog.selected_item_frame.winfo_children(): @@ -350,6 +440,7 @@ class ViewManager: self.dialog.widget_manager.filename_entry.insert(0, os.path.basename(path)) def on_list_select(self, event): + """Handles the selection of an item in the list view.""" if not self.dialog.tree.selection(): return item_id = self.dialog.tree.selection()[0] @@ -363,6 +454,7 @@ class ViewManager: self.dialog.widget_manager.filename_entry.insert(0, item_text) def on_list_context_menu(self, event): + """Shows the context menu for a list view item.""" iid = self.dialog.tree.identify_row(event.y) if not iid: return "break" @@ -373,6 +465,12 @@ class ViewManager: return "break" def on_item_double_click(self, path): + """ + Handles a double-click on an icon view item. + + Args: + path (str): The path of the double-clicked item. + """ if os.path.isdir(path): self.dialog.navigation_manager.navigate_to(path) elif self.dialog.dialog_mode == "open": @@ -385,6 +483,7 @@ class ViewManager: self.dialog.on_save() def on_list_double_click(self, event): + """Handles a double-click on a list view item.""" if not self.dialog.tree.selection(): return item_id = self.dialog.tree.selection()[0] @@ -401,6 +500,12 @@ class ViewManager: self.dialog.on_save() def _select_file_in_view(self, filename): + """ + Programmatically selects a file in the current view. + + Args: + filename (str): The name of the file to select. + """ if self.dialog.view_mode.get() == "list": for item_id in self.dialog.tree.get_children(): if self.dialog.tree.item(item_id, "text").strip() == filename: @@ -436,6 +541,7 @@ class ViewManager: break def _update_view_mode_buttons(self): + """Updates the visual state of the view mode toggle buttons.""" if self.dialog.view_mode.get() == "icons": self.dialog.widget_manager.icon_view_button.configure( style="Header.TButton.Active.Round") @@ -448,16 +554,19 @@ class ViewManager: style="Header.TButton.Borderless.Round") def set_icon_view(self): + """Switches to icon view and repopulates the files.""" self.dialog.view_mode.set("icons") self._update_view_mode_buttons() self.populate_files() def set_list_view(self): + """Switches to list view and repopulates the files.""" self.dialog.view_mode.set("list") self._update_view_mode_buttons() self.populate_files() def toggle_hidden_files(self): + """Toggles the visibility of hidden files and refreshes the view.""" self.dialog.show_hidden_files.set(not self.dialog.show_hidden_files.get()) if self.dialog.show_hidden_files.get(): self.dialog.widget_manager.hidden_files_button.config( @@ -472,6 +581,7 @@ class ViewManager: self.populate_files() def on_filter_change(self, event): + """Handles a change in the file type filter combobox.""" selected_desc = self.dialog.widget_manager.filter_combobox.get() for desc, pattern in self.dialog.filetypes: if desc == selected_desc: @@ -480,6 +590,7 @@ class ViewManager: self.populate_files() def _unbind_mouse_wheel_events(self): + """Unbinds all mouse wheel events from the dialog.""" self.dialog.unbind_all("") self.dialog.unbind_all("") self.dialog.unbind_all("")