Source code for schrodinger.trajectory.trajectory_gui_dir.export_snapshot_structures
import os
import schrodinger
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.structutils import analyze
from schrodinger.trajectory.trajectory_gui_dir.export_structure_enums import \
ExportFrameOption
from schrodinger.trajectory.trajectory_gui_dir.export_structure_enums import \
ExportToOption
from schrodinger.ui import maestro_ui
from schrodinger.ui.qt import atomselector
from schrodinger.ui.qt import filedialog
from schrodinger.ui.qt import utils
from schrodinger.utils import fileutils
from . import export_snapshot_structures_ui
from . import stylesheet
maestro = schrodinger.get_maestro()
[docs]class ExportStructures(QtWidgets.QDialog):
"""
Export structures class for trajectory snapshot panel.
:cvar exportButtonClicked: A signal emitted when clicked on 'Export' button.
:vartype exportButtonClicked: `QtCore.pyqtSignal`
"""
exportButtonClicked = QtCore.pyqtSignal()
[docs] def __init__(self, parent: QtWidgets.QWidget):
"""
:param parent: Parent widget.
"""
super(QtWidgets.QDialog, self).__init__(parent)
self.ui = export_snapshot_structures_ui.Ui_Dialog()
self.setStyleSheet(
stylesheet.EXPORT_SNAPSHOT_STRUCTURES_DIALOG_STYLESHEET)
self.ui.setupUi(self)
# Construct Atom Selector and place it in the place holder
self.atom_selector = atomselector.AtomSelector(self,
show_pick=False,
show_selection=False,
show_plus=True)
self.atom_selector.main_layout.setContentsMargins(2, 2, 2, 2)
layout = self.ui.atomselector_widget.layout()
layout.insertWidget(0, self.atom_selector)
self.atom_selector.atomSelectionDialogDismissed.connect(self.show)
self.atom_selector.atomSelectionDialogAboutToBeShown.connect(self.hide)
self.adjustSize()
self.ui.pt_radiobutton.setChecked(True)
self.ui.file_lineedit.setEnabled(False)
self.ui.browse_pushbutton.setEnabled(False)
self.ui.export_buttongroup.buttonToggled.connect(
self.updateFileDependentOptions)
self.ui.browse_pushbutton.clicked.connect(self.browse)
self.ui.all_in_list.toggled.connect(
self.ui.all_in_list_label.setEnabled)
self.ui.selected_only.toggled.connect(
self.ui.selected_only_label.setEnabled)
self.ui.all_in_list.setChecked(True)
self.ui.all_radiobutton.setChecked(True)
self.ui.atomselector_widget.setEnabled(False)
self.ui.specified_radiobutton.toggled.connect(
self.ui.atomselector_widget.setEnabled)
self.ui.load_sel_pushbutton.clicked.connect(
self.atom_selector.loadWorkspaceSelection)
self.ui.export_buttongroup.buttonToggled.connect(
self.updateExportButton)
self.ui.structures_buttongroup.buttonToggled.connect(
self.updateExportButton)
self.ui.file_lineedit.textChanged.connect(self.updateExportButton)
self.atom_selector.aslTextModified.connect(self.updateExportButton)
self.ui.cancel_pushbutton.clicked.connect(self.cancelClicked)
self.ui.export_pushbutton.clicked.connect(self.exportClicked)
self.ui.help_button.clicked.connect(self.help)
self._last_dir = None
self.file_formats = [fileutils.MAESTRO_STRICT]
[docs] def updateFileDependentOptions(self):
"""
Update File radio option dependent options.
"""
checked = self.ui.file_radiobutton.isChecked()
self.ui.file_lineedit.setEnabled(checked)
self.ui.browse_pushbutton.setEnabled(checked)
[docs] def browse(self):
"""
Slot triggered when 'Browse...' button is clicked on
"""
filter_string = filedialog.filter_string_from_formats(self.file_formats)
file_name = filedialog.get_save_file_name(
self,
dir=self._last_dir,
caption='Choose File for Export',
filter=filter_string)
if file_name:
self._last_dir = os.path.dirname(file_name)
# Ok pressed
self.ui.file_lineedit.setText(str(file_name))
[docs] def showDlg(self, all_frames: list, selected_frames: list):
"""
Show 'Export Structures' dialog with given information
"""
ws_hub = maestro_ui.WorkspaceHub.instance()
has_ws_atoms = ws_hub.getSelectedAtomCount() > 0
self.updateDlg(all_frames, selected_frames, has_ws_atoms)
# Show the dialog
self.show()
[docs] def updateFramesOption(self):
"""
Update frame options according to selected frames.
"""
has_selected_frames = self._selected_frames is not None and len(
self._selected_frames) > 0
self.ui.selected_only.setEnabled(has_selected_frames)
# If selected frames option was selected and now there is no selection,
# automatically set all in range option.
if not has_selected_frames:
self.ui.all_in_list.setChecked(True)
self.ui.selected_only_label.setEnabled(
self.ui.selected_only.isChecked())
[docs] def updateDlg(self, all_frames: list, selected_frames: list,
has_ws_atoms: bool):
"""
Initialze 'Export Structures' dialog with given information
:param has_ws_atoms: True if workspace has atoms.
:type has_ws_atoms: bool
"""
self._all_frames = all_frames
self._selected_frames = selected_frames
self.updateEntryCountLabels()
self.updateFramesOption()
# Enable 'Load Selection' only if workspace has selection
self.ui.load_sel_pushbutton.setEnabled(has_ws_atoms)
# Save current option values
self.saveOptions()
self.updateFileDependentOptions()
# Update 'Export' button
self.updateExportButton()
[docs] def saveOptions(self):
"""
Save current option values
"""
self._export_button = self.ui.export_buttongroup.checkedButton()
self._export_file_name = self.ui.file_lineedit.text()
self._frames_button = self.ui.frames_buttongroup.checkedButton()
self._structures_button = self.ui.structures_buttongroup.checkedButton()
self._structures_asl = self.atom_selector.getAsl()
[docs] def isValidASL(self):
"""
Return True if asl in the text box is valid.
"""
return analyze.validate_asl(self.export_asl)
[docs] def exportClicked(self):
"""
Accept and emit exportButtonClicked signal when 'Export' button is
clicked
"""
if not self.isValidASL():
asl = self.export_asl
maestro.warning(f"Invalid ASL {asl}")
return
self.close()
self.exportButtonClicked.emit()
[docs] def cancelClicked(self):
"""
Restore saved option values
"""
self.close()
self._export_button.setChecked(True)
self.ui.file_lineedit.setText(self._export_file_name)
self._frames_button.setChecked(True)
self._structures_button.setChecked(True)
self.atom_selector.setAsl(self._structures_asl)
@property
def frames_list(self):
"""
:return: Return frames list based on option selected by user.
:rtype: list
"""
if self.ui.all_in_list.isChecked():
return self._all_frames
else:
return self._selected_frames
@property
def export_frame_option(self):
"""
:return: Return frame option
:rtype: enum(ExportFrameOption)
"""
return ExportFrameOption.SNAPSHOT_FRAMES
@property
def export_to_option(self):
"""
:return: Return export option
:rtype: enum(ExportOption)
"""
if self.ui.pt_radiobutton.isChecked():
return ExportToOption.PROJECT_TABLE
else:
return ExportToOption.EXTERNAL_FILE
@property
def export_file_path(self):
"""
If file path does not contain extension, it also adds default .mae
extension.
:rtype: str
:return: Return file path to be used for export.
"""
file_path = self.ui.file_lineedit.text()
if fileutils.is_maestro_file(file_path):
return file_path
else:
return file_path + ".mae"
@property
def export_asl(self):
"""
:rtype: str
:return: Return asl of atoms to be exported.
"""
if self.ui.specified_radiobutton.isChecked():
return self.atom_selector.getAsl()
else:
return "all"
[docs] def updateEntryCountLabels(self):
"""
Updates entry count labels according to current values
"""
s = lambda n: 'entry' if n == 1 else 'entries'
all_total = len(self._all_frames)
selected_total = len(self._selected_frames)
self.ui.all_in_list_label.setText(f'({all_total} {s(all_total)})')
self.ui.selected_only_label.setText(
f'({selected_total} {s(selected_total)})')
[docs] def help(self):
"""
Shows 'Export Structures' dialog help
"""
utils.help_dialog("TRAJECTORY_EXPORT_SNAPSHOT_STRUCTURES", parent=self)