Esempio n. 1
0
class RangeFilter(QtGui.QWidget):
    def __init__(self, *args):
        super(RangeFilter, self).__init__(*args)

        self._createSpinBoxes()
        self.connect(self.minSpin, QtCore.SIGNAL("editingFinished()"),
                     self._released)
        self.connect(self.maxSpin, QtCore.SIGNAL("editingFinished()"),
                     self._released)

        self._createSlider()
        self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"),
                     self._released)

        #self.setMinimum( 0 )
        #self.setLowValue( 0 )
        #self.setMaximum( 100 )
        #self.setHighValue( 100 )

        self.recreateUi()

    def _createSpinBoxes(self):
        self.minSpin = QtGui.QSpinBox(self)
        self.maxSpin = QtGui.QSpinBox(self)
        self.connect(self.minSpin, QtCore.SIGNAL("valueChanged(int)"),
                     self.setLowValue)
        self.connect(self.maxSpin, QtCore.SIGNAL("valueChanged(int)"),
                     self.setHighValue)

    def _createSlider(self):
        self.slider = RangeSlider(self)
        self.connect(self.slider, QtCore.SIGNAL("sliderMoved(int)"),
                     self._moved)

    def recreateUi(self):
        layout = self.layout()
        if not layout:
            layout = QtGui.QGridLayout(self)
            layout.setMargin(0)
            self.setLayout(layout)

        else:
            layout.removeWidget(self.maxSpin)
            layout.removeWidget(self.slider)
            layout.removeWidget(self.minSpin)

        if self.slider.orientation() == QtCore.Qt.Horizontal:
            layout.addWidget(self.minSpin, 0, 0)
            layout.addWidget(self.slider, 0, 1)
            layout.addWidget(self.maxSpin, 0, 2)
            self.slider.setMinimumSize(QtCore.QSize(30, 0))

        else:
            layout.addWidget(self.maxSpin, 0, 0)
            layout.addWidget(self.slider, 1, 0)
            layout.addWidget(self.minSpin, 2, 0)
            self.slider.setMinimumSize(QtCore.QSize(0, 30))

    def orientation(self):
        return self.slider.orientation()

    def setOrientation(self, val):
        self.slider.setOrientation(val)
        self.recreateUi()

    def isActive(self):
        if self.lowValue() > self.minimum(): return True
        if self.highValue() < self.maximum(): return True
        return False

    def checkValue(self, val):
        val = self._getValue(val)
        if val is None: return False
        return val >= self._getValue(
            self.lowValue()) and val <= self._getValue(self.highValue())

    def _toSliderValue(self, val):
        return val

    def _fromSliderValue(self, val):
        return val

    def minimum(self):
        return self.minSpin.minimum()

    def maximum(self):
        return self.maxSpin.maximum()

    def setMinimum(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        self.minSpin.setMinimum(val)
        self.maxSpin.setMinimum(val)
        self.slider.setMinimum(self._toSliderValue(val))

    def setMaximum(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        self.minSpin.setMaximum(val)
        self.maxSpin.setMaximum(val)
        self.slider.setMaximum(self._toSliderValue(val))

        # avoid resizing when the max value changes
        minSpinSize = self.minSpin.sizeHint()
        maxSpinSize = self.maxSpin.sizeHint()
        w, h = max(minSpinSize.width(),
                   maxSpinSize.width()), max(minSpinSize.height(),
                                             maxSpinSize.height())
        self.minSpin.setFixedSize(w, h)
        self.maxSpin.setFixedSize(w, h)

    def lowValue(self):
        return self.minSpin.value()

    def highValue(self):
        return self.maxSpin.value()

    def setLowValue(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        minVal = self._getValue(self.minimum())
        if val < minVal:
            val = minVal

        if val == self._getValue(self.lowValue()):
            return

        self.minSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.minSpin.setValue(val)
        self.maxSpin.setMinimum(val)
        self.slider.setLowValue(self._toSliderValue(val))
        self.minSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit(QtCore.SIGNAL("lowValueChanged"), val)

    def setHighValue(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        maxVal = self._getValue(self.maximum())
        if val > maxVal:
            val = maxVal

        if val == self._getValue(self.highValue()):
            return

        self.maxSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.maxSpin.setValue(val)
        self.minSpin.setMaximum(val)
        self.slider.setHighValue(self._toSliderValue(val))
        self.maxSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit(QtCore.SIGNAL("highValueChanged"), val)

    def _updateValues(self):
        # avoid multiple signals when values don't change
        if hasattr(self, '_lastLowValueOnReleased') and hasattr(
                self, '_lastHighValueOnReleased'):
            if self._lastLowValueOnReleased == self.lowValue(
            ) and self._lastHighValueOnReleased == self.highValue():
                return False

        self._lastLowValueOnReleased = self.lowValue()
        self._lastHighValueOnReleased = self.highValue()
        return True

    def _moved(self, *args):
        self._sliderLowValueChanged(self.slider.lowValue())
        self._sliderHighValueChanged(self.slider.highValue())
        self.emit(QtCore.SIGNAL("valuesChanged"), self.lowValue(),
                  self.highValue())

    def _released(self, *args):
        if not self._updateValues():
            return
        # do not emit the signal now, wait the event loop
        QtCore.QTimer.singleShot(0, self._onChangeFinished)

    def _onChangeFinished(self):
        self.emit(QtCore.SIGNAL("changeFinished"),
                  self._lastLowValueOnReleased, self._lastHighValueOnReleased)

    def _sliderLowValueChanged(self, val):
        self.setLowValue(self._fromSliderValue(val))

    def _sliderHighValueChanged(self, val):
        self.setHighValue(self._fromSliderValue(val))

    @classmethod
    def _getValue(self, value):
        if not isinstance(value, QtCore.QVariant):
            return value

        if not value.isValid(): return

        val, ok = value.toInt()
        if ok: return val

        return int(float(value.toString()))
Esempio n. 2
0
class RangeFilter(QtGui.QWidget):
    """ A widget to select int ranges. 
        It displays a RangeSlider between two QSpinbox widgets. 

        @emit lowValueChanged signal when the low value is changed
        @emit highValueChanged signal when the high value is changed
        @emit valuesChanged signal when either the low or high value is changed
        @emit changeFinished signal when the slider is released in a new 
                position or the spinboxes editing finished
    """

    def __init__(self, *args):
        super(RangeFilter, self).__init__(*args)

        self._createSpinBoxes()
        self.connect( self.minSpin, QtCore.SIGNAL("editingFinished()"), self._released )
        self.connect( self.maxSpin, QtCore.SIGNAL("editingFinished()"), self._released )

        self._createSlider()
        self.connect( self.slider, QtCore.SIGNAL("sliderReleased()"), self._released )

        #self.setMinimum( 0 )
        #self.setLowValue( 0 )
        #self.setMaximum( 100 )
        #self.setHighValue( 100 )

        self._updateUi()

    def _createSpinBoxes(self):
        self.minSpin = QtGui.QSpinBox(self)
        self.maxSpin = QtGui.QSpinBox(self)
        self.connect( self.minSpin, QtCore.SIGNAL("valueChanged(int)"), self.setLowValue )
        self.connect( self.maxSpin, QtCore.SIGNAL("valueChanged(int)"), self.setHighValue )

    def _createSlider(self):
        self.slider = RangeSlider(self)
        self.connect( self.slider, QtCore.SIGNAL("sliderMoved(int)"), self._moved )

    def _updateUi(self):
        layout = self.layout()
        if not layout:
            layout = QtGui.QGridLayout(self)
            layout.setMargin(0)
            self.setLayout( layout )

        else:
            layout.removeWidget(self.maxSpin)
            layout.removeWidget(self.slider)
            layout.removeWidget(self.minSpin)

        if self.slider.orientation() == QtCore.Qt.Horizontal:
            layout.addWidget(self.minSpin, 0, 0)
            layout.addWidget(self.slider, 0, 1)
            layout.addWidget(self.maxSpin, 0, 2)
            self.slider.setMinimumSize(QtCore.QSize(30, 0))

        else:
            layout.addWidget(self.maxSpin, 0, 0)
            layout.addWidget(self.slider, 1, 0)
            layout.addWidget(self.minSpin, 2, 0)
            self.slider.setMinimumSize(QtCore.QSize(0, 30))


    def orientation(self):
        """ Get the widget orientation. """
        return self.slider.orientation()

    def setOrientation(self, val):
        """ Set the widget orientation. """
        self.slider.setOrientation( val )
        self._updateUi()

    def isActive(self):
        """ Check if the filter widget has low or high values different 
            from respectively the mininimum and maximum values.

            @returns True if low value is greather than the minimum OR 
                    the high value is less than the maximum, False otherwise
        """
        return self.lowValue() > self.minimum() or self.highValue() < self.maximum()


    def checkValue(self, val):
        """ Check if val is within the range [min, max]. 

            @returns True if val is in the range, False otherwise
        """

        val = self._getValue(val)
        if val is None: return False
        return val >= self._getValue( self.lowValue() ) and val <= self._getValue( self.highValue() )


    def _toSliderValue(self, val):
        return val

    def _fromSliderValue(self, val):
        return val


    def minimum(self):
        """ Get the minimum value. """
        return self.minSpin.minimum()

    def maximum(self):
        """ Get the maximum value. """
        return self.maxSpin.maximum()

    def setMinimum(self, value):
        """ Set the minimum value. """

        val = self._getValue( value )
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        self.minSpin.setMinimum(val)
        self.maxSpin.setMinimum(val)
        self.slider.setMinimum( self._toSliderValue(val) )

    def setMaximum(self, value):
        """ Set the maximum value. """

        val = self._getValue( value )
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value) )

        self.minSpin.setMaximum(val)
        self.maxSpin.setMaximum(val)
        self.slider.setMaximum( self._toSliderValue(val) )

        # avoid resizing when the max value changes
        minSpinSize = self.minSpin.sizeHint()
        maxSpinSize = self.maxSpin.sizeHint()
        w,h = max(minSpinSize.width(), maxSpinSize.width()), max(minSpinSize.height(), maxSpinSize.height())
        self.minSpin.setFixedSize( w, h )
        self.maxSpin.setFixedSize( w, h )


    def lowValue(self):
        return self.minSpin.value()

    def highValue(self):
        return self.maxSpin.value()

    def setLowValue(self, value):
        """ Set the low value. """

        val = self._getValue( value )
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value) )

        minVal = self._getValue( self.minimum() )
        if val < minVal:
            val = minVal

        if val == self._getValue( self.lowValue() ):
            return

        self.minSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.minSpin.setValue( val )
        self.maxSpin.setMinimum( val )
        self.slider.setLowValue( self._toSliderValue(val) )
        self.minSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit( QtCore.SIGNAL("lowValueChanged"), val )

    def setHighValue(self, value):
        """ Set the high value. """

        val = self._getValue( value )
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value) )

        maxVal = self._getValue(self.maximum())
        if val > maxVal:
            val = maxVal

        if val == self._getValue(self.highValue()):
            return

        self.maxSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.maxSpin.setValue( val )
        self.minSpin.setMaximum( val )
        self.slider.setHighValue( self._toSliderValue(val) )
        self.maxSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit( QtCore.SIGNAL("highValueChanged"), val )


    def _updateValues(self):
        # avoid multiple signals when values don't change
        if hasattr(self, '_lastLowValueOnReleased') and hasattr(self, '_lastHighValueOnReleased'):
            if self._lastLowValueOnReleased == self.lowValue() and self._lastHighValueOnReleased == self.highValue():
                return False

        self._lastLowValueOnReleased = self.lowValue()
        self._lastHighValueOnReleased = self.highValue()
        return True

    def _moved(self, *args):
        self._sliderLowValueChanged(self.slider.lowValue())
        self._sliderHighValueChanged(self.slider.highValue())
        self.emit( QtCore.SIGNAL("valuesChanged"), self.lowValue(), self.highValue() )

    def _released(self, *args):
        if not self._updateValues():
            return
        # do not emit the signal now, wait the event loop
        QtCore.QTimer.singleShot(0, self._onChangeFinished)

    def _onChangeFinished(self):
        self.emit( QtCore.SIGNAL("changeFinished"), self._lastLowValueOnReleased, self._lastHighValueOnReleased )


    def _sliderLowValueChanged(self, val):
        self.setLowValue( self._fromSliderValue(val) )

    def _sliderHighValueChanged(self, val):
        self.setHighValue( self._fromSliderValue(val) )


    @classmethod
    def _getValue(self, value):
        if not isinstance(value, QtCore.QVariant): 
            return value

        if not value.isValid(): return

        val, ok = value.toInt()
        if ok: return val

        return int(float(value.toString()))
Esempio n. 3
0
class RangeFilter(QtGui.QWidget):
    def __init__(self, *args):
        super(RangeFilter, self).__init__(*args)

        self._createSpinBoxes()
        self.connect(self.minSpin, QtCore.SIGNAL("editingFinished()"),
                     self._released)
        self.connect(self.maxSpin, QtCore.SIGNAL("editingFinished()"),
                     self._released)

        self._createSlider()
        self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"),
                     self._released)

        self.recreateUi()

    def _createSpinBoxes(self):
        self.minSpin = QtGui.QSpinBox(self)
        self.maxSpin = QtGui.QSpinBox(self)
        self.connect(self.minSpin, QtCore.SIGNAL("valueChanged(int)"),
                     self.setLowValue)
        self.connect(self.maxSpin, QtCore.SIGNAL("valueChanged(int)"),
                     self.setHighValue)

    def _createSlider(self):
        self.slider = RangeSlider(self)
        self.connect(self.slider, QtCore.SIGNAL("sliderMoved(int)"),
                     self._moved)

    def recreateUi(self):
        layout = self.layout()
        if not layout:
            layout = QtGui.QGridLayout(self)
            layout.setMargin(0)
            self.setLayout(layout)

        else:
            layout.removeWidget(self.maxSpin)
            layout.removeWidget(self.slider)
            layout.removeWidget(self.minSpin)

        if self.slider.orientation() == QtCore.Qt.Horizontal:
            layout.addWidget(self.minSpin, 0, 0)
            layout.addWidget(self.slider, 0, 1)
            layout.addWidget(self.maxSpin, 0, 2)
            self.slider.setMinimumSize(QtCore.QSize(30, 0))

        else:
            layout.addWidget(self.maxSpin, 0, 0)
            layout.addWidget(self.slider, 1, 0)
            layout.addWidget(self.minSpin, 2, 0)
            self.slider.setMinimumSize(QtCore.QSize(0, 30))

    def orientation(self):
        return self.slider.orientation()

    def setOrientation(self, val):
        self.slider.setOrientation(val)
        self.recreateUi()

    def isActive(self):
        if self.lowValue() > self.minimum():
            return True
        if self.highValue() < self.maximum():
            return True
        return False

    def checkValue(self, val):
        val = self._getValue(val)
        if val is None:
            return False
        return (self._getValue(self.lowValue()) <= val <=
                self._getValue(self.highValue()))

    def _toSliderValue(self, val):
        return val

    def _fromSliderValue(self, val):
        return val

    def minimum(self):
        return self.minSpin.minimum()

    def maximum(self):
        return self.maxSpin.maximum()

    def setMinimum(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        self.minSpin.setMinimum(val)
        self.maxSpin.setMinimum(val)
        self.slider.setMinimum(self._toSliderValue(val))

    def setMaximum(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        self.minSpin.setMaximum(val)
        self.maxSpin.setMaximum(val)
        self.slider.setMaximum(self._toSliderValue(val))

        # avoid resizing when the max value changes
        minSpinSize = self.minSpin.sizeHint()
        maxSpinSize = self.maxSpin.sizeHint()
        w, h = max(minSpinSize.width(), maxSpinSize.width()), max(
            minSpinSize.height(), maxSpinSize.height())
        self.minSpin.setFixedSize(w, h)
        self.maxSpin.setFixedSize(w, h)

    def lowValue(self):
        return self.minSpin.value()

    def highValue(self):
        return self.maxSpin.value()

    def setLowValue(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        minVal = self._getValue(self.minimum())
        if val < minVal:
            val = minVal

        if val == self._getValue(self.lowValue()):
            return

        self.minSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.minSpin.setValue(val)
        self.maxSpin.setMinimum(val)
        self.slider.setLowValue(self._toSliderValue(val))
        self.minSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit(QtCore.SIGNAL("lowValueChanged"), val)

    def setHighValue(self, value):
        val = self._getValue(value)
        if val is None:
            raise TypeError("invalid type for '%s'" % repr(value))

        maxVal = self._getValue(self.maximum())
        if val > maxVal:
            val = maxVal

        if val == self._getValue(self.highValue()):
            return

        self.maxSpin.blockSignals(True)
        self.slider.blockSignals(True)
        self.maxSpin.setValue(val)
        self.minSpin.setMaximum(val)
        self.slider.setHighValue(self._toSliderValue(val))
        self.maxSpin.blockSignals(False)
        self.slider.blockSignals(False)

        self.emit(QtCore.SIGNAL("highValueChanged"), val)

    def _updateValues(self):
        # avoid multiple signals when values don't change
        if hasattr(self, '_lastLowValueOnReleased') and \
                hasattr(self, '_lastHighValueOnReleased'):
            if self._lastLowValueOnReleased == self.lowValue() and \
                    self._lastHighValueOnReleased == self.highValue():
                return False

        self._lastLowValueOnReleased = self.lowValue()
        self._lastHighValueOnReleased = self.highValue()
        return True

    def _moved(self, *args):
        self._sliderLowValueChanged(self.slider.lowValue())
        self._sliderHighValueChanged(self.slider.highValue())
        self.emit(QtCore.SIGNAL("valuesChanged"), self.lowValue(),
                  self.highValue())

    def _released(self, *args):
        if not self._updateValues():
            return
            # do not emit the signal now, wait the event loop
        QtCore.QTimer.singleShot(0, self._onChangeFinished)

    def _onChangeFinished(self):
        self.emit(QtCore.SIGNAL("changeFinished"),
                  self._lastLowValueOnReleased,
                  self._lastHighValueOnReleased)

    def _sliderLowValueChanged(self, val):
        self.setLowValue(self._fromSliderValue(val))

    def _sliderHighValueChanged(self, val):
        self.setHighValue(self._fromSliderValue(val))

    @classmethod
    def _getValue(cls, value):
        return value