@@ -473,6 +473,195 @@ def test_measurement_mode_ctrl_rebuilds_on_instrument_change(window):
473473 assert before # sanity: there was something to compare against
474474
475475
476+ # --- measurement_mode_ctrl_handler's BPC choice dialog (issue #845) ---------
477+
478+
479+ def _prime_bpc_choice_conditions (window , monkeypatch , code ):
480+ """Stub the guards in ``measurement_mode_ctrl_handler`` so its BPC-choice
481+ dialog condition is met regardless of the stub worker's actual
482+ instrument/measurement-mode state."""
483+ setcfg ("calibration.black_point_correction_choice.show" , 1 )
484+ setcfg ("calibration.black_point_correction.auto" , 0 )
485+ monkeypatch .setattr (window , "get_measurement_mode" , lambda : code )
486+ monkeypatch .setattr (window , "get_trc" , lambda : "2.4" )
487+ monkeypatch .setattr (window , "get_black_point_correction" , lambda : "1.0" )
488+
489+
490+ def test_measurement_mode_ctrl_handler_shows_bpc_choice_dialog_when_applicable (
491+ window , monkeypatch
492+ ):
493+ # "l" has neither "c" nor "p", satisfying the guard's turn-off case
494+ # (``"c" not in code``).
495+ _prime_bpc_choice_conditions (window , monkeypatch , "l" )
496+ calls = []
497+ monkeypatch .setattr (
498+ window ,
499+ "_confirm_black_point_correction_choice" ,
500+ lambda code , cal_changed : calls .append ((code , cal_changed )),
501+ )
502+
503+ window .measurement_mode_ctrl_handler (0 )
504+
505+ assert calls and calls [0 ][0 ] == "l"
506+
507+
508+ def test_measurement_mode_ctrl_handler_skips_dialog_when_choice_hidden (
509+ window , monkeypatch
510+ ):
511+ _prime_bpc_choice_conditions (window , monkeypatch , "l" )
512+ setcfg ("calibration.black_point_correction_choice.show" , 0 )
513+ calls = []
514+ monkeypatch .setattr (
515+ window ,
516+ "_confirm_black_point_correction_choice" ,
517+ lambda * a , ** k : calls .append (True ),
518+ )
519+
520+ window .measurement_mode_ctrl_handler (0 )
521+
522+ assert calls == []
523+
524+
525+ def test_measurement_mode_ctrl_handler_skips_dialog_when_bpc_auto (
526+ window , monkeypatch
527+ ):
528+ _prime_bpc_choice_conditions (window , monkeypatch , "c" )
529+ setcfg ("calibration.black_point_correction.auto" , 1 )
530+ calls = []
531+ monkeypatch .setattr (
532+ window ,
533+ "_confirm_black_point_correction_choice" ,
534+ lambda * a , ** k : calls .append (True ),
535+ )
536+
537+ window .measurement_mode_ctrl_handler (0 )
538+
539+ assert calls == []
540+
541+
542+ def test_measurement_mode_ctrl_handler_skips_dialog_when_bpc_zero (
543+ window , monkeypatch
544+ ):
545+ _prime_bpc_choice_conditions (window , monkeypatch , "c" )
546+ monkeypatch .setattr (window , "get_black_point_correction" , lambda : "0.0" )
547+ calls = []
548+ monkeypatch .setattr (
549+ window ,
550+ "_confirm_black_point_correction_choice" ,
551+ lambda * a , ** k : calls .append (True ),
552+ )
553+
554+ window .measurement_mode_ctrl_handler (0 )
555+
556+ assert calls == []
557+
558+
559+ def test_confirm_bpc_choice_turn_on_accept_persists_bpc (window , monkeypatch ):
560+ setcfg ("calibration.black_point_correction" , 0.0 )
561+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
562+ _FakeBpcChoiceMessageBox .clicked_role = "accept"
563+ _FakeBpcChoiceMessageBox .check_clicked = False
564+ updated = []
565+ monkeypatch .setattr (
566+ window , "update_calibration_controls" , lambda : updated .append (True )
567+ )
568+
569+ window ._confirm_black_point_correction_choice ("c" , cal_changed = True )
570+
571+ assert getcfg ("calibration.black_point_correction" ) == 1.0
572+ assert updated == [True ]
573+
574+
575+ def test_confirm_bpc_choice_turn_off_accept_persists_bpc (window , monkeypatch ):
576+ setcfg ("calibration.black_point_correction" , 1.0 )
577+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
578+ _FakeBpcChoiceMessageBox .clicked_role = "accept"
579+ _FakeBpcChoiceMessageBox .check_clicked = False
580+ monkeypatch .setattr (window , "update_calibration_controls" , lambda : None )
581+
582+ window ._confirm_black_point_correction_choice ("l" , cal_changed = True )
583+
584+ assert getcfg ("calibration.black_point_correction" ) == 0.0
585+
586+
587+ def test_confirm_bpc_choice_keep_current_leaves_bpc_unchanged (window , monkeypatch ):
588+ setcfg ("calibration.black_point_correction" , 0.5 )
589+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
590+ _FakeBpcChoiceMessageBox .clicked_role = "reject"
591+ _FakeBpcChoiceMessageBox .check_clicked = False
592+ updated = []
593+ monkeypatch .setattr (
594+ window , "update_calibration_controls" , lambda : updated .append (True )
595+ )
596+
597+ window ._confirm_black_point_correction_choice ("c" , cal_changed = True )
598+
599+ assert getcfg ("calibration.black_point_correction" ) == 0.5
600+ assert updated == []
601+
602+
603+ def test_confirm_bpc_choice_checkbox_persists_regardless_of_button (
604+ window , monkeypatch
605+ ):
606+ setcfg ("calibration.black_point_correction_choice.show" , 1 )
607+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
608+ _FakeBpcChoiceMessageBox .clicked_role = "reject"
609+ _FakeBpcChoiceMessageBox .check_clicked = True
610+ monkeypatch .setattr (window , "update_calibration_controls" , lambda : None )
611+
612+ window ._confirm_black_point_correction_choice ("c" , cal_changed = True )
613+
614+ assert getcfg ("calibration.black_point_correction_choice.show" ) == 0
615+
616+
617+ def test_confirm_bpc_choice_unchecked_keeps_showing_next_time (window , monkeypatch ):
618+ setcfg ("calibration.black_point_correction_choice.show" , 1 )
619+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
620+ _FakeBpcChoiceMessageBox .clicked_role = "accept"
621+ _FakeBpcChoiceMessageBox .check_clicked = False
622+ monkeypatch .setattr (window , "update_calibration_controls" , lambda : None )
623+
624+ window ._confirm_black_point_correction_choice ("c" , cal_changed = True )
625+
626+ assert getcfg ("calibration.black_point_correction_choice.show" ) == 1
627+
628+
629+ def test_confirm_bpc_choice_marks_settings_changed_when_cal_unchanged (
630+ window , monkeypatch
631+ ):
632+ setcfg ("calibration.black_point_correction" , 0.0 )
633+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
634+ _FakeBpcChoiceMessageBox .clicked_role = "accept"
635+ _FakeBpcChoiceMessageBox .check_clicked = False
636+ monkeypatch .setattr (window , "update_calibration_controls" , lambda : None )
637+ marked = []
638+ monkeypatch .setattr (
639+ window , "_mark_profile_settings_changed" , lambda : marked .append (True )
640+ )
641+
642+ window ._confirm_black_point_correction_choice ("c" , cal_changed = False )
643+
644+ assert marked == [True ]
645+
646+
647+ def test_confirm_bpc_choice_skips_mark_when_cal_already_changed (
648+ window , monkeypatch
649+ ):
650+ setcfg ("calibration.black_point_correction" , 0.0 )
651+ monkeypatch .setattr (mw , "QMessageBox" , _FakeBpcChoiceMessageBox )
652+ _FakeBpcChoiceMessageBox .clicked_role = "accept"
653+ _FakeBpcChoiceMessageBox .check_clicked = False
654+ monkeypatch .setattr (window , "update_calibration_controls" , lambda : None )
655+ marked = []
656+ monkeypatch .setattr (
657+ window , "_mark_profile_settings_changed" , lambda : marked .append (True )
658+ )
659+
660+ window ._confirm_black_point_correction_choice ("c" , cal_changed = True )
661+
662+ assert marked == []
663+
664+
476665def test_colorimeter_correction_matrix_ctrl_hidden_when_ccxx_unsupported (window ):
477666 # The stub worker's default argyll_version ([0, 0, 0]) can't use CCXX.
478667 assert window .colorimeter_correction_matrix_ctrl .isVisibleTo (window ) is False
@@ -2565,6 +2754,24 @@ def clickedButton(self):
25652754 return self ._buttons [role ]
25662755
25672756
2757+ class _FakeBpcChoiceMessageBox (_FakeTwoButtonMessageBox ):
2758+ """Extends :class:`_FakeTwoButtonMessageBox` with the "don't ask again"
2759+ checkbox :meth:`MainWindow._confirm_black_point_correction_choice` adds
2760+ via ``setCheckBox`` -- the real ``QCheckBox`` instance production code
2761+ creates is stored as-is, so tests can flip it via ``check_clicked`` to
2762+ simulate the user ticking it before the (mocked) modal closes."""
2763+
2764+ check_clicked = False # set per-test
2765+
2766+ def setCheckBox (self , checkbox ):
2767+ self ._checkbox = checkbox
2768+
2769+ def exec_ (self ):
2770+ if self .check_clicked :
2771+ self ._checkbox .setChecked (True )
2772+ return None
2773+
2774+
25682775def test_profile_btn_handler_stashes_apply_calibration_and_begins (
25692776 window , monkeypatch
25702777):
0 commit comments