mirror of https://github.com/borgbase/vorta
Run actions on multiple archives. By @diivi (#1723)
This commit is contained in:
parent
ec1dfcd803
commit
157ac373a9
|
@ -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>
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue