Add welcome wizard, desktop entry, and Nautilus extension

First-run welcome dialog with skill level and output location setup.
Desktop entry file for GNOME app launcher integration.
Nautilus Python extension with dynamic 'Process with Pixstrip' submenu
that reads both built-in and user presets.
This commit is contained in:
2026-03-06 11:18:28 +02:00
parent e1c2e11165
commit eb16149824
4 changed files with 321 additions and 0 deletions

112
data/nautilus-pixstrip.py Normal file
View File

@@ -0,0 +1,112 @@
"""Nautilus extension for Pixstrip - adds 'Process with Pixstrip' submenu to image context menu."""
import os
import subprocess
import json
from gi.repository import Nautilus, GObject
SUPPORTED_MIMETYPES = [
"image/jpeg",
"image/png",
"image/webp",
"image/avif",
"image/gif",
"image/tiff",
"image/bmp",
]
def get_presets():
"""Load built-in and user presets."""
presets = [
"Blog Photos",
"Social Media",
"Web Optimization",
"Email Friendly",
"Privacy Clean",
"Photographer Export",
"Archive Compress",
"Fediverse Ready",
]
# Load user presets
config_dir = os.path.expanduser("~/.config/pixstrip/presets")
if os.path.isdir(config_dir):
for filename in sorted(os.listdir(config_dir)):
if filename.endswith(".json"):
filepath = os.path.join(config_dir, filename)
try:
with open(filepath) as f:
data = json.load(f)
name = data.get("name", "")
if name and name not in presets:
presets.append(name)
except (json.JSONDecodeError, IOError):
pass
return presets
class PixstripMenuProvider(GObject.GObject, Nautilus.MenuProvider):
def get_file_items(self, files):
# Only show for image files
if not files:
return []
for f in files:
if f.get_mime_type() not in SUPPORTED_MIMETYPES:
return []
items = []
# Main menu item
top_item = Nautilus.MenuItem(
name="PixstripMenuProvider::process",
label="Process with Pixstrip",
tip="Open images in Pixstrip for batch processing",
)
submenu = Nautilus.Menu()
top_item.set_submenu(submenu)
# Open in Pixstrip
open_item = Nautilus.MenuItem(
name="PixstripMenuProvider::open",
label="Open in Pixstrip...",
tip="Open the Pixstrip wizard with these images",
)
open_item.connect("activate", self._on_open, files)
submenu.append_item(open_item)
# Separator via disabled item
sep = Nautilus.MenuItem(
name="PixstripMenuProvider::sep1",
label="---",
sensitive=False,
)
submenu.append_item(sep)
# Preset items
for preset in get_presets():
safe_name = preset.replace(" ", "_").lower()
item = Nautilus.MenuItem(
name=f"PixstripMenuProvider::preset_{safe_name}",
label=preset,
tip=f"Process with {preset} preset",
)
item.connect("activate", self._on_preset, files, preset)
submenu.append_item(item)
items.append(top_item)
return items
def _on_open(self, menu, files):
paths = [f.get_location().get_path() for f in files]
subprocess.Popen(["pixstrip-gtk"] + paths)
def _on_preset(self, menu, files, preset):
paths = [f.get_location().get_path() for f in files]
subprocess.Popen(
["pixstrip-cli", "process"] + paths + ["--preset", preset]
)