From 24b5197884c435b03113b0164b758fdf4ff7be4d Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Fri, 2 Jun 2023 02:27:18 +0530 Subject: [PATCH 01/10] feat: refresh multiple archives --- src/vorta/views/archive_tab.py | 41 +++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index f5b92c8ee..44fc2fa41 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -333,9 +333,11 @@ def on_selection_change(self, selected=None, deselected=None): # toggle delete button if self.repoactions_enabled and len(indexes) > 0: self.bDelete.setEnabled(True) + self.bRefreshArchive.setEnabled(True) self.bDelete.setToolTip(self.tooltip_dict.get(self.bDelete, "")) else: self.bDelete.setEnabled(False) + self.bRefreshArchive.setEnabled(False) tooltip = self.tooltip_dict[self.bDelete] self.bDelete.setToolTip(tooltip + " " + reason or self.tr("(Select minimum one archive)")) @@ -365,14 +367,18 @@ def on_selection_change(self, selected=None, deselected=None): reason = reason or self.tr("(Select exactly one archive)") # too few or too many selected. - self.fArchiveActions.setEnabled(False) + self.bMountArchive.setEnabled(False) + self.bExtract.setEnabled(False) + self.bRename.setEnabled(False) for index in range(layout.count()): widget = layout.itemAt(index).widget() tooltip = widget.toolTip() tooltip = self.tooltip_dict.setdefault(widget, tooltip) - widget.setToolTip(tooltip + " " + reason) + + if 'Refresh' not in tooltip: + widget.setToolTip(tooltip + " " + reason) # special treatment for dynamic mount/unmount button. self.bmountarchive_refresh() @@ -488,15 +494,28 @@ def list_result(self, result): self.populate_from_profile() def refresh_archive_info(self): - archive_name = self.selected_archive_name() - if archive_name is not None: - params = BorgInfoArchiveJob.prepare(self.profile(), archive_name) - if params['ok']: - job = BorgInfoArchiveJob(params['cmd'], params, self.profile().repo.id) - job.updated.connect(self._set_status) - job.result.connect(self.info_result) - self._toggle_all_buttons(False) - self.app.jobs_manager.add_job(job) + selected_archives = self.archiveTable.selectionModel().selectedRows() + profile = self.profile() + + name_list = [] + for index in selected_archives: + name_list.append(self.archiveTable.item(index.row(), 4).text()) + + archive_list = ( + profile.repo.archives.select().where(ArchiveModel.name << name_list).order_by(ArchiveModel.time.desc()) + ) + + archive_names = [archive.name for archive in archive_list] + + for archive_name in archive_names: + if archive_name is not None: + params = BorgInfoArchiveJob.prepare(self.profile(), archive_name) + if params['ok']: + job = BorgInfoArchiveJob(params['cmd'], params, self.profile().repo.id) + job.updated.connect(self._set_status) + job.result.connect(self.info_result) + self._toggle_all_buttons(False) + self.app.jobs_manager.add_job(job) def info_result(self, result): self._toggle_all_buttons(True) From 888eaea7b53558b17edd7b7b6b5068abda6e38c5 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Fri, 2 Jun 2023 19:12:29 +0530 Subject: [PATCH 02/10] change conditional for brefresharchive check --- src/vorta/views/archive_tab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index 44fc2fa41..33793da72 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -377,7 +377,7 @@ def on_selection_change(self, selected=None, deselected=None): tooltip = self.tooltip_dict.setdefault(widget, tooltip) - if 'Refresh' not in tooltip: + if widget != self.bRefreshArchive: widget.setToolTip(tooltip + " " + reason) # special treatment for dynamic mount/unmount button. From 20a79c3737bd84786ac069b9f9f6153331beff17 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Fri, 9 Jun 2023 23:35:43 +0530 Subject: [PATCH 03/10] refactor --- src/vorta/views/archive_tab.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index 33793da72..c0aa8713b 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -330,7 +330,7 @@ def on_selection_change(self, selected=None, deselected=None): if not self.repoactions_enabled: reason = self.tr("(borg already running)") - # toggle delete button + # Disable the delete and refresh buttons if no archive is selected if self.repoactions_enabled and len(indexes) > 0: self.bDelete.setEnabled(True) self.bRefreshArchive.setEnabled(True) @@ -355,7 +355,8 @@ def on_selection_change(self, selected=None, deselected=None): if self.repoactions_enabled and len(indexes) == 1: # Enable archive actions - self.fArchiveActions.setEnabled(True) + for widget in [self.bMountArchive, self.bExtract, self.bRename]: + widget.setEnabled(True) for index in range(layout.count()): widget = layout.itemAt(index).widget() @@ -367,18 +368,11 @@ def on_selection_change(self, selected=None, deselected=None): reason = reason or self.tr("(Select exactly one archive)") # too few or too many selected. - self.bMountArchive.setEnabled(False) - self.bExtract.setEnabled(False) - self.bRename.setEnabled(False) - - for index in range(layout.count()): - widget = layout.itemAt(index).widget() + for widget in [self.bMountArchive, self.bExtract, self.bRename]: tooltip = widget.toolTip() - tooltip = self.tooltip_dict.setdefault(widget, tooltip) - - if widget != self.bRefreshArchive: - widget.setToolTip(tooltip + " " + reason) + widget.setToolTip(tooltip + " " + reason) + widget.setEnabled(False) # special treatment for dynamic mount/unmount button. self.bmountarchive_refresh() From dd0cbf2c0ef22fa891faa4fae2ce7a47e37d8e2f Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Sat, 10 Jun 2023 01:09:56 +0530 Subject: [PATCH 04/10] single archive action buttons --- src/vorta/views/archive_tab.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index c0aa8713b..b15bcfaa0 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -321,6 +321,8 @@ def on_selection_change(self, selected=None, deselected=None): # handle selection of more than 2 rows selectionModel: QItemSelectionModel = self.archiveTable.selectionModel() indexes = selectionModel.selectedRows() + # actions that are enabled only when a single archive is selected + single_archive_action_buttons = [self.bMountArchive, self.bExtract, self.bRename] # Toggle archive actions frame layout: QLayout = self.fArchiveActions.layout() @@ -355,7 +357,7 @@ def on_selection_change(self, selected=None, deselected=None): if self.repoactions_enabled and len(indexes) == 1: # Enable archive actions - for widget in [self.bMountArchive, self.bExtract, self.bRename]: + for widget in single_archive_action_buttons: widget.setEnabled(True) for index in range(layout.count()): @@ -368,7 +370,7 @@ def on_selection_change(self, selected=None, deselected=None): reason = reason or self.tr("(Select exactly one archive)") # too few or too many selected. - for widget in [self.bMountArchive, self.bExtract, self.bRename]: + for widget in single_archive_action_buttons: tooltip = widget.toolTip() tooltip = self.tooltip_dict.setdefault(widget, tooltip) widget.setToolTip(tooltip + " " + reason) From d1bd6f72b7360068f8ba8680e3d8ce55608fbc96 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Tue, 13 Jun 2023 01:08:48 +0530 Subject: [PATCH 05/10] group multi archive buttons --- src/vorta/views/archive_tab.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index b15bcfaa0..4f171872e 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -75,6 +75,7 @@ def __init__(self, parent=None, app=None): self.tooltip_dict: Dict[QWidget, str] = {} self.tooltip_dict[self.bDiff] = self.bDiff.toolTip() self.tooltip_dict[self.bDelete] = self.bDelete.toolTip() + self.tooltip_dict[self.bRefreshArchive] = self.bRefreshArchive.toolTip() header = self.archiveTable.horizontalHeader() header.setVisible(True) @@ -323,6 +324,8 @@ def on_selection_change(self, selected=None, deselected=None): indexes = selectionModel.selectedRows() # actions that are enabled only when a single archive is selected single_archive_action_buttons = [self.bMountArchive, self.bExtract, self.bRename] + # actions that are enabled when at least one archive is selected + multi_archive_action_buttons = [self.bDelete, self.bRefreshArchive] # Toggle archive actions frame layout: QLayout = self.fArchiveActions.layout() @@ -334,14 +337,13 @@ def on_selection_change(self, selected=None, deselected=None): # Disable the delete and refresh buttons if no archive is selected if self.repoactions_enabled and len(indexes) > 0: - self.bDelete.setEnabled(True) - self.bRefreshArchive.setEnabled(True) - self.bDelete.setToolTip(self.tooltip_dict.get(self.bDelete, "")) + for button in multi_archive_action_buttons: + button.setEnabled(True) + button.setToolTip(self.tooltip_dict.get(button, "")) else: - self.bDelete.setEnabled(False) - self.bRefreshArchive.setEnabled(False) - tooltip = self.tooltip_dict[self.bDelete] - self.bDelete.setToolTip(tooltip + " " + reason or self.tr("(Select minimum one archive)")) + for button in multi_archive_action_buttons: + button.setEnabled(False) + button.setToolTip(self.tooltip_dict.get(button, "") + " " + self.tr("(Select minimum one archive)")) # Toggle diff button if self.repoactions_enabled and len(indexes) == 2: From cecc66f09519998a4c690cdf7f7bb992488ae79f Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Thu, 15 Jun 2023 17:56:44 +0530 Subject: [PATCH 06/10] refactor and rename refresh to recalc --- src/vorta/assets/UI/archivetab.ui | 4 ++-- src/vorta/views/archive_tab.py | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/vorta/assets/UI/archivetab.ui b/src/vorta/assets/UI/archivetab.ui index 3e3b0b4c5..296b90d13 100644 --- a/src/vorta/assets/UI/archivetab.ui +++ b/src/vorta/assets/UI/archivetab.ui @@ -207,10 +207,10 @@ - Refresh selected archive + Recalculate selected archive's size(s) - Refresh + Recalculate Qt::ToolButtonTextBesideIcon diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index 4f171872e..7c5eec7cd 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -493,17 +493,10 @@ def list_result(self, result): def refresh_archive_info(self): selected_archives = self.archiveTable.selectionModel().selectedRows() - profile = self.profile() - name_list = [] + archive_names = [] for index in selected_archives: - name_list.append(self.archiveTable.item(index.row(), 4).text()) - - archive_list = ( - profile.repo.archives.select().where(ArchiveModel.name << name_list).order_by(ArchiveModel.time.desc()) - ) - - archive_names = [archive.name for archive in archive_list] + archive_names.append(self.archiveTable.item(index.row(), 4).text()) for archive_name in archive_names: if archive_name is not None: From 133216f49a300834e901b11dbc6c4e47a9162114 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Fri, 23 Jun 2023 23:42:44 +0530 Subject: [PATCH 07/10] set status on rename fail --- src/vorta/views/archive_tab.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index 7c5eec7cd..bddf317c1 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -507,6 +507,9 @@ def refresh_archive_info(self): job.result.connect(self.info_result) self._toggle_all_buttons(False) self.app.jobs_manager.add_job(job) + else: + self._set_status(params['message']) + return def info_result(self, result): self._toggle_all_buttons(True) From f2bd1a074c22764afc4318dae3ae1054a0b346c0 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Sun, 25 Jun 2023 20:12:52 +0530 Subject: [PATCH 08/10] enable buttons only when all archives are refreshed --- src/vorta/views/archive_tab.py | 16 +++++++++++----- src/vorta/views/main_window.py | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index bddf317c1..d94e5e024 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -70,6 +70,9 @@ def __init__(self, parent=None, app=None): self.app = app self.toolBox.setCurrentIndex(0) self.repoactions_enabled = True + self.remaining_refresh_archives = ( + 0 # number of archives that are left to refresh before action buttons are enabled again + ) #: Tooltip dict to save the tooltips set in the designer self.tooltip_dict: Dict[QWidget, str] = {} @@ -287,7 +290,8 @@ def populate_from_profile(self): self.archiveTable.scrollToItem(item) self.archiveTable.selectionModel().clearSelection() - self._toggle_all_buttons(enabled=True) + if self.remaining_refresh_archives == 0: + self._toggle_all_buttons(enabled=True) else: self.mount_points = {} self.archiveTable.setRowCount(0) @@ -498,6 +502,8 @@ def refresh_archive_info(self): for index in selected_archives: archive_names.append(self.archiveTable.item(index.row(), 4).text()) + self.remaining_refresh_archives = len(archive_names) # number of archives to refresh + self._toggle_all_buttons(False) for archive_name in archive_names: if archive_name is not None: params = BorgInfoArchiveJob.prepare(self.profile(), archive_name) @@ -505,16 +511,16 @@ def refresh_archive_info(self): job = BorgInfoArchiveJob(params['cmd'], params, self.profile().repo.id) job.updated.connect(self._set_status) job.result.connect(self.info_result) - self._toggle_all_buttons(False) self.app.jobs_manager.add_job(job) else: self._set_status(params['message']) return def info_result(self, result): - self._toggle_all_buttons(True) - if result['returncode'] == 0: - self._set_status(self.tr('Refreshed archive.')) + self.remaining_refresh_archives -= 1 + if result['returncode'] == 0 and self.remaining_refresh_archives == 0: + self._toggle_all_buttons(True) + self._set_status(self.tr('Refreshed archives.')) self.populate_from_profile() def selected_archive_name(self): diff --git a/src/vorta/views/main_window.py b/src/vorta/views/main_window.py index ca0c2426b..4d4ae8d01 100644 --- a/src/vorta/views/main_window.py +++ b/src/vorta/views/main_window.py @@ -274,7 +274,7 @@ def backup_finished_event(self): self.repoTab.init_repo_stats() self.scheduleTab.populate_logs() - if not self.app.jobs_manager.is_worker_running(): + if not self.app.jobs_manager.is_worker_running() and self.archiveTab.remaining_refresh_archives == 0: self._toggle_buttons(create_enabled=True) self.archiveTab._toggle_all_buttons(enabled=True) From 19f666eee6ca9714a826ce04833e7935fd8ba138 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Wed, 5 Jul 2023 08:52:08 +0530 Subject: [PATCH 09/10] re enable create button when refreshing is done --- src/vorta/views/main_window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vorta/views/main_window.py b/src/vorta/views/main_window.py index 31be593b0..80d3a0367 100644 --- a/src/vorta/views/main_window.py +++ b/src/vorta/views/main_window.py @@ -275,7 +275,7 @@ def backup_finished_event(self): self.repoTab.init_repo_stats() self.scheduleTab.populate_logs() - if not self.app.jobs_manager.is_worker_running() and self.archiveTab.remaining_refresh_archives == 0: + if not self.app.jobs_manager.is_worker_running() and self.archiveTab.remaining_refresh_archives == 1: self._toggle_buttons(create_enabled=True) self.archiveTab._toggle_all_buttons(enabled=True) From 8c3179e20e2bc054f1a7d9356a50453ae7a1a120 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Wed, 5 Jul 2023 09:49:52 +0530 Subject: [PATCH 10/10] fix tests --- src/vorta/views/main_window.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vorta/views/main_window.py b/src/vorta/views/main_window.py index 80d3a0367..3da134f46 100644 --- a/src/vorta/views/main_window.py +++ b/src/vorta/views/main_window.py @@ -275,7 +275,9 @@ def backup_finished_event(self): self.repoTab.init_repo_stats() self.scheduleTab.populate_logs() - if not self.app.jobs_manager.is_worker_running() and self.archiveTab.remaining_refresh_archives == 1: + if not self.app.jobs_manager.is_worker_running() and ( + self.archiveTab.remaining_refresh_archives == 0 or self.archiveTab.remaining_refresh_archives == 1 + ): # Either the refresh is done or this is the last archive to refresh. self._toggle_buttons(create_enabled=True) self.archiveTab._toggle_all_buttons(enabled=True)