"""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] )