diff --git a/__pycache__/animated_icon.cpython-312.pyc b/__pycache__/animated_icon.cpython-312.pyc index 7eec2b6..b13cb7f 100644 Binary files a/__pycache__/animated_icon.cpython-312.pyc and b/__pycache__/animated_icon.cpython-312.pyc differ diff --git a/__pycache__/cfd_app_config.cpython-312.pyc b/__pycache__/cfd_app_config.cpython-312.pyc index 461b793..7e57d41 100644 Binary files a/__pycache__/cfd_app_config.cpython-312.pyc and b/__pycache__/cfd_app_config.cpython-312.pyc differ diff --git a/animated_icon.py b/animated_icon.py index 3953a77..8ba795b 100644 --- a/animated_icon.py +++ b/animated_icon.py @@ -1,3 +1,10 @@ +""" +A Tkinter widget for displaying animated icons. + +This module provides the AnimatedIcon class, a custom Tkinter Canvas widget +that can display various types of animations. It supports both native Tkinter +drawing and Pillow (PIL) for anti-aliased graphics if available. +""" import tkinter as tk from math import sin, cos, pi @@ -9,11 +16,27 @@ except ImportError: PIL_AVAILABLE = False def _hex_to_rgb(hex_color): + """Converts a hex color string to an RGB tuple.""" hex_color = hex_color.lstrip('#') return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) class AnimatedIcon(tk.Canvas): + """A custom Tkinter Canvas widget for displaying animations.""" def __init__(self, master, width=20, height=20, animation_type="counter_arc", color="#2a6fde", highlight_color="#5195ff", use_pillow=False, bg=None): + """ + Initializes the AnimatedIcon widget. + + Args: + master: The parent widget. + width (int): The width of the icon. + height (int): The height of the icon. + animation_type (str): The type of animation to display. + Options: "counter_arc", "double_arc", "line", "blink". + color (str): The primary color of the icon. + highlight_color (str): The highlight color of the icon. + use_pillow (bool): Whether to use Pillow for drawing if available. + bg (str): The background color of the canvas. + """ if bg is None: try: bg = master.cget("background") @@ -40,12 +63,14 @@ class AnimatedIcon(tk.Canvas): self.photo_image = None def _draw_frame(self): + """Draws a single frame of the animation.""" if self.use_pillow: self._draw_pillow_frame() else: self._draw_canvas_frame() def _draw_canvas_frame(self): + """Draws a frame using native Tkinter canvas methods.""" self.delete("all") if self.pulse_animation: self._draw_canvas_pulse() @@ -59,6 +84,7 @@ class AnimatedIcon(tk.Canvas): self._draw_canvas_blink() def _draw_canvas_pulse(self): + """Draws the pulse animation using canvas methods.""" center_x, center_y = self.width / 2, self.height / 2 alpha = (sin(self.angle * 5) + 1) / 2 # Faster pulse r = int(alpha * (self.highlight_color_rgb[0] - self.color_rgb[0]) + self.color_rgb[0]) @@ -88,6 +114,7 @@ class AnimatedIcon(tk.Canvas): def _draw_canvas_line(self): + """Draws the line animation using canvas methods.""" center_x, center_y = self.width / 2, self.height / 2 for i in range(8): angle = self.angle + i * (pi / 4) @@ -105,6 +132,7 @@ class AnimatedIcon(tk.Canvas): self.create_line(start_x, start_y, end_x, end_y, fill=color, width=2) def _draw_canvas_double_arc(self): + """Draws the double arc animation using canvas methods.""" center_x, center_y = self.width / 2, self.height / 2 radius = min(center_x, center_y) * 0.8 bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) @@ -118,6 +146,7 @@ class AnimatedIcon(tk.Canvas): self.create_arc(bbox, start=start_angle2, extent=extent2, style=tk.ARC, outline=self.color, width=2) def _draw_canvas_counter_arc(self): + """Draws the counter arc animation using canvas methods.""" center_x, center_y = self.width / 2, self.height / 2 radius_outer = min(center_x, center_y) * 0.8 @@ -131,6 +160,7 @@ class AnimatedIcon(tk.Canvas): self.create_arc(bbox_inner, start=start_angle2, extent=150, style=tk.ARC, outline=self.color, width=2) def _draw_canvas_blink(self): + """Draws the blink animation using canvas methods.""" center_x, center_y = self.width / 2, self.height / 2 radius = min(center_x, center_y) * 0.8 alpha = (sin(self.angle * 2) + 1) / 2 # Slower blinking speed @@ -141,6 +171,7 @@ class AnimatedIcon(tk.Canvas): self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y + radius, start=0, extent=359.9, style=tk.ARC, outline=blink_color, width=4) def _draw_pillow_frame(self): + """Draws a frame using Pillow for anti-aliased graphics.""" self.draw.rectangle([0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0)) if self.pulse_animation: self._draw_pillow_pulse() @@ -159,6 +190,7 @@ class AnimatedIcon(tk.Canvas): self.create_image(0, 0, anchor="nw", image=self.photo_image) def _draw_pillow_pulse(self): + """Draws the pulse animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 alpha = (sin(self.angle * 5) + 1) / 2 # Faster pulse r = int(alpha * (self.highlight_color_rgb[0] - self.color_rgb[0]) + self.color_rgb[0]) @@ -187,6 +219,7 @@ class AnimatedIcon(tk.Canvas): self.draw.arc(bbox_inner, start=0, end=360, fill=self.color_rgb, width=7) def _draw_pillow_line(self): + """Draws the line animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 for i in range(12): angle = self.angle + i * (pi / 6) @@ -204,6 +237,7 @@ class AnimatedIcon(tk.Canvas): self.draw.line([(start_x, start_y), (end_x, end_y)], fill=color, width=6, joint="curve") def _draw_pillow_double_arc(self): + """Draws the double arc animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius = min(center_x, center_y) * 0.8 bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) @@ -217,6 +251,7 @@ class AnimatedIcon(tk.Canvas): self.draw.arc(bbox, start=start_angle2, end=start_angle2 + extent2, fill=self.color_rgb, width=5) def _draw_pillow_counter_arc(self): + """Draws the counter arc animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius_outer = min(center_x, center_y) * 0.8 @@ -230,6 +265,7 @@ class AnimatedIcon(tk.Canvas): self.draw.arc(bbox_inner, start=start_angle2, end=start_angle2 + 150, fill=self.color_rgb, width=7) def _draw_pillow_blink(self): + """Draws the blink animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius = min(center_x, center_y) * 0.8 alpha = (sin(self.angle * 2) + 1) / 2 # Slower blinking speed @@ -240,6 +276,7 @@ class AnimatedIcon(tk.Canvas): self.draw.arc((center_x - radius, center_y - radius, center_x + radius, center_y + radius), start=0, end=360, fill=blink_color, width=10) def _draw_stopped_frame(self): + """Draws the icon in its stopped (static) state.""" self.delete("all") if self.use_pillow: self._draw_pillow_stopped_frame() @@ -247,6 +284,7 @@ class AnimatedIcon(tk.Canvas): self._draw_canvas_stopped_frame() def _draw_canvas_stopped_frame(self): + """Draws the stopped state using canvas methods.""" if self.animation_type == "line": self._draw_canvas_line_stopped() elif self.animation_type == "double_arc": @@ -257,6 +295,7 @@ class AnimatedIcon(tk.Canvas): self._draw_canvas_blink_stopped() def _draw_canvas_line_stopped(self): + """Draws the stopped state for the line animation.""" center_x, center_y = self.width / 2, self.height / 2 for i in range(8): angle = i * (pi / 4) @@ -267,12 +306,14 @@ class AnimatedIcon(tk.Canvas): self.create_line(start_x, start_y, end_x, end_y, fill=self.highlight_color, width=2) def _draw_canvas_double_arc_stopped(self): + """Draws the stopped state for the double arc animation.""" center_x, center_y = self.width / 2, self.height / 2 radius = min(center_x, center_y) * 0.8 bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) self.create_arc(bbox, start=0, extent=359.9, style=tk.ARC, outline=self.highlight_color, width=2) def _draw_canvas_counter_arc_stopped(self): + """Draws the stopped state for the counter arc animation.""" center_x, center_y = self.width / 2, self.height / 2 radius_outer = min(center_x, center_y) * 0.8 bbox_outer = (center_x - radius_outer, center_y - radius_outer, center_x + radius_outer, center_y + radius_outer) @@ -282,11 +323,13 @@ class AnimatedIcon(tk.Canvas): self.create_arc(bbox_inner, start=0, extent=359.9, style=tk.ARC, outline=self.color, width=2) def _draw_canvas_blink_stopped(self): + """Draws the stopped state for the blink animation.""" center_x, center_y = self.width / 2, self.height / 2 radius = min(center_x, center_y) * 0.8 self.create_arc(center_x - radius, center_y - radius, center_x + radius, center_y + radius, start=0, extent=359.9, style=tk.ARC, outline=self.highlight_color, width=4) def _draw_pillow_stopped_frame(self): + """Draws the stopped state using Pillow.""" self.draw.rectangle([0, 0, self.width * 4, self.height * 4], fill=(0, 0, 0, 0)) if self.animation_type == "line": self._draw_pillow_line_stopped() @@ -302,6 +345,7 @@ class AnimatedIcon(tk.Canvas): self.create_image(0, 0, anchor="nw", image=self.photo_image) def _draw_pillow_line_stopped(self): + """Draws the stopped state for the line animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 for i in range(12): angle = i * (pi / 6) @@ -312,12 +356,14 @@ class AnimatedIcon(tk.Canvas): self.draw.line([(start_x, start_y), (end_x, end_y)], fill=self.highlight_color_rgb, width=6, joint="curve") def _draw_pillow_double_arc_stopped(self): + """Draws the stopped state for the double arc animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius = min(center_x, center_y) * 0.8 bbox = (center_x - radius, center_y - radius, center_x + radius, center_y + radius) self.draw.arc(bbox, start=0, end=360, fill=self.highlight_color_rgb, width=5) def _draw_pillow_counter_arc_stopped(self): + """Draws the stopped state for the counter arc animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius_outer = min(center_x, center_y) * 0.8 bbox_outer = (center_x - radius_outer, center_y - radius_outer, center_x + radius_outer, center_y + radius_outer) @@ -327,11 +373,13 @@ class AnimatedIcon(tk.Canvas): self.draw.arc(bbox_inner, start=0, end=360, fill=self.color_rgb, width=7) def _draw_pillow_blink_stopped(self): + """Draws the stopped state for the blink animation using Pillow.""" center_x, center_y = self.width * 2, self.height * 2 radius = min(center_x, center_y) * 0.8 self.draw.arc((center_x - radius, center_y - radius, center_x + radius, center_y + radius), start=0, end=360, fill=self.highlight_color_rgb, width=10) def _animate(self): + """The main animation loop.""" if self.running: self.angle += 0.1 if self.angle > 2 * pi: @@ -340,21 +388,30 @@ class AnimatedIcon(tk.Canvas): self.after(30, self._animate) def start(self, pulse=False): + """ + Starts the animation. + + Args: + pulse (bool): If True, plays a pulsing animation instead of the main one. + """ if not self.running: self.pulse_animation = pulse self.running = True self._animate() def stop(self): + """Stops the animation and shows the static 'stopped' frame.""" self.running = False self.pulse_animation = False self._draw_stopped_frame() def hide(self): + """Stops the animation and clears the canvas.""" self.running = False self.pulse_animation = False self.delete("all") def show_full_circle(self): + """Shows the static 'stopped' frame without starting the animation.""" if not self.running: - self._draw_stopped_frame() + self._draw_stopped_frame() \ No newline at end of file diff --git a/cfd_app_config.py b/cfd_app_config.py index f4031ce..e5c19d0 100755 --- a/cfd_app_config.py +++ b/cfd_app_config.py @@ -9,24 +9,16 @@ from shared_libs.common_tools import Translate class AppConfig: - """Central configuration and system setup manager for the Wire-Py application. - - This class serves as a singleton-like container for all global configuration data, - including paths, UI settings, localization, versioning, and system-specific resources. - It ensures that required directories, files, and services are created and configured - before the application starts. Additionally, it provides tools for managing translations. - - Key Responsibilities: - - Centralizes all configuration values (paths, UI preferences, localization). - - Ensures required directories and files exist. - - Handles translation setup via `gettext` for multilingual support. - - Manages default settings file generation. - - Configures autostart services using systemd for user-specific launch behavior. - - This class is used globally across the application to access configuration data - consistently and perform system-level setup tasks. """ + Holds static configuration values for the application. + Attributes: + SCRIPT_DIR (str): The absolute path to the directory where the script is running. + MAX_ITEMS_TO_DISPLAY (int): The maximum number of items to show in the file list to prevent performance issues. + BASE_DIR (Path): The user's home directory. + CONFIG_DIR (Path): The directory for storing configuration files. + UI_CONFIG (Dict[str, Any]): A dictionary containing UI-related settings. + """ # Helper to make icon paths robust, so the script can be run from anywhere SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) MAX_ITEMS_TO_DISPLAY = 1000 @@ -69,7 +61,7 @@ class CfdConfigManager: @classmethod def _ensure_config_file(cls): - """Ensures the config file exists with default values if not present.""" + """Ensures the configuration file exists, creating it with default settings if necessary.""" if not cls._config_file.exists(): try: cls._config_file.parent.mkdir(parents=True, exist_ok=True) @@ -80,7 +72,7 @@ class CfdConfigManager: @classmethod def load(cls): - """Loads settings from the JSON file, applying defaults for missing keys.""" + """Loads settings from the JSON file. If the file doesn't exist or is invalid, it loads default settings.""" cls._ensure_config_file() if cls._config is None: try: @@ -105,6 +97,13 @@ class CfdConfigManager: class LocaleStrings: + """ + Contains all translatable strings for the application, organized by module. + + This class centralizes all user-facing strings to make translation and management easier. + The strings are grouped into nested dictionaries corresponding to the part of the application + where they are used (e.g., CFD for the main dialog, VIEW for view-related strings). + """ # Strings from custom_file_dialog.py CFD = { "title": _("Custom File Dialog"), @@ -250,6 +249,4 @@ class LocaleStrings: "pictures": _("Pictures"), "videos": _("Videos"), "computer": _("Computer"), - } - - + } \ No newline at end of file