Update Documentation

robert 2026-01-06 16:43:07 +01:00
parent f05beea06f
commit 7d5b1565e2

@ -4,9 +4,9 @@
1. [Overview](#overview) 1. [Overview](#overview)
2. [Features](#features) 2. [Features](#features)
3. [Code Structure](#code-structure) 3. [Code Structure](#code-structure)
4. [Key Components](#key-components) 4. [Class Reference](#class-reference)
5. [Data Flow](#data-flow) 5. [Function Documentation](#function-documentation)
6. [API Reference](#api-reference) 6. [Data Flow](#data-flow)
7. [Usage Examples](#usage-examples) 7. [Usage Examples](#usage-examples)
8. [Troubleshooting](#troubleshooting) 8. [Troubleshooting](#troubleshooting)
@ -32,6 +32,7 @@ PNG Metadata Editor is a graphical application built with Python and Tkinter tha
``` ```
png-meta-editor.py png-meta-editor.py
├── Constants (APP_VERSION, APP_NAME)
├── PNGMetadataEditor (Main Class) ├── PNGMetadataEditor (Main Class)
│ ├── __init__() - Initialization │ ├── __init__() - Initialization
│ ├── setup_ui() - UI Construction │ ├── setup_ui() - UI Construction
@ -44,61 +45,34 @@ png-meta-editor.py
└── mark_as_modified() └── mark_as_modified()
``` ```
## Key Components ## Class Reference
### PNGMetadataEditor Class
### Main Application Class
```python ```python
class PNGMetadataEditor: class PNGMetadataEditor:
def __init__(self, root): def __init__(self, root):
# Initialize application state # Initialize application state
self.current_file = None self.current_file = None # Currently loaded PNG file path
self.metadata_dict = {} self.metadata_dict = {} # Dictionary storing all metadata fields
self.has_unsaved_changes = False self.has_unsaved_changes = False # Track unsaved modifications
self.status_timer = None # Timer for status messages
``` ```
### UI Components
- **Treeview**: Displays metadata keys with truncated values
- **Detail Text**: Shows full value of selected metadata
- **Status Bar**: Provides feedback messages
- **Dialogs**: Modal windows for adding/editing fields
### Data Handling
```python
def open_file(self):
"""Load PNG file and extract metadata"""
img = Image.open(filepath)
self.metadata_dict = dict(img.text) # Extract all text chunks
```
## Data Flow
1. **File Opening**:
- User selects PNG file → `open_file()` called
- PIL extracts text chunks → stored in `metadata_dict`
- UI refreshed with new data
2. **Editing Process**:
- User selects field → `on_selection_change()` updates detail view
- Edit initiated → `edit_entry()` opens dialog
- Changes saved → `mark_as_modified()` updates state
3. **Saving**:
- User clicks Save → `save_changes()` called
- New PngInfo object created with updated metadata
- File saved with `img.save()` using new metadata
## API Reference
### Public Methods ### Public Methods
| Method | Description | | Method | Description |
|--------|-------------| |--------|-------------|
| `open_file()` | Loads PNG file and extracts metadata | | `open_file()` | Loads PNG file and extracts metadata |
| `save_changes()` | Saves current metadata to file | | `save_changes()` | Saves current metadata to file |
| `add_field()` | Opens dialog to add new metadata field | | `add_field()` | Opens dialog to add new metadata field |
| `edit_entry()` | Opens dialog to edit selected field | | `edit_entry(event=None)` | Opens dialog to edit selected field |
| `delete_field()` | Removes selected metadata field | | `delete_field()` | Removes selected metadata field |
| `copy_value()` | Copies selected metadata value to clipboard |
| `show_about()` | Displays application about dialog |
### Helper Methods ### Helper Methods
```python ```python
def format_value_for_display(self, value): def format_value_for_display(self, value):
"""Try to parse as JSON for pretty printing""" """Try to parse as JSON for pretty printing"""
@ -110,8 +84,113 @@ def format_value_for_display(self, value):
def truncate_value(self, value, max_length=80): def truncate_value(self, value, max_length=80):
"""Shorten long values for tree display""" """Shorten long values for tree display"""
return str(value)[:max_length] + "..." if len(str(value)) > max_length else str(value) return str(value)[:max_length] + "..." if len(str(value)) > max_length else str(value)
def mark_as_modified(self):
"""Mark the document as having unsaved changes"""
if not self.has_unsaved_changes:
self.has_unsaved_changes = True
self.update_title()
self.changes_label.config(text="Unsaved changes")
``` ```
## Function Documentation
### Core Functions
1. **`open_file()`**
- Opens a file dialog to select PNG file
- Extracts text chunks using PIL's `Image.text` attribute
- Populates `metadata_dict` with key-value pairs
- Refreshes UI to display new metadata
2. **`save_changes()`**
- Creates new `PngInfo` object with current metadata
- Saves image with updated metadata using PIL's `img.save()`
- Marks changes as saved and updates UI state
3. **`refresh_tree()`**
- Clears existing tree view items
- Repopulates with current metadata from `metadata_dict`
- Truncates long values for display in tree
4. **`on_selection_change(event)`**
- Updates detail view when selection changes
- Formats selected value for display (JSON pretty-printing)
- Handles both JSON and plain text values
### UI Management Functions
1. **`set_status(message, duration=3000, color="")`**
- Displays temporary message in status bar
- Automatically clears after specified duration (ms)
- Supports colored messages for different status types
2. **`update_title()`**
- Updates window title based on current state
- Shows filename when file is loaded
- Adds asterisk (*) for unsaved changes
3. **`show_about()`**
- Displays application information dialog
- Shows version, description, author, and license
- Uses `messagebox.showinfo()` for standard dialog
### Data Handling Functions
1. **`format_value_for_display(value)`**
- Attempts to parse value as JSON
- Returns pretty-printed JSON if successful
- Falls back to string representation otherwise
2. **`truncate_value(value, max_length=80)`**
- Shortens long values for tree display
- Adds ellipsis (...) to truncated values
- Preserves full value in detail view
3. **`mark_as_modified()`**
- Sets unsaved changes flag
- Updates UI indicators (title, label)
- Prevents duplicate change notifications
## Data Flow
1. **File Opening**:
```mermaid
sequenceDiagram
User->>App: Click "Open PNG File"
App->>FileDialog: Show open dialog
User->>App: Select PNG file
App->>PIL: Image.open(filepath)
PIL->>App: Extract text chunks
App->>metadata_dict: Store key-value pairs
App->>UI: Refresh tree and detail view
```
2. **Editing Process**:
```mermaid
sequenceDiagram
User->>App: Select field in tree
App->>on_selection_change: Update detail view
User->>App: Click "Edit Field"
App->>Dialog: Show edit dialog
User->>App: Modify value
User->>App: Click "Save"
App->>metadata_dict: Update value
App->>mark_as_modified: Set unsaved flag
App->>UI: Refresh tree view
```
3. **Saving**:
```mermaid
sequenceDiagram
User->>App: Click "Save Changes"
App->>PIL: Image.open(current_file)
App->>PngInfo: Create new metadata object
App->>PIL: img.save(pnginfo=metadata)
App->>mark_as_saved: Clear unsaved flag
App->>UI: Update status and title
```
## Usage Examples ## Usage Examples
### Basic Workflow ### Basic Workflow
@ -120,13 +199,13 @@ def truncate_value(self, value, max_length=80):
root = tk.Tk() root = tk.Tk()
app = PNGMetadataEditor(root) app = PNGMetadataEditor(root)
# Open a file (simulated) # Open a file programmatically (simulated)
app.current_file = "example.png" app.current_file = "example.png"
img = Image.open("example.png") img = Image.open("example.png")
app.metadata_dict = dict(img.text) app.metadata_dict = dict(img.text)
app.refresh_tree() app.refresh_tree()
# Edit a field # Edit a field programmatically
app.edit_entry() # Would normally be triggered by UI event app.edit_entry() # Would normally be triggered by UI event
# Save changes # Save changes