Пример #1
0
    def makeSettingsButton(self, XnatSetting):
        """ Constructs a setting button with a wrench icon that
            opens the appropriate settings tab.
        """
        button = HoverButton()
        button.setIcon(qt.QIcon(os.path.join(self.MODULE.GLOBALS.LOCAL_URIS["icons"], "wrench.png")))
        button.setFixedWidth(23)
        button.setFixedHeight(17)
        button.setDefaultStyleSheet(
            "border: 1px solid transparent; border-radius: 2px; background-color: transparent; margin-left: 5px; text-align: left; padding-left: 0px; "
        )
        button.setHoverStyleSheet(
            "border: 1px solid rgb(150,150,150); border-radius: 2px; background-color: transparent; margin-left: 5px; text-align: left; padding-left: 0px;"
        )

        def openSettings():
            self.MODULE.XnatSettingsWindow.showWindow(XnatSetting.tabTitle)

        button.connect("clicked()", openSettings)
        return button
Пример #2
0
class AnimatedCollapsible(ctk.ctkExpandableWidget):
    """ Descriptor above.
    """
    
    def __init__(self, parent, title, maxHeight = 1000, minHeight = 60):
        """ Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

            

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()


        
        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()


        
        #-------------------- 
        # Set the arrow characters, 
        # described accordingly.
        #--------------------    
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'


        
        #-------------------- 
        # Set Collapsed Height
        #-------------------- 
        self.collapsedHeight = 30



        #-------------------- 
        # Set the min/max heights.
        #-------------------- 
        self.minHeight = minHeight
        self.maxHeight = maxHeight



        #-------------------- 
        # Set the toggleButton's height and width
        #-------------------- 
        self.toggleHeight = 16
        self.toggleWidth = 80



        #-------------------- 
        # Make sure the widget is 100% its parent's width.
        #--------------------        
        self.setStyleSheet('width: 100%')


        
        #-------------------- 
        # Set the animation duration
        #--------------------
        self.animDuration = 300


        
        #-------------------- 
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored, qt.QSizePolicy.MinimumExpanding)


        
        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.easingCurve = qt.QEasingCurve(2);


        
        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minHeight)
        

        
        #----------------
        # set the Title
        #----------------       
        self.title = title


        
        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')
        self.toggleButton.setDefaultStyleSheet('#animatedCollapsibleToggleButton {border: 1px solid transparent; background-color: white; margin-left: 5px; text-align: left; padding-left: 5px;}')
        self.toggleButton.setHoverStyleSheet('#animatedCollapsibleToggleButton {border: 1px solid rgb(200,200,200); background-color: white; border-radius: 2px; margin-left: 5px; text-align: left; padding-left: 5px;}')
        self.configureButton(True)
     

        
        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from 
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')
        self.frame.setStyleSheet('#animateCollapsibleFrame {margin-top: 9px; border: 2px solid lightgray; padding-top: 5px; padding-left: 2px; padding-right: 2px; padding-bottom: 2px}')

        
        
        #----------------
        # Stack the button on top of the frame via a 
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)
        


        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)



        #----------------
        # Set the sayout
        #----------------        
        self.setLayout(self.stackedLayout)


        
        #----------------
        # Init the animation group and callbacks.
        #----------------  
        self.animations = qt.QParallelAnimationGroup()
        self.onAnimate = None
        self.onCollapse = None
        self.onExpand = None
        self.ContentsWidgets = []


        
        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True



        #----------------
        # Set the stretch height.
        #
        # NOTE: This is different from the maximumHeight,
        # it's a target height that the user sets so that
        # the collapsible will stretch as far as self.stretchHeight
        # dictates once its expanded.  If we didn't have this 
        # variable, the the widget would have a sendentary height
        # within a layout, not stretching to the layout's
        # maximum extents.
        #
        #
        # TODO: Ideally this parameter would be more of a percentage
        # but setting stylesheet percentages is not possible, becase
        # we are manipulating the .maximumHeight' property of the widget 
        # during the animation.
        # Need to determine a more elegant way of of setting the 'stretch'
        # height to '100%' or equivalent.
        #----------------
        self.stretchHeight = None

            
        

    def suspendAnimationDuration(self, suspend):
        """ Suspends the animation length by converting
            the duration to 0, saving the previous state.
            When the user sets the 'suspend' argument to 
            'False' then the previous animation state is 
            restored.
        """
        if suspend:
            self.originalAnimDuration = self.animDuration
            self.animDuration = 0    
        else:
            self.animDuration = self.originalAnimDuration


            
        
    def setAnimationDuration(self, duration):
        """ As stated.
        """
        self.animDuration = duration;
        



    def configureButton(self, toggled):
        """ Modifies the arrow character of the button
            title to match the 'toggled' state and also
            sets its text to 'self.title.'
        """
        arrowChr = self.downArrowChar if toggled else self.rightArrowChar
        self.toggleButton.setText(arrowChr + '  ' + self.title)
        self.toggleButton.setFixedHeight(17)
        self.toggleButton.setMinimumWidth(10)
        self.toggleButton.setMaximumWidth(110)

  

        

    def setWidget(self, widget):
        """ Similar to the 'setWidget' function
            of a QWidget: sets the internal contents
            of the collapsible.
        """
        self.ContentsWidgets = [widget]
        layout = qt.QHBoxLayout()
        layout.addWidget(widget)
        layout.setContentsMargins(0,0,0,0)
        self.frame.setLayout(layout)

        
            
        
    def setOnCollapse(self, callback):
        """ Sets the callback for AFTER widget
            is collapsed.
        """
        self.onCollapse = callback



        
    def setOnExpand(self, callback):
        """ Sets the callback for AFTER the 
            widget's expansion.
        """
        self.onExpand = callback



        
    def setOnAnimate(self, callback):
        """ Sets the callback for DURING the
            widget's animation.
        """
        self.onAnimate = callback
       
                


    def setSizeGripVisible(self, visible):
        """ Sets the size grip in the bottom-right
            corner of the screen visible or hidden.
        """
        if not visible:
            self.sizeGrip.hide()
        else:
            self.sizeGrip.show()


            

    def hideContentsWidgets(self):
        """ As stated.
        """
        if self.ContentsWidgets:
            for contentsWidget in self.ContentsWidgets:
                contentsWidget.hide()



            
    def showContentsWidgets(self):
        """ As stated.
        """
        if self.ContentsWidgets:
            for contentsWidget in self.ContentsWidgets:
                contentsWidget.show()
        


            
    def onAnimateMain(self, variant):
        """ Function during main animation
            sequence.  Calls the user-inputted 'onAnimate'
            callback.
        """
        if self.onAnimate:
            self.onAnimate()
            self.setFixedHeight(variant.height())

            


        
    def onAnimationFinished(self):
        """ Callback function when the animation
            finishes.  Also calls the user-inputted
            'onExpand' callback or 'onCollapse' callbacks
            depending on the toggle state of the widget.
        """

        #---------------- 
        # Call the animate function one last time.
        #---------------- 
        self.onAnimateMain(qt.QSize(self.geometry.width(), self.geometry.height()))


        
        #---------------- 
        # If the widget is in a 'toggled' state.
        #---------------- 
        if self.toggled:
            
            #
            # Set its height to either 'stretchHeight'
            # or 'maxHeight.  For an explanation of 'stretchHeight'
            # see it's declaration in the __init__ function.
            #
            if self.stretchHeight:
                self.setMaximumHeight(self.stretchHeight)
            else:
                self.setMaximumHeight(self.maxHeight)
                
            self.setMinimumHeight(self.minHeight)
                
            #
            # Show the internal contents
            #
            self.showContentsWidgets()

            #
            # Run the the 'onExpand' callback.
            #
            if self.onExpand:
                self.onExpand()

                

        #---------------- 
        # Otherwise if it is 'collapsed'
        #---------------- 
        else:
                        
            #
            # Set the height to 'self.collapsedHeight'.
            #
            self.setFixedHeight(self.collapsedHeight)
            
            #
            # Run callbacks
            #
            if self.onCollapse:
                self.onCollapse()

    


    def setMaxHeight(self, height):
        """ As stated.
        """
        self.maxHeight = height


        

    def setMinHeight(self, height):
        """ As stated.
        """
        self.minHeight = height


        

    def setStretchHeight(self, height):
        """ As stated.  See declaration of 
            self.stretchHeight in the __init__
            function for explanation of that variable.
        """
        self.stretchHeight = height
        self.setMaximumHeight(height)
        

        
        
    def setChecked(self, toggled, animDuration = None):
        """ Constructs an executes an animation for the widget
            once the title button is toggled.
        """

        #---------------- 
        # We need to set the button state in case
        # this method is programatically called.
        #----------------         
        self.toggleButton.setChecked(toggled)


        
        #---------------- 
        # Track whether collapsible was toggled.
        #---------------- 
        self.toggled = toggled


        
        #---------------- 
        # Define the animation duration.
        #----------------        
        if not animDuration: 
            animDuration = self.animDuration


            
        #---------------- 
        # Clear animation
        #---------------- 
        self.animations.clear()



        #---------------- 
        # For safety, set the width of
        # the widget to '100%'
        #----------------   
        self.setStyleSheet('width: 100%')


        
        #---------------- 
        # Modify button text to match the toggled
        # state (down arrow or right arrow) 
        #----------------       
        self.configureButton(toggled)	


        
        #----------------
        # Make the animation object
        #----------------
        anim = qt.QPropertyAnimation(self, 'size')


        
        #----------------
        # Set the duration
        #----------------
        anim.setDuration(animDuration)	


        
        #----------------
        # Set the easing curve
        #----------------
        anim.setEasingCurve(self.easingCurve)


        
        #----------------
        # Set the start/end values depending on
        # the toggle state.
        #----------------
        if self.toggled:

            #
            # Establish the 'toggled'/expanded animation sizes.
            #	
            startSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            endSize = qt.QSize(self.geometry.width(), self.maxHeight)  
            self.setMaximumHeight(self.collapsedHeight)
            self.setMinimumHeight(self.collapsedHeight)


        else:

            #
            # Establish the 'untoggled'/collapsed animation sizes.
            #	
            startHeight = self.geometry.height()
            startSize = qt.QSize(self.geometry.width(), startHeight)
            endSize = qt.QSize(self.geometry.width(), self.collapsedHeight)  
            self.setMaximumHeight(startHeight)
            self.setMinimumHeight(startHeight)

            #
            # Hide the internal contents for better
            # visual clarity.
            #
            self.hideContentsWidgets()
            


        #---------------- 
        # Set the start/end animation values.
        #----------------            
        anim.setStartValue(startSize)
        anim.setEndValue(endSize)            


        
        #---------------- 
        # Set callback during animation.
        #----------------
        anim.valueChanged.connect(self.onAnimateMain)



        #---------------- 
        # Connect the 'finished()' signal of the animation
        # to the finished callback...
        #----------------
        anim.connect('finished()', self.onAnimationFinished)


        
        #---------------- 
        # Add main animation to queue and  
        # start animation.
        #----------------       
        self.animations.addAnimation(anim)
        self.animations.start()
Пример #3
0
    def __init__(self, parent, title, maxHeight = 1000, minHeight = 60):
        """ Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

            

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()


        
        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()


        
        #-------------------- 
        # Set the arrow characters, 
        # described accordingly.
        #--------------------    
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'


        
        #-------------------- 
        # Set Collapsed Height
        #-------------------- 
        self.collapsedHeight = 30



        #-------------------- 
        # Set the min/max heights.
        #-------------------- 
        self.minHeight = minHeight
        self.maxHeight = maxHeight



        #-------------------- 
        # Set the toggleButton's height and width
        #-------------------- 
        self.toggleHeight = 16
        self.toggleWidth = 80



        #-------------------- 
        # Make sure the widget is 100% its parent's width.
        #--------------------        
        self.setStyleSheet('width: 100%')


        
        #-------------------- 
        # Set the animation duration
        #--------------------
        self.animDuration = 300


        
        #-------------------- 
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored, qt.QSizePolicy.MinimumExpanding)


        
        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.easingCurve = qt.QEasingCurve(2);


        
        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minHeight)
        

        
        #----------------
        # set the Title
        #----------------       
        self.title = title


        
        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')
        self.toggleButton.setDefaultStyleSheet('#animatedCollapsibleToggleButton {border: 1px solid transparent; background-color: white; margin-left: 5px; text-align: left; padding-left: 5px;}')
        self.toggleButton.setHoverStyleSheet('#animatedCollapsibleToggleButton {border: 1px solid rgb(200,200,200); background-color: white; border-radius: 2px; margin-left: 5px; text-align: left; padding-left: 5px;}')
        self.configureButton(True)
     

        
        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from 
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')
        self.frame.setStyleSheet('#animateCollapsibleFrame {margin-top: 9px; border: 2px solid lightgray; padding-top: 5px; padding-left: 2px; padding-right: 2px; padding-bottom: 2px}')

        
        
        #----------------
        # Stack the button on top of the frame via a 
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)
        


        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)



        #----------------
        # Set the sayout
        #----------------        
        self.setLayout(self.stackedLayout)


        
        #----------------
        # Init the animation group and callbacks.
        #----------------  
        self.animations = qt.QParallelAnimationGroup()
        self.onAnimate = None
        self.onCollapse = None
        self.onExpand = None
        self.ContentsWidgets = []


        
        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True



        #----------------
        # Set the stretch height.
        #
        # NOTE: This is different from the maximumHeight,
        # it's a target height that the user sets so that
        # the collapsible will stretch as far as self.stretchHeight
        # dictates once its expanded.  If we didn't have this 
        # variable, the the widget would have a sendentary height
        # within a layout, not stretching to the layout's
        # maximum extents.
        #
        #
        # TODO: Ideally this parameter would be more of a percentage
        # but setting stylesheet percentages is not possible, becase
        # we are manipulating the .maximumHeight' property of the widget 
        # during the animation.
        # Need to determine a more elegant way of of setting the 'stretch'
        # height to '100%' or equivalent.
        #----------------
        self.stretchHeight = None
Пример #4
0
class AnimatedCollapsible(ctk.ctkExpandableWidget):
    """ Descriptor above.
    """
    def __init__(self, parent, title, maxHeight=1000, minHeight=60):
        """ Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()

        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()

        #--------------------
        # Set the arrow characters,
        # described accordingly.
        #--------------------
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'

        #--------------------
        # Set Collapsed Height
        #--------------------
        self.collapsedHeight = 30

        #--------------------
        # Set the min/max heights.
        #--------------------
        self.minHeight = minHeight
        self.maxHeight = maxHeight

        #--------------------
        # Set the toggleButton's height and width
        #--------------------
        self.toggleHeight = 16
        self.toggleWidth = 80

        #--------------------
        # Make sure the widget is 100% its parent's width.
        #--------------------
        self.setStyleSheet('width: 100%')

        #--------------------
        # Set the animation duration
        #--------------------
        self.animDuration = 300

        #--------------------
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored,
                           qt.QSizePolicy.MinimumExpanding)

        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.easingCurve = qt.QEasingCurve(2)

        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minHeight)

        #----------------
        # set the Title
        #----------------
        self.title = title

        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')
        self.toggleButton.setDefaultStyleSheet(
            '#animatedCollapsibleToggleButton {border: 1px solid transparent; background-color: white; margin-left: 5px; text-align: left; padding-left: 5px;}'
        )
        self.toggleButton.setHoverStyleSheet(
            '#animatedCollapsibleToggleButton {border: 1px solid rgb(200,200,200); background-color: white; border-radius: 2px; margin-left: 5px; text-align: left; padding-left: 5px;}'
        )
        self.configureButton(True)

        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')
        self.frame.setStyleSheet(
            '#animateCollapsibleFrame {margin-top: 9px; border: 2px solid lightgray; padding-top: 5px; padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        )

        #----------------
        # Stack the button on top of the frame via a
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)

        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)

        #----------------
        # Set the sayout
        #----------------
        self.setLayout(self.stackedLayout)

        #----------------
        # Init the animation group and callbacks.
        #----------------
        self.animations = qt.QParallelAnimationGroup()
        self.onAnimate = None
        self.onCollapse = None
        self.onExpand = None
        self.ContentsWidgets = []

        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True

        #----------------
        # Set the stretch height.
        #
        # NOTE: This is different from the maximumHeight,
        # it's a target height that the user sets so that
        # the collapsible will stretch as far as self.stretchHeight
        # dictates once its expanded.  If we didn't have this
        # variable, the the widget would have a sendentary height
        # within a layout, not stretching to the layout's
        # maximum extents.
        #
        #
        # TODO: Ideally this parameter would be more of a percentage
        # but setting stylesheet percentages is not possible, becase
        # we are manipulating the .maximumHeight' property of the widget
        # during the animation.
        # Need to determine a more elegant way of of setting the 'stretch'
        # height to '100%' or equivalent.
        #----------------
        self.stretchHeight = None

    def suspendAnimationDuration(self, suspend):
        """ Suspends the animation length by converting
            the duration to 0, saving the previous state.
            When the user sets the 'suspend' argument to 
            'False' then the previous animation state is 
            restored.
        """
        if suspend:
            self.originalAnimDuration = self.animDuration
            self.animDuration = 0
        else:
            self.animDuration = self.originalAnimDuration

    def setAnimationDuration(self, duration):
        """ As stated.
        """
        self.animDuration = duration

    def configureButton(self, toggled):
        """ Modifies the arrow character of the button
            title to match the 'toggled' state and also
            sets its text to 'self.title.'
        """
        arrowChr = self.downArrowChar if toggled else self.rightArrowChar
        self.toggleButton.setText(arrowChr + '  ' + self.title)
        self.toggleButton.setFixedHeight(17)
        self.toggleButton.setMinimumWidth(10)
        self.toggleButton.setMaximumWidth(110)

    def setWidget(self, widget):
        """ Similar to the 'setWidget' function
            of a QWidget: sets the internal contents
            of the collapsible.
        """
        self.ContentsWidgets = [widget]
        layout = qt.QHBoxLayout()
        layout.addWidget(widget)
        layout.setContentsMargins(0, 0, 0, 0)
        self.frame.setLayout(layout)

    def setOnCollapse(self, callback):
        """ Sets the callback for AFTER widget
            is collapsed.
        """
        self.onCollapse = callback

    def setOnExpand(self, callback):
        """ Sets the callback for AFTER the 
            widget's expansion.
        """
        self.onExpand = callback

    def setOnAnimate(self, callback):
        """ Sets the callback for DURING the
            widget's animation.
        """
        self.onAnimate = callback

    def setSizeGripVisible(self, visible):
        """ Sets the size grip in the bottom-right
            corner of the screen visible or hidden.
        """
        if not visible:
            self.sizeGrip.hide()
        else:
            self.sizeGrip.show()

    def hideContentsWidgets(self):
        """ As stated.
        """
        if self.ContentsWidgets:
            for contentsWidget in self.ContentsWidgets:
                contentsWidget.hide()

    def showContentsWidgets(self):
        """ As stated.
        """
        if self.ContentsWidgets:
            for contentsWidget in self.ContentsWidgets:
                contentsWidget.show()

    def onAnimateMain(self, variant):
        """ Function during main animation
            sequence.  Calls the user-inputted 'onAnimate'
            callback.
        """
        if self.onAnimate:
            self.onAnimate()
            self.setFixedHeight(variant.height())

    def onAnimationFinished(self):
        """ Callback function when the animation
            finishes.  Also calls the user-inputted
            'onExpand' callback or 'onCollapse' callbacks
            depending on the toggle state of the widget.
        """

        #----------------
        # Call the animate function one last time.
        #----------------
        self.onAnimateMain(
            qt.QSize(self.geometry.width(), self.geometry.height()))

        #----------------
        # If the widget is in a 'toggled' state.
        #----------------
        if self.toggled:

            #
            # Set its height to either 'stretchHeight'
            # or 'maxHeight.  For an explanation of 'stretchHeight'
            # see it's declaration in the __init__ function.
            #
            if self.stretchHeight:
                self.setMaximumHeight(self.stretchHeight)
            else:
                self.setMaximumHeight(self.maxHeight)

            self.setMinimumHeight(self.minHeight)

            #
            # Show the internal contents
            #
            self.showContentsWidgets()

            #
            # Run the the 'onExpand' callback.
            #
            if self.onExpand:
                self.onExpand()

        #----------------
        # Otherwise if it is 'collapsed'
        #----------------
        else:

            #
            # Set the height to 'self.collapsedHeight'.
            #
            self.setFixedHeight(self.collapsedHeight)

            #
            # Run callbacks
            #
            if self.onCollapse:
                self.onCollapse()

    def setMaxHeight(self, height):
        """ As stated.
        """
        self.maxHeight = height

    def setMinHeight(self, height):
        """ As stated.
        """
        self.minHeight = height

    def setStretchHeight(self, height):
        """ As stated.  See declaration of 
            self.stretchHeight in the __init__
            function for explanation of that variable.
        """
        self.stretchHeight = height
        self.setMaximumHeight(height)

    def setChecked(self, toggled, animDuration=None):
        """ Constructs an executes an animation for the widget
            once the title button is toggled.
        """

        #----------------
        # We need to set the button state in case
        # this method is programatically called.
        #----------------
        self.toggleButton.setChecked(toggled)

        #----------------
        # Track whether collapsible was toggled.
        #----------------
        self.toggled = toggled

        #----------------
        # Define the animation duration.
        #----------------
        if not animDuration:
            animDuration = self.animDuration

        #----------------
        # Clear animation
        #----------------
        self.animations.clear()

        #----------------
        # For safety, set the width of
        # the widget to '100%'
        #----------------
        self.setStyleSheet('width: 100%')

        #----------------
        # Modify button text to match the toggled
        # state (down arrow or right arrow)
        #----------------
        self.configureButton(toggled)

        #----------------
        # Make the animation object
        #----------------
        anim = qt.QPropertyAnimation(self, 'size')

        #----------------
        # Set the duration
        #----------------
        anim.setDuration(animDuration)

        #----------------
        # Set the easing curve
        #----------------
        anim.setEasingCurve(self.easingCurve)

        #----------------
        # Set the start/end values depending on
        # the toggle state.
        #----------------
        if self.toggled:

            #
            # Establish the 'toggled'/expanded animation sizes.
            #
            startSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            endSize = qt.QSize(self.geometry.width(), self.maxHeight)
            self.setMaximumHeight(self.collapsedHeight)
            self.setMinimumHeight(self.collapsedHeight)

        else:

            #
            # Establish the 'untoggled'/collapsed animation sizes.
            #
            startHeight = self.geometry.height()
            startSize = qt.QSize(self.geometry.width(), startHeight)
            endSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            self.setMaximumHeight(startHeight)
            self.setMinimumHeight(startHeight)

            #
            # Hide the internal contents for better
            # visual clarity.
            #
            self.hideContentsWidgets()

        #----------------
        # Set the start/end animation values.
        #----------------
        anim.setStartValue(startSize)
        anim.setEndValue(endSize)

        #----------------
        # Set callback during animation.
        #----------------
        anim.valueChanged.connect(self.onAnimateMain)

        #----------------
        # Connect the 'finished()' signal of the animation
        # to the finished callback...
        #----------------
        anim.connect('finished()', self.onAnimationFinished)

        #----------------
        # Add main animation to queue and
        # start animation.
        #----------------
        self.animations.addAnimation(anim)
        self.animations.start()
Пример #5
0
    def __init__(self, parent, title, maxHeight=1000, minHeight=60):
        """ Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()

        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()

        #--------------------
        # Set the arrow characters,
        # described accordingly.
        #--------------------
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'

        #--------------------
        # Set Collapsed Height
        #--------------------
        self.collapsedHeight = 30

        #--------------------
        # Set the min/max heights.
        #--------------------
        self.minHeight = minHeight
        self.maxHeight = maxHeight

        #--------------------
        # Set the toggleButton's height and width
        #--------------------
        self.toggleHeight = 16
        self.toggleWidth = 80

        #--------------------
        # Make sure the widget is 100% its parent's width.
        #--------------------
        self.setStyleSheet('width: 100%')

        #--------------------
        # Set the animation duration
        #--------------------
        self.animDuration = 300

        #--------------------
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored,
                           qt.QSizePolicy.MinimumExpanding)

        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.easingCurve = qt.QEasingCurve(2)

        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minHeight)

        #----------------
        # set the Title
        #----------------
        self.title = title

        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')
        self.toggleButton.setDefaultStyleSheet(
            '#animatedCollapsibleToggleButton {border: 1px solid transparent; background-color: white; margin-left: 5px; text-align: left; padding-left: 5px;}'
        )
        self.toggleButton.setHoverStyleSheet(
            '#animatedCollapsibleToggleButton {border: 1px solid rgb(200,200,200); background-color: white; border-radius: 2px; margin-left: 5px; text-align: left; padding-left: 5px;}'
        )
        self.configureButton(True)

        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')
        self.frame.setStyleSheet(
            '#animateCollapsibleFrame {margin-top: 9px; border: 2px solid lightgray; padding-top: 5px; padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        )

        #----------------
        # Stack the button on top of the frame via a
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)

        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)

        #----------------
        # Set the sayout
        #----------------
        self.setLayout(self.stackedLayout)

        #----------------
        # Init the animation group and callbacks.
        #----------------
        self.animations = qt.QParallelAnimationGroup()
        self.onAnimate = None
        self.onCollapse = None
        self.onExpand = None
        self.ContentsWidgets = []

        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True

        #----------------
        # Set the stretch height.
        #
        # NOTE: This is different from the maximumHeight,
        # it's a target height that the user sets so that
        # the collapsible will stretch as far as self.stretchHeight
        # dictates once its expanded.  If we didn't have this
        # variable, the the widget would have a sendentary height
        # within a layout, not stretching to the layout's
        # maximum extents.
        #
        #
        # TODO: Ideally this parameter would be more of a percentage
        # but setting stylesheet percentages is not possible, becase
        # we are manipulating the .maximumHeight' property of the widget
        # during the animation.
        # Need to determine a more elegant way of of setting the 'stretch'
        # height to '100%' or equivalent.
        #----------------
        self.stretchHeight = None
Пример #6
0
 def makeSettingsButton(self, XnatSetting):
     """ Constructs a setting button with a wrench icon that
         opens the appropriate settings tab.
     """
     button = HoverButton()
     button.setIcon(qt.QIcon(os.path.join(self.MODULE.GLOBALS.LOCAL_URIS['icons'], 'wrench.png')) )
     button.setFixedWidth(23)
     button.setFixedHeight(17)
     button.setDefaultStyleSheet('border: 1px solid transparent; border-radius: 2px; background-color: transparent; margin-left: 5px; text-align: left; padding-left: 0px; ')
     button.setHoverStyleSheet('border: 1px solid rgb(150,150,150); border-radius: 2px; background-color: transparent; margin-left: 5px; text-align: left; padding-left: 0px;')
     def openSettings():
         self.MODULE.XnatSettingsWindow.showWindow(XnatSetting.tabTitle)
     button.connect('clicked()', openSettings)
     return button
    def __init__(self, parent, title):
        """ 
        Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)



        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()
        #self.setSizeGripInside(False)

        
        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()


        
        #-------------------- 
        # Set the arrow characters, 
        # described accordingly.
        #--------------------    
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'


        
        #-------------------- 
        # Set Collapsed Height
        #-------------------- 
        self.collapsedHeight = 30



        #-------------------- 
        # Set the min/max heights.
        #-------------------- 
        self.minExpandedHeight = 60
        self.maxExpandedHeight = 1000



        #-------------------- 
        # Set the toggleButton's height and width
        #-------------------- 
        self.toggleHeight = 16
        self.toggleWidth = 80



        #-------------------- 
        # Make sure the widget is 100% its parent's width.
        #--------------------        
        self.setStyleSheet('width: 100%')


        
        #-------------------- 
        # Set the animation duration
        #--------------------
        self.animDuration = 250


        
        #-------------------- 
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored, qt.QSizePolicy.MinimumExpanding)
        

        
        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.__easingCurve = qt.QEasingCurve(6);


        
        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minExpandedHeight)
        

        
        #----------------
        # set the Title
        #----------------       
        self.title = title


        
        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')


        buttonDefault = '#animatedCollapsibleToggleButton '
        buttonDefault += '{border: 1px solid transparent; '
        buttonDefault += 'background-color: white; margin-left: '
        buttonDefault += '5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setDefaultStyleSheet(buttonDefault)

        buttonHover = '#animatedCollapsibleToggleButton {'
        buttonHover += 'border: 1px solid rgb(200,200,200); '
        buttonHover += 'background-color: white; border-radius: 2px; '
        buttonHover += 'margin-left: 5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setHoverStyleSheet(buttonHover)
        self.__modifyToggleButton(True)
     

        
        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from 
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')

        frameStyle = '#animateCollapsibleFrame '
        frameStyle += '{margin-top: 9px; border: '
        frameStyle += '2px solid lightgray; border-radius: 4px; padding-top: 5px; '
        frameStyle += 'padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        self.frame.setStyleSheet(frameStyle)

        
        
        #----------------
        # Stack the button on top of the frame via a 
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)
        


        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)



        #----------------
        # Set the sayout
        #----------------        
        self.setLayout(self.stackedLayout)


        
        #----------------
        # Init the animation group and callbacks.
        #----------------  
        self.animations = qt.QParallelAnimationGroup()
        self.__eventCallbacks = {}
        for key in AnimatedCollapsible.EVENT_TYPES:
            self.__eventCallbacks[key] = []
        self.__contents = []


        
        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True


        self.sizeGrip.installEventFilter(self)
        self.installEventFilter(self)
class AnimatedCollapsible(ctk.ctkExpandableWidget):
    """ 
    AnimatedCollapsible is a subclass of ctk.ctkExpandableWidget. 
    AnimatedCollapsible is designed around the premise of animating
    when the user clicks on its title button.
    
    Much like other QT widgets, the user can call 'setWidget'
    to apply contents to the inside of the widget.  Other parameters, 
    such as animation times and widgetsize, can also be set by the user.
   
    """


    EVENT_TYPES = [
        'collapseStart',
        'collapsing',
        'collapseEnd',
        'expandStart',
        'expanding',
        'expandEnd',
        'collapsed',
        'expanded',
        'animate',
    ] 

    
    def __init__(self, parent, title):
        """ 
        Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)



        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()
        #self.setSizeGripInside(False)

        
        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()


        
        #-------------------- 
        # Set the arrow characters, 
        # described accordingly.
        #--------------------    
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'


        
        #-------------------- 
        # Set Collapsed Height
        #-------------------- 
        self.collapsedHeight = 30



        #-------------------- 
        # Set the min/max heights.
        #-------------------- 
        self.minExpandedHeight = 60
        self.maxExpandedHeight = 1000



        #-------------------- 
        # Set the toggleButton's height and width
        #-------------------- 
        self.toggleHeight = 16
        self.toggleWidth = 80



        #-------------------- 
        # Make sure the widget is 100% its parent's width.
        #--------------------        
        self.setStyleSheet('width: 100%')


        
        #-------------------- 
        # Set the animation duration
        #--------------------
        self.animDuration = 250


        
        #-------------------- 
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored, qt.QSizePolicy.MinimumExpanding)
        

        
        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.__easingCurve = qt.QEasingCurve(6);


        
        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minExpandedHeight)
        

        
        #----------------
        # set the Title
        #----------------       
        self.title = title


        
        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')


        buttonDefault = '#animatedCollapsibleToggleButton '
        buttonDefault += '{border: 1px solid transparent; '
        buttonDefault += 'background-color: white; margin-left: '
        buttonDefault += '5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setDefaultStyleSheet(buttonDefault)

        buttonHover = '#animatedCollapsibleToggleButton {'
        buttonHover += 'border: 1px solid rgb(200,200,200); '
        buttonHover += 'background-color: white; border-radius: 2px; '
        buttonHover += 'margin-left: 5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setHoverStyleSheet(buttonHover)
        self.__modifyToggleButton(True)
     

        
        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from 
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')

        frameStyle = '#animateCollapsibleFrame '
        frameStyle += '{margin-top: 9px; border: '
        frameStyle += '2px solid lightgray; border-radius: 4px; padding-top: 5px; '
        frameStyle += 'padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        self.frame.setStyleSheet(frameStyle)

        
        
        #----------------
        # Stack the button on top of the frame via a 
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)
        


        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)



        #----------------
        # Set the sayout
        #----------------        
        self.setLayout(self.stackedLayout)


        
        #----------------
        # Init the animation group and callbacks.
        #----------------  
        self.animations = qt.QParallelAnimationGroup()
        self.__eventCallbacks = {}
        for key in AnimatedCollapsible.EVENT_TYPES:
            self.__eventCallbacks[key] = []
        self.__contents = []


        
        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True


        self.sizeGrip.installEventFilter(self)
        self.installEventFilter(self)



        
    def eventFilter(self, ob, event):
        """ 
        Event filter to for searchLine events.
        """
        str(event)
        pass
        #print event
        #if event.type() == qt.QEvent.FocusIn:
            #print "CLICK!"




    def onEvent(self, eventKey, callback):
        """
        Adds a callback for a given event.  
        Callbacks are strored internally as a dictionary of arrays.
        
        @param event: The event descriptor for the callbacks stored.  Refer
        to AnimatedCollapsible.EVENT_TYPES for the list.
        @type event: string
        
        @param callback: The callback function to enlist.
        @type callback: function
        
        @raise: Error if 'event' argument is not a valid event type.
        """
        if not eventKey in self.EVENT_TYPES:
            raise Exception("AnimatedCollapsible (onEvent): invalid event type '%s'"%(eventKey))
        self.__eventCallbacks[eventKey].append(callback)
                    

        

    def clearEvents(self, eventKey = None):
        """
        Clears the event callbacks associated with the 'eventKey' argument.  
        If 'eventKey' is not specified, clears all of the event callbacks.
        
        @param eventKey: The event key to clear.
        @type eventKey: string
        """
        
        if not eventKey:
            for key in self.EVENT_TYPES:
                self.__eventCallbacks[key] = []
            return
        if not eventKey in self.EVENT_TYPES:
            raise Exception("AnimatedCollapsible (clearEvent): invalid event type '%s'"%(eventKey))
        else:
            self.__eventCallbacks[eventKey] = []




    def __runCallbacks(self, eventKey, *args):
        """
        @param eventKey: The event key to clear.
        @type eventKey: string
        """
        if not eventKey in self.EVENT_TYPES:
            raise Exception("AnimatedCollapsible (runCallbacks): invalid event type '%s'"%(eventKey))
        else:
            for callback in self.__eventCallbacks[eventKey]:
                if args:
                    callback(*args)
                else:
                    callback()

        

    
    def isExpanded(self):
        """
        @return: Whether the collapsible is expanded or not.
        @rtype: boolean
        """
        return self.toggled

        


    def setContents(self, widget):
        """ 
        Similar to the 'setWidget' function
        of a QWidget: sets the internal contents
        of the collapsible.
        """
        self.__contents = [widget]
        layout = qt.QHBoxLayout()
        layout.addWidget(widget)
        layout.setContentsMargins(0,0,0,0)
        self.frame.setLayout(layout)




    def getContents(self):
        """ 
        """
        return self.__contents
        



    def setEasingCurve(self, easingCurve):
        """
        Sets the animation easing curve.

        @param easingCurve: The easing curve to set.
        @type easingCurve: qt.QEasingCurve
        """
        self.__easingCurve = easingCurve




    def setCollapsedHeight(self, height):
        """
        Sets the collapsed height.

        @param height: The height to set.
        @type height: number
        """
        self.collapsedHeight = height




    def setMaxExpandedHeight(self, height, applyImmediately = False):
        """ 
        
        
        @param height: The height to set.
        @type height: number

        @param applyImmediately: The whether to apply the height changes immediately using the 
            'ctk.CollapsibleButton.setMaximumHeight' function.  This usually is needed only
            when the collapsible is in the 'expanded' state.
        @type applyImmediately: boolean
        """
        self.maxExpandedHeight = height
        if applyImmediately:
            self.setMaximumHeight(height)


        

    def setMinExpandedHeight(self, height, applyImmediately = False):
        """ 
        As stated.

        @param height: The height to set.
        @type height: number

        @param applyImmediately: The whether to apply the height changes immediately using the 
            'ctk.CollapsibleButton.setMinimumHeight' function.  This usually is needed only
            when the collapsible is in the 'expanded' state.
        @type applyImmediately: boolean
        """
        self.minExpandedHeight = height
        if applyImmediately:
            self.setMinimumHeight(height)

            
        
        
    def setChecked(self, toggled, animDuration = None):
        """ 
        Constructs an executes an animation for the widget
        once the title button is toggled.
        """

        #---------------- 
        # We need to set the button state in case
        # this method is programatically called.
        #----------------         
        self.toggleButton.setChecked(toggled)


        
        #---------------- 
        # Track whether collapsible was toggled.
        #---------------- 
        self.toggled = toggled


        
        #---------------- 
        # Define the animation duration.
        #----------------        
        if not animDuration: 
            animDuration = self.animDuration


            
        #---------------- 
        # Clear animation
        #---------------- 
        self.animations.clear()



        #---------------- 
        # For safety, set the width of
        # the widget to '100%'
        #----------------   
        self.setStyleSheet('width: 100%')


        
        #---------------- 
        # Modify button text to match the toggled
        # state (down arrow or right arrow) 
        #----------------       
        self.__modifyToggleButton(toggled)	


        
        #----------------
        # Make the animation object
        #----------------
        anim = qt.QPropertyAnimation(self, 'size')


        
        #----------------
        # Set the duration
        #----------------
        anim.setDuration(animDuration)	


        
        #----------------
        # Set the easing curve
        #----------------
        anim.setEasingCurve(self.__easingCurve)


        
        

        #----------------
        # Set the start/end values depending on
        # the toggle state.
        #----------------
        if self.toggled:

            self.__runCallbacks('expandStart')


            #
            # Establish the 'toggled'/expanded animation sizes.
            #	            
            startSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            endSize = qt.QSize(self.geometry.width(), self.maxExpandedHeight)  
            self.setMaximumHeight(self.collapsedHeight)
            self.setMinimumHeight(self.collapsedHeight)
  


        else:

            self.__runCallbacks('collapseStart')


            #
            # Establish the 'untoggled'/collapsed animation sizes.
            #	
            startHeight = self.geometry.height()

            #
            # Save original stretch height
            #
            self.setMaximumHeight(startHeight)

            
            startSize = qt.QSize(self.geometry.width(), startHeight)
            endSize = qt.QSize(self.geometry.width(), self.collapsedHeight)  
            self.setMaximumHeight(startHeight)
            self.setMinimumHeight(startHeight)

            #
            # Hide the internal contents for better
            # visual clarity.
            #
            self.__hideContents()
            


        #---------------- 
        # Set the start/end animation values.
        #----------------            
        anim.setStartValue(startSize)
        anim.setEndValue(endSize)            


        
        #---------------- 
        # Set callback during animation.
        #----------------
        anim.valueChanged.connect(self.__onAnimate)



        #---------------- 
        # Connect the 'finished()' signal of the animation
        # to the finished callback...
        #----------------
        anim.connect('finished()', self.__onAnimEnd)


        
        #---------------- 
        # Add main animation to queue and  
        # start animation.
        #----------------       
        self.animations.addAnimation(anim)
        self.animations.start()




    def setSizeGripVisible(self, visible):
        """ 
        Sets the size grip in the bottom-right
        corner of the screen visible or hidden.
        """
        if visible:
            self.sizeGrip.show()
        else:
            self.sizeGrip.hide()



        
    def setAnimLength(self, duration):
        """ 
        As stated.
        """
        self.animDuration = duration;



    def suspendAnim(self, suspend = False):
        """ 
        Suspends the animation length by converting
        the duration to 0, saving the previous state.
        When the user sets the 'suspend' argument to 
        'False' then the previous animation state is 
        restored.
        """
        if suspend:
            self.originalAnimDuration = self.animDuration
            self.animDuration = 0    
        else:
            self.animDuration = self.originalAnimDuration




    def __modifyToggleButton(self, toggled):
        """ 
        Modifies the arrow character of the button
        title to match the 'toggled' state and also
        sets its text to 'self.title.'
        """
        arrowChr = self.downArrowChar if toggled else self.rightArrowChar
        self.toggleButton.setText(arrowChr + '  ' + self.title)
        self.toggleButton.setFixedHeight(17)
        self.toggleButton.setMinimumWidth(10)
        self.toggleButton.setMaximumWidth(110)




    def __onAnimate(self, variant):
        """ 
        Function during main animation
        sequence.  Calls the user-inputted 'onAnimate'
        callback.
        """
        self.__runCallbacks('animate')
        self.setFixedHeight(variant.height())

            


        
    def __onAnimEnd(self):
        """ 
        Callback function when the animation
        finishes.  Also calls the user-inputted
        'onExpand' callback or 'onCollapse' callbacks
        depending on the toggle state of the widget.
        """

        #---------------- 
        # Call the animate function one last time.
        #---------------- 
        self.__onAnimate(qt.QSize(self.geometry.width(), self.geometry.height()))


        
        #---------------- 
        # If the widget is in a 'toggled' state.
        #---------------- 
        if self.toggled:
            
            #
            # Set its height to either 'stretchHeight'
            # or 'expandedHeight.  For an explanation of 'stretchHeight'
            # see it's declaration in the __init__ function.
            #
            self.setMaximumHeight(self.maxExpandedHeight)
                
            self.setMinimumHeight(self.minExpandedHeight)
                
            #
            # Show the internal contents
            #
            self.__showContents()

            #
            # Run the the 'onExpand' callback.
            #
            self.__runCallbacks('expanded')
            self.__runCallbacks('expandEnd')

                

        #---------------- 
        # Otherwise if it is 'collapsed'
        #---------------- 
        else:
                        
            #
            # Set the height to 'self.collapsedHeight'.
            #
            self.setFixedHeight(self.collapsedHeight)
            
            #
            # Run callbacks
            #
            self.__runCallbacks('collapsed')
            self.__runCallbacks('collapseEnd')


    def __hideContents(self):
        """ 
        As stated.
        """
        if self.__contents:
            for contentsWidget in self.__contents:
                contentsWidget.hide()



            
    def __showContents(self):
        """ 
        As stated.
        """
        if self.__contents:
            for contentsWidget in self.__contents:
                contentsWidget.show()
Пример #9
0
    def __init__(self, parent, title):
        """ 
        Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()
        #self.setSizeGripInside(False)

        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()

        #--------------------
        # Set the arrow characters,
        # described accordingly.
        #--------------------
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'

        #--------------------
        # Set Collapsed Height
        #--------------------
        self.collapsedHeight = 30

        #--------------------
        # Set the min/max heights.
        #--------------------
        self.minExpandedHeight = 60
        self.maxExpandedHeight = 1000

        #--------------------
        # Set the toggleButton's height and width
        #--------------------
        self.toggleHeight = 16
        self.toggleWidth = 80

        #--------------------
        # Make sure the widget is 100% its parent's width.
        #--------------------
        self.setStyleSheet('width: 100%')

        #--------------------
        # Set the animation duration
        #--------------------
        self.animDuration = 250

        #--------------------
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored,
                           qt.QSizePolicy.MinimumExpanding)

        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.__easingCurve = qt.QEasingCurve(6)

        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minExpandedHeight)

        #----------------
        # set the Title
        #----------------
        self.title = title

        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')

        buttonDefault = '#animatedCollapsibleToggleButton '
        buttonDefault += '{border: 1px solid transparent; '
        buttonDefault += 'background-color: white; margin-left: '
        buttonDefault += '5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setDefaultStyleSheet(buttonDefault)

        buttonHover = '#animatedCollapsibleToggleButton {'
        buttonHover += 'border: 1px solid rgb(200,200,200); '
        buttonHover += 'background-color: white; border-radius: 2px; '
        buttonHover += 'margin-left: 5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setHoverStyleSheet(buttonHover)
        self.__modifyToggleButton(True)

        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')

        frameStyle = '#animateCollapsibleFrame '
        frameStyle += '{margin-top: 9px; border: '
        frameStyle += '2px solid lightgray; border-radius: 4px; padding-top: 5px; '
        frameStyle += 'padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        self.frame.setStyleSheet(frameStyle)

        #----------------
        # Stack the button on top of the frame via a
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)

        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)

        #----------------
        # Set the sayout
        #----------------
        self.setLayout(self.stackedLayout)

        #----------------
        # Init the animation group and callbacks.
        #----------------
        self.animations = qt.QParallelAnimationGroup()
        self.__eventCallbacks = {}
        for key in AnimatedCollapsible.EVENT_TYPES:
            self.__eventCallbacks[key] = []
        self.__contents = []

        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True

        self.sizeGrip.installEventFilter(self)
        self.installEventFilter(self)
Пример #10
0
class AnimatedCollapsible(ctk.ctkExpandableWidget):
    """ 
    AnimatedCollapsible is a subclass of ctk.ctkExpandableWidget. 
    AnimatedCollapsible is designed around the premise of animating
    when the user clicks on its title button.
    
    Much like other QT widgets, the user can call 'setWidget'
    to apply contents to the inside of the widget.  Other parameters, 
    such as animation times and widgetsize, can also be set by the user.
   
    """

    EVENT_TYPES = [
        'collapseStart',
        'collapsing',
        'collapseEnd',
        'expandStart',
        'expanding',
        'expandEnd',
        'collapsed',
        'expanded',
        'animate',
    ]

    def __init__(self, parent, title):
        """ 
        Init function.
        """

        if parent:
            super(AnimatedCollapsible, self).__init__(parent)
        else:
            super(AnimatedCollapsible, self).__init__(self)

        #--------------------
        # We want to grab the sizeGrip right off
        # the bat so we can control its visibility.
        #--------------------
        self.sizeGrip = self.children()[0]
        self.sizeGrip.hide()
        #self.setSizeGripInside(False)

        #--------------------
        # We hide the module first because
        # it creates a flikering on loadup
        #--------------------
        self.hide()

        #--------------------
        # Set the arrow characters,
        # described accordingly.
        #--------------------
        self.rightArrowChar = u'\u25b8'
        self.downArrowChar = u'\u25be'

        #--------------------
        # Set Collapsed Height
        #--------------------
        self.collapsedHeight = 30

        #--------------------
        # Set the min/max heights.
        #--------------------
        self.minExpandedHeight = 60
        self.maxExpandedHeight = 1000

        #--------------------
        # Set the toggleButton's height and width
        #--------------------
        self.toggleHeight = 16
        self.toggleWidth = 80

        #--------------------
        # Make sure the widget is 100% its parent's width.
        #--------------------
        self.setStyleSheet('width: 100%')

        #--------------------
        # Set the animation duration
        #--------------------
        self.animDuration = 250

        #--------------------
        # Set the size policy
        #--------------------
        self.setSizePolicy(qt.QSizePolicy.Ignored,
                           qt.QSizePolicy.MinimumExpanding)

        #----------------
        # Set the animation's easing curve.  See:
        # http://harmattan-dev.nokia.com/docs/library/html/qt4/qeasingcurve.html
        # for more options.
        #----------------
        self.__easingCurve = qt.QEasingCurve(6)

        #----------------
        # Set the minimum hieght
        #----------------
        self.setMinimumHeight(self.minExpandedHeight)

        #----------------
        # set the Title
        #----------------
        self.title = title

        #----------------
        # Make the toggle button
        #----------------
        self.toggleButton = HoverButton(self)
        self.toggleButton.hide()
        self.toggleButton.setParent(self)
        self.toggleButton.setFixedHeight(self.toggleHeight)
        self.toggleButton.setCheckable(True)
        self.toggleButton.setObjectName('animatedCollapsibleToggleButton')

        buttonDefault = '#animatedCollapsibleToggleButton '
        buttonDefault += '{border: 1px solid transparent; '
        buttonDefault += 'background-color: white; margin-left: '
        buttonDefault += '5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setDefaultStyleSheet(buttonDefault)

        buttonHover = '#animatedCollapsibleToggleButton {'
        buttonHover += 'border: 1px solid rgb(200,200,200); '
        buttonHover += 'background-color: white; border-radius: 2px; '
        buttonHover += 'margin-left: 5px; text-align: left; padding-left: 5px;}'
        self.toggleButton.setHoverStyleSheet(buttonHover)
        self.__modifyToggleButton(True)

        #----------------
        # Make the internal 'frame' and set the style
        # accordingly.
        #----------------
        self.frame = qt.QFrame(self)
        #
        # Prevent style sheet inheritance from
        # inner contents
        #
        self.frame.setObjectName('animateCollapsibleFrame')

        frameStyle = '#animateCollapsibleFrame '
        frameStyle += '{margin-top: 9px; border: '
        frameStyle += '2px solid lightgray; border-radius: 4px; padding-top: 5px; '
        frameStyle += 'padding-left: 2px; padding-right: 2px; padding-bottom: 2px}'
        self.frame.setStyleSheet(frameStyle)

        #----------------
        # Stack the button on top of the frame via a
        # QStackedLayout
        #----------------
        self.stackedLayout = qt.QStackedLayout()
        self.stackedLayout.addWidget(self.toggleButton)
        self.stackedLayout.addWidget(self.frame)

        #----------------
        # To make sure the button is on top.
        #----------------
        self.stackedLayout.setCurrentIndex(0)
        self.stackedLayout.setStackingMode(1)

        #----------------
        # Set the sayout
        #----------------
        self.setLayout(self.stackedLayout)

        #----------------
        # Init the animation group and callbacks.
        #----------------
        self.animations = qt.QParallelAnimationGroup()
        self.__eventCallbacks = {}
        for key in AnimatedCollapsible.EVENT_TYPES:
            self.__eventCallbacks[key] = []
        self.__contents = []

        #----------------
        # Set the default states after creation.
        #----------------
        self.toggleButton.connect('toggled(bool)', self.setChecked)
        self.toggled = True

        self.sizeGrip.installEventFilter(self)
        self.installEventFilter(self)

    def eventFilter(self, ob, event):
        """ 
        Event filter to for searchLine events.
        """
        str(event)
        pass
        #print event
        #if event.type() == qt.QEvent.FocusIn:
        #print "CLICK!"

    def onEvent(self, eventKey, callback):
        """
        Adds a callback for a given event.  
        Callbacks are strored internally as a dictionary of arrays.
        
        @param event: The event descriptor for the callbacks stored.  Refer
        to AnimatedCollapsible.EVENT_TYPES for the list.
        @type event: string
        
        @param callback: The callback function to enlist.
        @type callback: function
        
        @raise: Error if 'event' argument is not a valid event type.
        """
        if not eventKey in self.EVENT_TYPES:
            raise Exception(
                "AnimatedCollapsible (onEvent): invalid event type '%s'" %
                (eventKey))
        self.__eventCallbacks[eventKey].append(callback)

    def clearEvents(self, eventKey=None):
        """
        Clears the event callbacks associated with the 'eventKey' argument.  
        If 'eventKey' is not specified, clears all of the event callbacks.
        
        @param eventKey: The event key to clear.
        @type eventKey: string
        """

        if not eventKey:
            for key in self.EVENT_TYPES:
                self.__eventCallbacks[key] = []
            return
        if not eventKey in self.EVENT_TYPES:
            raise Exception(
                "AnimatedCollapsible (clearEvent): invalid event type '%s'" %
                (eventKey))
        else:
            self.__eventCallbacks[eventKey] = []

    def __runCallbacks(self, eventKey, *args):
        """
        @param eventKey: The event key to clear.
        @type eventKey: string
        """
        if not eventKey in self.EVENT_TYPES:
            raise Exception(
                "AnimatedCollapsible (runCallbacks): invalid event type '%s'" %
                (eventKey))
        else:
            for callback in self.__eventCallbacks[eventKey]:
                if args:
                    callback(*args)
                else:
                    callback()

    def isExpanded(self):
        """
        @return: Whether the collapsible is expanded or not.
        @rtype: boolean
        """
        return self.toggled

    def setContents(self, widget):
        """ 
        Similar to the 'setWidget' function
        of a QWidget: sets the internal contents
        of the collapsible.
        """
        self.__contents = [widget]
        layout = qt.QHBoxLayout()
        layout.addWidget(widget)
        layout.setContentsMargins(0, 0, 0, 0)
        self.frame.setLayout(layout)

    def getContents(self):
        """ 
        """
        return self.__contents

    def setEasingCurve(self, easingCurve):
        """
        Sets the animation easing curve.

        @param easingCurve: The easing curve to set.
        @type easingCurve: qt.QEasingCurve
        """
        self.__easingCurve = easingCurve

    def setCollapsedHeight(self, height):
        """
        Sets the collapsed height.

        @param height: The height to set.
        @type height: number
        """
        self.collapsedHeight = height

    def setMaxExpandedHeight(self, height, applyImmediately=False):
        """ 
        
        
        @param height: The height to set.
        @type height: number

        @param applyImmediately: The whether to apply the height changes immediately using the 
            'ctk.CollapsibleButton.setMaximumHeight' function.  This usually is needed only
            when the collapsible is in the 'expanded' state.
        @type applyImmediately: boolean
        """
        self.maxExpandedHeight = height
        if applyImmediately:
            self.setMaximumHeight(height)

    def setMinExpandedHeight(self, height, applyImmediately=False):
        """ 
        As stated.

        @param height: The height to set.
        @type height: number

        @param applyImmediately: The whether to apply the height changes immediately using the 
            'ctk.CollapsibleButton.setMinimumHeight' function.  This usually is needed only
            when the collapsible is in the 'expanded' state.
        @type applyImmediately: boolean
        """
        self.minExpandedHeight = height
        if applyImmediately:
            self.setMinimumHeight(height)

    def setChecked(self, toggled, animDuration=None):
        """ 
        Constructs an executes an animation for the widget
        once the title button is toggled.
        """

        #----------------
        # We need to set the button state in case
        # this method is programatically called.
        #----------------
        self.toggleButton.setChecked(toggled)

        #----------------
        # Track whether collapsible was toggled.
        #----------------
        self.toggled = toggled

        #----------------
        # Define the animation duration.
        #----------------
        if not animDuration:
            animDuration = self.animDuration

        #----------------
        # Clear animation
        #----------------
        self.animations.clear()

        #----------------
        # For safety, set the width of
        # the widget to '100%'
        #----------------
        self.setStyleSheet('width: 100%')

        #----------------
        # Modify button text to match the toggled
        # state (down arrow or right arrow)
        #----------------
        self.__modifyToggleButton(toggled)

        #----------------
        # Make the animation object
        #----------------
        anim = qt.QPropertyAnimation(self, 'size')

        #----------------
        # Set the duration
        #----------------
        anim.setDuration(animDuration)

        #----------------
        # Set the easing curve
        #----------------
        anim.setEasingCurve(self.__easingCurve)

        #----------------
        # Set the start/end values depending on
        # the toggle state.
        #----------------
        if self.toggled:

            self.__runCallbacks('expandStart')

            #
            # Establish the 'toggled'/expanded animation sizes.
            #
            startSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            endSize = qt.QSize(self.geometry.width(), self.maxExpandedHeight)
            self.setMaximumHeight(self.collapsedHeight)
            self.setMinimumHeight(self.collapsedHeight)

        else:

            self.__runCallbacks('collapseStart')

            #
            # Establish the 'untoggled'/collapsed animation sizes.
            #
            startHeight = self.geometry.height()

            #
            # Save original stretch height
            #
            self.setMaximumHeight(startHeight)

            startSize = qt.QSize(self.geometry.width(), startHeight)
            endSize = qt.QSize(self.geometry.width(), self.collapsedHeight)
            self.setMaximumHeight(startHeight)
            self.setMinimumHeight(startHeight)

            #
            # Hide the internal contents for better
            # visual clarity.
            #
            self.__hideContents()

        #----------------
        # Set the start/end animation values.
        #----------------
        anim.setStartValue(startSize)
        anim.setEndValue(endSize)

        #----------------
        # Set callback during animation.
        #----------------
        anim.valueChanged.connect(self.__onAnimate)

        #----------------
        # Connect the 'finished()' signal of the animation
        # to the finished callback...
        #----------------
        anim.connect('finished()', self.__onAnimEnd)

        #----------------
        # Add main animation to queue and
        # start animation.
        #----------------
        self.animations.addAnimation(anim)
        self.animations.start()

    def setSizeGripVisible(self, visible):
        """ 
        Sets the size grip in the bottom-right
        corner of the screen visible or hidden.
        """
        if visible:
            self.sizeGrip.show()
        else:
            self.sizeGrip.hide()

    def setAnimLength(self, duration):
        """ 
        As stated.
        """
        self.animDuration = duration

    def suspendAnim(self, suspend=False):
        """ 
        Suspends the animation length by converting
        the duration to 0, saving the previous state.
        When the user sets the 'suspend' argument to 
        'False' then the previous animation state is 
        restored.
        """
        if suspend:
            self.originalAnimDuration = self.animDuration
            self.animDuration = 0
        else:
            self.animDuration = self.originalAnimDuration

    def __modifyToggleButton(self, toggled):
        """ 
        Modifies the arrow character of the button
        title to match the 'toggled' state and also
        sets its text to 'self.title.'
        """
        arrowChr = self.downArrowChar if toggled else self.rightArrowChar
        self.toggleButton.setText(arrowChr + '  ' + self.title)
        self.toggleButton.setFixedHeight(17)
        self.toggleButton.setMinimumWidth(10)
        self.toggleButton.setMaximumWidth(110)

    def __onAnimate(self, variant):
        """ 
        Function during main animation
        sequence.  Calls the user-inputted 'onAnimate'
        callback.
        """
        self.__runCallbacks('animate')
        self.setFixedHeight(variant.height())

    def __onAnimEnd(self):
        """ 
        Callback function when the animation
        finishes.  Also calls the user-inputted
        'onExpand' callback or 'onCollapse' callbacks
        depending on the toggle state of the widget.
        """

        #----------------
        # Call the animate function one last time.
        #----------------
        self.__onAnimate(
            qt.QSize(self.geometry.width(), self.geometry.height()))

        #----------------
        # If the widget is in a 'toggled' state.
        #----------------
        if self.toggled:

            #
            # Set its height to either 'stretchHeight'
            # or 'expandedHeight.  For an explanation of 'stretchHeight'
            # see it's declaration in the __init__ function.
            #
            self.setMaximumHeight(self.maxExpandedHeight)

            self.setMinimumHeight(self.minExpandedHeight)

            #
            # Show the internal contents
            #
            self.__showContents()

            #
            # Run the the 'onExpand' callback.
            #
            self.__runCallbacks('expanded')
            self.__runCallbacks('expandEnd')

        #----------------
        # Otherwise if it is 'collapsed'
        #----------------
        else:

            #
            # Set the height to 'self.collapsedHeight'.
            #
            self.setFixedHeight(self.collapsedHeight)

            #
            # Run callbacks
            #
            self.__runCallbacks('collapsed')
            self.__runCallbacks('collapseEnd')

    def __hideContents(self):
        """ 
        As stated.
        """
        if self.__contents:
            for contentsWidget in self.__contents:
                contentsWidget.hide()

    def __showContents(self):
        """ 
        As stated.
        """
        if self.__contents:
            for contentsWidget in self.__contents:
                contentsWidget.show()