Run actions on multiple archives. By @diivi (#1723)

This commit is contained in:
Divyansh Singh 2023-07-05 15:58:09 +05:30 committed by GitHub
parent ec1dfcd803
commit 157ac373a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 28 deletions

View File

@ -209,10 +209,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Refresh selected archive</string> <string>Recalculate selected archive's size(s)</string>
</property> </property>
<property name="text"> <property name="text">
<string>Refresh</string> <string>Recalculate</string>
</property> </property>
<property name="toolButtonStyle"> <property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum> <enum>Qt::ToolButtonTextBesideIcon</enum>

View File

@ -79,11 +79,15 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
self.app = app self.app = app
self.toolBox.setCurrentIndex(0) self.toolBox.setCurrentIndex(0)
self.repoactions_enabled = True 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 #: Tooltip dict to save the tooltips set in the designer
self.tooltip_dict: Dict[QWidget, str] = {} self.tooltip_dict: Dict[QWidget, str] = {}
self.tooltip_dict[self.bDiff] = self.bDiff.toolTip() self.tooltip_dict[self.bDiff] = self.bDiff.toolTip()
self.tooltip_dict[self.bDelete] = self.bDelete.toolTip() self.tooltip_dict[self.bDelete] = self.bDelete.toolTip()
self.tooltip_dict[self.bRefreshArchive] = self.bRefreshArchive.toolTip()
self.tooltip_dict[self.compactButton] = self.compactButton.toolTip() self.tooltip_dict[self.compactButton] = self.compactButton.toolTip()
header = self.archiveTable.horizontalHeader() header = self.archiveTable.horizontalHeader()
@ -320,7 +324,8 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
self.archiveTable.scrollToItem(item) self.archiveTable.scrollToItem(item)
self.archiveTable.selectionModel().clearSelection() self.archiveTable.selectionModel().clearSelection()
self._toggle_all_buttons(enabled=True) if self.remaining_refresh_archives == 0:
self._toggle_all_buttons(enabled=True)
else: else:
self.mount_points = {} self.mount_points = {}
self.archiveTable.setRowCount(0) self.archiveTable.setRowCount(0)
@ -355,6 +360,10 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
# handle selection of more than 2 rows # handle selection of more than 2 rows
selectionModel: QItemSelectionModel = self.archiveTable.selectionModel() selectionModel: QItemSelectionModel = self.archiveTable.selectionModel()
indexes = selectionModel.selectedRows() 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 # Toggle archive actions frame
layout: QLayout = self.fArchiveActions.layout() layout: QLayout = self.fArchiveActions.layout()
@ -364,14 +373,15 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
if not self.repoactions_enabled: if not self.repoactions_enabled:
reason = self.tr("(borg already running)") 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: if self.repoactions_enabled and len(indexes) > 0:
self.bDelete.setEnabled(True) for button in multi_archive_action_buttons:
self.bDelete.setToolTip(self.tooltip_dict.get(self.bDelete, "")) button.setEnabled(True)
button.setToolTip(self.tooltip_dict.get(button, ""))
else: else:
self.bDelete.setEnabled(False) for button in multi_archive_action_buttons:
tooltip = self.tooltip_dict[self.bDelete] button.setEnabled(False)
self.bDelete.setToolTip(tooltip + " " + reason or self.tr("(Select minimum one archive)")) button.setToolTip(self.tooltip_dict.get(button, "") + " " + self.tr("(Select minimum one archive)"))
# Toggle diff button # Toggle diff button
if self.repoactions_enabled and len(indexes) == 2: if self.repoactions_enabled and len(indexes) == 2:
@ -387,7 +397,8 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
if self.repoactions_enabled and len(indexes) == 1: if self.repoactions_enabled and len(indexes) == 1:
# Enable archive actions # Enable archive actions
self.fArchiveActions.setEnabled(True) for widget in single_archive_action_buttons:
widget.setEnabled(True)
for index in range(layout.count()): for index in range(layout.count()):
widget = layout.itemAt(index).widget() widget = layout.itemAt(index).widget()
@ -399,14 +410,11 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
reason = reason or self.tr("(Select exactly one archive)") reason = reason or self.tr("(Select exactly one archive)")
# too few or too many selected. # too few or too many selected.
self.fArchiveActions.setEnabled(False) for widget in single_archive_action_buttons:
for index in range(layout.count()):
widget = layout.itemAt(index).widget()
tooltip = widget.toolTip() tooltip = widget.toolTip()
tooltip = self.tooltip_dict.setdefault(widget, tooltip) tooltip = self.tooltip_dict.setdefault(widget, tooltip)
widget.setToolTip(tooltip + " " + reason) widget.setToolTip(tooltip + " " + reason)
widget.setEnabled(False)
# special treatment for dynamic mount/unmount button. # special treatment for dynamic mount/unmount button.
self.bmountarchive_refresh() self.bmountarchive_refresh()
@ -522,20 +530,31 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
self.populate_from_profile() self.populate_from_profile()
def refresh_archive_info(self): def refresh_archive_info(self):
archive_name = self.selected_archive_name() selected_archives = self.archiveTable.selectionModel().selectedRows()
if archive_name is not None:
params = BorgInfoArchiveJob.prepare(self.profile(), archive_name) archive_names = []
if params['ok']: for index in selected_archives:
job = BorgInfoArchiveJob(params['cmd'], params, self.profile().repo.id) archive_names.append(self.archiveTable.item(index.row(), 4).text())
job.updated.connect(self._set_status)
job.result.connect(self.info_result) self.remaining_refresh_archives = len(archive_names) # number of archives to refresh
self._toggle_all_buttons(False) self._toggle_all_buttons(False)
self.app.jobs_manager.add_job(job) 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.app.jobs_manager.add_job(job)
else:
self._set_status(params['message'])
return
def info_result(self, result): def info_result(self, result):
self._toggle_all_buttons(True) self.remaining_refresh_archives -= 1
if result['returncode'] == 0: if result['returncode'] == 0 and self.remaining_refresh_archives == 0:
self._set_status(self.tr('Refreshed archive.')) self._toggle_all_buttons(True)
self._set_status(self.tr('Refreshed archives.'))
self.populate_from_profile() self.populate_from_profile()
def selected_archive_name(self): def selected_archive_name(self):

View File

@ -275,7 +275,9 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.repoTab.init_repo_stats() self.repoTab.init_repo_stats()
self.scheduleTab.populate_logs() 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 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._toggle_buttons(create_enabled=True)
self.archiveTab._toggle_all_buttons(enabled=True) self.archiveTab._toggle_all_buttons(enabled=True)