From c1580f6ace288a68a3523b4a706f6dccae3309d0 Mon Sep 17 00:00:00 2001 From: punix Date: Sun, 15 Jun 2025 15:37:27 +0200 Subject: [PATCH] import LxTools with try except and add images in readme --- Changelog | 8 +- README.md | 11 ++- logviewer.py | 1 - message.py | 222 ++++++++++++++++++++------------------------------- 4 files changed, 102 insertions(+), 140 deletions(-) diff --git a/Changelog b/Changelog index 0488a9d..e976829 100644 --- a/Changelog +++ b/Changelog @@ -4,7 +4,13 @@ Changelog for shared_libs - add Info Window for user in delete logfile bevore delete logfile. - + + ### Added +15-06-2025 + + - Update MessageDialog Class description + - import LxTools with try exception. + ### Added 14-06-2025 diff --git a/README.md b/README.md index 24b594c..efead32 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ # shared_libs -Module Project for apps by git.ilunix.de \ No newline at end of file +Module Project for apps by git.ilunix.de +Examples with a Theme from Projekt Wire-Py + +# Screenshots +[![info_example.png](https://fb.ilunix.de/api/public/dl/KtaTPMMq=true)](https://fb.ilunix.de/share/KtaTPMMq) +[![error_example.png](https://fb.ilunix.de/api/public/dl/cRO_ksrM=true)](https://fb.ilunix.de/share/cRO_ksrM) +[![warning_example.png](https://fb.ilunix.de/api/public/dl/1JEdSJcI=true)](https://fb.ilunix.de/share/1JEdSJcI) +[![question_light_example.png](https://fb.ilunix.de/api/public/dl/XxNey7y7=true)](https://fb.ilunix.de/share/1XxNey7y7) +[![question_dark_example.png](https://fb.ilunix.de/api/public/dl/4HCxiNwB=true)](https://fb.ilunix.de/share/4HCxiNwB) +[![example_with_own_title_and_icon.png](https://fb.ilunix.de/api/public/dl/uui8b1xx=true)](https://fb.ilunix.de/share/uui8b1xx) \ No newline at end of file diff --git a/logviewer.py b/logviewer.py index bf4944c..d5b9cae 100755 --- a/logviewer.py +++ b/logviewer.py @@ -17,7 +17,6 @@ from shared_libs.common_tools import ( ) import sys from file_and_dir_ensure import prepare_app_environment -import webbrowser class LogViewer(tk.Tk): diff --git a/message.py b/message.py index d52f931..f79714c 100644 --- a/message.py +++ b/message.py @@ -2,155 +2,104 @@ import os from typing import List, Optional, Dict import tkinter as tk from tkinter import ttk -from shared_libs.common_tools import LxTools -""" -#################################################### -Attention! MessageDialog returns different values. -From 3 buttons with Cancel, Cancel and the Close (x) -None returns. otherwise always False. -#################################################### -Usage Examples -1. Basic Info Dialog -from tkinter import Tk - -root = Tk() -dialog = MessageDialog( - message_type="info", - text="This is an information message.", - buttons=["OK"], - master=root, -) -result = dialog.show() -print("User clicked OK:", result) - ------------------------------------------------------ -My Favorite Example, -for simply information message: - -MessageDialog(text="This is an information message.") -result = MessageDialog(text="This is an information message.").show() ------------------------------------------------------ -Explanation: if you need the return value e.g. in the vaiable result, -you need to add .show(). otherwise only if no root.mainloop z.b is used to test the window. -##################################################### - -2. Error Dialog with Custom Icon and Command -def on_cancel(): - print("User canceled the operation.") - -root = Tk() -result = MessageDialog( - message_type="error", - text="An error occurred during processing.", - buttons=["Retry", "Cancel"], - commands=[None, on_cancel], - icon="/path/to/custom/error_icon.png", - title="Critical Error" -).show() - -print("User clicked Retry:", result) - ------------------------------------------------------ -My Favorite Example, -for simply Error message: - -MessageDialog( - "error", - text="An error occurred during processing.", -).show() - -##################################################### - -3. Confirmation Dialog with Yes/No Buttons -def on_confirm(): - print("User confirmed the action.") - -root = Tk() -dialog = MessageDialog( - message_type="ask", - text="Are you sure you want to proceed?", - buttons=["Yes", "No"], - commands=[on_confirm, None], # Either use comando or work with the values True and False -) -result = dialog.show() -print("User confirmed:", result) ------------------------------------------------------ - -My Favorite Example, -for simply Question message: - -dialog = MessageDialog( - "ask", - text="Are you sure you want to proceed?", - buttons=["Yes", "No"] - ).show() -##################################################### - -4. Warning Dialog with Custom Title - -root = Tk() -dialog = MessageDialog( - message_type="warning", - text="This action cannot be undone.", - buttons=["Proceed", "Cancel"], - title="Warning: Irreversible Action" -) -result = dialog.show() -print("User proceeded:", result) ------------------------------------------------------ -And a special example for a "open link" button: -Be careful not to forget to import it into the script in which this dialog is used!!! -import webbrowser -from functools import partial - -dialog = MessageDialog( - "ask", - text="Are you sure you want to proceed?", - buttons=["Yes", "Go to Exapmle"], - commands=[ - None, # Default on "OK" - partial(webbrowser.open, "https://exapmle.com"), - ], - icon="/pathh/to/custom/icon.png", - title="Example", -).show() - - -In all dialogues, a font can also be specified as a tuple. With font=("ubuntu", 11) -and wraplength=300, the text is automatically wrapped. -""" +try: + from manager import LxTools +except (ModuleNotFoundError, NameError): + from shared_libs.common_tools import LxTools class MessageDialog: """ - A customizable message dialog window using tkinter. + A customizable message dialog window using tkinter for user interaction. This class creates modal dialogs for displaying information, warnings, errors, - or questions to the user. It supports multiple button configurations and custom - icons. The dialog is centered on the screen and handles user interactions. + or questions to the user. It supports multiple button configurations, custom + icons, keyboard navigation, and command binding. The dialog is centered on the + screen and handles user interactions with focus management and accessibility. Attributes: message_type (str): Type of message ("info", "error", "warning", "ask"). - text (str): Main message content. + text (str): Main message content to display. buttons (List[str]): List of button labels (e.g., ["OK", "Cancel"]). - result (bool): True if the user clicked a positive button (like "Yes" or "OK"), else False. - icons: Dictionary mapping message types to tkinter.PhotoImage objects. + result (bool or None): + - True for positive actions (Yes, OK) + - False for negative actions (No, Cancel) + - None if "Cancel" was clicked with ≥3 buttons + icons: Dictionary mapping message types to tkinter.PhotoImage objects Parameters: - message_type: Type of message dialog (default: "info"). - text: Message content to display. - buttons: List of button labels (default: ["OK"]). - master: Parent tkinter window (optional). - commands: List of callables for each button (default: [None]). - icon: Custom icon path (overrides default icons if provided). - title: Window title (default: derived from message_type). + message_type: Type of message dialog (default: "info") + text: Message content to display + buttons: List of button labels (default: ["OK"]) + master: Parent tkinter window (optional) + commands: List of callables for each button (default: [None]) + icon: Custom icon path (overrides default icons if provided) + title: Window title (default: derived from message_type) + font: Font tuple for text styling + wraplength: Text wrapping width in pixels Methods: _get_title(): Returns the default window title based on message type. _load_icons(): Loads icons from system paths or fallback locations. _on_button_click(button_text): Sets result and closes the dialog. - show(): Displays the dialog and waits for user response (returns self.result). + show(): Displays the dialog and waits for user response. + + Example Usage: + + 1. Basic Info Dialog: + >>> MessageDialog( + ... text="This is an information message.") + >>> result = dialog.show() + >>> print("User clicked OK:", result) + + Notes: + My Favorite Example, + for simply information message: + + >>> MessageDialog(text="This is an information message.") + >>> result = MessageDialog(text="This is an information message.").show() + + Example Usage: + + 2. Error Dialog with Custom Command: + >>> def on_retry(): + ... print("User selected Retry") + + >>> dialog = MessageDialog( + ... message_type="error", + ... text="An error occurred during processing.", + ... buttons=["Retry", "Cancel"], + ... commands=[on_retry, None], + ... title="Critical Error" + ... ) + >>> result = dialog.show() + >>> print("User selected Retry:", result) + + Example Usage: + + 3. And a special example for a "open link" button: + Be careful not to forget to import it into the script in which + this dialog is used!!! import webbrowser from functools import partial + + >>> MessageDialog( + ... "info" + ... text="This is an information message.", + ... buttons=["Yes", "Go to Exapmle"], + ... commands=[ + ... None, # Default on "OK" + ... partial(webbrowser.open, "https://exapmle.com"), + ... ], + ... icon="/pathh/to/custom/icon.png", + ... title="Example", + ... ) + + Notes: + - Returns None if "Cancel" was clicked with ≥3 buttons + - Supports keyboard navigation (Left/Right arrows and Enter) + - Dialog automatically centers on screen + - Result is False for window close (X) with 2 buttons + - Font and wraplength parameters enable text styling """ DEFAULT_ICON_PATH = "/usr/share/icons/lx-icons" @@ -191,7 +140,7 @@ class MessageDialog: # Layout frame = ttk.Frame(self.window) - frame.pack(expand=True, fill="both") + frame.pack(expand=True, fill="both", padx=15, pady=8) # Grid-Configuration frame.grid_rowconfigure(0, weight=1) @@ -218,13 +167,12 @@ class MessageDialog: row=0, column=1, padx=(10, 20), - pady=(8, 20), sticky="nsew", ) # Create button frame self.button_frame = ttk.Frame(frame) - self.button_frame.grid(row=1, columnspan=2, pady=(15, 10)) + self.button_frame.grid(row=1, columnspan=2, pady=(8, 10)) for i, btn_text in enumerate(buttons): if commands and len(commands) > i and commands[i] is not None: @@ -243,7 +191,7 @@ class MessageDialog: ) padx_value = 50 if self.icon is not None and len(buttons) == 2 else 10 - btn.pack(side="left" if i == 0 else "right", padx=padx_value, pady=15) + btn.pack(side="left" if i == 0 else "right", padx=padx_value, pady=5) btn.focus_set() if i == 0 else None # Set focus on first button self.buttons_widgets.append(btn) @@ -309,12 +257,12 @@ class MessageDialog: if os.path.exists(icon_paths[key]): self.icons[key] = tk.PhotoImage(file=icon_paths[key]) else: - self.icons[key] = tk.PhotoImage(file=fallback_paths[key]) + if os.path.exists(fallback_paths[key]): + self.icons[key] = tk.PhotoImage(file=fallback_paths[key]) except Exception as e: print(f"Error on load Icon '{[key]}': {e}") self.icons[key] = tk.PhotoImage() print(f"⚠️ No Icon found for '{key}'. Use standard Tkinter icon.") - return self.icons def _get_icon_path(self) -> str: