113 lines
3.2 KiB
Python
113 lines
3.2 KiB
Python
"""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]
|
|
)
|