def _update_row(self, pkg: PackageView, update_check_enabled: bool = True, change_update_col: bool = True): self._set_col_icon(0, pkg) self._set_col_name(1, pkg) self._set_col_version(2, pkg) self._set_col_description(3, pkg) self._set_col_publisher(4, pkg) self._set_col_type(5, pkg) self._set_col_installed(6, pkg) self._set_col_actions(7, pkg) if change_update_col and update_check_enabled: if pkg.model.installed and not pkg.model.is_update_ignored( ) and pkg.model.update: col_update = QCustomToolbar() col_update.add_space() col_update.add_widget( UpgradeToggleButton(pkg=pkg, root=self.window, i18n=self.i18n, checked=pkg.update_checked if pkg.model.can_be_updated() else False, clickable=pkg.model.can_be_updated())) col_update.add_space() else: col_update = QLabel() self.setCellWidget(pkg.table_index, 8, col_update)
def _set_col_installed(self, col: int, pkg: PackageView): toolbar = QCustomToolbar() toolbar.add_space() if pkg.model.installed: if pkg.model.can_be_uninstalled(): def uninstall(): self._uninstall(pkg) item = self._gen_row_button( text=self.i18n['uninstall'].capitalize(), name='bt_uninstall', callback=uninstall, tip=self.i18n['manage_window.bt_uninstall.tip']) else: item = None elif pkg.model.can_be_installed(): def install(): self._install_app(pkg) item = self._gen_row_button( text=self.i18n['install'].capitalize(), name='bt_install', callback=install, tip=self.i18n['manage_window.bt_install.tip']) else: item = None toolbar.add_widget(item) toolbar.add_space() self.setCellWidget(pkg.table_index, col, toolbar)
def _set_col_actions(self, col: int, pkg: PackageView): toolbar = QCustomToolbar() toolbar.setObjectName('app_actions') toolbar.add_space() if pkg.model.installed: def run(): self.window.begin_launch_package(pkg) bt = IconButton(i18n=self.i18n, action=run, tooltip=self.i18n['action.run.tooltip']) bt.setObjectName('app_run') if not pkg.model.can_be_run(): bt.setEnabled(False) bt.setProperty('_enabled', 'false') toolbar.layout().addWidget(bt) settings = self.has_any_settings(pkg) if pkg.model.installed: def handle_custom_actions(): self.show_pkg_actions(pkg) bt = IconButton(i18n=self.i18n, action=handle_custom_actions, tooltip=self.i18n['action.settings.tooltip']) bt.setObjectName('app_actions') bt.setEnabled(bool(settings)) toolbar.layout().addWidget(bt) if not pkg.model.installed: def show_screenshots(): self.window.begin_show_screenshots(pkg) bt = IconButton(i18n=self.i18n, action=show_screenshots, tooltip=self.i18n['action.screenshots.tooltip']) bt.setObjectName('app_screenshots') if not pkg.model.has_screenshots(): bt.setEnabled(False) bt.setProperty('_enabled', 'false') toolbar.layout().addWidget(bt) def show_info(): self.window.begin_show_info(pkg) bt = IconButton(i18n=self.i18n, action=show_info, tooltip=self.i18n['action.info.tooltip']) bt.setObjectName('app_info') bt.setEnabled(bool(pkg.model.has_info())) toolbar.layout().addWidget(bt) self.setCellWidget(pkg.table_index, col, toolbar)
def __init__(self, context: ApplicationContext, manager: SoftwareManager, screen_size: QSize, i18n: I18n, manage_window: QWidget, app_config: dict): super(PreparePanel, self).__init__(flags=Qt.CustomizeWindowHint | Qt.WindowTitleHint) self.i18n = i18n self.context = context self.app_config = app_config self.manage_window = manage_window self.setWindowTitle('{} ({})'.format( __app_name__, self.i18n['prepare_panel.title.start'].lower())) self.setMinimumWidth(screen_size.width() * 0.5) self.setMinimumHeight(screen_size.height() * 0.35) self.setMaximumHeight(screen_size.height() * 0.95) self.setLayout(QVBoxLayout()) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.manager = manager self.tasks = {} self.output = {} self.added_tasks = 0 self.ftasks = 0 self.started_at = None self.self_close = False self.prepare_thread = Prepare(self.context, manager, self.i18n) self.prepare_thread.signal_register.connect(self.register_task) self.prepare_thread.signal_update.connect(self.update_progress) self.prepare_thread.signal_finished.connect(self.finish_task) self.prepare_thread.signal_started.connect(self.start) self.prepare_thread.signal_ask_password.connect(self.ask_root_password) self.prepare_thread.signal_output.connect(self.update_output) self.signal_password_response.connect( self.prepare_thread.set_password_reply) self.check_thread = CheckFinished() self.signal_status.connect(self.check_thread.update) self.check_thread.signal_finished.connect(self.finish) self.skip_thread = EnableSkip() self.skip_thread.signal_timeout.connect(self._enable_skip_button) self.progress_thread = AnimateProgress() self.progress_thread.signal_change.connect(self._change_progress) self.label_top = QLabel() self.label_top.setCursor(QCursor(Qt.WaitCursor)) self.label_top.setText("{}...".format( self.i18n['prepare_panel.title.start'].capitalize())) self.label_top.setObjectName('prepare_status') self.label_top.setAlignment(Qt.AlignHCenter) self.layout().addWidget(self.label_top) self.layout().addWidget(QLabel()) self.table = QTableWidget() self.table.setObjectName('tasks') self.table.setCursor(QCursor(Qt.WaitCursor)) self.table.setFocusPolicy(Qt.NoFocus) self.table.setShowGrid(False) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.horizontalHeader().setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self.table.setColumnCount(4) self.table.setHorizontalHeaderLabels(['' for _ in range(4)]) self.table.horizontalScrollBar().setCursor( QCursor(Qt.PointingHandCursor)) self.table.verticalScrollBar().setCursor(QCursor( Qt.PointingHandCursor)) self.layout().addWidget(self.table) self.textarea_details = QPlainTextEdit(self) self.textarea_details.setObjectName('task_details') self.textarea_details.setProperty('console', 'true') self.textarea_details.resize(self.table.size()) self.layout().addWidget(self.textarea_details) self.textarea_details.setVisible(False) self.textarea_details.setReadOnly(True) self.textarea_details.setMaximumHeight(100) self.current_output_task = None self.bottom_widget = QWidget() self.bottom_widget.setLayout(QHBoxLayout()) self.bottom_widget.layout().addStretch() bt_hide_details = QPushButton(self.i18n['prepare.bt_hide_details']) bt_hide_details.setObjectName('bt_hide_details') bt_hide_details.clicked.connect(self.hide_output) bt_hide_details.setCursor(QCursor(Qt.PointingHandCursor)) self.bottom_widget.layout().addWidget(bt_hide_details) self.bottom_widget.layout().addStretch() self.layout().addWidget(self.bottom_widget) self.bottom_widget.setVisible(False) self.bt_bar = QCustomToolbar() self.bt_close = QPushButton(self.i18n['close'].capitalize()) self.bt_close.setObjectName('bt_cancel') self.bt_close.setCursor(QCursor(Qt.PointingHandCursor)) self.bt_close.clicked.connect(self.close) self.bt_close.setVisible(False) self.bt_bar.add_widget(self.bt_close) self.bt_bar.add_widget(new_spacer()) self.progress_bar = QProgressBar() self.progress_bar.setObjectName('prepare_progress') self.progress_bar.setTextVisible(False) self.progress_bar.setVisible(False) self.progress_bar.setCursor(QCursor(Qt.WaitCursor)) self.bt_bar.add_widget(self.progress_bar) self.bt_bar.add_widget(new_spacer()) self.bt_skip = QPushButton( self.i18n['prepare_panel.bt_skip.label'].capitalize()) self.bt_skip.clicked.connect(self.finish) self.bt_skip.setEnabled(False) self.bt_skip.setCursor(QCursor(Qt.WaitCursor)) self.bt_bar.add_widget(self.bt_skip) self.layout().addWidget(self.bt_bar)
class PreparePanel(QWidget, TaskManager): signal_status = pyqtSignal(int) signal_password_response = pyqtSignal(bool, str) def __init__(self, context: ApplicationContext, manager: SoftwareManager, screen_size: QSize, i18n: I18n, manage_window: QWidget, app_config: dict): super(PreparePanel, self).__init__(flags=Qt.CustomizeWindowHint | Qt.WindowTitleHint) self.i18n = i18n self.context = context self.app_config = app_config self.manage_window = manage_window self.setWindowTitle('{} ({})'.format( __app_name__, self.i18n['prepare_panel.title.start'].lower())) self.setMinimumWidth(screen_size.width() * 0.5) self.setMinimumHeight(screen_size.height() * 0.35) self.setMaximumHeight(screen_size.height() * 0.95) self.setLayout(QVBoxLayout()) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.manager = manager self.tasks = {} self.output = {} self.added_tasks = 0 self.ftasks = 0 self.started_at = None self.self_close = False self.prepare_thread = Prepare(self.context, manager, self.i18n) self.prepare_thread.signal_register.connect(self.register_task) self.prepare_thread.signal_update.connect(self.update_progress) self.prepare_thread.signal_finished.connect(self.finish_task) self.prepare_thread.signal_started.connect(self.start) self.prepare_thread.signal_ask_password.connect(self.ask_root_password) self.prepare_thread.signal_output.connect(self.update_output) self.signal_password_response.connect( self.prepare_thread.set_password_reply) self.check_thread = CheckFinished() self.signal_status.connect(self.check_thread.update) self.check_thread.signal_finished.connect(self.finish) self.skip_thread = EnableSkip() self.skip_thread.signal_timeout.connect(self._enable_skip_button) self.progress_thread = AnimateProgress() self.progress_thread.signal_change.connect(self._change_progress) self.label_top = QLabel() self.label_top.setCursor(QCursor(Qt.WaitCursor)) self.label_top.setText("{}...".format( self.i18n['prepare_panel.title.start'].capitalize())) self.label_top.setObjectName('prepare_status') self.label_top.setAlignment(Qt.AlignHCenter) self.layout().addWidget(self.label_top) self.layout().addWidget(QLabel()) self.table = QTableWidget() self.table.setObjectName('tasks') self.table.setCursor(QCursor(Qt.WaitCursor)) self.table.setFocusPolicy(Qt.NoFocus) self.table.setShowGrid(False) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.horizontalHeader().setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self.table.setColumnCount(4) self.table.setHorizontalHeaderLabels(['' for _ in range(4)]) self.table.horizontalScrollBar().setCursor( QCursor(Qt.PointingHandCursor)) self.table.verticalScrollBar().setCursor(QCursor( Qt.PointingHandCursor)) self.layout().addWidget(self.table) self.textarea_details = QPlainTextEdit(self) self.textarea_details.setObjectName('task_details') self.textarea_details.setProperty('console', 'true') self.textarea_details.resize(self.table.size()) self.layout().addWidget(self.textarea_details) self.textarea_details.setVisible(False) self.textarea_details.setReadOnly(True) self.textarea_details.setMaximumHeight(100) self.current_output_task = None self.bottom_widget = QWidget() self.bottom_widget.setLayout(QHBoxLayout()) self.bottom_widget.layout().addStretch() bt_hide_details = QPushButton(self.i18n['prepare.bt_hide_details']) bt_hide_details.setObjectName('bt_hide_details') bt_hide_details.clicked.connect(self.hide_output) bt_hide_details.setCursor(QCursor(Qt.PointingHandCursor)) self.bottom_widget.layout().addWidget(bt_hide_details) self.bottom_widget.layout().addStretch() self.layout().addWidget(self.bottom_widget) self.bottom_widget.setVisible(False) self.bt_bar = QCustomToolbar() self.bt_close = QPushButton(self.i18n['close'].capitalize()) self.bt_close.setObjectName('bt_cancel') self.bt_close.setCursor(QCursor(Qt.PointingHandCursor)) self.bt_close.clicked.connect(self.close) self.bt_close.setVisible(False) self.bt_bar.add_widget(self.bt_close) self.bt_bar.add_widget(new_spacer()) self.progress_bar = QProgressBar() self.progress_bar.setObjectName('prepare_progress') self.progress_bar.setTextVisible(False) self.progress_bar.setVisible(False) self.progress_bar.setCursor(QCursor(Qt.WaitCursor)) self.bt_bar.add_widget(self.progress_bar) self.bt_bar.add_widget(new_spacer()) self.bt_skip = QPushButton( self.i18n['prepare_panel.bt_skip.label'].capitalize()) self.bt_skip.clicked.connect(self.finish) self.bt_skip.setEnabled(False) self.bt_skip.setCursor(QCursor(Qt.WaitCursor)) self.bt_bar.add_widget(self.bt_skip) self.layout().addWidget(self.bt_bar) def hide_output(self): self.current_output_task = None self.textarea_details.setVisible(False) self.textarea_details.clear() self.bottom_widget.setVisible(False) self._resize_columns() self.setFocus(Qt.NoFocusReason) if not self.bt_bar.isVisible(): self.bt_bar.setVisible(True) def ask_root_password(self): valid, root_pwd = RootDialog.ask_password(self.context, self.i18n) self.signal_password_response.emit(valid, root_pwd) def _enable_skip_button(self): self.bt_skip.setEnabled(True) self.bt_skip.setCursor(QCursor(Qt.PointingHandCursor)) def _change_progress(self, value: int): self.progress_bar.setValue(value) def get_table_width(self) -> int: return reduce(operator.add, [ self.table.columnWidth(i) for i in range(self.table.columnCount()) ]) def _resize_columns(self): header_horizontal = self.table.horizontalHeader() for i in range(self.table.columnCount()): header_horizontal.setSectionResizeMode( i, QHeaderView.ResizeToContents) self.resize(int(self.get_table_width() * 1.05), self.sizeHint().height()) def show(self): super(PreparePanel, self).show() self.prepare_thread.start() centralize(self) def start(self, tasks: int): self.started_at = time.time() self.check_thread.total = tasks self.check_thread.start() self.skip_thread.start() self.progress_thread.start() self.bt_close.setVisible(True) self.progress_bar.setVisible(True) def closeEvent(self, ev: QCloseEvent): if not self.self_close: QCoreApplication.exit() def register_task(self, id_: str, label: str, icon_path: str): self.added_tasks += 1 self.table.setRowCount(self.added_tasks) task_row = self.added_tasks - 1 icon_widget = QWidget() icon_widget.setProperty('container', 'true') icon_widget.setLayout(QHBoxLayout()) icon_widget.layout().setContentsMargins(10, 0, 10, 0) bt_icon = QToolButton() bt_icon.setObjectName('bt_task') bt_icon.setCursor(QCursor(Qt.WaitCursor)) bt_icon.setEnabled(False) bt_icon.setToolTip(self.i18n['prepare.bt_icon.no_output']) if icon_path: bt_icon.setIcon(QIcon(icon_path)) def _show_output(): lines = self.output[id_] if lines: self.current_output_task = id_ self.textarea_details.clear() self.textarea_details.setVisible(True) for l in lines: self.textarea_details.appendPlainText(l) self.bottom_widget.setVisible(True) self.setFocus(Qt.NoFocusReason) if self.bt_bar.isVisible(): self.bt_bar.setVisible(False) bt_icon.clicked.connect(_show_output) icon_widget.layout().addWidget(bt_icon) self.table.setCellWidget(task_row, 0, icon_widget) lb_status = QLabel(label) lb_status.setObjectName('task_status') lb_status.setProperty('status', 'running') lb_status.setCursor(Qt.WaitCursor) lb_status.setMinimumWidth(50) lb_status.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) lb_status_col = 1 self.table.setCellWidget(task_row, lb_status_col, lb_status) lb_progress = QLabel('{0:.2f}'.format(0) + '%') lb_progress.setObjectName('task_progress') lb_progress.setProperty('status', 'running') lb_progress.setCursor(Qt.WaitCursor) lb_progress.setContentsMargins(10, 0, 10, 0) lb_progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) lb_progress_col = 2 self.table.setCellWidget(task_row, lb_progress_col, lb_progress) lb_sub = QLabel() lb_sub.setObjectName('task_substatus') lb_sub.setCursor(Qt.WaitCursor) lb_sub.setContentsMargins(10, 0, 10, 0) lb_sub.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) lb_sub.setMinimumWidth(50) self.table.setCellWidget(task_row, 3, lb_sub) self.tasks[id_] = { 'bt_icon': bt_icon, 'lb_status': lb_status, 'lb_status_col': lb_status_col, 'lb_prog': lb_progress, 'lb_prog_col': lb_progress_col, 'progress': 0, 'lb_sub': lb_sub, 'finished': False, 'row': task_row } def update_progress(self, task_id: str, progress: float, substatus: str): task = self.tasks[task_id] if progress != task['progress']: task['progress'] = progress task['lb_prog'].setText('{0:.2f}'.format(progress) + '%') if substatus: task['lb_sub'].setText('({})'.format(substatus)) else: task['lb_sub'].setText('') self._resize_columns() def update_output(self, task_id: str, output: str): full_output = self.output.get(task_id) if full_output is None: full_output = [] self.output[task_id] = full_output task = self.tasks[task_id] task['bt_icon'].setEnabled(True) task['bt_icon'].setCursor(QCursor(Qt.PointingHandCursor)) task['bt_icon'].setToolTip(self.i18n['prepare.bt_icon.output']) full_output.append(output) if self.current_output_task == task_id: self.textarea_details.appendPlainText(output) def finish_task(self, task_id: str): task = self.tasks[task_id] for key in ('lb_prog', 'lb_status', 'lb_sub'): label = task[key] label.setProperty('status', 'done') label.style().unpolish(label) label.style().polish(label) label.update() task['finished'] = True self._resize_columns() self.ftasks += 1 self.signal_status.emit(self.ftasks) def finish(self): now = time.time() self.context.logger.info( "{0} tasks finished in {1:.9f} seconds".format( self.ftasks, (now - self.started_at))) if self.isVisible(): self.manage_window.show() if self.app_config['boot']['load_apps']: self.manage_window.begin_refresh_packages() else: self.manage_window.load_without_packages() self.self_close = True self.close()