From 44d70f5efddb56e5608c28fa68382b08ad3ba0ad Mon Sep 17 00:00:00 2001 From: Vinicius Moreira Date: Thu, 4 Jun 2020 12:16:53 -0300 Subject: [PATCH] [feature] new custom action to open the system backup tool --- CHANGELOG.md | 5 +++++ bauh/view/core/controller.py | 25 ++++++++++++++++++++++ bauh/view/qt/window.py | 14 +++++++++++- bauh/view/resources/locale/ca | 2 ++ bauh/view/resources/locale/de | 2 ++ bauh/view/resources/locale/en | 2 ++ bauh/view/resources/locale/es | 2 ++ bauh/view/resources/locale/it | 2 ++ bauh/view/resources/locale/pt | 2 ++ bauh/view/resources/locale/ru | 2 ++ bauh/view/resources/locale/tr | 2 ++ pictures/releases/0.9.5/backup_action.png | Bin 0 -> 10209 bytes 12 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pictures/releases/0.9.5/backup_action.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c916e5..dffcd08d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [0.9.5] 2020 +### Features +- new custom action (**+**) to open the system backups (snapshots). It is just a shortcut to Timeshift. +

+ +

### Improvements - Arch diff --git a/bauh/view/core/controller.py b/bauh/view/core/controller.py index be908ca8..f89dbdca 100755 --- a/bauh/view/core/controller.py +++ b/bauh/view/core/controller.py @@ -2,6 +2,7 @@ import re import re import time import traceback +from subprocess import Popen, PIPE, STDOUT from threading import Thread from typing import List, Set, Type, Tuple, Dict @@ -15,6 +16,7 @@ from bauh.api.abstract.view import ViewComponent, TabGroupComponent from bauh.api.exception import NoInternetException from bauh.commons import internet from bauh.commons.html import bold +from bauh.commons.system import run_cmd from bauh.view.core.settings import GenericSettingsManager from bauh.view.core.update import check_for_update from bauh.view.util import resource @@ -57,12 +59,30 @@ class GenericSoftwareManager(SoftwareManager): icon_path=resource.get_path('img/logo.svg'), requires_root=False, refresh=False)] + self.dynamic_extra_actions = {CustomSoftwareAction(i18_label_key='action.backups', + i18n_status_key='action.backups.status', + manager_method='launch_timeshift', + manager=self, + icon_path='timeshift', + requires_root=False, + refresh=False): self._is_timeshift_launcher_available} + + def _is_timeshift_launcher_available(self) -> bool: + return bool(run_cmd('which timeshift-launcher', print_error=False)) def reset_cache(self): if self._available_cache is not None: self._available_cache = {} self.working_managers.clear() + def launch_timeshift(self, root_password: str, watcher: ProcessWatcher): + try: + Popen(['timeshift-launcher'], stderr=STDOUT) + return True + except: + traceback.print_exc() + return False + def _sort(self, apps: List[SoftwarePackage], word: str) -> List[SoftwarePackage]: exact_name_matches, contains_name_matches, others = [], [], [] @@ -526,7 +546,12 @@ class GenericSoftwareManager(SoftwareManager): if man_actions: actions.extend(man_actions) + for action, available in self.dynamic_extra_actions.items(): + if available(): + actions.append(action) + actions.extend(self.extra_actions) + return actions def _fill_sizes(self, man: SoftwareManager, pkgs: List[SoftwarePackage]): diff --git a/bauh/view/qt/window.py b/bauh/view/qt/window.py index fa19e78a..f6248ed5 100755 --- a/bauh/view/qt/window.py +++ b/bauh/view/qt/window.py @@ -1252,7 +1252,19 @@ class ManageWindow(QWidget): def _map_custom_action(self, action: CustomSoftwareAction) -> QAction: custom_action = QAction(self.i18n[action.i18_label_key]) - custom_action.setIcon(QIcon(action.icon_path)) + + if action.icon_path: + try: + if action.icon_path.startswith('/'): + icon = QIcon(action.icon_path) + else: + icon = QIcon.fromTheme(action.icon_path) + + custom_action.setIcon(icon) + + except: + pass + custom_action.triggered.connect(lambda: self.execute_custom_action(None, action)) return custom_action diff --git a/bauh/view/resources/locale/ca b/bauh/view/resources/locale/ca index 36616464..1b61a70a 100644 --- a/bauh/view/resources/locale/ca +++ b/bauh/view/resources/locale/ca @@ -51,6 +51,8 @@ action.backup.invalid_mode=Invalid backup mode action.backup.msg=Do you want to generate a system copy before proceeding ? action.backup.substatus.create=Generating a new system backup action.backup.substatus.delete=Removing old system backups +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=l’usuari ha cancel·lat l’operació action.disk_trim=Optimizing disc ( TRIM ) action.disk_trim.error=There was a problem while optimizing the disk diff --git a/bauh/view/resources/locale/de b/bauh/view/resources/locale/de index 0c296604..ada44efb 100644 --- a/bauh/view/resources/locale/de +++ b/bauh/view/resources/locale/de @@ -51,6 +51,8 @@ action.backup.invalid_mode=Invalid backup mode action.backup.msg=Do you want to generate a system copy before proceeding ? action.backup.substatus.create=Generating a new system backup action.backup.substatus.delete=Removing old system backups +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=Aktion vom Nutzer abgebrochen action.disk_trim=Optimizing disc ( TRIM ) action.disk_trim.error=There was a problem while optimizing the disk diff --git a/bauh/view/resources/locale/en b/bauh/view/resources/locale/en index aadb6c83..cb471a1e 100644 --- a/bauh/view/resources/locale/en +++ b/bauh/view/resources/locale/en @@ -51,6 +51,8 @@ action.backup.invalid_mode=Invalid backup mode action.backup.msg=Do you want to generate a system copy before proceeding ? action.backup.substatus.create=Generating a new system backup action.backup.substatus.delete=Removing old system backups +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=operation cancelled by the user action.disk_trim.error=There was a problem while optimizing the disk action.disk_trim=Optimizing disc ( TRIM ) diff --git a/bauh/view/resources/locale/es b/bauh/view/resources/locale/es index 3ce963ca..c5e4eb5e 100644 --- a/bauh/view/resources/locale/es +++ b/bauh/view/resources/locale/es @@ -51,6 +51,8 @@ action.backup.invalid_mode=Modo de copia de seguridad inválido action.backup.msg=¿Desea generar una copia de seguridad del sistema antes de continuar? action.backup.substatus.create=Generando una nueva copia de seguridad action.backup.substatus.delete=Eliminando copias de seguridad antiguas +action.backups=Copias de seguridad +action.backups.status=Abriendo herramienta de copias de seguridad action.cancelled=operación cancelada por el usuario action.disk_trim=Optimizando el disco ( TRIM ) action.disk_trim.error=Hubo un problema al optimizar el disco diff --git a/bauh/view/resources/locale/it b/bauh/view/resources/locale/it index 410da3e6..b700cc30 100644 --- a/bauh/view/resources/locale/it +++ b/bauh/view/resources/locale/it @@ -51,6 +51,8 @@ action.backup.invalid_mode=Invalid backup mode action.backup.msg=Do you want to generate a system copy before proceeding ? action.backup.substatus.create=Generating a new system backup action.backup.substatus.delete=Removing old system backups +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=operazione annullata dall'utente action.disk_trim=Optimizing disc ( TRIM ) action.disk_trim.error=There was a problem while optimizing the disk diff --git a/bauh/view/resources/locale/pt b/bauh/view/resources/locale/pt index ac3a7c22..ee9c24a2 100644 --- a/bauh/view/resources/locale/pt +++ b/bauh/view/resources/locale/pt @@ -51,6 +51,8 @@ action.backup.invalid_mode=Modo de cópia de segurança inválido action.backup.msg=Você deseja gerar uma cópia de segurança do sistema antes de proceder ? action.backup.substatus.create=Gerando uma nova cópia de segurança action.backup.substatus.delete=Removendo cópias de segurança antigas +action.backups=Cópias de segurança +action.backups.status=Abrindo ferramenta de cópias de segurança action.cancelled=operação cancelada pelo usuário action.disk_trim.error=Ocorreu um problema ao otimizar o disco action.disk_trim=Otimizando disco ( TRIM ) diff --git a/bauh/view/resources/locale/ru b/bauh/view/resources/locale/ru index 12fb1584..d7206f4e 100644 --- a/bauh/view/resources/locale/ru +++ b/bauh/view/resources/locale/ru @@ -51,6 +51,8 @@ action.backup.invalid_mode=Invalid backup mode action.backup.msg=Do you want to generate a system copy before proceeding ? action.backup.substatus.create=Generating a new system backup action.backup.substatus.delete=Removing old system backups +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=Операция отменена пользователем action.disk_trim=Optimizing disc ( TRIM ) action.disk_trim.error=There was a problem while optimizing the disk diff --git a/bauh/view/resources/locale/tr b/bauh/view/resources/locale/tr index d75fc553..27523355 100644 --- a/bauh/view/resources/locale/tr +++ b/bauh/view/resources/locale/tr @@ -51,6 +51,8 @@ action.backup.invalid_mode=Geçersiz yedekleme modu action.backup.msg=Devam etmeden önce bir sistem kopyası oluşturmak istiyor musunuz? action.backup.substatus.create=Yeni bir sistem yedeklemesi oluştur action.backup.substatus.delete=Eski sistem yedeklemelerini kaldır +action.backups=Backups +action.backups.status=Opening backups tool action.cancelled=işlem kullanıcı tarafından iptal edildi action.disk_trim.error=Diski optimize ederken bir sorun oluştu action.disk_trim=Diski optimize etme ( TRIM ) diff --git a/pictures/releases/0.9.5/backup_action.png b/pictures/releases/0.9.5/backup_action.png new file mode 100644 index 0000000000000000000000000000000000000000..7d54436edf0d8f6abdf916ea56436e79931870d3 GIT binary patch literal 10209 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 N-bpG*l#3Yz{11dQxG4Yt literal 0 HcmV?d00001