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 updateExportButton(self): """ Enable/disable 'Export' button based on option values """ enable_export = True # Disable 'Export' button in below cases # Export to: File & file text is empty # Structures: Specified atom (ASL) & asl is empty if (((self.ui.file_radiobutton.isChecked() and not self.ui.file_lineedit.text()) or (self.ui.specified_radiobutton.isChecked() and not self.atom_selector.getAsl()))): enable_export = False self.ui.export_pushbutton.setEnabled(enable_export)
[docs] def help(self): """ Shows 'Export Structures' dialog help """ utils.help_dialog("TRAJECTORY_EXPORT_SNAPSHOT_STRUCTURES", parent=self)