def start(self, dummyResults='DIREKT'): """start the animation, returning its deferred""" assert self.state() != QAbstractAnimation.Running tiles = set() for animation in self.animations: tile = animation.targetObject() self.debug |= tile.element in Debug.animation tiles.add(tile) tile.setActiveAnimation(animation) self.addAnimation(animation) propName = animation.pName() animation.setStartValue(tile.getValue(propName)) if propName == 'rotation': # change direction if that makes the difference smaller endValue = animation.unpackEndValue() currValue = tile.rotation if endValue - currValue > 180: animation.setStartValue(currValue + 360) if currValue - endValue > 180: animation.setStartValue(currValue - 360) for tile in tiles: tile.graphics.setDrawingOrder() self.finished.connect(self.allFinished) scene = Internal.field.centralScene scene.disableFocusRect = True QParallelAnimationGroup.start(self, QAbstractAnimation.DeleteWhenStopped) if self.debug: logDebug('Animation group %d started (%s)' % (id(self), ','.join('A%d' % (id(x) % 10000) for x in self.animations))) return succeed(None)
def start(self, dummyResults='DIREKT'): """start the animation, returning its deferred""" assert self.state() != QAbstractAnimation.Running tiles = set() for animation in self.animations: tile = animation.targetObject() self.debug |= tile.element in Debug.animation tiles.add(tile) tile.setActiveAnimation(animation) self.addAnimation(animation) propName = animation.pName() animation.setStartValue(tile.getValue(propName)) if propName == 'rotation': # change direction if that makes the difference smaller endValue = animation.unpackEndValue() currValue = tile.rotation if endValue - currValue > 180: animation.setStartValue(currValue + 360) if currValue - endValue > 180: animation.setStartValue(currValue - 360) for tile in tiles: tile.graphics.setDrawingOrder() self.finished.connect(self.allFinished) scene = Internal.field.centralScene scene.disableFocusRect = True QParallelAnimationGroup.start(self, QAbstractAnimation.DeleteWhenStopped) if self.debug: logDebug('Animation group %d started (%s)' % ( id(self), ','.join('A%d' % (id(x) % 10000) for x in self.animations))) return succeed(None)
def trigger(self, ui): """ Trigger this animation """ glyph = [ glyph for glyph in ui.scene.items() if hasattr(glyph, 'entity') and glyph.entity == self.mover ][0] if self.direction in (2, 3, 4): self.flipped = True self.offset = 32 if self.direction in (6, 7, 8): self.flipped = False self.offset = 0 if self.flipped: glyph.flipped = True glyph.setTransform(QTransform.fromScale(-1, 1)) else: glyph.flipped = False glyph.setTransform(QTransform.fromScale(1, 1)) if glyph.entity.artificial_intelligence: adapter = MapGlyphAdapter(ui, glyph) else: adapter = MapGlyphAdapter(ui, glyph, True) animation = QParallelAnimationGroup() move_y = QPropertyAnimation(adapter, 'y_location') move_y.setDuration(100) move_y.setStartValue(self.start[1] * 32) move_y.setEndValue(self.destination[1] * 32) move_x = QPropertyAnimation(adapter, 'x_location') move_x.setDuration(100) move_x.setStartValue(self.start[0] * 32 + self.offset) move_x.setEndValue(self.destination[0] * 32 + self.offset) animation.addAnimation(move_y) animation.addAnimation(move_x) ui.animations.append(animation) animation.finished.connect(ui.remove_finished_animation) animation.start()
def trigger(self, ui): """ Trigger this animation """ glyph = [glyph for glyph in ui.scene.items() if hasattr(glyph, 'entity') and glyph.entity == self.mover][0] if self.direction in (2, 3, 4): self.flipped = True self.offset = 32 if self.direction in (6, 7, 8): self.flipped = False self.offset = 0 if self.flipped: glyph.flipped = True glyph.setTransform(QTransform.fromScale(-1, 1)) else: glyph.flipped = False glyph.setTransform(QTransform.fromScale(1, 1)) if glyph.entity.artificial_intelligence: adapter = MapGlyphAdapter(ui, glyph) else: adapter = MapGlyphAdapter(ui, glyph, True) animation = QParallelAnimationGroup() move_y = QPropertyAnimation(adapter, 'y_location') move_y.setDuration(100) move_y.setStartValue(self.start[1] * 32) move_y.setEndValue(self.destination[1] * 32) move_x = QPropertyAnimation(adapter, 'x_location') move_x.setDuration(100) move_x.setStartValue(self.start[0] * 32 + self.offset) move_x.setEndValue(self.destination[0] * 32 + self.offset) animation.addAnimation(move_y) animation.addAnimation(move_x) ui.animations.append(animation) animation.finished.connect(ui.remove_finished_animation) animation.start()
class Robot(RoboPart): def __init__(self, parent=None): RoboPart.__init__(self) self.setFlag(QGraphicsItem.ItemHasNoContents) self.torsoItem = RobotTorso(self) self.headItem = RobotHead(self.torsoItem) self.upperLeftArmItem = RobotLimb(self.torsoItem) self.lowerLeftArmItem = RobotLimb(self.upperLeftArmItem) self.upperRightArmItem = RobotLimb(self.torsoItem) self.lowerRightArmItem = RobotLimb(self.upperRightArmItem) self.upperRightLegItem = RobotLimb(self.torsoItem) self.lowerRightLegItem = RobotLimb(self.upperRightLegItem) self.upperLeftLegItem = RobotLimb(self.torsoItem) self.lowerLeftLegItem = RobotLimb(self.upperLeftLegItem) self.headItem.setPos(0, -18) self.upperLeftArmItem.setPos(-15, -10) self.lowerLeftArmItem.setPos(30, 0) self.upperRightArmItem.setPos(15, -10) self.lowerRightArmItem.setPos(30, 0) self.upperRightLegItem.setPos(10, 32) self.lowerRightLegItem.setPos(30, 0) self.upperLeftLegItem.setPos(-10, 32) self.lowerLeftLegItem.setPos(30, 0) self.animation = QParallelAnimationGroup(None) #self.headAnimation = QPropertyAnimation(self.headItem, "scale") #self.headAnimation.setStartValue(20) #self.headAnimation.setEndValue(-20) #self.headScaleAnimation = QPropertyAnimation(self.headItem, "scale") #self.headScaleAnimation.setEndValue(1.1) #self.animation.addAnimation(self.headAnimation) #self.animation.addAnimation(self.headScaleAnimation) #self.upperLeftArmAnimation = QPropertyAnimation(self.upperLeftArmItem, "rotation") #self.upperLeftArmAnimation.setStartValue(190) #self.upperLeftArmAnimation.setEndValue(180) #self.animation.addAnimation(self.upperLeftArmAnimation) #self.lowerLeftArmAnimation = QPropertyAnimation(self.lowerLeftArmItem, "rotation") #self.lowerLeftArmAnimation.setStartValue(50) #self.lowerLeftArmAnimation.setEndValue(10) #self.animation.addAnimation(self.lowerLeftArmAnimation) #self.upperRightArmAnimation = QPropertyAnimation(self.upperRightArmItem, "rotation") #self.upperRightArmAnimation.setStartValue(300) #self.upperRightArmAnimation.setEndValue(310) #self.animation.addAnimation(self.upperRightArmAnimation) #self.lowerRightArmAnimation = QPropertyAnimation(self.lowerRightArmItem, "rotation") #self.lowerRightArmAnimation.setStartValue(0) #self.lowerRightArmAnimation.setEndValue(-70) #self.animation.addAnimation(self.lowerRightArmAnimation) #self.upperLeftLegAnimation = QPropertyAnimation(self.upperLeftLegItem, "rotation") #self.upperLeftLegAnimation.setStartValue(150) #self.upperLeftLegAnimation.setEndValue(80) #self.animation.addAnimation(self.upperLeftLegAnimation) #self.lowerLeftLegAnimation = QPropertyAnimation(self.lowerLeftLegItem, "rotation") #self.lowerLeftLegAnimation.setStartValue(70) #self.lowerLeftLegAnimation.setEndValue(10) #self.animation.addAnimation(self.lowerLeftLegAnimation) #self.upperRightLegAnimation = QPropertyAnimation(self.upperRightLegItem, "rotation") #self.upperRightLegAnimation.setStartValue(40) #self.upperRightLegAnimation.setEndValue(120) #self.animation.addAnimation(self.upperRightLegAnimation) #self.lowerRightLegAnimation = QPropertyAnimation(self.lowerRightLegItem, "rotation") #self.lowerRightLegAnimation.setStartValue(10) #self.lowerRightLegAnimation.setEndValue(50) #self.animation.addAnimation(self.lowerRightLegAnimation) #self.torsoAnimation = QPropertyAnimation(self.torsoItem, "rotation") #self.torsoAnimation.setStartValue(5) #self.torsoAnimation.setEndValue(-20) #self.animation.addAnimation(self.torsoAnimation) for i in xrange(self.animation.animationCount()): anim = QPropertyAnimation(self.animation.animationAt(i)) anim.setEasingCurve(QEasingCurve.SineCurve) anim.setDuration(2000) self.animation.setLoopCount(-1) self.animation.start() def boundingRect(self): return QRectF() def paint(self): pass
class SlidingStackedWidget(QStackedWidget): animationEasingCurve = QtDynamicProperty('animationEasingCurve', int) animationDuration = QtDynamicProperty('animationDuration', int) verticalMode = QtDynamicProperty('verticalMode', bool) wrap = QtDynamicProperty('wrap', bool) animationFinished = pyqtSignal() LeftToRight, RightToLeft, TopToBottom, BottomToTop, Automatic = range(5) def __init__(self, parent=None): super(SlidingStackedWidget, self).__init__(parent) self.animationEasingCurve = QEasingCurve.Linear self.animationDuration = 250 self.verticalMode = False self.wrap = False self._active = False self._animation_group = QParallelAnimationGroup() self._animation_group.finished.connect(self._SH_AnimationGroupFinished) def slideInNext(self): next_index = self.currentIndex() + 1 if self.wrap or next_index < self.count(): self.slideInIndex(next_index % self.count(), direction=self.BottomToTop if self.verticalMode else self.RightToLeft) def slideInPrev(self): previous_index = self.currentIndex() - 1 if self.wrap or previous_index >= 0: self.slideInIndex(previous_index % self.count(), direction=self.TopToBottom if self.verticalMode else self.LeftToRight) def slideInIndex(self, index, direction=Automatic): self.slideInWidget(self.widget(index), direction) def slideInWidget(self, widget, direction=Automatic): if self.indexOf(widget) == -1 or widget is self.currentWidget(): return if self._active: return self._active = True prev_widget = self.currentWidget() next_widget = widget if direction == self.Automatic: if self.indexOf(prev_widget) < self.indexOf(next_widget): direction = self.BottomToTop if self.verticalMode else self.RightToLeft else: direction = self.TopToBottom if self.verticalMode else self.LeftToRight width = self.frameRect().width() height = self.frameRect().height() # the following is important, to ensure that the new widget has correct geometry information when sliding in the first time next_widget.setGeometry(0, 0, width, height) if direction in (self.TopToBottom, self.BottomToTop): offset = QPoint(0, height if direction == self.TopToBottom else -height) elif direction in (self.LeftToRight, self.RightToLeft): offset = QPoint(width if direction == self.LeftToRight else -width, 0) # re-position the next widget outside of the display area prev_widget_position = prev_widget.pos() next_widget_position = next_widget.pos() next_widget.move(next_widget_position - offset) next_widget.show() next_widget.raise_() prev_widget_animation = QPropertyAnimation(prev_widget, "pos") prev_widget_animation.setDuration(self.animationDuration) prev_widget_animation.setEasingCurve(QEasingCurve(self.animationEasingCurve)) prev_widget_animation.setStartValue(prev_widget_position) prev_widget_animation.setEndValue(prev_widget_position + offset) next_widget_animation = QPropertyAnimation(next_widget, "pos") next_widget_animation.setDuration(self.animationDuration) next_widget_animation.setEasingCurve(QEasingCurve(self.animationEasingCurve)) next_widget_animation.setStartValue(next_widget_position - offset) next_widget_animation.setEndValue(next_widget_position) self._animation_group.clear() self._animation_group.addAnimation(prev_widget_animation) self._animation_group.addAnimation(next_widget_animation) self._animation_group.start() def _SH_AnimationGroupFinished(self): prev_widget_animation = self._animation_group.animationAt(0) next_widget_animation = self._animation_group.animationAt(1) prev_widget = prev_widget_animation.targetObject() next_widget = next_widget_animation.targetObject() self.setCurrentWidget(next_widget) prev_widget.hide() # this may have been done already by QStackedWidget when changing the current widget above -Dan prev_widget.move(prev_widget_animation.startValue()) # move the out-shifted widget back to its original position self._animation_group.clear() self._active = False self.animationFinished.emit()
def slideIn(self, index, direction=Direction.Automatic): """ Slides in the panel at the inputed index in the given direction for this widget. :param index | <int> direction | <XStackedWidget.Direction> :return <bool> | success """ # do not allow multiple slides while it is active if self._active: return False # determine the proper index to calculate invert = False if self.count() <= index: if not self.wrap(): return False index = self.count() % index invert = True elif index < 0: if not self.wrap(): return False index = self.count() + index invert = True # define the direction information if index == self.currentIndex(): return False elif self.currentIndex() < index: if direction == XStackedWidget.Direction.Automatic: if self.isVerticalMode(): direction = XStackedWidget.Direction.BottomToTop else: direction = XStackedWidget.Direction.RightToLeft else: if direction == XStackedWidget.Direction.Automatic: if self.isVerticalMode(): direction = XStackedWidget.Direction.TopToBottom else: direction = XStackedWidget.Direction.LeftToRight # invert the animation if we are wrapping if invert: if direction == XStackedWidget.Direction.BottomToTop: direction = XStackedWidget.Direction.TopToBottom elif direction == XStackedWidget.Direction.TopToBottom: direction = XStackedWidget.Direction.BottomToTop elif direction == XStackedWidget.Direction.LeftToRight: direction = XStackedWidget.Direction.RightToLeft else: direction = XStackedWidget.Direction.LeftToRight self._active = True offset_x = self.frameRect().width() offset_y = self.frameRect().height() next_widget = self.widget(index) curr_widget = self.widget(self.currentIndex()) next_widget.setGeometry(0, 0, offset_x, offset_y) if direction == XStackedWidget.Direction.BottomToTop: offset_x = 0 offset_y = -offset_y elif direction == XStackedWidget.Direction.TopToBottom: offset_x = 0 elif direction == XStackedWidget.Direction.RightToLeft: offset_x = -offset_x offset_y = 0 elif direction == XStackedWidget.Direction.LeftToRight: offset_y = 0 next_point = next_widget.pos() curr_point = curr_widget.pos() self._nextIndex = index self._lastIndex = self.currentIndex() self._lastPoint = QPoint(curr_point) next_widget.move(next_point.x()-offset_x, next_point.y()-offset_y) next_widget.raise_() next_widget.show() curr_anim = QPropertyAnimation(curr_widget, 'pos') curr_anim.setDuration(self.speed()) curr_anim.setEasingCurve(self.animationType()) curr_anim.setStartValue(curr_point) curr_anim.setEndValue(QPoint(curr_point.x()+offset_x, curr_point.y()+offset_y)) next_anim = QPropertyAnimation(next_widget, 'pos') next_anim.setDuration(self.speed()) next_anim.setEasingCurve(self.animationType()) next_anim.setStartValue(QPoint(next_point.x()-offset_x, next_point.y()-offset_y)) next_anim.setEndValue(next_point) anim_group = QParallelAnimationGroup(self) anim_group.addAnimation(curr_anim) anim_group.addAnimation(next_anim) anim_group.finished.connect(self._finishAnimation) anim_group.finished.connect(anim_group.deleteLater) anim_group.start() return True
def slideIn(self, index, direction=Direction.Automatic): """ Slides in the panel at the inputed index in the given direction for this widget. :param index | <int> direction | <XStackedWidget.Direction> :return <bool> | success """ # do not allow multiple slides while it is active if self._active: return False # determine the proper index to calculate invert = False if self.count() <= index: if not self.wrap(): return False index = self.count() % index invert = True elif index < 0: if not self.wrap(): return False index = self.count() + index invert = True # define the direction information if index == self.currentIndex(): return False elif self.currentIndex() < index: if direction == XStackedWidget.Direction.Automatic: if self.isVerticalMode(): direction = XStackedWidget.Direction.BottomToTop else: direction = XStackedWidget.Direction.RightToLeft else: if direction == XStackedWidget.Direction.Automatic: if self.isVerticalMode(): direction = XStackedWidget.Direction.TopToBottom else: direction = XStackedWidget.Direction.LeftToRight # invert the animation if we are wrapping if invert: if direction == XStackedWidget.Direction.BottomToTop: direction = XStackedWidget.Direction.TopToBottom elif direction == XStackedWidget.Direction.TopToBottom: direction = XStackedWidget.Direction.BottomToTop elif direction == XStackedWidget.Direction.LeftToRight: direction = XStackedWidget.Direction.RightToLeft else: direction = XStackedWidget.Direction.LeftToRight self._active = True offset_x = self.frameRect().width() offset_y = self.frameRect().height() next_widget = self.widget(index) curr_widget = self.widget(self.currentIndex()) next_widget.setGeometry(0, 0, offset_x, offset_y) if direction == XStackedWidget.Direction.BottomToTop: offset_x = 0 offset_y = -offset_y elif direction == XStackedWidget.Direction.TopToBottom: offset_x = 0 elif direction == XStackedWidget.Direction.RightToLeft: offset_x = -offset_x offset_y = 0 elif direction == XStackedWidget.Direction.LeftToRight: offset_y = 0 next_point = next_widget.pos() curr_point = curr_widget.pos() self._nextIndex = index self._lastIndex = self.currentIndex() self._lastPoint = QPoint(curr_point) next_widget.move(next_point.x() - offset_x, next_point.y() - offset_y) next_widget.raise_() next_widget.show() curr_anim = QPropertyAnimation(curr_widget, 'pos') curr_anim.setDuration(self.speed()) curr_anim.setEasingCurve(self.animationType()) curr_anim.setStartValue(curr_point) curr_anim.setEndValue( QPoint(curr_point.x() + offset_x, curr_point.y() + offset_y)) next_anim = QPropertyAnimation(next_widget, 'pos') next_anim.setDuration(self.speed()) next_anim.setEasingCurve(self.animationType()) next_anim.setStartValue( QPoint(next_point.x() - offset_x, next_point.y() - offset_y)) next_anim.setEndValue(next_point) anim_group = QParallelAnimationGroup(self) anim_group.addAnimation(curr_anim) anim_group.addAnimation(next_anim) anim_group.finished.connect(self._finishAnimation) anim_group.finished.connect(anim_group.deleteLater) anim_group.start() return True
class SlidingStackedWidget(QStackedWidget): animationEasingCurve = QtDynamicProperty('animationEasingCurve', int) animationDuration = QtDynamicProperty('animationDuration', int) verticalMode = QtDynamicProperty('verticalMode', bool) wrap = QtDynamicProperty('wrap', bool) animationFinished = pyqtSignal() LeftToRight, RightToLeft, TopToBottom, BottomToTop, Automatic = range(5) def __init__(self, parent=None): super(SlidingStackedWidget, self).__init__(parent) self.animationEasingCurve = QEasingCurve.Linear self.animationDuration = 250 self.verticalMode = False self.wrap = False self._active = False self._animation_group = QParallelAnimationGroup() self._animation_group.finished.connect(self._SH_AnimationGroupFinished) def slideInNext(self): next_index = self.currentIndex() + 1 if self.wrap or next_index < self.count(): self.slideInIndex(next_index % self.count(), direction=self.BottomToTop if self.verticalMode else self.RightToLeft) def slideInPrev(self): previous_index = self.currentIndex() - 1 if self.wrap or previous_index >= 0: self.slideInIndex(previous_index % self.count(), direction=self.TopToBottom if self.verticalMode else self.LeftToRight) def slideInIndex(self, index, direction=Automatic): self.slideInWidget(self.widget(index), direction) def slideInWidget(self, widget, direction=Automatic): if self.indexOf(widget) == -1 or widget is self.currentWidget(): return if self._active: return self._active = True prev_widget = self.currentWidget() next_widget = widget if direction == self.Automatic: if self.indexOf(prev_widget) < self.indexOf(next_widget): direction = self.BottomToTop if self.verticalMode else self.RightToLeft else: direction = self.TopToBottom if self.verticalMode else self.LeftToRight width = self.frameRect().width() height = self.frameRect().height() # the following is important, to ensure that the new widget has correct geometry information when sliding in the first time next_widget.setGeometry(0, 0, width, height) if direction in (self.TopToBottom, self.BottomToTop): offset = QPoint( 0, height if direction == self.TopToBottom else -height) elif direction in (self.LeftToRight, self.RightToLeft): offset = QPoint(width if direction == self.LeftToRight else -width, 0) # re-position the next widget outside of the display area prev_widget_position = prev_widget.pos() next_widget_position = next_widget.pos() next_widget.move(next_widget_position - offset) next_widget.show() next_widget.raise_() prev_widget_animation = QPropertyAnimation(prev_widget, "pos") prev_widget_animation.setDuration(self.animationDuration) prev_widget_animation.setEasingCurve( QEasingCurve(self.animationEasingCurve)) prev_widget_animation.setStartValue(prev_widget_position) prev_widget_animation.setEndValue(prev_widget_position + offset) next_widget_animation = QPropertyAnimation(next_widget, "pos") next_widget_animation.setDuration(self.animationDuration) next_widget_animation.setEasingCurve( QEasingCurve(self.animationEasingCurve)) next_widget_animation.setStartValue(next_widget_position - offset) next_widget_animation.setEndValue(next_widget_position) self._animation_group.clear() self._animation_group.addAnimation(prev_widget_animation) self._animation_group.addAnimation(next_widget_animation) self._animation_group.start() def _SH_AnimationGroupFinished(self): prev_widget_animation = self._animation_group.animationAt(0) next_widget_animation = self._animation_group.animationAt(1) prev_widget = prev_widget_animation.targetObject() next_widget = next_widget_animation.targetObject() self.setCurrentWidget(next_widget) prev_widget.hide( ) # this may have been done already by QStackedWidget when changing the current widget above -Dan prev_widget.move(prev_widget_animation.startValue( )) # move the outshifted widget back to its original position self._animation_group.clear() self._active = False self.animationFinished.emit()
def setCurrentAction(self, action): """ Sets the current action for this widget that highlights the size for this toolbar. :param action | <QAction> """ if action == self._currentAction: return self._currentAction = action self.currentActionChanged.emit(action) labels = self.actionLabels() anim_grp = QParallelAnimationGroup(self) max_size = self.maximumPixmapSize() min_size = self.minimumPixmapSize() if action: label = self.labelForAction(action) index = labels.index(label) # create the highlight effect palette = self.palette() effect = QGraphicsDropShadowEffect(label) effect.setXOffset(0) effect.setYOffset(0) effect.setBlurRadius(20) effect.setColor(QColor(40, 40, 40)) label.setGraphicsEffect(effect) offset = self.padding() if self.position() in (XDockToolbar.Position.East, XDockToolbar.Position.West): self.resize(max_size.width() + offset, self.height()) elif self.position() in (XDockToolbar.Position.North, XDockToolbar.Position.South): self.resize(self.width(), max_size.height() + offset) w = max_size.width() h = max_size.height() dw = (max_size.width() - min_size.width()) / 3 dh = (max_size.height() - min_size.height()) / 3 for i in range(4): before = index - i after = index + i if 0 <= before and before < len(labels): anim = XObjectAnimation(labels[before], 'setPixmapSize', anim_grp) anim.setEasingCurve(self.easingCurve()) anim.setStartValue(labels[before].pixmapSize()) anim.setEndValue(QSize(w, h)) anim.setDuration(self.duration()) anim_grp.addAnimation(anim) if i: labels[before].setGraphicsEffect(None) if after != before and 0 <= after and after < len(labels): anim = XObjectAnimation(labels[after], 'setPixmapSize', anim_grp) anim.setEasingCurve(self.easingCurve()) anim.setStartValue(labels[after].pixmapSize()) anim.setEndValue(QSize(w, h)) anim.setDuration(self.duration()) anim_grp.addAnimation(anim) if i: labels[after].setGraphicsEffect(None) w -= dw h -= dh else: offset = self.padding() for label in self.actionLabels(): # clear the graphics effect label.setGraphicsEffect(None) # create the animation anim = XObjectAnimation(label, 'setPixmapSize', self) anim.setEasingCurve(self.easingCurve()) anim.setStartValue(label.pixmapSize()) anim.setEndValue(min_size) anim.setDuration(self.duration()) anim_grp.addAnimation(anim) anim_grp.finished.connect(self.resizeToMinimum) anim_grp.start() self._animating = True anim_grp.finished.connect(anim_grp.deleteLater) anim_grp.finished.connect(self.__markAnimatingFinished) if self._currentAction: self._hoverTimer.start() else: self._hoverTimer.stop()