Exemplo n.º 1
0
def load_animation2(window: object,
                    property_name: bytes = b'windowOpacity') -> None:
    animation = QPropertyAnimation()
    animation.setTargetObject(window)  # 设置动画目标对象

    # 设置动画属性
    # 注意:字节类型
    # pos---位置动画---QPoint
    # size---大小动画---QSize
    # geometry----位置+大小动画----QRect
    # windowOpacity---窗口的透明度(0.0是透明的    1.0是不透明)---好像只适合顶层窗口
    animation.setPropertyName(property_name)

    # animation.setStartValue(QPoint(0, 0))  # 设置开始位置---按钮的左上角位置
    # animation.setEndValue(QPoint(300, 300))  # 设置结束位置
    # animation.setStartValue(QSize(0, 0))  # 设置开始大小
    # animation.setEndValue(QSize(300, 300))  # 设置结束大小
    # animation.setStartValue(QRect(0, 0,100,100))  # 设置开始位置和大小
    # animation.setEndValue(QRect(100,100,300, 300))  # 设置结束位置和大小

    # 参数1 0.0到1.0  0.0表示开始点,1.0表示结束点
    # 在动画的中间插入透明度0.2
    animation.setStartValue(0.2)  # 设置开始不透明
    animation.setKeyValueAt(0.2, 0.4)  # 在动画的某时间点插入一个值
    animation.setKeyValueAt(0.4, 0.6)
    animation.setKeyValueAt(1, 1)  # 在动画的结束点是不透明的
    # 0透明, 1不透明
    # animation.setEndValue(1)  # 设置结束透明度
    animation.setEndValue(TRANSPARENT)  # 设置结束透明度

    animation.setDirection(3000)  # 设置动画单次时长---单位毫秒

    animation.setEasingCurve(QEasingCurve.InQuad)  # 设置动画的节奏
    animation.start()  # 动画开始---非阻塞
Exemplo n.º 2
0
class FileManager(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_AI()
        self.ui.setupUi(self)
        self.show()
        self.Loop()


    def Loop(self):
        self.light = QPropertyAnimation(self.ui.HologramLight, b"geometry")
        self.light.setDirection(1)
        self.light.setLoopCount(2)
        self.light.setStartValue(QRect(0, 781, 481, 20))
        self.light.setEndValue(QRect(0, 340, 481, 461))
        self.light.start()
        self.light.stop()

        self.anim = QPropertyAnimation(self.ui.Blur2, b"geometry")
        self.anim.setDirection(1)
        self.anim.setLoopCount(100)
        self.anim.setStartValue(QRect(110, 240, 231, 231))
        self.anim.setEndValue(QRect(130, 240, 231, 231))
        self.anim.start()

        mixer.init()
        mixer.music.load('/root/PycharmProjects/AI/good.mp3')
        mixer.music.play()
Exemplo n.º 3
0
class SwitchPrivate(QObject):
    def __init__(self, q, parent=None, isOn=False):
        self.isOn = isOn
        QObject.__init__(self, parent=parent)
        self.mPointer = q
        if self.isOn:
            self.mPosition = 1.0
        else:
            self.mPosition = 0.0

        self.mGradient = QLinearGradient()
        self.mGradient.setSpread(QGradient.PadSpread)

        self.animation = QPropertyAnimation(self)
        self.animation.setTargetObject(self)
        self.animation.setPropertyName(b'position')
        self.animation.setStartValue(0.0)
        self.animation.setEndValue(1.0)
        self.animation.setDuration(200)
        self.animation.setEasingCurve(QEasingCurve.InOutExpo)

        self.animation.finished.connect(self.mPointer.update)

    @pyqtProperty(float)
    def position(self):
        return self.mPosition

    @position.setter
    def position(self, value):
        self.mPosition = value
        self.mPointer.update()

    def draw(self, painter):
        r = self.mPointer.rect()
        margin = r.height() / 10

        painter.setPen(Qt.NoPen)

        self.background_color = QColor(118, 118, 118)
        painter.setBrush(self.background_color)
        painter.drawRoundedRect(r, r.height() / 2, r.height() / 2)

        self.mGradient = QColor(35, 35, 35)

        painter.setBrush(self.mGradient)

        x = r.height() / 2.0 + self.mPosition * (r.width() - r.height())
        painter.drawEllipse(QPointF(x,
                                    r.height() / 2),
                            r.height() / 2 - margin,
                            r.height() / 2 - margin)

    @pyqtSlot(bool, name='animate')
    def animate(self, checked):
        self.animation.setDirection(QPropertyAnimation.Forward if checked else
                                    QPropertyAnimation.Backward)
        self.animation.start()
Exemplo n.º 4
0
class MoreActionsMenu(QMenu):
    """ 更多操作圆角菜单,flag用来指示动作的类型,flag=1有四个动作,flag=0有三个动作 """
    def __init__(self, parent=None, actionFlag=1):
        super().__init__(parent)
        self.actionFlag = actionFlag
        # 创建动画
        self.animation = QPropertyAnimation(self, b'geometry')
        # 实例化子窗口
        self.subMenu = SubMoreActionsMenu(parent=self,
                                          actionFlag=self.actionFlag)
        # 实例化布局
        self.all_h_layout = QHBoxLayout(self)
        self.initWidget()
        self.initLayout()
        self.hide()

    def initWidget(self):
        """ 初始化小部件 """
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint
                            | Qt.NoDropShadowWindowHint)
        # 初始化动画
        self.animation.setDirection(300)
        self.animation.setEasingCurve(QEasingCurve.OutQuad)
        # 引用子菜单的动作
        self.savePlayListAct = self.subMenu.savePlayListAct
        self.clearPlayListAct = self.subMenu.clearPlayListAct
        if self.actionFlag:
            self.showPlayListAct = self.subMenu.showPlayListAct
            self.fillScreenAct = self.subMenu.fillScreenAct
        else:
            self.showSongerCover = self.subMenu.showSongerCover

    def initLayout(self):
        """ 初始化布局 """
        self.all_h_layout.addWidget(self.subMenu, 0, Qt.AlignCenter)
        self.all_h_layout.setContentsMargins(30, 30, 30, 30)

    def show(self, pos):
        """ 重载show() """
        self.move(pos)
        super().show()
Exemplo n.º 5
0
class MNavigationDrawer(MFrame):
    def __init__(self, parent):
        super(MNavigationDrawer, self).__init__(parent)

        self._parent = parent

        self.show_animation = None
        self.appear_btn = None

        self.set_style()

    def set_style(self, width=200, height=None, background_color="#FFFFFF"):
        if not height:
            height = self._parent.height()
        self.setGeometry(-width, 0, width, height)

        hide_btn = QPushButton(parent=self)
        hide_btn.setGeometry(int(width / 2 - 18), int(height - 60), 36, 36)
        hide_btn.setStyleSheet("border-image:url('assests/back.svg')")
        hide_btn.clicked.connect(self.disappear)

        self.show_animation = QPropertyAnimation(self, b"pos")
        self.show_animation.setStartValue(QPoint(-width, 0))
        self.show_animation.setEndValue(QPoint(0, 0))
        self.show_animation.setDuration(200)
        self.show_animation.setDirection(QAbstractAnimation.Forward)
        self.setStyleSheet(
            "background-color:{};border-right:1px solid #e0e0e0".format(
                background_color))

    def drawerEvent(self, Qevent):
        if Qevent <= 0:
            return
        self.move(min(Qevent - self.width(), 0), 0)

    def appear(self):
        # 如果采用 btn trigger使得menu出现,可使用该方法
        if self.appear_btn is not None:
            self.appear_btn.hide()
        self.show_animation.setStartValue(self.pos())
        self.show_animation.setDirection(QAbstractAnimation.Forward)
        self.show_animation.start()

    def disappear(self):
        if self.appear_btn is not None:
            self.appear_btn.show()
        self.show_animation.setEndValue(self.pos())
        self.show_animation.setDirection(QAbstractAnimation.Backward)
        self.show_animation.start()
Exemplo n.º 6
0
class PopupWidget(QtWidgets.QWidget):

    #   enum PointerPosition
    LeftSide = 0
    RightSide = 1
    TopSide = 2
    BottomSide = 3
    NoPointer = 4

    LR_MARGIN = 10.0  #8.0 #/* left / right margin  */
    TB_MARGIN = 8.0  #5.5 #/* top / bottom margin */

    didHide = pyqtSignal()
    didShow = pyqtSignal()
    onClick = pyqtSignal()
    onRightClick = pyqtSignal()

    def __init__(self,
                 parent=None,
                 timeout=None,
                 delete_on_hide=True,
                 activation_hides=True,
                 dark_mode=False):
        ''' parent should be a window or None
            timeout is the amount of time, in milliseconds, to show the widget before it is auto-hidden. None is no timeout.
            delete_on_hide, if True, will auto-delete this widget after it is hidden due to the timeout or due to calling hide().
        '''
        super().__init__(parent)
        self.layout = QtWidgets.QGridLayout(self)
        if sys.platform != 'darwin':
            self.layout.setContentsMargins(20, 20, 20, 20)
        self.animation = QPropertyAnimation(self)
        self.final_opacity = 1.0
        self.popup_opacity = 1.0
        self.pointerPos = self.LeftSide
        self._timer = None
        self.activation_hides = activation_hides
        self.dark_mode = dark_mode and sys.platform.lower() != "darwin"

        #self.resize(200, 50)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_ShowWithoutActivating)

        self.animation.setTargetObject(self)
        self.animation.setPropertyName(b'popupOpacity')
        self.animation.setDuration(200)

        self.setLayout(self.layout)

        if parent: parent.installEventFilter(self)

        self.timeout = timeout
        self.delete_on_hide = delete_on_hide

    def getPointerPosition(self):
        return self.pointerPos

    def setPointerPosition(self, r):
        self.pointerPos = r
        self.update()

    @pyqtProperty(
        float
    )  # Property so that Qt animations work. You may set the actual attrbute directly and ingore this in client code
    def popupOpacity(self):
        return self.popup_opacity

    @popupOpacity.setter
    def popupOpacity(self, value):
        self.popup_opacity = value
        self.setWindowOpacity(value)

    @pyqtProperty(
        float
    )  # Property so that Qt animations work. You may set the actual attrbute directly and ingore this in client code
    def finalOpacity(self):
        return self.final_opacity

    @finalOpacity.setter
    def finalOpacity(self, value):
        self.final_opacity = value

    def paintEvent(self, e):
        #// Draw the popup here
        #// You can always pick an image and use drawPixmap to
        #// draw it in order to make things simpler

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setClipRegion(e.region())
        painter.fillRect(e.rect(), QColor(0, 0, 0, 0))

        #// Prepare the popup dimensions
        roundedRectDimensions = QRectF()
        roundedRectDimensions.setX(self.rect().x() + self.LR_MARGIN)
        roundedRectDimensions.setY(self.rect().y() + self.TB_MARGIN)
        roundedRectDimensions.setWidth(self.rect().width() -
                                       self.LR_MARGIN * 2.0)
        roundedRectDimensions.setHeight(self.rect().height() -
                                        self.TB_MARGIN * 2.0)

        pal = QPalette(self.palette())

        painter.setBrush(
            QBrush(
                pal.color(
                    QPalette.Window if self.dark_mode else QPalette.Mid)))

        pen = QPen()
        pen.setColor(
            pal.color(QPalette.Light if self.dark_mode else QPalette.Button))
        pen.setWidth(3)
        painter.setPen(pen)

        #// Draw the popup body
        painter.drawRoundedRect(roundedRectDimensions, self.LR_MARGIN * 2.0,
                                self.TB_MARGIN * 2.0)

        painter.setPen(Qt.NoPen)
        painter.setBrush(
            QBrush(
                pal.color(
                    QPalette.BrightText if self.dark_mode else QPalette.Dark)))
        #// Draw the popup pointer based on relPos
        self.drawPopupPointer(painter)

        e.accept()

    def drawPopupPointer(self, p):
        r = QRectF(self.rect())

        if self.pointerPos == self.LeftSide:
            PPIX_X = self.LR_MARGIN
            PPIX_Y = PPIX_X * 2.0
            points = [
                QPointF(r.x() + PPIX_X,
                        r.height() / 2.0 - PPIX_Y / 2.0),
                QPointF(r.x() + PPIX_X,
                        r.height() / 2.0 + PPIX_Y / 2.0),
                QPointF(r.x(),
                        r.height() / 2.0),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.RightSide:
            PPIX_X = self.LR_MARGIN
            PPIX_Y = PPIX_X * 2.0
            points = [
                QPointF(r.right() - PPIX_X,
                        r.height() / 2.0 - PPIX_Y / 2.0),
                QPointF(r.right() - PPIX_X,
                        r.height() / 2.0 + PPIX_Y / 2.0),
                QPointF(r.right(),
                        r.height() / 2.0),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.TopSide:
            PPIX_Y = self.TB_MARGIN
            PPIX_X = PPIX_Y * 2.0
            points = [
                QPointF(r.x() + r.width() / 2.0 - PPIX_X / 2.0,
                        r.top() + PPIX_Y),
                QPointF(r.x() + r.width() / 2.0 + PPIX_X / 2.0,
                        r.top() + PPIX_Y),
                QPointF(r.x() + r.width() / 2.0, r.top()),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.BottomSide:
            PPIX_Y = self.TB_MARGIN
            PPIX_X = PPIX_Y * 2.0
            points = [
                QPointF(r.x() + r.width() / 2.0 - PPIX_X / 2.0,
                        r.bottom() - PPIX_Y),
                QPointF(r.x() + r.width() / 2.0 + PPIX_X / 2.0,
                        r.bottom() - PPIX_Y),
                QPointF(r.x() + r.width() / 2.0, r.bottom()),
            ]

            p.drawPolygon(*points)

    def showRelativeTo(self, w):
        s = self.size()
        self.moveRelativeTo(w)
        self.hide()
        self.show()
        if self.pointerPos == self.NoPointer:
            self.raise_()
        if s != self.size():
            # show caused widget resize.. recenter
            self.moveRelativeTo(w)

    def moveRelativeTo(self, w):
        if not w:
            print(
                "INTERNAL ERROR: PopupWidget::showRelativeTo got passed a NULL widget pointer! Ignoring.. FIXME!"
            )
            return

        p = w.mapToGlobal(QPoint(0, 0))
        if self.pointerPos == self.LeftSide:
            p.setX(p.x() + w.width())
            p.setY(p.y() - self.height() // 2 + w.height() // 2)
        elif self.pointerPos == self.RightSide:
            p.setX(p.x() - self.width())
            p.setY(p.y() - self.height() // 2 + w.height() // 2)
        elif self.pointerPos == self.BottomSide:
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() - self.height())
        elif self.pointerPos == self.TopSide:
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() + w.height())
        else:
            #// just center it on the widget
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() + w.height() // 2 - self.height() // 2)
            if self.isVisible():
                self.raise_()

        self.move(p)

    def _killTimer(self):
        if self._timer:
            self._timer.stop()
            self._timer.deleteLater()
            self._timer = None

    def _startTimer(self, target):
        self._killTimer()
        self._timer = QTimer(self)
        self._timer.setSingleShot(True)

        def timeout():
            self._killTimer()
            target()

        self._timer.timeout.connect(timeout)
        self._timer.start(int(self.timeout))

    def showEvent(self, e):
        super().showEvent(e)
        if not e.isAccepted():
            return
        if self.animation.state() == QAbstractAnimation.Running:
            return
        self.setWindowOpacity(0.0)

        self.animation.setStartValue(0.0)
        self.animation.setEndValue(self.final_opacity)

        self.didShow.emit()
        self._cleanUp()
        self.animation.setDirection(QAbstractAnimation.Forward)
        self.animation.start()

        if isinstance(self.timeout, (float, int)) and self.timeout > 0:

            def autoHide():
                self._cleanUp()
                self._startTimer(self.hideAnimated)

            self.animation.finished.connect(autoHide)

    def hideEvent(self, e):
        super().hideEvent(e)
        if e.isAccepted():
            self._cleanUp()
            if self.delete_on_hide:
                self.setParent(None)
                self.deleteLater()

    def _disconnectFinished(self):
        try:
            self.animation.finished.disconnect()
        except:
            pass

    def hideAnimated(self):
        if self.animation.state() == QAbstractAnimation.Running:
            return
        self._cleanUp()
        self.animation.setDirection(QAbstractAnimation.Backward)
        self.animation.start()

        def doHide():
            self._cleanUp()
            self.hide()
            self.didHide.emit()

        self.animation.finished.connect(doHide)

    def eventFilter(self, obj, e):
        evts = (QEvent.Move, QEvent.Resize, QEvent.Close, QEvent.Hide,
                QEvent.Show)
        if self.activation_hides:
            evts = (*evts, QEvent.WindowStateChange, QEvent.WindowDeactivate)
        if e.type() in evts:
            # if the parent window is moved or otherwise touched, make this popup go away
            self.hideAnimated()
        return False

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.onClick.emit()
            e.accept()
        elif e.button() == Qt.RightButton:
            self.onRightClick.emit()
            e.accept()

    def _cleanUp(self):
        ''' Forces animation and timer to stop. This is essential to force
        the object into a known consistent state ready for deletion, restart
        of animations, etc. '''
        self._disconnectFinished()
        self._killTimer()
        self.animation.stop()
Exemplo n.º 7
0
class StackedWidgetFadeInAnimator(AbstractAnimator):
    m_decorator: StackedWidgetFadeInDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _container, _fadeWidget):
        super(StackedWidgetFadeInAnimator, self).__init__(_container)

        self.m_decorator = StackedWidgetFadeInDecorator(_container, _fadeWidget=_fadeWidget)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"opacity")

        _container.installEventFilter(self)

        self.m_animation.setDuration(200)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()

            if self.m_animation.direction() == QPropertyAnimation.Forward:
                _container.setCurrentWidget(_fadeWidget)
            self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.fadeIn()

    def fadeIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.m_decorator.grabContainer()
        self.m_decorator.grabFadeWidget()

        startOpacity = 0
        finalOpacity = 1

        self.m_decorator.setOpacity(startOpacity)
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InQuad)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startOpacity)
            self.m_animation.setEndValue(finalOpacity)

            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.fadeWidget() and _event.type() == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.grabContainer()
            self.m_decorator.grabFadeWidget()

        return QWidget.eventFilter(self, _object, _event)

    def fadeWidget(self):
        return self.parent()
Exemplo n.º 8
0
class MainWindow(QMainWindow):
    siteLoaded = pyqtSignal(object)

    def __init__(self):
        QMainWindow.__init__(self)
        self.site = None
        self.editor = ""
        self.install_directory = os.getcwd()
        self.content_after_animation = ""
        self.default_path = ""
        self.method_after_animation = ""

        Generator.install_directory = self.install_directory

        self.initUndoRedo()
        self.initGui()
        self.readSettings()
        self.loadPlugins()

        if self.default_path:
            if self.loadProject(os.path.join(self.default_path, "Site.qml")):
                gen = Generator()
                gen.generateSite(self, self.site)

        self.dashboard.setExpanded(True)
        self.showDashboard()
        self.statusBar().showMessage(
            QCoreApplication.translate("MainWindow", "Ready"))

    def actualThemeChanged(self, themename):
        self.theme_settings_button.setVisible(False)
        for name in Plugins.themePluginNames():
            tei = Plugins.getThemePlugin(name)
            if tei:
                if tei.theme_name == themename:
                    self.theme_settings_button.setVisible(True)
                    break

    def loadProject(self, filename):
        self.default_path = filename[0:-9]  # - /Site.qml
        if self.reloadProject(filename):
            # create temp dir for undo redo
            tempPath = self.site.source_path[self.site.source_path.rfind("/") +
                                             1:]
            temp = QDir(os.path.join(QDir.tempPath(), "FlatSiteBuilder"))
            temp.mkdir(tempPath)
            temp.cd(tempPath)
            temp.mkdir("pages")
            temp.mkdir("posts")

            # in case these subfolders were empty and not published to github
            dir = QDir(self.site.source_path)
            dir.mkdir("pages")
            dir.mkdir("posts")
            dir.mkdir("assets")
            dir.cd("assets")
            dir.mkdir("images")
            return True
        else:
            return False

    def initUndoRedo(self):
        self.undoStack = QUndoStack()
        temp = QDir(os.path.join(QDir.tempPath(), "FlatSiteBuilder"))
        if temp.exists():
            temp.removeRecursively()
        temp.setPath(QDir.tempPath())
        temp.mkdir("FlatSiteBuilder")

    def initGui(self):
        self.installEventFilter(self)
        self.dashboard = Expander(
            QCoreApplication.translate("MainWindow", "Dashboard"),
            ":/images/dashboard_normal.png", ":/images/dashboard_hover.png",
            ":/images/dashboard_selected.png")
        self.content = Expander(
            QCoreApplication.translate("MainWindow",
                                       "Content"), ":/images/pages_normal.png",
            ":/images/pages_hover.png", ":/images/pages_selected.png")
        self.appearance = Expander(
            QCoreApplication.translate("MainWindow", "Appearance"),
            ":/images/appearance_normal.png", ":/images/appearance_hover.png",
            ":/images/appearance_selected.png")
        self.settings = Expander(
            QCoreApplication.translate("MainWindow", "Settings"),
            ":/images/settings_normal.png", ":/images/settings_hover.png",
            ":/images/settings_selected.png")

        self.setWindowTitle(QCoreApplication.applicationName() + " " +
                            QCoreApplication.applicationVersion())
        vbox = QVBoxLayout()
        vbox.addWidget(self.dashboard)
        vbox.addWidget(self.content)
        vbox.addWidget(self.appearance)
        vbox.addWidget(self.settings)
        vbox.addStretch()

        content_box = QVBoxLayout()
        pages_button = HyperLink(
            QCoreApplication.translate("MainWindow", "Pages"))
        posts_button = HyperLink(
            QCoreApplication.translate("MainWindow", "Posts"))
        content_box.addWidget(pages_button)
        content_box.addWidget(posts_button)
        self.content.addLayout(content_box)

        app_box = QVBoxLayout()
        themes_button = HyperLink(
            QCoreApplication.translate("MainWindow", "Themes"))
        menus_button = HyperLink(
            QCoreApplication.translate("MainWindow", "Menus"))
        self.theme_settings_button = HyperLink(
            QCoreApplication.translate("MainWindow", "Theme Settings"))
        self.theme_settings_button.setVisible(False)
        app_box.addWidget(menus_button)
        app_box.addWidget(themes_button)
        app_box.addWidget(self.theme_settings_button)

        self.appearance.addLayout(app_box)

        scroll_content = QWidget()
        scroll_content.setLayout(vbox)
        scroll = QScrollArea()
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setWidget(scroll_content)
        scroll.setWidgetResizable(True)
        scroll.setMaximumWidth(200)
        scroll.setMinimumWidth(200)

        self.navigationdock = QDockWidget(
            QCoreApplication.translate("MainWindow", "Navigation"), self)
        self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea
                                            | Qt.RightDockWidgetArea)
        self.navigationdock.setWidget(scroll)
        self.navigationdock.setObjectName("Navigation")

        self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock)

        self.showDock = FlatButton(":/images/edit_normal.png",
                                   ":/images/edit_hover.png")
        self.showDock.setToolTip(
            QCoreApplication.translate("MainWindow", "Show Navigation"))
        self.statusBar().addPermanentWidget(self.showDock)

        self.dashboard.expanded.connect(self.dashboardExpanded)
        self.dashboard.clicked.connect(self.showDashboard)
        self.content.expanded.connect(self.contentExpanded)
        self.content.clicked.connect(self.showPages)
        self.appearance.expanded.connect(self.appearanceExpanded)
        self.appearance.clicked.connect(self.showMenus)
        self.settings.expanded.connect(self.settingsExpanded)
        self.settings.clicked.connect(self.showSettings)
        menus_button.clicked.connect(self.showMenus)
        pages_button.clicked.connect(self.showPages)
        posts_button.clicked.connect(self.showPosts)
        themes_button.clicked.connect(self.showThemes)
        self.theme_settings_button.clicked.connect(self.showThemesSettings)
        self.showDock.clicked.connect(self.showMenu)
        self.navigationdock.visibilityChanged.connect(
            self.dockVisibilityChanged)

    def showDashboard(self):
        if self.editor:
            self.method_after_animation = "showDashboard"
            self.editor.closeEditor()
            return

        db = Dashboard(self.site, self.default_path)
        db.loadSite.connect(self.loadProject)
        db.previewSite.connect(self.previewSite)
        db.publishSite.connect(self.publishSite)
        db.createSite.connect(self.createSite)
        db.buildSite.connect(self.buildSite)

        self.siteLoaded.connect(db.siteLoaded)
        self.setCentralWidget(db)

    def setCentralWidget(self, widget):
        # do not delete plugin editors
        old_widget = self.takeCentralWidget()
        if not isinstance(old_widget, PublisherInterface) and not isinstance(
                old_widget, ThemeEditorInterface):
            del old_widget
        super().setCentralWidget(widget)
        widget.show()

    def closeEvent(self, event):
        self.writeSettings()
        event.accept()

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("state", self.saveState())
        if self.site:
            settings.setValue("lastSite", self.site.source_path)

    def readSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        geometry = settings.value("geometry", QByteArray())
        if geometry.isEmpty():
            availableGeometry = QApplication.desktop().availableGeometry(self)
            self.resize(int(availableGeometry.width() / 2),
                        int(availableGeometry.height() / 2))
            self.move(int(((availableGeometry.width() - self.width()) / 2)),
                      int((availableGeometry.height() - self.height()) / 2))
        else:
            self.restoreGeometry(geometry)
            self.restoreState(settings.value("state"))
        self.default_path = settings.value("lastSite")

    def reloadProject(self, filename):
        sys.stdout.flush()
        engine = QQmlEngine()
        self.site_component = component = QQmlComponent(engine)
        self.site_component.loadUrl(QUrl.fromLocalFile(filename))
        self.site = self.site_component.create()
        if self.site is not None:
            self.site.setFilename(filename)
            self.site.setWindow(self)
        else:
            for error in self.site_component.errors():
                print(error.toString())
            return False
        if self.site.output == "":
            self.site.output = "docs"
        self.site.loadMenus()
        self.site.loadPages()
        self.site.loadPosts()

        self.theme_settings_button.setVisible(False)
        Plugins.setActualThemeEditorPlugin("")
        for key in Plugins.themePluginNames():
            tei = Plugins.getThemePlugin(key)
            if tei:
                if tei.theme_name == self.site.theme:
                    Plugins.setActualThemeEditorPlugin(tei.class_name)
                    self.theme_settings_button.setVisible(True)
                    break

        #if not self.site.publisher:
        #    if len(Plugins.publishPluginNames()) > 0:
        #        self.site.publisher = Plugins.publishPluginNames[0]

        Plugins.setActualPublishPlugin(self.site.publisher)
        self.siteLoaded.emit(self.site)
        return True

    def dashboardExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.appearance.setExpanded(False)
            self.settings.setExpanded(False)

    def contentExpanded(self, value):
        if value:
            self.dashboard.setExpanded(False)
            self.appearance.setExpanded(False)
            self.settings.setExpanded(False)

    def appearanceExpanded(self, value):
        if value:
            self.dashboard.setExpanded(False)
            self.content.setExpanded(False)
            self.settings.setExpanded(False)

    def settingsExpanded(self, value):
        if value:
            self.dashboard.setExpanded(False)
            self.content.setExpanded(False)
            self.appearance.setExpanded(False)

    def showMenus(self):
        if self.editor:
            self.method_after_animation = "showMenus"
            self.editor.closeEditor()
            return

        edit = MenuList(self, self.site)
        edit.editContent.connect(self.editMenu)
        self.setCentralWidget(edit)

    def showPages(self):
        if self.editor:
            self.method_after_animation = "showPages"
            self.editor.closeEditor()
            return

        list = ContentList(self.site, ContentType.PAGE)
        list.editContent.connect(self.editContent)
        self.setCentralWidget(list)

    def showPosts(self):
        if self.editor:
            self.method_after_animation = "showPosts"
            self.editor.closeEditor()
            return

        list = ContentList(self.site, ContentType.POST)
        list.editContent.connect(self.editContent)
        self.setCentralWidget(list)

    def showThemes(self):
        if self.editor:
            self.method_after_animation = "showThemes"
            self.editor.closeEditor()
            return

        tc = ThemeChooser(self, self.site)
        self.setCentralWidget(tc)

    def showThemesSettings(self):
        tei = Plugins.getThemePlugin(Plugins.actualThemeEditorPlugin())
        if tei:
            if self.editor:
                self.method_after_animation = "showThemesSettings"
                self.editor.closeEditor()
                return

            path = self.site.source_path
            tei.setWindow(self)
            tei.setSourcePath(path)
            self.setCentralWidget(tei)
        else:
            self.statusBar().showMessage(
                QCoreApplication.translate("MainWindow",
                                           "Unable to load plugin") + " " +
                Plugins.actualThemeEditorPlugin())

    def showSettings(self):
        if self.editor:
            self.method_after_animation = "showSettings"
            self.editor.closeEditor()
            return

        sse = SiteSettingsEditor(self, self.site)
        self.setCentralWidget(sse)

    def showMenu(self):
        self.navigationdock.setVisible(True)

    def dockVisibilityChanged(self, visible):
        self.showDock.setVisible(not visible)

    def previewSite(self, content=None):
        if self.editor and content:
            self.content_after_animation = content
            self.editor.closeEditor()
            return

        dir = os.path.join(self.default_path, self.site.output)

        if not content:
            if len(self.site.pages) > 0:
                content = self.site.pages[0]
                for c in self.site.pages:
                    if c.url == "index.html":
                        content = c
                        break
            elif len(self.site.posts) > 0:
                content = self.site.posts()[0]

        if content:
            file = content.url
            self.webView = QWebEngineView()
            self.webView.loadFinished.connect(self.webViewLoadFinished)
            url = pathlib.Path(os.path.join(dir, file)).as_uri()
            self.webView.setUrl(QUrl(url))
            self.setCursor(Qt.WaitCursor)
        else:
            self.statusBar().showMessage(
                QCoreApplication.translate(
                    "MainWindow", "Site has no pages or posts to preview."))

    def webViewLoadFinished(self, success):
        if success:
            self.setCentralWidget(self.webView)
            self.webView.loadFinished.disconnect(self.webViewLoadFinished)
        else:
            QMessageBox.warning(
                self, "FlatSiteBuilder",
                QCoreApplication.translate("MainWindow",
                                           "Unable to open webpage."))
        self.setCursor(Qt.ArrowCursor)

    def publishSite(self):
        pluginName = Plugins.actualPublishPlugin()
        pi = Plugins.getPublishPlugin(pluginName)
        if pi:
            self.setCentralWidget(pi)
            pi.setSitePath(self.install_directory, self.site.source_path)
        else:
            QMessageBox.warning(
                self, "FlatSiteBuilder",
                QCoreApplication.translate(
                    "MainWindow", "Website has no publish plugin configured."))

    def createSite(self):
        wiz = SiteWizard(self.install_directory, parent=self)
        wiz.loadSite.connect(self.loadProject)
        wiz.buildSite.connect(self.buildSite)
        wiz.show()

    def buildSite(self):
        self.site.loadMenus()
        self.site.loadPages()
        self.site.loadPosts()
        if len(self.site.pages) == 0 and len(self.site.posts) == 0:
            self.statusBar().showMessage(
                QCoreApplication.translate(
                    "MainWindow", "Site has no pages or posts to build."))
        else:
            gen = Generator()
            gen.generateSite(self, self.site)
            self.statusBar().showMessage(
                self.site.title + " " +
                QCoreApplication.translate("MainWindow", "has been generated"))

    def editMenu(self, item):
        menu = item.data(Qt.UserRole)
        me = MenuEditor(self, menu, self.site)
        self.editor = me
        list = self.centralWidget()
        if list:
            list.registerMenuEditor(me)
            list.editedItemChanged.connect(self.editedItemChanged)

        self.editor.closes.connect(self.editorClosed)
        self.editor.contentChanged.connect(self.menuChanged)
        self.animate(item)

    def editContent(self, item):
        content = item.data(Qt.UserRole)
        self.editor = ContentEditor(self, self.site, content)
        self.siteLoaded.connect(self.editor.siteLoaded)
        self.editor.closes.connect(self.editorClosed)
        self.editor.preview.connect(self.previewSite)
        self.animate(item)

    def animate(self, item):
        panel = self.centralWidget()
        self.list = item.tableWidget()
        self.row = item.row()

        # create a cell widget to get the right position in the table
        self.cellWidget = QWidget()
        self.cellWidget.setMaximumHeight(0)
        self.list.setCellWidget(self.row, 1, self.cellWidget)
        pos = self.cellWidget.mapTo(panel, QPoint(0, 0))

        self.editor.setParent(panel)
        self.editor.move(pos)
        self.editor.resize(self.cellWidget.size())
        self.editor.show()

        self.animation = QPropertyAnimation(self.editor,
                                            "geometry".encode("utf-8"))
        self.animation.setDuration(300)
        self.animation.setStartValue(
            QRect(pos.x(), pos.y(),
                  self.cellWidget.size().width(),
                  self.cellWidget.size().height()))
        self.animation.setEndValue(
            QRect(0, 0,
                  panel.size().width(),
                  panel.size().height()))
        self.animation.start()

    def eventFilter(self, watched, event):
        if watched == self and event.type() == QEvent.Resize and self.editor:
            w = self.centralWidget()
            if w:
                self.editor.resize(w.size())
        return False

    def editorClosed(self):
        pos = self.cellWidget.mapTo(self.centralWidget(), QPoint(0, 0))
        # correct end values in case of resizing the window
        self.animation.setStartValue(
            QRect(pos.x(), pos.y(),
                  self.cellWidget.size().width(),
                  self.cellWidget.size().height()))
        self.animation.finished.connect(self.animationFineshedZoomOut)
        self.animation.setDirection(QAbstractAnimation.Backward)
        self.animation.start()

    def animationFineshedZoomOut(self):
        self.list.removeCellWidget(self.row, 1)
        del self.animation

        # in the case self.editor was a MenuEditor, we have to unregister it in the MenuList
        # should be refactored some day :-)
        list = self.centralWidget()
        if list is MenuEditor:
            list.unregisterMenuEditor()

        if isinstance(list, ContentList):
            list.reload()

        del self.editor
        self.editor = None

        if self.method_after_animation == "showDashboard":
            self.showDashboard()
            self.method_after_animation = ""
        elif self.method_after_animation == "showSettings":
            self.showSettings()
        elif self.method_after_animation == "showThemesSettings":
            self.showThemesSettings()
        elif self.method_after_animation == "showThemes":
            self.showThemes()
        elif self.method_after_animation == "showMenus":
            self.showMenus()
        elif self.method_after_animation == "showPages":
            self.showPages()
        elif self.method_after_animation == "showPosts":
            self.showPosts()

        if self.content_after_animation:
            self.previewSite(self.content_after_animation)
            self.content_after_animation = None

    def contentChanged(self, content):
        self.list.item(self.row, 1).setText(content.title())
        self.list.item(self.row, 2).setText(content.source())
        self.list.item(self.row, 3).setText(content.layout())
        self.list.item(self.row, 4).setText(content.author())
        self.list.item(self.row,
                       5).setText(content.date().toString("dd.MM.yyyy"))

    def menuChanged(self, menu):
        self.list.item(self.row, 1).setText(menu.name())

    def editedItemChanged(self, item):
        # this will happen, if the MenuList.reloadMenu() has been called by the undo.command
        self.list = item.tableWidget()
        self.row = item.row()
        self.cellWidget = QWidget()
        self.list.setCellWidget(self.row, 1, self.cellWidget)

    def loadPlugins(self):
        # check if we are running in a frozen environment (pyinstaller --onefile)
        if getattr(sys, "frozen", False):
            bundle_dir = sys._MEIPASS
            # if we are running in a onefile environment, then copy all plugin to /tmp/...
            if bundle_dir != os.getcwd():
                os.mkdir(os.path.join(bundle_dir, "plugins"))
                for root, dirs, files in os.walk(
                        os.path.join(os.getcwd(), "plugins")):
                    for file in files:
                        shutil.copy(os.path.join(root, file),
                                    os.path.join(bundle_dir, "plugins"))
                        print("copy", file)
                    break  # do not copy __pycache__
        else:
            bundle_dir = os.getcwd()

        plugins_dir = os.path.join(bundle_dir, "plugins")
        for root, dirs, files in os.walk(plugins_dir):
            for file in files:
                modulename, ext = os.path.splitext(file)
                if ext == ".py":
                    module = import_module("plugins." + modulename)
                    for name, klass in inspect.getmembers(
                            module, inspect.isclass):
                        if klass.__module__ == "plugins." + modulename:
                            instance = klass()
                            if isinstance(instance, ElementEditorInterface):
                                Plugins.addElementPlugin(name, instance)
                                instance.registerContenType()
                            elif isinstance(instance, ThemeEditorInterface):
                                Plugins.addThemePlugin(name, instance)
                            elif isinstance(instance, PublisherInterface):
                                Plugins.addPublishPlugin(name, instance)
                            elif isinstance(instance, GeneratorInterface):
                                Plugins.addGeneratorPlugin(name, instance)
            break  # not to list __pycache__
Exemplo n.º 9
0
class CircleFillAnimator(AbstractAnimator):
    m_decorator: CircleFillDecorator
    m_animation: QPropertyAnimation
    m_hideAfterFinish = True

    def __init__(self, _widgetForFill):
        super(CircleFillAnimator, self).__init__(_widgetForFill)

        self.m_decorator = CircleFillDecorator(_widgetForFill)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_radius")

        _widgetForFill.installEventFilter(self)

        self.m_animation.setDuration(500)

        self.m_decorator.setAttribute(Qt.WA_TransparentForMouseEvents)
        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.m_hideAfterFinish:
                self.hideDecorator()

        self.m_animation.finished.connect(finished)

    def setStartPoint(self, _point):
        self.m_decorator.setStartPoint(_point)

    def setFillColor(self, _color):
        self.m_decorator.setFillColor(_color)

    def setHideAfterFinish(self, _hide):
        self.m_hideAfterFinish = _hide

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.fillIn()

    def fillIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        startRadius = 0
        finalRadius = math.sqrt(
            self.widgetForFill().height() * self.widgetForFill().height() +
            self.widgetForFill().width() * self.widgetForFill().width())

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startRadius)
            self.m_animation.setEndValue(finalRadius)
            self.m_animation.start()

    def animateBackward(self):
        self.fillOut()

    def fillOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        startRadius = math.sqrt(
            self.widgetForFill().height() * self.widgetForFill().height() +
            self.widgetForFill().width() * self.widgetForFill().width())
        finalRadius = 0

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startRadius)
            self.m_animation.setEndValue(finalRadius)
            self.m_animation.start()

    def hideDecorator(self):
        hideEffect = self.m_decorator.graphicsEffect()
        if hideEffect == None:
            hideEffect = QGraphicsOpacityEffect(self.m_decorator)
            self.m_decorator.setGraphicsEffect(hideEffect)
        hideEffect.setOpacity(1)

        hideAnimation = QPropertyAnimation(hideEffect, b"opacity",
                                           self.m_decorator)
        hideAnimation.setDuration(400)
        hideAnimation.setStartValue(1)
        hideAnimation.setEndValue(0)

        def finished():
            self.m_decorator.hide()
            hideEffect.setOpacity(1)

        hideAnimation.finished.connect(finished)

        hideAnimation.start(QAbstractAnimation.DeleteWhenStopped)

    def widgetForFill(self):
        return self.parent()
Exemplo n.º 10
0
class AnimBox(QGraphicsObject):
    """A Box that draws an outline when hover over.

    Attributes
    ----------
    hoverEnter: pyqtSignal
        Emitted when the mouse hover into the box
    hoverExit: pyqtSignal
        Emitted when the mouse hover out of the box
    """
    hoverEnter = pyqtSignal()
    hoverExit = pyqtSignal()

    def __init__(self, x, y, width, height, parent=None):
        """Prepares the box and animation

        Parameters
        ----------
        x: float
            x position of the top-left corner of the box
        y: float
            y position of the top-left corner of the box
        width: float
            Width of the box
        height: float
            Height of the box
        parent: object
            Passed into QGraphicsObject init method
        """
        super().__init__(parent=parent)
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.circumference = 2 * (width + height)

        self.default_pen = QPen()
        self.default_pen.setColor(Qt.white)
        self.outline_pen = QPen()
        self.outline_pen.setColor(Qt.white)
        self.outline_pen.setWidth(5)

        self.detected = False  # Whether the mouse hover over the box
        self.btn_rect = QRectF(self.x, self.y, self.width, self.height)

        self.left = QLineF()
        self.down = QLineF()
        self.right = QLineF()
        self.up = QLineF()

        self.line_order = [self.up, self.right, self.down, self.left]

        self.set_freeze(False)

        self.length = 0
        self.anim = QPropertyAnimation(self, b'length')
        self.anim.setStartValue(0)
        for t in range(1, 10):
            self.anim.setKeyValueAt(t / 10, self.logistic_func(t / 10))
        self.anim.setEndValue(self.circumference)

    def set_freeze(self, freeze):
        """Set whether the box should accept the mouse events

        Parameters
        ----------
        freeze: bool
            True to stop the box from accepting mouse inputs, False otherwise
        """
        if freeze:
            self.setAcceptedMouseButtons(Qt.NoButton)
            self.setAcceptHoverEvents(False)
        else:
            self.setAcceptedMouseButtons(Qt.LeftButton)
            self.setAcceptHoverEvents(True)

    def toggle_anim(self, toggling):
        """Toggle the highlight animation to be play forward or backward

        Parameters
        ----------
        toggling: bool
            True for forward, False for backwards
        """
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()

    def logistic_func(self, x):
        """The logistic function that determines the animation motion

        Parameters
        ----------
        x: list or numpy array
            Values to be feed into the function

        Returns
        -------
        list or numpy array
            Values of the logistic function corresponding to the input range

        """
        return self.circumference / (1 + math.exp(-(x - 0.5) * 18))

    def boundingRect(self):
        """Reimplemented from QGraphicsObject.
        """
        return QRectF(self.x - 5, self.y - 5, self.width + 10,
                      self.height + 10)

    def paint(self, painter, style, widget=None):
        """Reimplemented from QGraphicsObject. Draws the Box and the highlights.
        """
        painter.setPen(self.outline_pen)
        for line in self.line_order:
            if line.length() > 1:
                painter.drawLine(line)
        painter.setPen(self.default_pen)
        painter.drawRect(self.btn_rect)

    @pyqtProperty(float)
    def length(self):
        """float: The length of the highlight to be drawn.
        When set, the length of the outlines are determined
        """
        return self._length

    @length.setter
    def length(self, value):
        self._length = value
        remaining_length = value
        if remaining_length >= 2 * self.width + self.height:
            length_to_draw = remaining_length - (2 * self.width + self.height)
            remaining_length -= length_to_draw
        else:
            length_to_draw = 0

        self.line_order[3].setLine(self.x, self.y + self.height, self.x,
                                   self.y + self.height - length_to_draw)
        if remaining_length >= self.width + self.height:
            length_to_draw = remaining_length - (self.width + self.height)
            remaining_length -= length_to_draw
        else:
            length_to_draw = 0
        self.line_order[2].setLine(self.x + self.width, self.y + self.height,
                                   self.x + self.width - length_to_draw,
                                   self.y + self.height)

        if remaining_length >= self.width:
            length_to_draw = remaining_length - self.width
            remaining_length -= length_to_draw
        else:
            length_to_draw = 0

        self.line_order[1].setLine(self.x + self.width, self.y,
                                   self.x + self.width,
                                   self.y + length_to_draw)
        self.line_order[0].setLine(self.x, self.y, self.x + remaining_length,
                                   self.y)
        self.update()

    def hoverEnterEvent(self, event):
        """Reimplemented hoverEnterEvent. Detect the mouse and toggle the animation
        """
        if ~self.detected:
            self.hoverEnter.emit()
            self.detected = True
            self.toggle_anim(True)
        super().hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        """Reimplemented hoverLeaveEvent. Detect the mouse leaving and reverse the animation
        """
        if self.detected:
            self.hoverExit.emit()
            self.detected = False
            self.toggle_anim(False)
        super().hoverLeaveEvent(event)
Exemplo n.º 11
0
class ScreensharingToolbox(base_class, ui_class):
    exposedPixels = 3

    def __init__(self, parent):
        super(ScreensharingToolbox, self).__init__(parent)
        with Resources.directory:
            self.setupUi()
        parent.installEventFilter(self)
        self.animation = QPropertyAnimation(self, 'pos')
        self.animation.setDuration(250)
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.setEasingCurve(QEasingCurve.Linear)  # or OutCirc with 300ms
        self.retract_timer = QTimer(self)
        self.retract_timer.setInterval(3000)
        self.retract_timer.setSingleShot(True)
        self.retract_timer.timeout.connect(self.retract)
        self.resize(self.size().expandedTo(self.toolbox_layout.minimumSize()))

    def setupUi(self):
        super(ScreensharingToolbox, self).setupUi(self)

        # fix the SVG icons, as the generated code loads them as pixmaps, losing their ability to scale -Dan
        scale_icon = QIcon()
        scale_icon.addFile(Resources.get('icons/scale.svg'), mode=QIcon.Normal, state=QIcon.Off)
        viewonly_icon = QIcon()
        viewonly_icon.addFile(Resources.get('icons/viewonly.svg'), mode=QIcon.Normal, state=QIcon.Off)
        screenshot_icon = QIcon()
        screenshot_icon.addFile(Resources.get('icons/screenshot.svg'), mode=QIcon.Normal, state=QIcon.Off)
        fullscreen_icon = QIcon()
        fullscreen_icon.addFile(Resources.get('icons/fullscreen.svg'), mode=QIcon.Normal, state=QIcon.Off)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Normal, state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Active, state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Disabled, state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Selected, state=QIcon.On)
        minimize_icon = QIcon()
        minimize_icon.addFile(Resources.get('icons/minimize.svg'), mode=QIcon.Normal, state=QIcon.Off)
        minimize_icon.addFile(Resources.get('icons/minimize-active.svg'), mode=QIcon.Active, state=QIcon.Off)
        close_icon = QIcon()
        close_icon.addFile(Resources.get('icons/close.svg'), mode=QIcon.Normal, state=QIcon.Off)
        close_icon.addFile(Resources.get('icons/close-active.svg'), mode=QIcon.Active, state=QIcon.Off)

        self.scale_action.setIcon(scale_icon)
        self.viewonly_action.setIcon(viewonly_icon)
        self.screenshot_action.setIcon(screenshot_icon)
        self.fullscreen_action.setIcon(fullscreen_icon)
        self.minimize_action.setIcon(minimize_icon)
        self.close_action.setIcon(close_icon)

        self.scale_button.setIcon(scale_icon)
        self.viewonly_button.setIcon(viewonly_icon)
        self.screenshot_button.setIcon(screenshot_icon)
        self.fullscreen_button.setIcon(fullscreen_icon)
        self.minimize_button.setIcon(minimize_icon)
        self.close_button.setIcon(close_icon)

        self.scale_button.setDefaultAction(self.scale_action)
        self.viewonly_button.setDefaultAction(self.viewonly_action)
        self.screenshot_button.setDefaultAction(self.screenshot_action)
        self.fullscreen_button.setDefaultAction(self.fullscreen_action)
        self.minimize_button.setDefaultAction(self.minimize_action)
        self.close_button.setDefaultAction(self.close_action)

        self.color_depth_button.clear()
        self.color_depth_button.addItem('Default Color Depth', ServerDefault)
        self.color_depth_button.addItem('TrueColor (24 bits)', TrueColor)
        self.color_depth_button.addItem('HighColor (16 bits)', HighColor)
        self.color_depth_button.addItem('LowColor (8 bits)', LowColor)

    def eventFilter(self, watched, event):
        if watched is self.parent() and event.type() == QEvent.Resize:
            new_x = (watched.width() - self.width()) / 2
            self.move(new_x, self.y())
            self.animation.setStartValue(QPoint(new_x, -self.height() + self.exposedPixels))
            self.animation.setEndValue(QPoint(new_x, 0))
        return False

    def enterEvent(self, event):
        super(ScreensharingToolbox, self).enterEvent(event)
        self.retract_timer.stop()
        self.expose()

    def leaveEvent(self, event):
        super(ScreensharingToolbox, self).leaveEvent(event)
        self.retract_timer.start()

    def paintEvent(self, event):  # make the widget style aware
        option = QStyleOption()
        option.initFrom(self)
        painter = QStylePainter(self)
        painter.drawPrimitive(QStyle.PE_Widget, option)

    def expose(self):
        if self.animation.state() == QPropertyAnimation.Running and self.animation.direction() == QPropertyAnimation.Forward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos() == self.animation.endValue():
            return
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.start()

    def retract(self):
        if self.animation.state() == QPropertyAnimation.Running and self.animation.direction() == QPropertyAnimation.Backward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos() == self.animation.startValue():
            return
        self.animation.setDirection(QPropertyAnimation.Backward)
        self.animation.start()
Exemplo n.º 12
0
class SideSlideAnimator(AbstractAnimator):
    m_side: ApplicationSide
    m_decorateBackground: bool
    m_decorator: SideSlideDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _widgetForSlide):
        super(SideSlideAnimator, self).__init__(_widgetForSlide)

        self.m_side = ApplicationSide()
        self.m_decorateBackground = True
        self.m_decorator = SideSlideDecorator(_widgetForSlide.parentWidget())
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_slidePos")

        _widgetForSlide.parentWidget().installEventFilter(self)

        self.m_animation.setEasingCurve(QEasingCurve.InQuad)
        self.m_animation.setDuration(260)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.isAnimatedForward():
                self.widgetForSlide().move(self.m_decorator.slidePos())
            else:
                self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

        self.m_decorator.clicked.connect(self.slideOut)

    def setApplicationSide(self, _side):
        if self.m_side != _side:
            self.m_side = _side

    def setDecorateBackground(self, _decorate):
        if self.m_decorateBackground != _decorate:
            self.m_decorateBackground = _decorate

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideIn()

    def slideIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.widgetForSlide().lower()
        self.widgetForSlide().move(-self.widgetForSlide().width(),
                                   -self.widgetForSlide().height())
        self.widgetForSlide().show()
        self.widgetForSlide().resize(self.widgetForSlide().sizeHint())

        _topWidget = self.widgetForSlide()
        topWidget = self.widgetForSlide()
        while _topWidget:
            topWidget = _topWidget
            _topWidget = topWidget.parentWidget()

        finalSize = self.widgetForSlide().size()
        startPosition = QPoint()
        finalPosition = QPoint()
        if self.m_side == ApplicationSide.LeftSide:
            finalSize.setHeight(topWidget.height())
            startPosition = QPoint(-finalSize.width(), 0)
            finalPosition = QPoint(0, 0)
        if self.m_side == ApplicationSide.TopSide:
            finalSize.setWidth(topWidget.width())
            startPosition = QPoint(0, -finalSize.height())
            finalPosition = QPoint(0, 0)
        if self.m_side == ApplicationSide.RightSide:
            finalSize.setHeight(topWidget.height())
            startPosition = QPoint(topWidget.width(), 0)
            finalPosition = QPoint(topWidget.width() - finalSize.width(), 0)
        if self.m_side == ApplicationSide.BottomSide:
            finalSize.setWidth(topWidget.width())
            startPosition = QPoint(0, topWidget.height())
            finalPosition = QPoint(0, topWidget.height() - finalSize.height())

        if self.m_decorateBackground:
            self.m_decorator.setParent(topWidget)
            self.m_decorator.move(0, 0)
            self.m_decorator.grabParent()
            self.m_decorator.show()
            self.m_decorator.raise_()

        self.widgetForSlide().move(startPosition)
        self.widgetForSlide().resize(finalSize)
        self.widgetForSlide().raise_()

        self.m_decorator.grabSlideWidget(self.widgetForSlide())

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPosition)
            self.m_animation.setEndValue(finalPosition)
            self.m_animation.start()

        if self.m_decorateBackground:
            DARKER = True
            self.m_decorator.decorate(DARKER)

    def animateBackward(self):
        self.slideOut()

    def slideOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        if self.widgetForSlide().isVisible():
            _topWidget = self.widgetForSlide()
            topWidget = self.widgetForSlide()
            while _topWidget:
                topWidget = _topWidget
                _topWidget = topWidget.parentWidget()

            self.widgetForSlide().hide()

            finalSize = self.widgetForSlide().size()
            startPosition = self.widgetForSlide().pos()
            finalPosition = QPoint()
            if self.m_side == ApplicationSide.LeftSide:
                startPosition = QPoint(0, 0)
                finalPosition = QPoint(-finalSize.width(), 0)
            if self.m_side == ApplicationSide.TopSide:
                startPosition = QPoint(0, 0)
                finalPosition = QPoint(0, -finalSize.height())
            if self.m_side == ApplicationSide.RightSide:
                startPosition = QPoint(topWidget.width() - finalSize.width(),
                                       0)
                finalPosition = QPoint(topWidget.width(), 0)
            if self.m_side == ApplicationSide.BottomSide:
                startPosition = QPoint(0,
                                       topWidget.height() - finalSize.height())
                finalPosition = QPoint(0, topWidget.height())

            if self.m_animation.state() == QPropertyAnimation.Running:
                self.m_animation.pause()
                self.m_animation.setDirection(QPropertyAnimation.Backward)
                self.m_animation.resume()
            else:
                self.m_animation.setEasingCurve(QEasingCurve.InQuart)
                self.m_animation.setDirection(QPropertyAnimation.Forward)
                self.m_animation.setStartValue(startPosition)
                self.m_animation.setEndValue(finalPosition)
                self.m_animation.start()

            if self.m_decorateBackground:
                LIGHTER = False
                self.m_decorator.decorate(LIGHTER)

    def eventFilter(self, _object, _event):
        if _object == self.widgetForSlide().parentWidget() and _event.type(
        ) == QEvent.Resize:
            widgetForSlideParent = self.widgetForSlide().parentWidget()
            if self.m_side == ApplicationSide.RightSide:
                self.widgetForSlide().move(
                    widgetForSlideParent.width() -
                    self.widgetForSlide().width(), 0)
            if self.m_side == ApplicationSide.LeftSide:
                self.widgetForSlide().resize(self.widgetForSlide().width(),
                                             widgetForSlideParent.height())
            if self.m_side == ApplicationSide.BottomSide:
                self.widgetForSlide().move(
                    0,
                    widgetForSlideParent.height() -
                    self.widgetForSlide().height())
            if self.m_side == ApplicationSide.TopSide:
                self.widgetForSlide().resize(widgetForSlideParent.width(),
                                             self.widgetForSlide().height())

            self.m_decorator.grabSlideWidget(self.widgetForSlide())

        return QObject.eventFilter(self, _object, _event)

    def widgetForSlide(self):
        return self.parent()
Exemplo n.º 13
0
class SudokuGrid(BaseSudokuItem):
    buttonClicked = pyqtSignal(float, float, bool)
    finishDrawing = pyqtSignal()
    puzzleFinished = pyqtSignal()

    def __init__(self, width, height, parent=None):
        super().__init__(parent)
        self.width = width
        self.height = height

        self.thick_pen = QPen()
        self.thick_pen.setColor(Qt.white)
        self.thick_unit = 5
        self.thick_pen.setWidth(self.thick_unit)

        self.thinlines = []
        self.thicklines = []

        self.cell_width = self.width / 9
        self.cell_height = self.height / 9

        for i in range(1, 9):
            delta_h = self.cell_height * i
            delta_w = self.cell_width * i
            if i % 3 == 0:
                self.thicklines.append(QLineF(0, delta_h, self.width, delta_h))
                self.thicklines.append(QLineF(delta_w, 0, delta_w,
                                              self.height))
            else:
                self.thinlines.append(QLineF(0, delta_h, self.width, delta_h))

                self.thinlines.append(QLineF(delta_w, 0, delta_w, self.height))

        self.sudoku_grid = sdk.SudokuSystem()
        self.grid_painter = NumberPainter(self, self.sudoku_grid)

        self.mouse_w = 0
        self.mouse_h = 0
        self.selection_unit = 8
        self.selection_pen = QPen()
        self.selection_pen.setColor(Qt.white)
        self.selection_pen.setWidth(self.selection_unit)
        self.selection_box = QRectF(0, 0, self.cell_width, self.cell_height)

        self.setAcceptHoverEvents(True)
        self.setAcceptedMouseButtons(Qt.LeftButton)
        self.setFlag(QGraphicsItem.ItemIsFocusable, True)
        self.set_disabled(False)

        # Length of the box to be drawn
        self.length = 0
        # Set up the length to be animated
        self.anim = QPropertyAnimation(self, b'length')
        self.anim.setDuration(500)  # Animation speed
        self.anim.setStartValue(0)
        for t in range(1, 10):
            self.anim.setKeyValueAt(t / 10, self.width * t / 10)
        self.anim.setEndValue(self.width)

        self.scribbling = False

        self.drawn = False
        self.anim.finished.connect(self.finish_drawing)

    def set_disabled(self, state):
        if state:
            self.setAcceptedMouseButtons(Qt.NoButton)
        else:
            self.setAcceptedMouseButtons(Qt.LeftButton)
        self.setAcceptHoverEvents(not state)

    def finish_drawing(self):
        if self.length == self.width:
            self.drawn = True
            self.finishDrawing.emit()

    # Toggle the animation to be play forward or backward
    def toggle_anim(self, toggling):
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()

    def generate_new_grid(self, difficulty):
        self.sudoku_grid.generate_random_board(difficulty)
        #self.sudoku_grid.generate_test_board(difficulty)   # Uncomment for testing
        self.update()

    def change_cell_scribbles(self, val):
        if val == 0:
            self.sudoku_grid.clear_scribble(self.mouse_h, self.mouse_w)
        else:
            self.sudoku_grid.toggle_scribble(self.mouse_h, self.mouse_w, val)
        self.grid_painter.update()

    def replace_cell_number(self, val):
        self.sudoku_grid.replace_cell_number(self.mouse_h, self.mouse_w, val)
        self.grid_painter.update()
        if self.sudoku_grid.completion_check():
            self.puzzleFinished.emit()

    def boundingRect(self):
        return QRectF(-5, -5, self.width + 10, self.height + 10)

    # Reimplemented paint
    def paint(self, painter, style, widget=None):
        painter.setPen(self.default_pen)
        for line in self.thinlines:
            painter.drawLine(line)

        painter.setPen(self.thick_pen)
        for line in self.thicklines:
            painter.drawLine(line)

        if self.drawn:
            painter.setPen(self.selection_pen)
            painter.drawRect(self.selection_box)

    def hoverMoveEvent(self, event):
        if not (self.freeze and self.drawn):
            box_w = bound_value(0, int(event.pos().x() / self.cell_width), 8)
            box_h = bound_value(0, int(event.pos().y() / self.cell_height), 8)
            if box_w != self.mouse_w or box_h != self.mouse_h:
                self.mouse_w = box_w
                self.mouse_h = box_h
                self.selection_box.moveTopLeft(
                    QPointF(box_w * self.cell_width, box_h * self.cell_height))
                self.update()

    def mousePressEvent(self, event):
        event.accept()
        #if self.drawn:
        #    w = (self.mouse_w + 0.5) * self.cell_width
        #    h = (self.mouse_h + 0.5) * self.cell_height

        #    if not self.sudoku_grid.get_cell_status(self.mouse_h, self.mouse_w) == sdk.FIXED:
        #        self.buttonClicked.emit(w, h, self.scribbling)
        #else:
        #    self.buttonClicked.emit(0, 0, self.scribbling)

    def mouseReleaseEvent(self, event):
        if self.drawn:
            w = (self.mouse_w + 0.5) * self.cell_width
            h = (self.mouse_h + 0.5) * self.cell_height

            if not self.sudoku_grid.get_cell_status(self.mouse_h,
                                                    self.mouse_w) == sdk.FIXED:
                self.buttonClicked.emit(w, h, self.scribbling)
        else:
            self.buttonClicked.emit(0, 0, self.scribbling)

    def focusInEvent(self, event):
        self.set_disabled(False)

    def focusOutEvent(self, event):
        self.set_disabled(True)

    def keyPressEvent(self, event):
        if not event.isAutoRepeat():
            if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
                self.scribbling = True

    def keyReleaseEvent(self, event):
        if not event.isAutoRepeat():
            if event.key() == SCRIBBLE_KEY and self.scribbling:
                self.scribbling = False

    # Defining the length to be drawn as a pyqtProperty
    @pyqtProperty(float)
    def length(self):
        return self._length

    # Determine the length of the four lines to be drawn
    @length.setter
    def length(self, value):
        self._length = value

        for lines in self.thinlines:
            if lines.x1() == 0:
                lines.setP2(QPointF(value, lines.y2()))
            else:
                lines.setP2(QPointF(lines.x2(), value))

        for lines in self.thicklines:
            if lines.x1() == 0:
                lines.setP2(QPointF(value, lines.y2()))
            else:
                lines.setP2(QPointF(lines.x2(), value))

        self.update()
Exemplo n.º 14
0
class SwitchPrivate(QObject):
    def __init__(self, q, parent=None):
        QObject.__init__(self, parent=parent)
        self.mPointer = q
        self.mPosition = 0.0
        self.mGradient = QLinearGradient()
        self.mGradient.setSpread(QGradient.PadSpread)

        self.animation = QPropertyAnimation(self)
        self.animation.setTargetObject(self)
        self.animation.setPropertyName(b'position')
        self.animation.setStartValue(0.0)
        self.animation.setEndValue(1.0)
        self.animation.setDuration(200)
        self.animation.setEasingCurve(QEasingCurve.InOutExpo)

        self.animation.finished.connect(self.mPointer.update)

    @pyqtProperty(float)
    def position(self):
        return self.mPosition

    @position.setter
    def position(self, value):
        self.mPosition = value
        self.mPointer.update()

    def draw(self, painter):
        r = self.mPointer.rect()
        margin = r.height() / 10
        shadow = self.mPointer.palette().color(QPalette.Dark)
        light = self.mPointer.palette().color(QPalette.Light)
        button = self.mPointer.palette().color(QPalette.Button)
        painter.setPen(Qt.NoPen)

        self.mGradient.setColorAt(0, shadow.darker(130))
        self.mGradient.setColorAt(1, light.darker(130))
        self.mGradient.setStart(0, r.height())
        self.mGradient.setFinalStop(0, 0)
        painter.setBrush(self.mGradient)
        painter.drawRoundedRect(r, r.height() / 2, r.height() / 2)

        self.mGradient.setColorAt(0, shadow.darker(140))
        self.mGradient.setColorAt(1, light.darker(160))
        self.mGradient.setStart(0, 0)
        self.mGradient.setFinalStop(0, r.height())
        painter.setBrush(self.mGradient)
        painter.drawRoundedRect(r.adjusted(margin, margin, -margin, -margin),
                                r.height() / 2,
                                r.height() / 2)

        self.mGradient.setColorAt(0, button.darker(130))
        self.mGradient.setColorAt(1, button)

        painter.setBrush(self.mGradient)

        x = r.height() / 2.0 + self.mPosition * (r.width() - r.height())
        painter.drawEllipse(QPointF(x,
                                    r.height() / 2),
                            r.height() / 2 - margin,
                            r.height() / 2 - margin)

    @pyqtSlot(bool, name='animate')
    def animate(self, checked):
        self.animation.setDirection(QPropertyAnimation.Forward if checked else
                                    QPropertyAnimation.Backward)
        self.animation.start()
Exemplo n.º 15
0
class NumberItem(SudokuItem):

    adj = 5
    valid_input = True

    def __init__(self, parent, row, col, num, rect: QRectF, disabled=False):
        super().__init__(parent=parent)
        self.rect = rect.adjusted(self.adj, self.adj, -self.adj, -self.adj)
        self.disabled = disabled
        self.row = row
        self.col = col

        # Create a link to the sudoku game instance.
        self.game = self.parent.parent.game

        if num == 0:
            self.num = ''
        else:
            self.num = num

        self.animations()

        if not self.disabled:
            self.setFlags(QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsSelectable)
        self.setAcceptHoverEvents(True)
        self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        self.setTransformOriginPoint(self.rect.center())

    def paint(self, painter, option, widget):
        # Change font color when user input is false.
        # Default pen color is set to black.
        black_pen = QPen(Qt.black, 1)
        red_pen = QPen(Qt.red, 1)

        painter.setPen(black_pen)

        brush = QBrush(Qt.NoBrush)
        if self.disabled:
            brush = QBrush(QColor(200, 200, 200), Qt.SolidPattern)
        if self.isSelected():
            width = self.rect.width() * 1.1
            height = self.rect.height() * 1.1
            x = self.rect.x() - ((width - self.rect.width()) / 2)
            y = self.rect.y() - ((height - self.rect.height()) / 2)
            rect = QRectF(x, y, width, height)
            brush = QBrush(QColor(160, 200, 255), Qt.SolidPattern)
        else:
            rect = self.rect

        painter.setBrush(brush)
        painter.setFont(QFont('Helvetica', 14, 50))
        painter.setRenderHint(QPainter.Antialiasing)
        painter.drawEllipse(rect)

        if self.parent.parent.show_errors and not self.valid_input:
            painter.setPen(red_pen)

        painter.drawText(rect, Qt.AlignCenter, f'{self.num}')

    def boundingRect(self):
        return self.rect.adjusted(-self.adj, -self.adj, self.adj, self.adj)

    def hoverEnterEvent(self, e):
        if not self.disabled:
            self.setCursor(Qt.IBeamCursor)
            self.start_animations(QAbstractAnimation.Forward)

    def hoverMoveEvent(self, e):
        pass

    def hoverLeaveEvent(self, e):
        if not self.disabled:
            self.setCursor(Qt.ArrowCursor)
            self.start_animations(QAbstractAnimation.Backward)

    def mousePressEvent(self, e):
        # Clear any item that may be selected that belongs to the same parent.
        # Also, remove the focus from that item.
        for item in self.parent.childItems():
            item.setSelected(False)
            item.setFocus(False)
        # Set the current item as selected, and give it focus.
        self.setSelected(True)
        self.setFocus(True)

    def keyPressEvent(self, e):
        print()
        # Only act on the item that currently has keyboard focus.
        if self.hasFocus():
            # On backspace or delete, remove the current number from spot.
            if e.key() == 16777219 or e.key() == 16777223:
                self.num = ''
                self.game.board[self.row][self.col] = 0
            elif e.key() >= 49 and e.key() <= 57:
                # If the number already exists in spot, do nothing.
                if str(e.key() - 48) == self.num:
                    return

                # Otherwise, set the number to the key that was pressed.
                self.num = str(e.key() - 48)

                board_copy = deepcopy(self.game.board)
                board_copy[self.row][self.col] = int(self.num)

                # Check to make sure that there are no overlaps in columns, and rows, and the board is solveable.
                if self.game.check_input(int(self.num), self.row, self.col,
                                         self.game.board):
                    self.valid_input = True
                else:
                    self.valid_input = False

                self.game.board[self.row][self.col] = int(self.num)

            self.update()

            if self.parent.parent.game.check_game_over():
                self.parent.parent.game_over.emit()

    def animations(self):
        scale_value = 1.1
        self.scale_anim = QPropertyAnimation(self, b'scale')
        self.scale_anim.setDuration(100)
        self.scale_anim.setStartValue(1)
        self.scale_anim.setEndValue(scale_value)

    def start_animations(self, direction: QAbstractAnimation):
        self.scale_anim.setDirection(direction)
        self.scale_anim.start()
Exemplo n.º 16
0
class QSlideSwitchPrivate(QObject):

    def __init__(self, q):
        QObject.__init__(self)

        self._position = 0
        self._sliderShape = QRectF()
        self._gradient = QLinearGradient()
        self._gradient.setSpread(QGradient.PadSpread)
        self._qPointer = q

        self.animation = QPropertyAnimation(self, b"position")
        self.animation.setTargetObject(self)
        # self.animation.setPropertyName()
        self.animation.setStartValue(0)
        self.animation.setEndValue(1)
        self.animation.setDuration(300)
        self.animation.setEasingCurve(QEasingCurve.InOutExpo)

    def __del__(self):
        del self.animation

    @pyqtProperty(float)
    def position(self):
        return self._position

    @position.setter
    def position(self, value):
        self._position = value
        self._qPointer.repaint()

    def drawSlider(self, painter):
        margin = 3
        r = self._qPointer.rect().adjusted(0, 0, -1, -1)
        dx = (r.width() - self._sliderShape.width()) * self._position
        sliderRect = self._sliderShape.translated(dx, 0)
        painter.setPen(Qt.NoPen)

        # basic settings
        shadow = self._qPointer.palette().color(QPalette.Dark)
        light = self._qPointer.palette().color(QPalette.Light)
        button = self._qPointer.palette().color(QPalette.Button)

        # draw background
        # draw outer background
        self._gradient.setColorAt(0, shadow.darker(130))
        self._gradient.setColorAt(1, light.darker(130))
        self._gradient.setStart(0, r.height())
        self._gradient.setFinalStop(0, 0)
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(r, 15, 15)

        # draw background
        # draw inner background
        self._gradient.setColorAt(0, shadow.darker(140))
        self._gradient.setColorAt(1, light.darker(160))
        self._gradient.setStart(0, 0)
        self._gradient.setFinalStop(0, r.height())
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(r.adjusted(margin, margin, -margin, -margin), 15, 15)

        # draw slider
        self._gradient.setColorAt(0, button.darker(130))
        self._gradient.setColorAt(1, button)

        # draw outer slider
        self._gradient.setStart(0, r.height())
        self._gradient.setFinalStop(0, 0)
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(sliderRect.adjusted(margin, margin, -margin, -margin), 10, 15)

        # draw inner slider
        self._gradient.setStart(0, 0)
        self._gradient.setFinalStop(0, r.height())
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(sliderRect.adjusted(2.5 * margin, 2.5 * margin, -2.5 * margin, - 2.5 * margin), 5, 15)

        # draw text
        if self.animation.state() == QPropertyAnimation.Running:
            return  # don't draw any text while animation is running

        font = self._qPointer.font()
        self._gradient.setColorAt(0, light)
        self._gradient.setColorAt(1, shadow)
        self._gradient.setStart(0, r.height() / 2.0 + font.pointSizeF())
        self._gradient.setFinalStop(0, r.height() / 2.0 - font.pointSizeF())
        painter.setFont(font)
        painter.setPen(QPen(QBrush(self._gradient), 0))

        if self._qPointer.isChecked():
            painter.drawText(0, 0, r.width() / 2, r.height() - 1, Qt.AlignCenter, "ON")
        else:
            painter.drawText(r.width() / 2, 0, r.width() / 2, r.height() - 1, Qt.AlignCenter, "OFF")

    def updateSliderRect(self, size):
        self._sliderShape.setWidth(size.width() / 2.0)
        self._sliderShape.setHeight(size.height() - 1.0)

    @pyqtSlot(bool, name='animate')
    def animate(self, checked):
        self.animation.setDirection(QPropertyAnimation.Forward if checked else QPropertyAnimation.Backward)
        self.animation.start()
Exemplo n.º 17
0
class SlideAnimator(AbstractAnimator):
    m_direction:AnimationDirection
    m_isFixBackground:bool
    m_isFixStartSize:bool
    m_startMinSize = QSize()
    m_startMaxSize = QSize()
    m_startSize = QSize()
    m_decorator: SlideForegroundDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _widgetForSlide):
        super(SlideAnimator, self).__init__(_widgetForSlide)

        self.m_direction = AnimationDirection.FromLeftToRight
        self.m_isFixBackground = True
        self.m_isFixStartSize = False
        self.m_decorator = SlideForegroundDecorator(_widgetForSlide)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"maximumWidth")

        _widgetForSlide.installEventFilter(self)

        self.m_animation.setDuration(300)

        self.m_decorator.hide()

        def valueChanged(_value):
            if self.isWidth():
                self.widgetForSlide().setMaximumWidth(_value)
            else:
                self.widgetForSlide().setMaximumHeight(_value)
        self.m_animation.valueChanged.connect(valueChanged)

        def finished():
            self.setAnimatedStopped()
            self.m_decorator.hide()
        self.m_animation.finished.connect(finished)

    def setAnimationDirection(self, _direction):
        if self.m_direction != _direction:
            self.m_direction = _direction
        self.m_animation.setPropertyName(b"maximumWidth" if self.isWidth() else b"maximumHeight")

    def setFixBackground(self, _fix):
        if self.m_isFixBackground != _fix:
            self.m_isFixBackground = _fix

    def setFixStartSize(self, _fix):
        if self.m_isFixStartSize != _fix:
            self.m_isFixStartSize = _fix

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideIn()

    def slideIn(self):
        if not self.m_startMinSize.isValid():
            self.m_startMinSize = self.widgetForSlide().minimumSize()
        if not self.m_startMaxSize.isValid():
            self.m_startMaxSize = self.widgetForSlide().maximumSize()
        if not self.m_startSize.isValid():
            self.m_startSize = self.widgetForSlide().sizeHint()

        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        if self.isWidth():
            self.widgetForSlide().setMaximumWidth(0)
        else:
            self.widgetForSlide().setMaximumHeight(0)

        self.widgetForSlide().show()
        currentSize = self.widgetForSlide().size()

        finalSize = QSize(currentSize.width(), currentSize.height())
        self.fixSize(self.m_startSize, finalSize)

        self.widgetForSlide().hide()
        self.fixSizeOfWidgetForSlide(finalSize)
        self.m_decorator.grabParent(finalSize)
        self.fixSizeOfWidgetForSlide(currentSize)
        self.widgetForSlide().show()

        if self.m_isFixBackground:
            self.m_decorator.move(0, 0)
            self.m_decorator.show()
            self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(self.widgetForSlide().width() if self.isWidth() else self.widgetForSlide().height())
            self.m_animation.setEndValue(finalSize.width() if self.isWidth() else finalSize.height())
            self.m_animation.start()

    def animateBackward(self):
        self.slideOut()

    def slideOut(self):
        if not self.m_startMinSize.isValid():
            self.m_startMinSize = self.widgetForSlide().minimumSize()
        if not self.m_startMaxSize.isValid():
            self.m_startMaxSize = self.widgetForSlide().maximumSize()
        if not self.m_startSize.isValid() or not self.m_isFixStartSize:
            self.m_startSize = self.widgetForSlide().size()

        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        finalSize = self.widgetForSlide().size()
        if self.isWidth():
            finalSize.setWidth(0)
        else:
            finalSize.setHeight(0)

        self.m_decorator.grabParent(self.widgetForSlide().size())

        if self.m_isFixBackground:
            self.m_decorator.move(0, 0)
            self.m_decorator.show()
            self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(self.widgetForSlide().width() if self.isWidth() else self.widgetForSlide().height())
            self.m_animation.setEndValue(finalSize.width() if self.isWidth() else finalSize.height())
            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.widgetForSlide() and _event.type() == QEvent.Resize and self.m_decorator.isVisible():
            if self.m_direction == AnimationDirection.FromLeftToRight:
                self.m_decorator.move(self.widgetForSlide().width() - self.m_decorator.width(), 0)
            if self.m_direction == AnimationDirection.FromTopToBottom:
                self.m_decorator.move(0, self.widgetForSlide().height() - self.m_decorator.height())

        return QObject.eventFilter(self, _object, _event)

    def isWidth(self):
        return self.m_direction == AnimationDirection.FromLeftToRight or self.m_direction == AnimationDirection.FromRightToLeft

    def fixSize(self, _sourceSize, _targetSize):
        if self.isWidth():
            _targetSize.setWidth(_sourceSize.width())
        else:
            _targetSize.setHeight(_sourceSize.height())

    def fixSizeOfWidgetForSlide(self, _sourceSize):
        if self.isWidth():
            self.widgetForSlide().setFixedWidth(_sourceSize.width())
        else:
            self.widgetForSlide().setFixedHeight(_sourceSize.height())


    def widgetForSlide(self):
        return self.parent()
Exemplo n.º 18
0
class AnimatedText(QGraphicsObject):
    def __init__(self, text, parent=None):
        super().__init__(parent=parent)
        self.parent = parent
        self.actual_text = text
        self.shown_text = ''
        self.delay = 3

        # Set up pens for drawing
        self.default_pen = QPen()
        self.default_pen.setColor(Qt.white)

        self.shown_length = 0

        # Set up the length to be animated
        self.anim = QPropertyAnimation(self, b'shown_length')
        self.anim.setDuration(len(self.actual_text) * 50)  # Animation speed
        self.anim.setStartValue(0)
        for t in range(1, 10):
            self.anim.setKeyValueAt(
                t / 10, (len(self.actual_text) + self.delay) * t / 10)
        self.anim.setEndValue(len(self.actual_text) + self.delay)
        self.visibleChanged.connect(self.show_text)

    def show_text(self):
        if self.isVisible():
            self.toggle_anim(True)
        else:
            self.shown_length = 0

    # Toggle the animation to be play forward or backward
    def toggle_anim(self, toggling):
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()

    def boundingRect(self):
        return self.parent.boundingRect()

    def paint(self, painter, style, widget=None):
        painter.setPen(self.default_pen)
        painter.drawText(self.parent.boundingRect(), Qt.AlignCenter,
                         self.shown_text)

    # Defining the length to be drawn as a pyqtProperty
    @pyqtProperty(int)
    def shown_length(self):
        return self._shown_length

    # Determine the length of the four lines to be drawn
    @shown_length.setter
    def shown_length(self, value):
        self._shown_length = value
        if value < self.delay:
            # All printed text should be garbage
            garbage = [
                chr(num) for num in
                [random.choice(range(33, 127)) for _ in range(value)]
            ]
            self.shown_text = ''.join(garbage)
        else:
            # Printed text contain some actual text
            garbage = [
                chr(num) for num in [
                    random.choice(range(33, 127)) for _ in range(
                        min(
                            len(self.actual_text) + self.delay -
                            value, self.delay))
                ]
            ]
            self.shown_text = self.actual_text[:value -
                                               self.delay] + ''.join(garbage)

        self.update()
Exemplo n.º 19
0
class BoxBoard(QGraphicsWidget):
    """A generic board that draws an animated rectangular border
    """
    def __init__(self, width, height, parent=None):
        """Prepare the lines to be drawn and set up the animation

        Parameters
        ----------
        width: float
            Width of the box
        height: float
            Height of the box
        parent: object
            Pass into QGraphicsWidget init method
        """
        super().__init__(parent)
        self.width = width
        self.height = height
        self.half_circumference = width + height
        self.freeze = False

        self.setMinimumSize(QSizeF(width, height))
        #self.setMaximumSize(QSizeF(width, height))

        self.size_policy = QSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)
        self.size_policy.setHeightForWidth(True)
        self.setSizePolicy(self.size_policy)

        # Set up a default pen for drawing
        self.default_pen = QPen()
        self.default_pen.setColor(Qt.white)
        self.default_pen.setWidth(5)

        # The 4 lines to construct the box
        self.left = QLineF(0, 0, 0, self.height)
        self.down = QLineF(0, self.height, self.width, self.height)
        self.right = QLineF(self.width, self.height, self.width, 0)
        self.up = QLineF(self.width, 0, 0, 0)

        self.line_order = [self.up, self.right, self.down, self.left]

        self.length = 0
        # Set up the length to be animated
        self.anim = QPropertyAnimation(self, b'length')
        self.anim.setDuration(800)  # Animation speed
        self.anim.setStartValue(0)
        for t in range(1, 10):
            self.anim.setKeyValueAt(t / 10, self.half_circumference * t / 10)
        self.anim.setEndValue(self.half_circumference)

    # Defining the length to be drawn as a pyqtProperty
    @pyqtProperty(float)
    def length(self):
        """float: The length of the box to be drawn

        When the value is set, the length of the lines making up the box
        are calculated and updated.
        """
        return self._length

    # Determine the length of the four lines to be drawn
    @length.setter
    def length(self, value):
        self._length = value
        remaining_length = value
        if remaining_length >= self.height:
            length_to_draw = remaining_length - self.height
            remaining_length -= length_to_draw
        else:
            length_to_draw = 0

        self.down.setLine(0, self.height, length_to_draw, self.height)
        self.up.setLine(self.width, 0, self.width - length_to_draw, 0)
        self.left.setLine(0, 0, 0, remaining_length)
        self.right.setLine(self.width, self.height, self.width,
                           self.height - remaining_length)
        self.update()

    def toggle_anim(self, toggling):
        """Toggle the animation forward and backwards

        Parameters
        ----------
        toggling: bool
            True for forward, False for backwards
        """
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()

    def paint(self, painter, style, widget=None):
        """Reimplemented from QGraphicsWdiget paint function. Draws the lines making up the box.
        """
        painter.setPen(self.default_pen)
        for line in self.line_order:
            if line.length() > 1:
                painter.drawLine(line)
Exemplo n.º 20
0
class StackedWidgetSlideOverAnimator(AbstractAnimator):
    m_direction: AnimationDirection
    m_coveredWidget: QWidget
    m_decorator: StackedWidgetSlideOverDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _container, _widgetForSlide):
        super(StackedWidgetSlideOverAnimator, self).__init__(_container)

        self.m_direction = AnimationDirection.FromLeftToRight
        self.m_coveredWidget = _container.currentWidget()
        self.m_decorator = StackedWidgetSlideOverDecorator(
            _container, _widgetForGrab=_widgetForSlide)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"pos")

        _container.installEventFilter(self)

        self.m_animation.setDuration(400)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()

            if self.isAnimatedForward():
                _container.setCurrentWidget(_widgetForSlide)
            self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def updateCoveredWidget(self):
        self.m_coveredWidget = self.stackedWidget().currentWidget()

    def setAnimationDirection(self, _direction):
        if self.m_direction != _direction:
            self.m_direction = _direction

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideOverIn()

    def slideOverIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.m_decorator.grabWidget()

        startPos = QPoint()
        finalPos = QPoint()

        if self.m_direction == AnimationDirection.FromLeftToRight:
            startPos.setX(-1 * self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromRightToLeft:
            startPos.setX(self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromTopToBottom:
            startPos.setY(-1 * self.stackedWidget().height())
        if self.m_direction == AnimationDirection.FromBottomToTop:
            startPos.setY(self.stackedWidget().height())

        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutExpo)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPos)
            self.m_animation.setEndValue(finalPos)

            self.m_animation.start()

    def animateBackward(self):
        self.slideOverOut()

    def slideOverOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        self.m_decorator.grabWidget()

        startPos = QPoint()
        finalPos = QPoint()

        if self.m_direction == AnimationDirection.FromLeftToRight:
            finalPos.setX(-1 * self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromRightToLeft:
            finalPos.setX(self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromTopToBottom:
            finalPos.setY(-1 * self.stackedWidget().height())
        if self.m_direction == AnimationDirection.FromBottomToTop:
            finalPos.setY(self.stackedWidget().height())

        if isinstance(self.stackedWidget(), type(self)):
            self.stackedWidget().setCurrentWidget(self.m_coveredWidget)

        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutExpo)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPos)
            self.m_animation.setEndValue(finalPos)

            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.stackedWidget() and _event.type(
        ) == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.grabWidget()

        return QWidget.eventFilter(self, _object, _event)

    def stackedWidget(self):
        return self.parent()
Exemplo n.º 21
0
class MainWindow(QMainWindow):
    siteLoaded = pyqtSignal(object)

    def __init__(self, app):
        QMainWindow.__init__(self)
        self.app = app
        self.initGui()
        self.readSettings()
        self.dashboard.setExpanded(True)
        self.showDashboard()
        self.loadDatabase()
        self.loadClients()
        self.statusBar().showMessage("Ready")

    def initGui(self):
        self.installEventFilter(self)
        self.dashboard = Expander("Dashboard", ":/images/dashboard_normal.png",
                                  ":/images/dashboard_hover.png",
                                  ":/images/dashboard_selected.png")
        self.content = Expander("Clients", ":/images/clients_normal.png",
                                ":/images/clients_hover.png",
                                ":/images/clients_selected.png")
        self.settings = Expander("Settings", ":/images/settings_normal.png",
                                 ":/images/settings_hover.png",
                                 ":/images/settings_selected.png")

        self.setWindowTitle(QCoreApplication.applicationName() + " " +
                            QCoreApplication.applicationVersion())
        vbox = QVBoxLayout()
        vbox.addWidget(self.dashboard)
        vbox.addWidget(self.content)
        vbox.addWidget(self.settings)
        vbox.addStretch()

        content_box = QVBoxLayout()
        filter_label = QLabel("Filter")
        self.filter = QLineEdit()
        self.filter.textChanged.connect(self.filterChanged)
        self.client_list = QListWidget()
        self.client_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        self.client_list.currentItemChanged.connect(self.clientChanged)

        content_box.addWidget(filter_label)
        content_box.addWidget(self.filter)
        content_box.addWidget(self.client_list)
        self.content.addLayout(content_box)

        scroll_content = QWidget()
        scroll_content.setLayout(vbox)
        scroll = QScrollArea()
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setWidget(scroll_content)
        scroll.setWidgetResizable(True)
        scroll.setMaximumWidth(200)
        scroll.setMinimumWidth(200)

        self.navigationdock = QDockWidget("Navigation", self)
        self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea
                                            | Qt.RightDockWidgetArea)
        self.navigationdock.setWidget(scroll)
        self.navigationdock.setObjectName("Navigation")

        self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock)

        self.showDock = FlatButton(":/images/edit_normal.png",
                                   ":/images/edit_hover.png")
        self.showDock.setToolTip("Show Navigation")
        self.statusBar().addPermanentWidget(self.showDock)

        self.dashboard.expanded.connect(self.dashboardExpanded)
        self.dashboard.clicked.connect(self.showDashboard)
        self.content.expanded.connect(self.contentExpanded)
        self.content.clicked.connect(self.showClient)

        self.settings.expanded.connect(self.settingsExpanded)
        self.settings.clicked.connect(self.showSettings)

        self.showDock.clicked.connect(self.showMenu)
        self.navigationdock.visibilityChanged.connect(
            self.dockVisibilityChanged)

        self.client = None
        self.client_editor = ClientEditor(self)

    def showDashboard(self):
        db = Dashboard()
        db.createSite.connect(self.addClient)
        self.setCentralWidget(db)

    def showClient(self):
        self.setCentralWidget(self.client_editor)

    def showSettings(self):
        s = SettingsEditor(self)
        self.setCentralWidget(s)

    def setCentralWidget(self, widget):
        old_widget = self.takeCentralWidget()
        super().setCentralWidget(widget)
        widget.show()

    def closeEvent(self, event):
        self.writeSettings()
        event.accept()

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("state", self.saveState())
        settings.setValue("databaseFile", self.databaseFile)
        settings.setValue("fontSize", str(self.fontSize))

    def readSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        geometry = settings.value("geometry", QByteArray())
        if geometry.isEmpty():
            availableGeometry = QApplication.desktop().availableGeometry(self)
            self.resize(availableGeometry.width() / 3,
                        availableGeometry.height() / 2)
            self.move(int(((availableGeometry.width() - self.width()) / 2)),
                      int((availableGeometry.height() - self.height()) / 2))
        else:
            self.restoreGeometry(geometry)
            self.restoreState(settings.value("state"))
        self.databaseFile = settings.value("databaseFile")
        if not self.databaseFile:
            self.databaseFile = "maria.json"
        fs = settings.value("fontSize")
        if not fs:
            fs = 10
        self.fontSize = int(fs)
        font = QFont("Sans Serif", self.fontSize)
        self.app.setFont(font)

    def dashboardExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.settings.setExpanded(False)

    def contentExpanded(self, value):
        if value:
            self.dashboard.setExpanded(False)
            self.settings.setExpanded(False)

    def settingsExpanded(self, value):
        if value:
            self.dashboard.setExpanded(False)
            self.content.setExpanded(False)

    def showMenu(self):
        self.navigationdock.setVisible(True)

    def dockVisibilityChanged(self, visible):
        self.showDock.setVisible(not visible)

    def animate(self, item):
        panel = self.centralWidget()
        self.list = item.tableWidget()
        self.row = item.row()

        # create a cell widget to get the right position in the table
        self.cellWidget = QWidget()
        self.cellWidget.setMaximumHeight(0)
        self.list.setCellWidget(self.row, 1, self.cellWidget)
        pos = self.cellWidget.mapTo(panel, QPoint(0, 0))

        self.editor.setParent(panel)
        self.editor.move(pos)
        self.editor.resize(self.cellWidget.size())
        self.editor.show()

        self.animation = QPropertyAnimation(self.editor,
                                            "geometry".encode("utf-8"))
        self.animation.setDuration(300)
        self.animation.setStartValue(
            QRect(pos.x(), pos.y(),
                  self.cellWidget.size().width(),
                  self.cellWidget.size().height()))
        self.animation.setEndValue(
            QRect(0, 0,
                  panel.size().width(),
                  panel.size().height()))
        self.animation.start()

    def editorClosed(self):
        pos = self.cellWidget.mapTo(self.centralWidget(), QPoint(0, 0))
        # correct end values in case of resizing the window
        self.animation.setStartValue(
            QRect(pos.x(), pos.y(),
                  self.cellWidget.size().width(),
                  self.cellWidget.size().height()))
        self.animation.finished.connect(self.animationFineshedZoomOut)
        self.animation.setDirection(QAbstractAnimation.Backward)
        self.animation.start()

    def animationFineshedZoomOut(self):
        self.list.removeCellWidget(self.row, 1)
        del self.animation

        # in the case self.editor was a MenuEditor, we have to unregister it in the MenuList
        # should be refactored some day :-)
        list = self.centralWidget()
        if list is MenuEditor:
            list.unregisterMenuEditor()

        del self.editor
        self.editor = None

        if self.method_after_animation == "showDashboard":
            self.showDashboard()
            self.method_after_animation = ""
        elif self.method_after_animation == "showSettings":
            self.showSettings()

        if self.content_after_animation:
            self.previewSite(self.content_after_animation)
            self.content_after_animation = None

    def filterChanged(self):
        self.loadClients()

    def loadDatabase(self):
        self.db = TinyDB(self.databaseFile)
        self.clients = self.db.table('Clients')

    def updateClient(self):
        for i in range(self.client_list.count()):
            item = self.client_list.item(i)
            c = item.data(3)
            if c.doc_id == self.client.doc_id:
                item.setData(3, self.client)
                item.setText(self.client["name"])
                break

    def loadClients(self):
        self.client_list.clear()
        filter = self.filter.text()

        a = []
        for c in self.clients:
            if filter in c["name"]:
                a.append(c)

        s = sorted(a, key=namesort)
        for c in s:
            item = QListWidgetItem()
            item.setText(c["name"])
            item.setData(3, c)
            self.client_list.addItem(item)
        self.client_list.setCurrentRow(0)

    def addClient(self):
        now = datetime.now()
        newclient = {
            "number": "",
            "name": "",
            "birthday_year": 1990,
            "birthday_month": 1,
            "birthday_day": 1,
            "profession": "",
            "address": "",
            "mobile": "",
            "email": "",
            "reason": "",
            "fiscal": "",
            "how": "",
            "first_contact_year": now.year,
            "first_contact_month": now.month,
            "first_contact_day": now.day,
            "notes": ""
        }
        self.clients.insert(newclient)
        self.showClient()
        self.loadClients()
        q = Query()
        self.client = self.clients.get(q.name == "")
        self.client["name"] = ""
        self.client_editor.reload()

    def clientChanged(self, item):
        if item:
            self.client = item.data(3)
            self.client_editor.reload()
        else:
            self.client = None
            self.client_editor.reload()
Exemplo n.º 22
0
class NumberRing(BaseSudokuItem):
    loseFocus = pyqtSignal()
    keyPressed = pyqtSignal(str, bool)

    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self.setVisible(False)
        self.cell_width = 24
        self.cell_height = 24

        self.cell_buttons = []
        for i in range(10):
            if i == 0:
                cell_string = 'X'
            else:
                cell_string = str(i)
            btn = buttons.RingButton(0,
                                     0,
                                     self.cell_width,
                                     self.cell_height,
                                     cell_string,
                                     parent=self)
            btn.buttonClicked.connect(self.send_button_press)
            self.cell_buttons.append(btn)

        self.radius = 54
        # Set up the radius to be animated
        self.anim = QPropertyAnimation(self, b'radius')
        self.anim.setDuration(100)  # Animation speed
        self.anim.setStartValue(0)
        for t in range(1, 10):
            self.anim.setKeyValueAt(t / 10, self.radius * t / 10)
        self.anim.setEndValue(self.radius)
        self.anim.finished.connect(self.finish_animation)

        self.setFlag(QGraphicsItem.ItemIsFocusable, True)
        self.setAcceptHoverEvents(True)

        self.freeze_buttons(True)
        self.scribbling = False

    def finish_animation(self):
        if self.radius == 0:
            self.setVisible(False)
            self.freeze_buttons(True)
            self.loseFocus.emit()
        else:
            self.freeze_buttons(False)
            if self.isUnderMouse():
                self.set_buttons_transparent(False)
            else:
                self.set_buttons_transparent(True)

    # Toggle the animation to be play forward or backward
    def toggle_anim(self, toggling):
        self.freeze_buttons(True)
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()

    def boundingRect(self):
        return QRectF(-5 - self.radius - self.cell_width / 2,
                      -5 - self.radius - self.cell_height / 2,
                      self.cell_width + self.radius * 2 + 10,
                      self.cell_height + self.radius * 2 + 10)

    # Reimplemented paint
    def paint(self, painter, style, widget=None):
        pass

    def send_button_press(self, val):
        self.keyPressed.emit(val, self.scribbling)
        self.close_menu()

    def freeze_buttons(self, freeze):
        for btn in self.cell_buttons:
            btn.set_freeze(freeze)

    def focusOutEvent(self, event):
        if not any(btn.isUnderMouse() for btn in self.cell_buttons):
            self.toggle_anim(False)
        else:
            self.setFocus()

    def mousePressEvent(self, event):
        if not any(btn.isUnderMouse() for btn in self.cell_buttons):
            self.toggle_anim(False)
        else:
            self.setFocus()

    def close_menu(self):
        if not self.scribbling:
            self.toggle_anim(False)

    def keyPressEvent(self, event):
        if not event.isAutoRepeat():
            if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
                self.scribbling = True
            if event.key() == 88:
                txt = 'X'
            elif 49 <= event.key() <= 57:
                txt = str(event.key() - 48)
            else:
                txt = ''

            if txt:
                self.keyPressed.emit(txt, self.scribbling)
                if not self.scribbling:
                    self.toggle_anim(False)
                    self.clearFocus()

    def keyReleaseEvent(self, event):
        if not event.isAutoRepeat():
            if event.key() == SCRIBBLE_KEY and self.scribbling:
                self.scribbling = False

    def hoverEnterEvent(self, event):
        self.set_buttons_transparent(False)

    def hoverLeaveEvent(self, event):
        self.set_buttons_transparent(True)

    def set_buttons_transparent(self, state):
        for btn in self.cell_buttons:
            btn.set_transparent(state)

    # Defining the length to be drawn as a pyqtProperty
    @pyqtProperty(float)
    def radius(self):
        return self._radius

    # Determine the length of the four lines to be drawn
    @radius.setter
    def radius(self, value):
        self._radius = value

        for i, btn in enumerate(self.cell_buttons):
            cell_x = value * np.sin(np.deg2rad(
                360 / 10 * i)) - self.cell_width / 2
            cell_y = -value * np.cos(np.deg2rad(
                360 / 10 * i)) - self.cell_height / 2

            btn.setX(cell_x)
            btn.setY(cell_y)

        self.update()
Exemplo n.º 23
0
class ExpandAnimator(AbstractAnimator):
    m_decorator: ExpandDecorator
    m_animation: QPropertyAnimation
    m_expandRect: QRect

    def __init__(self, _widgetForFill):
        super(ExpandAnimator, self).__init__(_widgetForFill)

        self.m_decorator = ExpandDecorator(_widgetForFill)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_expandRect")

        _widgetForFill.installEventFilter(self)

        self.m_animation.setDuration(400)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.isAnimatedBackward():
                self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def setExpandRect(self, _rect):
        self.m_expandRect = _rect
        self.m_decorator.setExpandRect(_rect)

    def setFillColor(self, _color):
        self.m_decorator.setFillColor(_color)

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.expandIn()

    def expandIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        startExpandRect = self.m_expandRect
        finalExpandRect = self.widgetForFill().rect()

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.grabExpandRect()
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startExpandRect)
            self.m_animation.setEndValue(finalExpandRect)
            self.m_animation.start()

    def animateBackward(self):
        self.expandOut()

    def expandOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        startExpandRect = self.widgetForFill().rect()
        finalExpandRect = self.m_expandRect

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.hide()
        self.m_decorator.grabExpandRect()
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startExpandRect)
            self.m_animation.setEndValue(finalExpandRect)
            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.widgetForFill() and _event.type(
        ) == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.resize(self.widgetForFill().size())
            self.m_animation.setEndValue(self.widgetForFill().rect())

        return QObject.eventFilter(self, _object, _event)

    def widgetForFill(self):
        return self.parent()
Exemplo n.º 24
0
class ScreensharingToolbox(base_class, ui_class):
    exposedPixels = 3

    def __init__(self, parent):
        super(ScreensharingToolbox, self).__init__(parent)
        with Resources.directory:
            self.setupUi()
        parent.installEventFilter(self)
        self.animation = QPropertyAnimation(self, 'pos')
        self.animation.setDuration(250)
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.setEasingCurve(
            QEasingCurve.Linear)  # or OutCirc with 300ms
        self.retract_timer = QTimer(self)
        self.retract_timer.setInterval(3000)
        self.retract_timer.setSingleShot(True)
        self.retract_timer.timeout.connect(self.retract)
        self.resize(self.size().expandedTo(self.toolbox_layout.minimumSize()))

    def setupUi(self):
        super(ScreensharingToolbox, self).setupUi(self)

        # fix the SVG icons, as the generated code loads them as pixmaps, losing their ability to scale -Dan
        scale_icon = QIcon()
        scale_icon.addFile(Resources.get('icons/scale.svg'),
                           mode=QIcon.Normal,
                           state=QIcon.Off)
        viewonly_icon = QIcon()
        viewonly_icon.addFile(Resources.get('icons/viewonly.svg'),
                              mode=QIcon.Normal,
                              state=QIcon.Off)
        screenshot_icon = QIcon()
        screenshot_icon.addFile(Resources.get('icons/screenshot.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.Off)
        fullscreen_icon = QIcon()
        fullscreen_icon.addFile(Resources.get('icons/fullscreen.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.Off)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Active,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Disabled,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Selected,
                                state=QIcon.On)
        minimize_icon = QIcon()
        minimize_icon.addFile(Resources.get('icons/minimize.svg'),
                              mode=QIcon.Normal,
                              state=QIcon.Off)
        minimize_icon.addFile(Resources.get('icons/minimize-active.svg'),
                              mode=QIcon.Active,
                              state=QIcon.Off)
        close_icon = QIcon()
        close_icon.addFile(Resources.get('icons/close.svg'),
                           mode=QIcon.Normal,
                           state=QIcon.Off)
        close_icon.addFile(Resources.get('icons/close-active.svg'),
                           mode=QIcon.Active,
                           state=QIcon.Off)

        self.scale_action.setIcon(scale_icon)
        self.viewonly_action.setIcon(viewonly_icon)
        self.screenshot_action.setIcon(screenshot_icon)
        self.fullscreen_action.setIcon(fullscreen_icon)
        self.minimize_action.setIcon(minimize_icon)
        self.close_action.setIcon(close_icon)

        self.scale_button.setIcon(scale_icon)
        self.viewonly_button.setIcon(viewonly_icon)
        self.screenshot_button.setIcon(screenshot_icon)
        self.fullscreen_button.setIcon(fullscreen_icon)
        self.minimize_button.setIcon(minimize_icon)
        self.close_button.setIcon(close_icon)

        self.scale_button.setDefaultAction(self.scale_action)
        self.viewonly_button.setDefaultAction(self.viewonly_action)
        self.screenshot_button.setDefaultAction(self.screenshot_action)
        self.fullscreen_button.setDefaultAction(self.fullscreen_action)
        self.minimize_button.setDefaultAction(self.minimize_action)
        self.close_button.setDefaultAction(self.close_action)

        self.color_depth_button.clear()
        self.color_depth_button.addItem('Default Color Depth', ServerDefault)
        self.color_depth_button.addItem('TrueColor (24 bits)', TrueColor)
        self.color_depth_button.addItem('HighColor (16 bits)', HighColor)
        self.color_depth_button.addItem('LowColor (8 bits)', LowColor)

    def eventFilter(self, watched, event):
        if watched is self.parent() and event.type() == QEvent.Resize:
            new_x = (watched.width() - self.width()) / 2
            self.move(new_x, self.y())
            self.animation.setStartValue(
                QPoint(new_x, -self.height() + self.exposedPixels))
            self.animation.setEndValue(QPoint(new_x, 0))
        return False

    def enterEvent(self, event):
        super(ScreensharingToolbox, self).enterEvent(event)
        self.retract_timer.stop()
        self.expose()

    def leaveEvent(self, event):
        super(ScreensharingToolbox, self).leaveEvent(event)
        self.retract_timer.start()

    def paintEvent(self, event):  # make the widget style aware
        option = QStyleOption()
        option.initFrom(self)
        painter = QStylePainter(self)
        painter.drawPrimitive(QStyle.PE_Widget, option)

    def expose(self):
        if self.animation.state(
        ) == QPropertyAnimation.Running and self.animation.direction(
        ) == QPropertyAnimation.Forward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos(
        ) == self.animation.endValue():
            return
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.start()

    def retract(self):
        if self.animation.state(
        ) == QPropertyAnimation.Running and self.animation.direction(
        ) == QPropertyAnimation.Backward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos(
        ) == self.animation.startValue():
            return
        self.animation.setDirection(QPropertyAnimation.Backward)
        self.animation.start()
Exemplo n.º 25
0
class MessageLabel(QLabel):
    """
    QLabel that a message, which is displayed through animation.
    """
    def __init__(self, text, speed=20, delay=-1, parent=None):
        """
        Does some text processing, and set up the animation to display the text

        Parameters
        ----------
        text: str
            Text to be displayed
        speed : int
            The period at which a new character is printed
            The total time is calculated as length of text * speed
            0 means instant display, like a regular QLabel.
        delay : int
            The number of garbage to be printed before printing the actual text
        parent: QWidget
            Pass into QLabel init method
        """
        super().__init__(text, parent)

        self.setWordWrap(True)
        self.setContentsMargins(0, 0, 0, 0)
        # Text processing
        # Make sure the garbage does not exceed the length of actual text
        self.actual_text = text
        self.shown_text = ''
        if delay >= 0:
            self.delay = min(delay, len(self.actual_text))
        else:
            self.delay = len(self.actual_text)

        # Find out where the new paragraphs are so that it is retained
        self.splitpoints = []
        current_point = 0
        line_splits = self.actual_text.split('\n')
        for line in line_splits:
            current_point += len(line)
            self.splitpoints.append(current_point)
            current_point += 1

        # Set up the shown text length to be animated
        self.shown_length = 0
        self.anim = QPropertyAnimation(self, b'shown_length')
        self.anim.setDuration(len(self.actual_text) * speed)
        self.anim.setStartValue(0)
        self.anim.setEndValue(len(self.actual_text) + self.delay)

        self.setStyleSheet("""
                    color: rgb(0, 255, 0);
                """)

    @pyqtProperty(int)
    def shown_length(self):
        """
        int : The value for the animation

        When the value is set, the text to be printed is generated accordingly.
        It determines whether actual text is to be printed, and retains the
        paragraphs when printing garbage.
        """
        return self._shown_length

    @shown_length.setter
    def shown_length(self, value):
        self._shown_length = value

        if value < self.delay:
            # All printed text should be garbage
            garbage = [
                chr(num) for num in
                [random.choice(range(33, 127)) for _ in range(value)]
            ]

            # Retain the paragraphs
            for num in self.splitpoints[:-1]:
                if num < value:
                    garbage[num] = '\n'

            self.setText(''.join(garbage))
        else:
            # Printed text contain some actual text
            garbage = [
                chr(num) for num in [
                    random.choice(range(33, 127)) for _ in range(
                        min(
                            len(self.actual_text) + self.delay -
                            value, self.delay))
                ]
            ]

            # Retain the paragraphs, but offset by the number of actual text
            non_garbage = value - self.delay
            for num in self.splitpoints[:-1]:
                if num - non_garbage > 0 and num < value:
                    garbage[num - non_garbage] = '\n'

            self.setText(self.actual_text[:value - self.delay] +
                         ''.join(garbage))

    def toggle_anim(self, toggling):
        """
        Toggle the animation to be play forward or backward

        Parameters
        ----------
        toggling: bool
            True for forward, False for backward
        """
        if toggling:
            self.anim.setDirection(QAbstractAnimation.Forward)
        else:
            self.anim.setDirection(QAbstractAnimation.Backward)

        self.anim.start()