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

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 dfd8233 was cd2cc745, checked in by Piotr Rozyczko <rozyczko@…>, 8 years ago

Workaround for the resource file requirement in each UI directory

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