From 65214b8e737910833a68d4c602462a472d822358 Mon Sep 17 00:00:00 2001 From: Manu Date: Thu, 22 Nov 2018 18:25:22 +0800 Subject: [PATCH] Add extraction dialog and code to test table performance. See #26. WIP --- src/vorta/assets/UI/archivetab.ui | 4 +- src/vorta/assets/UI/extractdialog.ui | 10 ++- src/vorta/views/archive_tab.py | 9 ++- src/vorta/views/extract_dialog.py | 94 ++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 src/vorta/views/extract_dialog.py diff --git a/src/vorta/assets/UI/archivetab.ui b/src/vorta/assets/UI/archivetab.ui index 41c1fb4e..3b4c46a6 100644 --- a/src/vorta/assets/UI/archivetab.ui +++ b/src/vorta/assets/UI/archivetab.ui @@ -245,9 +245,9 @@ - + - false + true Extract diff --git a/src/vorta/assets/UI/extractdialog.ui b/src/vorta/assets/UI/extractdialog.ui index 26776c7b..755e4724 100644 --- a/src/vorta/assets/UI/extractdialog.ui +++ b/src/vorta/assets/UI/extractdialog.ui @@ -63,7 +63,13 @@ - + + + + 1 + + + @@ -91,7 +97,7 @@ - + Extract diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index d9790d63..d78bcaab 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -1,6 +1,6 @@ import sys from datetime import timedelta -from PyQt5 import uic +from PyQt5 import uic, QtCore from PyQt5.QtCore import QSize from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QTableWidgetItem, QTableView, QHeaderView, QComboBox, QToolButton, QButtonGroup, QToolBar @@ -10,6 +10,7 @@ from vorta.borg.list import BorgListThread from vorta.borg.check import BorgCheckThread from vorta.borg.mount import BorgMountThread from vorta.borg.umount import BorgUmountThread +from vorta.views.extract_dialog import ExtractDialog from vorta.utils import get_asset, pretty_bytes, choose_folder_dialog from vorta.models import BackupProfileMixin, ArchiveModel @@ -49,6 +50,7 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin): self.listButton.clicked.connect(self.list_action) self.pruneButton.clicked.connect(self.prune_action) self.checkButton.clicked.connect(self.check_action) + self.extractButton.clicked.connect(self.extract_action) self.populate_from_profile() @@ -203,3 +205,8 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin): for i in self.prune_intervals: setattr(profile, f'prune_{i}', getattr(self, f'prune_{i}').value()) profile.save() + + def extract_action(self): + window = ExtractDialog() + window.setParent(self, QtCore.Qt.Sheet) + window.show() diff --git a/src/vorta/views/extract_dialog.py b/src/vorta/views/extract_dialog.py new file mode 100644 index 00000000..a1e69701 --- /dev/null +++ b/src/vorta/views/extract_dialog.py @@ -0,0 +1,94 @@ +import os +from PyQt5 import uic +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QApplication, QTreeWidgetItem, QHeaderView + +from paramiko.rsakey import RSAKey +from paramiko.ecdsakey import ECDSAKey +from paramiko.ed25519key import Ed25519Key + +from ..utils import get_asset + +uifile = get_asset('UI/extractdialog.ui') +ExtractDialogUI, ExtractDialogBase = uic.loadUiType(uifile) +n = 0 + +class ExtractDialog(ExtractDialogBase, ExtractDialogUI): + def __init__(self): + super().__init__() + self.setupUi(self) + + d = {'key1': 'value1', + 'key2': ['value2', 'value', 'value4'], + 'key5': {'another key1': 'another value1', + 'another key2': ['value2', 'value', 'value4']} + } + + # add some nested folders + for i in range(6, 200): + d[f'folder-{i}'] = {'another key1': 'another value1', + 'another key2': ['value2', 'value', 'value4']} + for j in range(50): + d[f'folder-{i}'][f'large folder {j}'] = {'another key1': 'another value1', + 'another key2': ['value2', 'value', 'value4']} + + # add top-level folders to test scroll performance + for f in range(1000000): + d[f'flat folder {f}'] = 'no subfolders. test' + + self.d = d + + t = self.fileTree + t.setColumnCount(2) + t.setHeaderLabels(['File/Foldername', 'Size', 'Modified']) + t.setAlternatingRowColors(True) + t.setUniformRowHeights(True) # Allows for scrolling optimizations. + header = t.header() + header.setStretchLastSection(False) + header.setSectionResizeMode(1, QHeaderView.ResizeToContents) + header.setSectionResizeMode(2, QHeaderView.ResizeToContents) + header.setSectionResizeMode(0, QHeaderView.Stretch) + + self.extractButton.clicked.connect(self.build_tree) + + def build_tree(self): + fill_item(self.fileTree.invisibleRootItem(), self.d) + print('Added test items', n) + +def fill_item(item, value): + global n + # item.setExpanded(True) + if type(value) is dict: + for key, val in sorted(value.items()): + child = QTreeWidgetItem() + child.setText(0, str(key)) + child.setText(1, str(key)) + child.setText(2, str(key)) + child.setFlags(child.flags() | Qt.ItemIsUserCheckable) + child.setCheckState(0, Qt.Unchecked) + item.addChild(child) + n+=1 + fill_item(child, val) + elif type(value) is list: + for val in value: + child = QTreeWidgetItem() + child.setFlags(child.flags() | Qt.ItemIsUserCheckable) + child.setCheckState(0, Qt.Unchecked) + item.addChild(child) + n+=1 + if type(val) is dict: + child.setText(0, '[dict]') + fill_item(child, val) + elif type(val) is list: + child.setText(0, '[list]') + fill_item(child, val) + else: + child.setText(0, str(val)) + else: + child = QTreeWidgetItem() + child.setText(0, str(value)) + child.setFlags(child.flags() | Qt.ItemIsUserCheckable) + child.setCheckState(0, Qt.Unchecked) + item.addChild(child) + n+=1 +