pyPhotoAlbum/pyPhotoAlbum/EMBEDDED_TEMPLATES.md
Duncan Tourolle a7558e3c39
All checks were successful
Python CI / test (push) Successful in 1m11s
Lint / lint (push) Successful in 1m9s
Tests / test (3.10) (push) Successful in 55s
Tests / test (3.11) (push) Successful in 56s
Tests / test (3.9) (push) Successful in 53s
updated tests and installer
2025-11-11 13:21:35 +01:00

270 lines
7.5 KiB
Markdown

# Embedded Templates Feature
## Overview
The embedded templates feature allows templates to be stored within project files (.ppz) so they travel with the document. When loading projects, embedded templates take priority over local filesystem templates, ensuring projects can be opened on any machine without missing custom templates.
## Key Benefits
**Portability**: Templates travel with project files
**Self-contained**: No dependency on local template files
**Priority**: Embedded templates override filesystem templates
**Automatic**: Templates are auto-embedded when used
**Backward Compatible**: Projects without embedded templates work as before
## How It Works
### Template Priority Order
When loading a template by name, the system checks in this order:
1. **Embedded templates** in the current project (highest priority)
2. **User templates** in `~/.pyphotoalbum/templates/`
3. **Built-in templates** in `pyPhotoAlbum/templates/`
### Automatic Embedding
Templates are automatically embedded in projects when:
- Applying a template to a page with `apply_template_to_page()`
- Creating a new page from a template with `create_page_from_template()`
You can disable auto-embedding by passing `auto_embed=False` to these methods.
### Template Naming
Templates are listed with prefixes indicating their source:
- `[Embedded] Template Name` - Embedded in current project
- `[Built-in] Template Name` - Built-in template
- `Template Name` - User template from filesystem
## Usage Examples
### Basic Usage
```python
from pyPhotoAlbum.project import Project, Page
from pyPhotoAlbum.template_manager import TemplateManager, Template
# Create a project
project = Project(name="My Album")
# Create template manager with project
template_manager = TemplateManager(project=project)
# Create a page from a template (auto-embeds by default)
template = template_manager.load_template("Grid_2x2")
page = template_manager.create_page_from_template(template, page_number=1)
project.add_page(page)
# The template is now embedded in the project!
print(project.embedded_templates.keys())
# Output: dict_keys(['Grid_2x2'])
```
### Manual Embedding
```python
# Manually embed a template
template = Template(name="Custom Layout")
# ... configure template ...
template_manager.embed_template(template)
```
### Saving Templates
```python
# Save to filesystem (default)
template_manager.save_template(template)
# Or embed in project instead
template_manager.save_template(template, embed_in_project=True)
```
### Listing Templates
```python
# List all available templates
templates = template_manager.list_templates()
# Returns: ['[Embedded] Custom', '[Built-in] Grid_2x2', 'MyUserTemplate', ...]
```
### Loading Templates
```python
# Load embedded template (priority)
template = template_manager.load_template("Custom")
# Load with explicit prefix
template = template_manager.load_template("[Embedded] Custom")
template = template_manager.load_template("[Built-in] Grid_2x2")
```
### Disabling Auto-Embed
```python
# Don't auto-embed when applying template
template_manager.apply_template_to_page(
template,
page,
auto_embed=False
)
# Don't auto-embed when creating page
page = template_manager.create_page_from_template(
template,
page_number=1,
auto_embed=False
)
```
## Project Serialization
Embedded templates are automatically serialized when saving projects:
```python
# Save project to ZIP file
from pyPhotoAlbum.project_serializer import save_to_zip
save_to_zip(project, "myalbum.ppz")
# Embedded templates are included in the .ppz file
```
When loading:
```python
from pyPhotoAlbum.project_serializer import load_from_zip
project, error = load_from_zip("myalbum.ppz")
# Embedded templates are automatically restored
# Create template manager to access them
template_manager = TemplateManager(project=project)
templates = template_manager.list_templates()
```
## Data Structure
Embedded templates are stored in the project's `embedded_templates` dictionary:
```python
project.embedded_templates = {
"Template Name": {
"name": "Template Name",
"description": "Template description",
"page_size_mm": [210, 297],
"elements": [
{
"type": "placeholder",
"position": [10, 10],
"size": [100, 100],
# ... more element data
},
# ... more elements
]
},
# ... more templates
}
```
## API Reference
### TemplateManager
#### Constructor
```python
TemplateManager(project=None)
```
Create a template manager. Pass a `Project` instance to enable embedded template support.
#### Methods
**`embed_template(template: Template)`**
Manually embed a template in the project.
**`load_template(name: str) -> Template`**
Load a template by name. Checks embedded templates first, then filesystem.
**`list_templates() -> List[str]`**
List all available templates with source prefixes.
**`save_template(template: Template, embed_in_project: bool = False)`**
Save template to filesystem or embed in project.
**`delete_template(name: str)`**
Delete a template (works with embedded and user templates).
**`apply_template_to_page(template, page, mode="replace", scale_mode="proportional", margin_percent=2.5, auto_embed=True)`**
Apply template to a page. Auto-embeds by default.
**`create_page_from_template(template, page_number=1, target_size_mm=None, scale_mode="proportional", auto_embed=True) -> Page`**
Create a new page from template. Auto-embeds by default.
### Project
#### Attributes
**`embedded_templates: Dict[str, Dict[str, Any]]`**
Dictionary storing embedded template definitions.
## Migration Guide
### Existing Projects
Existing projects without embedded templates will continue to work normally. Templates will be auto-embedded when:
1. You apply a template to a page
2. You create a new page from a template
3. You manually embed a template
### Sharing Projects
When sharing projects:
1. Templates are automatically embedded when used
2. Save the project to .ppz format
3. Share the .ppz file
4. Recipients can open the project and all templates are available
No manual steps required!
## Best Practices
1. **Let auto-embed work**: The default behavior of auto-embedding templates ensures portability
2. **Save projects after using templates**: Embedded templates are saved with the project
3. **Use descriptive template names**: This helps identify templates in the list
4. **Test on different machines**: Verify templates work when opening projects elsewhere
## Troubleshooting
**Q: Why isn't my template showing as embedded?**
A: Ensure you're creating the TemplateManager with the project:
```python
template_manager = TemplateManager(project=project)
```
**Q: Can I convert filesystem templates to embedded?**
A: Yes, just load and embed them:
```python
template = template_manager.load_template("MyTemplate")
template_manager.embed_template(template)
```
**Q: What happens if I have templates with the same name?**
A: Embedded templates take priority over filesystem templates with the same name.
**Q: Can I remove embedded templates?**
A: Yes, use:
```python
template_manager.delete_template("[Embedded] Template Name")
```
## Implementation Details
- Templates are stored as JSON in the project's `embedded_templates` dictionary
- Serialization includes embedded templates in the project.json within .ppz files
- Template manager checks embedded templates first when loading
- Auto-embed only happens if the template isn't already embedded
- All template operations preserve element properties (position, size, rotation, etc.)