add dochstring in cfd_file_operations, cfd_navigation_manager, cfd_search_manager, cfd_settings_dialog and fix entryfield on create new folder and new document in iconview

This commit is contained in:
2025-08-10 11:16:48 +02:00
parent 246addc34b
commit 14a50616a3
10 changed files with 220 additions and 8 deletions

View File

@@ -14,11 +14,28 @@ from cfd_app_config import LocaleStrings, _
class FileOperationsManager:
"""Manages file operations like delete, create, and rename."""
def __init__(self, dialog):
"""
Initializes the FileOperationsManager.
Args:
dialog: The main CustomFileDialog instance.
"""
self.dialog = dialog
def delete_selected_item(self, event=None):
"""Deletes or moves the selected item to trash based on settings."""
"""
Deletes the selected item or moves it to the trash.
This method checks user settings to determine whether to move the item
to the system's trash (if available) or delete it permanently.
It also handles the confirmation dialog based on user preferences.
Args:
event: The event that triggered the deletion (optional).
"""
if not self.dialog.selected_file or not os.path.exists(self.dialog.selected_file):
return
@@ -61,12 +78,22 @@ class FileOperationsManager:
).show()
def create_new_folder(self):
"""Creates a new folder in the current directory."""
self._create_new_item(is_folder=True)
def create_new_file(self):
"""Creates a new empty file in the current directory."""
self._create_new_item(is_folder=False)
def _create_new_item(self, is_folder):
"""
Internal helper to create a new file or folder.
It generates a unique name and creates the item, then refreshes the view.
Args:
is_folder (bool): True to create a folder, False to create a file.
"""
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)
@@ -82,6 +109,18 @@ class FileOperationsManager:
text=f"{LocaleStrings.FILE['error_creating']}: {e}")
def _get_unique_name(self, base_name):
"""
Generates a unique name for a file or folder.
If a file or folder with `base_name` already exists, it appends
a counter (e.g., "New Folder 2") until a unique name is found.
Args:
base_name (str): The initial name for the item.
Returns:
str: A unique name for the item in the current directory.
"""
name, ext = os.path.splitext(base_name)
counter = 1
new_name = base_name
@@ -91,12 +130,28 @@ class FileOperationsManager:
return new_name
def _copy_to_clipboard(self, data):
"""
Copies the given data to the system clipboard.
Args:
data (str): The text to be copied.
"""
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)}' {LocaleStrings.FILE['copied_to_clipboard']}")
def _show_context_menu(self, event, item_path):
"""
Displays a context menu for the selected item.
Args:
event: The mouse event that triggered the menu.
item_path (str): The full path to the item.
Returns:
str: "break" to prevent further event propagation.
"""
if not item_path:
return "break"
@@ -119,6 +174,15 @@ class FileOperationsManager:
return "break"
def _open_file_location_from_context(self, file_path):
"""
Navigates to the location of the given file path.
This is used by the context menu to jump to a file's directory,
which is especially useful when in search mode.
Args:
file_path (str): The full path to the file.
"""
directory = os.path.dirname(file_path)
filename = os.path.basename(file_path)
@@ -129,6 +193,17 @@ class FileOperationsManager:
self.dialog.after(100, lambda: self.dialog.view_manager._select_file_in_view(filename))
def on_rename_request(self, event, item_path=None, item_frame=None):
"""
Handles the initial request to rename an item.
This method is triggered by an event (e.g., F2 key press) and
initiates the renaming process based on the current view mode.
Args:
event: The event that triggered the rename.
item_path (str, optional): The path of the item in icon view.
item_frame (tk.Widget, optional): The frame of the item in icon view.
"""
if self.dialog.view_mode.get() == "list":
if not self.dialog.tree.selection():
return
@@ -141,16 +216,36 @@ class FileOperationsManager:
self.start_rename(item_frame, item_path)
def start_rename(self, item_widget, item_path):
"""
Starts the renaming UI for an item.
Dispatches to the appropriate method based on the current view mode.
Args:
item_widget: The widget representing the item (item_id for list view,
item_frame for icon view).
item_path (str): The full path to the item being renamed.
"""
if self.dialog.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
def _start_rename_icon_view(self, item_frame, item_path):
"""
Initiates the in-place rename UI for an item in icon view.
It replaces the item's label with an Entry widget.
Args:
item_frame (tk.Widget): The frame containing the item's icon and label.
item_path (str): The full path to the item.
"""
for child in item_frame.winfo_children():
child.destroy()
entry = ttk.Entry(item_frame)
entry.pack(fill="both", expand=True, padx=2, pady=20)
entry.insert(0, os.path.basename(item_path))
entry.select_range(0, tk.END)
entry.focus_set()
@@ -173,7 +268,7 @@ class FileOperationsManager:
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))
self.dialog.view_manager.populate_files(item_to_select=os.path.basename(item_path))
def cancel_rename(event):
self.dialog.view_manager.populate_files()
@@ -183,6 +278,14 @@ class FileOperationsManager:
entry.bind("<Escape>", cancel_rename)
def _start_rename_list_view(self, item_id):
"""
Initiates the in-place rename UI for an item in list view.
It places an Entry widget over the Treeview item's cell.
Args:
item_id: The ID of the treeview item to be renamed.
"""
self.dialog.tree.see(item_id)
self.dialog.tree.update_idletasks()
@@ -220,7 +323,7 @@ class FileOperationsManager:
text=f"{LocaleStrings.FILE['error_renaming']}: {e}")
self.dialog.view_manager.populate_files()
else:
self.dialog.populate_files(item_to_select=item_text)
self.dialog.view_manager.populate_files(item_to_select=item_text)
entry.destroy()
def cancel_rename(event):