Source code for schrodinger.ui.qt.directory_selector
"""
Module containing DirectorySelector. The widget's directory selection can be obtained by
mapping the widget to a param or alternatively by connecting a slot to the
directoryChanged signal.
To use without mapping, hook up the directoryChanged signal to a
slot that calls `DirectorySelector.getDirPath()`.
"""
from typing import Optional
from schrodinger.models import mappers
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt import basewidgets
from schrodinger.ui.qt import filedialog
[docs]class DirectorySelector(mappers.TargetMixin, basewidgets.BaseWidget):
    """
    Widget for showing an entry field and a browse button to let the user
    specify a single directory.
    :cvar directoryChanged: Signal emitted when the directory selection changes.
    :vartype directoryChanged: QtCore.pyqtSignal
    """
    directoryChanged = QtCore.pyqtSignal()
[docs]    def __init__(self,
                 parent: Optional[QtWidgets.QWidget] = None,
                 initial_dir: Optional[str] = None):
        """
        :param parent: Parent widget.
        :param initial_dir: Initial directory. Default is CWD.
        """
        self._initial_dir = initial_dir
        super().__init__(parent)
        self.setLabelText('Directory location:') 
[docs]    def initSetUp(self):
        super().initSetUp()
        self.dir_lbl = QtWidgets.QLabel()
        self.dir_le = QtWidgets.QLineEdit()
        self.dir_le.editingFinished.connect(self._dirPathEdited)
        self.dir_browse_btn = QtWidgets.QPushButton("Browse...")
        self.dir_browse_btn.clicked.connect(self._browseDir) 
[docs]    def initLayOut(self):
        super().initLayOut()
        self.dir_layout = QtWidgets.QHBoxLayout()
        self.dir_layout.addWidget(self.dir_lbl)
        self.dir_layout.addWidget(self.dir_le)
        self.dir_layout.addWidget(self.dir_browse_btn)
        self.widget_layout.addLayout(self.dir_layout) 
    # ==========================================================================
    # Main API
    # ==========================================================================
[docs]    def setLabelText(self, text: str):
        """
        Set the label text to the left of the line edit.
        """
        self.dir_lbl.setText(text) 
[docs]    def getDirectoryPath(self) -> str:
        """
        Return the currently selected directory path. Allows access to target
        """
        return self.targetGetValue() 
    # ==========================================================================
    # Internal Implementation Methods
    # ==========================================================================
[docs]    def targetGetValue(self) -> str:
        """
        Return the line edit text.
        """
        return self.dir_le.text() 
[docs]    def targetSetValue(self, value: str):
        """
        Set the line edit text based for a valid `value` and emit two signals:
        targetValueChanged for when this widget mapped to a
        param, and directoryChanged for when it is not.
        :param value: The directory path to set to the line edit.
        """
        self.dir_le.setText(value)
        self.directoryChanged.emit()
        self.targetValueChanged.emit() 
    def _browseDir(self):
        """
        Open a browse directory dialog and set the line edit text if the
        directory is valid.
        """
        new_dir = filedialog.get_existing_directory(
            parent=self,
            caption='Select Input Directory',
            dir=self._initial_dir)
        if new_dir:
            self.targetSetValue(new_dir)
    def _dirPathEdited(self):
        """
        Update the model when user manually edits the directory path.
        """
        self.targetSetValue(self.dir_le.text())