Source code for schrodinger.project.manager
from schrodinger import get_maestro
from schrodinger.project import ProjectException
from schrodinger.project import utils as project_utils
from schrodinger.Qt import QtCore
maestro = get_maestro()
[docs]class EntryGroupManager(QtCore.QObject):
    """
    Manage interactions with an entry group specified by a unique name. The
    manager is necessary because the entry group object itself may become
    inaccessible and change its properties if it loses all of its entries.
    """
    groupTitleChanged = QtCore.pyqtSignal(str)
[docs]    def __init__(self, parent=None, group_name=None, parent_group_name=None):
        """
        Initialize this object by specifying the unique name of the managed
        entry group.
        """
        super().__init__(parent=parent)
        if group_name is None:
            group_name = project_utils.generate_unique_group_name()
        self._name = group_name
        self._parent_group_name = parent_group_name
        self._title = group_name
        self._group_empty = bool(self.group)
        if maestro:
            maestro.project_update_callback_add(self.onProjectUpdate) 
    @property
    def group(self):
        """
        Return the entry group being managed if it is accessible. This
        is important, for example, if all of the entries are removed from an
        entry group.
        :return: The entry group, if it exists in the project.
        :rtype: project.EntryGroup or None
        """
        if maestro:
            return project_utils.get_entry_group(self._name)
    @property
    def name(self):
        """
        :return: the unique entry group name
        :rtype: str
        """
        return self._name
    @property
    def parent_group(self):
        group = self.group
        if group:
            return group.getParentGroup()
    @property
    def parent_group_name(self):
        """
        :return: the unique name of the parent group, if any
        :rtype: str
        """
        return self._parent_group_name
    @property
    def title(self):
        """
        Return the title stored with this manager. By default it is the group
        name that this manager was initialized with, but it can be set directly
        by calling `setTitle`. It should be automatically updated via maestro
        callback if the entry group title is changed by the user in the project
        table.
        :return: the entry group name
        :rtype: str
        """
        return self._title
    @title.setter
    def title(self, title):
        """
        Set the title of the entry group. Even if the group is empty (and
        therefore not active), cache the title string within this manager so
        that it can be applied to the group when it becomes active again.
        :param title: the new title
        :type title: str
        """
        self._title = title
        if self.group:
            self.group.title = title
[docs]    def moveToGroup(self, entry_ids):
        """
        Move the specified entry IDs to this group.
        This is preferred over row.moveToGroup if `parent_group_name` is
        specified, because it will create the group with the correct nesting.
        """
        entry_ids = list(entry_ids)  # in case it's exhaustible
        pg_name = self._parent_group_name
        if pg_name and self.group is None:
            # If it's a child group and doesn't exist, need to create it
            if project_utils.get_entry_group(pg_name) is None:
                # Recreate parent group if it doesn't exist by moving first row
                row = project_utils.get_row(entry_ids[0])
                row.moveToGroup(pg_name)
            project_utils.create_child_group(entry_ids=entry_ids,
                                             parent_group_name=pg_name,
                                             group_name=self.name)
        else:
            # If group already exists or there's no parent group
            for entry in project_utils.get_rows(entry_ids):
                entry.moveToGroup(self.name) 
    def _writeTitleToGroup(self):
        """
        Update the managed entry group's title to be the title string saved on
        this manager.
        This method should automatically be called when the entry group
        transitions from containing no entries to containing at least one entry.
        """
        if self.group:
            self.group.title = self._title
    def _readTitleFromGroup(self):
        """
        Set the `_title` attribute to the managed entry group's title.
        This method should be called automatically when the entry group's name
        changes while contains at least one entry.
        """
        if self.group:
            self._title = self.group.title
            self.groupTitleChanged.emit(self._title)
[docs]    def onProjectUpdate(self):
        """
        Respond to changes in the Maestro project by updating locally-cached
        variables. Meant to be called from a Maestro callback.
        """
        try:
            group = self.group
        except ProjectException:
            # Prevent traceback reported in PANEL-16311
            return
        with maestro.IgnoreProjectUpdate(self.onProjectUpdate):
            if group and not self._group_empty:
                # Keep the stored group title up to date, in case it was changed
                # by the user in the project table
                self._readTitleFromGroup()
            elif group and self._group_empty:
                # Update the group title from the stored value. This is
                # necessary after the the group has had no entries in it, as
                # empty groups will forget their titles
                self._group_empty = False
                self._writeTitleToGroup()
            else:
                self._group_empty = True
        parent_group = self.parent_group
        if parent_group:
            self._parent_group_name = parent_group.name