def createEditor(self, parent, option, index): """Create editor widget""" model = index.model() # TODO: dtype should be taken from the model instead (or even from the actual value?) value = model.get_value(index) if self.dtype.name == "bool": # toggle value value = not value model.setData(index, to_qvariant(value)) return elif value is not np.ma.masked: minvalue, maxvalue = self.minvalue, self.maxvalue if minvalue is not None and maxvalue is not None: msg = "value must be between %s and %s" % (minvalue, maxvalue) elif minvalue is not None: msg = "value must be >= %s" % minvalue elif maxvalue is not None: msg = "value must be <= %s" % maxvalue else: msg = None # Not using a QSpinBox for integer inputs because I could not find # a way to prevent the spinbox/editor from closing if the value is # invalid. Using the builtin minimum/maximum of the spinbox works # but that provides no message so it is less clear. editor = QLineEdit(parent) if is_number(self.dtype): validator = QDoubleValidator(editor) if is_float(self.dtype) \ else QIntValidator(editor) if minvalue is not None: validator.setBottom(minvalue) if maxvalue is not None: validator.setTop(maxvalue) editor.setValidator(validator) def on_editor_text_edited(): if not editor.hasAcceptableInput(): QToolTip.showText(editor.mapToGlobal(QPoint()), msg) else: QToolTip.hideText() if msg is not None: editor.textEdited.connect(on_editor_text_edited) editor.setFont(self.font) editor.setAlignment(Qt.AlignRight) editor.destroyed.connect(self.on_editor_destroyed) self.editor_count += 1 return editor
def convert_value(self, value): """ Parameters ---------- value : str """ dtype = self._data.dtype if dtype.name == "bool": try: return bool(float(value)) except ValueError: return value.lower() == "true" elif dtype.name.startswith("string"): return str(value) elif dtype.name.startswith("unicode"): return to_text_string(value) elif is_float(dtype): return float(value) elif is_number(dtype): return int(value) else: return complex(value)
def _update_digits_scientific(self, scientific=None, digits=None): dtype = self.data_adapter.dtype if dtype.type in (np.str, np.str_, np.bool_, np.bool, np.object_): scientific = False ndecimals = 0 else: data = self.data_adapter.get_sample() # max_digits = self.get_max_digits() # default width can fit 8 chars # FIXME: use max_digits? avail_digits = 8 frac_zeros, int_digits, has_negative = self.format_helper(data) # choose whether or not to use scientific notation # ================================================ if scientific is None: # use scientific format if there are more integer digits than we can display or if we can display more # information that way (scientific format "uses" 4 digits, so we have a net win if we have >= 4 zeros -- # *including the integer one*) # TODO: only do so if we would actually display more information # 0.00001 can be displayed with 8 chars # 1e-05 # would scientific = int_digits > avail_digits or frac_zeros >= 4 # determine best number of decimals to display # ============================================ # TODO: ndecimals vs self.digits => rename self.digits to either frac_digits or ndecimals if digits is not None: ndecimals = digits else: data_frac_digits = self._data_digits(data) if scientific: int_digits = 2 if has_negative else 1 exp_digits = 4 else: exp_digits = 0 # - 1 for the dot ndecimals = avail_digits - 1 - int_digits - exp_digits if ndecimals < 0: ndecimals = 0 if data_frac_digits < ndecimals: ndecimals = data_frac_digits self.digits = ndecimals self.use_scientific = scientific # avoid triggering digits_changed which would cause a useless redraw self.digits_spinbox.blockSignals(True) self.digits_spinbox.setValue(ndecimals) self.digits_spinbox.setEnabled(is_number(dtype)) self.digits_spinbox.blockSignals(False) # avoid triggering scientific_changed which would call this function a second time self.scientific_checkbox.blockSignals(True) self.scientific_checkbox.setChecked(scientific) self.scientific_checkbox.setEnabled(is_number(dtype)) self.scientific_checkbox.blockSignals(False) # 1) setting the format explicitly instead of relying on digits_spinbox.digits_changed to set it because # digits_changed is only triggered when digits actually changed, not when passing from # scientific -> non scientific or number -> object # 2) data model is reset in set_format by default self.set_format(ndecimals, scientific)