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