source: sasview/src/sas/qtgui/Calculators/DensityPanel.py @ b6f47be

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since b6f47be was b6f47be, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 6 years ago

Allow widget resize. Update model on every text change of molecular
formula line edit.
SASVIEW-1139

  • Property mode set to 100644
File size: 6.9 KB
Line 
1# global
2import logging
3import functools
4from PyQt5 import QtCore
5from PyQt5 import QtGui
6from PyQt5 import QtWidgets
7
8from periodictable import formula as Formula
9
10from sas.qtgui.Utilities.GuiUtils import FormulaValidator
11from sas.qtgui.UI import main_resources_rc
12from sas.qtgui.Utilities.GuiUtils import HELP_DIRECTORY_LOCATION
13
14# Local UI
15from sas.qtgui.Calculators.UI.DensityPanel import Ui_DensityPanel
16
17from sas.qtgui.Utilities.GuiUtils import enum
18from sas.qtgui.Utilities.GuiUtils import formatNumber
19
20MODEL = enum(
21    'MOLECULAR_FORMULA',
22    'MOLAR_MASS',
23    'MOLAR_VOLUME',
24    'MASS_DENSITY',
25)
26
27MODES = enum(
28    'VOLUME_TO_DENSITY',
29    'DENSITY_TO_VOLUME',
30)
31
32def toMolarMass(formula):
33    AVOGADRO = 6.02214129e23
34
35    try:
36        f = Formula(str(formula))
37        return "%g" % (f.molecular_mass * AVOGADRO)
38    except:
39        return ""
40
41
42class DensityPanel(QtWidgets.QDialog):
43
44    def __init__(self, parent=None):
45        super(DensityPanel, self).__init__()
46
47        self.mode = None
48        self.manager = parent
49        self.setupUi()
50        self.setupModel()
51        self.setupMapper()
52
53    def setupUi(self):
54        self.ui = Ui_DensityPanel()
55        self.ui.setupUi(self)
56
57        #self.setFixedSize(self.minimumSizeHint())
58        self.resize(self.minimumSizeHint())
59
60        # set validators
61        #self.ui.editMolecularFormula.setValidator(FormulaValidator(self.ui.editMolecularFormula))
62
63        rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?")
64        self.ui.editMolarVolume.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMolarVolume))
65        self.ui.editMassDensity.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMassDensity))
66
67        # signals
68        self.ui.editMolarVolume.textEdited.connect(functools.partial(self.setMode, MODES.VOLUME_TO_DENSITY))
69        self.ui.editMassDensity.textEdited.connect(functools.partial(self.setMode, MODES.DENSITY_TO_VOLUME))
70
71        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
72        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
73
74    def setupModel(self):
75        self.model = QtGui.QStandardItemModel(self)
76        self.model.setItem(MODEL.MOLECULAR_FORMULA, QtGui.QStandardItem())
77        self.model.setItem(MODEL.MOLAR_MASS       , QtGui.QStandardItem())
78        self.model.setItem(MODEL.MOLAR_VOLUME     , QtGui.QStandardItem())
79        self.model.setItem(MODEL.MASS_DENSITY     , QtGui.QStandardItem())
80
81        self.model.dataChanged.connect(self.dataChanged)
82
83        self.ui.editMolarVolume.textEdited.connect(self.volumeChanged)
84        self.ui.editMassDensity.textEdited.connect(self.massChanged)
85        self.ui.editMolecularFormula.textEdited.connect(self.formulaChanged)
86
87        self.modelReset()
88
89    def setupMapper(self):
90        self.mapper = QtWidgets.QDataWidgetMapper(self)
91        self.mapper.setModel(self.model)
92        self.mapper.setOrientation(QtCore.Qt.Vertical)
93
94        self.mapper.addMapping(self.ui.editMolecularFormula, MODEL.MOLECULAR_FORMULA)
95        self.mapper.addMapping(self.ui.editMolarMass       , MODEL.MOLAR_MASS)
96        self.mapper.addMapping(self.ui.editMolarVolume     , MODEL.MOLAR_VOLUME)
97        self.mapper.addMapping(self.ui.editMassDensity     , MODEL.MASS_DENSITY)
98
99        self.mapper.toFirst()
100
101    def dataChanged(self, top, bottom):
102        for index in range(top.row(), bottom.row() + 1):
103            if index == MODEL.MOLECULAR_FORMULA:
104                molarMass = toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text())
105                molarMass = formatNumber(molarMass, high=True)
106                self.model.item(MODEL.MOLAR_MASS).setText(molarMass)
107
108                if self.mode == MODES.VOLUME_TO_DENSITY:
109                    self._updateDensity()
110                elif self.mode == MODES.DENSITY_TO_VOLUME:
111                    self._updateVolume()
112
113            elif index == MODEL.MOLAR_VOLUME and self.mode == MODES.VOLUME_TO_DENSITY:
114                self._updateDensity()
115
116            elif index == MODEL.MASS_DENSITY and self.mode == MODES.DENSITY_TO_VOLUME:
117                self._updateVolume()
118
119    def volumeChanged(self, current_text):
120        try:
121            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
122            molarVolume = float(current_text)
123
124            molarDensity = molarMass / molarVolume
125            molarDensity = formatNumber(molarDensity, high=True)
126            self.model.item(MODEL.MASS_DENSITY).setText(str(molarDensity))
127
128        except (ArithmeticError, ValueError):
129            self.model.item(MODEL.MASS_DENSITY).setText("")
130
131    def massChanged(self, current_text):
132        try:
133            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
134            molarDensity = float(current_text)
135
136            molarVolume = molarMass / molarDensity
137            molarVolume = formatNumber(molarVolume, high=True)
138            self.model.item(MODEL.MOLAR_VOLUME).setText(str(molarVolume))
139
140        except (ArithmeticError, ValueError):
141            self.model.item(MODEL.MOLAR_VOLUME).setText("")
142
143    def formulaChanged(self, current_text):
144        try:
145            molarMass = toMolarMass(current_text)
146            # if this doesn't fail, update the model item for formula
147            # so related values can get recomputed
148            self.model.item(MODEL.MOLECULAR_FORMULA).setText(current_text)
149
150        except (ArithmeticError, ValueError):
151            self.model.item(MODEL.MOLAR_VOLUME).setText("")
152
153    def setMode(self, mode):
154        self.mode = mode
155
156    def _updateDensity(self):
157        try:
158            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
159            molarVolume = float(self.model.item(MODEL.MOLAR_VOLUME).text())
160
161            molarDensity = molarMass / molarVolume
162            molarDensity = formatNumber(molarDensity, high=True)
163            self.model.item(MODEL.MASS_DENSITY).setText(str(molarDensity))
164
165        except (ArithmeticError, ValueError):
166            self.model.item(MODEL.MASS_DENSITY).setText("")
167
168    def _updateVolume(self):
169        try:
170            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
171            molarDensity = float(self.model.item(MODEL.MASS_DENSITY).text())
172
173            molarVolume = molarMass / molarDensity
174            molarVolume = formatNumber(molarVolume, high=True)
175            self.model.item(MODEL.MOLAR_VOLUME).setText(str(molarVolume))
176
177        except (ArithmeticError, ValueError):
178            self.model.item(MODEL.MOLAR_VOLUME).setText("")
179
180    def modelReset(self):
181        try:
182            self.setMode(None)
183            self.model.item(MODEL.MOLECULAR_FORMULA).setText("H2O")
184            self.model.item(MODEL.MOLAR_VOLUME     ).setText("")
185            self.model.item(MODEL.MASS_DENSITY     ).setText("")
186        finally:
187            pass
188
189    def displayHelp(self):
190        location = "/user/qtgui/Calculators/density_calculator_help.html"
191        self.manager.showHelp(location)
192
193
Note: See TracBrowser for help on using the repository browser.