@@ -340,30 +340,51 @@ def start_end_time(self) -> ty.Optional[ty.Tuple[str, str]]:
340340 return self ._start_time .get (), self ._end_time .get ()
341341
342342
343- class SettingsArea :
343+ class SettingsWindow :
344344 def __init__ (self , root : tk .Widget ):
345345 self ._root = root
346- self ._advanced = tk .Toplevel (master = root )
347- self ._advanced .withdraw ()
346+ self ._window = tk .Toplevel (master = root )
347+ self ._window .withdraw ()
348348
349349 root .rowconfigure (0 , pad = PADDING , weight = 1 )
350- root .rowconfigure (1 , pad = PADDING , weight = 1 )
351- root .rowconfigure (2 , pad = PADDING , weight = 1 )
352350 root .columnconfigure (0 , pad = PADDING , weight = 1 )
353- root .columnconfigure (1 , pad = PADDING , weight = 1 )
354- root .columnconfigure (2 , pad = PADDING , weight = 2 )
355- root .columnconfigure (3 , pad = PADDING , weight = 1 )
356- root .columnconfigure (4 , pad = PADDING , weight = 1 )
357- root .columnconfigure (5 , pad = PADDING , weight = 1 )
358- root .columnconfigure (6 , pad = PADDING , weight = 12 , minsize = 0 )
351+ root .columnconfigure (1 , pad = PADDING , weight = 12 , minsize = 0 )
352+
353+ STICKY = tk .EW
354+
355+ #
356+ #
357+ # Advanced Window
358+ #
359+ #
360+ self ._window .minsize (width = MIN_WINDOW_WIDTH , height = MIN_WINDOW_HEIGHT )
361+ self ._window .title ("Motion Settings" )
362+ self ._window .resizable (True , True )
363+ self ._window .protocol ("WM_DELETE_WINDOW" , self ._dismiss_advanced )
364+ self ._window .rowconfigure (0 , weight = 1 )
365+ self ._window .rowconfigure (1 , weight = 1 )
366+ self ._window .columnconfigure (0 , weight = 1 )
367+
368+ frame = ttk .LabelFrame (self ._window , text = "Motion" , padding = PADDING )
369+ frame .grid (row = 0 , sticky = tk .NSEW , padx = PADDING , pady = PADDING )
370+ frame .rowconfigure (0 , pad = PADDING , weight = 1 )
371+ frame .rowconfigure (1 , pad = PADDING , weight = 1 )
372+ frame .rowconfigure (2 , pad = PADDING , weight = 1 )
373+ frame .columnconfigure (0 , pad = PADDING , weight = 1 )
374+ frame .columnconfigure (1 , pad = PADDING , weight = 1 )
375+ frame .columnconfigure (2 , pad = PADDING , weight = 2 )
376+ frame .columnconfigure (3 , pad = PADDING , weight = 1 )
377+ frame .columnconfigure (4 , pad = PADDING , weight = 1 )
378+ frame .columnconfigure (5 , pad = PADDING , weight = 1 )
379+ frame .columnconfigure (6 , pad = PADDING , weight = 12 , minsize = 0 )
359380
360381 STICKY = tk .EW
361382
362383 # Detector
363384
364- tk .Label (root , text = "Subtractor" ).grid (row = 0 , column = 0 , sticky = STICKY )
385+ tk .Label (frame , text = "Subtractor" ).grid (row = 0 , column = 0 , sticky = STICKY )
365386 self ._bg_subtractor = tk .StringVar ()
366- combo = ttk .Combobox (root , textvariable = self ._bg_subtractor , width = SETTING_INPUT_WIDTH )
387+ combo = ttk .Combobox (frame , textvariable = self ._bg_subtractor , width = SETTING_INPUT_WIDTH )
367388 combo .state (["readonly" ])
368389 if SubtractorCudaMOG2 .is_available ():
369390 combo ["values" ] = ("MOG2_CUDA" , "MOG2" , "CNT" )
@@ -374,9 +395,11 @@ def __init__(self, root: tk.Widget):
374395
375396 combo .grid (row = 0 , column = 1 , sticky = STICKY )
376397
377- tk .Label (root , text = "Kernel Size" ).grid (row = 1 , column = 0 , sticky = STICKY )
398+ tk .Label (frame , text = "Kernel Size" ).grid (row = 1 , column = 0 , sticky = STICKY )
378399
379- self ._kernel_size_combobox = ttk .Combobox (root , width = SETTING_INPUT_WIDTH , state = "readonly" )
400+ self ._kernel_size_combobox = ttk .Combobox (
401+ frame , width = SETTING_INPUT_WIDTH , state = "readonly"
402+ )
380403 # 0: Auto
381404 # 1: Off
382405 # 2: 3x3
@@ -391,9 +414,9 @@ def __init__(self, root: tk.Widget):
391414 self ._kernel_size_combobox .grid (row = 1 , column = 1 , sticky = STICKY )
392415 self ._kernel_size_combobox .current (1 )
393416
394- tk .Label (root , text = "Threshold" ).grid (row = 2 , column = 0 , sticky = STICKY )
417+ tk .Label (frame , text = "Threshold" ).grid (row = 2 , column = 0 , sticky = STICKY )
395418 self ._threshold = Spinbox (
396- root ,
419+ frame ,
397420 value = str (CONFIG_MAP ["threshold" ]),
398421 from_ = 0.0 ,
399422 to = 255.0 ,
@@ -402,9 +425,9 @@ def __init__(self, root: tk.Widget):
402425 self ._threshold .grid (row = 2 , column = 1 , sticky = STICKY )
403426
404427 # Events
405- tk .Label (root , text = "Min. Event Length" ).grid (row = 0 , column = 3 , sticky = STICKY )
428+ tk .Label (frame , text = "Min. Event Length" ).grid (row = 0 , column = 3 , sticky = STICKY )
406429 self ._min_event_length = Spinbox (
407- root ,
430+ frame ,
408431 value = str (CONFIG_MAP ["min-event-length" ]),
409432 from_ = 0.0 ,
410433 to = MAX_DURATION ,
@@ -413,9 +436,9 @@ def __init__(self, root: tk.Widget):
413436 )
414437 self ._min_event_length .grid (row = 0 , column = 4 , sticky = STICKY )
415438
416- tk .Label (root , text = "Time Pre-Event" ).grid (row = 1 , column = 3 , sticky = STICKY )
439+ tk .Label (frame , text = "Time Pre-Event" ).grid (row = 1 , column = 3 , sticky = STICKY )
417440 self ._time_before_event = Spinbox (
418- root ,
441+ frame ,
419442 value = str (CONFIG_MAP ["time-before-event" ]),
420443 from_ = 0.0 ,
421444 to = MAX_DURATION ,
@@ -424,9 +447,9 @@ def __init__(self, root: tk.Widget):
424447 )
425448 self ._time_before_event .grid (row = 1 , column = 4 , sticky = STICKY )
426449
427- tk .Label (root , text = "Time Post-Event" ).grid (row = 2 , column = 3 , sticky = STICKY )
450+ tk .Label (frame , text = "Time Post-Event" ).grid (row = 2 , column = 3 , sticky = STICKY )
428451 self ._time_post_event = Spinbox (
429- root ,
452+ frame ,
430453 value = str (CONFIG_MAP ["time-post-event" ]),
431454 from_ = 0.0 ,
432455 to = MAX_DURATION ,
@@ -437,35 +460,15 @@ def __init__(self, root: tk.Widget):
437460
438461 self ._mask_output = tk .BooleanVar (value = False )
439462 ttk .Checkbutton (
440- root ,
463+ frame ,
441464 text = "Save Motion Mask" ,
442465 variable = self ._mask_output ,
443466 onvalue = True ,
444467 offvalue = False ,
445468 ).grid (row = 3 , column = 0 , columnspan = 2 , sticky = tk .W , padx = PADDING , pady = PADDING )
446469
447- # Processing
448-
449- self ._advanced_button = ttk .Button (
450- root , text = "Advanced..." , command = self ._show_advanced , width = SETTING_INPUT_WIDTH
451- )
452- self ._advanced_button .grid (
453- row = 3 , column = 3 , columnspan = 2 , sticky = tk .EW , pady = PADDING , padx = PADDING
454- )
455-
456- #
457- #
458- # Advanced Window
459- #
460- #
461- self ._advanced .minsize (width = MIN_WINDOW_WIDTH , height = MIN_WINDOW_HEIGHT )
462- self ._advanced .title ("Motion Settings" )
463- self ._advanced .resizable (True , True )
464- self ._advanced .protocol ("WM_DELETE_WINDOW" , self ._dismiss_advanced )
465- self ._advanced .rowconfigure (0 , weight = 1 )
466- self ._advanced .columnconfigure (0 , weight = 1 )
467- frame = ttk .LabelFrame (self ._advanced , text = "Advanced" , padding = PADDING )
468- frame .grid (row = 0 , sticky = tk .NSEW , padx = PADDING , pady = PADDING )
470+ frame = ttk .LabelFrame (self ._window , text = "Advanced" , padding = PADDING )
471+ frame .grid (row = 1 , sticky = tk .NSEW , padx = PADDING , pady = PADDING )
469472 frame .columnconfigure (0 , weight = 1 )
470473 frame .columnconfigure (1 , weight = 1 )
471474 frame .columnconfigure (2 , weight = 2 )
@@ -541,8 +544,8 @@ def __init__(self, root: tk.Widget):
541544 offvalue = False ,
542545 ).grid (row = 2 , column = 0 , columnspan = 2 , padx = PADDING , sticky = STICKY , pady = PADDING )
543546
544- tk .Button (self ._advanced , text = "Close" , command = self ._dismiss_advanced ).grid (
545- row = 1 , column = 0 , sticky = tk .E , padx = PADDING , pady = PADDING
547+ tk .Button (self ._window , text = "Close" , command = self ._dismiss_advanced ).grid (
548+ row = 2 , column = 0 , sticky = tk .E , padx = PADDING , pady = PADDING
546549 )
547550
548551 tk .Label (frame , text = "Frame Skip" ).grid (
@@ -562,19 +565,19 @@ def _on_auto_learning_rate(self):
562565 tk .DISABLED if self ._learning_rate_auto .get () else tk .NORMAL
563566 )
564567
565- def _show_advanced (self ):
568+ def show (self ):
566569 logger .debug ("showing advanced settings window" )
567- self ._advanced .transient (self ._root )
568- self ._advanced .deiconify ()
569- self ._advanced .focus ()
570- self ._advanced .grab_set ()
571- self ._advanced .wait_window ()
570+ self ._window .transient (self ._root )
571+ self ._window .deiconify ()
572+ self ._window .focus ()
573+ self ._window .grab_set ()
574+ self ._window .wait_window ()
572575
573576 def _dismiss_advanced (self ):
574577 logger .debug ("closing advanced settings window" )
575- self ._advanced .withdraw ()
576- self ._advanced .grab_release ()
577- self ._advanced_button .focus ()
578+ self ._window .withdraw ()
579+ self ._window .grab_release ()
580+ self ._root .focus ()
578581
579582 @property
580583 def _kernel_size (self ) -> int :
@@ -1168,28 +1171,27 @@ def __init__(self, settings: ScanSettings, initial_videos: ty.List[str]):
11681171 self ._root .columnconfigure (0 , weight = 1 , pad = PADDING )
11691172 self ._root .rowconfigure (0 , weight = 1 )
11701173
1171- self ._create_menubar ()
1172-
11731174 input_frame = ttk .Labelframe (self ._root , text = "Input" , padding = PADDING )
11741175 self ._input_area = InputArea (input_frame )
11751176 input_frame .grid (row = 0 , sticky = tk .NSEW , padx = PADDING , pady = (PADDING , 0 ))
11761177
1177- settings_frame = ttk .Labelframe (self ._root , text = "Motion" , padding = PADDING )
1178- self ._settings_area = SettingsArea (settings_frame )
1179- settings_frame .grid (row = 1 , sticky = tk .EW , padx = PADDING , pady = (PADDING , 0 ))
1178+ # settings_frame = ttk.Labelframe(self._root, text="Scanner", padding=PADDING)
1179+ self ._settings_area = SettingsWindow (self ._root )
11801180
11811181 output_frame = ttk .Labelframe (self ._root , text = "Output" , padding = PADDING )
11821182 self ._output_area = OutputArea (output_frame )
11831183 output_frame .grid (row = 2 , sticky = tk .EW , padx = PADDING , pady = (PADDING , 0 ))
11841184
1185- scan_frame = ttk .Labelframe (self ._root , text = "Scan " , padding = PADDING )
1185+ scan_frame = ttk .Labelframe (self ._root , text = "Run " , padding = PADDING )
11861186 self ._scan_area = ScanArea (self ._root , scan_frame )
11871187 scan_frame .grid (row = 3 , sticky = tk .EW , padx = PADDING , pady = PADDING )
11881188
11891189 self ._scan_window : ty .Optional [ScanWindow ] = None
11901190 self ._root .bind ("<<StartScan>>" , lambda _ : self ._start_scan ())
11911191 self ._root .protocol ("WM_DELETE_WINDOW" , self ._destroy )
11921192
1193+ self ._create_menubar ()
1194+
11931195 if not SUPPRESS_EXCEPTIONS :
11941196
11951197 def error_handler (* args ):
@@ -1223,6 +1225,13 @@ def _create_menubar(self):
12231225
12241226 settings_menu = tk .Menu (root_menu )
12251227 root_menu .add_cascade (menu = settings_menu , label = "Settings" , underline = 0 )
1228+ # TODO(#201): Add ability to change input settings.
1229+ settings_menu .add_command (
1230+ label = "Motion" ,
1231+ underline = 0 ,
1232+ command = self ._settings_area .show ,
1233+ )
1234+ settings_menu .add_separator ()
12261235 settings_menu .add_command (
12271236 label = "Load..." ,
12281237 underline = 0 ,
0 commit comments