source: sasview/src/sas/qtgui/Plotting/SlicerParameters.py @ 84df556

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 84df556 was d6b8a1d, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

More Qt5 related fixes

  • Property mode set to 100644
File size: 6.3 KB
RevLine 
[3bdbfcc]1"""
2Allows users to modify the box slicer parameters.
3"""
[161713c]4import numpy
[57b7ee2]5import functools
[4992ff2]6from PyQt5 import QtCore
7from PyQt5 import QtGui
8from PyQt5 import QtWidgets
9from PyQt5 import QtWebKitWidgets
[3bdbfcc]10
[d6b8a1d]11import sas.qtgui.Utilities.GuiUtils as GuiUtils
12
[3bdbfcc]13# Local UI
[cd2cc745]14from sas.qtgui.UI import main_resources_rc
[83eb5208]15from sas.qtgui.Plotting.UI.SlicerParametersUI import Ui_SlicerParametersUI
[3bdbfcc]16
[4992ff2]17class SlicerParameters(QtWidgets.QDialog, Ui_SlicerParametersUI):
[3bdbfcc]18    """
19    Interaction between the QTableView and the underlying model,
20    passed from a slicer instance.
21    """
[57b7ee2]22    close_signal = QtCore.pyqtSignal()
[161713c]23    def __init__(self, model=None, validate_method=None):
[3bdbfcc]24        super(SlicerParameters, self).__init__()
25
26        self.setupUi(self)
[161713c]27
[3bdbfcc]28        assert isinstance(model, QtGui.QStandardItemModel)
29
30        self.model = model
[161713c]31        self.validate_method = validate_method
[3bdbfcc]32
33        # Define a proxy model so cell enablement can be finegrained.
34        self.proxy = ProxyModel(self)
35        self.proxy.setSourceModel(self.model)
36
37        # Set the proxy model for display in the Table View.
38        self.lstParams.setModel(self.proxy)
39
40        # Disallow edit of the parameter name column.
41        self.lstParams.model().setColumnReadOnly(0, True)
42
[57b7ee2]43        # Specify the validator on the parameter value column.
[161713c]44        self.delegate = EditDelegate(self, validate_method=self.validate_method)
45        self.lstParams.setItemDelegate(self.delegate)
46        self.delegate.refocus_signal.connect(self.onFocus)
[57b7ee2]47
48        # Display Help on clicking the button
[4992ff2]49        self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.onHelp)
[57b7ee2]50
51        # Close doesn't trigger closeEvent automatically, so force it
[4992ff2]52        self.buttonBox.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(functools.partial(self.closeEvent, None))
[57b7ee2]53
[b789967]54        # Disable row number display
55        self.lstParams.verticalHeader().setVisible(False)
[57b7ee2]56        self.lstParams.setAlternatingRowColors(True)
[4992ff2]57        self.lstParams.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
[57b7ee2]58
59        # Header properties for nicer display
60        header = self.lstParams.horizontalHeader()
[4992ff2]61        header.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
[57b7ee2]62        header.setStretchLastSection(True)
63
[161713c]64    def onFocus(self, row, column):
65        """ Set the focus on the cell (row, column) """
66        selection_model = self.lstParams.selectionModel()
67        selection_model.select(self.model.index(row, column), QtGui.QItemSelectionModel.Select)
68        self.lstParams.setSelectionModel(selection_model)
69        self.lstParams.setCurrentIndex(self.model.index(row, column))
[57b7ee2]70
71    def setModel(self, model):
72        """ Model setter """
73        self.model = model
74        self.proxy.setSourceModel(self.model)
75
76    def closeEvent(self, event):
77        """
78        Overwritten close widget method in order to send the close
79        signal to the parent.
80        """
81        self.close_signal.emit()
82        if event:
83            event.accept()
84
85    def onHelp(self):
86        """
87        Display generic data averaging help
88        """
89        location = "docs/sphinx-docs/build/html" + \
90            "/user/sasgui/guiframe/graph_help.html#d-data-averaging"
[4992ff2]91        self.helpView = QtWebKitWidgets.QWebView()
[9a05a8d5]92        self.helpView.load(QtCore.QUrl(location))
93        self.helpView.show()
[b789967]94
[3bdbfcc]95
[4992ff2]96class ProxyModel(QtCore.QIdentityProxyModel):
[3bdbfcc]97    """
98    Trivial proxy model with custom column edit flag
99    """
100    def __init__(self, parent=None):
101        super(ProxyModel, self).__init__(parent)
102        self._columns = set()
103
104    def columnReadOnly(self, column):
[9a05a8d5]105        '''Returns True if column is read only, false otherwise'''
[3bdbfcc]106        return column in self._columns
107
108    def setColumnReadOnly(self, column, readonly=True):
[9a05a8d5]109        '''Add/removes a column from the readonly list'''
[3bdbfcc]110        if readonly:
111            self._columns.add(column)
112        else:
113            self._columns.discard(column)
114
115    def flags(self, index):
[9a05a8d5]116        '''Sets column flags'''
[3bdbfcc]117        flags = super(ProxyModel, self).flags(index)
118        if self.columnReadOnly(index.column()):
119            flags &= ~QtCore.Qt.ItemIsEditable
120        return flags
121
[4992ff2]122class PositiveDoubleEditor(QtWidgets.QLineEdit):
[161713c]123    # a signal to tell the delegate when we have finished editing
124    editingFinished = QtCore.Signal()
[3bdbfcc]125
[161713c]126    def __init__(self, parent=None):
127            # Initialize the editor object
128            super(PositiveDoubleEditor, self).__init__(parent)
129            self.setAutoFillBackground(True)
[d6b8a1d]130            validator = GuiUtils.DoubleValidator()
[b789967]131            # Don't use the scientific notation, cause 'e'.
[d6b8a1d]132            validator.setNotation(GuiUtils.DoubleValidator.StandardNotation)
[161713c]133
134            self.setValidator(validator)
135
136    def focusOutEvent(self, event):
137            # Once focus is lost, tell the delegate we're done editing
138            self.editingFinished.emit()
139
140
[4992ff2]141class EditDelegate(QtWidgets.QStyledItemDelegate):
[161713c]142    refocus_signal = QtCore.pyqtSignal(int, int)
143    def __init__(self, parent=None, validate_method=None):
144        super(EditDelegate, self).__init__(parent)
145        self.editor = None
146        self.index = None
147        self.validate_method = validate_method
148
149    def createEditor(self, parent, option, index):
150        # Creates and returns the custom editor object we will use to edit the cell
151        if not index.isValid():
152            return 0
153
154        result = index.column()
155        if result==1:
156                self.editor = PositiveDoubleEditor(parent)
157                self.index = index
158                return self.editor
159        else:
[4992ff2]160                return QtWidgets.QStyledItemDelegate.createEditor(self, parent, option, index)
[161713c]161
162    def setModelData(self, editor, model, index):
163        """
164        Custom version of the model update, rejecting bad values
165        """
166        self.index = index
167
168        # Find out the changed parameter name and proposed value
169        new_value = self.editor.text().toFloat()[0]
170        param_name = str(model.sourceModel().item(index.row(),0).text())
171
172        validated = True
173        if self.validate_method:
174            # Validate the proposed value in the slicer
175            value_accepted = self.validate_method(param_name, new_value)
176
177        if value_accepted:
178            # Update the model only if value accepted
179            return super(EditDelegate, self).setModelData(editor, model, index)         
Note: See TracBrowser for help on using the repository browser.