From 6df899507e178d252a134796eceea72f66157c8d Mon Sep 17 00:00:00 2001 From: Thomas Mello Date: Wed, 17 Sep 2025 03:28:17 +0300 Subject: [PATCH 1/2] feat(gui): add move markup setting --- src/clipper/argparser.py | 6 +++ src/clipper/gui/engine.py | 42 +++++++++++++++++++ src/clipper/gui/settings_manager.py | 1 + .../src/components/SettingsPanel.vue | 8 ++++ src/gui-frontend/src/types/settings.ts | 1 + 5 files changed, 58 insertions(+) diff --git a/src/clipper/argparser.py b/src/clipper/argparser.py index 5668f31..544ba81 100644 --- a/src/clipper/argparser.py +++ b/src/clipper/argparser.py @@ -678,6 +678,12 @@ def getSettingsSchema() -> Dict[str, Any]: "default": 5000, "cli_args": ["--cache-max-size-mb"], }, + "move_markup_on_success": { + "type": "boolean", + "description": "Move original markup JSON into output folder after successful processing", + "default": False, + "cli_args": ["--move-markup-on-success"], + }, # Color Grading / UI tuning (GUI only for now) "lgg_projection_gain": { "type": "number", diff --git a/src/clipper/gui/engine.py b/src/clipper/gui/engine.py index 2b2c374..998b078 100644 --- a/src/clipper/gui/engine.py +++ b/src/clipper/gui/engine.py @@ -175,6 +175,47 @@ def process_files(self, markup_path: Optional[str] = None, video_path: Optional[ clip_maker.previewClips(self.cs) message = "Preview completed successfully" + # After successful processing, optionally move the original markup JSON + # into the output folder if the user has enabled the setting and we + # actually processed from a file (not in-memory data). This helps keep + # related artifacts together for archival/organization. + try: + if ( + message.startswith("Clips") # only on real generation + and markup_path # only if we have a source file path + and gui_settings.get("move_markup_on_success") + ): + src_path = Path(markup_path) + if src_path.exists(): + dest_dir = Path(self.cs.clipper_paths.clipsPath) + dest_dir.mkdir(parents=True, exist_ok=True) + dest_path = dest_dir / src_path.name + # Use replace to overwrite if it already exists + if dest_path.resolve() == src_path.resolve(): + # Already in the output folder; nothing to do + self.logger.debug( + "Markup file already located in output directory; skipping move" + ) + else: + self.logger.debug( + "Moving markup JSON '%s' -> '%s'", src_path, dest_path + ) + try: + # Attempt an atomic-ish move; fallback to copy+unlink if needed + src_path.replace(dest_path) + except Exception: + import shutil + shutil.copy2(src_path, dest_path) + src_path.unlink(missing_ok=True) # type: ignore[arg-type] + self.logger.info( + "Moved markup JSON to output directory: %s", dest_path + ) + except Exception as move_err: + # Non-fatal: we still succeeded overall. + self.logger.warning( + "Failed to move markup JSON to output directory: %s", move_err + ) + # Update persistent cache after processing (preserve RIFE loaded state) self._update_persistent_cache() @@ -297,6 +338,7 @@ def _apply_gui_settings_to_clipper_state(self, gui_settings: Dict[str, Any]) -> # Other settings 'preview': 'preview', 'notify_on_completion': 'notifyOnCompletion', + 'move_markup_on_success': 'moveMarkupOnSuccess', # GUI-only behavioral setting # yt-dlp settings 'ytdl_location': 'ytdlLocation', diff --git a/src/clipper/gui/settings_manager.py b/src/clipper/gui/settings_manager.py index a2e7a2d..3940958 100644 --- a/src/clipper/gui/settings_manager.py +++ b/src/clipper/gui/settings_manager.py @@ -69,6 +69,7 @@ class GeneralSettings: # === COLOR GRADING / UI TUNING === # Multiplier applied to LGG color wheel hue projection (was hardcoded 1.5) lgg_projection_gain: float = 1.5 + move_markup_on_success: bool = False # === WINDOW OPTIONS === window_width: int = 1000 # Default window width diff --git a/src/gui-frontend/src/components/SettingsPanel.vue b/src/gui-frontend/src/components/SettingsPanel.vue index 0394962..67ab6aa 100644 --- a/src/gui-frontend/src/components/SettingsPanel.vue +++ b/src/gui-frontend/src/components/SettingsPanel.vue @@ -384,6 +384,14 @@ Intensity multiplier for LGG color wheel hue projection. Lower = gentler isolation; higher = stronger channel separation. + + + After successful processing, move the original markup JSON into the output clips folder for archival. + diff --git a/src/gui-frontend/src/types/settings.ts b/src/gui-frontend/src/types/settings.ts index 9045455..d73cf78 100644 --- a/src/gui-frontend/src/types/settings.ts +++ b/src/gui-frontend/src/types/settings.ts @@ -55,6 +55,7 @@ export interface GeneralSettings { // === COLOR GRADING / UI TUNING === lgg_projection_gain: number + move_markup_on_success: boolean } export interface VideoSpecificSettings { From 6eac9823d2f2c1adf794985e1a439889aee85af3 Mon Sep 17 00:00:00 2001 From: Thomas Mello Date: Wed, 17 Sep 2025 03:30:42 +0300 Subject: [PATCH 2/2] style: lint --- src/clipper/gui/engine.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clipper/gui/engine.py b/src/clipper/gui/engine.py index 998b078..c0c9ed7 100644 --- a/src/clipper/gui/engine.py +++ b/src/clipper/gui/engine.py @@ -194,11 +194,11 @@ def process_files(self, markup_path: Optional[str] = None, video_path: Optional[ if dest_path.resolve() == src_path.resolve(): # Already in the output folder; nothing to do self.logger.debug( - "Markup file already located in output directory; skipping move" + "Markup file already located in output directory; skipping move", ) else: self.logger.debug( - "Moving markup JSON '%s' -> '%s'", src_path, dest_path + "Moving markup JSON '%s' -> '%s'", src_path, dest_path, ) try: # Attempt an atomic-ish move; fallback to copy+unlink if needed @@ -208,12 +208,12 @@ def process_files(self, markup_path: Optional[str] = None, video_path: Optional[ shutil.copy2(src_path, dest_path) src_path.unlink(missing_ok=True) # type: ignore[arg-type] self.logger.info( - "Moved markup JSON to output directory: %s", dest_path + "Moved markup JSON to output directory: %s", dest_path, ) except Exception as move_err: # Non-fatal: we still succeeded overall. self.logger.warning( - "Failed to move markup JSON to output directory: %s", move_err + "Failed to move markup JSON to output directory: %s", move_err, ) # Update persistent cache after processing (preserve RIFE loaded state)