Exemple #1
0
    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
Exemple #2
0
 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)
Exemple #3
0
    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)