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()
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
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)
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()
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)
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)
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)
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()
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()
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()
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)