Source code for schrodinger.ui.qt.presets.manage_presets_dialog
import os
import typing
import traceback
from schrodinger.ui.qt import basewidgets, filedialog
from schrodinger.ui.qt.presets import manage_presets_dialog_ui
from schrodinger.ui.qt.mapperwidgets import plptable
from schrodinger.Qt import QtWidgets
from schrodinger.models import parameters, mappers
from schrodinger.models.presets import Direction
IN_DEV_MODE = 'SCHRODINGER_SRC' in os.environ
[docs]class PresetRowModel(parameters.CompoundParam):
preset_name: str
is_default: bool
[docs]class ManagePresetsModel(parameters.CompoundParam):
preset_names: typing.List[PresetRowModel]
selected_names: typing.List[PresetRowModel]
[docs]class ManagePresetsTableSpec(plptable.TableSpec):
preset_name = plptable.FieldColumn(
PresetRowModel.preset_name, sample_data='OptionInputsOptionInputs')
is_default = plptable.FieldColumn(
PresetRowModel.is_default, sample_data='(User default)')
[docs] @is_default.data_method()
def displayDefault(self, is_default):
if is_default:
return "(user default)"
else:
return ""
[docs]class ManagePresetsDialog(mappers.MapperMixin, basewidgets.BaseDialog):
ui_module = manage_presets_dialog_ui
model_class = ManagePresetsModel
[docs] def __init__(self, preset_manager, preset_model):
"""
:param preset_manager: The preset manager to use for saving a preset.
:type preset_manager: schrodinger.models.tasks.presets.PresetManager
:param preset_model: The model to use for applying any presets.
:type preset_model: schrodinger.models.parameters.CompoundParam
"""
self._preset_manager = preset_manager
self.preset_model = preset_model
super().__init__()
[docs] def initSetUp(self):
super().initSetUp()
self._all_options_table = plptable.PLPTableWidget(
spec=ManagePresetsTableSpec())
self._styleAllOptionsTable()
self._all_options_table.view.setSelectionMode(
QtWidgets.QAbstractItemView.SingleSelection)
self.ui.delete_btn.clicked.connect(self._deleteSelected)
self.ui.clear_or_set_default_btn.clicked.connect(
self._clearOrSetDefault)
self.ui.apply_btn.clicked.connect(self._applySelectedPreset)
self.ui.up_arrow_btn.clicked.connect(
lambda: self._movePreset(Direction.UP))
self.ui.down_arrow_btn.clicked.connect(
lambda: self._movePreset(Direction.DOWN))
self.ui.export_btn.clicked.connect(self._exportPresets)
self.ui.import_btn.clicked.connect(self._importPresets)
# Emojis for now, eventually should be up / down arrow icons
self.ui.up_arrow_btn.setText("⬆")
self.ui.down_arrow_btn.setText("⬇")
self.ui.up_arrow_btn.setEnabled(False)
self.ui.down_arrow_btn.setEnabled(False)
self._hideNotImplementedFeatures()
def _styleAllOptionsTable(self):
self._all_options_table.view.setShowGrid(False)
self._all_options_table.view.horizontalHeader().hide()
def _hideNotImplementedFeatures(self):
self.ui.options_editor_widget.setVisible(False)
[docs] def initLayOut(self):
super().initLayOut()
self.ui.all_options_table_layout.addWidget(self._all_options_table)
[docs] def initFinalize(self):
super().initFinalize()
default = self._preset_manager.getDefaultPreset()
self._loadOrdering(select=default)
[docs] def defineMappings(self):
return [
(self._all_options_table, self.model_class.preset_names),
(self._all_options_table.selection_target,
self.model_class.selected_names), # yapf: disable
(self._setExportEnable, self.model_class.preset_names)
]
[docs] def getSignalsAndSlots(self, model):
return [(model.selected_namesChanged, self._updateButtons),
(model.preset_namesChanged, self._setExportEnable)]
def _deleteSelected(self):
if len(self.model.selected_names) == 1:
name = self.model.selected_names[0].preset_name
self._preset_manager.deletePreset(name)
self._all_options_table.removeSelectedParams()
def _setExportEnable(self):
if len(self.model.preset_names) > 0:
self.ui.export_btn.setEnabled(True)
else:
self.ui.export_btn.setEnabled(False)
def _updateButtons(self):
selected_names = self.model.selected_names
if len(selected_names) == 1:
if selected_names[0].is_default:
self.ui.clear_or_set_default_btn.setText('Clear Default')
self.ui.up_arrow_btn.setEnabled(False)
self.ui.down_arrow_btn.setEnabled(False)
else:
selected_index = self.model.preset_names.index(
selected_names[0])
top_no_default = selected_index == 0
top_with_default = self._preset_manager.getDefaultPreset(
) and selected_index == 1
top = top_no_default or top_with_default
bottom = selected_index == len(self.model.preset_names) - 1
# If the selection is at the top or bottom disable clicking up and down
# respectively
self.ui.up_arrow_btn.setEnabled(not top)
self.ui.down_arrow_btn.setEnabled(not bottom)
self.ui.clear_or_set_default_btn.setText('Set as Default')
def _clearOrSetDefault(self):
"""
If the default preset is currently selected clear its default status.
If a non-default preset is currently selected set it as the default
and reorder the table to put the new default on top.
"""
selected_names = self.model.selected_names
if len(selected_names) == 1:
selected_row = selected_names[0]
if selected_row.is_default:
self._clearDefault(selected_row)
else:
self._setDefault(selected_row)
def _clearDefault(self, selected_row):
"""
Assumes the given row is the only selected row and is the default preset
"""
selected_row.is_default = False
self._preset_manager.clearDefaultPreset()
def _setDefault(self, selected_row):
"""
Assumes the given row is the only selected row and is not the default
preset
"""
default_name = self._preset_manager.getDefaultPreset()
for row in self.model.preset_names:
if row.preset_name == default_name:
row.is_default = False
# Put the new default at the top, the old default will be one
# below. Assumes on init any default is always on top.
selected_index = self.model.preset_names.index(selected_row)
selected_row.is_default = True
new_default = self.model.preset_names.pop(selected_index)
self.model.preset_names.insert(0, new_default)
self._all_options_table.setSelectedParams(self.model.preset_names[:1])
self._preset_manager.setDefaultPreset(selected_row.preset_name)
def _applySelectedPreset(self):
selected_names = self.model.selected_names
if len(selected_names) == 1:
name = selected_names[0].preset_name
try:
self._preset_manager.loadPreset(name, self.preset_model)
except Exception as e:
self.error(
"Encountered an error while trying to load the "
"settings. They are either out of date or corrupted.")
if IN_DEV_MODE:
traceback.print_stack()
def _movePreset(self, direction):
selected_names = self.model.selected_names
if len(selected_names) == 1:
selected_name = selected_names[0].preset_name
self._preset_manager.movePreset(selected_name, direction)
self._loadOrdering(select=selected_name)
def _loadOrdering(self, select=None):
"""
Populates the table by requesting the ordering from the manager.
:param select: The name of the preset to be selected after the table
is populated
:type select: str
"""
preset_rows = []
default_name = self._preset_manager.getDefaultPreset()
for name in self._preset_manager.getAvailablePresets():
default = default_name == name
row = PresetRowModel(preset_name=name, is_default=default)
preset_rows.append(row)
self.model.preset_names = preset_rows
if select:
names = [row.preset_name for row in self.model.preset_names]
index = names.index(select)
select_row = self.model.preset_names[index:index + 1]
self._all_options_table.setSelectedParams(select_row)
def _exportPresets(self):
"""
Opens a save file dialog to export the selected file.
"""
preset_names = self.model.preset_names
if len(preset_names) > 0:
export_fname = filedialog.get_save_file_name(
parent=self,
caption='Export Preset',
filter='Panel Options files (*.opts)',
accept_label='Export',
default_filename='panel_options')
if export_fname:
self._preset_manager.exportPresets(export_fname)
else:
raise RuntimeError('No available presets to export')
def _importPresets(self):
"""
Opens an open file dialog to import the selected file.
"""
import_fname = filedialog.get_open_file_name(
parent=self,
caption='Import Preset',
filter='Panel Options files (*.opts)',
accept_label='Import')
if import_fname:
try:
self._preset_manager.importPresets(import_fname,
self.preset_model)
except Exception as e:
self.error("Encountered an error while trying to import the "
"options. They are either out of date or corrupted.")
if IN_DEV_MODE:
traceback.print_stack()
else:
self._loadOrdering()
if __name__ == "__main__":
dlg = ManagePresetsDialog()