@@ -3,8 +3,11 @@ use super::{
33 segment:: refresh_affected_segments,
44 track:: get_selected_segment_indices,
55} ;
6- use crate :: { global_store, slint_generatedAppWindow:: AppWindow } ;
7- use slint:: ComponentHandle ;
6+ use crate :: { global_store, global_ve_filter, slint_generatedAppWindow:: {
7+ AppWindow , BrightnessDetail as UIBrightnessDetail , PresetFilter as UIPresetFilter ,
8+ SegmentFilter as UISegmentFilter ,
9+ } } ;
10+ use slint:: { ComponentHandle , Model , SharedString , VecModel } ;
811use video_editor:: filters:: {
912 audio:: {
1013 CompressorFilter , FadeInFilter as AudioFadeInFilter , FadeOutFilter as AudioFadeOutFilter ,
@@ -45,12 +48,6 @@ use video_editor::{
4548 tracks:: track:: Track ,
4649} ;
4750
48- macro_rules! global_ve_filter {
49- ( $ui: expr) => {
50- $ui. global:: <crate :: slint_generatedAppWindow:: VEFilter >( )
51- } ;
52- }
53-
5451#[ macro_export]
5552macro_rules! ve_filter_cb {
5653 ( $callback_name: ident, $ui: expr, $( $arg: ident) ,* ) => {
@@ -78,26 +75,18 @@ macro_rules! ve_filter_cb {
7875}
7976
8077pub fn init ( ui : & AppWindow ) {
81- // ve_filter_cb!(up_filter, ui, index);
82- // ve_filter_cb!(down_filter, ui, index);
83- // ve_filter_cb!(remove_filter, ui, index);
84- // ve_filter_cb!(toggle_filter, ui, index);
85- // ve_filter_cb!(copy_filter, ui, index);
86- // ve_filter_cb!(add_filter, ui, filter_name);
87-
88- // Register add-filter callback
89- let ui_weak = ui. as_weak ( ) ;
90- global_ve_filter ! ( ui) . on_add_filter ( move |filter_name| {
91- let ui = ui_weak. unwrap ( ) ;
92- video_editor_filter_add ( & ui, filter_name. to_string ( ) ) ;
93- } ) ;
94-
95- // Register toggle-filter callback
96- let ui_weak = ui. as_weak ( ) ;
97- global_ve_filter ! ( ui) . on_toggle_filter ( move |index| {
98- let ui = ui_weak. unwrap ( ) ;
99- video_editor_filter_toggle ( & ui, index) ;
100- } ) ;
78+ ve_filter_cb ! ( up_filter, ui, index) ;
79+ ve_filter_cb ! ( down_filter, ui, index) ;
80+ ve_filter_cb ! ( remove_filter, ui, index) ;
81+ ve_filter_cb ! ( toggle_filter, ui, index) ;
82+ ve_filter_cb ! ( copy_filter, ui, index) ;
83+ ve_filter_cb ! ( add_filter, ui, filter_name) ;
84+ ve_filter_cb ! ( create_preset_filter, ui, name) ;
85+ ve_filter_cb ! ( add_preset_filter, ui, filter) ;
86+ ve_filter_cb ! ( add_cache_preset_filter, ui, filter) ;
87+ ve_filter_cb ! ( remove_cache_preset_filter, ui, filter) ;
88+ ve_filter_cb ! ( from_brightness_json, ui, json) ;
89+ ve_filter_cb ! ( modify_brightness_filter, ui, index, config) ;
10190}
10291
10392/// Get the current filter type based on the current track type
@@ -125,7 +114,7 @@ fn get_current_filter_type(ui: &AppWindow) -> FilterType {
125114}
126115
127116/// Move filter up in order
128- pub fn filter_up ( ui : & AppWindow , index : i32 ) {
117+ pub fn up_filter ( ui : & AppWindow , index : i32 ) {
129118 let filter_index = index as usize ;
130119 let filter_type = get_current_filter_type ( ui) ;
131120
@@ -169,7 +158,7 @@ pub fn filter_up(ui: &AppWindow, index: i32) {
169158}
170159
171160/// Move filter down in order
172- pub fn filter_down ( ui : & AppWindow , index : i32 ) {
161+ pub fn down_filter ( ui : & AppWindow , index : i32 ) {
173162 let filter_index = index as usize ;
174163 let filter_type = get_current_filter_type ( ui) ;
175164
@@ -209,7 +198,7 @@ pub fn filter_down(ui: &AppWindow, index: i32) {
209198}
210199
211200/// Remove a filter from selected segments
212- pub fn filter_remove ( ui : & AppWindow , index : i32 ) {
201+ pub fn remove_filter ( ui : & AppWindow , index : i32 ) {
213202 let filter_index = index as usize ;
214203 let filter_type = get_current_filter_type ( ui) ;
215204
@@ -265,7 +254,7 @@ pub fn filter_remove(ui: &AppWindow, index: i32) {
265254}
266255
267256/// Toggle filter enabled state
268- fn video_editor_filter_toggle ( ui : & AppWindow , index : i32 ) {
257+ fn toggle_filter ( ui : & AppWindow , index : i32 ) {
269258 let filter_index = index as usize ;
270259 let filter_type = get_current_filter_type ( ui) ;
271260
@@ -300,7 +289,7 @@ fn video_editor_filter_toggle(ui: &AppWindow, index: i32) {
300289}
301290
302291/// Copy filter to clipboard (for later pasting)
303- pub fn filter_copy ( ui : & AppWindow , index : i32 ) {
292+ pub fn copy_filter ( ui : & AppWindow , index : i32 ) {
304293 let filter_index = index as usize ;
305294 let filter_type = get_current_filter_type ( ui) ;
306295
@@ -348,7 +337,8 @@ pub fn filter_copy(ui: &AppWindow, index: i32) {
348337}
349338
350339/// Add a filter to selected segments
351- fn video_editor_filter_add ( ui : & AppWindow , filter_name : String ) {
340+ fn add_filter ( ui : & AppWindow , filter_name : SharedString ) {
341+ let filter_name = filter_name. to_string ( ) ;
352342 let filter_type = get_current_filter_type ( ui) ;
353343 let selected_segments = get_selected_segment_indices ( ui) ;
354344
@@ -384,6 +374,139 @@ fn video_editor_filter_add(ui: &AppWindow, filter_name: String) {
384374 }
385375}
386376
377+ /// Create a preset filter from cached filters
378+ fn create_preset_filter ( ui : & AppWindow , name : slint:: SharedString ) {
379+ let cache_filters = global_ve_filter ! ( ui) . get_cache_preset_filters ( ) ;
380+
381+ if cache_filters. row_count ( ) == 0 {
382+ crate :: toast_warn!( ui, "No filters selected for preset" ) ;
383+ return ;
384+ }
385+
386+ // Collect all SegmentFilters from the cached PresetFilters
387+ let mut all_filters: Vec < UISegmentFilter > = Vec :: new ( ) ;
388+ for preset in cache_filters. iter ( ) {
389+ for seg_filter in preset. filters . iter ( ) {
390+ all_filters. push ( seg_filter) ;
391+ }
392+ }
393+
394+ let preset_filter = UIPresetFilter {
395+ name,
396+ filters : slint:: ModelRc :: from ( std:: rc:: Rc :: new ( VecModel :: from ( all_filters) ) ) ,
397+ } ;
398+
399+ // Add to video preset filters by default (can be extended for other types)
400+ let current_filters = global_ve_filter ! ( ui) . get_video_preset_filters ( ) ;
401+ let mut new_filters: Vec < UIPresetFilter > = current_filters. iter ( ) . collect ( ) ;
402+ new_filters. push ( preset_filter) ;
403+
404+ global_ve_filter ! ( ui) . set_video_preset_filters ( slint:: ModelRc :: from ( std:: rc:: Rc :: new ( VecModel :: from ( new_filters) ) ) ) ;
405+
406+ // Clear cache after creating preset
407+ global_ve_filter ! ( ui) . set_cache_preset_filters ( slint:: ModelRc :: default ( ) ) ;
408+
409+ crate :: toast_success!( ui, "Preset filter created" ) ;
410+ }
411+
412+ /// Add a preset filter to selected segments
413+ fn add_preset_filter ( ui : & AppWindow , filter : UIPresetFilter ) {
414+ let filter_type = get_current_filter_type ( ui) ;
415+ let selected_segments = get_selected_segment_indices ( ui) ;
416+
417+ if selected_segments. is_empty ( ) {
418+ crate :: toast_warn!( ui, "No segments selected" ) ;
419+ return ;
420+ }
421+
422+ let mut batch_command = BatchCommand :: new ( format ! ( "Add preset filter: {}" , filter. name) ) ;
423+
424+ for segment_filter in filter. filters . iter ( ) {
425+ let filter_name = segment_filter. name . to_string ( ) ;
426+
427+ for ( track_idx, seg_idx) in & selected_segments {
428+ let command =
429+ create_filter_command ( * track_idx, * seg_idx, filter_type. clone ( ) , & filter_name) ;
430+ if let Some ( cmd) = command {
431+ batch_command. add_command ( cmd) ;
432+ }
433+ }
434+ }
435+
436+ let result = with_history_manager ( |state| {
437+ state
438+ . history_manager
439+ . execute ( & mut state. tracks_manager , Box :: new ( batch_command) )
440+ } ) ;
441+
442+ match result {
443+ Ok ( execute_result) => {
444+ sync_manager_to_ui ( ui) ;
445+ refresh_affected_segments ( ui, execute_result. affected_segments ) ;
446+ refresh_preview ( ui) ;
447+ crate :: toast_success!( ui, format!( "Added preset filter: {}" , filter. name) ) ;
448+ }
449+ Err ( e) => crate :: toast_warn!( ui, format!( "Failed to add preset filter: {}" , e) ) ,
450+ }
451+ }
452+
453+ /// Add filter to cache for preset creation
454+ fn add_cache_preset_filter ( ui : & AppWindow , filter : UISegmentFilter ) {
455+ // Wrap the SegmentFilter in a PresetFilter for storage in cache-preset-filters
456+ let preset = UIPresetFilter {
457+ name : slint:: SharedString :: new ( ) ,
458+ filters : slint:: ModelRc :: from ( std:: rc:: Rc :: new ( VecModel :: from ( vec ! [ filter] ) ) ) ,
459+ } ;
460+
461+ let current_cache = global_ve_filter ! ( ui) . get_cache_preset_filters ( ) ;
462+ let mut new_cache: Vec < UIPresetFilter > = current_cache. iter ( ) . collect ( ) ;
463+ new_cache. push ( preset) ;
464+ global_ve_filter ! ( ui) . set_cache_preset_filters ( slint:: ModelRc :: from ( std:: rc:: Rc :: new ( VecModel :: from ( new_cache) ) ) ) ;
465+ }
466+
467+ /// Remove filter from cache for preset creation
468+ fn remove_cache_preset_filter ( ui : & AppWindow , filter : UISegmentFilter ) {
469+ let current_cache = global_ve_filter ! ( ui) . get_cache_preset_filters ( ) ;
470+ // Remove PresetFilters that contain a matching SegmentFilter
471+ let new_cache: Vec < UIPresetFilter > = current_cache
472+ . iter ( )
473+ . filter ( |preset| {
474+ // Keep the preset if none of its filters match
475+ preset. filters . iter ( ) . all ( |f| f. name != filter. name || f. detail != filter. detail )
476+ } )
477+ . collect ( ) ;
478+ global_ve_filter ! ( ui) . set_cache_preset_filters ( slint:: ModelRc :: from ( std:: rc:: Rc :: new ( VecModel :: from ( new_cache) ) ) ) ;
479+ }
480+
481+ /// Deserialize brightness config from JSON (pure callback)
482+ fn from_brightness_json ( _ui : & AppWindow , json : slint:: SharedString ) -> UIBrightnessDetail {
483+ // Parse JSON and return BrightnessDetail
484+ match serde_json:: from_str :: < serde_json:: Value > ( json. as_str ( ) ) {
485+ Ok ( value) => {
486+ let adjustment = value
487+ . get ( "adjustment" )
488+ . and_then ( |v| v. as_f64 ( ) )
489+ . unwrap_or ( 0.0 ) as f32 ;
490+ UIBrightnessDetail { adjustment }
491+ }
492+ Err ( _) => UIBrightnessDetail { adjustment : 0.0 } ,
493+ }
494+ }
495+
496+ /// Modify brightness filter configuration
497+ fn modify_brightness_filter ( ui : & AppWindow , index : i32 , config : UIBrightnessDetail ) {
498+ // TODO: Implement proper filter modification through command pattern
499+ // This requires adding as_any_mut() to the VideoFilter trait or implementing
500+ // a ModifyFilterCommand in the video-editor library.
501+ log:: warn!(
502+ "modify_brightness_filter called with index={}, adjustment={}" ,
503+ index,
504+ config. adjustment
505+ ) ;
506+ // Refresh UI to reflect current state
507+ sync_manager_to_ui ( ui) ;
508+ }
509+
387510/// Get available video filter names
388511#[ allow( dead_code) ]
389512fn video_editor_filter_get_video_filters ( _ui : & AppWindow , _flag : bool ) -> Vec < String > {
0 commit comments