mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 01:14:15 +02:00
722 lines
29 KiB
Python
Executable File
722 lines
29 KiB
Python
Executable File
import operator
|
|
from functools import reduce
|
|
from typing import List, Set
|
|
|
|
from PyQt5.QtCore import QEvent, Qt, QSize, pyqtSignal
|
|
from PyQt5.QtGui import QIcon, QWindowStateChangeEvent, QPixmap
|
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QCheckBox, QHeaderView, QToolButton, QToolBar, \
|
|
QSizePolicy, QLabel, QPlainTextEdit, QLineEdit, QProgressBar, QHBoxLayout
|
|
from bauh_api.abstract.controller import ApplicationManager
|
|
from bauh_api.abstract.model import Application
|
|
from bauh_api.util.cache import Cache
|
|
|
|
from bauh.core import resource
|
|
from bauh.util import util
|
|
from bauh.view.qt import dialog
|
|
from bauh.view.qt.about import AboutDialog
|
|
from bauh.view.qt.apps_table import AppsTable
|
|
from bauh.view.qt.history import HistoryDialog
|
|
from bauh.view.qt.info import InfoDialog
|
|
from bauh.view.qt.root import is_root, ask_root_password
|
|
from bauh.view.qt.thread import UpdateSelectedApps, RefreshApps, UninstallApp, DowngradeApp, GetAppInfo, \
|
|
GetAppHistory, SearchApps, InstallApp, AnimateProgress, VerifyModels, RefreshApp, FindSuggestions, ListWarnings, \
|
|
AsyncAction
|
|
from bauh.view.qt.view_model import ApplicationView
|
|
|
|
DARK_ORANGE = '#FF4500'
|
|
|
|
|
|
class ManageWindow(QWidget):
|
|
__BASE_HEIGHT__ = 400
|
|
|
|
signal_user_res = pyqtSignal(dict)
|
|
|
|
def __init__(self, locale_keys: dict, icon_cache: Cache, manager: ApplicationManager, disk_cache: bool, download_icons: bool, screen_size, suggestions: bool, tray_icon=None):
|
|
super(ManageWindow, self).__init__()
|
|
self.locale_keys = locale_keys
|
|
self.manager = manager
|
|
self.tray_icon = tray_icon
|
|
self.working = False # restrict the number of threaded actions
|
|
self.apps = []
|
|
self.label_flatpak = None
|
|
self.icon_cache = icon_cache
|
|
self.disk_cache = disk_cache
|
|
self.download_icons = download_icons
|
|
self.screen_size = screen_size
|
|
|
|
self.icon_flathub = QIcon(resource.get_path('img/logo.svg'))
|
|
self.resize(ManageWindow.__BASE_HEIGHT__, ManageWindow.__BASE_HEIGHT__)
|
|
self.setWindowIcon(self.icon_flathub)
|
|
|
|
self.layout = QVBoxLayout()
|
|
self.setLayout(self.layout)
|
|
|
|
self.toolbar_top = QToolBar()
|
|
self.toolbar_top.addWidget(self._new_spacer())
|
|
|
|
self.label_status = QLabel()
|
|
self.label_status.setText('')
|
|
self.label_status.setStyleSheet("font-weight: bold")
|
|
self.toolbar_top.addWidget(self.label_status)
|
|
|
|
self.toolbar_search = QToolBar()
|
|
self.toolbar_search.setStyleSheet("spacing: 0px;")
|
|
self.toolbar_search.setContentsMargins(0, 0, 0, 0)
|
|
|
|
label_pre_search = QLabel()
|
|
label_pre_search.setStyleSheet("background: white; border-top-left-radius: 5px; border-bottom-left-radius: 5px;")
|
|
self.toolbar_search.addWidget(label_pre_search)
|
|
|
|
self.input_search = QLineEdit()
|
|
self.input_search.setMaxLength(20)
|
|
self.input_search.setFrame(False)
|
|
self.input_search.setPlaceholderText(self.locale_keys['window_manage.input_search.placeholder'] + "...")
|
|
self.input_search.setToolTip(self.locale_keys['window_manage.input_search.tooltip'])
|
|
self.input_search.setStyleSheet("QLineEdit { background-color: white; color: gray; spacing: 0;}")
|
|
self.input_search.returnPressed.connect(self.search)
|
|
self.toolbar_search.addWidget(self.input_search)
|
|
|
|
label_pos_search = QLabel()
|
|
label_pos_search.setPixmap(QPixmap(resource.get_path('img/search.svg')))
|
|
label_pos_search.setStyleSheet("background: white; padding-right: 10px; border-top-right-radius: 5px; border-bottom-right-radius: 5px;")
|
|
self.toolbar_search.addWidget(label_pos_search)
|
|
|
|
self.ref_toolbar_search = self.toolbar_top.addWidget(self.toolbar_search)
|
|
self.toolbar_top.addWidget(self._new_spacer())
|
|
self.layout.addWidget(self.toolbar_top)
|
|
|
|
toolbar = QToolBar()
|
|
|
|
self.checkbox_updates = QCheckBox()
|
|
self.checkbox_updates.setText(self.locale_keys['updates'].capitalize())
|
|
self.checkbox_updates.stateChanged.connect(self._handle_updates_filter)
|
|
self.ref_checkbox_updates = toolbar.addWidget(self.checkbox_updates)
|
|
|
|
self.checkbox_only_apps = QCheckBox()
|
|
self.checkbox_only_apps.setText(self.locale_keys['manage_window.checkbox.only_apps'])
|
|
self.checkbox_only_apps.setChecked(True)
|
|
self.checkbox_only_apps.stateChanged.connect(self._handle_filter_only_apps)
|
|
self.ref_checkbox_only_apps = toolbar.addWidget(self.checkbox_only_apps)
|
|
|
|
self.extra_filters = QWidget()
|
|
self.extra_filters.setLayout(QHBoxLayout())
|
|
toolbar.addWidget(self.extra_filters)
|
|
|
|
toolbar.addWidget(self._new_spacer())
|
|
|
|
self.bt_refresh = QToolButton()
|
|
self.bt_refresh.setToolTip(locale_keys['manage_window.bt.refresh.tooltip'])
|
|
self.bt_refresh.setIcon(QIcon(resource.get_path('img/refresh.svg')))
|
|
self.bt_refresh.clicked.connect(lambda: self.refresh_apps(keep_console=False))
|
|
toolbar.addWidget(self.bt_refresh)
|
|
|
|
self.bt_upgrade = QToolButton()
|
|
self.bt_upgrade.setToolTip(locale_keys['manage_window.bt.upgrade.tooltip'])
|
|
self.bt_upgrade.setIcon(QIcon(resource.get_path('img/update_green.svg')))
|
|
self.bt_upgrade.setEnabled(False)
|
|
self.bt_upgrade.clicked.connect(self.update_selected)
|
|
self.ref_bt_upgrade = toolbar.addWidget(self.bt_upgrade)
|
|
|
|
self.layout.addWidget(toolbar)
|
|
|
|
self.table_apps = AppsTable(self, self.icon_cache, disk_cache=self.disk_cache, download_icons=self.download_icons)
|
|
self.table_apps.change_headers_policy()
|
|
|
|
self.layout.addWidget(self.table_apps)
|
|
|
|
toolbar_console = QToolBar()
|
|
|
|
self.checkbox_console = QCheckBox()
|
|
self.checkbox_console.setText(self.locale_keys['manage_window.checkbox.show_details'])
|
|
self.checkbox_console.stateChanged.connect(self._handle_console)
|
|
self.checkbox_console.setVisible(False)
|
|
self.ref_checkbox_console = toolbar_console.addWidget(self.checkbox_console)
|
|
|
|
toolbar_console.addWidget(self._new_spacer())
|
|
self.layout.addWidget(toolbar_console)
|
|
|
|
self.textarea_output = QPlainTextEdit(self)
|
|
self.textarea_output.resize(self.table_apps.size())
|
|
self.textarea_output.setStyleSheet("background: black; color: white;")
|
|
self.layout.addWidget(self.textarea_output)
|
|
self.textarea_output.setVisible(False)
|
|
self.textarea_output.setReadOnly(True)
|
|
|
|
self.thread_update = self._bind_async_action(UpdateSelectedApps(self.manager, self.locale_keys), finished_call=self._finish_update_selected)
|
|
self.thread_refresh = self._bind_async_action(RefreshApps(self.manager), finished_call=self._finish_refresh_apps, only_finished=True)
|
|
self.thread_uninstall = self._bind_async_action(UninstallApp(self.manager, self.icon_cache), finished_call=self._finish_uninstall)
|
|
self.thread_get_info = self._bind_async_action(GetAppInfo(self.manager), finished_call=self._finish_get_info)
|
|
self.thread_get_history = self._bind_async_action(GetAppHistory(self.manager, self.locale_keys), finished_call=self._finish_get_history)
|
|
self.thread_search = self._bind_async_action(SearchApps(self.manager), finished_call=self._finish_search, only_finished=True)
|
|
self.thread_downgrade = self._bind_async_action(DowngradeApp(self.manager, self.locale_keys), finished_call=self._finish_downgrade)
|
|
self.thread_refresh_app = self._bind_async_action(RefreshApp(manager=self.manager), finished_call=self._finish_refresh)
|
|
self.thread_suggestions = self._bind_async_action(FindSuggestions(man=self.manager), finished_call=self._finish_search, only_finished=True)
|
|
|
|
self.thread_install = InstallApp(manager=self.manager, disk_cache=self.disk_cache, icon_cache=self.icon_cache, locale_keys=self.locale_keys)
|
|
self._bind_async_action(self.thread_install, finished_call=self._finish_install)
|
|
|
|
self.thread_animate_progress = AnimateProgress()
|
|
self.thread_animate_progress.signal_change.connect(self._update_progress)
|
|
|
|
self.thread_verify_models = VerifyModels()
|
|
self.thread_verify_models.signal_updates.connect(self._notify_model_data_change)
|
|
|
|
self.toolbar_bottom = QToolBar()
|
|
self.toolbar_bottom.setIconSize(QSize(16, 16))
|
|
|
|
self.label_updates = QLabel()
|
|
self.ref_label_updates = self.toolbar_bottom.addWidget(self.label_updates)
|
|
|
|
self.toolbar_bottom.addWidget(self._new_spacer())
|
|
|
|
self.progress_bar = QProgressBar()
|
|
self.progress_bar.setTextVisible(False)
|
|
self.ref_progress_bar = self.toolbar_bottom.addWidget(self.progress_bar)
|
|
|
|
self.toolbar_bottom.addWidget(self._new_spacer())
|
|
|
|
bt_about = QToolButton()
|
|
bt_about.setStyleSheet('QToolButton { border: 0px; }')
|
|
bt_about.setIcon(QIcon(resource.get_path('img/about.svg')))
|
|
bt_about.clicked.connect(self._show_about)
|
|
bt_about.setToolTip(self.locale_keys['manage_window.bt_about.tooltip'])
|
|
self.ref_bt_about = self.toolbar_bottom.addWidget(bt_about)
|
|
|
|
self.layout.addWidget(self.toolbar_bottom)
|
|
|
|
self.centralize()
|
|
|
|
self.filter_only_apps = True
|
|
self.filter_types = set()
|
|
self.filter_updates = False
|
|
self._maximized = False
|
|
|
|
self.dialog_about = None
|
|
self.first_refresh = suggestions
|
|
|
|
self.thread_warnings = ListWarnings(man=manager, locale_keys=locale_keys)
|
|
self.thread_warnings.signal_warnings.connect(self._show_warnings)
|
|
|
|
def _bind_async_action(self, action: AsyncAction, finished_call, only_finished: bool = False) -> AsyncAction:
|
|
action.signal_finished.connect(finished_call)
|
|
|
|
if not only_finished:
|
|
action.signal_confirmation.connect(self._ask_confirmation)
|
|
action.signal_output.connect(self._update_action_output)
|
|
action.signal_error.connect(self._show_error)
|
|
action.signal_status.connect(self._change_label_status)
|
|
self.signal_user_res.connect(action.confirm)
|
|
|
|
return action
|
|
|
|
def _ask_confirmation(self, msg: dict):
|
|
res = dialog.ask_confirmation(msg['title'], msg['body'], self.locale_keys)
|
|
self.signal_user_res.emit({'proceed': res, 'options': {}})
|
|
|
|
def _show_error(self, msg: dict):
|
|
dialog.show_error(title=msg['title'], body=msg['body'])
|
|
|
|
def _show_warnings(self, warnings: List[str]):
|
|
if warnings:
|
|
for warning in warnings:
|
|
dialog.show_warning(title=self.locale_keys['warning'].capitalize(), body=warning)
|
|
|
|
def show(self):
|
|
super(ManageWindow, self).show()
|
|
if not self.thread_warnings.isFinished():
|
|
self.thread_warnings.start()
|
|
|
|
def _show_about(self):
|
|
if self.dialog_about is None:
|
|
self.dialog_about = AboutDialog(self.locale_keys)
|
|
|
|
self.dialog_about.show()
|
|
|
|
def _handle_updates_filter(self, status: int):
|
|
self.filter_updates = status == 2
|
|
self.apply_filters()
|
|
|
|
def _handle_filter_only_apps(self, status: int):
|
|
self.filter_only_apps = status == 2
|
|
self.apply_filters()
|
|
|
|
def _handle_type_filter(self, status: int, app_type: str):
|
|
|
|
if status == 2:
|
|
self.filter_types.add(app_type)
|
|
elif app_type in self.filter_types:
|
|
self.filter_types.remove(app_type)
|
|
|
|
self.apply_filters()
|
|
|
|
def _notify_model_data_change(self):
|
|
self.table_apps.fill_async_data()
|
|
|
|
def _new_spacer(self):
|
|
spacer = QWidget()
|
|
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
return spacer
|
|
|
|
def changeEvent(self, e: QEvent):
|
|
if isinstance(e, QWindowStateChangeEvent):
|
|
self._maximized = self.isMaximized()
|
|
policy = QHeaderView.Stretch if self._maximized else QHeaderView.ResizeToContents
|
|
self.table_apps.change_headers_policy(policy)
|
|
|
|
def closeEvent(self, event):
|
|
|
|
if self.tray_icon:
|
|
event.ignore()
|
|
self.hide()
|
|
self._handle_console_option(False)
|
|
|
|
def _handle_console(self, checked: bool):
|
|
|
|
if checked:
|
|
self.textarea_output.show()
|
|
else:
|
|
self.textarea_output.hide()
|
|
|
|
def _handle_console_option(self, enable: bool):
|
|
|
|
if enable:
|
|
self.textarea_output.clear()
|
|
|
|
self.ref_checkbox_console.setVisible(enable)
|
|
self.checkbox_console.setChecked(False)
|
|
self.textarea_output.hide()
|
|
|
|
def refresh_apps(self, keep_console: bool = True):
|
|
self.filter_types.clear()
|
|
self.input_search.clear()
|
|
|
|
if not keep_console:
|
|
self._handle_console_option(False)
|
|
|
|
self.ref_checkbox_updates.setVisible(False)
|
|
self.ref_checkbox_only_apps.setVisible(False)
|
|
self._begin_action(self.locale_keys['manage_window.status.refreshing'], clear_filters=True)
|
|
self.thread_refresh.start()
|
|
|
|
def _finish_refresh_apps(self, apps: List[Application]):
|
|
self.finish_action()
|
|
self.ref_checkbox_only_apps.setVisible(True)
|
|
self.ref_bt_upgrade.setVisible(True)
|
|
self.update_apps(apps)
|
|
self.first_refresh = False
|
|
|
|
def uninstall_app(self, app: ApplicationView):
|
|
pwd = None
|
|
requires_root = self.manager.requires_root('uninstall', app.model)
|
|
|
|
if not is_root() and requires_root:
|
|
pwd, ok = ask_root_password(self.locale_keys)
|
|
|
|
if not ok:
|
|
return
|
|
|
|
self._handle_console_option(True)
|
|
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.uninstalling'], app.model.base_data.name))
|
|
|
|
self.thread_uninstall.app = app
|
|
self.thread_uninstall.root_password = pwd
|
|
self.thread_uninstall.start()
|
|
|
|
def refresh(self, app: ApplicationView):
|
|
pwd = None
|
|
requires_root = self.manager.requires_root('refresh', app.model)
|
|
|
|
if not is_root() and requires_root:
|
|
pwd, ok = ask_root_password(self.locale_keys)
|
|
|
|
if not ok:
|
|
return
|
|
|
|
self._handle_console_option(True)
|
|
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.refreshing_app'], app.model.base_data.name))
|
|
|
|
self.thread_refresh_app.app = app
|
|
self.thread_refresh_app.root_password = pwd
|
|
self.thread_refresh_app.start()
|
|
|
|
def _finish_uninstall(self, app: ApplicationView):
|
|
self.finish_action()
|
|
|
|
if app:
|
|
if self._can_notify_user():
|
|
util.notify_user('{} ({}) {}'.format(app.model.base_data.name, app.model.get_type(), self.locale_keys['uninstalled']))
|
|
|
|
self.refresh_apps()
|
|
else:
|
|
if self._can_notify_user():
|
|
util.notify_user('{}: {}'.format(app.model.base_data.name, self.locale_keys['notification.uninstall.failed']))
|
|
|
|
self.checkbox_console.setChecked(True)
|
|
|
|
def _can_notify_user(self):
|
|
return self.isHidden() or self.isMinimized()
|
|
|
|
def _finish_downgrade(self, success: bool):
|
|
self.finish_action()
|
|
|
|
if success:
|
|
if self._can_notify_user():
|
|
app = self.table_apps.get_selected_app()
|
|
util.notify_user('{} ({}) {}'.format(app.model.base_data.name, app.model.get_type(), self.locale_keys['downgraded']))
|
|
|
|
self.refresh_apps()
|
|
|
|
if self.tray_icon:
|
|
self.tray_icon.verify_updates(notify_user=False)
|
|
else:
|
|
if self._can_notify_user():
|
|
util.notify_user(self.locale_keys['notification.downgrade.failed'])
|
|
|
|
self.checkbox_console.setChecked(True)
|
|
|
|
def _finish_refresh(self, success: bool):
|
|
self.finish_action()
|
|
|
|
if success:
|
|
self.refresh_apps()
|
|
else:
|
|
self.checkbox_console.setChecked(True)
|
|
|
|
def _change_label_status(self, status: str):
|
|
self.label_status.setText(status)
|
|
|
|
def apply_filters(self):
|
|
if self.apps:
|
|
visible_apps = len(self.apps)
|
|
for idx, app_v in enumerate(self.apps):
|
|
hidden = self.filter_only_apps and app_v.model.is_library()
|
|
|
|
if not hidden and self.filter_types is not None:
|
|
hidden = app_v.model.get_type() not in self.filter_types
|
|
|
|
if not hidden and self.filter_updates:
|
|
hidden = not app_v.model.update
|
|
|
|
self.table_apps.setRowHidden(idx, hidden)
|
|
app_v.visible = not hidden
|
|
visible_apps -= 1 if hidden else 0
|
|
|
|
self.change_update_state(change_filters=False)
|
|
|
|
if not self._maximized:
|
|
self.table_apps.change_headers_policy(QHeaderView.Stretch)
|
|
self.table_apps.change_headers_policy()
|
|
self.resize_and_center(accept_lower_width=visible_apps > 0)
|
|
|
|
def change_update_state(self, change_filters: bool = True):
|
|
enable_bt_update = False
|
|
app_updates, library_updates, not_installed = 0, 0, 0
|
|
|
|
for app_v in self.apps:
|
|
if app_v.model.update:
|
|
if app_v.model.is_library():
|
|
library_updates += 1
|
|
else:
|
|
app_updates += 1
|
|
|
|
if not app_v.model.installed:
|
|
not_installed += 1
|
|
|
|
for app_v in self.apps:
|
|
if not_installed == 0 and app_v.visible and app_v.update_checked:
|
|
enable_bt_update = True
|
|
break
|
|
|
|
self.bt_upgrade.setEnabled(enable_bt_update)
|
|
|
|
total_updates = app_updates + library_updates
|
|
|
|
if total_updates > 0:
|
|
self.label_updates.setPixmap(QPixmap(resource.get_path('img/exclamation.svg')).scaled(16, 16, Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
|
self.label_updates.setToolTip('{}: {} ( {} {} | {} {} )'.format(self.locale_keys['manage_window.label.updates'],
|
|
total_updates,
|
|
app_updates,
|
|
self.locale_keys['manage_window.checkbox.only_apps'].lower(),
|
|
library_updates,
|
|
self.locale_keys['others'].lower()))
|
|
|
|
if not_installed == 0:
|
|
if not self.ref_checkbox_updates.isVisible():
|
|
self.ref_checkbox_updates.setVisible(True)
|
|
|
|
if change_filters and not self.checkbox_updates.isChecked():
|
|
self.checkbox_updates.setChecked(True)
|
|
|
|
if change_filters and library_updates > 0 and self.checkbox_only_apps.isChecked():
|
|
self.checkbox_only_apps.setChecked(False)
|
|
else:
|
|
self.checkbox_updates.setChecked(False)
|
|
self.ref_checkbox_updates.setVisible(False)
|
|
self.label_updates.setPixmap(QPixmap())
|
|
|
|
def centralize(self):
|
|
geo = self.frameGeometry()
|
|
screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
|
|
center_point = QApplication.desktop().screenGeometry(screen).center()
|
|
geo.moveCenter(center_point)
|
|
self.move(geo.topLeft())
|
|
|
|
def update_apps(self, apps: List[Application], update_check_enabled: bool = True):
|
|
self.apps = []
|
|
|
|
napps = 0 # number of apps (not libraries)
|
|
available_types = set()
|
|
|
|
if apps:
|
|
for app in apps:
|
|
app_model = ApplicationView(model=app, visible=(not app.is_library()) or not self.checkbox_only_apps.isChecked())
|
|
available_types.add(app.get_type())
|
|
napps += 1 if not app.is_library() else 0
|
|
self.apps.append(app_model)
|
|
|
|
if napps == 0:
|
|
|
|
if self.first_refresh:
|
|
self._begin_search('')
|
|
self.thread_suggestions.start()
|
|
return
|
|
else:
|
|
self.checkbox_only_apps.setChecked(False)
|
|
self.checkbox_only_apps.setCheckable(False)
|
|
else:
|
|
self.checkbox_only_apps.setCheckable(True)
|
|
self.checkbox_only_apps.setChecked(True)
|
|
|
|
self._update_type_filters(available_types)
|
|
self.table_apps.update_apps(self.apps, update_check_enabled=update_check_enabled)
|
|
self.apply_filters()
|
|
self.change_update_state()
|
|
self.resize_and_center()
|
|
|
|
self.thread_verify_models.apps = self.apps
|
|
self.thread_verify_models.start()
|
|
|
|
def _update_type_filters(self, available_types: Set[str]):
|
|
|
|
self.filter_types = available_types
|
|
|
|
filters_layout = self.extra_filters.layout()
|
|
for i in reversed(range(filters_layout.count())):
|
|
filters_layout.itemAt(i).widget().setParent(None)
|
|
|
|
if available_types:
|
|
for app_type in sorted(list(available_types)):
|
|
checkbox_app_type = QCheckBox()
|
|
checkbox_app_type.setChecked(True)
|
|
checkbox_app_type.setText(app_type.capitalize())
|
|
|
|
def handle_click(status: int, filter_type: str = app_type):
|
|
self._handle_type_filter(status, filter_type)
|
|
|
|
checkbox_app_type.stateChanged.connect(handle_click)
|
|
filters_layout.addWidget(checkbox_app_type)
|
|
|
|
def resize_and_center(self, accept_lower_width: bool = True):
|
|
new_width = reduce(operator.add, [self.table_apps.columnWidth(i) for i in range(len(self.table_apps.column_names))]) * 1.05
|
|
|
|
if accept_lower_width or new_width > self.width():
|
|
self.resize(new_width, self.height())
|
|
|
|
self.centralize()
|
|
|
|
def update_selected(self):
|
|
if self.apps:
|
|
requires_root = False
|
|
|
|
to_update = []
|
|
|
|
for app_v in self.apps:
|
|
if app_v.visible and app_v.update_checked:
|
|
to_update.append(app_v)
|
|
|
|
if self.manager.requires_root('update', app_v.model):
|
|
requires_root = True
|
|
|
|
if to_update and dialog.ask_confirmation(title=self.locale_keys['manage_window.upgrade_all.popup.title'],
|
|
body=self.locale_keys['manage_window.upgrade_all.popup.body'],
|
|
locale_keys=self.locale_keys):
|
|
pwd = None
|
|
|
|
if not is_root() and requires_root:
|
|
pwd, ok = ask_root_password(self.locale_keys)
|
|
|
|
if not ok:
|
|
return
|
|
|
|
self._handle_console_option(True)
|
|
self._begin_action(self.locale_keys['manage_window.status.upgrading'])
|
|
self.thread_update.apps_to_update = to_update
|
|
self.thread_update.root_password = pwd
|
|
self.thread_update.start()
|
|
|
|
def _finish_update_selected(self, res: dict):
|
|
self.finish_action()
|
|
|
|
if res['success']:
|
|
if self._can_notify_user():
|
|
util.notify_user('{} {}'.format(res['updated'], self.locale_keys['notification.update_selected.success']))
|
|
|
|
self.refresh_apps()
|
|
|
|
if self.tray_icon:
|
|
self.tray_icon.verify_updates()
|
|
else:
|
|
if self._can_notify_user():
|
|
util.notify_user(self.locale_keys['notification.update_selected.failed'])
|
|
|
|
self.bt_upgrade.setEnabled(True)
|
|
self.checkbox_console.setChecked(True)
|
|
|
|
def _update_action_output(self, output: str):
|
|
self.textarea_output.appendPlainText(output)
|
|
|
|
def _begin_action(self, action_label: str, keep_search: bool = False, clear_filters: bool = False):
|
|
self.ref_bt_about.setVisible(False)
|
|
self.ref_label_updates.setVisible(False)
|
|
self.thread_animate_progress.stop = False
|
|
self.thread_animate_progress.start()
|
|
self.ref_progress_bar.setVisible(True)
|
|
|
|
self.label_status.setText(action_label + "...")
|
|
self.bt_upgrade.setEnabled(False)
|
|
self.bt_refresh.setEnabled(False)
|
|
self.checkbox_only_apps.setEnabled(False)
|
|
self.table_apps.setEnabled(False)
|
|
self.checkbox_updates.setEnabled(False)
|
|
|
|
if keep_search:
|
|
self.ref_toolbar_search.setVisible(True)
|
|
else:
|
|
self.ref_toolbar_search.setVisible(False)
|
|
|
|
if clear_filters:
|
|
self._update_type_filters(set())
|
|
else:
|
|
self.extra_filters.setEnabled(False)
|
|
|
|
def finish_action(self):
|
|
self.ref_bt_about.setVisible(True)
|
|
self.ref_progress_bar.setVisible(False)
|
|
self.ref_label_updates.setVisible(True)
|
|
self.thread_animate_progress.stop = True
|
|
self.progress_bar.setValue(0)
|
|
self.bt_refresh.setEnabled(True)
|
|
self.checkbox_only_apps.setEnabled(True)
|
|
self.table_apps.setEnabled(True)
|
|
self.input_search.setEnabled(True)
|
|
self.label_status.setText('')
|
|
self.ref_toolbar_search.setVisible(True)
|
|
self.ref_toolbar_search.setEnabled(True)
|
|
self.extra_filters.setEnabled(True)
|
|
self.checkbox_updates.setEnabled(True)
|
|
|
|
def downgrade_app(self, app: ApplicationView):
|
|
pwd = None
|
|
requires_root = self.manager.requires_root('downgrade', app.model)
|
|
|
|
if not is_root() and requires_root:
|
|
pwd, ok = ask_root_password(self.locale_keys)
|
|
|
|
if not ok:
|
|
return
|
|
|
|
self._handle_console_option(True)
|
|
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.downgrading'], app.model.base_data.name))
|
|
|
|
self.thread_downgrade.app = app
|
|
self.thread_downgrade.root_password = pwd
|
|
self.thread_downgrade.start()
|
|
|
|
def get_app_info(self, app: dict):
|
|
self._handle_console_option(False)
|
|
self._begin_action(self.locale_keys['manage_window.status.info'])
|
|
|
|
self.thread_get_info.app = app
|
|
self.thread_get_info.start()
|
|
|
|
def get_app_history(self, app: dict):
|
|
self._handle_console_option(False)
|
|
self._begin_action(self.locale_keys['manage_window.status.history'])
|
|
|
|
self.thread_get_history.app = app
|
|
self.thread_get_history.start()
|
|
|
|
def _finish_get_info(self, app_info: dict):
|
|
self.finish_action()
|
|
self.change_update_state(change_filters=False)
|
|
dialog_info = InfoDialog(app=app_info, icon_cache=self.icon_cache, locale_keys=self.locale_keys, screen_size=self.screen_size)
|
|
dialog_info.exec_()
|
|
|
|
def _finish_get_history(self, res: dict):
|
|
self.finish_action()
|
|
self.change_update_state(change_filters=False)
|
|
|
|
if res.get('error'):
|
|
self._handle_console_option(True)
|
|
self.textarea_output.appendPlainText(res['error'])
|
|
self.checkbox_console.setChecked(True)
|
|
else:
|
|
dialog_history = HistoryDialog(res['history'], self.icon_cache, self.locale_keys)
|
|
dialog_history.exec_()
|
|
|
|
def _begin_search(self, word):
|
|
self._handle_console_option(False)
|
|
self.ref_checkbox_only_apps.setVisible(False)
|
|
self.ref_checkbox_updates.setVisible(False)
|
|
self.filter_updates = False
|
|
self._begin_action('{}{}'.format(self.locale_keys['manage_window.status.searching'], '"{}"'.format(word) if word else ''), clear_filters=True)
|
|
|
|
def search(self):
|
|
|
|
word = self.input_search.text().strip()
|
|
|
|
if word:
|
|
self._begin_search(word)
|
|
self.thread_search.word = word
|
|
self.thread_search.start()
|
|
|
|
def _finish_search(self, apps_found: List[Application]):
|
|
self.finish_action()
|
|
self.ref_bt_upgrade.setVisible(False)
|
|
self.update_apps(apps_found, update_check_enabled=False)
|
|
|
|
def install_app(self, app: ApplicationView):
|
|
pwd = None
|
|
requires_root = self.manager.requires_root('install', app.model)
|
|
|
|
if not is_root() and requires_root:
|
|
pwd, ok = ask_root_password(self.locale_keys)
|
|
|
|
if not ok:
|
|
return
|
|
|
|
self._handle_console_option(True)
|
|
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.installing'], app.model.base_data.name))
|
|
|
|
self.thread_install.app = app
|
|
self.thread_install.root_password = pwd
|
|
self.thread_install.start()
|
|
|
|
def _finish_install(self, app: ApplicationView):
|
|
self.input_search.setText('')
|
|
self.finish_action()
|
|
|
|
if app:
|
|
if self._can_notify_user():
|
|
util.notify_user(msg='{} ({}) {}'.format(app.model.base_data.name, app.model.get_type(), self.locale_keys['installed']))
|
|
|
|
self.refresh_apps()
|
|
else:
|
|
if self._can_notify_user():
|
|
util.notify_user('{}: {}'.format(app.model.base_data.name, self.locale_keys['notification.install.failed']))
|
|
|
|
self.checkbox_console.setChecked(True)
|
|
|
|
def _update_progress(self, value: int):
|
|
self.progress_bar.setValue(value)
|