from schrodinger.application.msv.gui.homology_modeling import constants
from schrodinger.application.msv.gui.homology_modeling import hm_models
from schrodinger.application.msv.gui.homology_modeling import settings_dialog_ui
from schrodinger.models import mappers
from schrodinger.Qt import QtCore
from schrodinger.ui.qt import basewidgets
from schrodinger.ui.qt import mapperwidgets
[docs]class SettingsDialog(mappers.MapperMixin,
                     basewidgets.panelmixins.CleanStateMixin,
                     basewidgets.BaseDialog):
    model_class = hm_models.HomologyModelingSettings
    ui_module = settings_dialog_ui
    removeResidueConstraintsRequested = QtCore.pyqtSignal()
[docs]    def initSetOptions(self):
        super().initSetOptions()
        self.setWindowTitle("View Modeling Settings")
        self.help_topic = 'MSV_HOMOLOGY_MODELING_SETTINGS'
        self.std_btn_specs = {
            self.StdBtn.Ok: None,
            self.StdBtn.Cancel: self.discardChanges,
            self.StdBtn.Reset: None,
        } 
[docs]    def initSetUp(self):
        super().initSetUp()
        ui = self.ui
        self.method_btn_grp = mapperwidgets.MappableButtonGroup({
            ui.knowledge_based_rb: constants.PrimeMethod.KNOWLEDGE,
            ui.energy_based_rb: constants.PrimeMethod.ENERGY,
        })
        self.method_btn_grp.buttonClicked.connect(self._onMethodBtnClicked)
        ui.models_sb.setMinimum(1)
        ui.method_options_sw.setEnum(constants.PrimeMethod)
        ui.constraint_info_btn.setToolTip(
            "Set constraints within Reference sequence to keep pairs of "
            "residues close together in the model.")
        ui.clear_constraint_btn.clicked.connect(
            self.removeResidueConstraintsRequested)
        for push_btn in (ui.clear_constraint_btn, ui.constraint_pick_btn):
            push_btn.setAutoDefault(False)
        # TODO MSV-2468
        ui.add_residue_labels_cb.setEnabled(False)
        ui.add_residue_labels_cb.setToolTip("Not implemented")
        # MSV-3357: Hiding unimplemented features for beta
        ui.add_residue_labels_cb.setVisible(False) 
[docs]    def setModel(self, model):
        if self.model is not None:
            self.model.prime_settings.prime_methodChanged.disconnect(
                self.method_btn_grp.targetSetValue)
        super().setModel(model)
        if model is not None:
            self.method_btn_grp.targetSetValue(
                model.prime_settings.prime_method)
            model.prime_settings.prime_methodChanged.connect(
                self.method_btn_grp.targetSetValue) 
[docs]    def defineMappings(self):
        M = self.model_class
        settings = M.prime_settings
        enable_insertions_le_target = mappers.TargetSpec(
            setter=self.ui.limit_insertions_le.setEnabled)
        enable_reset_target = mappers.TargetSpec(setter=self._updateResetBtn)
        enable_clear_target = mappers.TargetSpec(setter=self._updateClearBtn)
        # Note: we intentionally don't map `self.method_btn_grp` to
        # `settings.prime_method` because we may need to prompt the user before
        # changing the method. See `_onMethodBtnClicked`
        return [
            (enable_reset_target, M),
            (mappers.TargetSpec(setter=self._onPrimeMethodChanged), settings.prime_method),
            (self.ui.method_options_sw, settings.prime_method),
            (self.ui.models_sb, settings.num_output_struct),
            (self.ui.constraint_cb, M.set_constraints),
            (enable_clear_target, M.proximity_constraints),
            (self.ui.constraint_pick_btn, M.pick_proximity),
            (self.ui.keep_residue_numbers_cb, settings.template_residue_numbers),
            (self.ui.add_residue_labels_cb, M.add_residue_labels),
            (self.ui.minimize_non_template_cb, settings.minimize),
            (self.ui.preserve_rotamers_cb, settings.keep_rotamers),
            (self._updateOptimizeSidechainsCbText, settings.keep_rotamers),
            (self.ui.optimize_side_chains_cb, settings.side_opt),
            (self.ui.limit_insertions_cb, settings.build_insertions),
            (enable_insertions_le_target, settings.build_insertions),
            (self.ui.limit_insertions_le, settings.max_insertion_size),
            (self.ui.template_junctions_cb, settings.build_transitions),
            (self.ui.deletions_cb, settings.build_deletions),
        ]  # yapf: disable 
[docs]    def hideEvent(self, event):
        super().hideEvent(event)
        self.model.pick_proximity = False 
    def _updateResetBtn(self, model):
        self.reset_btn.setEnabled(not model.isDefault())
    def _updateClearBtn(self, proximity_constraints):
        self.ui.clear_constraint_btn.setEnabled(bool(proximity_constraints))
    def _onPrimeMethodChanged(self, prime_method):
        """
        Only allow non-default num_output_struct for Knowledge-based
        """
        can_change_num = prime_method is constants.PrimeMethod.KNOWLEDGE
        self.ui.models_sb.setEnabled(can_change_num)
    def _onMethodBtnClicked(self, btn):
        prime_method = self.method_btn_grp.getValueForWidget(btn)
        if prime_method is constants.PrimeMethod.KNOWLEDGE:
            lig_model = self.model.ligand_dlg_model
            if lig_model.constrain_ligand and lig_model.ligand_constraints:
                resp = self.question(
                    "This will turn off the binding site proximity constraints. Continue anyway?"
                )
                if resp:
                    lig_model.constrain_ligand = False
                else:
                    self.method_btn_grp.targetSetValue(
                        self.model.prime_settings.prime_method)
                    return
            self.model.set_constraints = False
        self.model.prime_settings.prime_method = prime_method
    def _updateOptimizeSidechainsCbText(self):
        extension = " (other than conserved residues)" if self.model.prime_settings.keep_rotamers else ''
        text = f"Optimize side chains{extension}"
        self.ui.optimize_side_chains_cb.setText(text)