예제 #1
1
    def addMovementAnimation(self, animGroup):
#        print(">>MoveAnim")
        for phIdx in self.photoIdxsToMove:
            item = self.photosInGrid[phIdx]
            anim = QPropertyAnimation(item.pixmap, "pos")
            anim.setDuration(self.moveDuration - item.gridCol * self.moveModifier)
            anim.setEasingCurve(QEasingCurve.Linear)
            startCoords = self.getCellTLCoords(item.gridRow, item.gridCol)
            endCoords = self.getCellTLCoords(item.gridRow, item.gridCol + self.columnMovementDist)
            anim.setStartValue(startCoords)
            anim.setEndValue(endCoords)
            animGroup.addAnimation(anim)
예제 #2
0
class MoveSymbol(QUndoCommand):
    ''' Undo/Redo command for moving symbols '''
    def __init__(self, symbol_id, old_pos, new_pos, animate=False):
        super(MoveSymbol, self).__init__()
        self.setText('Move symbol')
        self.symbol = symbol_id
        self.old_pos = old_pos
        self.new_pos = new_pos
        if animate:
            self.animation = QPropertyAnimation(self.symbol, "position")
            self.animation.setDuration(500)
            self.animation.setStartValue(self.old_pos)
            self.animation.setEndValue(self.new_pos)
            self.animation.setEasingCurve(QEasingCurve.OutCirc)

    def undo(self):
        ''' Undo a symbol move '''
        self.symbol.position = self.old_pos
        try:
            self.symbol.decisionParent.updateConnectionPointPosition()
        except AttributeError:
            pass

    def redo(self):
        ''' Apply a symbol move '''
        try:
            self.animation.start()
        except AttributeError:
            self.symbol.position = self.new_pos
        try:
            self.symbol.decisionParent.updateConnectionPointPosition()
        except AttributeError:
            pass
예제 #3
0
 def createPositionAnimation(self, item, duration):
     ani = QPropertyAnimation(item, b'pos', self)
     ani.setDuration(duration)
     ani.setStartValue(item.pos())
     width = self.squareWidth * 7
     ani.setEndValue(QPointF(width - item.x(),
                             width - item.y()))
     return ani
예제 #4
0
    def createAnimation(self, target, index):
        '''创建动画'''
        # 暂停动画一
        PauseAnimation1 = QPauseAnimation(target)
        PauseAnimation1.setDuration(150 * index)

        # 并行动画组一
        # #透明度动画一
        OpacityAnimation1 = QPropertyAnimation(target, b"opacity")
        OpacityAnimation1.setDuration(400)
        OpacityAnimation1.setStartValue(0)
        OpacityAnimation1.setEndValue(1)
        # #移动动画一
        MoveAnimation1 = _MoveAnimation(target, self.parent, self.easing)
        MoveAnimation1.setMoveType(_MoveAnimation.MOVE1)
        MoveAnimation1.setDuration(400)
        MoveAnimation1.setStartValue(QPoint(0, 0))
        MoveAnimation1.setEndValue(QPoint(self.parent.width() / 4.0, 0))
        # 添加到并行动画里面
        ParallelAnimation1 = QParallelAnimationGroup()
        ParallelAnimation1.addAnimation(OpacityAnimation1)
        ParallelAnimation1.addAnimation(MoveAnimation1)

        # 移动动画二
        MoveAnimation2 = _MoveAnimation(target, self.parent, self.easing)
        MoveAnimation2.setMoveType(_MoveAnimation.MOVE2)
        MoveAnimation2.setDuration(2000)
        MoveAnimation2.setEndValue(QPoint((self.parent.width() / 4.0) * 3.0, 0))

        # 并行动画组二
        # #透明度动画二
        OpacityAnimation2 = QPropertyAnimation(target, b"opacity")
        OpacityAnimation2.setDuration(400)
        OpacityAnimation2.setStartValue(1)
        OpacityAnimation2.setEndValue(0)
        # #移动动画三
        MoveAnimation3 = _MoveAnimation(target, self.parent, self.easing)
        MoveAnimation3.setMoveType(_MoveAnimation.MOVE3)
        MoveAnimation3.setDuration(400)
        MoveAnimation3.setEndValue(QPoint(self.parent.width(), 0))
        # 添加到并行动画里面
        ParallelAnimation2 = QParallelAnimationGroup()
        ParallelAnimation2.addAnimation(OpacityAnimation2)
        ParallelAnimation2.addAnimation(MoveAnimation3)

        # 暂停动画二
        PauseAnimation2 = QPauseAnimation(target)
        PauseAnimation2.setDuration(150 * (5 - index - 1))

        # 串行动画组
        self.setLoopCount(-1)    # 无限循环
        self.addAnimation(PauseAnimation1)
        self.addAnimation(ParallelAnimation1)
        self.addAnimation(MoveAnimation2)
        self.addAnimation(ParallelAnimation2)
        self.addAnimation(PauseAnimation2)
예제 #5
0
    def __init__(self):
        super(Robot, self).__init__()

        self.setFlag(self.ItemHasNoContents)

        self.torsoItem = RobotTorso(self)
        self.headItem = RobotHead(self.torsoItem)
        self.upperLeftArmItem = RobotLimb(self.torsoItem)
        self.lowerLeftArmItem = RobotLimb(self.upperLeftArmItem)
        self.upperRightArmItem = RobotLimb(self.torsoItem)
        self.lowerRightArmItem = RobotLimb(self.upperRightArmItem)
        self.upperRightLegItem = RobotLimb(self.torsoItem)
        self.lowerRightLegItem = RobotLimb(self.upperRightLegItem)
        self.upperLeftLegItem = RobotLimb(self.torsoItem)
        self.lowerLeftLegItem = RobotLimb(self.upperLeftLegItem)

        settings = (
            #    Item                       Position        Rotation  Scale
            #                                x     y    start    end
            (self.headItem, 0, -18, 20, -20, 1.1),
            (self.upperLeftArmItem, -15, -10, 190, 180, 0),
            (self.lowerLeftArmItem, 30, 0, 50, 10, 0),
            (self.upperRightArmItem, 15, -10, 300, 310, 0),
            (self.lowerRightArmItem, 30, 0, 0, -70, 0),
            (self.upperRightLegItem, 10, 32, 40, 120, 0),
            (self.lowerRightLegItem, 30, 0, 10, 50, 0),
            (self.upperLeftLegItem, -10, 32, 150, 80, 0),
            (self.lowerLeftLegItem, 30, 0, 70, 10, 0),
            (self.torsoItem, 0, 0, 5, -20, 0),
        )

        animation = QParallelAnimationGroup(self)
        for item, pos_x, pos_y, start_rot, end_rot, scale in settings:
            item.setPos(pos_x, pos_y)

            rot_animation = QPropertyAnimation(item, b"rotation")
            rot_animation.setStartValue(start_rot)
            rot_animation.setEndValue(end_rot)
            rot_animation.setEasingCurve(QEasingCurve.SineCurve)
            rot_animation.setDuration(2000)
            animation.addAnimation(rot_animation)

            if scale > 0:
                scale_animation = QPropertyAnimation(item, b"scale")
                scale_animation.setEndValue(scale)
                scale_animation.setEasingCurve(QEasingCurve.SineCurve)
                scale_animation.setDuration(2000)
                animation.addAnimation(scale_animation)

        animation.setLoopCount(-1)
        animation.start()
예제 #6
0
class CircleObstruction(QColorThemedGraphicsObject):
    """
    Useful for notifications, I...guess?
    """
    def get_thickness(self):
        return self._thickness
    def set_thickness(self,c):
        self._thickness = c
        self.update()
    thickness = pyqtProperty(float, get_thickness, set_thickness)
    def __init__(self, sz, thickness, parent=None):
        super(CircleObstruction, self).__init__(parent)
        self._sz = sz
        self._thickness = thickness
        self._color = Qt.blue
    def boundingRect(self):
        return QRectF(-self._thickness,
                      -self._thickness,
                      self._sz + 2*self._thickness,
                      self._sz + 2*self._thickness)

    def paint(self, painter, option, widget):
        # painter.setPen(QPen(self._color,
        #                     self._thickness))
        painter.setBrush(self._color)
        painter.setPen(Qt.NoPen)
        painter.drawEllipse(QRectF(
            self._sz/2.0 - self._thickness,
            self._sz/2.0 - self._thickness,
            2*self._thickness,
            2*self._thickness,
        ))
    def show_anim(self):
        self.anim = QPropertyAnimation(self, "thickness")
        self.anim.setDuration(2000)
        self.anim.setStartValue(self.get_thickness())
        self.anim.setEndValue(50.0)
        self.anim.setEasingCurve(QEasingCurve.OutElastic)
        self.anim.start()
    def hide_anim(self):
        self.anim = QPropertyAnimation(self, "thickness")
        self.anim.setDuration(500)
        self.anim.setStartValue(self.get_thickness())
        self.anim.setEndValue(0.0)
        self.anim.setEasingCurve(QEasingCurve.InBack)
        self.anim.start()
예제 #7
0
파일: notify.py 프로젝트: ykelvis/FeelUOwn
class NotifyWidget(QWidget):
    def __init__(self):
        super().__init__()

        self.layout = QVBoxLayout(self)

        self.sub_widget = _NotifySubWidget(self)
        self.layout.addWidget(self.sub_widget)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self._exit_shortcut = QShortcut(QKeySequence(Qt.Key_Escape), self)
        self._exit_shortcut.activated.connect(self.close)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_MacAlwaysShowToolWindow)

        self.resize(width, height)
        self.move(QApplication.desktop().width() - self.width() - 20, 40)
        self.setLayout(self.layout)

        self._animation = QPropertyAnimation(self, b'windowOpacity')
        self._animation.setStartValue(0.8)
        self._animation.setKeyValueAt(0.4, 1)
        self._animation.setEndValue(0)
        self._animation.setDuration(5000)
        self._animation.finished.connect(self.close)

    def show(self):
        super().show()
        self._animation.start()

    def show_message(self, title, content, pixmap=None):
        if not self.isVisible():
            self.show()
        self._animation.stop()
        self._animation.setCurrentTime(0)
        self._animation.start()
        self.sub_widget.set_title(title)
        self.sub_widget.set_content(content)
        pixmap = pixmap if pixmap else QPixmap(WINDOW_ICON)
        self.sub_widget.set_pixmap(pixmap)

    def enterEvent(self, event):
        self._animation.setCurrentTime(0)
예제 #8
0
    def animate(self, item, property_name, duration, start_value, end_value):
        """Summary

        Args:
            item (TYPE): Description
            property_name (TYPE): Description
            duration (TYPE): Description
            start_value (TYPE): Description
            end_value (TYPE): Description
        """
        if item is not None:
            b_name = property_name.encode('ascii')
            anim = QPropertyAnimation(item.adapter, b_name)
            anim.setDuration(duration)
            anim.setStartValue(start_value)
            anim.setEndValue(end_value)
            anim.start()
            item.adapter.saveRef(property_name, anim)
예제 #9
0
    def addRemovalAnimation(self, animGroup):
#        print(">>RemoveAnim")
        for phIdx in self.photoIdxsToRemove:
            item = self.photosInGrid[phIdx]
            anim = QPropertyAnimation(item.pixmap, "scale")
            anim.setDuration(self.shrinkDuration)
            anim.setEasingCurve(QEasingCurve.Linear)
            anim.setStartValue(1.0)
            anim.setEndValue(0.0)
            animGroup.addAnimation(anim)
            anim = QPropertyAnimation(item.pixmap, "pos")
            anim.setDuration(self.shrinkDuration)
            anim.setEasingCurve(QEasingCurve.Linear)
            startCoords = self.getCellTLCoords(item.gridRow, item.gridCol)
            endCoords = QPointF(startCoords.x()+self.cellSize.width()*item.xFactor, startCoords.y() + item.pixmap.pixmapSize.height() / 2)
            anim.setStartValue(startCoords)
            anim.setEndValue(endCoords)
            animGroup.addAnimation(anim)
예제 #10
0
    def addInsertionAnimation(self, animGroup):
        # Animation for added
#        print(">>>InsAnim")
        for ph in self.picItemsToAdd:
            # Set pixmap start location
            newPixmap = ph[0].pixmap
            row = ph[1]
            col = ph[2]
            xFact = ph[0].xFactor
            endCoords = self.getCellTLCoords(row, col)
            startCoords = QPointF(endCoords.x()-self.cellSize.width()*xFact, endCoords.y())
            newPixmap.pixmap_item.setPos(startCoords)
            newPixmap.pixmap_item.setVisible(True)
            # Animate in
            anim = QPropertyAnimation(newPixmap, "pos")
            anim.setDuration(self.insertDuration)
            anim.setStartValue(startCoords)
            anim.setEasingCurve(QEasingCurve.Linear)
            anim.setEndValue(endCoords)
            animGroup.addAnimation(anim)
예제 #11
0
 def animate(self, item: QGraphicsItem,
                 property_name: str, duration: int,
                 start_value, end_value):
     """
     Args:
         item: Description
         property_name: Description
         duration: Description
         start_value (QVariant): Description
         end_value (QVariant): Description
     """
     b_name = property_name.encode('ascii')
     anim = item.adapter.getRef(property_name)
     if anim is None:
         anim = QPropertyAnimation(item.adapter, b_name)
         item.adapter.saveRef(property_name, anim)
     anim.setDuration(duration)
     anim.setStartValue(start_value)
     anim.setEndValue(end_value)
     anim.start()
예제 #12
0
class ChannelListItem(QWidget):
    """
    This class is responsible for managing the item in the list of channels.
    The list item supports a fade-in effect, which can be enabled with the should_fade parameter in the constructor.
    """

    def __init__(self, parent, channel, fade_delay=0, should_fade=False):
        super(QWidget, self).__init__(parent)

        uic.loadUi('qt_resources/channel_list_item.ui', self)

        self.channel_name.setText(channel["name"])
        self.channel_description_label.setText("Active 6 days ago • %d items" % channel["torrents"])
        self.channel_num_subs_label.setText(str(channel["votes"]))
        if channel["sub"]:
            self.channel_subscribe_button.setText("✓ subscribed")
        else:
            self.channel_subscribe_button.setText("subscribe")

        if should_fade:
            self.opacity_effect = QGraphicsOpacityEffect(self)
            self.opacity_effect.setOpacity(0)
            self.setGraphicsEffect(self.opacity_effect)

            self.timer = QTimer()
            self.timer.setInterval(fade_delay)
            self.timer.timeout.connect(self.fadeIn)
            self.timer.start()

    def fadeIn(self):
        self.anim = QPropertyAnimation(self.opacity_effect, 'opacity')
        self.anim.setDuration(800)
        self.anim.setStartValue(0)
        self.anim.setEndValue(1)
        self.anim.start()
        self.timer.stop()
예제 #13
0
class FlipWidget(QWidget):
    Left = 0  # 从右往左
    Right = 1  # 从左往右
    Scale = 3  # 图片缩放比例
    finished = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(FlipWidget, self).__init__(*args, **kwargs)
        # 无边框无任务栏
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint
                            | Qt.SubWindow)
        # 背景透明
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        # 翻转角度
        self._angle = 0
        # 属性动画针对自定义属性`angle`
        self._animation = QPropertyAnimation(self, b'angle', self)
        self._animation.setDuration(550)
        self._animation.setEasingCurve(QEasingCurve.OutInQuad)
        self._animation.finished.connect(self.finished.emit)

    @pyqtProperty(int)
    def angle(self):
        return self._angle

    @angle.setter
    def angle(self, angle):
        self._angle = angle
        self.update()

    def updateImages(self, direction, image1, image2):
        """设置两张切换图
        :param direction:        方向
        :param image1:           图片1
        :param image2:           图片2
        """
        self.image1 = image1
        self.image2 = image2
        self.show()
        self._angle = 0
        # 根据方向设置动画的初始和结束值
        if direction == self.Right:
            self._animation.setStartValue(1)
            self._animation.setEndValue(-180)
        elif direction == self.Left:
            self._animation.setStartValue(1)
            self._animation.setEndValue(180)
        self._animation.start()

    def paintEvent(self, event):
        super(FlipWidget, self).paintEvent(event)

        if hasattr(self, 'image1') and hasattr(self,
                                               'image2') and self.isVisible():

            painter = QPainter(self)
            painter.setRenderHint(QPainter.Antialiasing, True)
            painter.setRenderHint(QPainter.SmoothPixmapTransform, True)

            # 变换
            transform = QTransform()
            # 把圆心设置为矩形中心
            transform.translate(self.width() / 2, self.height() / 2)

            if self._angle >= -90 and self._angle <= 90:
                # 当翻转角度在90范围内显示第一张图,且从大图缩放到小图的过程
                painter.save()
                # 设置翻转角度
                transform.rotate(self._angle, Qt.YAxis)
                painter.setTransform(transform)
                # 缩放图片高度
                width = self.image1.width() / 2
                height = int(self.image1.height() *
                             (1 - abs(self._angle / self.Scale) / 100))
                image = self.image1.scaled(self.image1.width(), height,
                                           Qt.IgnoreAspectRatio,
                                           Qt.SmoothTransformation)
                painter.drawPixmap(QPointF(-width, -height / 2), image)
                painter.restore()
            else:
                # 当翻转角度在90范围内显示第二张图,且从小图缩放到原图的过程
                painter.save()
                if self._angle > 0:
                    angle = 180 + self._angle
                else:
                    angle = self._angle - 180
                # 设置翻转角度, 注意这里角度有差异
                transform.rotate(angle, Qt.YAxis)
                painter.setTransform(transform)
                # 缩放图片高度
                width = self.image2.width() / 2
                height = int(self.image2.height() *
                             (1 - ((360 - abs(angle)) / self.Scale / 100)))
                image = self.image2.scaled(self.image2.width(), height,
                                           Qt.IgnoreAspectRatio,
                                           Qt.SmoothTransformation)
                painter.drawPixmap(QPointF(-width, -height / 2), image)
                painter.restore()
예제 #14
0
class CurrencyCov(QtWidgets.QMainWindow):
    def __init__(self):
        super(CurrencyCov, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init_UI()

    def init_UI(self):

        self.ui.input_amount.setValidator(QtGui.QDoubleValidator())

        self.setWindowTitle("Конвертер валют")
        self.setFixedSize(1068, 732)

        self.ui.convert_slide_btn.clicked.connect(self.convert_page_show)
        self.ui.history_slide_btn.clicked.connect(self.history_page_show)

        self.ui.pushButton.clicked.connect(self.slide_bar)

        self.ui.input_amount.setPlaceholderText("Cума:")
        self.ui.convert_button.clicked.connect(self.converter)

        with open("data.txt", "r") as data:
            for i in data:
                self.ui.history_listWidget.addItem(i)

    def slide_bar(self):
        width = self.ui.left_side_menu.width()

        if width == 70:
            newWidth = 220
            self.ui.convert_slide_btn.setStyleSheet("padding-left:0;")
            self.ui.history_slide_btn.setStyleSheet("padding-left:0;")
        else:
            newWidth = 70
            self.ui.convert_slide_btn.setStyleSheet("padding-left:110;")
            self.ui.history_slide_btn.setStyleSheet("padding-left:110;")

        self.animation = QPropertyAnimation(self.ui.left_side_menu,
                                            b"minimumWidth")
        self.animation.setDuration(200)
        self.animation.setStartValue(width)
        self.animation.setEndValue(newWidth)
        self.animation.setEasingCurve(QtCore.QEasingCurve.InOutQuart)

        self.animation.start()

    def convert_page_show(self):
        self.ui.stackedWidget.setCurrentWidget(self.ui.convert_page)

    def history_page_show(self):
        self.ui.stackedWidget.setCurrentWidget(self.ui.history_page)

    def readFile(self):
        f = open("data.txt", "r")
        lineList = f.readlines()
        f.close()
        self.ui.history_listWidget.addItem(lineList[-1])

    def converter(self):

        c = CurrencyConverter()
        if self.ui.input_amount.text():
            input_amount = float(self.ui.input_amount.text())

            input_currency = self.ui.input_currency.currentText()
            output_currency = self.ui.output_currency.currentText()
            amount = input_amount = float(self.ui.input_amount.text())

            if input_currency != 'USD':
                input_amount = round(input_amount / currencies[input_currency],
                                     2)

            output_result = round(input_amount * currencies[output_currency],
                                  2)
            self.ui.result_label.setText(
                str(amount) + " " + str(input_currency) + " = " +
                str(output_result) + " " + str(output_currency))

            f = open("data.txt", "a")
            f.write(
                str(input_amount) + " " + str(input_currency) + " -> " +
                str(output_result) + " " + str(output_currency) + "\n")
            f.close()

        self.readFile()
예제 #15
0
class Preferences(QDialog):
    # Signal to warn that the window is closed
    settingsClosed = pyqtSignal()

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

        # Main container
        # This contains a grid
        main_box = QVBoxLayout(self)
        main_box.setContentsMargins(200, 50, 200, 100)

        # The grid contains two containers
        # left container and right container
        grid = QGridLayout()

        # Left Container
        left_container = QVBoxLayout()
        left_container.setContentsMargins(0, 0, 0, 0)

        # General
        group_gral = QGroupBox(self.tr("General"))
        box_gral = QVBoxLayout(group_gral)
        # Updates
        btn_updates = QPushButton(self.tr("Check for updates"))
        box_gral.addWidget(btn_updates)
        # Language
        group_language = QGroupBox(self.tr("Language"))
        box = QVBoxLayout(group_language)
        # Find .qm files in language path
        available_langs = file_manager.get_files_from_folder(
            settings.LANGUAGE_PATH)

        languages = ["English"] + available_langs
        self._combo_lang = QComboBox()
        box.addWidget(self._combo_lang)
        self._combo_lang.addItems(languages)
        self._combo_lang.currentIndexChanged[int].connect(
            self._change_lang)
        if PSetting.LANGUAGE:
            self._combo_lang.setCurrentText(PSetting.LANGUAGE)
        box.addWidget(QLabel(self.tr("(Requires restart)")))

        # Add widgets
        left_container.addWidget(group_gral)
        left_container.addWidget(group_language)
        left_container.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding,
                                           QSizePolicy.Expanding))

        # Right Container
        right_container = QVBoxLayout()
        right_container.setContentsMargins(0, 0, 0, 0)

        # Editor
        editor_group = QGroupBox(self.tr("Editor Configurations"))
        box_editor = QHBoxLayout(editor_group)
        # Current line
        self._highlight_current_line = QCheckBox(
            self.tr("Highlight Current Line"))
        self._highlight_current_line.setChecked(
            PSetting.HIGHLIGHT_CURRENT_LINE)
        self._highlight_current_line.stateChanged[int].connect(
            self.__current_line_value_changed)
        box_editor.addWidget(self._highlight_current_line)
        # Matching paren
        self._matching_paren = QCheckBox(self.tr("Matching Parenthesis"))
        self._matching_paren.setChecked(
            PSetting.MATCHING_PARENTHESIS)
        self._matching_paren.stateChanged[int].connect(
            self.__set_enabled_matching_parenthesis)
        box_editor.addWidget(self._matching_paren)
        # Font group
        font_group = QGroupBox(self.tr("Font"))
        font_grid = QGridLayout(font_group)
        font_grid.addWidget(QLabel(self.tr("Family")), 0, 0)
        self._combo_font = QFontComboBox()
        self._combo_font.setCurrentFont(PSetting.FONT)
        font_grid.addWidget(self._combo_font, 0, 1)
        font_grid.addWidget(QLabel(self.tr("Point Size")), 1, 0)
        self._combo_font_size = QComboBox()
        fdb = QFontDatabase()
        combo_sizes = fdb.pointSizes(PSetting.FONT.family())
        current_size_index = combo_sizes.index(
            PSetting.FONT.pointSize())

        self._combo_font_size.addItems([str(f) for f in combo_sizes])
        self._combo_font_size.setCurrentIndex(current_size_index)
        font_grid.addWidget(self._combo_font_size, 1, 1)

        right_container.addWidget(editor_group)
        right_container.addWidget(font_group)
        right_container.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding,
                                            QSizePolicy.Expanding))

        # Add widgets
        grid.addLayout(left_container, 0, 0)
        grid.addLayout(right_container, 0, 1)
        main_box.addLayout(grid)

        # Button close and reset
        hbox = QHBoxLayout()
        hbox.setSpacing(20)
        hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        btn_cancel = QPushButton(self.tr("Back"))
        hbox.addWidget(btn_cancel)
        btn_reset = QPushButton(self.tr("Reset Configurations"))
        hbox.addWidget(btn_reset)
        main_box.addLayout(hbox)

        # Overlay
        self.overlay = overlay_widget.OverlayWidget(self)
        self.overlay.hide()

        # Effect and animations
        self.effect = QGraphicsOpacityEffect()
        self.setGraphicsEffect(self.effect)
        duration, x = 180, 150  # Animation duration
        # Animation start
        # Opacity animation
        self.opacity_animation_s = QPropertyAnimation(self.effect, b"opacity")
        self.opacity_animation_s.setDuration(duration)
        self.opacity_animation_s.setStartValue(0.0)
        self.opacity_animation_s.setEndValue(1.0)
        # X animation
        self.x_animation_s = QPropertyAnimation(self, b"geometry")
        self.x_animation_s.setDuration(duration)
        self.x_animation_s.setStartValue(QRect(x, 0, parent.width(),
                                               parent.height()))
        self.x_animation_s.setEndValue(QRect(0, 0, parent.width(),
                                             parent.height()))
        # Animation end
        # Opacity animation
        self.opacity_animation_e = QPropertyAnimation(self.effect, b"opacity")
        self.opacity_animation_e.setDuration(duration)
        self.opacity_animation_e.setStartValue(1.0)
        self.opacity_animation_e.setEndValue(0.0)
        # X animation
        self.x_animation_e = QPropertyAnimation(self, b"geometry")
        self.x_animation_e.setDuration(duration)
        self.x_animation_e.setStartValue(QRect(0, 0, parent.width(),
                                               parent.height()))
        self.x_animation_e.setEndValue(QRect(-x, 0, parent.width(),
                                             parent.height()))

        # Group animation start
        self.group_animation_s = QParallelAnimationGroup()
        self.group_animation_s.addAnimation(self.opacity_animation_s)
        self.group_animation_s.addAnimation(self.x_animation_s)

        # Group animation end
        self.group_animation_e = QParallelAnimationGroup()
        self.group_animation_e.addAnimation(self.opacity_animation_e)
        self.group_animation_e.addAnimation(self.x_animation_e)

        # Connections
        self.group_animation_e.finished.connect(
            self._on_group_animation_finished)
        btn_cancel.clicked.connect(self.close)
        btn_reset.clicked.connect(self._reset_settings)
        btn_updates.clicked.connect(self._check_for_updates)
        # self.thread.finished.connect(self._on_thread_finished)
        self._combo_font.currentFontChanged.connect(
            self._change_font)
        self._combo_font_size.currentTextChanged.connect(
            self._change_font_size)

    def __current_line_value_changed(self, value):
        qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
        qs.setValue('highlight_current_line', value)
        PSetting.HIGHLIGHT_CURRENT_LINE = value

    def __set_enabled_matching_parenthesis(self, value):
        qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
        qs.setValue("matching_parenthesis", value)
        PSetting.MATCHING_PARENTHESIS = value

    def _change_font(self, font):
        # FIXME: un quilombo esto
        central = Pireal.get_service("central")
        mcontainer = central.get_active_db()
        if mcontainer is not None:
            query_widget = mcontainer.query_container.currentWidget()
            if query_widget is not None:
                weditor = query_widget.get_editor()
                if weditor is not None:
                    qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
                    weditor.set_font(font)
                    qs.setValue("font", font)

    def _change_font_size(self, size):
        # FIXME: un quilombo esto
        font = self._combo_font.currentFont()
        font.setPointSize(int(size))
        central = Pireal.get_service("central")
        mcontainer = central.get_active_db()
        if mcontainer is not None:
            query_widget = mcontainer.query_container.currentWidget()
            if query_widget is not None:
                weditor = query_widget.get_editor()
                if weditor is not None:
                    qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
                    weditor.set_font(font)
                    qs.setValue("font", font)

    def showEvent(self, event):
        super(Preferences, self).showEvent(event)
        self.group_animation_s.start()

    def resizeEvent(self, event):
        self.overlay.resize(self.size())
        event.accept()

    def done(self, result):
        self.res = result
        self.group_animation_e.start()

    def _on_group_animation_finished(self):
        super(Preferences, self).done(self.res)
        self.settingsClosed.emit()

    def _check_for_updates(self):
        # Thread
        self._thread = QThread()
        self._updater = updater.Updater()
        self._updater.moveToThread(self._thread)
        self._thread.started.connect(self._updater.check_updates)
        self._updater.finished.connect(self.__on_thread_update_finished)
        # Show overlay widget
        self.overlay.show()
        # Start thread
        self._thread.start()

    def __on_thread_update_finished(self):
        # Hide overlay widget
        self.overlay.hide()
        self._thread.quit()
        msg = QMessageBox(self)
        if not self._updater.error:
            if self._updater.version:
                version = self._updater.version
                msg.setWindowTitle(self.tr("New version available!"))
                msg.setText(self.tr("Check the web site to "
                                    "download <b>Pireal {}</b>".format(
                                        version)))
                download_btn = msg.addButton(self.tr("Download!"),
                                             QMessageBox.YesRole)
                msg.addButton(self.tr("Cancel"),
                              QMessageBox.RejectRole)
                msg.exec_()
                r = msg.clickedButton()
                if r == download_btn:
                    webbrowser.open_new(
                        "http://centaurialpha.github.io/pireal")
            else:
                msg.setWindowTitle(self.tr("Information"))
                msg.setText(self.tr("Last version installed"))
                msg.addButton(self.tr("Ok"),
                              QMessageBox.AcceptRole)
                msg.exec_()
        else:
            msg.critical(self, self.tr("Error"),
                         self.tr("Connection error"))

        self._thread.deleteLater()
        self._updater.deleteLater()

    def _reset_settings(self):
        """ Remove all settings """

        msg = QMessageBox(self)
        msg.setWindowTitle(self.tr("Reset Settings"))
        msg.setText(self.tr("Are you sure you want to clear all settings?"))
        msg.setIcon(QMessageBox.Question)
        msg.addButton(self.tr("No"), QMessageBox.NoRole)
        yes_btn = msg.addButton(self.tr("Yes"),
                                QMessageBox.YesRole)
        msg.exec_()
        r = msg.clickedButton()
        if r == yes_btn:
            QSettings(settings.SETTINGS_PATH, QSettings.IniFormat).clear()
            self.close()

    def _change_lang(self, index):
        lang = self._combo_lang.itemText(index)
        qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
        qs.setValue('language', lang)
예제 #16
0
class MiniMap(QPlainTextEdit):

    def __init__(self, parent):
        super(MiniMap, self).__init__(parent)
        self.setWordWrapMode(QTextOption.NoWrap)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setReadOnly(True)
        self.setCenterOnScroll(True)
        self.setMouseTracking(True)
        self.viewport().setCursor(Qt.PointingHandCursor)
        self.setTextInteractionFlags(Qt.NoTextInteraction)

        self._parent = parent
        self.highlighter = None
        self.lines_count = 0

        if ACTIVATE_OPACITY:
            self.goe = QGraphicsOpacityEffect()
            self.setGraphicsEffect(self.goe)
            self.goe.setOpacity(settings.MINIMAP_MIN_OPACITY)
            self.animation = QPropertyAnimation(self.goe, b"opacity")

        self.slider = SliderArea(self)
        self.slider.show()

    def __calculate_max(self):
        line_height = self._parent.cursorRect().height()
        if line_height > 0:
            self.lines_count = self._parent.viewport().height() / line_height
        self.slider.update_position()
        self.update_visible_area()

    def set_code(self, source):
        self.setPlainText(source)
        self.__calculate_max()

    def adjust_to_parent(self):
        self.setFixedHeight(self._parent.height())
        self.setFixedWidth(self._parent.width() * settings.SIZE_PROPORTION)
        x = self._parent.width() - self.width()
        self.move(x, 0)
        fontsize = int(self.width() / settings.MARGIN_LINE)
        if fontsize < 1:
            fontsize = 1
        font = self.document().defaultFont()
        font.setPointSize(fontsize)
        self.setFont(font)
        self.__calculate_max()

    def update_visible_area(self):
        if not self.slider.pressed:
            line_number = self._parent.firstVisibleBlock().blockNumber()
            block = self.document().findBlockByLineNumber(line_number)
            cursor = self.textCursor()
            cursor.setPosition(block.position())
            rect = self.cursorRect(cursor)
            self.setTextCursor(cursor)
            self.slider.move_slider(rect.y())

    def enterEvent(self, event):
        if ACTIVATE_OPACITY:
            self.animation.setDuration(300)
            self.animation.setStartValue(settings.MINIMAP_MIN_OPACITY)
            self.animation.setEndValue(settings.MINIMAP_MAX_OPACITY)
            self.animation.start()

    def leaveEvent(self, event):
        if ACTIVATE_OPACITY:
            self.animation.setDuration(300)
            self.animation.setStartValue(settings.MINIMAP_MAX_OPACITY)
            self.animation.setEndValue(settings.MINIMAP_MIN_OPACITY)
            self.animation.start()

    def mousePressEvent(self, event):
        super(MiniMap, self).mousePressEvent(event)
        cursor = self.cursorForPosition(event.pos())
        self._parent.jump_to_line(cursor.blockNumber())

    def resizeEvent(self, event):
        super(MiniMap, self).resizeEvent(event)
        self.slider.update_position()

    def scroll_area(self, pos_parent, pos_slider):
        pos_parent.setY(pos_parent.y() - pos_slider.y())
        cursor = self.cursorForPosition(pos_parent)
        self._parent.verticalScrollBar().setValue(cursor.blockNumber())

    def wheelEvent(self, event):
        super(MiniMap, self).wheelEvent(event)
        self._parent.wheelEvent(event)
예제 #17
0
class PlayGround(MFrame):
    def __init__(self, parent=None):
        super(PlayGround, self).__init__(parent)

        # 效果
        self.shadow_effect = None
        self.shadow_animation = None
        # 控件
        self.top_bar = None
        self.line_label = None
        self.view_box = None
        self.setup_ui()

    def setup_ui(self):
        shadow_effect = QGraphicsDropShadowEffect()
        shadow_effect.setBlurRadius(1)
        shadow_effect.setColor(QColor(200, 200, 200))
        shadow_effect.setOffset(0, 0)
        self.shadow_effect = shadow_effect
        self.setGraphicsEffect(self.shadow_effect)
        self.setStyleSheet(
            "MFrame{margin:0px;padding:0px;border:1px solid;"
            "border-color:rgb(220,220,220);background-color:white}")
        self.setGeometry(100, 100, 1366, 768)
        self.top_bar = MFrame(self)
        self.top_bar.setGeometry(0, 0, 1366, 80)

        font_id = QFontDatabase.addApplicationFont(
            "font/Roboto-Regular-14.ttf")
        font_name = QFontDatabase.applicationFontFamilies(font_id)[0]
        font = QFont(font_name, 14, 1)
        config_label = QLabel("Configuration", self.top_bar)
        config_label.setGeometry(1030, 1, 150, 78)
        config_label.setStyleSheet("color: rgb(100, 100, 100)")
        config_label.setFont(font)

        self.line_label = QLabel(self.top_bar)
        self.line_label.setStyleSheet("background-color:rgb(80, 80, 80)")
        self.line_label.setGeometry(50, 76, 200, 4)

        view_box = MFrame(self)
        view_box.setGeometry(0, 80, 1000, 688)
        view_box.setStyleSheet("border-top:none;background-color:#fafafa")
        self.view_box = view_box
        self.fillViewBox()

        self.buildupTopBtns()
        self.line_label.raise_()

        options = MFrame(self)
        options.setGeometry(1000, 80, 366, 688)
        options.setStyleSheet("border-top:none;border-left:none;")

        option_label = QLabel("Options", options)
        option_label.setGeometry(30, 30, 150, 60)
        font = QFont(font_name, 13, 1)
        option_label.setStyleSheet("color: rgb(100, 100, 100)")
        option_label.setFont(font)

        self.shadow_animation = QPropertyAnimation(self)
        self.shadow_animation.setTargetObject(self.shadow_effect)
        self.shadow_animation.setPropertyName(b"blurRadius")
        self.shadow_animation.setStartValue(1)
        self.shadow_animation.setEndValue(40)
        self.shadow_animation.setDuration(500)

    def buildupTopBtns(self):
        pass

    def buildupOptions(self):
        pass

    def fillViewBox(self):
        pass

    def moveSlider(self):
        animation = QPropertyAnimation(self)
        animation.setTargetObject(self.line_label)
        animation.setPropertyName(b"geometry")
        animation.setStartValue(self.line_label.geometry())
        geo = self.sender().geometry()
        animation.setEndValue(QRect(geo.x(), 76, geo.width(), 4))
        animation.setDuration(200)
        animation.start()

    def enterEvent(self, Qevent):
        self.shadow_animation.start()

    def leaveEvent(self, Qevent):
        self.shadow_animation.stop()
        self.shadow_effect.setBlurRadius(1)
예제 #18
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(364, 371)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.MusicPlayerFrame = QtWidgets.QFrame(self.centralwidget)
        self.MusicPlayerFrame.setGeometry(QtCore.QRect(10, 10, 311, 281))
        self.MusicPlayerFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.MusicPlayerFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.MusicPlayerFrame.setObjectName("MusicPlayerFrame")
        self.AlbumPhoto = QtWidgets.QGraphicsView(self.MusicPlayerFrame)
        self.AlbumPhoto.setGeometry(QtCore.QRect(40, 10, 231, 192))
        self.AlbumPhoto.setObjectName("AlbumPhoto")
        self.songSlider = QtWidgets.QSlider(self.MusicPlayerFrame)
        self.songSlider.setGeometry(QtCore.QRect(39, 210, 231, 20))
        self.songSlider.setOrientation(QtCore.Qt.Horizontal)
        self.songSlider.setObjectName("songSlider")
        self.centerButton = QtWidgets.QPushButton(self.MusicPlayerFrame)
        self.centerButton.setGeometry(QtCore.QRect(140, 240, 31, 31))
        self.centerButton.setObjectName("centerButton")
        self.LeftButton = QtWidgets.QPushButton(self.MusicPlayerFrame)
        self.LeftButton.setGeometry(QtCore.QRect(80, 240, 31, 31))
        self.LeftButton.setObjectName("LeftButton")
        self.RightButton = QtWidgets.QPushButton(self.MusicPlayerFrame)
        self.RightButton.setGeometry(QtCore.QRect(200, 240, 31, 31))
        self.RightButton.setObjectName("RightButton")
        self.songCurrentTime = QtWidgets.QLabel(self.MusicPlayerFrame)
        self.songCurrentTime.setGeometry(QtCore.QRect(10, 210, 31, 16))
        self.songCurrentTime.setObjectName("songCurrentTime")
        self.songTotalTime = QtWidgets.QLabel(self.MusicPlayerFrame)
        self.songTotalTime.setGeometry(QtCore.QRect(280, 210, 31, 16))
        self.songTotalTime.setObjectName("songTotalTime")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 364, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.centerButton.clicked.connect(self.animateFrame)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.centerButton.setText(_translate("MainWindow", "||"))
        self.LeftButton.setText(_translate("MainWindow", "<<"))
        self.RightButton.setText(_translate("MainWindow", ">>"))
        self.songCurrentTime.setText(_translate("MainWindow", "--:--"))
        self.songTotalTime.setText(_translate("MainWindow", "--:--"))

    def playSong(self):
        pygame.mixer.init(48000)
        pygame.mixer.music.load('CakeByOcean.mp3')
        pygame.mixer.music.play()

    def sleeptime(self):
        time.sleep(1)
        self.MusicPlayerFrame.hide()
        time.sleep(1)
        self.MusicPlayerFrame.show()

    def animateFrame(self):

        self.anim = QPropertyAnimation(self.MusicPlayerFrame, b"geometry")
        self.anim.setDuration(1000)  #time in miliseconds
        self.anim.setStartValue(QRect(0, 0, 311, 281))
        self.anim.setEndValue(QRect(0, 900, 500, 500))
        self.anim.start()
        threading.Thread(target=self.sleeptime).start()
예제 #19
0
class Button(QGraphicsObject):
    font: QFont = QFont("monospace", 16)

    clicked = pyqtSignal('PyQt_PyObject')
    hovered_ = pyqtSignal('PyQt_PyObject')

    def __init__(self, btn_id: str, label: str, tooltip: str = "", parent: QGraphicsItem = None):
        QGraphicsObject.__init__(self, parent)
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
        self.scaling = 1.0
        self.label = QGraphicsSimpleTextItem(label, self)
        self.label.setFont(Button.font)
        self.text_color_enabled = QColor(255, 255, 255, 255)
        self.text_color_disabled = QColor(200, 200, 200, 255)
        self.fill_color_disabled = QColor(125, 125, 125, 200)
        self.label.setBrush(QBrush(self.text_color_enabled))
        self.btn_id = btn_id
        self.rect = QRectF(0, 0, 0, 0)

        self.tooltip = QGraphicsSimpleTextItem(tooltip, self)
        self.tooltip.setBrush(QColor(255, 255, 255, 200))
        self.tooltip.setFont(Button.font)
        self.tooltip.setVisible(False)
        self.tooltip.setZValue(25)
        self.tooltip_shown = False

        self.base_color = ButtonColor.GRAY

        self.hor_margin = 10
        self.ver_margin = 5
        self.current_timer = 0

        self.logic: Union[CheckbuttonLogic, PushbuttonLogic] = PushbuttonLogic("gray")
        self.fill_color_current = self.logic.idle_color()

        self.color_animation = QPropertyAnimation(self, b"current_fill_color")
        self.color_animation.setEasingCurve(QEasingCurve.Linear)

        self.hovered = False
        self.setAcceptHoverEvents(True)
        self.setZValue(4)
        self.set_height(12)

        self.pixmap: QPixmap = None
        self.max_pixmap_height = 128
        self.disabled = False

        self.mode = ButtonMode.Button

    def set_height(self, h: int):
        self.prepareGeometryChange()
        self.ver_margin = int(0.25 * h)
        font: QFont = self.label.font()
        font.setPointSize(h)
        self.label.setFont(font)
        self.rect.setWidth(self.label.boundingRect().width() + 2 * self.hor_margin)
        self.rect.setHeight(self.label.boundingRect().height() + 2 * self.ver_margin)
        self._reposition_text()

    def set_width(self, w: int):
        if self.pixmap is not None:
            return
        self.prepareGeometryChange()
        self.rect.setWidth(w)
        self.hor_margin = self.ver_margin
        if self.label.boundingRect().width() > self.rect.width():
            w = self.rect.width() - 2 * self.hor_margin
            factor = w / self.label.boundingRect().width()
            h = factor * self.label.boundingRect().height()
            font = self.label.font()
            font.setPixelSize(max(h, 12))
            self.label.setFont(font)
        self._reposition_text()

    def set_button_height(self, h: int):
        self.rect.setHeight(h)
        self._reposition_text()

    def scale_button(self, factor: float):
        factor = 1.0
        self.rect.setHeight(int(factor * self.rect.height()))
        self.rect.setWidth(int(factor * self.rect.width()))
        self.label.setScale(self.scaling)
        self.fit_to_contents()

    def _reposition_text(self):
        x = self.rect.width() / 2 - self.label.boundingRect().width() / 2
        y = self.rect.height() / 2 - self.label.boundingRect().height() / 2
        self.label.setPos(QPointF(x, y))
        self.update()

    def boundingRect(self):
        return self.rect

    def paint(self, painter: QPainter, options, widget=None):
        painter.setBrush(QBrush(self.fill_color_current))
        painter.setPen(QPen(QColor(0, 0, 0, 0)))

        painter.drawRoundedRect(self.rect, 5, 5)

        if self.pixmap is not None:
            painter.drawPixmap(self.hor_margin * self.scaling, self.ver_margin * self.scaling, self.pixmap)
        if self.tooltip_shown:
            painter.setBrush(QBrush(QColor(50, 50, 50, 200)))
            painter.drawRoundedRect(self.tooltip.boundingRect().translated(self.tooltip.pos())
                                    .marginsAdded(QMarginsF(5, 0, 5, 0)), 5, 5)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.fill_color_current = self.logic.press_color()
        self.scene().update()

    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.click_button()

    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': True})
        self.hovered = True

        if len(self.tooltip.text()) > 0:
            self.tooltip_shown = True
            self.tooltip.setVisible(True)
            view = self.scene().views()[0]
            rect_ = view.mapFromScene(self.tooltip.sceneBoundingRect()).boundingRect()
            pos = self.boundingRect().topRight()
            mouse_pos = view.mapFromScene(event.scenePos())
            if mouse_pos.x() + rect_.width() >= view.viewport().width():
                pos = QPointF(-self.tooltip.boundingRect().width(), 0)

            self.tooltip.setPos(pos)

        self.color_animation.setDuration(200)
        self.color_animation.setStartValue(self.logic.idle_color())
        self.color_animation.setEndValue(self.logic.hover_enter_color())
        self.scene().update()
        if self.current_timer >= 0:
            self.killTimer(self.current_timer)
        self.color_animation.start()
        self.current_timer = self.startTimer(self.color_animation.duration() // 80)

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return

        self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False})
        self.hovered = False
        self.tooltip_shown = False
        self.tooltip.setVisible(False)

        self.color_animation.setDuration(200)
        self.color_animation.setStartValue(self.logic.hover_enter_color())
        self.color_animation.setEndValue(self.logic.hover_left_color())
        self.scene().update()
        if self.current_timer > 0:
            self.killTimer(self.current_timer)
        self.color_animation.start()
        self.current_timer = self.startTimer(self.color_animation.duration() // 80)

    def hoverMoveEvent(self, event: QGraphicsSceneHoverEvent):
        pass

    @pyqtProperty(QColor)
    def current_fill_color(self):
        return self.fill_color_current

    @current_fill_color.setter
    def current_fill_color(self, color: QColor):
        self.fill_color_current = color

    def timerEvent(self, ev: QTimerEvent):
        self.scene().update()
        if self.color_animation.state() == QPropertyAnimation.Stopped:
            self.killTimer(ev.timerId())
            self.current_timer = 0

    def set_base_color(self, colors: List[ButtonColor]):
        self.logic.set_colors(colors)
        self.fill_color_current = self.logic.idle_color()

    def is_on(self):
        return self.logic.is_down()

    def set_on(self, value: bool):
        if isinstance(self.logic, CheckbuttonLogic):
            self.logic.down = value
            self.fill_color_current = self.logic.press_color() if value else self.logic.idle_color()
            self.update()

    def set_is_check_button(self, value: bool):
        if value:
            self.logic = CheckbuttonLogic()
        else:
            self.logic = PushbuttonLogic("gray")

    def set_pixmap(self, pixmap: QPixmap):
        if pixmap is not None:
            self.pixmap = pixmap.scaledToHeight(self.max_pixmap_height * self.scaling) if pixmap is not None else None
            self.fit_to_contents()

    def fit_to_contents(self):
        self.prepareGeometryChange()
        width = 2 * self.hor_margin * self.label.scale()
        height = 2 * self.ver_margin * self.label.scale() + self.label.boundingRect().height() * self.label.scale()
        if self.pixmap is not None:
            width += max(self.pixmap.width(), self.label.boundingRect().width() * self.label.scale())
            height += self.ver_margin * self.scaling + self.pixmap.height()
        else:
            width += self.label.boundingRect().width() * self.label.scale()
        self.rect.setWidth(width)
        self.rect.setHeight(height)

        self.label.setPos(0.5 * width - 0.5 * self.label.boundingRect().width() * self.label.scale() + 0.0 * self.hor_margin,
                          height - self.label.boundingRect().height() * self.label.scale() - self.ver_margin * self.scaling)
        self.update()

    def adjust_text_to_button(self):
        height_diff = 0.75 * self.rect.height() - self.label.boundingRect().height()
        fac = height_diff / (0.75 * self.rect.height())
        self.label.setTransformOriginPoint(self.label.boundingRect().center())
        self.label.setScale(1.0 + fac)
        self._reposition_text()

    def set_label(self, text: str, direction: str = 'horizontal'):
        if direction == 'vertical':
            text = '\n'.join(list(text))
        self.label.setText(text)
        self._reposition_text()

    def click_button(self, artificial_emit: bool = False):
        if self.disabled:
            return
        self.logic.do_click()
        self.fill_color_current = self.logic.release_color() if not artificial_emit else self.logic.idle_color()
        self.clicked.emit({"btn_id": self.btn_id, "btn_label": self.label, "button": self, 'checked': self.is_on()})
        if artificial_emit:
            self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False})
            self.update()
        if self.scene() is not None:
            self.scene().update()

    def set_opacity(self, opacity: float):
        self.setOpacity(opacity)
        self.update()

    def set_default_state(self):
        self.logic.reset_state()
        self.fill_color_current = self.logic.idle_color()
        self.tooltip.setVisible(False)
        self.tooltip_shown = False
        self.update()

    def set_disabled(self, disabled: bool):
        self.disabled = disabled
        if disabled:
            self.label.setBrush(QBrush(self.text_color_disabled))
            self.fill_color_current = self.fill_color_disabled
        else:
            self.label.setBrush(QBrush(self.text_color_enabled))
            self.fill_color_current = self.logic.idle_color()
        self.update()

    def set_tooltip(self, tooltip: str):
        self.tooltip.setVisible(False)
        self.tooltip_shown = False
        self.tooltip.setText(tooltip)

    def set_custom_color(self, colors: List[QColor]):
        if isinstance(self.logic, CheckbuttonLogic):
            if len(colors) < 2:
                return
            self.logic.set_colors(colors=[
                colors[0],
                colors[0].lighter(120),
                colors[0].darker(120),

                colors[1],
                colors[1].lighter(120),
                colors[1].darker(120)
            ])
        else:
            self.logic.set_colors(colors=[
                colors[0],
                colors[0].lighter(120),
                colors[0].darker(120)
            ])
        self.fill_color_current = self.logic.idle_color()
        self.update()

    def set_mode(self, mode: ButtonMode):
        self.mode = mode
class NotificationDialog(QDialog):
    NOTIFICATION_LIVETIME = 2000

    def __init__(self, assignID, eventDescription, channelName, message,
                 positionNumber, font, notificationManager):
        super(NotificationDialog, self).__init__(
            notificationManager.chatScreen.chatUI.centralWidget.mainWindow)
        self.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.assignID = assignID
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.mainWindow = notificationManager.chatScreen.chatUI.centralWidget.mainWindow
        self.notificationManager = notificationManager
        self.eventDescription = eventDescription
        self.channelName = channelName
        self.message = message
        self.closeTime = time.time() + NotificationDialog.NOTIFICATION_LIVETIME
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.right = QApplication.desktop().screenGeometry().bottomRight().x(
        ) + 1
        self.bottom = QApplication.desktop().screenGeometry().bottomRight().y()
        self.height = math.floor(
            QApplication.desktop().screenGeometry().bottomRight().y() / 10)
        self.width = math.floor(
            QApplication.desktop().screenGeometry().bottomRight().x() / 6)
        self.setGeometry(self.right - self.width, self.height * positionNumber,
                         self.width, self.height - 10)

        self.label = QLabel()
        self.label.setObjectName("NotificationLabel")
        self.label.setText("\t" + eventDescription + "\n\t" + channelName +
                           "\n\t" + message)
        self.label.setFont(font)
        self.label.mouseReleaseEvent = self.clicked
        self.label.setMouseTracking(True)
        self.label.leaveEvent = self.mouseLeave
        self.label.enterEvent = self.mouseEnter

        layout1 = QVBoxLayout()
        layout1.setContentsMargins(0, 0, 0, 0)
        layout1.addWidget(self.label)
        self.setLayout(layout1)
        self.setWindowModality(Qt.NonModal)
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setEasingCurve(QEasingCurve.InCubic)
        self.animation.setDuration(1000)
        self.animation.setStartValue(self.windowOpacity())
        self.animation.setEndValue(0.1)
        self.hovered = True
        self.animation.finished.connect(self.fadeOutClose)
        self.show()

    def moveUpByOne(self):
        self.setGeometry(self.x(),
                         self.y() - self.height, self.width, self.height - 10)

    def mouseLeave(self, _):
        self.closeTime = time.time() + NotificationDialog.NOTIFICATION_LIVETIME
        self.notificationManager.addToSchedule(self)

    def mouseEnter(self, _):
        self.animation.stop()
        self.setWindowOpacity(1.0)
        self.notificationManager.removeFromScheduleByAssignID(self.assignID)

    def fadeOutClose(self):
        self.notificationManager.notificationHasFadedOut(self.assignID)
        self.close()

    def fadeOut(self):
        self.animation.start()

    def clicked(self, event):
        if event.button() == Qt.RightButton:
            self.notificationManager.chatScreen.joinChannel(self.channelName)
        self.notificationManager.closeNotification(self.assignID)
        self.close()

    def __eq__(self, other):
        return self.assignID == other
예제 #21
0
class MainWidget(QWidget):

    showed = pyqtSignal()
    closed = pyqtSignal()
    exited = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MainWidget, self).__init__(*args, **kwargs)
        self.resize(800, 600)
        # 保证qss有效
        self.setAttribute(Qt.WA_StyledBackground, True)
        # 左侧菜单栏和右侧内容栏
        self._initView()

    def showEvent(self, event):
        super(MainWidget, self).showEvent(event)
        # 动画效果
        self._initAnimations()

    def resizeEvent(self, event):
        super(MainWidget, self).resizeEvent(event)
        if not hasattr(self, "_animationGroupShow"):
            return
        self._initAnimationsValues()

    def onClose(self):
        self._animationGroup.stop()
        self._initAnimationsValues(False)
        self._animationGroup.finished.connect(self.exited.emit)
        self._animationGroup.start()

    def showNormalBtn(self, visible):
        self._titleBar.showNormalBtn(visible)

    def _initView(self):
        '''标题栏'''
        parent = self.parent() or self.parentWidget() or self
        self._titleBar = TitleWidget(parent=self)
        self._titleBar.minimized.connect(parent.showMinimized)
        self._titleBar.maximized.connect(parent.showMaximized)
        self._titleBar.normaled.connect(parent.showNormal)
        self._titleBar.closed.connect(self.onClose)
        '''左侧菜单栏和右侧内容栏'''
        cLayout = QHBoxLayout()
        self._menuWidget = MenuWidget(self)
        self._linkWidget = LinkWidget(self)
        self._contentWidget = ContentWidget(self)
        cLayout.addWidget(self._menuWidget)
        cLayout.addWidget(self._linkWidget)
        cLayout.addWidget(self._contentWidget)
        # 总体布局
        layout = QVBoxLayout(self, spacing=0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._titleBar)
        layout.addLayout(cLayout)

    def _initAnimations(self):
        '''动画效果'''
        if hasattr(self, "_animationGroup"):
            return  # 由于showEvent的关系,这里要防止多次实例化
        self._animationGroup = QParallelAnimationGroup(self)  # 并行动画
        # 标题栏
        self._animationTitleBar = QPropertyAnimation(
            self._titleBar, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000)
        # 菜单栏
        self._animationMenuWidget = QPropertyAnimation(
            self._menuWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000)
        # 链接
        self._animationLinkWidget = QPropertyAnimation(
            self._linkWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000)
        # 内容
        self._animationContentWidget = QPropertyAnimation(
            self._contentWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000)
        # add to group
        self._animationGroup.addAnimation(self._animationTitleBar)
        self._animationGroup.addAnimation(self._animationMenuWidget)
        self._animationGroup.addAnimation(self._animationLinkWidget)
        self._animationGroup.addAnimation(self._animationContentWidget)
        # 初始化位置
        self._initAnimationsValues(True)
        # 启动动画效果
        self._animationGroup.start()

    def _initAnimationsValues(self, show=True):
        # 标题栏
        startValue = QRect(self.width(), 0, self._titleBar.width(),
                           self._titleBar.height())
        endValue = QRect(0, 0, self._titleBar.width(),
                         self._titleBar.height())
        self._animationTitleBar.setStartValue(startValue if show else endValue)
        self._animationTitleBar.setEndValue(endValue if show else startValue)

        # 菜单栏
        startValue = QRect(-self._menuWidget.width(), self._titleBar.height(),
                           self._menuWidget.width(), self._menuWidget.height())
        endValue = QRect(0, self._titleBar.height(),
                         self._menuWidget.width(), self._menuWidget.height())
        self._animationMenuWidget.setStartValue(
            startValue if show else endValue)
        self._animationMenuWidget.setEndValue(endValue if show else startValue)

        # 链接
        startValue = QRect(self._menuWidget.width(
        ), -self.height(), self._linkWidget.width(), self._linkWidget.height())
        endValue = QRect(
            self._menuWidget.width(), self._titleBar.height(),
            self._linkWidget.width(), self._linkWidget.height())
        self._animationLinkWidget.setStartValue(
            startValue if show else endValue)
        self._animationLinkWidget.setEndValue(endValue if show else startValue)

        # 内容
        startValue = QRect(self.width(), self.height(), self._contentWidget.width(),
                           self._contentWidget.height())
        endValue = QRect(
            self._menuWidget.width() + self._linkWidget.width(),
            self._titleBar.height(), self._contentWidget.width(),
            self._contentWidget.height())
        self._animationContentWidget.setStartValue(
            startValue if show else endValue)
        self._animationContentWidget.setEndValue(
            endValue if show else startValue)
예제 #22
0
class UiTasklist(object):
    def setup(self, Dialog):
        Dialog.setObjectName("TaskList")
        Dialog.setEnabled(True)
        Dialog.setWindowFlags(QtCore.Qt.FramelessWindowHint)

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
        Dialog.setSizePolicy(sizePolicy)
        Dialog.setStyleSheet(CSS)
        self.label_3 = QtWidgets.QLabel(Dialog)
        self.label_3.setGeometry(QtCore.QRect(100, 0, 91, 16))
        self.label_3.setObjectName("label_3")
        self.verticalLayoutWidget = QtWidgets.QWidget(Dialog)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 341, 541))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setSizeConstraint(
            QtWidgets.QLayout.SetMaximumSize)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 6)
        self.verticalLayout_2.setSpacing(4)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.lbl_status = QtWidgets.QLabel(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.lbl_status.setFont(font)
        self.lbl_status.setAlignment(QtCore.Qt.AlignCenter)
        self.lbl_status.setObjectName("lbl_status")
        self.verticalLayout_2.addWidget(self.lbl_status)
        self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label_2.setFont(font)
        self.label_2.setTextFormat(QtCore.Qt.AutoText)
        self.label_2.setScaledContents(False)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setWordWrap(False)
        self.label_2.setObjectName("label_2")
        self.verticalLayout_2.addWidget(self.label_2)
        self.verticalLayout.addLayout(self.verticalLayout_2)
        self.listWidget = QtWidgets.QListWidget(self.verticalLayoutWidget)
        self.listWidget.setFixedHeight(460)
        self.listWidget.setFixedWidth(340)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.listWidget.sizePolicy().hasHeightForWidth())
        self.listWidget.setSizePolicy(sizePolicy)
        self.listWidget.setAutoFillBackground(False)
        self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.listWidget.setFrameShadow(QtWidgets.QFrame.Raised)
        self.listWidget.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.listWidget.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listWidget.setSelectionMode(
            QtWidgets.QAbstractItemView.NoSelection)
        self.listWidget.setMovement(QtWidgets.QListView.Static)
        #self.listWidget.setProperty("isWrapping", False)
        self.listWidget.setResizeMode(QtWidgets.QListView.Fixed)
        self.listWidget.setLayoutMode(QtWidgets.QListView.SinglePass)
        self.listWidget.setViewMode(QtWidgets.QListView.ListMode)
        self.listWidget.setSelectionRectVisible(False)
        self.listWidget.setObjectName("listWidget")
        self.verticalLayout.addWidget(self.listWidget)
        self.retranslate(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslate(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "GSyncftp - Tasklist"))
        self.lbl_status.setText(
            _translate("TaskList", "O GSyncftp está atualizado"))
        self.label_2.setText(_translate("TaskList", " Enterprise Coorp. LTDA"))
        self.listWidget.setSortingEnabled(False)
        self.listWidget.addItem("Nenhum arquivo na fila")

    def status_sync(self):
        _translate = QtCore.QCoreApplication.translate
        self.lbl_status.setText(
            _translate("TaskList", "Enviando os arquivos..."))

    def status_synced(self):
        _translate = QtCore.QCoreApplication.translate
        self.lbl_status.setText(
            _translate("TaskList", "O GSyncftp está atualizado"))

    def do_animation(self, Dialog):
        size_screen = QtWidgets.QDesktopWidget().screenGeometry(-1)
        pt_x = size_screen.width() - 339
        pt_y = size_screen.height() - 537
        self.anim = QPropertyAnimation(Dialog, b"geometry")
        self.anim.setDuration(250)
        self.anim.setStartValue(QRect(pt_x, size_screen.height(), 339, 537))
        self.anim.setEndValue(QRect(pt_x, pt_y, 339, 537))
        self.anim.start()
        Dialog.setEnabled(True)

    def not_in_animation(self):
        return self.anim and self.anim.state() != 2
예제 #23
0
class LoginView(QWidget):
    signal_login = pyqtSignal()
    def __init__(self):
        super(LoginView, self).__init__()
        self.resize(476, 200)
        stack_layout = QStackedLayout(self)
        stack_layout.setStackingMode(QStackedLayout.StackAll)
        stack_layout.addChildWidget(UICreatetor.create_background())

        content = self.create_login_content()
        content.move( self.width()-content.width() >> 1, self.height()-content.height() >> 1 )
        stack_layout.addChildWidget(content)

        self.msg_alert = QLabel("密码不能为空")
        self.msg_alert.setStyleSheet("background-color: rgb(242, 206, 58);"
                                "color: rgb(80, 80, 80);font: 12pt \"Microsoft YaHei UI\";")
        self.msg_alert.resize(476, 30)
        self.msg_alert.setAlignment(Qt.AlignCenter)
        self.msg_alert.move(0, 200)
        stack_layout.addChildWidget(self.msg_alert)

        self.alert_anim_in = QPropertyAnimation(self.msg_alert, b"pos")
        self.alert_anim_in.setStartValue(QPoint(0, 200))
        self.alert_anim_in.setEndValue(QPoint(0, 200))
        self.alert_anim_in.setEasingCurve(QEasingCurve.OutBack)
        self.alert_anim_in.setKeyValueAt(0.05, QPoint(0, 170))
        self.alert_anim_in.setKeyValueAt(0.95, QPoint(0, 170))
        self.alert_anim_in.setDuration(8000)

        self.anim_in = QPropertyAnimation(self, b"pos")
        self.anim_out = QPropertyAnimation(self, b"pos")
        self.anim_in.setStartValue(QPoint(2, 0))
        self.anim_in.setEndValue(QPoint(2, 200))
        self.anim_in.setKeyValueAt(0.5, QPoint(2, 0))
        self.anim_in.setEasingCurve(QEasingCurve.InOutBounce)
        self.anim_in.setDuration(2000)

        self.anim_out.setDuration(500)
        self.anim_out.setStartValue(QPoint(2, 200))
        self.anim_out.setEndValue(QPoint(2, 0))
        self.anim_out.setEasingCurve(QEasingCurve.OutExpo)

        if os.path.exists("ac.bin"):
            with open("ac.bin", "r") as file:
                content = file.read()
                dec_str = LoginTool.decrypt(content)
                print(dec_str)
                dec_str = dec_str.replace("\x00", "")
                ups = dec_str.split("|")
                print(ups,len(ups))
                if len(ups) == 2:
                    self.username_edit.setText(ups[0])
                    self.password_edit.setText(ups[1])
                file.close()
        else:
            print("密码文件不存在")

    def show_alert(self, msg):
        self.msg_alert.setText(msg)
        self.alert_anim_in.stop()
        self.alert_anim_in.start()

    def create_login_content(self):
        widget = QWidget()
        layout = QVBoxLayout(widget)
        self.username_edit = UICreatetor.create_username_input()
        layout.addWidget(self.username_edit, 0, Qt.AlignCenter)

        self.password_edit = UICreatetor.create_password_input()
        self.password_edit.returnPressed.connect(self.on_login_clicked)
        layout.addWidget(self.password_edit, 0, Qt.AlignCenter)

        center_layout = QHBoxLayout()
        self.save_paw_check = QCheckBox("保存密码")
        self.save_paw_check.setChecked(True)
        self.save_paw_check.setStyleSheet("font: 75 11pt \"Microsoft YaHei UI\";color: rgb(134, 134, 134);")
        center_layout.addWidget(self.save_paw_check)
        forget = QLabel("忘记密码")
        # forget.addAction()
        forget.setStyleSheet("font: 75 11pt \"Microsoft YaHei UI\";color: rgb(108, 202, 218);padding-right:0px")
        center_layout.addWidget(forget, 0, Qt.AlignRight)
        layout.addLayout(center_layout)
        layout.addSpacing(10)

        login_btn = UICreatetor.create_login_button()
        login_btn.clicked.connect(self.on_login_clicked)
        layout.addWidget(login_btn, 0, Qt.AlignCenter)
        login_btn.setFixedSize(188, 38)
        layout.addStretch()
        widget.resize(290, 200)
        return widget

    def on_login_clicked(self):
        self.signal_login.emit()

    def easing_in(self):
        self.anim_in.start()

    def easing_out(self):
        self.anim_out.start()
예제 #24
0
class SidebarCardHolder(QFrame):

    clicked = pyqtSignal(int)

    def __init__(self, wgt_id, text, parent=None):
        super().__init__(parent)
        # self.setFrameShape(QFrame.StyledPanel)
        # self.setFrameShadow(QFrame.Plain)

        self.widget_id = wgt_id
        self.setMouseTracking(True)

        self.text_lbl = QLabel(text)
        self.bottom_line = QFrame()
        self.bottom_line.setFrameShape(QFrame.HLine)
        self.bottom_line.setFrameShadow(QFrame.Sunken)
        self.bottom_line.setFixedHeight(1)
        self.bottom_line.setObjectName('CardHolderBLine')
        self.bottom_line.setStyleSheet('#CardHolderBLine{background: blue;}')

        mlayout = QVBoxLayout()
        mlayout.setContentsMargins(0, 0, 0, 0)
        mlayout.addWidget(self.text_lbl, 0, Qt.AlignCenter)
        mlayout.addWidget(self.bottom_line, 0, Qt.AlignCenter)
        self.setLayout(mlayout)

        size_hint = self.sizeHint()
        # Needed because of hover visuals when card-holder is triggered(displayed).
        size_hint.setHeight(size_hint.height() + 1)
        self.setFixedSize(size_hint)

        self.anim = QPropertyAnimation(self.bottom_line, b'minimumWidth')
        self.anim.setDuration(300)
        self.triggered = False

    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        self.clicked.emit(self.widget_id)
        self.triggered = not self.triggered
        if self.triggered:
            self.anim.stop()
            self.bottom_line.setFixedHeight(2)
            self.anim.setStartValue(self.bottom_line.width())
            self.anim.setEndValue(self.width() + 10)
            self.anim.start()
        else:
            self.bottom_line.setFixedHeight(1)

    def enterEvent(self, event):
        if self.triggered:
            self.bottom_line.setFixedHeight(2)
        else:
            self.anim.stop()
            self.anim.setStartValue(self.bottom_line.width())
            self.anim.setEndValue(self.width() + 10)
            self.anim.start()

    def leaveEvent(self, event):
        if self.triggered:
            self.bottom_line.setFixedHeight(1)
        else:
            self.anim.stop()
            self.anim.setStartValue(self.bottom_line.width())
            self.anim.setEndValue(0)
            self.anim.start()
예제 #25
0
class MainWindow(QMainWindow):
    htmlReady = pyqtSignal(str)

    def __init__(self, app):
        QMainWindow.__init__(self)
        self.install_directory = os.getcwd()

        self.app = app
        self.book = None
        self.last_book = ""
        self.filename = ""
        self._part_is_new = False
        self.tread_running = False
        self.initTheme()
        self.createUi()
        self.loadPlugins()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()

        self.text_edit.textChanged.connect(self.textChanged)

    def initTheme(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        self.theme = settings.value("theme", "DarkFusion")
        hilite_color = settings.value(
            "hiliteColor",
            self.palette().highlight().color().name())
        self.changeStyle(self.theme, hilite_color)

    def showEvent(self, event):
        if self.last_book:
            self.loadBook(self.last_book)

    def changeStyle(self, theme, hilite_color):
        self.theme = theme
        if theme == "DarkFusion":
            QApplication.setStyle(DarkFusion(hilite_color))
        else:
            QApplication.setStyle(QStyleFactory.create(theme))
            pal = self.app.palette()
            pal.setColor(QPalette.Highlight, QColor(hilite_color))
            self.app.setPalette(pal)

    def createUi(self):
        self.content = Expander("Content", ":/images/parts.svg")
        self.images = Expander("Images", ":/images/images.svg")
        self.settings = Expander("Settings", ":/images/settings.svg")

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

        self.content_list = QListWidget()
        self.content_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        content_box = QVBoxLayout()
        content_box.addWidget(self.content_list)
        self.item_edit = QLineEdit()
        self.item_edit.setMaximumHeight(0)
        self.item_edit.editingFinished.connect(self.editItemFinished)
        self.item_anim = QPropertyAnimation(self.item_edit,
                                            "maximumHeight".encode("utf-8"))
        content_box.addWidget(self.item_edit)
        button_layout = QHBoxLayout()
        plus_button = FlatButton(":/images/plus.svg")
        self.edit_button = FlatButton(":/images/edit.svg")
        self.trash_button = FlatButton(":/images/trash.svg")
        self.up_button = FlatButton(":/images/up.svg")
        self.down_button = FlatButton(":/images/down.svg")
        self.trash_button.enabled = False
        self.up_button.enabled = False
        self.down_button.enabled = False
        button_layout.addWidget(plus_button)
        button_layout.addWidget(self.up_button)
        button_layout.addWidget(self.down_button)
        button_layout.addWidget(self.edit_button)
        button_layout.addWidget(self.trash_button)
        content_box.addLayout(button_layout)
        self.content.addLayout(content_box)
        plus_button.clicked.connect(self.addPart)
        self.trash_button.clicked.connect(self.dropPart)
        self.up_button.clicked.connect(self.partUp)
        self.down_button.clicked.connect(self.partDown)
        self.edit_button.clicked.connect(self.editPart)

        self.image_list = QListWidget()
        self.image_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        image_box = QVBoxLayout()
        image_box.addWidget(self.image_list)
        image_button_layout = QHBoxLayout()
        image_plus_button = FlatButton(":/images/plus.svg")
        self.image_trash_button = FlatButton(":/images/trash.svg")
        self.image_trash_button.enabled = False
        image_button_layout.addWidget(image_plus_button)
        image_button_layout.addWidget(self.image_trash_button)
        image_box.addLayout(image_button_layout)
        self.images.addLayout(image_box)
        image_plus_button.clicked.connect(self.addImage)
        self.image_trash_button.clicked.connect(self.dropImage)

        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.splitter = QSplitter()
        self.text_edit = MarkdownEdit()
        self.text_edit.setFont(QFont("Courier", 11))
        self.preview = QWebEngineView()
        self.preview.setMinimumWidth(300)
        self.setWindowTitle(QCoreApplication.applicationName())

        self.splitter.addWidget(self.text_edit)
        self.splitter.addWidget(self.preview)
        self.setCentralWidget(self.splitter)

        self.content.expanded.connect(self.contentExpanded)
        self.images.expanded.connect(self.imagesExpanded)
        self.settings.expanded.connect(self.settingsExpanded)
        self.settings.clicked.connect(self.openSettings)
        self.content_list.currentItemChanged.connect(self.partSelectionChanged)
        self.image_list.currentItemChanged.connect(self.imageSelectionChanged)
        self.image_list.itemDoubleClicked.connect(self.insertImage)

        self.text_edit.undoAvailable.connect(self.undoAvailable)
        self.text_edit.redoAvailable.connect(self.redoAvailable)
        self.text_edit.copyAvailable.connect(self.copyAvailable)

        QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged)

    def undoAvailable(self, value):
        self.undo_act.setEnabled(value)

    def redoAvailable(self, value):
        self.redo_act.setEnabled(value)

    def copyAvailable(self, value):
        self.copy_act.setEnabled(value)
        self.cut_act.setEnabled(value)

    def clipboardDataChanged(self):
        md = QApplication.clipboard().mimeData()
        self.paste_act.setEnabled(md.hasText())

    def openSettings(self):
        dlg = Settings(self.book, self.install_directory)
        dlg.exec()
        if dlg.saved:
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

    def addPart(self):
        self.item_edit.setText("")
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = True

    def addItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.addPart(text)
                self.loadBook(self.last_book)

    def updateItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.updatePart(
                    self.content_list.currentItem().data(1).name, text)
                self.loadBook(self.last_book)

    def editItemFinished(self):
        if self._part_is_new:
            self.addItem()
        else:
            self.updateItem()
        self.item_anim.setStartValue(23)
        self.item_anim.setEndValue(0)
        self.item_anim.start()

    def editPart(self):
        item = self.content_list.currentItem().data(1).name
        self.item_edit.setText(item)
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = False

    def dropPart(self):
        item = self.content_list.currentItem().data(1).name
        msgBox = QMessageBox()
        msgBox.setText("You are about to delete the part <i>" + item + "</i>")
        msgBox.setInformativeText("Do you really want to delete the item?")
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        msgBox.setDefaultButton(QMessageBox.Cancel)
        ret = msgBox.exec()
        if ret == QMessageBox.Yes:
            self.book.dropPart(item)
            self.loadBook(self.last_book)

    def addImage(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("Image Files(*.png *.jpg *.bmp *.gif);;All (*)")
        dialog.setWindowTitle("Load Image")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return

        base = os.path.basename(fileName)
        if not os.path.exists(
                os.path.join(self.book.source_path, "images", base)):
            copy(fileName, os.path.join(self.book.source_path, "images"))
        item = QListWidgetItem()
        item.setText(Path(fileName).name)
        item.setData(
            1,
            os.path.join(self.book.source_path, "images",
                         Path(fileName).name))
        self.image_list.addItem(item)

    def dropImage(self):
        item = self.image_list.currentItem()
        image = item.data(1)
        filename = os.path.join(self.book.source_path, "parts", image)
        os.remove(filename)
        self.loadImages()

    def loadImages(self):
        self.image_list.clear()
        for root, dir, files in os.walk(
                os.path.join(self.book.source_path, "images")):
            for file in files:
                filename = os.path.join(self.book.source_path, "images",
                                        Path(file).name)
                item = QListWidgetItem()
                item.setToolTip("Doubleclick image to insert into text")
                item.setText(Path(file).name)
                item.setData(1, filename)
                self.image_list.addItem(item)

    def partUp(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos - 1, item)
        self.content_list.setCurrentRow(pos - 1)
        self.book.partUp(item.data(1).name)

    def partDown(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos + 1, item)
        self.content_list.setCurrentRow(pos + 1)
        self.book.partDown(item.data(1).name)

    def partSelectionChanged(self, item):
        if item:
            part = item.data(1)
            self.filename = os.path.join(self.book.source_path, "parts",
                                         part.src)
            with open(self.filename, "r") as f:
                t = f.read()
                self.text_edit.setPlainText(t)
            self.trash_button.enabled = True
            self.up_button.enabled = self.content_list.currentRow() > 0
            self.down_button.enabled = self.content_list.currentRow(
            ) < self.content_list.count() - 1
            self.edit_button.enabled = True
        else:
            self.text_edit.setText("")
            self.trash_button.enabled = False
            self.up_button.enabled = False
            self.down_button.enabled = False
            self.edit_button.enabled = False

    def imageSelectionChanged(self, item):
        if item:
            self.image_trash_button.enabled = True
        else:
            self.image_trash_button.enabled = False

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

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

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

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

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

    def createMenus(self):
        new_icon = QIcon(QPixmap(":/images/new.svg"))
        open_icon = QIcon(QPixmap(":/images/open.svg"))
        book_icon = QIcon(QPixmap(":/images/book.svg"))
        bold_icon = QIcon(QPixmap(":/images/bold.svg"))
        italic_icon = QIcon(QPixmap(":/images/italic.svg"))
        image_icon = QIcon(QPixmap(":/images/image.svg"))
        table_icon = QIcon(QPixmap(":/images/table.svg"))
        á_icon = QIcon(QPixmap(":/images/á.svg"))
        ã_icon = QIcon(QPixmap(":/images/ã.svg"))
        é_icon = QIcon(QPixmap(":/images/é.svg"))
        ê_icon = QIcon(QPixmap(":/images/ê.svg"))
        ó_icon = QIcon(QPixmap(":/images/ó.svg"))

        new_act = QAction(new_icon, "&New", self)
        new_act.setShortcuts(QKeySequence.New)
        new_act.setStatusTip("Create a new ebook project")
        new_act.triggered.connect(self.newFile)
        new_act.setToolTip("Create new ebook project")

        open_act = QAction(open_icon, "&Open", self)
        open_act.setShortcuts(QKeySequence.Open)
        open_act.setStatusTip("Open an existing ebook project")
        open_act.triggered.connect(self.open)
        open_act.setToolTip("Open an existing ebook project")

        book_act = QAction(book_icon, "&Create Book", self)
        book_act.setShortcuts(QKeySequence.SaveAs)
        book_act.setStatusTip("Create an ebook")
        book_act.triggered.connect(self.create)
        book_act.setToolTip("Create an ebook")

        pdf_act = QAction("Create &PDF", self)
        pdf_act.setStatusTip("Create PDF")
        pdf_act.setToolTip("Create PDF")
        pdf_act.triggered.connect(self.pdfExport)

        settings_act = QAction("&Settings", self)
        settings_act.setStatusTip("Open settings dialog")
        settings_act.triggered.connect(self.settingsDialog)
        settings_act.setToolTip("Open settings dialog")

        exit_act = QAction("E&xit", self)
        exit_act.setShortcuts(QKeySequence.Quit)
        exit_act.setStatusTip("Exit the application")
        exit_act.triggered.connect(self.close)

        self.undo_act = QAction("Undo", self)
        self.undo_act.setShortcut(QKeySequence.Undo)
        self.undo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doUndo)

        self.redo_act = QAction("Redo", self)
        self.redo_act.setShortcut(QKeySequence.Redo)
        self.redo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doRedo)

        self.cut_act = QAction("Cu&t", self)
        self.cut_act.setShortcut(QKeySequence.Cut)
        self.cut_act.triggered.connect(self.doCut)
        self.cut_act.setEnabled(False)

        self.copy_act = QAction("&Copy", self)
        self.copy_act.setShortcut(QKeySequence.Copy)
        self.copy_act.triggered.connect(self.doCopy)
        self.copy_act.setEnabled(False)

        self.paste_act = QAction("&Paste", self)
        self.paste_act.setShortcut(QKeySequence.Paste)
        self.paste_act.triggered.connect(self.doPaste)
        self.paste_act.setEnabled(False)

        bold_act = QAction(bold_icon, "Bold", self)
        bold_act.setShortcut(Qt.CTRL + Qt.Key_B)
        bold_act.triggered.connect(self.bold)

        italic_act = QAction(italic_icon, "Italic", self)
        italic_act.setShortcut(Qt.CTRL + Qt.Key_I)
        italic_act.triggered.connect(self.italic)

        image_act = QAction(image_icon, "Image", self)
        image_act.setShortcut(Qt.CTRL + Qt.Key_G)
        image_act.triggered.connect(self.insertImage)
        image_act.setToolTip("Insert an image")

        table_act = QAction(table_icon, "Table", self)
        table_act.setShortcut(Qt.CTRL + Qt.Key_T)
        table_act.triggered.connect(self.insertTable)
        table_act.setToolTip("Insert a table")

        á_act = QAction(á_icon, "á", self)
        á_act.triggered.connect(self.insertLetterA1)
        á_act.setToolTip("Insert letter á")

        ã_act = QAction(ã_icon, "ã", self)
        ã_act.triggered.connect(self.insertLetterA2)
        ã_act.setToolTip("Insert letter ã")

        é_act = QAction(é_icon, "é", self)
        é_act.triggered.connect(self.insertLetterE1)
        é_act.setToolTip("Insert letter é")

        ê_act = QAction(ê_icon, "ê", self)
        ê_act.triggered.connect(self.insertLetterE2)
        ê_act.setToolTip("Insert letter ê")

        ó_act = QAction(ó_icon, "ó", self)
        ó_act.triggered.connect(self.insertLetterO1)
        ó_act.setToolTip("Insert letter ó")

        about_act = QAction("&About", self)
        about_act.triggered.connect(self.about)
        about_act.setStatusTip("Show the application's About box")

        spell_act = QAction("&Spellcheck", self)
        spell_act.setShortcut(Qt.CTRL + Qt.Key_P)
        spell_act.triggered.connect(self.spellCheck)
        spell_act.setStatusTip("Spellcheck")

        file_menu = self.menuBar().addMenu("&File")
        file_menu.addAction(new_act)
        file_menu.addAction(open_act)
        file_menu.addAction(book_act)
        file_menu.addAction(pdf_act)
        file_menu.addSeparator()
        file_menu.addAction(settings_act)
        file_menu.addSeparator()
        file_menu.addAction(exit_act)

        edit_menu = self.menuBar().addMenu("&Edit")
        edit_menu.addAction(self.undo_act)
        edit_menu.addAction(self.redo_act)
        edit_menu.addSeparator()
        edit_menu.addAction(self.cut_act)
        edit_menu.addAction(self.copy_act)
        edit_menu.addAction(self.paste_act)

        format_menu = self.menuBar().addMenu("&Format")
        format_menu.addAction(bold_act)
        format_menu.addAction(italic_act)

        insert_menu = self.menuBar().addMenu("&Insert")
        insert_menu.addAction(image_act)
        insert_menu.addAction(table_act)

        for key in Plugins.generatorPluginNames():
            gen = Plugins.getGeneratorPlugin(key)
            if gen:
                act = QAction(gen.display_name, self)
                #act.triggered.connect(self.insertTable)
                #act.setToolTip("Insert a table")
                insert_menu.addAction(act)
                act.triggered.connect(gen.menu_action)

        help_menu = self.menuBar().addMenu("&Help")
        help_menu.addAction(about_act)
        help_menu.addAction(spell_act)

        file_tool_bar = self.addToolBar("File")
        file_tool_bar.addAction(new_act)
        file_tool_bar.addAction(open_act)
        file_tool_bar.addAction(book_act)

        format_tool_bar = self.addToolBar("Format")
        format_tool_bar.addAction(bold_act)
        format_tool_bar.addAction(italic_act)

        insert_toolbar = self.addToolBar("Insert")
        insert_toolbar.addAction(image_act)
        insert_toolbar.addAction(table_act)
        insert_toolbar.addAction(á_act)
        insert_toolbar.addAction(ã_act)
        insert_toolbar.addAction(é_act)
        insert_toolbar.addAction(ê_act)
        insert_toolbar.addAction(ó_act)

    def doUndo(self):
        self.text_edit.undo()

    def doRedo(self):
        self.text_edit.redo()

    def doCut(self):
        self.text_edit.cut()

    def doCopy(self):
        self.text_edit.copy()

    def doPaste(self):
        self.text_edit.paste()

    def insertImage(self):
        if not self.book:
            QMessageBox.warning(self, QCoreApplication.applicationName(),
                                "You have to load or create a book first!")
            return
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        if self.image_list.count() == 0:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to add an image to the image list first!")
            return
        if not self.image_list.currentItem():
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select an image from the image list first!")
            return

        item = self.image_list.currentItem()
        filename = item.text()
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        base = filename.split(".")[0].replace("_", "-")
        cursor.insertText("![" + base + "](../images/" + filename + " \"" +
                          base + "\")")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def insertTable(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText(
            "| alignLeft | alignCenter | unAligned | alignRight |\n"
            "|  :---     |   :---:     |   ---     |   ---:     |\n"
            "|  cell a   |   cell b    |   cell c  |   cell d   |\n"
            "|  cell e   |   cell f    |   cell g  |   cell h   |\n")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def insertLetterA1(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText("á")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def insertLetterA2(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText("ã")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def insertLetterE1(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText("é")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def insertLetterE2(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText("ê")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def insertLetterO1(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText("ó")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def about(self):
        QMessageBox.about(
            self, "About " + QCoreApplication.applicationName(),
            "EbookCreator\nVersion: " + QCoreApplication.applicationVersion() +
            "\n(C) Copyright 2020 CrowdWare. All rights reserved.\n\nThis program is provided AS IS with NO\nWARRANTY OF ANY KIND, INCLUDING THE\nWARRANTY OF DESIGN, MERCHANTABILITY AND\nFITNESS FOR A PATICULAR PURPOSE."
        )

    def newFile(self):
        dlg = ProjectWizard(self.install_directory, parent=self)
        dlg.loadBook.connect(self.loadBook)
        dlg.show()

    def open(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("EbookCreator (book.qml);;All (*)")
        dialog.setWindowTitle("Load Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setDirectory(os.path.join(self.install_directory, "sources"))
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return
        self.loadBook(fileName)

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("lastBook", self.last_book)

    def readSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        geometry = settings.value("geometry", QByteArray())
        self.last_book = settings.value("lastBook")
        if not geometry:
            availableGeometry = QApplication.desktop().availableGeometry(self)
            self.resize(availableGeometry.width() / 3,
                        availableGeometry.height() / 2)
            self.move((availableGeometry.width() - self.width()) / 2,
                      (availableGeometry.height() - self.height()) / 2)
        else:
            self.restoreGeometry(geometry)

    def bold(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("**" + cursor.selectedText() + "**")
        cursor.setPosition(pos + 2)
        self.text_edit.setTextCursor(cursor)

    def italic(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("*" + cursor.selectedText() + "*")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def create(self):
        filename = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("ePub3 (*.epub);;All (*)")
        dialog.setWindowTitle("Create Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setDirectory(self.book.source_path)
        dialog.setDefaultSuffix("epub")
        if dialog.exec_():
            filename = dialog.selectedFiles()[0]
        del dialog
        if not filename:
            return
        QApplication.setOverrideCursor(Qt.WaitCursor)
        createEpub(filename, self.book, self)
        QApplication.restoreOverrideCursor()

    def loadStatusChanged(self, status):
        if status == 1:
            self.book = self.component.create()
            if self.book is not None:
                self.book.setFilename(self.last_book)
                self.book.setWindow(self)
            else:
                for error in self.component.errors():
                    print(error.toString())
                return

            self.content_list.clear()
            for part in self.book.parts:
                item = QListWidgetItem()
                item.setText(part.name)
                item.setData(1, part)
                self.content_list.addItem(item)

            self.loadImages()
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

            self.content.setExpanded(True)
            self.content_list.setCurrentRow(0)
        elif status == 3:
            for error in self.component.errors():
                print(error.toString())
            return

    def loadBook(self, filename):
        self.last_book = filename
        self.filename = ""
        engine = QQmlEngine()
        self.component = QQmlComponent(engine)
        self.component.statusChanged.connect(self.loadStatusChanged)
        self.component.loadUrl(QUrl.fromLocalFile(filename))

    def settingsDialog(self):
        dlg = SettingsDialog(self.theme,
                             self.palette().highlight().color().name(),
                             parent=self)
        dlg.exec()
        if dlg.theme != self.theme or dlg.hilite_color != self.palette(
        ).highlight().color().name():
            settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                                 QCoreApplication.organizationName(),
                                 QCoreApplication.applicationName())
            settings.setValue("theme", dlg.theme)
            settings.setValue("hiliteColor", dlg.hilite_color)

            msgBox = QMessageBox()
            msgBox.setText("Please restart the app to change the theme!")
            msgBox.exec()

    def textChanged(self):
        text = self.text_edit.toPlainText()
        if self.filename:
            with open(self.filename, "w") as f:
                f.write(text)

        self.lock = Lock()
        with self.lock:
            if not self.tread_running:
                self.tread_running = True
                self.htmlReady.connect(self.previewReady)
                thread = Thread(target=self.createHtml, args=(text, ))
                thread.daemon = True
                thread.start()

    def previewReady(self, html):
        self.preview.setHtml(
            html,
            baseUrl=QUrl(
                Path(os.path.join(self.book.source_path, "parts",
                                  "index.html")).as_uri()))
        self.htmlReady.disconnect()
        with self.lock:
            self.tread_running = False

    def createHtml(self, text):
        html = '<html>\n<head>\n'
        html += '<link href="../css/pastie.css" rel="stylesheet" type="text/css"/>\n'
        html += '<link href="../css/stylesheet.css" rel="stylesheet" type="text/css"/>\n'
        html += '</head>\n<body>\n'
        html += markdown(text,
                         html4tags=False,
                         extras=[
                             "fenced-code-blocks", "wiki-tables", "tables",
                             "header-ids"
                         ])
        html += '\n</body>\n</html>'
        html = addLineNumbers(html)
        self.htmlReady.emit(html)

    def pdfExport(self):
        p = PdfExport(self.book, self.statusBar())

    def spellCheck(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        spell = Speller(lang='en')
        changed = spell(cursor.selectedText())
        if changed != cursor.selectedText():
            cursor.insertText(changed)
            self.text_edit.setTextCursor(cursor)

    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, GeneratorInterface):
                                Plugins.addGeneratorPlugin(name, instance)
                                instance.setTextEdit(self.text_edit)
                                #instance.registerContenType()
            break  # not to list __pycache__
예제 #26
0
class KeyboardUI(QMainWindow):
        
    def __init__(self):
        super().__init__()
        self.keyboard()
        QThread.currentThread().setObjectName('main')
        self.__work_done=None
        self.__threads=None
        self.animation=None
        self.animation = None
    
    def __del__(self):
        sys.__stdout__ = sys.stdout                                  # 初始化标准输出
        sys.__stderr__ = sys.stderr                                  # 初始化标准输出'''

    def closeEvent(self,event):
        if self.animation is None:
            self.animation=QPropertyAnimation(self,"windowOpacity")
            self.animation.setDuration(300)
            self.animation.setStartValue(1)
            self.animation.setEndValue(0)
            self.animation.finished.connect(self.close)
            self.animation.start()
            event.ignore()


    def keyboard(self):        
        self.setWindowTitle('KeyBoard Test Tool Beta1.0')
        
        self.savedStdout = sys.stdout
        self.savedStderr = sys.stderr
        sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)  # 重新定义系统标准输出
        sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)  # 重新定义系统标准错误'''
        
        mainLayout=QGridLayout()
        serailLayout=QGridLayout()

        line1Layout=QHBoxLayout()
        line2Layout=QHBoxLayout()
        line3Layout=QHBoxLayout()
        line4Layout=QHBoxLayout()
        line5Layout=QHBoxLayout()
        line6Layout=QHBoxLayout()
        line7Layout=QHBoxLayout()

        self.Serial_chose_Widget=QGroupBox('')
        self.TxtWidget=QTextEdit()
        self.Txtline=QLineEdit()
        self.Txtline.setFont(QFont("Roman times",13))
        
        self.runbutton=QPushButton('RUN')
        
        self.serial_name_label=QLabel(' 串口')
        self.serial_name_widget=QComboBox()

        self.serial_name_widget.addItem("COM1")
        self.serial_name_widget.addItem("COM2")
        self.serial_name_widget.addItem("COM3")
        self.serial_name_widget.addItem("COM4")
        self.serial_name_widget.addItem("COM5")
        self.serial_name_widget.addItem("COM6")
        self.serial_name_widget.addItem("COM7")
        self.serial_name_widget.addItem("COM8")
        self.serial_name_widget.addItem("COM9")
        self.serial_name_widget.addItem("COM10")

        self.serail_baudrate_label=QLabel("波特率")
        self.serial_lineedit = QLineEdit()
        
        
        self.Serial_chose_Widget.setLayout(serailLayout)
        serailLayout.addWidget(self.serial_name_label,0,0,1,2)
        serailLayout.addWidget(self.serial_name_widget, 0,2,1,3)
        serailLayout.addWidget(self.serail_baudrate_label,1,0,1,2)
        serailLayout.addWidget(self.serial_lineedit,1,2,1,3)


        self.line1widget=QWidget()
        self.line1widget.setLayout(line1Layout)
        self.line2widget=QWidget()
        self.line2widget.setLayout(line2Layout)
        self.line3widget=QWidget()
        self.line3widget.setLayout(line3Layout)
        self.line4widget=QWidget()
        self.line4widget.setLayout(line4Layout)
        self.line5widget=QWidget()
        self.line5widget.setLayout(line5Layout)
        self.line6widget=QWidget()
        self.line6widget.setLayout(line6Layout)
        self.line7widget=QWidget()
        self.line7widget.setLayout(line7Layout)
        
        MainWindow=QWidget()
        MainWindow.setLayout(mainLayout)
        self.setCentralWidget(MainWindow)

        mainLayout.addWidget(self.Serial_chose_Widget,0,0,1,1)
        mainLayout.addWidget(self.TxtWidget,0,1,1,18)
        mainLayout.addWidget(self.runbutton,1,0,1,1)
        mainLayout.addWidget(self.Txtline,1,1,1,18)
        key_line1=['Esc','F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12','Home','End','Insert','Delete']
        key_line2=['~\n·\n','!\n1\n','@\n2\n','#\n3\n','$\n4\n','%\n5\n','^\n6\n','&&\n7\n','*\n8\n','(\n9\n',')\n0\n','-\n-\n','+\n=\n','\nBackspace\n']
        key_line3=['\nTab\n','\nQ\n','\nW\n','\nE\n','\nR\n','\nT\n','\nY\n','\nU\n','\nI\n','\nO\n','\nP\n','{\n[\n','}\n]\n','|\n\\\n']
        key_line4=['\nCaps Lock\n','\nA\n','\nS\n','\nD\n','\nF\n','\nG\n','\nH\n','\nJ\n','\nK\n','\nL\n',':\n;\n','"\n\'\n','\nEnter\n']
        key_line5=['\nShift\n','\nZ\n','\nX\n','\nC\n','\nV\n','\nB\n','\nN\n','\nM\n','<\n,\n','>\n.\n','?\n/\n','\nShift\n']
        key_line6=['\nFn\n','\nCtrl\n','\n▆▇\n▇▇','\nAlt\n','\n------------------------------------------------------------------\n','\nAlt\n','\nPrtScn\n','\nCtrl\n','\nPgUp\n','\n↑\n','\nPgDn\n']
        key_line7=['←','↓','→']
        
        key_line=[]
        key_line.append(key_line1)
        key_line.append(key_line2)
        key_line.append(key_line3)
        key_line.append(key_line4)
        key_line.append(key_line5)
        key_line.append(key_line6)
        key_line.append(key_line7)
        
        self.button=locals()
        
        positions1= [ j for j in range(17)]
        for position,key in zip(positions1,key_line1):
            self.button['button1_%s'%position]=QPushButton(key)
            self.button['button1_%s'%position].setFont(QFont("Roman times",8,QFont.Bold))
            #self.button['button1_%s'%position].setCheckable(True)
            #self.button['button1_%s'%position].setAutoExclusive(True)
            line1Layout.addWidget(self.button['button1_%s'%position],position)
        mainLayout.addWidget(self.line1widget,2,0,1,19)
              
        positions2= [ j for j in range(14)]
        for position,key in zip(positions2,key_line2):
            self.button['button2_%s'%position]=QPushButton(key)
            self.button['button2_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))
            line2Layout.addWidget(self.button['button2_%s'%position],position)
            line2Layout.setSpacing(8)
        mainLayout.addWidget(self.line2widget,3,0,1,19) 
        
        positions3= [ j for j in range(14)]
        for position,key in zip(positions3,key_line3):
            self.button['button3_%s'%position]=QPushButton(key)
            self.button['button3_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))
            line3Layout.addWidget(self.button['button3_%s'%position],position)
            line3Layout.setSpacing(10)
        mainLayout.addWidget(self.line3widget,4,0,1,19)

        positions4= [ j for j in range(13)]
        for position,key in zip(positions4,key_line4):
            self.button['button4_%s'%position]=QPushButton(key)
            self.button['button4_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))
            line4Layout.addWidget(self.button['button4_%s'%position],position)
            line4Layout.setSpacing(13)
        mainLayout.addWidget(self.line4widget,5,0,1,19)

        positions5= [ j for j in range(12)]
        for position,key in zip(positions5,key_line5):
            self.button['button5_%s'%position]=QPushButton(key)
            self.button['button5_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))
            line5Layout.addWidget(self.button['button5_%s'%position],position)
            line5Layout.setSpacing(15)
        mainLayout.addWidget(self.line5widget,6,0,1,19)


        positions6= [ j for j in range(11)]
        for position,key in zip(positions6,key_line6):
            self.button['button6_%s'%position]=QPushButton(key)
            self.button['button6_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))
            if key=='\n------------------------------------------------------------------\n':
                self.button['button6_%s'%position].setStyleSheet('''
                QPushButton{
                color: rgb(211,211,211) ;
                }
                ''')

            line6Layout.addWidget(self.button['button6_%s'%position],position)
            line6Layout.setSpacing(12)
        mainLayout.addWidget(self.line6widget,7,0,1,19)

        positions7= [ j for j in range(3)]
        for position,key in zip(positions7,key_line7):
            self.button['button7_%s'%position]=QPushButton(key)
            self.button['button7_%s'%position].setFont(QFont("Roman times",9,QFont.Bold))

            line7Layout.addWidget(self.button['button7_%s'%position],position+8)
            line7Layout.setSpacing(12)
        mainLayout.addWidget(self.line7widget,8,14,1,5)
        
        self.move(300,150)
        self.show()
        
    def normalOutputWritten(self, text):
        cursor = self.TxtWidget.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.TxtWidget.setTextCursor(cursor)
        self.TxtWidget.ensureCursorVisible()
예제 #27
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()
class Platform(QWidget):
    def __init__(self):
        super(Platform, self).__init__()
        self._desktop = QApplication.instance().desktop()
        self.__dir = os.path.dirname(os.path.dirname(
            os.path.abspath(__file__)))
        self.__WebContent()
        self.__initPosition()
        self.__connectJs()
        print("启动desk")

    def __WebContent(self):
        self.resize(self._desktop.screenGeometry().width() / 5,
                    self._desktop.availableGeometry().height())
        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.webView = QWebView()
        # BASE_DIR = os.path.dirname(os.path.dirname(__file__))
        # new = os.path.join(BASE_DIR, 'web')
        #
        # new_file_name = os.path.join(new, 'noticeContent.html')
        # fname = 'file:///'+new_file_name
        # print(fname)
        # self.webView.load(QUrl('file:///C:/Users/Administrator/Desktop/app/mainWin/desk/web/desk.html'))
        print('file:///' + self.__dir + '/web/desk.html')
        self.webView.load(QUrl('file:///' + self.__dir + '/web/desk.html'))
        # self.webView.load(QUrl(fname))
        self.verticalLayout.addWidget(self.webView)
        # self.webView.loadFinished.connect(self.test)

    def onClose(self):
        #点击关闭按钮时
        self.isShow = False
        QTimer.singleShot(100, self.closeAnimation)  #启动弹回动画

    def __initPosition(self):
        # 隐藏任务栏|去掉边框|顶层显示
        self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint
                            | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)

        # 是否在显示标志
        self.isShow = True

        # 桌面
        # self._desktop = QApplication.instance().desktop()
        # 窗口初始开始位置
        self._startPos = QPoint(
            self._desktop.screenGeometry().width(),
            self._desktop.availableGeometry().height() - self.height())
        print(self._startPos)
        # 窗口弹出结束位置
        self._endPos = QPoint(
            self._desktop.screenGeometry().width() - self.width(),
            self._desktop.availableGeometry().height() - self.height())
        print(self._endPos)
        # 初始化位置到右侧
        self.move(self._startPos)

        # 动画
        self.animation = QPropertyAnimation(self, b"pos")

        self.hide()  # 先隐藏
        super(Platform, self).show()

    def __connectJs(self):

        connector = ConnectJs(self)
        self.webView.page().mainFrame().javaScriptWindowObjectCleared.connect(
            lambda: self.webView.page().mainFrame(
            ).addToJavaScriptWindowObject('pyNotice', connector))

    def add(self, content=""):
        if content:
            self.__notice_list.insert(0, content)
            self.webView.page().mainFrame().evaluateJavaScript(
                "pyNoticeAdd(%s)" % str(content))

    def show(self, title="", content=""):
        # 显示动画
        self.isShow = True
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self._endPos)
        self.animation.start()

    def closeAnimation(self):

        self.isShow = False
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self._startPos)
        self.animation.start()
예제 #29
0
class Point(QObject):

    valueChanged = pyqtSignal()

    def __init__(self, x, ox, y, oy, *args, **kwargs):
        super(Point, self).__init__(*args, **kwargs)
        self.__x = x
        self._x = x
        self.originX = ox
        self._y = y
        self.__y = y
        self.originY = oy
        # 5个闭合点
        self.closest = [0, 0, 0, 0, 0]
        # 圆半径
        self.radius = 2 + random() * 2
        # 连线颜色
        self.lineColor = QColor(156, 217, 249)
        # 圆颜色
        self.circleColor = QColor(156, 217, 249)

    def initAnimation(self):
        # 属性动画
        if not hasattr(self, 'xanimation'):
            self.xanimation = QPropertyAnimation(
                self, b'x', self, valueChanged=self.valueChanged.emit,
                easingCurve=QEasingCurve.InOutSine)
            self.yanimation = QPropertyAnimation(
                self, b'y', self, valueChanged=self.valueChanged.emit,
                easingCurve=QEasingCurve.InOutSine,
                finished=self.updateAnimation)
            self.updateAnimation()

    def updateAnimation(self):
        self.xanimation.stop()
        self.yanimation.stop()
        duration = (1 + random()) * 1000
        self.xanimation.setDuration(duration)
        self.yanimation.setDuration(duration)
        self.xanimation.setStartValue(self.__x)
        self.xanimation.setEndValue(self.originX - 50 + random() * 100)
        self.yanimation.setStartValue(self.__y)
        self.yanimation.setEndValue(self.originY - 50 + random() * 100)
        self.xanimation.start()
        self.yanimation.start()

    @pyqtProperty(float)
    def x(self):
        return self._x

    @x.setter
    def x(self, x):
        self._x = x

    @pyqtProperty(float)
    def y(self):
        return self._y

    @y.setter
    def y(self, y):
        self._y = y
예제 #30
0
    def __init__(self):
        super().__init__()
        self.setBackgroundBrush(QBrush(QPixmap(':/images/background.png')))
        self.skill_label = self.addSimpleText(Config.UserName, Config.BigFont)
        self.skill_label.setPos(-400, -100)

        self.photos = list()
        group = QParallelAnimationGroup(self)

        for i in range(7):
            photo = Photo()
            self.photos.append(photo)

            self.addItem(photo)
            x = i * photo.boundingRect().width() + Config.Rect.x()
            y = Config.Rect.y() + 10
            duration = 1500.0 * qrand() / RAND_MAX

            translation = QPropertyAnimation(photo, bytes("pos", 'utf-8'))
            translation.setEndValue(QPointF(x, y))
            translation.setEasingCurve(QEasingCurve.OutBounce)
            translation.setDuration(duration)

            group.addAnimation(translation)

        self.photos[0].loadAvatar("generals/small/caocao.png")
        self.photos[1].loadAvatar("generals/small/liubei.png")
        self.photos[2].loadAvatar("generals/small/sunquan.png")
        self.photos[3].loadAvatar("generals/small/simayi.png")
        self.photos[4].loadAvatar("generals/small/guojia.png")
        self.photos[5].loadAvatar("generals/small/zhugeliang.png")
        self.photos[6].loadAvatar("generals/small/zhouyu.png")

        self.dashboard = Dashboard()
        self.dashboard.setGeneral(General("caocao", "wei", 4, True))
        self.addItem(self.dashboard)

        start_pos = Config.Rect.topLeft()
        end_pos = QPointF(
            Config.Rect.x(),
            Config.Rect.bottom() - self.dashboard.boundingRect().height())
        duration = 1500

        translation = QPropertyAnimation(self.dashboard, bytes("pos", 'utf-8'))
        translation.setStartValue(start_pos)
        translation.setEndValue(end_pos)
        translation.setEasingCurve(QEasingCurve.OutBounce)
        translation.setDuration(duration)

        enlarge = QPropertyAnimation(self.dashboard, bytes("scale", 'utf-8'))
        enlarge.setStartValue(0.2)
        enlarge.setEndValue(1.0)
        enlarge.setEasingCurve(QEasingCurve.OutBounce)
        enlarge.setDuration(duration)

        group.addAnimation(translation)
        group.addAnimation(enlarge)

        group.start(QAbstractAnimation.DeleteWhenStopped)

        card1 = Card("savage_assault", Card.Spade, 1)
        card2 = Card("slash", Card.Club, 7)
        card3 = Card("jink", Card.Heart, 2)
        card4 = Card("peach", Card.Diamond, 10)
        card5 = Card("archery_attack", Card.Heart, 11)
        card6 = Card("crossbow", Card.Club, 12)

        self.dashboard.addCard(card1)
        self.dashboard.addCard(card2)
        self.dashboard.addCard(card3)
        self.dashboard.addCard(card4)
        self.dashboard.addCard(card5)
        self.dashboard.addCard(card6)

        card4.setEnabled(False)
예제 #31
0
파일: blueApp.py 프로젝트: blackskygg/jielu
class BlueApp:
    def __init__(self, argv):
        self.app = QApplication(argv)

        self.mainWindow = QtWidgets.QMainWindow()
        self.mainWindow.closeEvent = self.onClose
        self.ui = blueMainUi.Ui_MainWindow()
        self.ui.setupUi(self.mainWindow)


        #settings and statistics
        self.defaultSettings = dict(image_detect=True, text_detect=True,
                                    game_type=0, pipeRank=0,
                                    goal = 10, startDate = time.time(),
                                    avata = "res/icon.png", name = "窜天猴")
        self.defaultStat = dict(stat = [ [0, 0, 0, 0] for i in range(7)],
                                achivement = 0, lastWater = 0, lastFertilize = 0,
                                cleanHours = 0, cleanMinutes = 0)
        self.achivementsList = ["大淫魔", "从头开始", "欲火渐盛",
                                "钢筋铁骨", "渐入佳境","心无杂念"]
        self.achivementsStd = [0, 24, 24 * 3, 24 * 7, 24 * 31, 27 * 365]
        self.loadSettings()
        self.validateSettings()
        self.loadStatistics()

        #setup the visibles
        self.setupUi2()
        self.setupWidget1()
        self.setupWidget2()
        self.setupWidget3()
        self.setupWidget4()
        self.refreshStatistics()


        #setup porn_detector
        self.devMode = False
        self.timeToExit = False
        self.pornDectector = porn_detector_final.PornDetector()
        self.pornDetected = False
        self.detectThread = threading.Thread(target = self.detectPorn)
        self.detectThread.start()
        self.alarm = False  #first alarm, then take action

        #setup timer
        self.cleanMinute = 0
        self.MinuteTimer = QTimer()
        self.MinuteTimer.setInterval(1000 * 60)
        self.MinuteTimer.timeout.connect(self.addCleanMinute)
        self.MinuteTimer.start()


        #lauch
        self.mainWindow.show()

        self.connections()

    def addCleanMinute(self):
        self.stat["cleanMinutes"] += 1
        if self.stat["cleanMinutes"] == 60:
            self.self.stat["cleanMinutes"] = 0
            self.stat["cleanHours"] += 1
            self.saveStatistics()
            self.refreshStatistics()
            self.checkLevel()

    def call_zqz(self):
        if self.settings["game_type"] == 0:
            os.system("python2 easy_maze/PyMaze.py")
        else :
            os.system("python2 esay_game/play.py")
        QtWidgets.QMessageBox.information(None, "bluer", "你有10s的时间关掉黄黄的东西。")
        time.sleep(10)



    def detectPorn(self):
        while(True):
            if "PORN_DETECTED" == self.pornDectector.porn_detector(self.settings["image_detect"], self.settings["text_detect"], self.devMode):
                if self.alarm:
                    self.call_zqz()
                    self.stat["cleanHours"] -= 24
                    if self.stat["cleanHours"] < 0:
                        self.stat["cleanHours"] = 0

                    l = self.stat["stat"][time.localtime(time.time())[6]]
                    h = time.localtime(time.time())[3]
                    if h >= 0 and h < 6:
                        l[0] = 1
                    elif h >= 6 and h < 12:
                        l[1] = 1
                    elif h >= 12 and h < 18:
                        l[2] = 1;
                    else:
                        l[3] = 1;
                else:
                    self.alarm = True
            else:
                self.alarm = True

                self.saveStatistics()
                self.refreshStatistics()

            time.sleep(10)

    def onClose(self, event):
        self.mainWindow.hide()
        event.ignore()

    def onTrayClicked(self, event):
        if event == QSystemTrayIcon.Trigger or event == QSystemTrayIcon.DoubleClick:
            self.mainWindow.show()

    def saveSettings(self, event):
        QtWidgets.QMessageBox.Question = QIcon("res/logo-tray.png")
        if self.settings["goal"] != self.ui.spin_goal.value():
            ret = QtWidgets.QMessageBox.question(self.mainWindow, "Blue", "确定要将目标改为" + str(self.ui.spin_goal.value()) + "天吗?\n"
                                                 "此操作会重置当前任务的进度。")

            if ret != QtWidgets.QMessageBox.No:
                self.settings["goal"] = self.ui.spin_goal.value()
                self.saveStatistics()
                self.refreshStatistics()
                QtWidgets.QMessageBox.information(None, "Blue", "新目标设置为" + str(self.settings["goal"]) + "天")
            else:
                QtWidgets.QMessageBox.information(None, "Blue", "目标没有被重置")

        try:
            sfile = open(PATH_TO_SETTINGS, "w")
            json.dump(self.settings, sfile)
            sfile.close()
        except Exception:
            return

        QtWidgets.QMessageBox.information(None, "Blue", "设置已保存:D")

        self.refreshStatistics()

    def checkLevel(self):
        for i in range(5, -1, -1):
            if self.stat["cleanHours"] >= self.achivementsStd[i] and self.stat["achivement"] < i:
                QtWidgets.QMessageBox.information(None, "Blue", "等级提升为Lv. " + str(i) + " :" + self.achivementsList[i])
                self.stat["achivement"] = i
                self.saveStatistics()
                break

    def saveStatistics(self):
        json.dump(self.stat, open(PATH_TO_STATISTICS, "w"))

    def refreshStatistics(self):
        days = time.localtime(time.time())

        delta = self.settings["goal"] - self.stat["cleanHours"]

        if delta == 0:
            QtWidgets.QMessageBox.information(None, "Blue", "目标达成!!!\n请设置新的目标!!!")
            self.slideClicked3(None)

        self.ui.lb_days.setText(str(delta))
        self.ui.lb_goal.setText(str(self.settings["goal"]))
        self.ui.lb_achv.setText(self.achivementsList[self.stat["achivement"]])
        self.ui.lb_lv.setText("Lv. " + str(self.stat["achivement"]))
        self.ui.lb_growth.setText(str(self.stat["cleanHours"] // 24))

        #setup the water and ferilization
        if days[7] == time.localtime(self.stat["lastWater"])[7]:
            self.ui.lb_jiaoshui.setPixmap(QPixmap("res/ack.png"))
            self.watered = True
        else:
            self.watered = False

        if days[7] == time.localtime(self.stat["lastFertilize"])[7]:
            self.ui.lb_shifei.setPixmap(QPixmap("res/ack.png"))
            self.fertilized = True
        else:
            self.fertilized = False



        #setup the calendar
        pixmapA = QPixmap("res/lu.png")
        pixmapB = QPixmap("res/blue.png")

        h = days[3]
        if h >= 0 and h < 6:
            r = 0
        elif h >= 6 and h < 12:
            r = 1
        elif h >= 12 and h < 18:
            r = 2
        else:
            r = 3

        for i in range(days[6]):
            for j in range(4):
                if self.stat["stat"][i][j] == 0:
                    self.statLabels[i][j].setPixmap(pixmapA)
                else:
                    self.statLabels[i][j].setPixmap(pixmapB)

        day = days[6]
        for j in range(r):
            if self.stat["stat"][day][j] == 0:
                self.statLabels[day][j].setPixmap(pixmapA)
            else:
                self.statLabels[day][j].setPixmap(pixmapB)

        #setup the wall
        for i in range(6):
            self.achivIcons[i].setPixmap(QPixmap("res/" + str(i) * 2))

        for i in range(self.stat["achivement"] + 1):
            self.achivIcons[i].setPixmap(QPixmap("res/" + str(i)))


    def loadSettings(self):
        try:
            sfile = open(PATH_TO_SETTINGS, "r")
            self.settings = json.load(sfile)
            sfile.close()
        except:
            self.settings = self.defaultSettings
            self.saveSettings(None)

    def validateSettings(self):
        for keys in self.defaultSettings:
            try:
                self.settings[keys]
            except:
                self.settings[keys] = self.defaultSettings[keys]

    def loadStatistics(self):
        try:
            sfile = open(PATH_TO_STATISTICS, "r")
            self.stat = json.load(sfile)
        except:
            self.stat = self.defaultStat

        for keys in self.defaultStat:
            try:
                self.stat[keys]
            except:
                self.stat[keys] = self.defaultStat[keys]
        self.saveStatistics()

    def refreshInfo(self):
        #setup avata
        pixmap = QPixmap()
        pixmap.load("res/avata_mask")
        pixmap.scaled(115, 115)
        self.ui.lb_avata.setMask(pixmap.mask())
        pixmap.load(self.settings["avata"])
        self.ui.lb_avata.setPixmap(pixmap)

#        self.ui.lb_avata2.setMask(pixmap.mask())
#        pixmap.load(self.settings["avata"])
#        self.ui.lb_avata2.setPixmap(pixmap)


        #setup the name
        self.ui.lb_welcomname.setText(self.settings["name"])
        self.ui.lb_nick.setText(self.settings["name"])



    def appExit(self, event):
        if self.devMode == False:
            QtWidgets.QMessageBox.information(None, "bluer", "开发者模式开启")
            self.devMode = True
        else:
            QtWidgets.QMessageBox.information(None, "bluer", "开发者模式关闭")
            self.devMode = False

    def avataEdit(self, event):
        openDlg = QtWidgets.QFontDialog()
        openDlg.open()

    def setupUi2(self):
        #setup event handling
        self.sideButtons = [self.ui.lb1, self.ui.lb2, self.ui.lb3, self.ui.lb4]
        self.ui.lb_exit.mousePressEvent = self.appExit
        self.setupAnimes()
        self.setupSideButtons()
        self.refreshInfo()

        #setup tray
        self.icon = QIcon("res/logo-tray.png")
        self.trayIcon = QSystemTrayIcon()
        self.trayIcon.setIcon(self.icon)
        self.trayIcon.activated.connect(self.onTrayClicked)
        self.trayIcon.show()

        #setup the info edit
        self.ui.lb_avata.mousePressEvent = self.avataEdit

    def setupAnimes(self):
        self.shiftAnime1 = QPropertyAnimation()
        self.shiftAnime1.setTargetObject(self.ui.widget1)
        self.shiftAnime1.setPropertyName("geometry".encode())
        self.shiftAnime1.setDuration(400)
        self.shiftAnime1.setStartValue(QRect(177, 29, 0, 571))
        self.shiftAnime1.setEndValue(QRect(177, 29, 623, 571))

        self.shiftAnime2 = QPropertyAnimation()
        self.shiftAnime2.setTargetObject(self.ui.widget2)
        self.shiftAnime2.setPropertyName("geometry".encode())
        self.shiftAnime2.setDuration(400)
        self.shiftAnime2.setStartValue(QRect(800, 29, 0, 571))
        self.shiftAnime2.setEndValue(QRect(177, 29, 623, 571))

        self.shiftAnime3 = QPropertyAnimation()
        self.shiftAnime3.setTargetObject(self.ui.widget3)
        self.shiftAnime3.setPropertyName("geometry".encode())
        self.shiftAnime3.setDuration(400)
        self.shiftAnime3.setStartValue(QRect(800, 29, 623, 571))
        self.shiftAnime3.setEndValue(QRect(177, 29, 623, 571))

        self.shiftAnime4 = QPropertyAnimation()
        self.shiftAnime4.setTargetObject(self.ui.widget4)
        self.shiftAnime4.setPropertyName("geometry".encode())
        self.shiftAnime4.setDuration(400)
        self.shiftAnime4.setStartValue(QRect(800, 29, 623, 571))
        self.shiftAnime4.setEndValue(QRect(177, 29, 623, 571))

        self.selectedWidget = self.ui.widget1


    def setSlideMid(self, bt):
        if self.selectedSideButton != bt:
            bt.setStyleSheet(slide_bt_mid)

    def setSlideUp(self, bt):
        if self.selectedSideButton != bt:
            bt.setStyleSheet(slide_bt_up)

    def setSlideDown(self, bt):
        self.selectedSideButton.setStyleSheet(slide_bt_up)
        self.selectedSideButton = bt
        bt.setStyleSheet(slide_bt_down)


    def slideEnter1(self, event):
        self.setSlideMid(self.ui.lb1)

    def slideEnter2(self, event):
        self.setSlideMid(self.ui.lb2)

    def slideEnter3(self, event):
        self.setSlideMid(self.ui.lb3)

    def slideEnter4(self, event):
        self.setSlideMid(self.ui.lb4)

    def slideLeave1(self, event):
        self.setSlideUp(self.ui.lb1)

    def slideLeave2(self, event):
        self.setSlideUp(self.ui.lb2)

    def slideLeave3(self, event):
        self.setSlideUp(self.ui.lb3)

    def slideLeave4(self, event):
        self.setSlideUp(self.ui.lb4)

    def slideBack(self, event):
        self.setSlideDown(self.ui.lb1)
        self.ui.widget1.raise_()
        self.shiftAnime1.start()
        self.selectedWidget = self.ui.widget1

    def slideClicked1(self, event):
        self.setSlideDown(self.ui.lb1)
        if self.selectedWidget != self.ui.widget1:
            self.ui.widget1.raise_()
            self.shiftAnime1.start()
            self.selectedWidget = self.ui.widget1

    def slideClicked2(self, event):
        self.setSlideDown(self.ui.lb2)
        if self.selectedWidget != self.ui.widget2:
            self.ui.widget2.raise_()
            self.shiftAnime2.start()
            self.selectedWidget = self.ui.widget2

    def slideClicked3(self, event):
        self.setSlideDown(self.ui.lb3)
        if self.selectedWidget != self.ui.widget3:
            self.ui.widget3.raise_()
            self.shiftAnime3.start()
            self.selectedWidget = self.ui.widget3

    def jiaoshuiCheck(self, event):
        pixmap = QPixmap()
        pixmap.load("res/ack.png")
        self.ui.lb_jiaoshui.setPixmap(pixmap)
        self.stat["lastWater"] = time.time()
        self.saveStatistics()

    def shifeiCheck(self, event):
        pixmap = QPixmap()
        pixmap.load("res/ack.png")
        self.ui.lb_shifei.setPixmap(pixmap)
        self.stat["lastFertilize"] = time.time()
        self.saveStatistics()


    def slideClicked4(self, event):
        self.setSlideDown(self.ui.lb4)
        if self.selectedWidget != self.ui.widget4:
            self.ui.widget4.raise_()
            self.shiftAnime4.start()
            self.selectedWidget = self.ui.widget4

    def setupWidget1(self):
        #setup the tree
        movie = QMovie()
        movie.setFileName("res/tree.gif")
        self.ui.lb_tree.setMovie(movie)
        self.ui.lb_tree_big.setMovie(movie)
        movie.start()

        #setup the statistics
        self.ui.gridLayout.setHorizontalSpacing(60)
        self.ui.gridLayout.setVerticalSpacing(10)
        self.ui.gridLayout.setGeometry(QRect(0, 51, 291, 224))
        self.ui.gridLayout.setAlignment(QtCore.Qt.AlignCenter)
        self.statLabels = []
        for i in range(7):
            self.statLabels.append([])
            for j in range(4):
                self.statLabels[i].append(QLabel())
                self.statLabels[i][j].setScaledContents(True)
                self.statLabels[i][j].setAutoFillBackground(False)
                self.statLabels[i][j].setAlignment(QtCore.Qt.AlignCenter)
                self.ui.gridLayout.addWidget(self.statLabels[i][j], i, j, 1, 1)

    def setupWidget2(self):
        self.ui.lb_jiaoshui.mousePressEvent = self.jiaoshuiCheck
        self.ui.lb_shifei.mousePressEvent = self.shifeiCheck

    def setupWidget3(self):
        self.ui.check_maze.mousePressEvent = self.mazeCliked
        self.ui.check_paper.mousePressEvent = self.paperCliked
        self.ui.check_pic.mousePressEvent = self.picCliked
        self.ui.check_text.mousePressEvent = self.textClicked
        self.ui.lb_save.mousePressEvent = self.saveSettings

        self.ui.spin_goal.setValue(self.settings["goal"])

        if self.settings["game_type"] == 0:
            self.mazeCliked(None)
        else:
            self.paperCliked(None)

        self.picCliked(None)
        self.picCliked(None)

        self.textClicked(None)
        self.textClicked(None)

    def setupWidget4(self):
        self.achivIcons = [self.ui.lb_a0, self.ui.lb_a1, self.ui.lb_a2,
                           self.ui.lb_a3, self.ui.lb_a4, self.ui.lb_a5]

        for i in range(6):
            self.achivIcons[i].setPixmap(QPixmap("res/" + str(i) * 2))

    def mazeCliked(self, event):
        pixmap = QPixmap()
        pixmap.load("res/checked.png")
        self.ui.check_maze.setPixmap(pixmap)

        pixmap.load("res/unchecked.png")
        self.ui.check_paper.setPixmap(pixmap)

        self.settings["game_type"] = 0

    def paperCliked(self, event):
        pixmap = QPixmap()
        pixmap.load("res/checked.png")
        self.ui.check_paper.setPixmap(pixmap)

        pixmap.load("res/unchecked.png")
        self.ui.check_maze.setPixmap(pixmap)

        self.settings["game_type"] = 1

    def picCliked(self, event):
        pixmap = QPixmap()
        pixmap.load("res/checked.png")
        self.ui.check_pic.setPixmap(pixmap)

        pixmap.load("res/unchecked.png")
        self.ui.check_text.setPixmap(pixmap)

        self.settings["pic_detect"] = 1
        self.settings["text_detect"] = 0


    def textClicked(self, event):
        pixmap = QPixmap()
        pixmap.load("res/checked.png")
        self.ui.check_text.setPixmap(pixmap)

        pixmap.load("res/unchecked.png")
        self.ui.check_pic.setPixmap(pixmap)

        self.settings["pic_detect"] = 1
        self.settings["text_detect"] = 1

    def setupSideButtons(self):
        self.ui.lb1.enterEvent = self.slideEnter1
        self.ui.lb1.leaveEvent = self.slideLeave1
        self.ui.lb1.mousePressEvent = self.slideClicked1
        self.ui.lb2.enterEvent = self.slideEnter2
        self.ui.lb2.leaveEvent = self.slideLeave2
        self.ui.lb2.mousePressEvent = self.slideClicked2
        self.ui.lb3.enterEvent = self.slideEnter3
        self.ui.lb3.leaveEvent = self.slideLeave3
        self.ui.lb3.mousePressEvent = self.slideClicked3
        self.ui.lb4.enterEvent = self.slideEnter4
        self.ui.lb4.leaveEvent = self.slideLeave4
        self.ui.lb4.mousePressEvent = self.slideClicked4
        self.ui.lb4.enterEvent = self.slideEnter4
        self.ui.lb4.leaveEvent = self.slideLeave4
        self.ui.lb4.mousePressEvent = self.slideClicked4


        self.ui.lb_back2.mousePressEvent = self.slideBack
        self.ui.lb_back3.mousePressEvent = self.slideBack
        self.ui.lb_back4.mousePressEvent = self.slideBack


        for lb in self.sideButtons:
            lb.setStyleSheet(slide_bt_up)
        self.selectedSideButton = self.ui.lb1
        self.slideClicked1(None)

    def connections(self):
        pass
예제 #32
0
class Widgets(QWidget):
    def __init__(self, parent=None):
        super(Widgets, self).__init__(parent)

        self.parent = parent

        self.initUI()

    def initUI(self):

        # ======================== WIDGETS ===========================

        framePrincipal = QFrame(self)
        framePrincipal.setFrameShape(QFrame.Box)
        framePrincipal.setFrameShadow(QFrame.Sunken)
        framePrincipal.setAutoFillBackground(True)
        framePrincipal.setBackgroundRole(QPalette.Light)
        framePrincipal.setFixedSize(662, 503)
        framePrincipal.move(10, 10)

        frame = QFrame(framePrincipal)
        frame.setFixedSize(640, 480)
        frame.move(10, 10)

        self.labelImagen = QLabel(frame)
        self.labelImagen.setAlignment(Qt.AlignCenter)
        self.labelImagen.setGeometry(0, 0, 640, 480)
        # self.labelImagen.setScaledContents(True)

        self.labelImagenUno = QLabel(frame)
        self.labelImagenUno.setAlignment(Qt.AlignCenter)
        self.labelImagenUno.setGeometry(-650, 0, 640, 480)

        # =================== BOTONES (QPUSHBUTTON) ==================

        self.buttonCargar = QPushButton("Cargar imagen", self)
        self.buttonCargar.setCursor(Qt.PointingHandCursor)
        self.buttonCargar.setFixedSize(325, 30)
        self.buttonCargar.move(10, 519)

        self.buttonEliminar = QPushButton("Eliminar imagen", self)
        self.buttonEliminar.setCursor(Qt.PointingHandCursor)
        self.buttonEliminar.setFixedSize(255, 30)
        self.buttonEliminar.move(345, 519)

        self.buttonAnterior = QPushButton("<", self)
        self.buttonAnterior.setObjectName("Anterior")
        self.buttonAnterior.setToolTip("Imagen anterior")
        self.buttonAnterior.setCursor(Qt.PointingHandCursor)
        self.buttonAnterior.setFixedSize(30, 30)
        self.buttonAnterior.move(607, 519)

        self.buttonSiguiente = QPushButton(">", self)
        self.buttonSiguiente.setObjectName("Siguiente")
        self.buttonSiguiente.setToolTip("Imagen siguiente")
        self.buttonSiguiente.setCursor(Qt.PointingHandCursor)
        self.buttonSiguiente.setFixedSize(30, 30)
        self.buttonSiguiente.move(642, 519)

        # ===================== CONECTAR SEÑALES =====================

        self.buttonCargar.clicked.connect(self.Cargar)
        self.buttonEliminar.clicked.connect(self.Eliminar)
        self.buttonAnterior.clicked.connect(self.anteriorSiguiente)
        self.buttonSiguiente.clicked.connect(self.anteriorSiguiente)

        # Establecer los valores predeterminados
        self.posicion = int
        self.estadoAnterior, self.estadoSiguiente = False, False
        self.carpetaActual = QDir()
        self.imagenesCarpeta = []

# ======================= FUNCIONES ==============================

    def bloquearBotones(self, bool):
        self.buttonCargar.setEnabled(bool)
        self.buttonEliminar.setEnabled(bool)
        self.buttonAnterior.setEnabled(bool)
        self.buttonSiguiente.setEnabled(bool)

    def Mostrar(self, label, imagen, nombre, posicionX=650):
        imagen = QPixmap.fromImage(imagen)

        # Escalar imagen a 640x480 si el ancho es mayor a 640 o el alto mayor a 480
        if imagen.width() > 640 or imagen.height() > 480:
            imagen = imagen.scaled(640, 480, Qt.KeepAspectRatio,
                                   Qt.SmoothTransformation)

        # Mostrar imagen
        label.setPixmap(imagen)

        # Animación (al finalizar la animación se muestra en la barra de estado el nombre y la extensión de la imagen
        # y se desbloquean los botones).
        self.animacionMostar = QPropertyAnimation(label, b"geometry")
        self.animacionMostar.finished.connect(
            lambda: (self.parent.statusBar.showMessage(nombre),
                     self.bloquearBotones(True)))
        self.animacionMostar.setDuration(200)
        self.animacionMostar.setStartValue(QRect(posicionX, 0, 640, 480))
        self.animacionMostar.setEndValue(QRect(0, 0, 640, 480))
        self.animacionMostar.start(QAbstractAnimation.DeleteWhenStopped)

    def Limpiar(self,
                labelConImagen,
                labelMostrarImagen,
                imagen,
                nombre,
                posicionInternaX,
                posicionX=None):
        def Continuar(estado):
            if estado:
                if posicionX:
                    self.Mostrar(labelMostrarImagen, imagen, nombre, posicionX)
                else:
                    self.Mostrar(labelMostrarImagen, imagen, nombre)

        self.animacionLimpiar = QPropertyAnimation(labelConImagen, b"geometry")
        self.animacionLimpiar.finished.connect(lambda: labelConImagen.clear())
        self.animacionLimpiar.setDuration(200)
        # self.animacionLimpiar.valueChanged.connect(lambda x: print(x))
        self.animacionLimpiar.stateChanged.connect(Continuar)
        self.animacionLimpiar.setStartValue(QRect(0, 0, 640, 480))
        self.animacionLimpiar.setEndValue(QRect(posicionInternaX, 0, 640, 480))
        self.animacionLimpiar.start(QAbstractAnimation.DeleteWhenStopped)

    def Cargar(self):
        nombreImagen, _ = QFileDialog.getOpenFileName(
            self, "Seleccionar imagen", QDir.currentPath(),
            "Archivos de imagen (*.jpg *.png *.ico *.bmp)")

        if nombreImagen:
            # Verificar que QLabel tiene imagen
            labelConImagen = ""
            if self.labelImagen.pixmap():
                labelConImagen = self.labelImagen
            elif self.labelImagenUno.pixmap():
                labelConImagen = self.labelImagenUno

            imagen = QImage(nombreImagen)
            if imagen.isNull():
                if labelConImagen:
                    self.Eliminar()

                QMessageBox.information(
                    self, "Visor de imágenes",
                    "No se puede cargar %s." % nombreImagen)
                return

            # Obtener ruta de la carpeta que contiene la imagen seleccionada
            self.carpetaActual = QDir(
                QFileInfo(nombreImagen).absoluteDir().path())

            # Obtener la ruta y el nombre de las imagenes que se encuentren en la carpeta de
            # la imagen seleccionada
            imagenes = self.carpetaActual.entryInfoList(
                ["*.jpg", "*.png", "*.ico", "*.bmp"], QDir.Files, QDir.Name)
            self.imagenesCarpeta = [
                imagen.absoluteFilePath() for imagen in imagenes
            ]

            self.posicion = self.imagenesCarpeta.index(nombreImagen)
            self.estadoAnterior = True if self.posicion == 0 else False
            self.estadoSiguiente = True if self.posicion == len(
                self.imagenesCarpeta) - 1 else False

            # Función encargada de bloquear o desbloquear los botones
            self.bloquearBotones(False)

            # Nombre y extensión de la imagen
            nombre = QFileInfo(nombreImagen).fileName()

            if labelConImagen:
                posicionInternaX = -650
                labelMostrarImagen = self.labelImagen if self.labelImagenUno.pixmap(
                ) else self.labelImagenUno
                self.Limpiar(labelConImagen, labelMostrarImagen, imagen,
                             nombre, posicionInternaX)
            else:
                self.Mostrar(self.labelImagen, imagen, nombre)

    def Eliminar(self):
        def establecerValores():
            labelConImagen.clear()
            labelConImagen.move(0, 0)

            # Limpiar la barra de estado
            self.parent.statusBar.clearMessage()

            # Establecer los valores predeterminados
            self.posicion = int
            self.estadoAnterior, self.estadoSiguiente = False, False
            self.carpetaActual = QDir()
            self.imagenesCarpeta.clear()

            self.bloquearBotones(True)

        # Verificar que QLabel tiene imagen
        labelConImagen = ""
        if self.labelImagen.pixmap():
            labelConImagen = self.labelImagen
        elif self.labelImagenUno.pixmap():
            labelConImagen = self.labelImagenUno

        if labelConImagen:
            self.bloquearBotones(False)

            self.animacionEliminar = QPropertyAnimation(
                labelConImagen, b"geometry")
            self.animacionEliminar.finished.connect(establecerValores)
            self.animacionEliminar.setDuration(200)
            self.animacionEliminar.setStartValue(QRect(0, 0, 640, 480))
            self.animacionEliminar.setEndValue(QRect(-650, 0, 640, 480))
            self.animacionEliminar.start(QAbstractAnimation.DeleteWhenStopped)

    def anteriorSiguiente(self):
        if self.imagenesCarpeta:
            widget = self.sender().objectName()

            if widget == "Anterior":
                self.estadoAnterior = True if self.posicion == 0 else False
                self.estadoSiguiente = False

                self.posicion -= 1 if self.posicion > 0 else 0
                posicionInternaX, posicionX = 650, -650
            else:
                self.estadoSiguiente = True if self.posicion == len(
                    self.imagenesCarpeta) - 1 else False
                self.estadoAnterior = False

                self.posicion += 1 if self.posicion < len(
                    self.imagenesCarpeta) - 1 else 0
                posicionInternaX, posicionX = -650, 650

            if self.estadoAnterior or self.estadoSiguiente:
                return
            else:
                imagen = self.imagenesCarpeta[self.posicion]

                # Verificar que la carpeta que contiene la imagene exista
                if not QDir(self.carpetaActual).exists():
                    self.Eliminar()
                    return
                elif not QFile.exists(imagen):
                    # Obtener la ruta y el nombre de las imagenes que se encuentren en la
                    # carpeta de la imagen seleccionada
                    imagenes = self.carpetaActual.entryInfoList(
                        ["*.jpg", "*.png", "*.ico", "*.bmp"], QDir.Files,
                        QDir.Name)

                    if not imagenes:
                        self.Eliminar()
                        return

                    self.imagenesCarpeta = [
                        imagen.absoluteFilePath() for imagen in imagenes
                    ]

                    self.posicion = randint(0, len(self.imagenesCarpeta) - 1)
                    self.estadoAnterior = True if self.posicion == 0 else False
                    self.estadoSiguiente = True if self.posicion == len(
                        self.imagenesCarpeta) - 1 else False
                elif QImage(imagen).isNull():
                    del self.imagenesCarpeta[self.posicion]

                    if not self.imagenesCarpeta:
                        self.Eliminar()
                        return

                    self.posicion = randint(0, len(self.imagenesCarpeta) - 1)
                    self.estadoAnterior = True if self.posicion == 0 else False
                    self.estadoSiguiente = True if self.posicion == len(
                        self.imagenesCarpeta) - 1 else False

                imagen = self.imagenesCarpeta[self.posicion]

                if self.labelImagen.pixmap():
                    labelConImagen = self.labelImagen
                elif self.labelImagenUno.pixmap():
                    labelConImagen = self.labelImagenUno

                # Función encargada de bloquear o desbloquear los botones
                self.bloquearBotones(False)

                # Nombre y extensión de la imagen
                nombre = QFileInfo(imagen).fileName()

                # Label en el que se va a mostrar la imagen
                labelMostrarImagen = self.labelImagen if self.labelImagenUno.pixmap(
                ) else self.labelImagenUno

                # Quitar la imagen actual y mostrar la siguiente
                self.Limpiar(labelConImagen, labelMostrarImagen,
                             QImage(imagen), nombre, posicionInternaX,
                             posicionX)
예제 #33
0
from PyQt5.QtCore import QPropertyAnimation, QEasingCurve


animation = QPropertyAnimation()
animation.setTargetObject()
animation.setStartValue(0)
animation.setEndValue(1000)
animation.setDuration(1000)
animation.setEasingCurve(QEasingCurve.InOutQuad)

animation.start()
예제 #34
0
class StateToolTip(QWidget):
    """ 进度提示框 """
    def __init__(self,
                 title='',
                 content='',
                 associatedThread=None,
                 parent=None):
        super().__init__(parent)
        self.title = title
        self.content = content
        self.associatedThread = associatedThread
        # 实例化小部件
        self.createWidgets()
        # 初始化参数
        self.isDone = False
        self.rotateAngle = 0
        self.deltaAngle = 18
        # 初始化
        self.initWidget()
        self.initLayout()
        self.setQss()

    def createWidgets(self):
        """ 创建小部件 """
        icon_path = {
            'normal':
            r'resource\images\createPlaylistPanel\stateToolTip_closeBt_normal_14_14.png',
            'hover':
            r'resource\images\createPlaylistPanel\stateToolTip_closeBt_hover_14_14.png',
            'pressed':
            r'resource\images\createPlaylistPanel\stateToolTip_closeBt_hover_14_14.png'
        }

        self.closeButton = ThreeStateButton(icon_path, self, (14, 14))
        self.titleLabel = QLabel(self.title, self)
        self.contentLabel = QLabel(self.content, self)
        self.rotateTimer = QTimer(self)
        self.closeTimer = QTimer(self)
        self.animation = QPropertyAnimation(self, b'windowOpacity')
        self.busyImage = QPixmap(
            r'resource\images\createPlaylistPanel\running_22_22.png')
        self.doneImage = QPixmap(
            r'resource\images\createPlaylistPanel\complete_20_20.png')

    def initWidget(self):
        """ 初始化小部件 """
        self.setFixedSize(370, 60)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window)
        self.rotateTimer.setInterval(50)
        self.closeTimer.setInterval(3000)
        self.contentLabel.setMinimumWidth(200)
        # 分配ID
        self.titleLabel.setObjectName('titleLabel')
        self.contentLabel.setObjectName('contentLabel')
        # 将信号连接到槽函数
        self.closeButton.clicked.connect(self.closeButtonEvent)
        self.rotateTimer.timeout.connect(self.timeOutEvent)
        self.closeTimer.timeout.connect(self.slowlyClose)
        # 打开定时器
        self.rotateTimer.start()

    def initLayout(self):
        """ 初始化布局 """
        self.titleLabel.move(39, 11)
        self.contentLabel.move(15, 34)
        self.closeButton.move(self.width() - 29, 23)

    def setQss(self):
        """ 设置层叠样式 """
        with open(r'resource\css\stateToolTip.qss', encoding='utf-8') as f:
            self.setStyleSheet(f.read())

    def setTitle(self, title):
        """ 更新提示框的标题 """
        self.title = title
        self.titleLabel.setText(title)

    def setContent(self, content):
        """ 更新提示框内容 """
        self.content = content
        self.contentLabel.setText(content)

    def setState(self, isDone=False):
        """ 设置运行状态 """
        self.isDone = isDone
        self.update()
        # 运行完成后主动关闭窗口
        if self.isDone:
            self.closeTimer.start()

    def closeButtonEvent(self):
        """ 按下关闭按钮前摧毁相关线程 """
        if self.associatedThread:
            self.associatedThread.stop()
            self.associatedThread.requestInterruption()
            self.associatedThread.wait()
        self.deleteLater()

    def slowlyClose(self):
        """ 缓慢关闭窗口 """
        self.rotateTimer.stop()
        self.animation.setEasingCurve(QEasingCurve.Linear)
        self.animation.setDuration(500)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        self.animation.finished.connect(self.deleteLater)
        self.animation.start()

    def timeOutEvent(self):
        """ 定时器溢出时旋转箭头 """
        self.rotateAngle = (self.rotateAngle + self.deltaAngle) % 360
        self.update()

    def paintEvent(self, QPaintEvent):
        """ 绘制背景 """
        super().paintEvent(QPaintEvent)
        # 绘制旋转箭头
        painter = QPainter(self)
        painter.setRenderHints(QPainter.SmoothPixmapTransform)
        painter.setPen(Qt.NoPen)
        if not self.isDone:
            painter.translate(24, 20)  # 原点平移到旋转中心
            painter.rotate(self.rotateAngle)  # 坐标系旋转
            painter.drawPixmap(-int(self.busyImage.width() / 2),
                               -int(self.busyImage.height() / 2),
                               self.busyImage)
        else:
            painter.drawPixmap(14, 13, self.doneImage.width(),
                               self.doneImage.height(), self.doneImage)

    def show(self):
        """ 重写show()函数 """
        if self.parent():
            self.move(
                self.parent().x() + self.parent().width() - self.width() - 30,
                self.parent().y() + 70)
        super().show()
예제 #35
0
class RecoveryKeyExporter(QObject):

    done = pyqtSignal(str)

    def __init__(self, parent=None):
        super(RecoveryKeyExporter, self).__init__(parent)
        self.parent = parent
        self.filepath = None
        self.progress = None
        self.animation = None
        self.crypter = None
        self.crypter_thread = None
        self.ciphertext = None

    def _on_encryption_failed(self, message):
        self.crypter_thread.quit()
        error(self.parent, "Error encrypting data", message)
        self.crypter_thread.wait()

    def _on_encryption_succeeded(self, ciphertext):
        self.crypter_thread.quit()
        if self.filepath:
            with atomic_write(self.filepath, mode="wb", overwrite=True) as f:
                f.write(ciphertext)
            self.done.emit(self.filepath)
            self.filepath = None
        else:
            self.ciphertext = ciphertext
        self.crypter_thread.wait()

    def _export_encrypted_recovery(self, gateway, password):
        settings = gateway.get_settings(include_rootcap=True)
        if gateway.use_tor:
            settings["hide-ip"] = True
        data = json.dumps(settings)
        self.progress = QProgressDialog("Encrypting...", None, 0, 100)
        self.progress.show()
        self.animation = QPropertyAnimation(self.progress, b"value")
        self.animation.setDuration(6000)  # XXX
        self.animation.setStartValue(0)
        self.animation.setEndValue(99)
        self.animation.start()
        self.crypter = Crypter(data.encode(), password.encode())
        self.crypter_thread = QThread()
        self.crypter.moveToThread(self.crypter_thread)
        self.crypter.succeeded.connect(self.animation.stop)
        self.crypter.succeeded.connect(self.progress.close)
        self.crypter.succeeded.connect(self._on_encryption_succeeded)
        self.crypter.failed.connect(self.animation.stop)
        self.crypter.failed.connect(self.progress.close)
        self.crypter.failed.connect(self._on_encryption_failed)
        self.crypter_thread.started.connect(self.crypter.encrypt)
        self.crypter_thread.start()
        dest, _ = QFileDialog.getSaveFileName(
            self.parent,
            "Select a destination",
            os.path.join(
                os.path.expanduser("~"),
                gateway.name + " Recovery Key.json.encrypted",
            ),
        )
        if not dest:
            return
        if self.ciphertext:
            with atomic_write(dest, mode="wb", overwrite=True) as f:
                f.write(self.ciphertext)
            self.done.emit(dest)
            self.ciphertext = None
        else:
            self.filepath = dest

    def _export_plaintext_recovery(self, gateway):
        dest, _ = QFileDialog.getSaveFileName(
            self.parent,
            "Select a destination",
            os.path.join(os.path.expanduser("~"),
                         gateway.name + " Recovery Key.json"),
        )
        if not dest:
            return
        try:
            gateway.export(dest, include_rootcap=True)
        except Exception as e:  # pylint: disable=broad-except
            error(self.parent, "Error exporting Recovery Key", str(e))
            return
        self.done.emit(dest)

    def do_export(self, gateway):
        password, ok = PasswordDialog.get_password(
            self.parent,
            "Encryption passphrase (optional):",
            "A long passphrase will help keep your files safe in the event "
            "that your Recovery Key is ever compromised.",
        )
        if ok and password:
            self._export_encrypted_recovery(gateway, password)
        elif ok:
            self._export_plaintext_recovery(gateway)
예제 #36
0
class FlatTabWidget(QWidget):
    tabClicked = pyqtSignal(int)
    scrolledUp = pyqtSignal()
    scrolledDown = pyqtSignal()
    fadein = True # 是否添加淡入效果,默认True,注意需要设置边框为none,不然会变形

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

        self.setupUi()

        self.normal_color = ResourceLoader().qt_color_sub_text
        self.active_color = ResourceLoader().qt_color_text

        self.currentSelection = 0
        self.lineMorph = QPropertyAnimation()
        self.pages = []
        self.enqueueSeparatorRepaint = True
        self.animatePageChange = True
        self.customSW = None
        self.detachCustomStackedWidget = False

        def scrolledUp():
            if self.currentSelection - 1 < 0 or len(self.pages) == 0:
                return

            self.scrolledUp.emit()
            item = self.pages[self.currentSelection - 1]
            if item.label != None:
                self.setCurrentTab(self.currentSelection - 1)
        self.TabBarContainer.scrolledUp.connect(scrolledUp)

        def scrolledDown():
            if self.currentSelection + 1 >= len(self.pages) or len(self.pages) == 0:
                return

            self.scrolledDown.emit()
            item = self.pages[self.currentSelection + 1]
            if item.label != None:
                self.setCurrentTab(self.currentSelection + 1)
        self.TabBarContainer.scrolledDown.connect(scrolledDown)

    def setupUi(self):
        self.setObjectName("FlatTabWidget")
        self.resize(601, 352)
        self.horizontalLayout = QtWidgets.QHBoxLayout(self)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.MasterLayout = QtWidgets.QVBoxLayout()
        self.MasterLayout.setContentsMargins(-1, 0, -1, -1)
        self.MasterLayout.setSpacing(1)
        self.MasterLayout.setObjectName("MasterLayout")
        self.TabBarContainer = CustomTabBar(self)
        self.TabBarContainer.setMinimumSize(QtCore.QSize(0, 0))
        self.TabBarContainer.setObjectName("TabBarContainer")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.TabBarContainer)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.MasterLayout.addWidget(self.TabBarContainer)
        self.SeparatorContainer = QtWidgets.QWidget(self)
        self.SeparatorContainer.setMinimumSize(QtCore.QSize(0, 5))
        self.SeparatorContainer.setMaximumSize(QtCore.QSize(16777215, 5))
        self.SeparatorContainer.setObjectName("SeparatorContainer")
        self.SeparatorLine = QtWidgets.QLabel(self.SeparatorContainer)
        self.SeparatorLine.setGeometry(QtCore.QRect(0, 0, 100, 1))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.SeparatorLine.sizePolicy().hasHeightForWidth())
        self.SeparatorLine.setSizePolicy(sizePolicy)
        self.SeparatorLine.setMaximumSize(QtCore.QSize(16777215, 1))
        self.SeparatorLine.setFrameShape(QtWidgets.QFrame.HLine)
        self.SeparatorLine.setText("")
        self.SeparatorLine.setObjectName("SeparatorLine")
        self.MasterLayout.addWidget(self.SeparatorContainer)
        self.Content = QtWidgets.QStackedWidget(self)
        self.Content.setObjectName("Content")
        self.MasterLayout.addWidget(self.Content)
        self.horizontalLayout.addLayout(self.MasterLayout)

        self.retranslateUi()
        self.Content.setCurrentIndex(-1)
        QtCore.QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("FlatTabWidget", "FlatTabWidget"))

    def insertWidget(self, layout, reference, widget, pos=InsertPosition.InsertBefore, stretch=0, alignment=0):
        index = -1
        for i, item in enumerate(layout.count()):
            if item.widget() == reference:
                index = i
                break
        if index < 0:
            return False
        if pos == InsertPosition.InsertAfter:
            return False
        layout.insertWidget(index, widget, stretch, alignment)
        return True

    def addPage(self, title, page, index = -1):
        textcolor_active = self.getColor(ColorRole.Active)
        textcolor_disabled = self.getColor(ColorRole.Inactive)

        lbl = ClickableLabel()
        lbl.setText(title)
        if len(self.pages) == 0:
            lbl.setColor(textcolor_active)
            self.currentSelection = 0
        else:
            lbl.setColor(textcolor_disabled)
        lbl.clicked.connect(self.lblHandler)

        if index < 0:
            self.pages.append(FlatTabItem(lbl, page))
        else:
            self.pages.insert(index, FlatTabItem(lbl, page))
        self.updatePages()

    def updatePages(self, overrideSeparator=False):
        activeContainer = self.getActiveStackedWidget()
        spacer = self.TabBarContainer.layout().takeAt(len(self.TabBarContainer.layout()) - 1)
        wItem = self.TabBarContainer.layout().takeAt(0)
        while wItem:
            wItem.widget().hide()
            del wItem
            wItem = self.TabBarContainer.layout().takeAt(0)
        if not self.detachCustomStackedWidget:
            while len(activeContainer) > 0:
                widget = activeContainer.widget(0)
                activeContainer.removeWidget(widget)
        self.TabBarContainer.repaint()

        for page in self.pages:
            self.TabBarContainer.layout().addWidget(page.label)
            if not self.detachCustomStackedWidget:
                activeContainer.addWidget(page.widget)
            page.label.show()

        self.TabBarContainer.layout().addItem(spacer)

        if overrideSeparator:
            self.repaintDivider()

        self.setCurrentTab(self.currentSelection)

    def paintEvent(self, event):
        if self.enqueueSeparatorRepaint:
            if len(self.pages) == 0 or self.currentSelection < 0 or self.currentSelection >= len(self.pages):
                return

            button = self.pages[self.currentSelection].label
            rect = QRect(button.x(), 0, button.width(), button.height())
            self.lineMorph.stop()
            self.SeparatorLine.setGeometry(rect)
            self.enqueueSeparatorRepaint = False

        if event.type() == QPaintEvent.PaletteChange:
            self.redrawTabBar()

        QWidget.paintEvent(self, event)

    def showEvent(self, event):
        self.repaintDivider()
        self.setPalette(self.palette())
        QWidget.showEvent(self, event)

    def redrawTabBar(self):
        for page in self.pages:
            page.label.setColor(self.getColor(ColorRole.Inactive))
        temp = self.currentSelection
        self.setCurrentTab(temp)

    def removePage(self, id):
        textcolor_disabled = self.getColor(ColorRole.Inactive)

        if len(self.pages) != 0 and id >= 0 and id < len(self.pages):
            if id < len(self.pages) - 1:
                self.pages[id + 1].label.setColor(textcolor_disabled)
            self.pages.remove(id)
        self.updatePages()

    def setCurrentTab(self, id):
        if len(self.pages) == 0:
            return
        if id < 0:
            id = 0
        if id >= len(self.pages):
            id = len(self.pages) - 1

        textcolor_active = self.getColor(ColorRole.Active)
        textcolor_disabled = self.getColor(ColorRole.Inactive)
        button = self.pages[id].label
        rect = QRect(button.x(), 0, button.width(), button.height())
        if id == self.currentSelection:
            self.pages[id].label.setColor(textcolor_active)
            self.lineMorph.stop()
            self.SeparatorLine.setGeometry(rect)
        else:
            self.pages[id].fadeIn.stop()
            self.pages[id].fadeOut.stop()
            self.pages[id].fadeIn = QPropertyAnimation(self.pages[id].label, b"_color")
            self.pages[id].fadeIn.setDuration(300)
            self.pages[id].fadeIn.setStartValue(textcolor_disabled)
            self.pages[id].fadeIn.setEndValue(textcolor_active)

            if len(self.pages) > self.currentSelection:
                self.pages[self.currentSelection].fadeIn.stop()
                self.pages[self.currentSelection].fadeOut.stop()
                self.pages[self.currentSelection].fadeOut = QPropertyAnimation(self.pages[self.currentSelection].label, b"_color")
                self.pages[self.currentSelection].fadeOut.setDuration(300)
                self.pages[self.currentSelection].fadeOut.setStartValue(textcolor_active)
                self.pages[self.currentSelection].fadeOut.setEndValue(textcolor_disabled)
                self.pages[self.currentSelection].fadeOut.start()
            self.pages[id].fadeIn.start()

        self.lineMorph.stop()
        self.lineMorph = QPropertyAnimation(self.SeparatorLine, b"geometry")
        self.lineMorph.setDuration(300)
        self.lineMorph.setEasingCurve(QEasingCurve.OutCirc)
        self.lineMorph.setStartValue(self.SeparatorLine.geometry())
        self.lineMorph.setEndValue(rect)
        self.lineMorph.start()

        if self.animatePageChange:
            widget = self.getActiveStackedWidget().widget(id)
            if widget != None:
                if self.fadein:
                    StackedWidgetAnimation.fadeIn(self.getActiveStackedWidget(), widget)
                else:
                    self.getActiveStackedWidget().setCurrentWidget(widget)
        else:
            self.getActiveStackedWidget().setCurrentIndex(id)
        self.currentSelection = id

    def getCurrentTab(self):
        return self.currentSelection

    def repaintDivider(self):
        self.enqueueSeparatorRepaint = True
        self.repaint()

    def getActiveStackedWidget(self):
        if self.customSW != None:
            return self.customSW
        else:
            return self.Content

    def getColor(self, role):
        if role == ColorRole.Active:
            return self.active_color
        else:
            return self.normal_color

        # pal = self.palette()
        # textcolor_active = pal.color(QPalette.ButtonText).darker(0)
        # textcolor_disabled_light = pal.color(QPalette.Disabled, QPalette.WindowText).darker(150)
        # textcolor_disabled_dark = pal.color(QPalette.Disabled, QPalette.WindowText).lighter(150)
        #
        # if role == ColorRole.Active:
        #     return textcolor_active
        # else:
        #     return textcolor_disabled_dark

    def getItem(self, id):
        if id >= 0 and id < len(self.pages):
            return self.pages[id]
        return FlatTabItem()

    def getItem(self, title):
        id = self.getId(title)
        if id < 0:
            return FlatTabItem()
        else:
            return self.getItem(id)

    def getId(self, title):
        for index, page in enumerate(self.pages):
            if page.label.text() == title:
                return index
        return -1

    def lblHandler(self):
        id = self.getId(self.sender().text())
        if id >= 0:
            self.setCurrentTab(id)
            self.tabClicked.emit(id)

    def getDetachCustomStackedWidget(self):
        return self.detachCustomStackedWidget

    def setDetachCustomStackedWidget(self, value):
        self.detachCustomStackedWidget = value

    def getCustomStackWidget(self):
        return self.customSW

    def setCustomStackWidget(self, value):
        self.customSW = value
        if value == None:
            self.Content.show()
        else:
            self.Content.hide()

    def getAnimatePageChange(self):
        return self.animatePageChange

    def setAnimatePageChange(self, value):
        self.animatePageChange = value
예제 #37
0
class RecoveryKeyImporter(QObject):

    done = pyqtSignal(dict)

    def __init__(self, parent=None):
        super(RecoveryKeyImporter, self).__init__()
        self.parent = parent
        self.filepath = None
        self.progress = None
        self.animation = None
        self.crypter = None
        self.crypter_thread = None

    def _on_decryption_failed(self, msg):
        logging.error("%s", msg)
        self.crypter_thread.quit()
        if msg == "Decryption failed. Ciphertext failed verification":
            msg = "The provided passphrase was incorrect. Please try again."
        reply = QMessageBox.critical(
            self.parent,
            "Decryption Error",
            msg,
            QMessageBox.Abort | QMessageBox.Retry,
        )
        self.crypter_thread.wait()
        if reply == QMessageBox.Retry:
            self._load_from_file(self.filepath)

    def _on_decryption_succeeded(self, plaintext):
        logging.debug("Decryption of %s succeeded", self.filepath)
        self.crypter_thread.quit()
        try:
            settings = json.loads(plaintext.decode("utf-8"))
        except (UnicodeDecodeError, json.decoder.JSONDecodeError) as e:
            error(self, type(e).__name__, str(e))
            return
        self.done.emit(settings)
        self.crypter_thread.wait()

    def _decrypt_content(self, data, password):
        logging.debug("Trying to decrypt %s...", self.filepath)
        self.progress = QProgressDialog(
            "Trying to decrypt {}...".format(os.path.basename(self.filepath)),
            None,
            0,
            100,
        )
        self.progress.show()
        self.animation = QPropertyAnimation(self.progress, b"value")
        self.animation.setDuration(6000)  # XXX
        self.animation.setStartValue(0)
        self.animation.setEndValue(99)
        self.animation.start()
        self.crypter = Crypter(data, password.encode())
        self.crypter_thread = QThread()
        self.crypter.moveToThread(self.crypter_thread)
        self.crypter.succeeded.connect(self.animation.stop)
        self.crypter.succeeded.connect(self.progress.close)
        self.crypter.succeeded.connect(self._on_decryption_succeeded)
        self.crypter.failed.connect(self.animation.stop)
        self.crypter.failed.connect(self.progress.close)
        self.crypter.failed.connect(self._on_decryption_failed)
        self.crypter_thread.started.connect(self.crypter.decrypt)
        self.crypter_thread.start()

    def _parse_content(self, content):
        try:
            settings = json.loads(content.decode("utf-8"))
        except (UnicodeDecodeError, json.decoder.JSONDecodeError):
            logging.debug("JSON decoding failed; %s is likely encrypted",
                          self.filepath)
            password, ok = PasswordDialog.get_password(
                self.parent,
                "Decryption passphrase (required):",
                "This Recovery Key is protected by a passphrase. Enter the "
                "correct passphrase to decrypt it.",
                show_stats=False,
            )
            if ok:
                self._decrypt_content(content, password)
            return
        self.done.emit(settings)

    def _load_from_file(self, path):
        logging.debug("Loading %s...", self.filepath)
        try:
            with open(path, "rb") as f:
                content = f.read()
        except Exception as e:  # pylint: disable=broad-except
            error(self, type(e).__name__, str(e))
            return
        self._parse_content(content)

    def _select_file(self):
        dialog = QFileDialog(self.parent, "Select a Recovery Key")
        dialog.setDirectory(os.path.expanduser("~"))
        dialog.setFileMode(QFileDialog.ExistingFile)
        if dialog.exec_():
            return dialog.selectedFiles()[0]
        return None

    def do_import(self, filepath=None):
        if not filepath:
            filepath = self._select_file()
        self.filepath = filepath
        if self.filepath:
            self._load_from_file(self.filepath)
예제 #38
0
class CoffeeFundWindow(QWidget):
    signal_back = pyqtSignal()
    signal_coffee = pyqtSignal()
    signal_account = pyqtSignal()

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

        self.cards = {}  # type: Dict[GuiCards, QWidget]
        """
            Python's GC will clean up QPropertyAnimations as soon as it leaves the button handler,
             therefore they will appear not to work. Use members to store the animations.
            see http://stackoverflow.com/a/6953965
        """
        self.slide_in_animation = None
        self.slide_out_animation = None
        self.animation_group = None
        self.setObjectName("coffeeFundWindow")

        """
            Store the position and size of visible/hidden cards for the animation sequences
        """
        self.hidden_geometry = None
        self.visible_geometry = None

        layout = QStackedLayout()
        layout.setStackingMode(QStackedLayout.StackAll)

        card_remove = RemoveCard()
        self.cards[GuiCards.RemoveCard] = card_remove
        layout.addWidget(card_remove)

        card_choose_action = ChooseActionCard()
        self.cards[GuiCards.ChooseAction] = card_choose_action
        layout.addWidget(card_choose_action)

        card_account = AccountCard()
        self.cards[GuiCards.AccountInfo] = card_account
        layout.addWidget(card_account)

        # keep this as last initialized card, the last card will be shown on startup!
        card_start = StartCard()
        self.cards[GuiCards.Start] = card_start
        layout.addWidget(card_start)

        self.setLayout(layout)
        self.setWindowTitle("Kaffeekasse")

        layout.setCurrentWidget(card_start)
        self.active_card = None

        card_choose_action.button_account.clicked.connect(self.signal_account)
        card_choose_action.button_coffee.clicked.connect(self.signal_coffee)
        card_account.button_back.clicked.connect(self.signal_back)

    def set_card_hidden(self, card: QWidget):
        card.setGeometry(self.hidden_geometry)

    def show_start(self):
        self.show_card(GuiCards.Start)

    def show_account(self, name, value):
        self.cards[GuiCards.AccountInfo].set_user_name(name)
        self.cards[GuiCards.AccountInfo].set_balance(value)
        self.show_card(GuiCards.AccountInfo)

    def show_choose_action(self, name: str):
        self.cards[GuiCards.ChooseAction].set_user_name(name)
        self.show_card(GuiCards.ChooseAction)

    def show_remove(self):
        self.show_card(GuiCards.RemoveCard)

    def show_card(self, card_id: GuiCards):
        if self.active_card is None:
            self.active_card = self.cards[GuiCards.Start]

        if self.active_card == self.cards[card_id]:
            return

        if self.visible_geometry is None or self.hidden_geometry is None:
            self.visible_geometry = self.active_card.geometry()  # type: QRect
            self.hidden_geometry = QRect(self.visible_geometry.x(), self.visible_geometry.height() * 1.5,
                                         self.visible_geometry.width(), self.visible_geometry.height())
        for key in self.cards.keys():
            if key != self.active_card:
                self.set_card_hidden(self.cards[key])

        card_to_show = self.cards[card_id]
        self.start_card_switch(card_to_show)
        self.active_card = self.cards[card_id]
        self.layout().setCurrentWidget(self.active_card)

    def start_card_switch(self, card_to_show):
        self.slide_out_animation = QPropertyAnimation(self.active_card, "geometry")
        self.slide_out_animation.setDuration(ANIMATION_DURATION)
        self.slide_out_animation.setEasingCurve(QEasingCurve.OutCubic)
        self.slide_out_animation.setStartValue(self.visible_geometry)
        self.slide_out_animation.setEndValue(self.hidden_geometry)
        self.set_card_hidden(card_to_show)
        self.slide_in_animation = QPropertyAnimation(card_to_show, "geometry")
        self.slide_in_animation.setDuration(ANIMATION_DURATION)
        self.slide_in_animation.setEasingCurve(QEasingCurve.InCubic)
        self.slide_in_animation.setStartValue(self.hidden_geometry)
        self.slide_in_animation.setEndValue(self.visible_geometry)
        self.animation_group = QParallelAnimationGroup()
        self.animation_group.addAnimation(self.slide_out_animation)
        self.animation_group.addAnimation(self.slide_in_animation)
        self.animation_group.start()
예제 #39
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()
예제 #40
0
class Eye(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.body_color = QColor(0xffffff)
        self.border_color = QColor(0x000000)
        self.border_size = 0.02

        self.iris_size = 0.4
        self.watch_direction = (0.0, 0.0)

        self.iris = Iris(QColor(0x00aa00), parent=self)
        self.iris_move_anim = QPropertyAnimation(
            self.iris, b'pos')  # Animation for iris position
        self.iris_move_anim.setDuration(100)
        self.iris_size_anim = QPropertyAnimation(
            self.iris, b'pupil_size')  # Animation for pupil size
        self.iris_size_anim.setDuration(500)
        self.resize_iris()

    def resize_iris(self):
        pupil_size = int(min(self.width(), self.height()) * self.iris_size)
        self.iris.setFixedSize(pupil_size, pupil_size)
        self.set_watch_direction(*self.watch_direction, animate=False)

    def resizeEvent(self, event: QResizeEvent):
        self.resize_iris()

    def paintEvent(self, event):
        size = min(self.width(), self.height())
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.translate(self.width() / 2, self.height() / 2)

        # draw border around eye
        painter.setBrush(QBrush(self.border_color))
        painter.drawEllipse(QPointF(0, 0), size / 2, size / 2)

        # draw sclera (white part of eyes)
        painter.setBrush(QBrush(self.body_color))
        body_size = size * (1 - self.border_size) * 0.5
        painter.drawEllipse(QPointF(0, 0), body_size, body_size)

    @property
    def radius(self):
        return min(self.width(), self.height()) / 2

    @property
    def body_radius(self):
        return self.radius * (1 - self.border_size)

    @staticmethod
    def cart2pol(x, y):
        """Convert cartesian coordinate to polar"""
        # https://stackoverflow.com/a/26757297/8181134
        mag = np.sqrt(x**2 + y**2)
        angle = np.arctan2(y, x)
        return (mag, angle)

    @staticmethod
    def pol2cart(mag, angle):
        """Convert polar coordinate to cartesian"""
        # https://stackoverflow.com/a/26757297/8181134
        x = mag * np.cos(angle)
        y = mag * np.sin(angle)
        return (x, y)

    def set_watch_direction(self, horizontal, vertical, animate=True):
        """ Move the eyes to the specified direction
        :param horizontal: float [-1 1]
        :param vertical: float [-1 1]
        """
        self.watch_direction = (horizontal, vertical)
        mag, angle = self.cart2pol(horizontal, vertical)
        mag = np.clip(mag, 0, 1)  # Limit the magnitude to max 1
        mag *= (self.body_radius - self.iris.radius
                )  # Max value for mag is so the edge of iris hits edge of eye
        x, y = self.pol2cart(mag, angle)

        x += (self.width() /
              2) - self.iris.radius  # Position of top-left corner of iris
        y += (self.height() / 2) - self.iris.radius

        if self.iris_move_anim.state() != QPropertyAnimation.Stopped:
            self.iris_move_anim.stop()
        if animate:
            self.iris_move_anim.setStartValue(self.iris.pos())
            self.iris_move_anim.setEndValue(QPointF(x, y))
            QTimer.singleShot(0, self.iris_move_anim.start)
        else:
            QTimer.singleShot(0, lambda x=x, y=y: self.iris.move(x, y))

    def set_pupil_size(self, size: float):
        """Set the pupil size
        :arg size: Size of the pupil [0..1]
        """
        self.iris_size_anim.stop()
        self.iris_size_anim.setStartValue(self.iris.pupil_size)
        self.iris_size_anim.setEndValue(size)
        QTimer.singleShot(0, self.iris_size_anim.start)
예제 #41
0
class Example(QDialog):
    '''
    按钮动画
    '''
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        '''
        一些界面设置
        '''
        self.resize(350, 200)
        self.setWindowTitle('你爱我吗?微信公众号号:学点编程吧出品')
        self.btbuai = QPushButton("不爱", self)
        self.btai = QPushButton('爱', self)
        self.btbuai.resize(70, 25)
        self.btbuai.move(200, 150)
        self.btai.resize(70, 25)
        self.btai.move(100, 150)
        label = QLabel('你难道不爱我吗????', self)
        label.move(50, 50)

        self.show()

        self.flag = 'move'

        self.btai.setMouseTracking(True)
        self.btbuai.setMouseTracking(True)
        # 启用鼠标追踪

        self.btai.installEventFilter(self)
        self.btbuai.installEventFilter(self)
        # 按钮安装事件过滤器

    def eventFilter(self, object, event):
        '''
        事件过滤器,分别调用不同的动画
        '''
        if object == self.btbuai:
            if event.type() == QEvent.Enter:
                self.doAnim1()
        elif object == self.btai:
            if event.type() == QEvent.Enter:
                self.doAnim2()
            elif event.type() == QEvent.MouseButtonRelease:
                self.makelove()
        return QDialog.eventFilter(self, object, event)

    def closeEvent(self, event):
        '''
        关闭事件
        '''
        QMessageBox.about(self, 'Love', '你就算关闭了窗口也阻止不了你心中对我的爱!')

    def doAnim1(self):
        '''
        动画效果
        '''
        if self.flag == 'move' and self.btbuai.pos() == QPoint(200, 150):
            self.anim = QPropertyAnimation(self.btbuai, b"geometry")
            self.anim.setDuration(1500)
            # 这里我们设置了动画的时间1500毫秒
            self.anim.setStartValue(QRect(200, 150, 70, 25))
            self.anim.setEndValue(QRect(200, 30, 70, 25))
            # 动画的对象的起始终点位置和大小;
            self.anim.setEasingCurve(QEasingCurve.OutCubic)
            # 动画的移动样式
            self.anim.start()
            # 启动动画
            # 下同
        elif self.flag == 'move' and self.btbuai.pos() == QPoint(200, 30):
            self.anim = QPropertyAnimation(self.btbuai, b"geometry")
            self.anim.setDuration(1500)
            self.anim.setStartValue(QRect(200, 30, 70, 25))
            self.anim.setEndValue(QRect(200, 150, 70, 25))
            self.anim.setEasingCurve(QEasingCurve.OutCubic)
            self.anim.start()
            self.flag = 'change'
        elif self.flag == 'change' and self.btbuai.text() == '不爱':
            self.btbuai.setText('爱')
            self.btai.setText('不爱')
            # 爱和不爱的变化

    def doAnim2(self):
        '''
        爱与不爱的转换
        '''
        if self.flag == 'change' and self.btbuai.text() == '爱':
            self.btbuai.setText('不爱')
            self.btai.setText('爱')
            self.flag = 'move'

    def makelove(self):
        '''
        爱你
        '''
        msg = MsgBox()
        msg.exec()
예제 #42
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()
예제 #43
0
class LoginDialog(QDialog):
    """登录对话框"""

    clicked_ok = pyqtSignal()

    def __init__(self, config):
        super().__init__()
        self._cwd = os.getcwd()
        self._config = config
        self._cookie_assister = 'login_assister.exe'
        self._user = ""
        self._pwd = ""
        self._cookie = {}
        self._del_user = ""
        self.initUI()
        self.setStyleSheet(dialog_qss_style)
        self.setMinimumWidth(380)
        self.name_ed.setFocus()
        # 信号
        self.name_ed.textChanged.connect(self.set_user)
        self.pwd_ed.textChanged.connect(self.set_pwd)
        self.cookie_ed.textChanged.connect(self.set_cookie)

    def update_selection(self, user):
        """显示已经保存的登录用户信息"""
        user_info = self._config.get_user_info(user)
        if user_info:
            self._user = user_info[0]
            self._pwd = user_info[1]
            self._cookie = user_info[2]
        # 更新控件显示内容
        self.name_ed.setText(self._user)
        self.pwd_ed.setText(self._pwd)
        try:
            text = ";".join([f'{k}={v}' for k, v in self._cookie.items()])
        except:
            text = ''
        self.cookie_ed.setPlainText(text)

    def initUI(self):
        self.setWindowTitle("登录蓝奏云")
        self.setWindowIcon(QIcon(SRC_DIR + "login.ico"))
        logo = QLabel()
        logo.setPixmap(QPixmap(SRC_DIR + "logo3.gif"))
        logo.setStyleSheet("background-color:rgb(0,153,255);")
        logo.setAlignment(Qt.AlignCenter)

        self.tabs = QTabWidget()
        self.auto_tab = QWidget()
        self.hand_tab = QWidget()

        # Add tabs
        self.tabs.addTab(self.auto_tab, "自动获取Cookie")
        self.tabs.addTab(self.hand_tab, "手动输入Cookie")
        self.auto_get_cookie_ok = AutoResizingTextEdit("🔶点击👇自动获取浏览器登录信息👇")
        self.auto_get_cookie_ok.setReadOnly(True)
        self.auto_get_cookie_btn = QPushButton("自动读取浏览器登录信息")
        auto_cookie_notice = '支持浏览器:Chrome, Chromium, Opera, Edge, Firefox'
        self.auto_get_cookie_btn.setToolTip(auto_cookie_notice)
        self.auto_get_cookie_btn.clicked.connect(self.call_auto_get_cookie)
        self.auto_get_cookie_btn.setStyleSheet(
            "QPushButton {min-width: 210px;max-width: 210px;}")

        self.name_lb = QLabel("&U 用户")
        self.name_lb.setAlignment(Qt.AlignCenter)
        self.name_ed = QLineEdit()
        self.name_lb.setBuddy(self.name_ed)

        self.pwd_lb = QLabel("&P 密码")
        self.pwd_lb.setAlignment(Qt.AlignCenter)
        self.pwd_ed = QLineEdit()
        self.pwd_ed.setEchoMode(QLineEdit.Password)
        self.pwd_lb.setBuddy(self.pwd_ed)

        self.cookie_lb = QLabel("&Cookie")
        self.cookie_ed = QTextEdit()
        notice = "由于滑动验证的存在,需要输入cookie,cookie请使用浏览器获取\n" + \
            "cookie会保存在本地,下次使用。其格式如下:\n ylogin=value1; phpdisk_info=value2"
        self.cookie_ed.setPlaceholderText(notice)
        self.cookie_lb.setBuddy(self.cookie_ed)

        self.show_input_cookie_btn = QPushButton("显示Cookie输入框")
        self.show_input_cookie_btn.setToolTip(notice)
        self.show_input_cookie_btn.setStyleSheet(
            "QPushButton {min-width: 110px;max-width: 110px;}")
        self.show_input_cookie_btn.clicked.connect(
            self.change_show_input_cookie)
        self.ok_btn = QPushButton("登录")
        self.ok_btn.clicked.connect(self.change_ok_btn)
        self.cancel_btn = QPushButton("取消")
        self.cancel_btn.clicked.connect(self.change_cancel_btn)
        lb_line_1 = QLabel()
        lb_line_1.setText('<html><hr />切换用户</html>')
        lb_line_2 = QLabel()
        lb_line_2.setText('<html><hr /></html>')

        self.form = QFormLayout()
        self.form.setLabelAlignment(Qt.AlignRight)
        self.form.addRow(self.name_lb, self.name_ed)
        self.form.addRow(self.pwd_lb, self.pwd_ed)
        if is_windows:

            def set_assister_path():
                """设置辅助登录程序路径"""
                assister_path = QFileDialog.getOpenFileName(
                    self, "选择辅助登录程序路径", self._cwd, "EXE Files (*.exe)")
                if not assister_path[0]:
                    return None
                assister_path = os.path.normpath(
                    assister_path[0])  # windows backslash
                if assister_path == self._cookie_assister:
                    return None
                self.assister_ed.setText(assister_path)
                self._cookie_assister = assister_path

            self.assister_lb = QLabel("登录辅助程序")
            self.assister_lb.setAlignment(Qt.AlignCenter)
            self.assister_ed = MyLineEdit(self)
            self.assister_ed.setText(self._cookie_assister)
            self.assister_ed.clicked.connect(set_assister_path)
            self.assister_lb.setBuddy(self.assister_ed)
            self.form.addRow(self.assister_lb, self.assister_ed)

        hbox = QHBoxLayout()
        hbox.addWidget(self.show_input_cookie_btn)
        hbox.addStretch(1)
        hbox.addWidget(self.ok_btn)
        hbox.addWidget(self.cancel_btn)

        user_box = QHBoxLayout()
        self.user_num = 0
        self.user_btns = {}
        for user in self._config.users_name:
            user = str(user)  # TODO: 可能需要删掉
            self.user_btns[user] = QDoublePushButton(user)
            self.user_btns[user].setStyleSheet("QPushButton {border:none;}")
            if user == self._config.name:
                self.user_btns[user].setStyleSheet(
                    "QPushButton {background-color:rgb(0,153,2);}")
                self.tabs.setCurrentIndex(1)
            self.user_btns[user].setToolTip(f"点击选中,双击切换至用户:{user}")
            self.user_btns[user].doubleClicked.connect(self.choose_user)
            self.user_btns[user].clicked.connect(self.delete_chose_user)
            user_box.addWidget(self.user_btns[user])
            self.user_num += 1
            user_box.addStretch(1)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(logo)
        vbox = QVBoxLayout()
        if self._config.name:
            vbox.addWidget(lb_line_1)
            user_box.setAlignment(Qt.AlignCenter)
            vbox.addLayout(user_box)
            vbox.addWidget(lb_line_2)
            if self.user_num > 1:
                self.del_user_btn = QPushButton("删除账户")
                self.del_user_btn.setIcon(QIcon(SRC_DIR + "delete.ico"))
                self.del_user_btn.setStyleSheet(
                    "QPushButton {min-width: 180px;max-width: 180px;}")
                self.del_user_btn.clicked.connect(self.call_del_chose_user)
                vbox.addWidget(self.del_user_btn)
            else:
                self.del_user_btn = None
            vbox.addStretch(1)

        vbox.addLayout(self.form)
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        vbox.setAlignment(Qt.AlignCenter)

        self.hand_tab.setLayout(vbox)
        auto_cookie_vbox = QVBoxLayout()
        auto_cookie_vbox.addWidget(self.auto_get_cookie_ok)
        auto_cookie_vbox.addWidget(self.auto_get_cookie_btn)
        auto_cookie_vbox.setAlignment(Qt.AlignCenter)
        self.auto_tab.setLayout(auto_cookie_vbox)
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)
        self.update_selection(self._config.name)

    def call_del_chose_user(self):
        if self._del_user:
            if self._del_user != self._config.name:
                self.user_num -= 1
                self._config.del_user(self._del_user)
                self.user_btns[self._del_user].close()
                self._del_user = ""
                if self.user_num <= 1:
                    self.del_user_btn.close()
                    self.del_user_btn = None
                return
            else:
                title = '不能删除'
                msg = '不能删除当前登录账户,请先切换用户!'
        else:
            title = '请选择账户'
            msg = '请单击选择需要删除的账户\n\n注意不能删除当前账户(绿色)'
        message_box = QMessageBox(self)
        message_box.setIcon(QMessageBox.Critical)
        message_box.setStyleSheet(btn_style)
        message_box.setWindowTitle(title)
        message_box.setText(msg)
        message_box.setStandardButtons(QMessageBox.Close)
        buttonC = message_box.button(QMessageBox.Close)
        buttonC.setText('关闭')
        message_box.exec()

    def delete_chose_user(self):
        """更改单击选中需要删除的用户"""
        user = str(self.sender().text())
        self._del_user = user
        if self.del_user_btn:
            self.del_user_btn.setText(f"删除 <{user}>")

    def choose_user(self):
        """切换用户"""
        user = self.sender().text()
        if user != self._config.name:
            self.ok_btn.setText("切换用户")
        else:
            self.ok_btn.setText("登录")
        self.update_selection(user)

    def change_show_input_cookie(self):
        row_c = 4 if is_windows else 3
        if self.form.rowCount() < row_c:
            self.org_height = self.height()
            self.form.addRow(self.cookie_lb, self.cookie_ed)
            self.show_input_cookie_btn.setText("隐藏Cookie输入框")
            self.change_height = None
            self.adjustSize()
        else:
            if not self.change_height:
                self.change_height = self.height()
            if self.cookie_ed.isVisible():
                self.cookie_lb.setVisible(False)
                self.cookie_ed.setVisible(False)
                self.show_input_cookie_btn.setText("显示Cookie输入框")
                start_height, end_height = self.change_height, self.org_height
            else:
                self.cookie_lb.setVisible(True)
                self.cookie_ed.setVisible(True)
                self.show_input_cookie_btn.setText("隐藏Cookie输入框")
                start_height, end_height = self.org_height, self.change_height
            gm = self.geometry()
            x, y = gm.x(), gm.y()
            wd = self.width()
            self.animation = QPropertyAnimation(self, b'geometry')
            self.animation.setDuration(400)
            self.animation.setStartValue(QRect(x, y, wd, start_height))
            self.animation.setEndValue(QRect(x, y, wd, end_height))
            self.animation.start()

    def set_user(self, user):
        self._user = user
        if not user:
            return None
        if user not in self._config.users_name:
            self.ok_btn.setText("添加用户")
            self.cookie_ed.setPlainText("")
        elif user != self._config.name:
            self.update_selection(user)
            self.ok_btn.setText("切换用户")
        else:
            self.update_selection(user)
            self.ok_btn.setText("登录")

    def set_pwd(self, pwd):
        if self._user in self._config.users_name:
            user_info = self._config.get_user_info(self._user)
            if pwd and pwd != user_info[1]:  # 改变密码,cookie作废
                self.cookie_ed.setPlainText("")
                self._cookie = None
            if not pwd:  # 输入空密码,表示删除对pwd的存储,并使用以前的cookie
                self._cookie = user_info[2]
                try:
                    text = ";".join(
                        [f'{k}={v}' for k, v in self._cookie.items()])
                except:
                    text = ''
                self.cookie_ed.setPlainText(text)
        self._pwd = pwd

    def set_cookie(self):
        cookies = self.cookie_ed.toPlainText()
        if cookies:
            try:
                self._cookie = {
                    kv.split("=")[0].strip(" "): kv.split("=")[1].strip(" ")
                    for kv in cookies.split(";")
                }
            except:
                self._cookie = None

    def change_cancel_btn(self):
        self.update_selection(self._config.name)
        self.close()

    def change_ok_btn(self):
        if self._user and self._pwd:
            if self._user not in self._config.users_name:
                self._cookie = None
        if self._cookie:
            up_info = {
                "name": self._user,
                "pwd": self._pwd,
                "cookie": self._cookie,
                "work_id": -1
            }
            if self.ok_btn.text() == "切换用户":
                self._config.change_user(self._user)
            else:
                self._config.set_infos(up_info)
            self.clicked_ok.emit()
            self.close()
        elif USE_WEB_ENG:
            self.web = LoginWindow(self._user, self._pwd)
            self.web.cookie.connect(self.get_cookie_by_web)
            self.web.setWindowModality(Qt.ApplicationModal)
            self.web.exec()
        elif os.path.isfile(self._cookie_assister):
            try:
                result = os.popen(
                    f'{self._cookie_assister} {self._user} {self._pwd}')
                cookie = result.read()
                try:
                    self._cookie = {
                        kv.split("=")[0].strip(" "):
                        kv.split("=")[1].strip(" ")
                        for kv in cookie.split(";")
                    }
                except:
                    self._cookie = None
                if not self._cookie:
                    return None
                up_info = {
                    "name": self._user,
                    "pwd": self._pwd,
                    "cookie": self._cookie,
                    "work_id": -1
                }
                self._config.set_infos(up_info)
                self.clicked_ok.emit()
                self.close()
            except:
                pass
        else:
            title = '请使用 Cookie 登录或是选择 登录辅助程序'
            msg = '没有输入 Cookie,或者没有找到登录辅助程序!\n\n' + \
                  '推荐使用浏览器获取 cookie 填入 cookie 输入框\n\n' + \
                  '如果不嫌文件体积大,请下载登录辅助程序:\n' + \
                  'https://github.com/rachpt/lanzou-gui/releases'
            message_box = QMessageBox(self)
            message_box.setIcon(QMessageBox.Critical)
            message_box.setStyleSheet(btn_style)
            message_box.setWindowTitle(title)
            message_box.setText(msg)
            message_box.setStandardButtons(QMessageBox.Close)
            buttonC = message_box.button(QMessageBox.Close)
            buttonC.setText('关闭')
            message_box.exec()

    def get_cookie_by_web(self, cookie):
        """使用辅助登录程序槽函数"""
        self._cookie = cookie
        self._close_dialog()

    def call_auto_get_cookie(self):
        """自动读取浏览器cookie槽函数"""
        try:
            self._cookie = get_cookie_from_browser()
        except Exception as e:
            logger.error(f"Browser_cookie3 Error: {e}")
            self.auto_get_cookie_ok.setPlainText(f"❌获取失败,错误信息\n{e}")
        else:
            if self._cookie:
                self._user = self._pwd = ''
                self.auto_get_cookie_ok.setPlainText("✅获取成功即将登录……")
                QTimer.singleShot(2000, self._close_dialog)
            else:
                self.auto_get_cookie_ok.setPlainText(
                    "❌获取失败\n请提前使用支持的浏览器登录蓝奏云,读取前完全退出浏览器!\n支持的浏览器与顺序:\nchrome, chromium, opera, edge, firefox"
                )

    def _close_dialog(self):
        """关闭对话框"""
        up_info = {
            "name": self._user,
            "pwd": self._pwd,
            "cookie": self._cookie
        }
        self._config.set_infos(up_info)
        self.clicked_ok.emit()
        self.close()
예제 #44
0
class MyForm(QDialog):
    def __init__(self):
        super(MyForm, self).__init__()
        self.ui = uic.loadUi('file_ui/Game.ui', self)
        self.ui.frame.setStyleSheet('background-image:url("image/Lane.png")')
        self.label_10.setPixmap(QPixmap('image/Super-car.png'))
        self.image = ["image/Car-Blue.png", "image/Car-Green.png", "image/Car-Oranges.png", "image/Car-Pink.png"]
        self.setWindowTitle('Car Rush')
        self.setWindowIcon(QIcon('image/Supercar.png'))

        self.ui.pushButton_4.setEnabled(True)
        self.ui.pushButton_3.setEnabled(False)
        self.ui.pushButton_5.setEnabled(False)

        self.ui.pushButton_3.clicked.connect(self.stop)
        self.ui.pushButton_4.clicked.connect(self.Go)
        self.ui.pushButton_5.clicked.connect(self.resume)

        # xoá dữ liệu file.txt
        # self.ctx = open('text1.txt', 'w')
        # self.ctx.write('')

        self.best_point = 0
        self.bestscore()
        self.step = 30
        self.x = 190
        self.y = 400
        self.settime2 = 6000
        self.speed2 = 6000
        self.settime = 5000
        self.speed = 5000
        self.xea = 0
        self.lstR2 = [30, 190, 360]

    def bestscore(self):
        bp = open('text1.txt', 'r')
        for i in bp.readlines():
            if int(i) > int(self.best_point):
                self.best_point = i
        self.ui.label_7.setText('BEST SCORE: ' + str(self.best_point))

    def Go(self):
        self.p = vlc.MediaPlayer("music/Rush.mp3")
        self.p.play()
        self.p.audio_set_volume(50)
        print("Go")

        MF3 = MyForm3()
        MF3.show()
        self.resetpoint()
        self.setPos()

        # Xe1
        self.timexe1 = QtCore.QTimer()
        self.timexe1.start(self.settime)
        self.timexe1.timeout.connect(self.create)

        # Xe2
        self.timexe2 = QtCore.QTimer()
        self.timexe2.start(self.settime2)
        self.timexe2.timeout.connect(self.create2)

        # point
        self.time_point = QtCore.QTimer()
        self.time_point.start(self.speed)
        self.time_point.timeout.connect(self.calculatePoint)

        #point 2
        self.time_point2 = QtCore.QTimer()
        self.time_point2.start(self.speed2)
        self.time_point2.timeout.connect(self.calculatePoint2)

        # check
        self.timeCheck = QtCore.QTimer()
        self.timeCheck.start(100)
        self.timeCheck.timeout.connect(self.check)

        # time Disable
        self.timeDisable = QtCore.QTimer()
        self.timeDisable.start(4000)
        self.timeDisable.timeout.connect(self.Enabled)

    def create(self):
        self.lstR2 = [30, 190, 360]
        image = random.choice(self.image)
        self.labelXe1.setPixmap(QPixmap(image))

        self.xea = random.choice(self.lstR2)
        self.CN = QPropertyAnimation(self.ui.labelXe1, b"geometry")
        self.CN.setDuration(self.speed)
        self.CN.setStartValue(QRect(self.xea, -50, 100, 150))
        self.CN.setEndValue(QRect(self.xea, 800, 100, 150))
        self.CN.start()

    def create2(self):
        r2 = random.choice(self.lstR2)
        print(self.xea)

        if r2 != self.xea:
            print("run r2 "+str(r2))
            self.labelXe2.setPixmap(QPixmap(random.choice(self.image)))
            self.CN2 = QPropertyAnimation(self.ui.labelXe2, b"geometry")
            self.CN2.setDuration(self.speed)
            self.CN2.setStartValue(QRect(r2, -50, 100, 150))
            self.CN2.setEndValue(QRect(r2, 800, 100, 150))
            self.CN2.start()
        else:
            self.lstR2.remove(self.xea)
            print(self.lstR2)
            r_again = random.choice(self.lstR2)
            print("run r_again "+str(r_again))
            self.labelXe2.setPixmap(QPixmap(random.choice(self.image)))
            self.CN2 = QPropertyAnimation(self.ui.labelXe2, b"geometry")
            self.CN2.setDuration(self.speed)
            self.CN2.setStartValue(QRect(r_again, -50, 100, 150))
            self.CN2.setEndValue(QRect(r_again, 800, 100, 150))
            self.CN2.start()


    def Enabled(self):
        print("Enabled")
        self.ui.pushButton_3.setEnabled(True)
        self.ui.pushButton_4.setEnabled(False)
        self.ui.pushButton_5.setEnabled(True)
        self.timeDisable.stop()
    def Disable(self):
        print("Disable")
        self.ui.pushButton_3.setEnabled(False)
        self.ui.pushButton_4.setEnabled(False)
        self.ui.pushButton_5.setEnabled(False)

    def setPos(self):
        self.ui.labelXe1.setGeometry(180, -200, 100, 150)
        self.ui.label_10.setGeometry(190, 400, 100, 150)
        self.x = 190
        self.y = 400

    def check(self):
        self.a = None
        # tọa độ xe 1
        w_car = self.ui.labelXe1.width()
        h_car = self.ui.labelXe1.height()
        X_car = self.ui.labelXe1.x()
        Y_car = self.ui.labelXe1.y()
        # tọa độ xe 2
        w_car2 = self.ui.labelXe2.width()
        h_car2 = self.ui.labelXe2.height()
        X_car2 = self.ui.labelXe2.x()
        Y_car2 = self.ui.labelXe2.y()
        # chiều cao, rộng xe đỏ
        w_card = self.ui.label_10.width()
        h_card = self.ui.label_10.height()

        # print("Xe 1 ", X_car, Y_car, "|","Xe 2 ", X_car2, Y_car2,"|", self.x, self.y)

        if ((self.x <= (X_car + w_car) and self.x >= X_car) or (self.x + w_card >= X_car and self.x + w_card <= X_car + w_car)) \
                and ((h_car + Y_car >= self.y) and (h_card + Y_car <= self.y + h_card) or ((Y_car >= self.y) and (Y_car <= self.y + w_card))):
            self.time_point.stop()
            self.time_point2.stop()
            self.timeCheck.stop()
            self.timexe1.stop()
            self.timexe2.stop()
            self.CN.stop()
            self.CN2.stop()
            self.p.stop()
            self.ui.labelXe1.move(-200, -200)
            self.ui.labelXe2.move(-200, -200)
            #Âm thanh đụng xe
            self.crash = vlc.MediaPlayer("music/BOOM.mp3")
            self.crash.play()
            self.crash = vlc.MediaPlayer("music/HEAVENLY.mp3")
            self.crash.play()
            self.Disable()
            print("Game Over")
            # append the  point to text1.txt
            a = open('text1.txt', 'a')
            a.write(str(self.point))
            a.write('\n')
            a.close()

            self.MF2 = MyForm2()
            self.MF2.ui.pushButton.clicked.connect(self.PlayAgain)

            # kiểm tra điểm
            a = open('text1.txt', 'r')
            for i in a.readlines():
                if int(self.best_point) < int(i):
                    self.best_point =i
            if int(self.best_point) <= int(self.point):
                self.MF2.ui.label.setText('BEST SCORE: ' + str(self.point))
            else:
                self.MF2.ui.label.setText('SCORE: ' + str(self.point))
            self.MF2.show()
        if ((self.x <= (X_car2 + w_car2) and self.x >= X_car2) or (self.x + w_card >= X_car2 and self.x + w_card <= X_car2 + w_car2)) \
                and ((h_car2 + Y_car2 >= self.y) and (h_card + Y_car2 <= self.y + h_card) or ((Y_car2 >= self.y) and (Y_car2 <= self.y + w_card))):
            self.time_point.stop()
            self.time_point2.stop()
            self.timexe1.stop()
            self.timexe2.stop()
            self.timeCheck.stop()
            self.CN.stop()
            self.CN2.stop()
            self.p.stop()
            self.ui.labelXe1.move(-200, -200)
            self.ui.labelXe2.move(-200, -200)
            # Âm thanh đụng xe
            self.crash = vlc.MediaPlayer("music/BOOM.mp3")
            self.crash.play()
            self.crash = vlc.MediaPlayer("music/HEAVENLY.mp3")
            self.crash.play()
            self.Disable()
            print("Game Over")
            # append the  point to text1.txt
            a = open('text1.txt', 'a')
            a.write(str(self.point))
            a.write('\n')
            a.close()

            self.MF2 = MyForm2()
            self.MF2.ui.pushButton.clicked.connect(self.PlayAgain)

            # kiểm tra điểm
            a = open('text1.txt', 'r')
            for i in a.readlines():
                if int(self.best_point) < int(i):
                    self.best_point = i
            if int(self.best_point) <= int(self.point):
                self.MF2.ui.label.setText('BEST SCORE: ' + str(self.point))
            else:
                self.MF2.ui.label.setText('SCORE: ' + str(self.point))
            self.MF2.show()
    def PlayAgain(self):
        self.a = None
        self.crash.stop()
        self.settime2 = 7000
        self.speed2 = 7000
        self.settime = 5000
        self.speed = 5000
        self.Go()
        self.MF2.close()
        self.bestscore()
    def move(self):
        self.anim = QPropertyAnimation(self.ui.label_10, b"geometry")
        self.anim.setDuration(-10)
        self.anim.setStartValue(QRect(self.x, self.y, 100, 150))
        self.anim.setEndValue(QRect(self.x, self.y, 100, 150))
        self.anim.start()

    def stop(self):
        self.timexe1.stop()
        self.timexe2.stop()
        self.time_point.stop()
        self.time_point2.stop()
        self.timeCheck.stop()
        self.CN.pause()
        self.CN2.pause()
        self.ui.pushButton_3.setEnabled(False)
        self.step = 0
        self.p.pause()
        print("Stop")

    def resume(self):
        self.timexe1.start()
        self.timexe2.start()
        self.time_point.start()
        self.time_point2.start()
        self.timeCheck.start()
        self.CN.resume()
        self.CN2.resume()
        self.ui.pushButton_3.setEnabled(True)
        self.ui.pushButton_5.setEnabled(True)
        self.step = 30
        self.p.play()
        print("Resume")

    def calculatePoint(self):
        if self.ui.labelXe1.y() > 700:
            self.point += 10
            self.ui.label.setText(str(self.point))
            print("Calculate Point 1")
            if self.point == 20:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)
                print(self.point)
            if self.point == 50:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)
            if self.point == 70:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)
            if self.point == 100:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)
            if self.point == 150:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)
            if self.point == 200:
                self.settime = self.settime - 500
                self.speed = self.speed - 500
                print(self.settime, self.speed)

    def calculatePoint2(self):
        if self.ui.labelXe2.y() > 700:
            self.point += 10
            print(self.point)
            self.ui.label.setText(str(self.point))
            print("Calculate Point 2")
            if self.point == 30:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)
                print(self.point)
            if self.point == 60:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)
            if self.point == 80:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)
            if self.point == 110:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)
            if self.point == 160:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)
            if self.point == 210:
                self.settime2 = self.settime2 - 500
                self.speed2 = self.speed2 - 500
                print(self.settime2, self.speed2)

    def resetpoint(self):
        self.point = 0
        self.ui.label.setText(str(0))
    def keyPressEvent(self, e):
        if e.key() == QtCore.Qt.Key_W or e.key() == QtCore.Qt.Key_Up:

            if self.y > 250:
                self.y -= self.step
                self.x += 0

        elif e.key() == QtCore.Qt.Key_S or e.key() == QtCore.Qt.Key_Down:

            if self.y < 420:
                self.y += self.step
                # self.x += 0

        elif e.key() == QtCore.Qt.Key_A or e.key() == QtCore.Qt.Key_Right:

            if self.x > 10:
                self.y += 0
                self.x -= self.step

        elif e.key() == QtCore.Qt.Key_D or e.key() == QtCore.Qt.Key_Left:

            if self.x < 350:
                self.y += 0
                self.x += self.step

        self.move()
    def stopall(self):
        sys.exit()
예제 #45
0
class SubPlayWindow(QWidget):
    """ 桌面左上角子播放窗口 """
    def __init__(self, parent=None, songInfo: dict = None):
        super().__init__(parent)
        self.songInfo = {}
        if songInfo:
            self.songInfo = songInfo
        self.__lastSongIconPath = {
            "normal":
            r"app\resource\images\sub_play_window\lastSong_50_50_normal.png",
            "hover":
            r"app\resource\images\sub_play_window\lastSong_50_50_hover.png",
            "pressed":
            r"app\resource\images\sub_play_window\lastSong_50_50_pressed.png",
        }
        self.__nextSongIconPath = {
            "normal":
            r"app\resource\images\sub_play_window\nextSong_50_50_normal.png",
            "hover":
            r"app\resource\images\sub_play_window\nextSong_50_50_hover.png",
            "pressed":
            r"app\resource\images\sub_play_window\nextSong_50_50_pressed.png",
        }
        # 创建小部件
        self.volumeSlider = Slider(Qt.Vertical, self)
        self.volumeLabel = QLabel(self)
        self.lastSongButton = ThreeStateButton(self.__lastSongIconPath, self,
                                               (50, 50))
        self.playButton = PlayButton(self)
        self.nextSongButton = ThreeStateButton(self.__nextSongIconPath, self,
                                               (50, 50))
        self.albumPic = QLabel(self)
        self.songNameLabel = QLabel(self)
        self.songerNameLabel = QLabel(self)
        self.ani = QPropertyAnimation(self, b"windowOpacity")
        self.timer = QTimer(self)
        # 系统音量控制类
        self.systemVolume = SystemVolume()
        # 初始化
        self.__initWidget()

    def __initWidget(self):
        """ 初始化小部件 """
        self.resize(635, 175)
        self.__initLayout()
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window
                            | Qt.WindowStaysOnTopHint)
        # 初始化音量滑块
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setSingleStep(1)
        # 初始化动画和定时器
        self.timer.setInterval(3000)
        self.ani.setEasingCurve(QEasingCurve.Linear)
        self.ani.setDuration(700)
        self.ani.setStartValue(1)
        self.ani.setEndValue(0)
        # 分配ID
        self.volumeLabel.setObjectName("volumeLabel")
        self.songNameLabel.setObjectName("songNameLabel")
        self.songerNameLabel.setObjectName("songerNameLabel")
        # 设置层叠样式
        self.__setQss()
        # 将信号连接到槽
        self.__connectSignalToSlot()
        self.volumeSlider.setValue(self.systemVolume.getVolume())
        # 设置封面和标签
        self.updateWindow(self.songInfo)
        # 引用方法
        self.setPlay = self.playButton.setPlay

    def __initLayout(self):
        """ 初始化布局 """
        self.move(62, 75)
        self.albumPic.move(478, 25)
        self.playButton.move(222, 26)
        self.volumeLabel.move(32, 140)
        self.volumeSlider.move(34, 25)
        self.songNameLabel.move(122, 93)
        self.lastSongButton.move(122, 26)
        self.nextSongButton.move(322, 26)
        self.songerNameLabel.move(122, 135)
        self.albumPic.setFixedSize(125, 125)
        self.songNameLabel.setFixedWidth(285)
        self.songerNameLabel.setFixedWidth(290)
        self.volumeLabel.setFixedWidth(65)

    def updateWindow(self, songInfo: dict):
        """ 设置窗口内容 """
        self.songInfo = songInfo
        self.songName = self.songInfo.get("songName", "未知歌曲")
        self.songerName = self.songInfo.get("songer", "未知歌手")
        # 调整长度
        self.__adjustText()
        # 更新标签和专辑封面
        self.songNameLabel.setText(self.songName)
        self.songerNameLabel.setText(self.songerName)
        self.__setAlbumCover()

    def timerSlot(self):
        """ 定时器溢出时间 """
        self.timer.stop()
        self.ani.start()

    def enterEvent(self, e):
        """ 鼠标进入时停止动画并重置定时器 """
        self.timer.stop()
        if self.ani.state() == QAbstractAnimation.Running:
            self.ani.stop()
            self.setWindowOpacity(1)

    def leaveEvent(self, e):
        """ 鼠标离开窗口时打开计时器 """
        # 判断事件发生的位置发生在自己所占的rect内
        notLeave = isNotLeave(self)
        if not notLeave:
            self.timer.start()

    def show(self):
        """ show()时重置透明度并根据鼠标位置决定是否打开计时器 """
        self.setWindowOpacity(1)
        self.volumeSlider.setValue(self.systemVolume.getVolume())
        super().show()
        notLeave = isNotLeave(self)
        if not notLeave:
            self.timer.start()

    def paintEvent(self, e):
        """ 绘制背景色 """
        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)
        painter.setPen(Qt.NoPen)
        brush = QBrush(Qt.black)
        painter.setBrush(brush)
        # 绘制音量滑动条的背景
        painter.drawRect(0, 0, 81, 175)
        # 绘制控制面板的背景
        painter.drawRect(86, 0, 549, 175)

    def __connectSignalToSlot(self):
        """ 将信号连接到槽 """
        self.ani.finished.connect(self.hide)
        self.timer.timeout.connect(self.timerSlot)
        self.volumeSlider.valueChanged.connect(self.sliderValueChangedSlot)

    def __setQss(self):
        """ 设置层叠样式 """
        with open(r"app\resource\css\subPlayWindow.qss",
                  encoding="utf-8") as f:
            self.setStyleSheet(f.read())

    def __setAlbumCover(self):
        """ 设置封面 """
        # 如果专辑信息为空就直接隐藏
        self.coverPath = getCoverPath(self.songInfo.get("modifiedAlbum"))
        self.albumPic.setPixmap(
            QPixmap(self.coverPath).scaled(125, 125, Qt.KeepAspectRatio,
                                           Qt.SmoothTransformation))

    def __adjustText(self):
        """ 根据文本长度决定是否显示省略号 """
        fontMetrics_1 = QFontMetrics(QFont("Microsoft YaHei", 17, 63))
        self.songName = fontMetrics_1.elidedText(self.songName, Qt.ElideRight,
                                                 285)
        fontMetrics_2 = QFontMetrics(QFont("Microsoft YaHei", 9))
        self.songerName = fontMetrics_2.elidedText(self.songerName,
                                                   Qt.ElideRight, 290)

    def __adjustVolumeLabelPos(self):
        """ 调整音量标签的位置 """
        if 10 <= int(self.volumeLabel.text()) <= 99:
            self.volumeLabel.move(32, 140)
        elif 0 <= int(self.volumeLabel.text()) <= 9:
            self.volumeLabel.move(37, 140)
        else:
            self.volumeLabel.move(27, 140)

    def sliderValueChangedSlot(self, value):
        """ 音量改变时调整系统音量并更新标签 """
        self.volumeLabel.setText(str(value))
        self.__adjustVolumeLabelPos()
        self.systemVolume.setVolume(value)
예제 #46
0
    def __init__(self, parent=None):
        QStatusBar.__init__(self, parent)
        self.setAutoFillBackground(
            True)  # set the widget background to be filled automatically

        # Define colours to use in animations
        red = QColor(255, 0, 0)
        red_transparent = QColor(255, 0, 0, alpha=0)
        green = QColor(0, 255, 0)
        green_transparent = QColor(0, 255, 0, alpha=0)

        # Setup fade out animation for red
        fade_out = QPropertyAnimation(self, b"back_color")
        fade_out.setStartValue(red)
        fade_out.setEndValue(red_transparent)
        fade_out.setDuration(2000)

        # Setup fade in animation for red
        fade_in = QPropertyAnimation(self, b"back_color")
        fade_in.setStartValue(red_transparent)
        fade_in.setEndValue(red)
        fade_in.setDuration(2000)

        # Setup stay animation for red
        stay_red = QPropertyAnimation(self, b"back_color")
        stay_red.setStartValue(red)
        stay_red.setEndValue(red)
        stay_red.setDuration(1000)

        # Setup animation group for no connection
        self._no_conn_anim = QSequentialAnimationGroup()
        self._no_conn_anim.addAnimation(fade_out)
        self._no_conn_anim.addAnimation(fade_in)
        self._no_conn_anim.addAnimation(stay_red)
        self._no_conn_anim.setLoopCount(-1)  # loop infinitely

        # Setup fade out animation for green
        fade_out = QPropertyAnimation(self, b"back_color")
        fade_out.setStartValue(green)
        fade_out.setEndValue(green_transparent)
        fade_out.setDuration(2000)

        # Setup fade in animation for green
        fade_in = QPropertyAnimation(self, b"back_color")
        fade_in.setStartValue(green_transparent)
        fade_in.setEndValue(green)
        fade_in.setDuration(2000)

        # Setup stay animation for green
        stay_green = QPropertyAnimation(self, b"back_color")
        stay_green.setStartValue(green)
        stay_green.setEndValue(green)
        stay_green.setDuration(1000)

        # Setup animation group for a connection
        self._conn_anim = QSequentialAnimationGroup()
        self._conn_anim.addAnimation(fade_out)
        self._conn_anim.addAnimation(fade_in)
        self._conn_anim.addAnimation(stay_green)
        self._conn_anim.setLoopCount(-1)
예제 #47
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)
예제 #48
0
class SidebarItem(QWidget):
    on_pressed = pyqtSignal(bool)

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

        rgb_value = 255 if options.theme == 'dark' else 0
        self.theme = options.theme

        # You are supposed to set size policy like this, and not to override sizePolicy()
        # If vertical policy was preferred, then you would have to implement minimumSizeHint and
        # maximumSize to limit how much the item can shrink and grow.
        self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        self.text = text
        self.pixmap = pixmap
        self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200))
        self.spacing = 12
        self.font = QApplication.font()
        self.font.setBold(True)
        self.fm = QFontMetrics(self.font)
        self.mouse_over = False
        self.checked = False
        self.active = False
        self.setMouseTracking(True)

        self.background_color = QColor(rgb_value, rgb_value, rgb_value, 0)
        self.background_animation = QPropertyAnimation(self, b'opacity')
        self.background_animation.setStartValue(0)
        self.background_animation.setEndValue(40)
        self.background_animation.setDuration(300)

        self.indicator_pos = 5
        self.indicator_position_anim = QPropertyAnimation(
            self, b'indicator_position')
        self.indicator_position_anim.setStartValue(5)
        self.indicator_position_anim.setEndValue(-5)
        self.indicator_position_anim.setDuration(300)

        self.indicator_background = QColor(rgb_value, rgb_value, rgb_value, 0)
        self.indicator_opacity_anim = QPropertyAnimation(
            self, b'indicator_opacity')
        self.indicator_opacity_anim.setStartValue(0)
        self.indicator_opacity_anim.setEndValue(140)
        self.indicator_opacity_anim.setDuration(300)

        self.all_animations = QParallelAnimationGroup()
        self.all_animations.addAnimation(self.background_animation)
        self.all_animations.addAnimation(self.indicator_position_anim)
        self.all_animations.addAnimation(self.indicator_opacity_anim)

        OptionEventChannel.subscribe('theme', self.handle_theme_change)

    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        self.on_pressed.emit(True)

    def set_checked(self, checked):
        self.checked = checked
        self.check_active()

    def check_active(self):
        old_active = self.active
        if self.checked:
            self.active = True
        else:
            self.active = self.mouse_over

        if old_active == self.active:
            return

        if self.active is True:
            self.all_animations.setDirection(QParallelAnimationGroup.Forward)
            self.all_animations.start()
        else:
            self.all_animations.setDirection(QParallelAnimationGroup.Backward)
            self.all_animations.start()

        # Calling update 10 times will result in only one update.
        # So it's fine to do this even after starting the animations.
        self.update()

    def enterEvent(self, event):
        self.mouse_over = True
        self.check_active()

    def leaveEvent(self, event):
        self.mouse_over = False
        self.check_active()

    def sizeHint(self):
        # sizeHint is used by layouts to get the recommended size of the widget.
        return QSize(100, 40)

    # def minimumSizeHint(self):
    #     # minimumSizeHint is used by layouts to get the minimum size of the widget.
    #     # It's ignored if minimumSize is also implemented
    #     return self.sizeHint()

    def paintEvent(self, paint_event):
        super().paintEvent(paint_event)
        widget_rect = self.rect()
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.fillRect(widget_rect, self.background_color)

        if self.mouse_over:
            indicator_rect = QRect(
                widget_rect.width() + self.indicator_pos - 6,
                (widget_rect.height() - 6) // 2, 6, 9)
            triangle_path = QPainterPath(indicator_rect.topRight())
            triangle_path.lineTo(indicator_rect.bottomRight())
            mid_left = indicator_rect.bottomLeft()
            mid_left.setY(mid_left.y() - indicator_rect.height() // 2)
            triangle_path.lineTo(mid_left)
            triangle_path.lineTo(indicator_rect.topRight())

            painter.fillPath(triangle_path, self.indicator_background)

        if self.pixmap:
            pixmap_rect = QRect(self.spacing, (widget_rect.height() - 20) // 2,
                                20, 20)
            painter.drawPixmap(pixmap_rect, self.pixmap, self.pixmap.rect())
            # painter.drawRect(pixmap_rect)
        else:
            pixmap_rect = QRect(0, 0, 0, 0)

        text_rect = QRect(pixmap_rect.right() + self.spacing, 0, 0,
                          widget_rect.height())
        text_rect.setWidth(widget_rect.width() - text_rect.left())
        # painter.drawRect(text_rect)

        text = self.fm.elidedText(self.text, Qt.ElideRight, text_rect.width())
        painter.setFont(self.font)
        painter.drawText(text_rect, Qt.AlignVCenter | Qt.AlignLeft, text)

    def _prepare_pixmap(self, qcolor):
        if self.pixmap is None:
            return
        painter = QPainter(self.pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceAtop)
        painter.fillRect(self.pixmap.rect(), qcolor)
        painter.end()

    def _get_opacity(self):
        return self.background_color.alpha()

    def _set_opacity(self, new_value):
        self.background_color.setAlpha(new_value)
        self.update()

    opacity = pyqtProperty('int', _get_opacity, _set_opacity)

    def _get_indicator_position(self):
        return self.indicator_pos

    def _set_indicator_position(self, new_value):
        self.indicator_pos = new_value
        self.update()

    indicator_position = pyqtProperty('int', _get_indicator_position,
                                      _set_indicator_position)

    def _get_indicator_opacity(self):
        return self.indicator_background.alpha()

    def _set_indicator_opacity(self, new_value):
        self.indicator_background.setAlpha(new_value)
        self.update()

    indicator_opacity = pyqtProperty('int', _get_indicator_opacity,
                                     _set_indicator_opacity)

    def handle_theme_change(self, theme):
        if theme == self.theme:
            return

        self.theme = theme
        if theme == 'dark':
            rgb_value = 255
        else:
            rgb_value = 0

        self.background_color.setRgb(rgb_value, rgb_value, rgb_value,
                                     self.background_color.alpha())
        self.indicator_background.setRgb(rgb_value, rgb_value, rgb_value,
                                         self.indicator_background.alpha())
        self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200))
        self.update()