Beispiel #1
0
class SystemTrayIcon(QSystemTrayIcon):
    def __init__(self, parent):
        super(SystemTrayIcon, self).__init__()
        self.parent = parent

        self.icon = QIcon(resource(settings['application']['tray_icon']))
        self.setIcon(self.icon)

        self.menu = Menu(self)
        self.setContextMenu(self.menu)
        self.activated.connect(self.on_click)

        self.animation = QMovie()
        self.animation.setFileName(
            resource(settings['application']['tray_icon_sync']))
        self.animation.updated.connect(self.update)
        self.animation.setCacheMode(True)

    def update(self):
        if self.parent.core.operations:
            self.animation.setPaused(False)
            self.setIcon(QIcon(self.animation.currentPixmap()))
        else:
            self.animation.setPaused(True)
            self.setIcon(self.icon)

    def on_click(self, value):
        if value == QSystemTrayIcon.Trigger and sys.platform != 'darwin':
            self.parent.show_main_window()
Beispiel #2
0
class QBusyWidget(QLabel,
                  QObserver,
                  qobservables={BusyObservable: {'busy_changed'}}):
    """A widget indicating a that some component is busy.
    """
    _label: QLabel = None
    _movie: QMovie = None
    _busy: bool = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Animated gifs can be obtained from
        # http://www.ajaxload.info/#preview
        self._busy = None
        self._movie = QMovie(os.path.join('assets', 'busy.gif'))
        self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    def busy_changed(self, busyBody: BusyObservable,
                     change: BusyObservable.Change) -> None:
        """React to a change of business.
        """
        LOG.debug("QBusyWidget[%s].busy_changed(%s): %s", busyBody, change,
                  busyBody.busy)
        self.setBusy(busyBody.busy)

    def busy(self) -> bool:
        return self._busy

    def setBusy(self, busy: bool) -> None:
        if busy is not self._busy:
            self._busy = busy
            self.update()

    def update(self) -> None:
        self._movie.setPaused(not self._busy)
        if self._busy:
            # Setting the text clears any previous content (like
            # text, picture, etc.)
            self.setMovie(self._movie)
        else:
            # Setting the text clears any previous content (like
            # picture, movie, etc.)
            self.setText("Not busy")
        super().update()

    def __del__(self):
        """Free resources used by this :py:class:`QBusyWidget`.
        """
        # Make sure the movie stops playing.
        self._movie.stop()
        del self._movie
Beispiel #3
0
class Delegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(Delegate, self).__init__(parent=None)
        self.parent = parent
        self.waiting_movie = QMovie(resource('waiting.gif'))
        self.waiting_movie.setCacheMode(True)
        self.waiting_movie.frameChanged.connect(self.on_frame_changed)
        self.sync_movie = QMovie(resource('sync.gif'))
        self.sync_movie.setCacheMode(True)
        self.sync_movie.frameChanged.connect(self.on_frame_changed)

    def on_frame_changed(self):
        values = self.parent.model().status_dict.values()
        if 0 in values or 1 in values:
            self.parent.viewport().update()
        else:
            self.waiting_movie.setPaused(True)
            self.sync_movie.setPaused(True)

    def paint(self, painter, option, index):
        column = index.column()
        if column == 1:
            pixmap = None
            status = index.data(Qt.UserRole)
            if not status:  # "Loading..."
                self.waiting_movie.setPaused(False)
                pixmap = self.waiting_movie.currentPixmap().scaled(20, 20)
            elif status == 1:  # "Syncing"
                self.sync_movie.setPaused(False)
                pixmap = self.sync_movie.currentPixmap().scaled(20, 20)
            if pixmap:
                point = option.rect.topLeft()
                painter.drawPixmap(QPoint(point.x(), point.y() + 5), pixmap)
                option.rect = option.rect.translated(pixmap.width(), 0)
        super(Delegate, self).paint(painter, option, index)
Beispiel #4
0
class SystemTrayIcon(QSystemTrayIcon):
    def __init__(self, gui):
        super(SystemTrayIcon, self).__init__()
        self.gui = gui

        tray_icon_path = resource(settings['application']['tray_icon'])
        self.app_pixmap = QPixmap(tray_icon_path)
        self.app_icon = QIcon(tray_icon_path)
        self.setIcon(self.app_icon)

        self.menu = Menu(self.gui)
        self.setContextMenu(self.menu)
        self.activated.connect(self.on_click)

        self.messageClicked.connect(self.gui.show_main_window)

        self.animation = QMovie()
        self.animation.setFileName(
            resource(settings['application']['tray_icon_sync']))
        self.animation.updated.connect(self.update)
        self.animation.setCacheMode(True)

    def update(self):
        if self.gui.core.operations:
            self.animation.setPaused(False)
            pixmap = self.animation.currentPixmap()
            if self.gui.unread_messages:
                pixmap = BadgedPixmap(
                    pixmap, len(self.gui.unread_messages), 0.6
                )
            self.setIcon(QIcon(pixmap))
        else:
            self.animation.setPaused(True)
            if self.gui.unread_messages:
                self.setIcon(QIcon(BadgedPixmap(
                    self.app_pixmap, len(self.gui.unread_messages), 0.6
                )))
            else:
                self.setIcon(self.app_icon)

    def on_click(self, value):
        if value == QSystemTrayIcon.Trigger and sys.platform != 'darwin':
            self.gui.show_main_window()
Beispiel #5
0
class MainWidget(QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.setStyleSheet('background-color: white')

        self.label = QLabel()
        # 居中对齐
        self.label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        self.loading = QMovie("images/loading.gif")
        self.label.setMovie(self.loading)
        self.layout = QHBoxLayout()
        self.layout.addWidget(self.label)
        self.loading_start()
        self.setLayout(self.layout)

    def loading_start(self):
        self.loading.start()
        # self.loading.stop()
        time.sleep(2)
        self.loading.setPaused(True)
Beispiel #6
0
class StatusBarView(QStatusBar):
    """
    The model of Navigation component
    """
    def __init__(self, parent):
        super().__init__(parent)

        self.status_label = QLabel("", parent)
        self.status_label.setTextFormat(Qt.RichText)

        self.label_time = QLabel("", parent)

        self.combo_referential = QComboBox(parent)
        self.movie_loader = QMovie(":/icons/loader")
        self.label_loading = QLabel(parent)
        self.label_loading.setMovie(self.movie_loader)
        self.label_loading.setMaximumHeight(self.height())
        self.movie_loader.setScaledSize(QSize(16, 16))
        self.movie_loader.start()
        self.movie_loader.setPaused(True)
        self.addPermanentWidget(self.label_loading)
        self.addPermanentWidget(self.status_label, 2)
        self.addPermanentWidget(self.label_time)
        self.addPermanentWidget(self.combo_referential)

    def start_loading(self):
        self.movie_loader.setPaused(False)

    def stop_loading(self):
        self.movie_loader.setPaused(True)
Beispiel #7
0
class StatusBarView(QStatusBar):
    """
    The model of Navigation component
    """

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

        self.status_label = QLabel("", parent)
        self.status_label.setTextFormat(Qt.RichText)

        self.label_time = QLabel("", parent)

        self.combo_referential = QComboBox(parent)
        self.movie_loader = QMovie(":/icons/loader")
        self.label_loading = QLabel(parent)
        self.label_loading.setMovie(self.movie_loader)
        self.label_loading.setMaximumHeight(self.height())
        self.movie_loader.setScaledSize(QSize(16, 16))
        self.movie_loader.start()
        self.movie_loader.setPaused(True)
        self.addPermanentWidget(self.label_loading)
        self.addPermanentWidget(self.status_label, 2)
        self.addPermanentWidget(self.label_time)
        self.addPermanentWidget(self.combo_referential)

    def start_loading(self):
        self.movie_loader.setPaused(False)

    def stop_loading(self):
        self.movie_loader.setPaused(True)
Beispiel #8
0
class Delegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__(parent=None)
        self.parent = parent
        self.waiting_movie = QMovie(resource("waiting.gif"))
        self.waiting_movie.setCacheMode(True)
        self.waiting_movie.frameChanged.connect(self.on_frame_changed)
        self.sync_movie = QMovie(resource("sync.gif"))
        self.sync_movie.setCacheMode(True)
        self.sync_movie.frameChanged.connect(self.on_frame_changed)

    def on_frame_changed(self):
        values = self.parent.model().status_dict.values()
        if (MagicFolderChecker.LOADING in values
                or MagicFolderChecker.SYNCING in values
                or MagicFolderChecker.SCANNING in values):
            self.parent.viewport().update()
        else:
            self.waiting_movie.setPaused(True)
            self.sync_movie.setPaused(True)

    def paint(self, painter, option, index):
        column = index.column()
        if column == 1:
            pixmap = None
            status = index.data(Qt.UserRole)
            if status == MagicFolderChecker.LOADING:
                self.waiting_movie.setPaused(False)
                pixmap = self.waiting_movie.currentPixmap().scaled(
                    20, 20, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            elif status in (
                    MagicFolderChecker.SYNCING,
                    MagicFolderChecker.SCANNING,
            ):
                self.sync_movie.setPaused(False)
                pixmap = self.sync_movie.currentPixmap().scaled(
                    20, 20, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            if pixmap:
                point = option.rect.topLeft()
                painter.drawPixmap(QPoint(point.x(), point.y() + 5), pixmap)
                option.rect = option.rect.translated(pixmap.width(), 0)
        super().paint(painter, option, index)
Beispiel #9
0
class StatusPanel(QWidget):
    def __init__(self, gateway, gui):
        super().__init__()
        self.gateway = gateway
        self.gui = gui

        self.state = 0
        self.num_connected = 0
        self.num_known = 0
        self.available_space = 0

        self.checkmark_icon = QLabel()
        self.checkmark_icon.setPixmap(Pixmap("checkmark.png", 20))

        self.syncing_icon = QLabel()

        self.sync_movie = QMovie(resource("sync.gif"))
        self.sync_movie.setCacheMode(True)
        self.sync_movie.updated.connect(
            lambda: self.syncing_icon.setPixmap(self.sync_movie.currentPixmap(
            ).scaled(20, 20, Qt.KeepAspectRatio, Qt.SmoothTransformation)))

        self.status_label = QLabel()
        p = self.palette()
        dimmer_grey = BlendedColor(p.windowText().color(),
                                   p.window().color(), 0.6).name()
        self.status_label.setStyleSheet(f"QLabel {{ color: {dimmer_grey} }}")
        self.status_label.setFont(Font(10))

        self.setStyleSheet("QToolButton { border: none }")
        # self.setStyleSheet("""
        #    QToolButton { color: dimgrey; border: none; }
        #    QToolButton:hover {
        #        background-color: #FAFAFA;
        #        border: 1px solid grey;
        #        border-radius: 2px;
        #    }
        # """)

        self.tor_button = QToolButton()
        self.tor_button.setIconSize(QSize(20, 20))
        self.tor_action = QAction(
            QIcon(resource("tor-onion.png")),
            "This connection is being routed through the Tor network",
        )
        self.tor_button.setDefaultAction(self.tor_action)
        if not self.gateway.use_tor:
            self.tor_button.hide()

        preferences_button = QToolButton(self)
        preferences_button.setIcon(QIcon(resource("preferences.png")))
        preferences_button.setIconSize(QSize(20, 20))
        preferences_button.setMenu(Menu(self.gui, show_open_action=False))
        preferences_button.setPopupMode(2)
        preferences_button.setStyleSheet(
            "QToolButton::menu-indicator { image: none }")

        layout = QGridLayout(self)
        left, _, right, bottom = layout.getContentsMargins()
        layout.setContentsMargins(left, 0, right, bottom - 2)
        layout.addWidget(self.checkmark_icon, 1, 1)
        layout.addWidget(self.syncing_icon, 1, 1)
        layout.addWidget(self.status_label, 1, 2)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3)
        layout.addWidget(self.tor_button, 1, 4)
        layout.addWidget(preferences_button, 1, 6)

        self.gateway.monitor.total_sync_state_updated.connect(
            self.on_sync_state_updated)
        self.gateway.monitor.space_updated.connect(self.on_space_updated)
        self.gateway.monitor.nodes_updated.connect(self.on_nodes_updated)

        self.on_sync_state_updated(0)

    def _update_status_label(self):
        if self.state == 0:
            if self.gateway.shares_happy:
                if self.num_connected < self.gateway.shares_happy:
                    self.status_label.setText(
                        f"Connecting to {self.gateway.name} ("
                        f"{self.num_connected}/{self.gateway.shares_happy})..."
                    )
                else:
                    self.status_label.setText(
                        f"Connected to {self.gateway.name}")

            else:
                self.status_label.setText(
                    f"Connecting to {self.gateway.name}...")
            self.sync_movie.setPaused(True)
            self.syncing_icon.hide()
            self.checkmark_icon.hide()
        elif self.state == 1:
            self.status_label.setText("Syncing")
            self.checkmark_icon.hide()
            self.syncing_icon.show()
            self.sync_movie.setPaused(False)
        elif self.state == 2:
            self.status_label.setText("Up to date")
            self.sync_movie.setPaused(True)
            self.syncing_icon.hide()
            self.checkmark_icon.show()
        if self.available_space:
            self.status_label.setToolTip(
                "Connected to {} of {} storage nodes\n{} available".format(
                    self.num_connected, self.num_known, self.available_space))
        else:
            self.status_label.setToolTip(
                "Connected to {} of {} storage nodes".format(
                    self.num_connected, self.num_known))

    def on_sync_state_updated(self, state):
        self.state = state
        self._update_status_label()

    def on_space_updated(self, space):
        self.available_space = naturalsize(space)
        self._update_status_label()

    def on_nodes_updated(self, connected, known):
        self.num_connected = connected
        self.num_known = known
        self._update_status_label()
Beispiel #10
0
class App(QMainWindow):
    def __init__(self,
                 model_config=json.load(open('./model_util/config.json',
                                             "r"))):
        super().__init__()
        self.title = "Voice Conversion App"
        self.left = 0
        self.top = 0
        self.width = 800
        self.height = 800
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        #========================= some default setting =========================
        self.image_mapping = defaultdict(lambda: model_config["default_image"],
                                         model_config["speakers_image"])
        self.model_config = model_config

        self.central_widget = QWidget()
        self.layout = QHBoxLayout(self.central_widget)

        self.speaker_widget = display.SignalDisplayWidget(self, "Speaker")
        self.convert_widget = display.SignalDisplayWidget(self, "Convert")

        self.control_panel = QGroupBox("Control Panel")
        self.build_control_widget()  # will create self.control_widget
        #========================= start connect something ======================

        self.left_group = QGroupBox("Speaker")
        self.left_group_layout = QHBoxLayout(self.left_group)

        self.left_group_layout.addWidget(self.speaker_widget)
        self.left_group_layout.addWidget(self.control_widget)
        self.layout.addWidget(self.left_group)
        self.layout.addWidget(self.convert_widget)
        self.layout.addWidget(self.Movie_Label)

        self.control_items["Load"].clicked.connect(lambda: self.load_audio())
        self.control_items["Record"].clicked.connect(
            lambda: self.record_callback())

        self.setCentralWidget(self.central_widget)
        self.show()

    def build_control_widget(self):
        self.control_widget = QWidget()
        self.control_layout = QVBoxLayout()
        self.control_items = dict()
        CI = self.control_items

        # Label
        CI["Label_Sound"] = QLabel("==Sound==")
        # Push Buttons
        sound_button_names = ["Load", "Record"]
        for _name in sound_button_names:
            CI[_name] = QPushButton(_name, self)

        CI["Label_Model"] = QLabel("==Model==")
        CI["model_widget"] = self.construct_model_widget()

        for _, item in CI.items():
            self.control_layout.addWidget(item)
        self.control_layout.addStretch(1)
        self.control_widget.setLayout(self.control_layout)

    def record_callback(self):
        signal, sr = record.ui.record_dialog()
        self.set_audio(signal, sr)

    def load_audio(self):
        signal, sr = self.speaker_widget.load_audio()
        self.set_audio(signal, sr)

    def set_audio(self, signal, sr):
        self.speaker_widget.set_audio(signal, sr)
        self.model_widget.set_signal(signal, sr)

    def construct_model_widget(self):
        self.model_widget = model_helper.ModelDisplayWidget(
            self, self.model_config)

        but = self.model_widget.convert_button
        but.clicked.disconnect()
        but.clicked.connect(self.go_convert)

        combo_box = self.model_widget.trg_combo_box
        combo_box.currentIndexChanged.connect(self.change_target)
        self.movie = QMovie(self)
        self.Movie_Label = QLabel(self)
        self.Movie_Label.setMovie(self.movie)

        self.change_target()  # change target image

        return self.model_widget

    def go_convert(self):
        signal, sr = self.model_widget.go_convert()
        print(signal, sr)
        self.convert_widget.set_audio(signal, sr)

    def change_target(self):
        self.movie.setPaused(True)
        trg_name = self.model_widget.trg_combo_box.currentText()
        image_path = self.image_mapping[trg_name]
        self.movie.setFileName(image_path)
        self.movie.start()
Beispiel #11
0
class StatusPanel(QWidget):
    def __init__(self, gateway, gui):
        super(StatusPanel, self).__init__()
        self.gateway = gateway
        self.gui = gui

        self.num_connected = 0
        self.num_known = 0
        self.available_space = 0

        self.checkmark_icon = QLabel()
        self.checkmark_icon.setPixmap(
            QPixmap(resource('checkmark.png')).scaled(20, 20))

        self.syncing_icon = QLabel()

        self.sync_movie = QMovie(resource('sync.gif'))
        self.sync_movie.setCacheMode(True)
        self.sync_movie.updated.connect(lambda: self.syncing_icon.setPixmap(
            self.sync_movie.currentPixmap().scaled(20, 20)))

        self.status_label = QLabel()
        self.status_label.setStyleSheet("color: dimgrey")

        self.on_sync_state_updated(0)

        self.setStyleSheet('QToolButton { color: dimgrey; border: none; }')
        #self.setStyleSheet("""
        #    QToolButton { color: dimgrey; border: none; }
        #    QToolButton:hover {
        #        background-color: #FAFAFA;
        #        border: 1px solid grey;
        #        border-radius: 2px;
        #    }
        #""")

        self.tor_button = QToolButton()
        self.tor_button.setIconSize(QSize(20, 20))
        self.tor_action = QAction(
            QIcon(resource('tor-onion.png')),
            "This connection is being routed through the Tor network")
        self.tor_button.setDefaultAction(self.tor_action)
        if not self.gateway.use_tor:
            self.tor_button.hide()

        self.globe_button = QToolButton()
        self.globe_button.setIconSize(QSize(20, 20))
        self.globe_action = QAction(QIcon(resource('globe.png')), '')
        self.globe_button.setDefaultAction(self.globe_action)

        preferences_button = QToolButton(self)
        preferences_button.setIcon(QIcon(resource('preferences.png')))
        preferences_button.setIconSize(QSize(20, 20))
        preferences_button.setMenu(Menu(self.gui, show_open_action=False))
        preferences_button.setPopupMode(2)
        preferences_button.setStyleSheet(
            'QToolButton::menu-indicator { image: none }')

        if QSystemTrayIcon.isSystemTrayAvailable():
            preferences_button.hide()

        layout = QGridLayout(self)
        left, _, right, bottom = layout.getContentsMargins()
        layout.setContentsMargins(left, 0, right, bottom - 2)
        layout.addWidget(self.checkmark_icon, 1, 1)
        layout.addWidget(self.syncing_icon, 1, 1)
        layout.addWidget(self.status_label, 1, 2)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3)
        layout.addWidget(self.tor_button, 1, 4)
        layout.addWidget(self.globe_button, 1, 5)
        layout.addWidget(preferences_button, 1, 6)

        self.gateway.monitor.total_sync_state_updated.connect(
            self.on_sync_state_updated)
        self.gateway.monitor.space_updated.connect(self.on_space_updated)
        self.gateway.monitor.nodes_updated.connect(self.on_nodes_updated)

    def on_sync_state_updated(self, state):
        if state == 0:
            self.status_label.setText("Connecting...")
            self.sync_movie.setPaused(True)
            self.syncing_icon.hide()
            self.checkmark_icon.hide()
        elif state == 1:
            self.status_label.setText("Syncing")
            self.checkmark_icon.hide()
            self.syncing_icon.show()
            self.sync_movie.setPaused(False)
        elif state == 2:
            self.status_label.setText("Up to date")
            self.sync_movie.setPaused(True)
            self.syncing_icon.hide()
            self.checkmark_icon.show()

    def _update_grid_info_tooltip(self):
        if self.available_space:
            self.globe_action.setToolTip(
                "Connected to {} of {} storage nodes\n{} available".format(
                    self.num_connected, self.num_known, self.available_space))
        else:
            self.globe_action.setToolTip(
                "Connected to {} of {} storage nodes".format(
                    self.num_connected, self.num_known))

    def on_space_updated(self, space):
        self.available_space = naturalsize(space)
        self._update_grid_info_tooltip()

    def on_nodes_updated(self, connected, known):
        self.status_label.setText("Connected to {} of {} storage nodes".format(
            connected, known))
        self.num_connected = connected
        self.num_known = known
        self._update_grid_info_tooltip()
Beispiel #12
0
class GIFItem(BaseItem):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.gesture_id = self.item_spec['id']
        self.verbose_name = cn.GESTURES[self.gesture_id].verbose_name
        gif_path = cn.MODELS_FOLDER / f'{cn.GESTURES[self.gesture_id].slug}.gif'

        if not gif_path.exists():
            raise ValueError(f'Missing gif at {gif_path}.')

        self.width = self.item_spec.get(
            'width', cn.GIF_RECORDING_SIZE[0] * cn.GIF_DISPLAY_SIZE)
        self.height = self.item_spec.get(
            'height', cn.GIF_RECORDING_SIZE[1] * cn.GIF_DISPLAY_SIZE)

        self.movie = QMovie(gif_path.as_posix())
        self.gif_progress_bar = QProgressBar()

    def get_widget(self) -> Union[QWidget, None]:
        name_label = QLabel(self.verbose_name)
        name_label.setAlignment(Qt.AlignCenter)

        gif_label = QLabel()
        gif_label.setMovie(self.movie)
        self.movie.start()

        gif_label.setScaledContents(True)
        gif_label.setFixedSize(self.width, self.height)
        gif_label.setAlignment(Qt.AlignCenter)
        gif_label.setFrameStyle(QFrame.Panel)

        last_frame = self.movie.frameCount() - 1
        self.gif_progress_bar.setMaximum(last_frame)

        def update_animation_progress(frame_index):
            try:
                self.gif_progress_bar.setValue(frame_index)
                if frame_index == last_frame:
                    self.movie.setPaused(True)
                    QTimer.singleShot(1000,
                                      lambda: self.movie.setPaused(False))
            except RuntimeError:
                # This is a temporary fix, because the parent widget is deleted manually
                logger.debug('Gif Item Progress bar deleted before stopping.')
                self.movie.stop()

        self.movie.frameChanged.connect(update_animation_progress)
        GlobalEventFilter.get_instance().install_key_hook(
            Qt.Key_Space, self.replay_movie)

        layout = QVBoxLayout()
        layout.addWidget(name_label)
        layout.addWidget(gif_label)
        layout.addWidget(self.gif_progress_bar)
        layout.setSpacing(5)
        layout.setContentsMargins(0, 0, 0, 0)

        widget = QWidget()
        widget.setLayout(layout)
        widget.setFixedSize(self.width, self.height + 50)
        return widget

    def replay_movie(self, _, event: QEvent):
        key_event = QKeyEvent(event)
        if key_event.type(
        ) == QKeyEvent.KeyPress and not key_event.isAutoRepeat():
            self.movie.stop()
            self.movie.start()
            effect = QGraphicsDropShadowEffect()
            effect.setBlurRadius(20)
            effect.setXOffset(0)
            effect.setYOffset(0)
            effect.setColor(Qt.red)
            self.gif_progress_bar.setGraphicsEffect(effect)

        if key_event.type() == QKeyEvent.KeyRelease:
            self.gif_progress_bar.setGraphicsEffect(None)

    def finish(self):
        self.movie.stop()
        GlobalEventFilter.get_instance().remove_key_hook(
            Qt.Key_Space, self.replay_movie)