|
13 | 13 | QLayout, |
14 | 14 | QMenu, |
15 | 15 | QMessageBox, |
| 16 | + QProgressDialog, |
16 | 17 | QStyledItemDelegate, |
17 | 18 | QTableView, |
18 | 19 | QTableWidgetItem, |
|
23 | 24 | from vorta.borg.compact import BorgCompactJob |
24 | 25 | from vorta.borg.delete import BorgDeleteJob |
25 | 26 | from vorta.borg.diff import BorgDiffJob |
| 27 | +from vorta.borg.extract import BorgExtractJob |
26 | 28 | from vorta.borg.info_archive import BorgInfoArchiveJob |
| 29 | +from vorta.borg.list_archive import BorgListArchiveJob |
27 | 30 | from vorta.borg.list_repo import BorgListRepoJob |
28 | 31 | from vorta.borg.prune import BorgPruneJob |
29 | 32 | from vorta.borg.rename import BorgRenameJob |
|
32 | 35 | from vorta.store.models import ArchiveModel, SettingsModel |
33 | 36 | from vorta.utils import ( |
34 | 37 | borg_compat, |
| 38 | + choose_file_dialog, |
35 | 39 | find_best_unit_for_sizes, |
36 | 40 | format_archive_name, |
37 | 41 | get_asset, |
38 | 42 | get_mount_points, |
39 | 43 | pretty_bytes, |
40 | 44 | ) |
41 | | -from vorta.views.archive.archive_extract import ArchiveExtract |
42 | 45 | from vorta.views.archive.archive_mount import ArchiveMount |
43 | 46 | from vorta.views.base_tab import BaseTab |
44 | 47 | from vorta.views.dialogs.archive import diff_result |
| 48 | +from vorta.views.dialogs.archive import extract as extract_dialog |
45 | 49 | from vorta.views.dialogs.archive.diff_result import DiffResultDialog, DiffTree |
| 50 | +from vorta.views.dialogs.archive.extract import ExtractDialog, ExtractTree |
46 | 51 | from vorta.views.source_tab import SizeItem |
47 | 52 | from vorta.views.utils import get_colored_icon |
48 | 53 |
|
@@ -83,7 +88,6 @@ def __init__(self, parent=None, app=None, profile_provider=None): |
83 | 88 | ) |
84 | 89 |
|
85 | 90 | self.archive_mount = ArchiveMount(self) |
86 | | - self.archive_extract = ArchiveExtract(self) |
87 | 91 |
|
88 | 92 | #: Tooltip dict to save the tooltips set in the designer |
89 | 93 | self.tooltip_dict: Dict[QWidget, str] = {} |
@@ -142,7 +146,7 @@ def __init__(self, parent=None, app=None, profile_provider=None): |
142 | 146 | self.bRefreshArchive.clicked.connect(self.refresh_archive_info) |
143 | 147 | self.bRename.clicked.connect(self.cell_double_clicked) |
144 | 148 | self.bDelete.clicked.connect(self.delete_action) |
145 | | - self.bExtract.clicked.connect(self.archive_extract.extract_action) |
| 149 | + self.bExtract.clicked.connect(self.extract_action) |
146 | 150 | self.compactButton.clicked.connect(self.compact_action) |
147 | 151 |
|
148 | 152 | # other signals |
@@ -212,7 +216,7 @@ def archiveitem_contextmenu(self, pos: QPoint): |
212 | 216 | (self.bRefreshArchive, self.refresh_archive_info), |
213 | 217 | (self.bDiff, self.diff_action), |
214 | 218 | (self.bMountArchive, self.archive_mount.bmountarchive_clicked), |
215 | | - (self.bExtract, self.archive_extract.extract_action), |
| 219 | + (self.bExtract, self.extract_action), |
216 | 220 | (self.bRename, self.cell_double_clicked), |
217 | 221 | (self.bDelete, self.delete_action), |
218 | 222 | ] |
@@ -487,7 +491,8 @@ def check_action(self): |
487 | 491 | archive_cell = self.archiveTable.item(row_selected[0].row(), 4) |
488 | 492 | if archive_cell: |
489 | 493 | archive_name = archive_cell.text() |
490 | | - params['cmd'][-1] += f'::{archive_name}' |
| 494 | + cmd: list = params['cmd'] # type: ignore[index] |
| 495 | + cmd[-1] += f'::{archive_name}' |
491 | 496 |
|
492 | 497 | job = BorgCheckJob(params['cmd'], params, self.profile().repo.id) |
493 | 498 | job.updated.connect(self._set_status) |
@@ -591,6 +596,85 @@ def save_prune_setting(self, new_value=None): |
591 | 596 | profile.prune_keep_within = self.prune_keep_within.text() |
592 | 597 | profile.save() |
593 | 598 |
|
| 599 | + def extract_action(self): |
| 600 | + """ |
| 601 | + Open a dialog for choosing what to extract from the selected archive. |
| 602 | + """ |
| 603 | + profile = self.profile() |
| 604 | + |
| 605 | + row_selected = self.archiveTable.selectionModel().selectedRows() |
| 606 | + if row_selected: |
| 607 | + archive_cell = self.archiveTable.item(row_selected[0].row(), 4) |
| 608 | + if archive_cell: |
| 609 | + archive_name = archive_cell.text() |
| 610 | + params = BorgListArchiveJob.prepare(profile, archive_name) |
| 611 | + |
| 612 | + if not params['ok']: |
| 613 | + self._set_status(params['message']) |
| 614 | + return |
| 615 | + self._set_status('') |
| 616 | + self._toggle_all_buttons(False) |
| 617 | + |
| 618 | + job = BorgListArchiveJob(params['cmd'], params, self.profile().repo.id) |
| 619 | + job.updated.connect(self.mountErrors.setText) |
| 620 | + job.result.connect(self.extract_list_result) |
| 621 | + self.app.jobs_manager.add_job(job) |
| 622 | + return job |
| 623 | + else: |
| 624 | + self._set_status(self.tr('Select an archive to restore first.')) |
| 625 | + |
| 626 | + def extract_list_result(self, result): |
| 627 | + """Process the contents of the archive to extract.""" |
| 628 | + self._set_status('') |
| 629 | + if result['returncode'] == 0: |
| 630 | + archive = ArchiveModel.get(name=result['params']['archive_name']) |
| 631 | + model = ExtractTree() |
| 632 | + |
| 633 | + progress = QProgressDialog(self.tr("Processing archive contents…"), None, 0, 0, self) |
| 634 | + progress.setWindowTitle(self.tr("Please wait")) |
| 635 | + progress.setWindowModality(Qt.WindowModality.WindowModal) |
| 636 | + progress.setMinimumDuration(0) |
| 637 | + progress.setValue(0) |
| 638 | + self._extract_progress = progress |
| 639 | + |
| 640 | + self._t = extract_dialog.ParseThread(result['data'], model) |
| 641 | + self._t.finished.connect(self._extract_progress.close) |
| 642 | + self._t.finished.connect(self._extract_progress.deleteLater) |
| 643 | + self._t.finished.connect(lambda: self.extract_show_dialog(archive, model)) |
| 644 | + self._t.start() |
| 645 | + |
| 646 | + def extract_show_dialog(self, archive, model): |
| 647 | + """Show the dialog for choosing the archive contents to extract.""" |
| 648 | + self._set_status('') |
| 649 | + |
| 650 | + def process_result(): |
| 651 | + def receive(): |
| 652 | + extraction_folder = dialog.selectedFiles() |
| 653 | + if extraction_folder: |
| 654 | + params = BorgExtractJob.prepare(self.profile(), archive.name, model, extraction_folder[0]) |
| 655 | + if params['ok']: |
| 656 | + self._toggle_all_buttons(False) |
| 657 | + job = BorgExtractJob(params['cmd'], params, self.profile().repo.id) |
| 658 | + job.updated.connect(self.mountErrors.setText) |
| 659 | + job.result.connect(self.extract_archive_result) |
| 660 | + self.app.jobs_manager.add_job(job) |
| 661 | + else: |
| 662 | + self._set_status(params['message']) |
| 663 | + |
| 664 | + dialog = choose_file_dialog(self, self.tr("Choose Extraction Point"), want_folder=True) |
| 665 | + dialog.open(receive) |
| 666 | + |
| 667 | + window = ExtractDialog(archive, model) |
| 668 | + self._toggle_all_buttons(True) |
| 669 | + window.setParent(self, QtCore.Qt.WindowType.Sheet) |
| 670 | + self._window = window # for testing |
| 671 | + window.show() |
| 672 | + window.accepted.connect(process_result) |
| 673 | + |
| 674 | + def extract_archive_result(self, result): |
| 675 | + """Finished extraction.""" |
| 676 | + self._toggle_all_buttons(True) |
| 677 | + |
594 | 678 | def cell_double_clicked(self, row=None, column=None): |
595 | 679 | if not self.bRename.isEnabled(): |
596 | 680 | return |
|
0 commit comments