Source code for schrodinger.application.jaguar.gui.solvent_selector

"""
A filterable selector for solvents.

Copyright Schrodinger, LLC. All rights reserved.
"""

import csv
from functools import partial

from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.Qt.QtCore import Qt

from schrodinger.application.jaguar import jaguar_keyword_utils
from schrodinger.application.matsci import msutils
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.SCheckboxButtonGroup(self) self._polar_group.addButton(cbs["polar"]) self._polar_group.addButton(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())