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

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

Replace Apply button menu driven functionality with additional button.
Removed Cancel.
Removed the window system context help button from all affected widgets.
SASVIEW-1239

  • Property mode set to 100644
File size: 7.1 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        # disable the context help icon
51        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)
52
53        self.setupModel()
54        self.setupMapper()
55
56    def setupUi(self):
57        self.ui = Ui_DensityPanel()
58        self.ui.setupUi(self)
59
60        #self.setFixedSize(self.minimumSizeHint())
61        self.resize(self.minimumSizeHint())
62
63        # set validators
64        #self.ui.editMolecularFormula.setValidator(FormulaValidator(self.ui.editMolecularFormula))
65
66        rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?")
67        self.ui.editMolarVolume.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMolarVolume))
68        self.ui.editMassDensity.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMassDensity))
69
70        # signals
71        self.ui.editMolarVolume.textEdited.connect(functools.partial(self.setMode, MODES.VOLUME_TO_DENSITY))
72        self.ui.editMassDensity.textEdited.connect(functools.partial(self.setMode, MODES.DENSITY_TO_VOLUME))
73
74        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
75        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
76
77    def setupModel(self):
78        self.model = QtGui.QStandardItemModel(self)
79        self.model.setItem(MODEL.MOLECULAR_FORMULA, QtGui.QStandardItem())
80        self.model.setItem(MODEL.MOLAR_MASS       , QtGui.QStandardItem())
81        self.model.setItem(MODEL.MOLAR_VOLUME     , QtGui.QStandardItem())
82        self.model.setItem(MODEL.MASS_DENSITY     , QtGui.QStandardItem())
83
84        self.model.dataChanged.connect(self.dataChanged)
85
86        self.ui.editMolarVolume.textEdited.connect(self.volumeChanged)
87        self.ui.editMassDensity.textEdited.connect(self.massChanged)
88        self.ui.editMolecularFormula.textEdited.connect(self.formulaChanged)
89
90        self.modelReset()
91
92    def setupMapper(self):
93        self.mapper = QtWidgets.QDataWidgetMapper(self)
94        self.mapper.setModel(self.model)
95        self.mapper.setOrientation(QtCore.Qt.Vertical)
96
97        self.mapper.addMapping(self.ui.editMolecularFormula, MODEL.MOLECULAR_FORMULA)
98        self.mapper.addMapping(self.ui.editMolarMass       , MODEL.MOLAR_MASS)
99        self.mapper.addMapping(self.ui.editMolarVolume     , MODEL.MOLAR_VOLUME)
100        self.mapper.addMapping(self.ui.editMassDensity     , MODEL.MASS_DENSITY)
101
102        self.mapper.toFirst()
103
104    def dataChanged(self, top, bottom):
105        for index in range(top.row(), bottom.row() + 1):
106            if index == MODEL.MOLECULAR_FORMULA:
107                molarMass = toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text())
108                molarMass = formatNumber(molarMass, high=True)
109                self.model.item(MODEL.MOLAR_MASS).setText(molarMass)
110
111                if self.mode == MODES.VOLUME_TO_DENSITY:
112                    self._updateDensity()
113                elif self.mode == MODES.DENSITY_TO_VOLUME:
114                    self._updateVolume()
115
116            elif index == MODEL.MOLAR_VOLUME and self.mode == MODES.VOLUME_TO_DENSITY:
117                self._updateDensity()
118
119            elif index == MODEL.MASS_DENSITY and self.mode == MODES.DENSITY_TO_VOLUME:
120                self._updateVolume()
121
122    def volumeChanged(self, current_text):
123        try:
124            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
125            molarVolume = float(current_text)
126
127            molarDensity = molarMass / molarVolume
128            molarDensity = formatNumber(molarDensity, high=True)
129            self.model.item(MODEL.MASS_DENSITY).setText(str(molarDensity))
130
131        except (ArithmeticError, ValueError):
132            self.model.item(MODEL.MASS_DENSITY).setText("")
133
134    def massChanged(self, current_text):
135        try:
136            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
137            molarDensity = float(current_text)
138
139            molarVolume = molarMass / molarDensity
140            molarVolume = formatNumber(molarVolume, high=True)
141            self.model.item(MODEL.MOLAR_VOLUME).setText(str(molarVolume))
142
143        except (ArithmeticError, ValueError):
144            self.model.item(MODEL.MOLAR_VOLUME).setText("")
145
146    def formulaChanged(self, current_text):
147        try:
148            molarMass = toMolarMass(current_text)
149            # if this doesn't fail, update the model item for formula
150            # so related values can get recomputed
151            self.model.item(MODEL.MOLECULAR_FORMULA).setText(current_text)
152
153        except (ArithmeticError, ValueError):
154            self.model.item(MODEL.MOLAR_VOLUME).setText("")
155
156    def setMode(self, mode):
157        self.mode = mode
158
159    def _updateDensity(self):
160        try:
161            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
162            molarVolume = float(self.model.item(MODEL.MOLAR_VOLUME).text())
163
164            molarDensity = molarMass / molarVolume
165            molarDensity = formatNumber(molarDensity, high=True)
166            self.model.item(MODEL.MASS_DENSITY).setText(str(molarDensity))
167
168        except (ArithmeticError, ValueError):
169            self.model.item(MODEL.MASS_DENSITY).setText("")
170
171    def _updateVolume(self):
172        try:
173            molarMass = float(toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()))
174            molarDensity = float(self.model.item(MODEL.MASS_DENSITY).text())
175
176            molarVolume = molarMass / molarDensity
177            molarVolume = formatNumber(molarVolume, high=True)
178            self.model.item(MODEL.MOLAR_VOLUME).setText(str(molarVolume))
179
180        except (ArithmeticError, ValueError):
181            self.model.item(MODEL.MOLAR_VOLUME).setText("")
182
183    def modelReset(self):
184        try:
185            self.setMode(None)
186            self.model.item(MODEL.MOLECULAR_FORMULA).setText("H2O")
187            self.model.item(MODEL.MOLAR_VOLUME     ).setText("")
188            self.model.item(MODEL.MASS_DENSITY     ).setText("")
189        finally:
190            pass
191
192    def displayHelp(self):
193        location = "/user/qtgui/Calculators/density_calculator_help.html"
194        self.manager.showHelp(location)
195
196
Note: See TracBrowser for help on using the repository browser.