added versioning, requirements and setup

This commit is contained in:
robert 2026-01-06 16:15:18 +01:00
parent b0c968622e
commit 835ac2e9a6
6 changed files with 97 additions and 12 deletions

1
.gitignore vendored
View file

@ -162,3 +162,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
.DS_Store

View file

@ -1,4 +1,4 @@
# PNG Metadata Editor # PNG Metadata Editor v1.0.0
A graphical tool for viewing and editing metadata in PNG files. A graphical tool for viewing and editing metadata in PNG files.
@ -42,21 +42,42 @@ pip install pillow pngmeta
## Building for Distribution ## Building for Distribution
To create a standalone executable: ### Mac OS (using py2app)
1. First install the required build tools:
```bash
pip install py2app
```
2. Build the application bundle:
```bash
python setup.py py2app
```
3. The resulting .app bundle will be in the `dist/` directory
### Windows (using PyInstaller)
```bash ```bash
pyinstaller --name="PNG Metadata Editor" \ pyinstaller --name="PNG Metadata Editor" \
--windowed \ --windowed \
--onefile \ --onefile \
--icon=AppIcon.icns \ --icon=AppIcon.ico \
png-meta-editor.py png-meta-editor.py
``` ```
The resulting executable will be in the `dist/` directory. ### Linux (using PyInstaller)
```bash
pyinstaller --name="PNG Metadata Editor" \
--windowed \
--onefile \
png-meta-editor.py
```
## License ## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. This project is licensed under the MIT License - see [LICENSE](LICENSE) for details.
## Author ## Author
@ -65,4 +86,4 @@ Robert Tusa
## Version History ## Version History
- 2026-01-05: Initial release - **1.0.0 (2026-01-05)**: Initial release

View file

@ -1,4 +1,3 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk, filedialog, messagebox from tkinter import ttk, filedialog, messagebox
from pathlib import Path from pathlib import Path
@ -6,10 +5,14 @@ import json
from PIL import Image from PIL import Image
from PIL.PngImagePlugin import PngInfo from PIL.PngImagePlugin import PngInfo
# Application metadata
APP_VERSION = "1.0.0"
APP_NAME = "PNG Metadata Editor"
class PNGMetadataEditor: class PNGMetadataEditor:
def __init__(self, root): def __init__(self, root):
self.root = root self.root = root
self.root.title("PNG Metadata Editor") self.root.title(f"{APP_NAME} - No file loaded")
self.root.geometry("900x700") self.root.geometry("900x700")
self.current_file = None self.current_file = None
@ -32,6 +35,7 @@ class PNGMetadataEditor:
ttk.Button(top_frame, text="Open PNG File", command=self.open_file).pack(side=tk.LEFT, padx=5) ttk.Button(top_frame, text="Open PNG File", command=self.open_file).pack(side=tk.LEFT, padx=5)
ttk.Button(top_frame, text="Save Changes", command=self.save_changes).pack(side=tk.LEFT, padx=5) ttk.Button(top_frame, text="Save Changes", command=self.save_changes).pack(side=tk.LEFT, padx=5)
ttk.Button(top_frame, text="About", command=self.show_about).pack(side=tk.RIGHT, padx=5) # New About button
self.file_label = ttk.Label(top_frame, text="No file loaded", foreground="gray") self.file_label = ttk.Label(top_frame, text="No file loaded", foreground="gray")
self.file_label.pack(side=tk.LEFT, padx=20) self.file_label.pack(side=tk.LEFT, padx=20)
@ -52,7 +56,7 @@ class PNGMetadataEditor:
tree_scroll = ttk.Scrollbar(tree_frame) tree_scroll = ttk.Scrollbar(tree_frame)
tree_scroll.pack(side=tk.RIGHT, fill=tk.Y) tree_scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.tree = ttk.Treeview(tree_frame, columns=("Key", "Value"), show="headings", self.tree = ttk.Treeview(tree_frame, columns=("Key", "Value"), show="headings",
yscrollcommand=tree_scroll.set) yscrollcommand=tree_scroll.set)
self.tree.heading("Key", text="Key") self.tree.heading("Key", text="Key")
self.tree.heading("Value", text="Value Preview") self.tree.heading("Value", text="Value Preview")
@ -98,6 +102,19 @@ class PNGMetadataEditor:
self.status_label = ttk.Label(status_frame, text="Ready", padding=(10, 5)) self.status_label = ttk.Label(status_frame, text="Ready", padding=(10, 5))
self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True) self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
def show_about(self):
"""Show application about dialog"""
about_text = f"{APP_NAME} v{APP_VERSION}\n\n" \
"A graphical tool for viewing and editing metadata in PNG files.\n\n" \
"Author: Robert Tusa\n" \
"License: MIT"
messagebox.showinfo(
f"About {APP_NAME}",
about_text,
parent=self.root
)
def set_status(self, message, duration=3000, color=""): def set_status(self, message, duration=3000, color=""):
"""Set status bar message that auto-clears after duration (ms)""" """Set status bar message that auto-clears after duration (ms)"""
# Cancel any existing timer # Cancel any existing timer
@ -126,7 +143,7 @@ class PNGMetadataEditor:
def update_title(self): def update_title(self):
"""Update window title with unsaved indicator""" """Update window title with unsaved indicator"""
base_title = "PNG Metadata Editor" base_title = f"{APP_NAME} v{APP_VERSION}"
if self.current_file: if self.current_file:
filename = Path(self.current_file).name filename = Path(self.current_file).name
if self.has_unsaved_changes: if self.has_unsaved_changes:
@ -243,7 +260,7 @@ class PNGMetadataEditor:
value_scroll = ttk.Scrollbar(text_frame) value_scroll = ttk.Scrollbar(text_frame)
value_scroll.pack(side=tk.RIGHT, fill=tk.Y) value_scroll.pack(side=tk.RIGHT, fill=tk.Y)
value_text = tk.Text(text_frame, wrap=tk.WORD, yscrollcommand=value_scroll.set, value_text = tk.Text(text_frame, wrap=tk.WORD, yscrollcommand=value_scroll.set,
font=("Menlo", 11)) font=("Menlo", 11))
value_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) value_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
value_scroll.config(command=value_text.yview) value_scroll.config(command=value_text.yview)
@ -387,4 +404,4 @@ class PNGMetadataEditor:
if __name__ == "__main__": if __name__ == "__main__":
root = tk.Tk() root = tk.Tk()
app = PNGMetadataEditor(root) app = PNGMetadataEditor(root)
root.mainloop() root.mainloop()

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
pillow>=9.0.0
pngmeta>=1.0.0

41
setup.py Normal file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import sys
from setuptools import setup
# Application metadata
APP_NAME = "PNG Metadata Editor"
APP_VERSION = "1.0.0"
AUTHOR = "Robert Tusa"
DESCRIPTION = "A graphical tool for viewing and editing metadata in PNG files"
# Read the long description from README
with open('README.md', 'r', encoding='utf-8') as f:
long_description = f.read()
setup(
name=APP_NAME,
version=APP_VERSION,
description=DESCRIPTION,
long_description=long_description,
long_description_content_type='text/markdown',
author=AUTHOR,
author_email='robert@tusa.at', # Replace with your email
url='https://git.tusa.at/robert/png-meta-editor', # Replace with your repo
license='MIT',
python_requires='>=3.6',
app=['png-meta-editor.py'], # Your main script
data_files=[('',
['AppIcon.icns', 'version.txt'])], # Include these files
options={
'py2app': {
'argv_emulation': True,
'iconfile': 'AppIcon.icns',
'plist': {
'CFBundleName': APP_NAME,
'CFBundleShortVersionString': APP_VERSION,
'CFBundleVersion': APP_VERSION,
},
},
},
setup_requires=['py2app'],
)

3
version.txt Normal file
View file

@ -0,0 +1,3 @@
1.0.0
FileVersion 1, 0, 0, 0
ProductVersion 1.0.0