Source code for schrodinger.ui.qt.presets.manage_presets_dialog
import os
import traceback
import typing
from schrodinger.models import mappers
from schrodinger.models import parameters
from schrodinger.models.presets import Direction
from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt import basewidgets
from schrodinger.ui.qt import filedialog
from schrodinger.ui.qt.mapperwidgets import plptable
from schrodinger.ui.qt.presets import manage_presets_dialog_ui
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()