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())