Esempio n. 1
0
class Robot(RobotPart):
    def __init__(self):
        super(Robot, self).__init__()

        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.timeline = QTimeLine()
        settings = [
        #             item               position    rotation at
        #                                 x    y    time 0  /  1
            ( self.headItem,              0,  -18,      20,   -20 ),
            ( self.upperLeftArmItem,    -15,  -10,     190,   180 ),
            ( self.lowerLeftArmItem,     30,    0,      50,    10 ),
            ( self.upperRightArmItem,    15,  -10,     300,   310 ),
            ( self.lowerRightArmItem,    30,    0,       0,   -70 ),
            ( self.upperRightLegItem,    10,   32,      40,   120 ),
            ( self.lowerRightLegItem,    30,    0,      10,    50 ),
            ( self.upperLeftLegItem,    -10,   32,     150,    80 ),
            ( self.lowerLeftLegItem,     30,    0,      70,    10 ),
            ( self.torsoItem,             0,    0,       5,   -20 )
        ]
        self.animations = []
        for item, pos_x, pos_y, rotation1, rotation2 in settings: 
            item.setPos(pos_x,pos_y)
            animation = QGraphicsItemAnimation()
            animation.setItem(item)
            animation.setTimeLine(self.timeline)
            animation.setRotationAt(0, rotation1)
            animation.setRotationAt(1, rotation2)
            self.animations.append(animation)
        self.animations[0].setScaleAt(1, 1.1, 1.1)
    
        self.timeline.setUpdateInterval(1000 / 25)
        self.timeline.setCurveShape(QTimeLine.SineCurve)
        self.timeline.setLoopCount(0)
        self.timeline.setDuration(2000)
        self.timeline.start()

    def boundingRect(self):
        return QRectF()

    def paint(self, painter, option, widget=None):
        pass
Esempio n. 2
0
class Robot(RobotPart):
    def __init__(self):
        super(Robot, self).__init__()

        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.timeline = QTimeLine()
        settings = [
            #             item               position    rotation at
            #                                 x    y    time 0  /  1
            (self.headItem, 0, -18, 20, -20),
            (self.upperLeftArmItem, -15, -10, 190, 180),
            (self.lowerLeftArmItem, 30, 0, 50, 10),
            (self.upperRightArmItem, 15, -10, 300, 310),
            (self.lowerRightArmItem, 30, 0, 0, -70),
            (self.upperRightLegItem, 10, 32, 40, 120),
            (self.lowerRightLegItem, 30, 0, 10, 50),
            (self.upperLeftLegItem, -10, 32, 150, 80),
            (self.lowerLeftLegItem, 30, 0, 70, 10),
            (self.torsoItem, 0, 0, 5, -20)
        ]
        self.animations = []
        for item, pos_x, pos_y, rotation1, rotation2 in settings:
            item.setPos(pos_x, pos_y)
            animation = QGraphicsItemAnimation()
            animation.setItem(item)
            animation.setTimeLine(self.timeline)
            animation.setRotationAt(0, rotation1)
            animation.setRotationAt(1, rotation2)
            self.animations.append(animation)
        self.animations[0].setScaleAt(1, 1.1, 1.1)

        self.timeline.setUpdateInterval(1000 / 25)
        self.timeline.setCurveShape(QTimeLine.SineCurve)
        self.timeline.setLoopCount(0)
        self.timeline.setDuration(2000)
        self.timeline.start()

    def boundingRect(self):
        return QRectF()

    def paint(self, painter, option, widget=None):
        pass
Esempio n. 3
0
    def wheelEvent(self, event):
        numDegrees = event.angleDelta() / 8
        print("wheel: {}".format(numDegrees))
        numSteps = numDegrees.y() / 15
        self._numScheduledScalings += numSteps
        if self._numScheduledScalings * numSteps < 0:
            self._numScheduledScalings = numSteps

        anim = QTimeLine(350, self)
        anim.setUpdateInterval(20)
        anim.valueChanged.connect(self.ScalingTime)
        anim.finished.connect(self.AnimFinished)
        anim.start()
Esempio n. 4
0
 def wheelEvent(self, event):
     # Check if zooming is enabled
     if not self.parent.menu.options[1].isChecked(): return
     # Zooming event on mouse scroll
     numDegrees = event.angleDelta() / 8
     numSteps = (numDegrees / 15).y()
     self._numScheduledScalings += numSteps
     if self._numScheduledScalings * numSteps < 0:
         self._numScheduledScalings = numSteps
     anim = QTimeLine(350, self)
     anim.setUpdateInterval(20)
     anim.valueChanged.connect(self.scalingTime)
     anim.finished.connect(self.animFinished)
     anim.start()
Esempio n. 5
0
    def wheelEvent(self, event):
        numDegrees = event.angleDelta() / 8
        numSteps = numDegrees / 15
        self._numScheduledScalings += numSteps.y()
        """ if user moved the wheel in another direction, we reset previously scheduled scalings """
        if self._numScheduledScalings * numSteps.y() < 0:
            self._numScheduledScalings = numSteps.y()

        anim = QTimeLine(350, self)
        anim.setUpdateInterval(20)

        anim.valueChanged.connect(self.scalingTime)
        anim.finished.connect(self.animFinished)

        anim.start()
Esempio n. 6
0
    def zoom(self, numDegrees):
        numSteps = numDegrees / 15
        self._numScheduledScalings += numSteps

        if (
                self._numScheduledScalings * numSteps < 0
        ):  # if user moved the wheel in another direction, we reset previously scheduled scalings
            self._numScheduledScalings = numSteps

        anim = QTimeLine(350, self)
        anim.setUpdateInterval(20)

        anim.valueChanged.connect(self.scalingTime)
        anim.finished.connect(self.scaleAnimFinished)
        anim.start()
Esempio n. 7
0
    def translateVerticalEvent(self, dy):
        numSteps = dy * 20
        self._numScheduledVTranslations += numSteps

        if (
                self._numScheduledVTranslations * numSteps < 0
        ):  # if user moved the wheel in another direction, we reset previously scheduled scalings
            self._numScheduledVTranslations = numSteps

        if not self.animatingV:
            anim = QTimeLine(350, self)
            anim.setUpdateInterval(10)

            anim.valueChanged.connect(self.translateVTime)
            anim.finished.connect(self.translateVAnimFinished)
            anim.start()
Esempio n. 8
0
    def wheelEvent(self, event):
        degree = event.angleDelta().y() / 8
        step = degree / 15

        self.scheduledscaling = self.scheduledscaling + step

        animation = QTimeLine(350)
        animation.setUpdateInterval(20)
        animation.valueChanged.connect(
            animation.currentValue
        )  #Timeline does not start without this line, maybe a QT bug
        animation.valueChanged.connect(
            lambda: self.scale(1.0 + self.scheduledscaling / 300.0, 1.0 + self.
                               scheduledscaling / 300.0))
        animation.finished.connect(self.reset)
        animation.start()
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("Screen and Gaze Capture")
        grid = QGridLayout()
        layout_frame = QFrame()
        layout_frame.setLayout(grid)
        self.setCentralWidget(layout_frame)

        self.tracker_label = QLabel("No eye tracker connected.")
        grid.addWidget(self.tracker_label, 0, 0)

        connect_button = QPushButton("Connect to Eye Tracker")
        connect_button.pressed.connect(connect_to_tracker)
        grid.addWidget(connect_button, 1, 0)

        calibrate_button = QPushButton("Calibrate Eye Tracker")
        calibrate_button.pressed.connect(calibrate)
        grid.addWidget(calibrate_button, 2, 0)

        self.record_button = QPushButton("Record Screen and Gaze")
        self.record_button.pressed.connect(capture_screen)
        grid.addWidget(self.record_button, 3, 0)

        self.author_vid_button = QPushButton("Write Author Video")
        self.author_vid_button.pressed.connect(create_video)
        grid.addWidget(self.author_vid_button, 4, 0)
        self.author_vid_button.setEnabled(False)

        self.timeline = QTimeLine()
        self.timeline.setCurveShape(QTimeLine.LinearCurve)
        self.timeline.setDuration(360000)  #Totsl video lengthn in milliseconds
        self.timeline.setFrameRange(
            0, 7500)  #Maximum Frames in this video as 30 fps
        self.timeline.frameChanged.connect(update_frame)
        self.timeline.setUpdateInterval(10)  #Rate of Frame Capture

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            app.closeAllWindows()
Esempio n. 10
0
    def wheelEvent(self, event: QWheelEvent) -> None:
        if event.modifiers() & Qt.ControlModifier:
            num_degrees = event.angleDelta().y() / 8.0
            num_steps = num_degrees / 15.0

            self.num_scheduled_steps += num_steps

            if self.num_scheduled_steps * num_steps < 0:
                self.num_scheduled_steps = num_steps

            animation = QTimeLine(duration=350, parent=self)
            animation.setUpdateInterval(20)

            value_changed_sig: pyqtBoundSignal = animation.valueChanged
            value_changed_sig.connect(self.scaling_step)

            finished_sig: pyqtBoundSignal = animation.finished
            finished_sig.connect(self.animation_finished)

            animation.start()
        else:
            super().wheelEvent(event)
class SideSlideDecorator(QWidget):
    m_slidePos: QPoint
    m_slideWidgetPixmap: QPixmap
    m_timeline: QTimeLine
    m_backgroundPixmap: QPixmap
    m_decorationColor: QColor

    clicked = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(SideSlideDecorator, self).__init__(*args, **kwargs)

        self.resize(self.maximumSize())

        self.m_backgroundPixmap = QPixmap()

        self.m_slidePos = QPoint()
        self.m_timeline = QTimeLine()
        self.m_timeline.setDuration(260)
        self.m_timeline.setUpdateInterval(40)
        self.m_timeline.setEasingCurve(QEasingCurve.OutQuad)
        self.m_timeline.setStartFrame(0)
        self.m_timeline.setEndFrame(10000)

        self.m_decorationColor = QColor(0, 0, 0, 0)

        def frameChanged(_value):
            self.m_decorationColor = QColor(0, 0, 0, _value / 100)
            self.update()

        self.m_timeline.frameChanged.connect(frameChanged)

    def grabSlideWidget(self, _slideWidget):
        self.m_slideWidgetPixmap = _slideWidget.grab()

    def grabParent(self):
        # self.m_backgroundPixmap = self.parentWidget().grab()
        pass

    def decorate(self, _dark):
        if self.m_timeline.state() == QTimeLine.Running:
            self.m_timeline.stop()

        self.m_timeline.setDirection(
            QTimeLine.Forward if _dark else QTimeLine.Backward)
        self.m_timeline.start()

    def slidePos(self):
        return self.m_slidePos

    def setSlidePos(self, _pos):
        if self.m_slidePos != _pos:
            self.m_slidePos = _pos
            self.update()

    def paintEvent(self, _event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.m_backgroundPixmap)
        painter.fillRect(self.rect(), self.m_decorationColor)
        painter.drawPixmap(self.m_slidePos, self.m_slideWidgetPixmap)

        super(SideSlideDecorator, self).paintEvent(_event)

    def mousePressEvent(self, _event):
        self.clicked.emit()

        super(SideSlideDecorator, self).mousePressEvent(_event)

    _slidePos = pyqtProperty(QPoint, fget=slidePos, fset=setSlidePos)
Esempio n. 12
0
class QPageWidget(QScrollArea):
    """ The QPageWidget provides a stack widget with animated page transitions. """

    #Emits
    currentChanged = pyqtSignal()

    def __init__(self, parent=None, direction="ltr", rtf=False):
        """ Creates a new QPageWidget on given parent object. 

        parent: QWidget parent
        direction: "ltr" -> Left To Right
                   "ttb" -> Top To Bottom
        rtf: Return to first, if its True it flips to the first page 
             when next page requested at the last page
        """

        # First initialize, QPageWidget is based on QScrollArea
        QScrollArea.__init__(self, parent)

        # Properties for QScrollArea
        self.setFrameShape(QFrame.NoFrame)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setWidgetResizable(True)

        # Main widget, which stores all Pages in it
        self.widget = QWidget(self)

        # Layout based on QBoxLayout which supports Vertical or Horizontal layout
        if direction == "ltr":
            self.layout = QBoxLayout(QBoxLayout.LeftToRight, self.widget)
            self.__scrollBar = self.horizontalScrollBar()
            self.__base_value = self.width
        else:
            self.layout = QBoxLayout(QBoxLayout.TopToBottom, self.widget)
            self.__scrollBar = self.verticalScrollBar()
            self.__base_value = self.height
        self.layout.setSpacing(0)

        #qboxlayout setmargin özelliği yok
        #self.layout.setMargin(0)

        # Return to first
        self.__return_to_first = rtf

        # TMP_PAGE, its using as last page in stack
        # A workaround for a QScrollArea bug
        self.__tmp_page = Page(QWidget(self.widget))
        self.__pages = [self.__tmp_page]
        self.__current = 0
        self.__last = 0

        # Set main widget
        self.setWidget(self.widget)

        # Animation TimeLine
        self.__timeline = QTimeLine()
        self.__timeline.setUpdateInterval(2)

        # Updates scrollbar position when frame changed
        self.__timeline.frameChanged.connect(
            lambda x: self.__scrollBar.setValue(x))

        # End of the animation
        self.__timeline.finished.connect(self._animateFinished)

        # Initialize animation
        self.setAnimation()
        self.setDuration()

    def _animateFinished(self):
        """ Its called by TimeLine when animation finished.

        It first runs the outMethod of last Page and then the inMethod of current Page
        Finally tt gives the focus to the current page and fixes the scrollBar
        """

        # Disable other widgets
        for page in self.__pages:
            if not page == self.__pages[self.__current]:
                page.widget.setEnabled(False)

        # Run last page's outMethod if exists
        if self.__pages[self.__last].outMethod:
            self.__pages[self.__last].outMethod()

        # Run new page's inMethod if exists
        if self.__pages[self.__current].inMethod:
            self.__pages[self.__current].inMethod()

        # Give focus to the current Page
        self.__pages[self.__current].widget.setFocus()

        # Update scrollbar position for current page
        self.__scrollBar.setValue(self.__current * self.__base_value())

        # Emit currentChanged SIGNAL
        self.currentChanged.emit()

    def event(self, event):
        """ Overrides the main event handler to catch resize events """
        # Catch Resize event
        if event.type() == QEvent.Resize:
            # Update each page size limits to mainwidget's new size
            for page in self.__pages:
                page.widget.setMinimumSize(self.size())
                page.widget.setMaximumSize(self.size())

            # Update viewport size limits to mainwidget's new size
            # It's a workaround for QScrollArea updateGeometry bug
            self.viewport().setMinimumSize(self.size())
            self.viewport().setMaximumSize(self.size())

            # Update scrollbar position for current page
            self.__scrollBar.setValue(self.__current * self.__base_value())

        # Return the Event
        return QScrollArea.event(self, event)

    def keyPressEvent(self, event):
        """ Overrides the keyPressEvent to ignore them """
        pass

    def wheelEvent(self, event):
        """ Overrides the wheelEvent to ignore them """
        pass

    def createPage(self, widget, inMethod=None, outMethod=None):
        """ Creates and adds new Page for given widget with given in/out methods.

        widget: A QWidget which is the mainwidget for this Page
        inMethod: (optional) QPageWidget triggers this method when the Page appear
        outMethod: (optional) QPageWidget triggers this method when the Page disappear
        """
        self.addPage(Page(widget, inMethod, outMethod))

    def addPage(self, page):
        """ Adds the given Page to the stack.

        page: A Page object
        """
        # First remove the last page; its __tmp_page
        self.__pages.pop()

        # Add new page
        self.__pages.append(page)
        self.layout.addWidget(page.widget)

        # Add __tmp_page to end
        self.__pages.append(self.__tmp_page)
        self.layout.addWidget(self.__tmp_page.widget)

        # Create connections for page navigation signals from new page
        try:
            page.widget.pageNext.connect(self.next)
            page.widget.pagePrevious.connect(self.prev)
            page.widget.setCurrent[int].connect(self.setCurrent)
        except:
            pass

    def __setCurrent(self, pageNumber):
        """ Internal method to set current page index. """
        self.__last = self.__current
        self.__current = min(max(0, pageNumber), len(self.__pages) - 2)
        if pageNumber == len(self.__pages) - 1 and self.__return_to_first:
            self.__current = 0

    def setCurrent(self, pageNumber=0):
        """ Set and flip the page with given pageNumber.

        pageNumber: index number of Page (default is 0)
        """
        self.__setCurrent(pageNumber)
        self.flipPage()

    def getCurrent(self):
        """ Returns current page index. """
        return self.__current

    def getCurrentWidget(self):
        """ Returns current page widget. """
        return self.getWidget(self.getCurrent())

    def getWidget(self, pageNumber):
        """ Returns widget for given page index 

        pageNumber: index number of Page
        """
        try:
            return self.__pages[pageNumber].widget
        except:
            return None

    def count(self):
        """ Returns number of pages. """
        return len(self.__pages) - 1

    def setAnimation(self, animation=35):
        """ Set the transition animation with the given animation.

        animation: the number represents predefined QEasingCurves
                   List of predefined QEasingCurves can be found from:
                   http://doc.qt.nokia.com/4/qeasingcurve.html#Type-enum

                   Default is QEasingCurve::InOutBack (35)
        """
        self.__animation = animation
        self.__timeline.setEasingCurve(QEasingCurve(self.__animation))

    def setDuration(self, duration=400):
        """ Set the transition duration.

        duration: duration time in ms
        """
        self.__duration = duration
        self.__timeline.setDuration(self.__duration)

    def flipPage(self, direction=0):
        """ Flip the page with given direction.

        direction: can be -1, 0 or +1
                   -1: previous page (if exists)
                    0: just flip to current page
                   +1: next page (if exists)
        """
        # Enable all widgets
        for page in self.__pages:
            page.widget.setEnabled(True)

        # Check given direction
        direction = direction if direction == 0 else max(min(1, direction), -1)

        # If direction is equal to zero no need to re-set current
        if not direction == 0:
            self.__setCurrent(self.__current + direction)

        # If last page is different from new page, flip it !
        if not self.__last == self.__current:
            self.__timeline.setFrameRange(self.__scrollBar.value(),
                                          self.__current * self.__base_value())
            self.__timeline.start()

    def next(self):
        """ Helper method to flip next page. """
        self.flipPage(1)

    def prev(self):
        """ Helper method to flip previous page. """
        self.flipPage(-1)
Esempio n. 13
0
class QPageWidget(QScrollArea):
    """ The QPageWidget provides a stack widget with animated page transitions. """

    #Emits
    currentChanged = pyqtSignal()
    
    def __init__(self, parent = None, direction = "ltr", rtf = False):
        """ Creates a new QPageWidget on given parent object. 

        parent: QWidget parent
        direction: "ltr" -> Left To Right
                   "ttb" -> Top To Bottom
        rtf: Return to first, if its True it flips to the first page 
             when next page requested at the last page
        """
                
        # First initialize, QPageWidget is based on QScrollArea
        QScrollArea.__init__(self, parent)

        # Properties for QScrollArea
        self.setFrameShape(QFrame.NoFrame)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setWidgetResizable(True)

        # Main widget, which stores all Pages in it
        self.widget = QWidget(self)

        # Layout based on QBoxLayout which supports Vertical or Horizontal layout
        if direction == "ltr":
            self.layout = QBoxLayout(QBoxLayout.LeftToRight, self.widget)
            self.__scrollBar = self.horizontalScrollBar()
            self.__base_value = self.width
        else:
            self.layout = QBoxLayout(QBoxLayout.TopToBottom, self.widget)
            self.__scrollBar = self.verticalScrollBar()
            self.__base_value = self.height
        self.layout.setSpacing(0)
        
        #qboxlayout setmargin özelliği yok
        #self.layout.setMargin(0)

        # Return to first
        self.__return_to_first = rtf

        # TMP_PAGE, its using as last page in stack
        # A workaround for a QScrollArea bug
        self.__tmp_page = Page(QWidget(self.widget))
        self.__pages = [self.__tmp_page]
        self.__current = 0
        self.__last = 0

        # Set main widget
        self.setWidget(self.widget)

        # Animation TimeLine
        self.__timeline = QTimeLine()
        self.__timeline.setUpdateInterval(2)

        # Updates scrollbar position when frame changed
        self.__timeline.frameChanged.connect(lambda x: self.__scrollBar.setValue(x))

        # End of the animation
        self.__timeline.finished.connect(self._animateFinished)

        # Initialize animation
        self.setAnimation()
        self.setDuration()

    def _animateFinished(self):
        """ Its called by TimeLine when animation finished.

        It first runs the outMethod of last Page and then the inMethod of current Page
        Finally tt gives the focus to the current page and fixes the scrollBar
        """

        # Disable other widgets
        for page in self.__pages:
            if not page == self.__pages[self.__current]:
                page.widget.setEnabled(False)

        # Run last page's outMethod if exists
        if self.__pages[self.__last].outMethod:
            self.__pages[self.__last].outMethod()

        # Run new page's inMethod if exists
        if self.__pages[self.__current].inMethod:
            self.__pages[self.__current].inMethod()

        # Give focus to the current Page
        self.__pages[self.__current].widget.setFocus()

        # Update scrollbar position for current page
        self.__scrollBar.setValue(self.__current * self.__base_value())

        # Emit currentChanged SIGNAL
        self.currentChanged.emit()

    def event(self, event):
        """ Overrides the main event handler to catch resize events """
        # Catch Resize event
        if event.type() == QEvent.Resize:
            # Update each page size limits to mainwidget's new size
            for page in self.__pages:
                page.widget.setMinimumSize(self.size())
                page.widget.setMaximumSize(self.size())

            # Update viewport size limits to mainwidget's new size
            # It's a workaround for QScrollArea updateGeometry bug
            self.viewport().setMinimumSize(self.size())
            self.viewport().setMaximumSize(self.size())

            # Update scrollbar position for current page
            self.__scrollBar.setValue(self.__current * self.__base_value())

        # Return the Event
        return QScrollArea.event(self, event)

    def keyPressEvent(self, event):
        """ Overrides the keyPressEvent to ignore them """
        pass

    def wheelEvent(self, event):
        """ Overrides the wheelEvent to ignore them """
        pass

    def createPage(self, widget, inMethod = None, outMethod = None):
        """ Creates and adds new Page for given widget with given in/out methods.

        widget: A QWidget which is the mainwidget for this Page
        inMethod: (optional) QPageWidget triggers this method when the Page appear
        outMethod: (optional) QPageWidget triggers this method when the Page disappear
        """
        self.addPage(Page(widget, inMethod, outMethod))

    def addPage(self, page):
        """ Adds the given Page to the stack.

        page: A Page object
        """
        # First remove the last page; its __tmp_page
        self.__pages.pop()

        # Add new page
        self.__pages.append(page)
        self.layout.addWidget(page.widget)

        # Add __tmp_page to end
        self.__pages.append(self.__tmp_page)
        self.layout.addWidget(self.__tmp_page.widget)

        # Create connections for page navigation signals from new page
        try:
            page.widget.pageNext.connect(self.next)
            page.widget.pagePrevious.connect(self.prev)
            page.widget.setCurrent[int].connect(self.setCurrent)
        except:
            pass

    def __setCurrent(self, pageNumber):
        """ Internal method to set current page index. """
        self.__last = self.__current
        self.__current = min(max(0, pageNumber), len(self.__pages) - 2)
        if pageNumber == len(self.__pages) - 1 and self.__return_to_first:
            self.__current = 0

    def setCurrent(self, pageNumber = 0):
        """ Set and flip the page with given pageNumber.

        pageNumber: index number of Page (default is 0)
        """
        self.__setCurrent(pageNumber)
        self.flipPage()

    def getCurrent(self):
        """ Returns current page index. """
        return self.__current

    def getCurrentWidget(self):
        """ Returns current page widget. """
        return self.getWidget(self.getCurrent())

    def getWidget(self, pageNumber):
        """ Returns widget for given page index 

        pageNumber: index number of Page
        """
        try:
            return self.__pages[pageNumber].widget
        except:
            return None

    def count(self):
        """ Returns number of pages. """
        return len(self.__pages) - 1

    def setAnimation(self, animation = 35):
        """ Set the transition animation with the given animation.

        animation: the number represents predefined QEasingCurves
                   List of predefined QEasingCurves can be found from:
                   http://doc.qt.nokia.com/4/qeasingcurve.html#Type-enum

                   Default is QEasingCurve::InOutBack (35)
        """
        self.__animation = animation
        self.__timeline.setEasingCurve(QEasingCurve(self.__animation))

    def setDuration(self, duration = 400):
        """ Set the transition duration.

        duration: duration time in ms
        """
        self.__duration = duration
        self.__timeline.setDuration(self.__duration)

    def flipPage(self, direction=0):
        """ Flip the page with given direction.

        direction: can be -1, 0 or +1
                   -1: previous page (if exists)
                    0: just flip to current page
                   +1: next page (if exists)
        """
        # Enable all widgets
        for page in self.__pages:
            page.widget.setEnabled(True)

        # Check given direction
        direction = direction if direction == 0 else max(min(1, direction), -1)

        # If direction is equal to zero no need to re-set current
        if not direction == 0:
            self.__setCurrent(self.__current + direction)

        # If last page is different from new page, flip it !
        if not self.__last == self.__current:
            self.__timeline.setFrameRange(self.__scrollBar.value(), self.__current * self.__base_value())
            self.__timeline.start()

    def next(self):
        """ Helper method to flip next page. """
        self.flipPage(1)

    def prev(self):
        """ Helper method to flip previous page. """
        self.flipPage(-1)
Esempio n. 14
0
class TSScene(QGraphicsScene):

    starttimechanged = pyqtSignal(str)
    endtimechanged = pyqtSignal(str)

    def __init__(self, parent, width=14, height=12, numofchannel=6):
        super(TSScene, self).__init__(parent)

        # set waveform windows
        figure = Figure()
        figure.set_size_inches(width, height)
        self.graphwidth = figure.dpi * width
        self.canvas = FigureCanvas(figure)
        self.addWidget(self.canvas)
        self.canvas.mpl_connect('button_press_event',self.button_press_event)
        self.canvas.mpl_connect('button_release_event', self.button_release_event)
        self.canvas.mpl_connect('motion_notify_event', self.motion_notify_event)
        self.canvas.mpl_connect('scroll_event', self.scroll_event)

        self.axesavailability = [True for i in range(numofchannel)]
        self.axes = []
        for i in range(numofchannel):
            self.axes.append(figure.add_subplot(str(numofchannel)+'1'+str(i+1)))


        # set backend data model
        self.data = TSData()
        self.visibleWave = {}
        self.starttime = None
        self.endtime = None

        # prepare for user input
        self.downxcoord = None
        self.wheelactive = False
        self.rect = None

        self.installEventFilter(self)
        self.showgap = False
        self.downbutton = None
        self.currentxdata = None

        self.count = 0
        self.state = 'ready'

        self.timeline = QTimeLine(1)
        self.timeline.setCurrentTime(0)
        self.timeline.setUpdateInterval(1)
        self.timeline.finished.connect(self.timeshift)
        self.timeline.finished.connect(self.animfinished)



    def animfinished(self):
        self.state = 'ready'
        self.timeline.setCurrentTime(0)

    def togglegap(self):
        self.showgap = ~self.showgap

        tmplist = self.visibleWave.copy()
        for wave in tmplist:
            self.refreshwave(wave,tmplist[wave][1])

            # self.togglewave(wave)
            # self.togglewave(wave, tmplist[wave][1])

    def applytime(self, start: str, end: str):
        if self.data is None:
            return


        for wave in self.visibleWave:
            if start<self.visibleWave[wave][3]:
                start = self.visibleWave[wave][3]
            if end>self.visibleWave[wave][4]:
                end = self.visibleWave[wave][4]

        self.starttime = UTCDateTime(start)
        self.endtime = UTCDateTime(end)
        print((self.starttime, self.endtime, '-----------------'))

        tmplist = self.visibleWave.copy()
        for wave in tmplist:
            self.refreshwave(wave, tmplist[wave][1])
            # self.togglewave(wave)
            # self.togglewave(wave, tmplist[wave][2])

    def loadfile(self, filename: str):
        self.data.loadFile(filename)

    def getlist(self):
        return self.data.getlist()

    def getsegments(self, item: object):
        waves = self.data.getsegments(item.text(0))


        wavelist = QListWidget()
        for w in waves:
            wavelist.addItem(w)
            # print(w)
        wavelist.itemDoubleClicked.connect(self.segmentselected)

        wavelistwindowlayout = QVBoxLayout()
        wavelistwindowlayout.addWidget(wavelist)

        self.wavelistwindow = QDialog(self.parent())
        self.wavelistwindow.setWindowTitle('segments')
        self.wavelistwindow.setLayout(wavelistwindowlayout)
        self.wavelistwindow.resize(800,600)
        self.wavelistwindow.show()
        self.segmentsource = item.text(0)
        self.currentitem = item

    def segmentselected(self, segment: str):

        matches = re.match(r'[^ ]+ \| ([^ ]+) - ([^ ]+) \| .*', segment.text(), flags=0)
        start = UTCDateTime(matches.group(1))
        end = UTCDateTime(matches.group(2))
        print(start)
        print(end)

        if self.segmentsource in self.visibleWave:
            self.applytime(start, end)
        else:
            self.starttime = start
            self.endtime = end
            print((self.segmentsource))
            self.togglewave(self.segmentsource)
            self.currentitem.setSelected(True)


    def refreshwave(self, wave: str, colorcode:int=0):
        if wave in self.visibleWave:
            axes, lines, _, _, _, _ = self.visibleWave[wave]
            self.removewave(axes, lines)
            self.visibleWave.pop(wave, None)
            channelid = self.axes.index(axes)
            self.axesavailability[channelid] = True
            waveform, wavename, starttime, endtime, gaps = self.data.getwaveform(wave, self.starttime, self.endtime)
            axes, lines = self.displaywave(wavename, waveform, gaps)
            if axes is not None:
                self.visibleWave[wave] = (axes, lines, colorcode, starttime, endtime, gaps)

    def hidewave(self, wave: str, colorcode:int=0):
        if wave in self.visibleWave:
            axes, lines, _, _, _, _ = self.visibleWave[wave]
            self.removewave(axes, lines)
            self.visibleWave.pop(wave, None)
            channelid = self.axes.index(axes)
            self.axesavailability[channelid] = True
            if len(self.visibleWave)==0:
                self.starttime = None
                self.endtime = None
            return True

    def showwave(self, wave: str, starttime=None, endtime=None):
        if starttime is None or endtime is None:
            if wave in self.visibleWave:
                pass
            else:
                self.togglewave(wave)
        else:
            self.starttime = starttime
            self.endtime = endtime
            tmplist = self.visibleWave.copy()
            for wave in tmplist:
                self.refreshwave(wave, tmplist[wave][1])
            if wave not in self.visibleWave:
                self.togglewave(wave)




    def togglewave(self, wave: str, colorcode:int=0):
        if wave in self.visibleWave:
            axes, lines, _, _, _, _ = self.visibleWave[wave]
            self.removewave(axes, lines)
            self.visibleWave.pop(wave, None)
            channelid = self.axes.index(axes)
            self.axesavailability[channelid] = True
            if len(self.visibleWave)==0:
                self.starttime = None
                self.endtime = None
        else:
            # print(wave)

            waveform, wavename, starttime, endtime, gaps = self.data.getwaveform(wave, self.starttime, self.endtime)
            print((starttime, endtime))
            axes, lines = self.displaywave(wavename, waveform, gaps)
            if axes is not None:
                self.visibleWave[wave] = (axes, lines, colorcode, starttime, endtime, gaps)
                #print("togglewave:", starttime, endtime)


    def displaywave(self, wavename: str, waveform: np.array, gaps, colorcode: int=None):

        if True not in self.axesavailability:
            return None, None
        else:

            location = self.axesavailability.index(True)
            axes = self.axes[location]
            self.axesavailability[location] = False
            if wavename is not None and waveform is not None:
                if colorcode is None:
                    colorcode = 'C'+str(location%10)

                times = waveform[0,:]
                span = round(len(times)/4)

                if span<1:
                    span = 1

                axes.set_xticks(times[::span])
                axes.set_xticklabels([UTCDateTime(t).strftime("%Y-%m-%d %H:%M:%S") for t in times[::span]])

                lines = axes.plot(times, waveform[1,:],linestyle="-", label=wavename, color=colorcode)
                if self.showgap:
                    for g in gaps:

                        if g[4].timestamp>=times[0] and g[5].timestamp<times[-1]:
                            axes.axvspan(g[4],g[5],facecolor='0.2',alpha=0.5)
                axes.legend()

                self.canvas.draw()

                if self.endtime is not None and self.starttime is not None and len(times)>0:
                    timewindow = self.endtime-self.starttime
                    if abs(times[0]-times[-1]-timewindow)/timewindow<0.1:
                        self.starttime = UTCDateTime(times[0])
                        self.endtime = self.starttime + timewindow
                elif len(times)>0:
                    self.starttime = UTCDateTime(times[0])
                    self.endtime = UTCDateTime(times[-1])



                self.starttimechanged.emit(self.starttime.strftime("%Y-%m-%d %H:%M:%S"))
                self.endtimechanged.emit(self.endtime.strftime("%Y-%m-%d %H:%M:%S"))
                return axes, lines
            else:
                lines = None
                axes.legend([wavename])

            return axes, lines




    def removewave(self, axes: Axes, lines: Line2D):
        if lines is not None:
            lines.pop(0).remove()
        axes.relim()
        axes.autoscale_view(True, True, True)
        axes.clear()
        self.canvas.draw()

    def timeshift(self):
        if self.downxcoord is None or self.currentxdata is None:
            return
        shift = self.downxcoord-self.currentxdata
        if shift == 0:
            print('skipped')
            return

        if self.starttime is None:
            return

        starttime = self.starttime + shift
        endtime = self.endtime + shift

        for wave in self.visibleWave:
            if starttime<self.visibleWave[wave][3]:
                starttime = self.visibleWave[wave][3]
            if endtime>self.visibleWave[wave][4]:
                endtime = self.visibleWave[wave][4]


        if starttime!=self.starttime and endtime!=self.endtime:
            self.starttime = starttime
            self.endtime = endtime

            tmplist = self.visibleWave.copy()

            for wave in tmplist:
                self.refreshwave(wave, tmplist[wave][1])
                # self.togglewave(wave)
                # self.togglewave(wave, tmplist[wave][2])



        return

    def timescale(self, delta: float):
        if self.starttime is None:
            return

        shift = (self.endtime - self.starttime) * -delta*0.1

        starttime = self.starttime + shift
        endtime = self.endtime - shift


        for wave in self.visibleWave:
            if starttime<self.visibleWave[wave][3]:
                starttime = self.starttime
            if endtime>self.visibleWave[wave][4]:
                endtime = self.endtime


        if endtime-starttime<0.1:
            pass
        elif starttime==self.starttime and endtime==self.endtime:
            pass
        else:
            self.starttime = starttime
            self.endtime = endtime
            tmplist = self.visibleWave.copy()
            for wave in tmplist:
                self.refreshwave(wave, tmplist[wave][1])
                # self.togglewave(wave)
                # self.togglewave(wave, tmplist[wave][1])






    def button_press_event(self, event):

        if self.starttime is None:
            return
        self.downxcoord = event.xdata
        self.downx = event.x
        self.downbutton = event.button
        self.count = 0




    def motion_notify_event(self, event):
        # print(event.button, self.starttime, self.downbutton, self.downxcoord, event.xdata)
        self.count += 1
        self.currentxdata = event.xdata
        #print(self.currentxdata,"+" * 10)

        if self.starttime is None:
            return
        elif self.downxcoord is not None:
            if self.downbutton == 1 and self.timeline.currentTime()==0:
                self.state = 'busy'
                self.timeline.start()
            elif self.downbutton == 1:
                pass
            elif self.downbutton == 3:
                if self.rect is not None:
                    self.removeItem(self.rect)
                if self.downx < event.x:
                    self.rect = self.addRect(self.downx, 0, event.x - self.downx, self.height(), pen=QPen(Qt.red))
                else:
                    self.rect = self.addRect(event.x, 0, self.downx - event.x, self.height(), pen=QPen(Qt.red))

    def button_release_event(self, event):
        if self.starttime is None:
            return
        if event.button == 3:
            left = 225
            right = 1215
            if self.downxcoord < event.xdata:
                start = self.downxcoord
                end = event.xdata
            else:
                start = event.xdata
                end = self.downxcoord
            start = UTCDateTime(start)
            end = UTCDateTime(end)
            print((start,end,'================'))
            self.applytime(start, end)
        # self.downx = None
        self.downbutton = None
        self.removeItem(self.rect)
        self.rect = None
        self.downxcoord = None
        self.currentxdata = None
        #print(self.count,'count!!!!!!!!')
        self.count=0

    def scroll_event(self, event):

        delta = -event.step

        if self.wheelactive==False and event.xdata>= self.starttime and event.xdata<= self.endtime:
            self.wheelactive = True
            self.timescale(delta)
            self.wheelactive = False


    def exportmetadata(self, filename: tuple):
        wavelist = self.getlist()
        
        outfile =  open(filename[0]+'.txt','w')
        for network in wavelist:
            for station in wavelist[network]:
                for wave in wavelist[network][station]:
                    for w in wavelist[network][station][wave]:
                        outfile.write("%s\n\n" % w)

        outfile.close()





    def exportwaveform(self, filename: tuple):
        traces = []
        for wave in self.visibleWave:
            fill_value = 'last'
            waveform, wavename, starttime, endtime, gaps = self.data.readdisc(wave, self.starttime, self.endtime, resample=False, fill_value=fill_value)
            traces.append(waveform)

        stream = Stream(traces=traces)
        if 'MSEED' in filename[1]:
            stream.write(filename[0] + ".mseed", format='MSEED')
        elif 'txt' in filename[1]:
            stream.write(filename[0] + ".txt", format='TSPAIR')


    def gettimeboundary(self):
        return self.starttime, self.endtime



        return False