Source code for schrodinger.application.jaguar.gui.solvent_selector
"""
A filterable selector for solvents.
Copyright Schrodinger, LLC. All rights reserved.
"""
import csv
from schrodinger.application.jaguar import jaguar_keyword_utils
from schrodinger.application.matsci import msutils
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.Qt.QtCore import Qt
from schrodinger.ui.qt import filter_list
from schrodinger.ui.qt import swidgets
from schrodinger.utils import csv_unicode
[docs]class SolventListWidgetItem(QtWidgets.QListWidgetItem):
"""
A solvent that appears in the selector.
"""
[docs] def __init__(self, name, common, halogenated, aromatic, hydrocarbon,
carbonyl, polar, nonpolar):
super().__init__(name)
self.name = name
self.common = common
self.halogenated = halogenated
self.aromatic = aromatic
self.hydrocarbon = hydrocarbon
self.carbonyl = carbonyl
self.polar = polar
self.nonpolar = nonpolar
[docs]class SolventSelectorFilterListPopUp(filter_list.FilterListPopUp):
"""
A pop up that allows the solvents to be filtered by category.
"""
[docs] def __init__(self, parent):
list_items = self._createListItems()
cbs = self._createFilterCheckBoxes()
super().__init__(parent, list_items, cbs.values(),
'Limit list to matching solvents')
# make the polar and non-polar check boxes mutually exclusive
self._polar_group = swidgets.SRadioButtonGroup(self, radio=False)
self._polar_group.setExclusive(True, uncheckable=True)
self._polar_group.addExistingButton(cbs["polar"])
self._polar_group.addExistingButton(cbs["nonpolar"])
def _createListItems(self):
"""
:return: A tuple of items for the list widget.
:rtype: tuple(SolventListWidgetItem)
"""
list_items = []
with csv_unicode.reader_open(jaguar_keyword_utils.SOLVENTS) as fh:
reader = csv.DictReader(fh)
for row in reader:
name = row.pop("name")
# convert the category values from strings of "0" or "1" to
# Booleans
categories = {
key: msutils.setting_to_bool(val)
for key, val in row.items()
}
list_items.append(SolventListWidgetItem(name, **categories))
return tuple(list_items)
def _createFilterCheckBoxes(self):
"""
:return: A dictionary of filter checkboxes in the form
{`SolventListWidgetItem` attribute name: check box}
:rtype: dict(str, filter_list.FilterCheckBox)
"""
# tuples of (text to display in GUI, attribute name, enabled by default)
cb_text_and_attr_name = (
("Common", "common", True),
("Halogenated", "halogenated", False),
("Aromatic", "aromatic", False),
("Hydrocarbon", "hydrocarbon", False),
("Carbonyl", "carbonyl", False),
("Polar", "polar", False),
("Non-polar", "nonpolar", False),
)
def filter_on(attr_name):
return lambda list_item: getattr(list_item, attr_name)
return {
attr_name: filter_list.FilterCheckBox(cb_text,
filter_on(attr_name),
on_by_default=on_by_default)
for cb_text, attr_name, on_by_default in cb_text_and_attr_name
}
[docs] def getSolvent(self):
"""
:return: The currently selected solvent
:rtype: str or None
"""
current_item = self._list_widget.currentItem()
if not current_item:
return None
return current_item.name
[docs] def setSolvent(self, solvent=None):
"""
Set the current solvent.
:param solvent: Solvent value to be set. If None, no solvent will be
selected.
:type solvent: str or None
:raise ValueError: If the specified solvent was not found.
"""
if solvent is None:
self._list_widget.setCurrentItem(None)
return
items = self._list_widget.findItems(solvent,
Qt.MatchFlag.MatchFixedString)
if len(items) != 1:
raise ValueError(f"Solvent {solvent} not found")
self._list_widget.setCurrentItem(items[0])
[docs]class SolventSelectorFilterListToolButton(
filter_list.ToolButtonWithFilterListPopUp):
"""
Custom tool button with a solvent selector filter list pop up.
"""
POP_UP_CLASS = SolventSelectorFilterListPopUp
solventChanged = QtCore.pyqtSignal(str)
[docs] def __init__(self, parent):
super().__init__(parent)
self.popUpClosing.connect(self._emitSolventChanged)
[docs] def getSolvent(self):
"""
:return: The currently selected solvent
:rtype: str or None
"""
return self._pop_up.getSolvent()
[docs] def setSolvent(self, solvent=None):
"""
Set the current solvent.
:param solvent: Solvent value to be set. If None, no solvent will be
selected.
:type solvent: str or None
:raise ValueError: If the specified solvent was not found.
"""
self._pop_up.setSolvent(solvent)
self._emitSolventChanged()
def _emitSolventChanged(self):
self.solventChanged.emit(self.getSolvent())