From 1b072fc3558f715775850e1199ed176a5b7a206d Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 5 Sep 2020 21:59:44 +0200
Subject: [PATCH 01/64] add function to get path info async
---
src/vorta/utils.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index d13f67ee3..875b6f800 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -17,6 +17,7 @@
from paramiko.ed25519key import Ed25519Key
from paramiko.rsakey import RSAKey
from PyQt5 import QtCore
+from PyQt5.QtCore import QFileInfo, QDir, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from vorta.borg._compatibility import BorgCompatibility
@@ -34,6 +35,53 @@
borg_compat = BorgCompatibility()
+class FilePathInfoAsync(QThread):
+ signal = pyqtSignal(str,int,int)
+ def __init__(self,path):
+ self.path = path
+ QThread.__init__(self)
+ self.exiting = False
+
+ def run(self):
+ logger.info("running thread to get path=%s...",self.path)
+ self.filecount = 0
+ self.size, self.filecount=get_path_datasize(self.path)
+ self.sleep(5)
+ self.signal.emit(self.path,self.size,self.filecount)
+
+
+def get_directory_size(dirPath):
+ dataSize = 0
+ qDir=QDir(dirPath)
+ qDir.setFilter(QDir.AllEntries | QDir.Hidden | QDir.System | QDir.NoDotAndDotDot)
+ filescount=qDir.count()
+ logger.info("file in dir=%u",filescount)
+
+
+ for fileInfo in qDir.entryInfoList():
+ if fileInfo.isDir():
+ logger.info("foldername %s",fileInfo.absoluteFilePath())
+ dataSize, ftmp = get_directory_size(fileInfo.absoluteFilePath())
+ filescount += ftmp
+ else:
+ logger.info("filename %s size=%u",fileInfo.absoluteFilePath(),fileInfo.size())
+ dataSize += fileInfo.size()
+
+ return dataSize, filescount
+
+def get_path_datasize(path):
+ fileInfo = QFileInfo(path)
+ folderSize=0
+
+ if fileInfo.isDir():
+ folderSize, filescount = get_directory_size(fileInfo.absoluteFilePath())
+ logger.info("path (folder) %s %u elements size now=%u (%s)",fileInfo.absoluteFilePath(),filescount,folderSize,pretty_bytes(folderSize))
+ else:
+ logger.info("path (file) %s size=%u",fileInfo.path(),fileInfo.size())
+ folderSize = fileInfo.size()
+ filescount = 1
+
+ return folderSize, filescount
def nested_dict():
"""
From 13fd1a26b41855cee63b916ed8ea2349f89ef9f1 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 5 Sep 2020 22:00:43 +0200
Subject: [PATCH 02/64] change sourcelist to QTableWidget
---
src/vorta/assets/UI/sourcetab.ui | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index e17d13cd0..271677ca3 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -24,7 +24,10 @@
-
-
-
+
+
+ true
+
0
@@ -37,12 +40,33 @@
0
+
+ QAbstractItemView::NoEditTriggers
+
QAbstractItemView::ExtendedSelection
-
- true
+
+ QAbstractItemView::SelectRows
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ true
+
-
From 9ec1b20ede4d84188cb0c0aff78474fd8f8a7d2f Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 5 Sep 2020 22:07:44 +0200
Subject: [PATCH 03/64] update for new source control
---
src/vorta/views/source_tab.py | 46 +++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 5 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 305931995..e8396ce98 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,7 +1,7 @@
from PyQt5 import uic
from ..models import SourceFileModel, BackupProfileMixin
-from ..utils import get_asset, choose_file_dialog
-from PyQt5.QtWidgets import QApplication, QMessageBox
+from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
+from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
import os
uifile = get_asset('UI/sourcetab.ui')
@@ -9,9 +9,26 @@
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
+ updateThreads = []
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
+
+ headerTxt=["Path","Type","Size","Folder/\nFiles Count"]
+
+ self.sourceFilesWidget.setColumnCount(len(headerTxt))
+ header = self.sourceFilesWidget.horizontalHeader()
+
+ header.setVisible(True)
+ header.setSortIndicatorShown(1)
+
+ header.setSectionResizeMode(0, QHeaderView.Stretch)
+ header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
+
+ self.sourceFilesWidget.setHorizontalHeaderLabels(headerTxt)
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
@@ -20,17 +37,36 @@ def __init__(self, parent=None):
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
+
+ def set_path_info(self,path,datasize,filecount):
+ items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
+ for item in items:
+ self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(datasize))
+ self.sourceFilesWidget.item(item.row(),3).setText(format(filecount))
+
+ def add_source_to_table(self,path):
+ indexRow = self.sourceFilesWidget.rowCount()
+ self.sourceFilesWidget.insertRow(indexRow)
+ itemPath = QTableWidgetItem(path)
+ self.sourceFilesWidget.setItem(indexRow,0,itemPath)
+ self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem("DIR"))
+ self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("load..."))
+ getDir = FilePathInfoAsync(path)
+ getDir.signal.connect(self.set_path_info)
+ self.updateThreads.append(getDir)
+ getDir.start()
def populate_from_profile(self):
profile = self.profile()
self.excludePatternsField.textChanged.disconnect()
self.excludeIfPresentField.textChanged.disconnect()
- self.sourceFilesWidget.clear()
+ self.sourceFilesWidget.clearContents()
self.excludePatternsField.clear()
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.sourceFilesWidget.addItem(source.dir)
+ self.add_source_to_table(source.dir)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
@@ -43,7 +79,7 @@ def receive():
for dir in dirs:
new_source, created = SourceFileModel.get_or_create(dir=dir, profile=self.profile())
if created:
- self.sourceFilesWidget.addItem(dir)
+ self.add_source_to_table(dir)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
From 768278008ec3e8b86187edf5f2401f646bfadfe7 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 5 Sep 2020 22:14:10 +0200
Subject: [PATCH 04/64] Update source_tab.py
---
src/vorta/views/source_tab.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index e8396ce98..eb596c04f 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,6 +1,7 @@
from PyQt5 import uic
from ..models import SourceFileModel, BackupProfileMixin
from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
+from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
import os
From dc5001ef0d9cfd7d6033033ad0aa713a574336e3 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 6 Sep 2020 20:13:30 +0000
Subject: [PATCH 05/64] add more attributes for paths in source list
Not working yet, requires a new DB version I guess.
Would appreciate any help in this regard
---
src/vorta/models.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 0d04b4845..762a5b464 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -106,6 +106,9 @@ class Meta:
class SourceFileModel(pw.Model):
"""A folder to be backed up, related to a Backup Configuration."""
dir = pw.CharField()
+ dirSize = pw.IntegerField()
+ dirFilesCount = pw.IntegerField()
+ dirType = pw.BooleanField()
profile = pw.ForeignKeyField(BackupProfileModel, default=1)
added_at = pw.DateTimeField(default=datetime.utcnow)
From 6974a8cb8ee3e95931edc649a8092efb5da7a876 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 6 Sep 2020 20:30:37 +0000
Subject: [PATCH 06/64] add missing code for DB update
---
src/vorta/models.py | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 762a5b464..5f7d02a09 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -16,7 +16,7 @@
from vorta.i18n import trans_late
from vorta.utils import slugify
-SCHEMA_VERSION = 15
+SCHEMA_VERSION = 16
db = pw.Proxy()
@@ -106,9 +106,9 @@ class Meta:
class SourceFileModel(pw.Model):
"""A folder to be backed up, related to a Backup Configuration."""
dir = pw.CharField()
- dirSize = pw.IntegerField()
- dirFilesCount = pw.IntegerField()
- dirType = pw.BooleanField()
+ dir_size = pw.IntegerField()
+ dir_files_count = pw.IntegerField()
+ dir_type_isdir = pw.BooleanField()
profile = pw.ForeignKeyField(BackupProfileModel, default=1)
added_at = pw.DateTimeField(default=datetime.utcnow)
@@ -365,6 +365,17 @@ def init_db(con=None):
'dont_run_on_metered_networks', pw.BooleanField(default=True))
)
+ if current_schema.version < 16:
+ _apply_schema_update(
+ current_schema, 16,
+ migrator.add_column(SourceFileModel._meta.table_name,
+ 'dir_size', pw.IntegerField(default = 0)),
+ migrator.add_column(SourceFileModel._meta.table_name,
+ 'dir_files_count', pw.IntegerField(default = 0)),
+ migrator.add_column(SourceFileModel._meta.table_name,
+ 'dir_type_isdir', pw.BooleanField(default = False))
+ )
+
# Create missing settings and update labels. Leave setting values untouched.
for setting in get_misc_settings():
s, created = SettingsModel.get_or_create(key=setting['key'], defaults=setting)
From 9e5e62601c27428f2b767507caac70c59b63d201 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 7 Sep 2020 14:24:31 +0000
Subject: [PATCH 07/64] updated source entry data
---
src/vorta/models.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 5f7d02a09..3444abbcb 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -106,9 +106,9 @@ class Meta:
class SourceFileModel(pw.Model):
"""A folder to be backed up, related to a Backup Configuration."""
dir = pw.CharField()
- dir_size = pw.IntegerField()
- dir_files_count = pw.IntegerField()
- dir_type_isdir = pw.BooleanField()
+ dir_size = pw.BigIntegerField()
+ dir_files_count = pw.BigIntegerField()
+ path_isdir = pw.BooleanField()
profile = pw.ForeignKeyField(BackupProfileModel, default=1)
added_at = pw.DateTimeField(default=datetime.utcnow)
@@ -369,11 +369,11 @@ def init_db(con=None):
_apply_schema_update(
current_schema, 16,
migrator.add_column(SourceFileModel._meta.table_name,
- 'dir_size', pw.IntegerField(default = 0)),
+ 'dir_size', pw.BigIntegerField(default = -1)),
migrator.add_column(SourceFileModel._meta.table_name,
- 'dir_files_count', pw.IntegerField(default = 0)),
+ 'dir_files_count', pw.BigIntegerField(default = -1)),
migrator.add_column(SourceFileModel._meta.table_name,
- 'dir_type_isdir', pw.BooleanField(default = False))
+ 'path_isdir', pw.BooleanField(default = False))
)
# Create missing settings and update labels. Leave setting values untouched.
From 1e28b9109281f67bdf685e968601d97f6c0f3324 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 7 Sep 2020 14:25:35 +0000
Subject: [PATCH 08/64] updated function for getting a folders size
Use native unix commands
---
src/vorta/utils.py | 58 ++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 875b6f800..c2ee8fe42 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -7,6 +7,7 @@
import re
import sys
import unicodedata
+import subprocess
from collections import defaultdict
from datetime import datetime as dt
from functools import reduce
@@ -44,44 +45,41 @@ def __init__(self,path):
def run(self):
logger.info("running thread to get path=%s...",self.path)
- self.filecount = 0
- self.size, self.filecount=get_path_datasize(self.path)
+ self.files_count = 0
+ self.size, self.files_count = get_path_datasize(self.path)
self.sleep(5)
- self.signal.emit(self.path,self.size,self.filecount)
-
+ self.signal.emit(self.path,self.size,self.files_count)
def get_directory_size(dirPath):
- dataSize = 0
- qDir=QDir(dirPath)
- qDir.setFilter(QDir.AllEntries | QDir.Hidden | QDir.System | QDir.NoDotAndDotDot)
- filescount=qDir.count()
- logger.info("file in dir=%u",filescount)
-
-
- for fileInfo in qDir.entryInfoList():
- if fileInfo.isDir():
- logger.info("foldername %s",fileInfo.absoluteFilePath())
- dataSize, ftmp = get_directory_size(fileInfo.absoluteFilePath())
- filescount += ftmp
- else:
- logger.info("filename %s size=%u",fileInfo.absoluteFilePath(),fileInfo.size())
- dataSize += fileInfo.size()
-
- return dataSize, filescount
+ res = subprocess.run('find . | wc -l', cwd=dirPath, shell=True, check=False,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+
+ files_count = int(res.stdout.split(b'\t')[0])
+
+ if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
+ res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+ data_size = int(res.stdout.split(b'\t')[0])
+ else:
+ data_size = 0
+ files_count = 0
+
+ return data_size, files_count
+
def get_path_datasize(path):
- fileInfo = QFileInfo(path)
- folderSize=0
+ file_info = QFileInfo(path)
+ data_size = 0
- if fileInfo.isDir():
- folderSize, filescount = get_directory_size(fileInfo.absoluteFilePath())
- logger.info("path (folder) %s %u elements size now=%u (%s)",fileInfo.absoluteFilePath(),filescount,folderSize,pretty_bytes(folderSize))
+ if file_info.isDir():
+ data_size, files_count = get_directory_size(file_info.absoluteFilePath())
+ logger.info("path (folder) %s %u elements size now=%u (%s)",file_info.absoluteFilePath(),files_count,data_size,pretty_bytes(data_size))
else:
- logger.info("path (file) %s size=%u",fileInfo.path(),fileInfo.size())
- folderSize = fileInfo.size()
- filescount = 1
+ logger.info("path (file) %s size=%u",file_info.path(),file_info.size())
+ data_size = file_info.size()
+ files_count = 1
- return folderSize, filescount
+ return data_size, files_count
def nested_dict():
"""
From fef831fe5c04d7f9e6adc4610088cefd5d321849 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 7 Sep 2020 14:27:09 +0000
Subject: [PATCH 09/64] Improved add/remove functionality
It should now work to add items to the source list, and deleting them aswell.
Size & files count is calculated once when added, and stored in database then
---
src/vorta/views/source_tab.py | 63 +++++++++++++++++++++++------------
1 file changed, 42 insertions(+), 21 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index eb596c04f..655eb3706 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -2,6 +2,7 @@
from ..models import SourceFileModel, BackupProfileMixin
from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
from PyQt5 import QtCore
+from PyQt5.QtCore import QFileInfo
from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
import os
@@ -16,7 +17,7 @@ def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
- headerTxt=["Path","Type","Size","Folder/\nFiles Count"]
+ headerTxt=["Path","Type","Size","Elements Count"]
self.sourceFilesWidget.setColumnCount(len(headerTxt))
header = self.sourceFilesWidget.horizontalHeader()
@@ -39,24 +40,40 @@ def __init__(self, parent=None):
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
- def set_path_info(self,path,datasize,filecount):
+ def set_path_info(self,path,data_size,files_count):
items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
for item in items:
- self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(datasize))
- self.sourceFilesWidget.item(item.row(),3).setText(format(filecount))
-
- def add_source_to_table(self,path):
+ self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(),3).setText(format(files_count))
+ db_item = SourceFileModel.get(dir=path)
+ db_item.dir_size = data_size
+ db_item.dir_files_count = files_count
+ db_item.save()
+
+
+ def add_source_to_table(self,source,update_data):
indexRow = self.sourceFilesWidget.rowCount()
self.sourceFilesWidget.insertRow(indexRow)
- itemPath = QTableWidgetItem(path)
+ itemPath = QTableWidgetItem(source.dir)
self.sourceFilesWidget.setItem(indexRow,0,itemPath)
- self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem("DIR"))
- self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("load..."))
- getDir = FilePathInfoAsync(path)
- getDir.signal.connect(self.set_path_info)
- self.updateThreads.append(getDir)
- getDir.start()
+ if source.path_isdir == True:
+ self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem(""))
+ else:
+ self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem(""))
+ if update_data == True:
+ self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("load..."))
+ getDir = FilePathInfoAsync(source.dir)
+ getDir.signal.connect(self.set_path_info)
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ getDir.start()
+ else: # Use cached data from DB
+ if source.dir_size < 0:
+ self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("N/A"))
+ else:
+ self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
@@ -67,7 +84,7 @@ def populate_from_profile(self):
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source.dir)
+ self.add_source_to_table(source,False)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
@@ -78,9 +95,13 @@ def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir, profile=self.profile())
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=QFileInfo(dir).isDir(),
+ profile=self.profile())
if created:
- self.add_source_to_table(dir)
+ self.add_source_to_table(new_source,True)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
@@ -88,14 +109,14 @@ def receive():
dialog.open(receive)
def source_remove(self):
- indexes = self.sourceFilesWidget.selectionModel().selectedIndexes()
+ indexes = self.sourceFilesWidget.selectionModel().selectedRows()
# sort indexes, starting with lowest
indexes.sort()
- # remove each selected entry, starting with highest index (otherways, higher indexes become invalid)
+ # remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- item = self.sourceFilesWidget.takeItem(index.row())
- db_item = SourceFileModel.get(dir=item.text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(),0).text())
db_item.delete_instance()
+ self.sourceFilesWidget.removeRow(index.row())
def save_exclude_patterns(self):
profile = self.profile()
From c4a9a6d79e3bbcbc426dfa572b344950d28ee592 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Thu, 10 Sep 2020 19:04:37 +0000
Subject: [PATCH 10/64] update properties
---
src/vorta/assets/UI/sourcetab.ui | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 271677ca3..87b38d0b1 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -62,10 +62,10 @@
false
- true
+ false
- true
+ false
From 8d5923b09e0285b14d41ce3a114960b50b6fe09a Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Thu, 10 Sep 2020 19:25:00 +0000
Subject: [PATCH 11/64] Add new option in misc ui
Option is to enable/disable calculating source folder size when added to the list
---
src/vorta/models.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 3444abbcb..d78298ebb 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -218,6 +218,11 @@ def get_misc_settings():
'label': trans_late('settings',
'Open main window on startup')
},
+ {
+ 'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
+ 'label': trans_late('settings',
+ 'Get Size of Source path when added')
+ },
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
'label': 'Previously selected profile'
From acf444e60a7d59398442af91fd9ae86e8b2c5845 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Thu, 10 Sep 2020 19:26:11 +0000
Subject: [PATCH 12/64] Check if new added source's size should be updated
---
src/vorta/views/source_tab.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 655eb3706..20b85c8fb 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,5 +1,5 @@
from PyQt5 import uic
-from ..models import SourceFileModel, BackupProfileMixin
+from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo
@@ -101,7 +101,7 @@ def receive():
path_isdir=QFileInfo(dir).isDir(),
profile=self.profile())
if created:
- self.add_source_to_table(new_source,True)
+ self.add_source_to_table(new_source,SettingsModel.get(key="get_srcpath_datasize").value)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
From 8a810971431f7fbf43caa84541b0d23d46082f63 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Thu, 10 Sep 2020 19:40:25 +0000
Subject: [PATCH 13/64] variable name cleanup
---
src/vorta/utils.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 228f33ed8..6dd0e134e 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -47,14 +47,14 @@ def run(self):
self.sleep(5)
self.signal.emit(self.path,self.size,self.files_count)
-def get_directory_size(dirPath):
- res = subprocess.run('find . | wc -l', cwd=dirPath, shell=True, check=False,
+def get_directory_size(path):
+ res = subprocess.run('find . | wc -l', cwd=path, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
files_count = int(res.stdout.split(b'\t')[0])
if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
+ res = subprocess.run('du -sb .', cwd=path, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
data_size = int(res.stdout.split(b'\t')[0])
else:
From 34f23c97c9ae7d0fa382b90fdfbc1e56dd18a54c Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 26 Sep 2020 20:10:41 +0000
Subject: [PATCH 14/64] Add "Update sources" button
---
src/vorta/assets/UI/sourcetab.ui | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 87b38d0b1..2b8d88603 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -95,13 +95,20 @@
- -
+
-
Remove
+ -
+
+
+ Update Sources
+
+
+
From 00d91f72ddeb8b308786794ff192409f4a579428 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 26 Sep 2020 20:11:45 +0000
Subject: [PATCH 15/64] remove debug stuff
---
src/vorta/utils.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 6dd0e134e..99885eee8 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -41,10 +41,8 @@ def __init__(self,path):
self.exiting = False
def run(self):
- logger.info("running thread to get path=%s...",self.path)
self.files_count = 0
self.size, self.files_count = get_path_datasize(self.path)
- self.sleep(5)
self.signal.emit(self.path,self.size,self.files_count)
def get_directory_size(path):
@@ -70,9 +68,9 @@ def get_path_datasize(path):
if file_info.isDir():
data_size, files_count = get_directory_size(file_info.absoluteFilePath())
- logger.info("path (folder) %s %u elements size now=%u (%s)",file_info.absoluteFilePath(),files_count,data_size,pretty_bytes(data_size))
+ # logger.info("path (folder) %s %u elements size now=%u (%s)",file_info.absoluteFilePath(),files_count,data_size,pretty_bytes(data_size))
else:
- logger.info("path (file) %s size=%u",file_info.path(),file_info.size())
+ # logger.info("path (file) %s size=%u",file_info.path(),file_info.size())
data_size = file_info.size()
files_count = 1
From ae6eba8af248fad723383909efc619062b1e20af Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 26 Sep 2020 20:17:09 +0000
Subject: [PATCH 16/64] Add stuff to update source infos
---
src/vorta/views/source_tab.py | 47 ++++++++++++++++++++++-------------
1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 20b85c8fb..2dcbe83a7 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -35,6 +35,7 @@ def __init__(self, parent=None):
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
+ self.sourcesUpdate.clicked.connect(self.sources_update)
self.paste.clicked.connect(self.paste_text)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
@@ -49,31 +50,39 @@ def set_path_info(self,path,data_size,files_count):
db_item.dir_size = data_size
db_item.dir_files_count = files_count
db_item.save()
-
+ # Remove thread from list when it's done
+ for thrd in self.updateThreads:
+ if thrd.objectName() == path:
+ self.updateThreads.remove(thrd)
+
+ def update_path_info(self,index_row):
+ path = self.sourceFilesWidget.item(index_row,0).text()
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("load..."))
+ getDir = FilePathInfoAsync(path)
+ getDir.signal.connect(self.set_path_info)
+ getDir.setObjectName(path)
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ getDir.start()
def add_source_to_table(self,source,update_data):
- indexRow = self.sourceFilesWidget.rowCount()
- self.sourceFilesWidget.insertRow(indexRow)
- itemPath = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(indexRow,0,itemPath)
+ index_row = self.sourceFilesWidget.rowCount()
+ self.sourceFilesWidget.insertRow(index_row)
+ item_path = QTableWidgetItem(source.dir)
+ self.sourceFilesWidget.setItem(index_row,0,item_path)
if source.path_isdir == True:
- self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem("
"))
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem(""))
else:
- self.sourceFilesWidget.setItem(indexRow,1,QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem(""))
if update_data == True:
- self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("load..."))
- getDir = FilePathInfoAsync(source.dir)
- getDir.signal.connect(self.set_path_info)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
- getDir.start()
+ self.update_path_info(index_row)
else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("N/A"))
else:
- self.sourceFilesWidget.setItem(indexRow,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(indexRow,3,QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
@@ -91,6 +100,10 @@ def populate_from_profile(self):
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
+ def sources_update(self):
+ for row in range(0, self.sourceFilesWidget.rowCount()):
+ self.update_path_info(row) # Update data for each entry
+
def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
From e54bd42ed4d0e78cb8e33d096aaafbb2e28efe5c Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 08:45:55 +0000
Subject: [PATCH 17/64] Update src/vorta/assets/UI/sourcetab.ui
Co-authored-by: Samuel Woon
---
src/vorta/assets/UI/sourcetab.ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 2b8d88603..8a9534505 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -105,7 +105,7 @@
-
- Update Sources
+ Recalculate sizes
From 65916b1586c03ff9c4e44e9c0a480e3e51fcf87c Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 08:46:27 +0000
Subject: [PATCH 18/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel Woon
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 2dcbe83a7..a9b2b3240 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -71,7 +71,7 @@ def add_source_to_table(self,source,update_data):
item_path = QTableWidgetItem(source.dir)
self.sourceFilesWidget.setItem(index_row,0,item_path)
if source.path_isdir == True:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
else:
self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem(""))
if update_data == True:
From 384c2c700cd6ddb937bf993b62c60d0669f9829b Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 08:46:36 +0000
Subject: [PATCH 19/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel Woon
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index a9b2b3240..8455eac0d 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -73,7 +73,7 @@ def add_source_to_table(self,source,update_data):
if source.path_isdir == True:
self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
else:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("File"))
if update_data == True:
self.update_path_info(index_row)
else: # Use cached data from DB
From 7516a74192b7ed785f57a8d57338ea64a1fdf633 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 08:49:34 +0000
Subject: [PATCH 20/64] Update src/vorta/assets/UI/sourcetab.ui
Co-authored-by: Samuel Woon
---
src/vorta/assets/UI/sourcetab.ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 8a9534505..a467fe14a 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -95,7 +95,7 @@
- -
+
-
Remove
From b64a486086e9d16500646ee6c5c741072eaef82b Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 17:51:33 +0000
Subject: [PATCH 21/64] run lint
---
src/vorta/models.py | 11 +++--------
src/vorta/utils.py | 44 ++++++++++++++++++++++----------------------
2 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index d78298ebb..d0cebdccf 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -218,11 +218,6 @@ def get_misc_settings():
'label': trans_late('settings',
'Open main window on startup')
},
- {
- 'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
- 'label': trans_late('settings',
- 'Get Size of Source path when added')
- },
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
'label': 'Previously selected profile'
@@ -374,11 +369,11 @@ def init_db(con=None):
_apply_schema_update(
current_schema, 16,
migrator.add_column(SourceFileModel._meta.table_name,
- 'dir_size', pw.BigIntegerField(default = -1)),
+ 'dir_size', pw.BigIntegerField(default=-1)),
migrator.add_column(SourceFileModel._meta.table_name,
- 'dir_files_count', pw.BigIntegerField(default = -1)),
+ 'dir_files_count', pw.BigIntegerField(default=-1)),
migrator.add_column(SourceFileModel._meta.table_name,
- 'path_isdir', pw.BooleanField(default = False))
+ 'path_isdir', pw.BooleanField(default=False))
)
# Create missing settings and update labels. Leave setting values untouched.
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 99885eee8..89c005046 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -31,28 +31,36 @@
keyring = VortaKeyring.get_keyring()
logger.info('Using %s Keyring implementation.', keyring.__class__.__name__)
+network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
+logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
+
borg_compat = BorgCompatibility()
+
class FilePathInfoAsync(QThread):
- signal = pyqtSignal(str,int,int)
- def __init__(self,path):
+ signal = pyqtSignal(str, int, int)
+
+ def __init__(self, path):
self.path = path
QThread.__init__(self)
self.exiting = False
def run(self):
+ logger.info("running thread to get path=%s...", self.path)
self.files_count = 0
self.size, self.files_count = get_path_datasize(self.path)
- self.signal.emit(self.path,self.size,self.files_count)
+ self.sleep(5)
+ self.signal.emit(self.path, self.size, self.files_count)
+
-def get_directory_size(path):
- res = subprocess.run('find . | wc -l', cwd=path, shell=True, check=False,
+def get_directory_size(dirPath):
+ res = subprocess.run('find . | wc -l', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
files_count = int(res.stdout.split(b'\t')[0])
- if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- res = subprocess.run('du -sb .', cwd=path, shell=True, check=False,
+ if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
+ res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
data_size = int(res.stdout.split(b'\t')[0])
else:
@@ -64,28 +72,19 @@ def get_directory_size(path):
def get_path_datasize(path):
file_info = QFileInfo(path)
- data_size = 0
+ data_size = 0
if file_info.isDir():
data_size, files_count = get_directory_size(file_info.absoluteFilePath())
- # logger.info("path (folder) %s %u elements size now=%u (%s)",file_info.absoluteFilePath(),files_count,data_size,pretty_bytes(data_size))
+ logger.info("path (folder) %s %u elements size now=%u (%s)",
+ file_info.absoluteFilePath(), files_count, data_size, pretty_bytes(data_size))
else:
- # logger.info("path (file) %s size=%u",file_info.path(),file_info.size())
+ logger.info("path (file) %s size=%u", file_info.path(), file_info.size())
data_size = file_info.size()
files_count = 1
return data_size, files_count
-_network_status_monitor = None
-
-
-def get_network_status_monitor():
- global _network_status_monitor
- if _network_status_monitor is None:
- _network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
- logger.info('Using %s NetworkStatusMonitor implementation.', _network_status_monitor.__class__.__name__)
- return _network_status_monitor
-
def nested_dict():
"""
@@ -148,7 +147,7 @@ def get_private_keys():
def pretty_bytes(size):
"""from https://stackoverflow.com/questions/12523586/
python-format-size-application-converting-b-to-kb-mb-gb-tb/37423778"""
- if type(size) != int:
+ if not isinstance(size, int):
return ''
power = 1000 # GiB is base 2**10, GB is base 10**3.
n = 0
@@ -179,7 +178,7 @@ def get_sorted_wifis(profile):
from vorta.models import WifiSettingModel
- system_wifis = get_network_status_monitor().get_known_wifis()
+ system_wifis = network_status_monitor.get_known_wifis()
if system_wifis is None:
# Don't show any networks if we can't get the current list
return []
@@ -295,3 +294,4 @@ def is_system_tray_available():
is_available = tray.isSystemTrayAvailable()
return is_available
+
From f67203ee51d5a2b6f6f41f3ecd8b845229fbad07 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 27 Sep 2020 17:52:07 +0000
Subject: [PATCH 22/64] run lint
---
src/vorta/views/source_tab.py | 86 +++++++++++++++--------------------
1 file changed, 36 insertions(+), 50 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 8455eac0d..828f4f2cc 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,5 +1,5 @@
from PyQt5 import uic
-from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
+from ..models import SourceFileModel, BackupProfileMixin
from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo
@@ -12,19 +12,19 @@
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
-
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
-
- headerTxt=["Path","Type","Size","Elements Count"]
+
+ headerTxt = ["Path", "Type", "Size", "Elements Count"]
self.sourceFilesWidget.setColumnCount(len(headerTxt))
header = self.sourceFilesWidget.horizontalHeader()
header.setVisible(True)
header.setSortIndicatorShown(1)
-
+
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
@@ -35,54 +35,44 @@ def __init__(self, parent=None):
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
- self.sourcesUpdate.clicked.connect(self.sources_update)
self.paste.clicked.connect(self.paste_text)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
-
- def set_path_info(self,path,data_size,files_count):
- items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
+
+ def set_path_info(self, path, data_size, files_count):
+ items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
for item in items:
- self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(),3).setText(format(files_count))
+ self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item = SourceFileModel.get(dir=path)
db_item.dir_size = data_size
db_item.dir_files_count = files_count
db_item.save()
- # Remove thread from list when it's done
- for thrd in self.updateThreads:
- if thrd.objectName() == path:
- self.updateThreads.remove(thrd)
-
- def update_path_info(self,index_row):
- path = self.sourceFilesWidget.item(index_row,0).text()
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("load..."))
- getDir = FilePathInfoAsync(path)
- getDir.signal.connect(self.set_path_info)
- getDir.setObjectName(path)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
- getDir.start()
-
- def add_source_to_table(self,source,update_data):
- index_row = self.sourceFilesWidget.rowCount()
- self.sourceFilesWidget.insertRow(index_row)
- item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row,0,item_path)
+
+ def add_source_to_table(self, source, update_data):
+ indexRow = self.sourceFilesWidget.rowCount()
+ self.sourceFilesWidget.insertRow(indexRow)
+ itemPath = QTableWidgetItem(source.dir)
+ self.sourceFilesWidget.setItem(indexRow, 0, itemPath)
if source.path_isdir == True:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.setItem(indexRow, 1, QTableWidgetItem(""))
else:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(indexRow, 1, QTableWidgetItem(""))
if update_data == True:
- self.update_path_info(index_row)
- else: # Use cached data from DB
+ self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem("load..."))
+ getDir = FilePathInfoAsync(source.dir)
+ getDir.signal.connect(self.set_path_info)
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ getDir.start()
+ else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem("N/A"))
else:
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
@@ -93,28 +83,24 @@ def populate_from_profile(self):
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source,False)
+ self.add_source_to_table(source, False)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
- def sources_update(self):
- for row in range(0, self.sourceFilesWidget.rowCount()):
- self.update_path_info(row) # Update data for each entry
-
def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir,
- dir_size=-1,
- dir_files_count=-1,
- path_isdir=QFileInfo(dir).isDir(),
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=QFileInfo(dir).isDir(),
profile=self.profile())
if created:
- self.add_source_to_table(new_source,SettingsModel.get(key="get_srcpath_datasize").value)
+ self.add_source_to_table(new_source, True)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
@@ -127,7 +113,7 @@ def source_remove(self):
indexes.sort()
# remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(),0).text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
db_item.delete_instance()
self.sourceFilesWidget.removeRow(index.row())
From b84f7a95c13294510f42c6edd75e2128a3cd363b Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 19:00:42 +0000
Subject: [PATCH 23/64] re-add network status monitor
---
src/vorta/utils.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 431cad544..c9168ed9e 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -28,6 +28,10 @@
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons
+keyring = VortaKeyring.get_keyring()
+logger.info('Using %s Keyring implementation.', keyring.__class__.__name__)
+network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
+logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
borg_compat = BorgCompatibility()
From 567cbbea0c12b3fadbf503e611ed6a78da711c66 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 19:04:51 +0000
Subject: [PATCH 24/64] Add spacer
---
src/vorta/assets/UI/sourcetab.ui | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index a467fe14a..484694b95 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -109,6 +109,19 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
From 1e7b2a09e7c7f5b3e9354056649d055538582634 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 21:06:54 +0200
Subject: [PATCH 25/64] re-add network status monitor
---
src/vorta/utils.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index c9168ed9e..aa3125899 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -68,6 +68,13 @@ def get_directory_size(dirPath):
return data_size, files_count
+def get_network_status_monitor():
+ global _network_status_monitor
+ if _network_status_monitor is None:
+ _network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
+ logger.info('Using %s NetworkStatusMonitor implementation.', _network_status_monitor.__class__.__name__)
+ return _network_status_monitor
+
def get_path_datasize(path):
file_info = QFileInfo(path)
From 04ec022160bfa3206bc0d538b72c814ef44fbfa9 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 21:09:28 +0200
Subject: [PATCH 26/64] remove keyring stuff
---
src/vorta/utils.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index aa3125899..b30de5a96 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -28,8 +28,6 @@
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons
-keyring = VortaKeyring.get_keyring()
-logger.info('Using %s Keyring implementation.', keyring.__class__.__name__)
network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
From 4023708fe039838e051fc0d7beff67428caea6f2 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 20:04:00 +0000
Subject: [PATCH 27/64] fixes some previous bugs
---
src/vorta/models.py | 5 +++++
src/vorta/utils.py | 15 +++++++--------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index d0cebdccf..62011f2a1 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -218,6 +218,11 @@ def get_misc_settings():
'label': trans_late('settings',
'Open main window on startup')
},
+ {
+ 'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
+ 'label': trans_late('settings',
+ 'Get Size of Source path when added')
+ },
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
'label': 'Previously selected profile'
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index b30de5a96..07c4f749f 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -32,10 +32,10 @@
logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
borg_compat = BorgCompatibility()
-
+_network_status_monitor = None
class FilePathInfoAsync(QThread):
- signal = pyqtSignal(str, int, int)
+ signal = pyqtSignal(str, str, str)
def __init__(self, path):
self.path = path
@@ -43,11 +43,10 @@ def __init__(self, path):
self.exiting = False
def run(self):
- logger.info("running thread to get path=%s...", self.path)
+ # logger.info("running thread to get path=%s...", self.path)
self.files_count = 0
self.size, self.files_count = get_path_datasize(self.path)
- self.sleep(5)
- self.signal.emit(self.path, self.size, self.files_count)
+ self.signal.emit(self.path, str(self.size), str(self.files_count))
def get_directory_size(dirPath):
@@ -80,10 +79,10 @@ def get_path_datasize(path):
if file_info.isDir():
data_size, files_count = get_directory_size(file_info.absoluteFilePath())
- logger.info("path (folder) %s %u elements size now=%u (%s)",
- file_info.absoluteFilePath(), files_count, data_size, pretty_bytes(data_size))
+ # logger.info("path (folder) %s %u elements size now=%u (%s)",
+ # file_info.absoluteFilePath(), files_count, data_size, pretty_bytes(data_size))
else:
- logger.info("path (file) %s size=%u", file_info.path(), file_info.size())
+ # logger.info("path (file) %s size=%u", file_info.path(), file_info.size())
data_size = file_info.size()
files_count = 1
From 55a125771db3562780550be79ca087130ed99836 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 29 Sep 2020 20:06:06 +0000
Subject: [PATCH 28/64] Fixed some bugs
---
src/vorta/views/source_tab.py | 102 ++++++++++++++++++++++------------
1 file changed, 65 insertions(+), 37 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 828f4f2cc..468c10d4a 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,5 +1,5 @@
from PyQt5 import uic
-from ..models import SourceFileModel, BackupProfileMixin
+from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo
@@ -12,19 +12,19 @@
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
-
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
-
- headerTxt = ["Path", "Type", "Size", "Elements Count"]
+
+ headerTxt=["Path", "Type", "Size", "Folders /\nFiles Count"]
self.sourceFilesWidget.setColumnCount(len(headerTxt))
header = self.sourceFilesWidget.horizontalHeader()
header.setVisible(True)
header.setSortIndicatorShown(1)
-
+
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
@@ -35,44 +35,68 @@ def __init__(self, parent=None):
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
+ self.sourcesUpdate.clicked.connect(self.sources_update)
self.paste.clicked.connect(self.paste_text)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
+
+ def set_path_info(self,path,data_size,files_count):
+ items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
+ # Conversion int->str->int needed because QT limits int to 32-bit
+ data_size = int(data_size)
+ files_count = int(files_count)
- def set_path_info(self, path, data_size, files_count):
- items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
for item in items:
- self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item = SourceFileModel.get(dir=path)
+ if QFileInfo(path).isDir():
+ self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("Folder"))
+ db_item.path_isdir = True
+ else:
+ self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("File"))
+ db_item.path_isdir = False
+ self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(),3).setText(format(files_count))
+
db_item.dir_size = data_size
db_item.dir_files_count = files_count
db_item.save()
-
- def add_source_to_table(self, source, update_data):
- indexRow = self.sourceFilesWidget.rowCount()
- self.sourceFilesWidget.insertRow(indexRow)
- itemPath = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(indexRow, 0, itemPath)
- if source.path_isdir == True:
- self.sourceFilesWidget.setItem(indexRow, 1, QTableWidgetItem(""))
- else:
- self.sourceFilesWidget.setItem(indexRow, 1, QTableWidgetItem(""))
+ # Remove thread from list when it's done
+ for thrd in self.updateThreads:
+ if thrd.objectName() == path:
+ self.updateThreads.remove(thrd)
+
+ def update_path_info(self,index_row):
+ path = self.sourceFilesWidget.item(index_row,0).text()
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("load..."))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("load..."))
+ getDir = FilePathInfoAsync(path)
+ getDir.signal.connect(self.set_path_info)
+ getDir.setObjectName(path)
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ getDir.start()
+
+ def add_source_to_table(self,source,update_data):
+ index_row = self.sourceFilesWidget.rowCount()
+ self.sourceFilesWidget.insertRow(index_row)
+ item_path = QTableWidgetItem(source.dir)
+ self.sourceFilesWidget.setItem(index_row,0,item_path)
if update_data == True:
- self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem("load..."))
- getDir = FilePathInfoAsync(source.dir)
- getDir.signal.connect(self.set_path_info)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
- getDir.start()
- else: # Use cached data from DB
+ self.update_path_info(index_row)
+ else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("N/A"))
else:
- self.sourceFilesWidget.setItem(indexRow, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(indexRow, 3, QTableWidgetItem(format(source.dir_files_count)))
+ if source.path_isdir == True:
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
+ else:
+ self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("File"))
+
+ self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
@@ -83,24 +107,28 @@ def populate_from_profile(self):
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source, False)
+ self.add_source_to_table(source,False)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
+ def sources_update(self):
+ for row in range(0, self.sourceFilesWidget.rowCount()):
+ self.update_path_info(row) # Update data for each entry
+
def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir,
- dir_size=-1,
- dir_files_count=-1,
- path_isdir=QFileInfo(dir).isDir(),
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=False,
profile=self.profile())
if created:
- self.add_source_to_table(new_source, True)
+ self.add_source_to_table(new_source,SettingsModel.get(key="get_srcpath_datasize").value)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
@@ -113,7 +141,7 @@ def source_remove(self):
indexes.sort()
# remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(),0).text())
db_item.delete_instance()
self.sourceFilesWidget.removeRow(index.row())
From b71c1565082611e79754eed4faa3c51fef74f9bd Mon Sep 17 00:00:00 2001
From: Samuel
Date: Thu, 1 Oct 2020 03:01:04 -0500
Subject: [PATCH 29/64] Lint, use QTableWidget
---
src/vorta/__init__.py | 1 -
src/vorta/assets/UI/sourcetab.ui | 37 ++++++++++-----
src/vorta/models.py | 2 +-
src/vorta/utils.py | 5 ++-
src/vorta/views/source_tab.py | 77 +++++++++++++++-----------------
5 files changed, 67 insertions(+), 55 deletions(-)
delete mode 100644 src/vorta/__init__.py
diff --git a/src/vorta/__init__.py b/src/vorta/__init__.py
deleted file mode 100644
index 8dee4bf82..000000000
--- a/src/vorta/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from ._version import __version__
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 484694b95..0759ff2c7 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -64,9 +64,26 @@
false
-
- false
-
+
+
+ Path
+
+
+
+
+ Type
+
+
+
+
+ Size
+
+
+
+
+ File/Folder Count
+
+
-
@@ -85,6 +102,13 @@
+ -
+
+
+ Remove
+
+
+
-
@@ -95,13 +119,6 @@
- -
-
-
- Remove
-
-
-
-
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 62011f2a1..9996158e6 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -221,7 +221,7 @@ def get_misc_settings():
{
'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
'label': trans_late('settings',
- 'Get Size of Source path when added')
+ 'Get size of file/folder when added')
},
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 07c4f749f..49198f457 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -18,7 +18,7 @@
from paramiko.ed25519key import Ed25519Key
from paramiko.rsakey import RSAKey
from PyQt5 import QtCore
-from PyQt5.QtCore import QFileInfo, QDir, QThread, pyqtSignal
+from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from vorta.borg._compatibility import BorgCompatibility
@@ -34,6 +34,7 @@
borg_compat = BorgCompatibility()
_network_status_monitor = None
+
class FilePathInfoAsync(QThread):
signal = pyqtSignal(str, str, str)
@@ -65,6 +66,7 @@ def get_directory_size(dirPath):
return data_size, files_count
+
def get_network_status_monitor():
global _network_status_monitor
if _network_status_monitor is None:
@@ -297,4 +299,3 @@ def is_system_tray_available():
is_available = tray.isSystemTrayAvailable()
return is_available
-
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 468c10d4a..b1a11cfb8 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -12,26 +12,21 @@
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
-
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
-
- headerTxt=["Path", "Type", "Size", "Folders /\nFiles Count"]
- self.sourceFilesWidget.setColumnCount(len(headerTxt))
header = self.sourceFilesWidget.horizontalHeader()
header.setVisible(True)
header.setSortIndicatorShown(1)
-
+
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
- self.sourceFilesWidget.setHorizontalHeaderLabels(headerTxt)
-
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
@@ -40,9 +35,9 @@ def __init__(self, parent=None):
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
-
- def set_path_info(self,path,data_size,files_count):
- items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
+
+ def set_path_info(self, path, data_size, files_count):
+ items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
# Conversion int->str->int needed because QT limits int to 32-bit
data_size = int(data_size)
files_count = int(files_count)
@@ -50,13 +45,13 @@ def set_path_info(self,path,data_size,files_count):
for item in items:
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
- self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
db_item.path_isdir = True
else:
- self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
db_item.path_isdir = False
- self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(),3).setText(format(files_count))
+ self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item.dir_size = data_size
db_item.dir_files_count = files_count
@@ -66,48 +61,48 @@ def set_path_info(self,path,data_size,files_count):
if thrd.objectName() == path:
self.updateThreads.remove(thrd)
- def update_path_info(self,index_row):
- path = self.sourceFilesWidget.item(index_row,0).text()
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("load..."))
+ def update_path_info(self, index_row):
+ path = self.sourceFilesWidget.item(index_row, 0).text()
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("Calculating..."))
getDir = FilePathInfoAsync(path)
getDir.signal.connect(self.set_path_info)
getDir.setObjectName(path)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
getDir.start()
- def add_source_to_table(self,source,update_data):
+ def add_source_to_table(self, source, update_data):
index_row = self.sourceFilesWidget.rowCount()
self.sourceFilesWidget.insertRow(index_row)
item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row,0,item_path)
- if update_data == True:
+ self.sourceFilesWidget.setItem(index_row, 0, item_path)
+ if update_data:
self.update_path_info(index_row)
- else: # Use cached data from DB
+ else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("N/A"))
else:
- if source.path_isdir == True:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
+ if source.path_isdir:
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
else:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
self.excludePatternsField.textChanged.disconnect()
self.excludeIfPresentField.textChanged.disconnect()
- self.sourceFilesWidget.clearContents()
+ self.sourceFilesWidget.setRowCount(0) # Clear rows
self.excludePatternsField.clear()
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source,False)
+ self.add_source_to_table(source, False)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
@@ -116,19 +111,19 @@ def populate_from_profile(self):
def sources_update(self):
for row in range(0, self.sourceFilesWidget.rowCount()):
- self.update_path_info(row) # Update data for each entry
+ self.update_path_info(row) # Update data for each entry
def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir,
- dir_size=-1,
- dir_files_count=-1,
- path_isdir=False,
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=False,
profile=self.profile())
if created:
- self.add_source_to_table(new_source,SettingsModel.get(key="get_srcpath_datasize").value)
+ self.add_source_to_table(new_source, SettingsModel.get(key="get_srcpath_datasize").value)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
@@ -141,7 +136,7 @@ def source_remove(self):
indexes.sort()
# remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(),0).text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
db_item.delete_instance()
self.sourceFilesWidget.removeRow(index.row())
From dec0ae90355bf2360203301a536dc87de3d06008 Mon Sep 17 00:00:00 2001
From: Samuel
Date: Thu, 1 Oct 2020 03:12:14 -0500
Subject: [PATCH 30/64] Fix tests
---
tests/conftest.py | 2 +-
tests/test_source.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/conftest.py b/tests/conftest.py
index f462a420a..bc54d7513 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -37,7 +37,7 @@ def init_db(qapp):
test_archive1 = ArchiveModel(snapshot_id='99998', name='test-archive1', time=dt(2000, 1, 1, 0, 0), repo=1)
test_archive1.save()
- source_dir = SourceFileModel(dir='/tmp/another', repo=new_repo)
+ source_dir = SourceFileModel(dir='/tmp/another', repo=new_repo, dir_size=100, dir_files_count=18, path_isdir=True)
source_dir.save()
qapp.open_main_window_action()
diff --git a/tests/test_source.py b/tests/test_source.py
index b461dad09..0fb751a61 100644
--- a/tests/test_source.py
+++ b/tests/test_source.py
@@ -11,4 +11,4 @@ def test_add_folder(qapp, qtbot, tmpdir, monkeypatch, choose_file_dialog):
tab = main.sourceTab
tab.sourceAddFolder.click()
- qtbot.waitUntil(lambda: tab.sourceFilesWidget.count() == 2, timeout=5000)
+ qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 2, timeout=5000)
From cf4d35ecf28a3565ea9dff7af1be7be303126f4e Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 3 Oct 2020 20:13:59 +0000
Subject: [PATCH 31/64] applied patch
---
src/vorta/assets/UI/source_tab.py | 169 ++++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 src/vorta/assets/UI/source_tab.py
diff --git a/src/vorta/assets/UI/source_tab.py b/src/vorta/assets/UI/source_tab.py
new file mode 100644
index 000000000..b1a11cfb8
--- /dev/null
+++ b/src/vorta/assets/UI/source_tab.py
@@ -0,0 +1,169 @@
+from PyQt5 import uic
+from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
+from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
+from PyQt5 import QtCore
+from PyQt5.QtCore import QFileInfo
+from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
+import os
+
+uifile = get_asset('UI/sourcetab.ui')
+SourceUI, SourceBase = uic.loadUiType(uifile)
+
+
+class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
+ updateThreads = []
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setupUi(parent)
+
+ header = self.sourceFilesWidget.horizontalHeader()
+
+ header.setVisible(True)
+ header.setSortIndicatorShown(1)
+
+ header.setSectionResizeMode(0, QHeaderView.Stretch)
+ header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
+
+ self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
+ self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
+ self.sourceRemove.clicked.connect(self.source_remove)
+ self.sourcesUpdate.clicked.connect(self.sources_update)
+ self.paste.clicked.connect(self.paste_text)
+ self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
+ self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
+ self.populate_from_profile()
+
+ def set_path_info(self, path, data_size, files_count):
+ items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
+ # Conversion int->str->int needed because QT limits int to 32-bit
+ data_size = int(data_size)
+ files_count = int(files_count)
+
+ for item in items:
+ db_item = SourceFileModel.get(dir=path)
+ if QFileInfo(path).isDir():
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
+ db_item.path_isdir = True
+ else:
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
+ db_item.path_isdir = False
+ self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
+
+ db_item.dir_size = data_size
+ db_item.dir_files_count = files_count
+ db_item.save()
+ # Remove thread from list when it's done
+ for thrd in self.updateThreads:
+ if thrd.objectName() == path:
+ self.updateThreads.remove(thrd)
+
+ def update_path_info(self, index_row):
+ path = self.sourceFilesWidget.item(index_row, 0).text()
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("Calculating..."))
+ getDir = FilePathInfoAsync(path)
+ getDir.signal.connect(self.set_path_info)
+ getDir.setObjectName(path)
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ getDir.start()
+
+ def add_source_to_table(self, source, update_data):
+ index_row = self.sourceFilesWidget.rowCount()
+ self.sourceFilesWidget.insertRow(index_row)
+ item_path = QTableWidgetItem(source.dir)
+ self.sourceFilesWidget.setItem(index_row, 0, item_path)
+ if update_data:
+ self.update_path_info(index_row)
+ else: # Use cached data from DB
+ if source.dir_size < 0:
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("N/A"))
+ else:
+ if source.path_isdir:
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
+ else:
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
+
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
+
+ def populate_from_profile(self):
+ profile = self.profile()
+ self.excludePatternsField.textChanged.disconnect()
+ self.excludeIfPresentField.textChanged.disconnect()
+ self.sourceFilesWidget.setRowCount(0) # Clear rows
+ self.excludePatternsField.clear()
+ self.excludeIfPresentField.clear()
+
+ for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
+ self.add_source_to_table(source, False)
+
+ self.excludePatternsField.appendPlainText(profile.exclude_patterns)
+ self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
+ self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
+ self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
+
+ def sources_update(self):
+ for row in range(0, self.sourceFilesWidget.rowCount()):
+ self.update_path_info(row) # Update data for each entry
+
+ def source_add(self, want_folder):
+ def receive():
+ dirs = dialog.selectedFiles()
+ for dir in dirs:
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=False,
+ profile=self.profile())
+ if created:
+ self.add_source_to_table(new_source, SettingsModel.get(key="get_srcpath_datasize").value)
+ new_source.save()
+
+ msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
+ dialog = choose_file_dialog(self, msg, want_folder=want_folder)
+ dialog.open(receive)
+
+ def source_remove(self):
+ indexes = self.sourceFilesWidget.selectionModel().selectedRows()
+ # sort indexes, starting with lowest
+ indexes.sort()
+ # remove each selected row, starting with highest index (otherways, higher indexes become invalid)
+ for index in reversed(indexes):
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
+ db_item.delete_instance()
+ self.sourceFilesWidget.removeRow(index.row())
+
+ def save_exclude_patterns(self):
+ profile = self.profile()
+ profile.exclude_patterns = self.excludePatternsField.toPlainText()
+ profile.save()
+
+ def save_exclude_if_present(self):
+ profile = self.profile()
+ profile.exclude_if_present = self.excludeIfPresentField.toPlainText()
+ profile.save()
+
+ def paste_text(self):
+ sources = QApplication.clipboard().text().splitlines()
+ invalidSources = ""
+ for source in sources:
+ if len(source) > 0: # Ignore empty newlines
+ if not os.path.exists(source):
+ invalidSources = invalidSources + "\n" + source
+ else:
+ new_source, created = SourceFileModel.get_or_create(dir=source, profile=self.profile())
+ if created:
+ self.sourceFilesWidget.addItem(source)
+ new_source.save()
+
+ if len(invalidSources) != 0: # Check if any invalid paths
+ msg = QMessageBox()
+ msg.setText("Some of your sources are invalid:" + invalidSources)
+ msg.exec()
From 2db7347f1e8a3bc9abc957f3a4d05c81399f8171 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 3 Oct 2020 20:14:30 +0000
Subject: [PATCH 32/64] applied patch
---
src/vorta/models.py | 2 +-
src/vorta/utils.py | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 62011f2a1..9996158e6 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -221,7 +221,7 @@ def get_misc_settings():
{
'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
'label': trans_late('settings',
- 'Get Size of Source path when added')
+ 'Get size of file/folder when added')
},
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 07c4f749f..49198f457 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -18,7 +18,7 @@
from paramiko.ed25519key import Ed25519Key
from paramiko.rsakey import RSAKey
from PyQt5 import QtCore
-from PyQt5.QtCore import QFileInfo, QDir, QThread, pyqtSignal
+from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from vorta.borg._compatibility import BorgCompatibility
@@ -34,6 +34,7 @@
borg_compat = BorgCompatibility()
_network_status_monitor = None
+
class FilePathInfoAsync(QThread):
signal = pyqtSignal(str, str, str)
@@ -65,6 +66,7 @@ def get_directory_size(dirPath):
return data_size, files_count
+
def get_network_status_monitor():
global _network_status_monitor
if _network_status_monitor is None:
@@ -297,4 +299,3 @@ def is_system_tray_available():
is_available = tray.isSystemTrayAvailable()
return is_available
-
From a22455c9dc818376fd61561707bf48c6aa5674b6 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 3 Oct 2020 20:15:10 +0000
Subject: [PATCH 33/64] applied patch
---
src/vorta/views/source_tab.py | 77 ++++++++++++++++-------------------
1 file changed, 36 insertions(+), 41 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 468c10d4a..b1a11cfb8 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -12,26 +12,21 @@
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
-
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
-
- headerTxt=["Path", "Type", "Size", "Folders /\nFiles Count"]
- self.sourceFilesWidget.setColumnCount(len(headerTxt))
header = self.sourceFilesWidget.horizontalHeader()
header.setVisible(True)
header.setSortIndicatorShown(1)
-
+
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
- self.sourceFilesWidget.setHorizontalHeaderLabels(headerTxt)
-
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
@@ -40,9 +35,9 @@ def __init__(self, parent=None):
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
-
- def set_path_info(self,path,data_size,files_count):
- items = self.sourceFilesWidget.findItems(path,QtCore.Qt.MatchExactly)
+
+ def set_path_info(self, path, data_size, files_count):
+ items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
# Conversion int->str->int needed because QT limits int to 32-bit
data_size = int(data_size)
files_count = int(files_count)
@@ -50,13 +45,13 @@ def set_path_info(self,path,data_size,files_count):
for item in items:
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
- self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
db_item.path_isdir = True
else:
- self.sourceFilesWidget.setItem(item.row(),1,QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
db_item.path_isdir = False
- self.sourceFilesWidget.item(item.row(),2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(),3).setText(format(files_count))
+ self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item.dir_size = data_size
db_item.dir_files_count = files_count
@@ -66,48 +61,48 @@ def set_path_info(self,path,data_size,files_count):
if thrd.objectName() == path:
self.updateThreads.remove(thrd)
- def update_path_info(self,index_row):
- path = self.sourceFilesWidget.item(index_row,0).text()
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("load..."))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("load..."))
+ def update_path_info(self, index_row):
+ path = self.sourceFilesWidget.item(index_row, 0).text()
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("Calculating..."))
getDir = FilePathInfoAsync(path)
getDir.signal.connect(self.set_path_info)
getDir.setObjectName(path)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
+ self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
getDir.start()
- def add_source_to_table(self,source,update_data):
+ def add_source_to_table(self, source, update_data):
index_row = self.sourceFilesWidget.rowCount()
self.sourceFilesWidget.insertRow(index_row)
item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row,0,item_path)
- if update_data == True:
+ self.sourceFilesWidget.setItem(index_row, 0, item_path)
+ if update_data:
self.update_path_info(index_row)
- else: # Use cached data from DB
+ else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("N/A"))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("N/A"))
else:
- if source.path_isdir == True:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("Folder"))
+ if source.path_isdir:
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
else:
- self.sourceFilesWidget.setItem(index_row,1,QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
- self.sourceFilesWidget.setItem(index_row,2,QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(index_row,3,QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
self.excludePatternsField.textChanged.disconnect()
self.excludeIfPresentField.textChanged.disconnect()
- self.sourceFilesWidget.clearContents()
+ self.sourceFilesWidget.setRowCount(0) # Clear rows
self.excludePatternsField.clear()
self.excludeIfPresentField.clear()
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source,False)
+ self.add_source_to_table(source, False)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
@@ -116,19 +111,19 @@ def populate_from_profile(self):
def sources_update(self):
for row in range(0, self.sourceFilesWidget.rowCount()):
- self.update_path_info(row) # Update data for each entry
+ self.update_path_info(row) # Update data for each entry
def source_add(self, want_folder):
def receive():
dirs = dialog.selectedFiles()
for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir,
- dir_size=-1,
- dir_files_count=-1,
- path_isdir=False,
+ new_source, created = SourceFileModel.get_or_create(dir=dir,
+ dir_size=-1,
+ dir_files_count=-1,
+ path_isdir=False,
profile=self.profile())
if created:
- self.add_source_to_table(new_source,SettingsModel.get(key="get_srcpath_datasize").value)
+ self.add_source_to_table(new_source, SettingsModel.get(key="get_srcpath_datasize").value)
new_source.save()
msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
@@ -141,7 +136,7 @@ def source_remove(self):
indexes.sort()
# remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(),0).text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
db_item.delete_instance()
self.sourceFilesWidget.removeRow(index.row())
From 6f6de6700b7fd7a851bef3535f77710d63493f1e Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 3 Oct 2020 20:59:30 +0000
Subject: [PATCH 34/64] Changed as requested
Files count for file = empty,
Text "N/A" removed for unknown entry data
---
src/vorta/views/source_tab.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index b1a11cfb8..5f2793e0c 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -46,12 +46,14 @@ def set_path_info(self, path, data_size, files_count):
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item.path_isdir = True
else:
self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
+ # No files count, if entry itself is a file
+ self.sourceFilesWidget.item(item.row(), 3).setText("")
db_item.path_isdir = False
self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
db_item.dir_size = data_size
db_item.dir_files_count = files_count
@@ -81,17 +83,19 @@ def add_source_to_table(self, source, update_data):
self.update_path_info(index_row)
else: # Use cached data from DB
if source.dir_size < 0:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("N/A"))
+ # Size/count wasn't calculated yet
+ self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(""))
else:
if source.path_isdir:
self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
else:
self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(""))
self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
def populate_from_profile(self):
profile = self.profile()
From 4464318df50c9070fe2fd7ba2e31b516852a95dd Mon Sep 17 00:00:00 2001
From: samuel-w
Date: Sat, 3 Oct 2020 16:11:36 -0500
Subject: [PATCH 35/64] Remove extra file
---
src/vorta/assets/UI/source_tab.py | 169 ------------------------------
1 file changed, 169 deletions(-)
delete mode 100644 src/vorta/assets/UI/source_tab.py
diff --git a/src/vorta/assets/UI/source_tab.py b/src/vorta/assets/UI/source_tab.py
deleted file mode 100644
index b1a11cfb8..000000000
--- a/src/vorta/assets/UI/source_tab.py
+++ /dev/null
@@ -1,169 +0,0 @@
-from PyQt5 import uic
-from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
-from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
-from PyQt5 import QtCore
-from PyQt5.QtCore import QFileInfo
-from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
-import os
-
-uifile = get_asset('UI/sourcetab.ui')
-SourceUI, SourceBase = uic.loadUiType(uifile)
-
-
-class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
- updateThreads = []
-
- def __init__(self, parent=None):
- super().__init__(parent)
- self.setupUi(parent)
-
- header = self.sourceFilesWidget.horizontalHeader()
-
- header.setVisible(True)
- header.setSortIndicatorShown(1)
-
- header.setSectionResizeMode(0, QHeaderView.Stretch)
- header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
- header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
- header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
-
- self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
- self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
- self.sourceRemove.clicked.connect(self.source_remove)
- self.sourcesUpdate.clicked.connect(self.sources_update)
- self.paste.clicked.connect(self.paste_text)
- self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
- self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
- self.populate_from_profile()
-
- def set_path_info(self, path, data_size, files_count):
- items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
- # Conversion int->str->int needed because QT limits int to 32-bit
- data_size = int(data_size)
- files_count = int(files_count)
-
- for item in items:
- db_item = SourceFileModel.get(dir=path)
- if QFileInfo(path).isDir():
- self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
- db_item.path_isdir = True
- else:
- self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
- db_item.path_isdir = False
- self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
- self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
-
- db_item.dir_size = data_size
- db_item.dir_files_count = files_count
- db_item.save()
- # Remove thread from list when it's done
- for thrd in self.updateThreads:
- if thrd.objectName() == path:
- self.updateThreads.remove(thrd)
-
- def update_path_info(self, index_row):
- path = self.sourceFilesWidget.item(index_row, 0).text()
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("Calculating..."))
- getDir = FilePathInfoAsync(path)
- getDir.signal.connect(self.set_path_info)
- getDir.setObjectName(path)
- self.updateThreads.append(getDir) # this is ugly, is there a better way to keep the thread object?
- getDir.start()
-
- def add_source_to_table(self, source, update_data):
- index_row = self.sourceFilesWidget.rowCount()
- self.sourceFilesWidget.insertRow(index_row)
- item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row, 0, item_path)
- if update_data:
- self.update_path_info(index_row)
- else: # Use cached data from DB
- if source.dir_size < 0:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("N/A"))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("N/A"))
- else:
- if source.path_isdir:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
- else:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
-
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
-
- def populate_from_profile(self):
- profile = self.profile()
- self.excludePatternsField.textChanged.disconnect()
- self.excludeIfPresentField.textChanged.disconnect()
- self.sourceFilesWidget.setRowCount(0) # Clear rows
- self.excludePatternsField.clear()
- self.excludeIfPresentField.clear()
-
- for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
- self.add_source_to_table(source, False)
-
- self.excludePatternsField.appendPlainText(profile.exclude_patterns)
- self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
- self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
- self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
-
- def sources_update(self):
- for row in range(0, self.sourceFilesWidget.rowCount()):
- self.update_path_info(row) # Update data for each entry
-
- def source_add(self, want_folder):
- def receive():
- dirs = dialog.selectedFiles()
- for dir in dirs:
- new_source, created = SourceFileModel.get_or_create(dir=dir,
- dir_size=-1,
- dir_files_count=-1,
- path_isdir=False,
- profile=self.profile())
- if created:
- self.add_source_to_table(new_source, SettingsModel.get(key="get_srcpath_datasize").value)
- new_source.save()
-
- msg = self.tr("Choose directory to back up") if want_folder else self.tr("Choose file(s) to back up")
- dialog = choose_file_dialog(self, msg, want_folder=want_folder)
- dialog.open(receive)
-
- def source_remove(self):
- indexes = self.sourceFilesWidget.selectionModel().selectedRows()
- # sort indexes, starting with lowest
- indexes.sort()
- # remove each selected row, starting with highest index (otherways, higher indexes become invalid)
- for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
- db_item.delete_instance()
- self.sourceFilesWidget.removeRow(index.row())
-
- def save_exclude_patterns(self):
- profile = self.profile()
- profile.exclude_patterns = self.excludePatternsField.toPlainText()
- profile.save()
-
- def save_exclude_if_present(self):
- profile = self.profile()
- profile.exclude_if_present = self.excludeIfPresentField.toPlainText()
- profile.save()
-
- def paste_text(self):
- sources = QApplication.clipboard().text().splitlines()
- invalidSources = ""
- for source in sources:
- if len(source) > 0: # Ignore empty newlines
- if not os.path.exists(source):
- invalidSources = invalidSources + "\n" + source
- else:
- new_source, created = SourceFileModel.get_or_create(dir=source, profile=self.profile())
- if created:
- self.sourceFilesWidget.addItem(source)
- new_source.save()
-
- if len(invalidSources) != 0: # Check if any invalid paths
- msg = QMessageBox()
- msg.setText("Some of your sources are invalid:" + invalidSources)
- msg.exec()
From 99c7d8ce6722993ffc61a68b568f045ac6d56631 Mon Sep 17 00:00:00 2001
From: samuel-w
Date: Sun, 4 Oct 2020 02:52:27 -0500
Subject: [PATCH 36/64] Undelete version
---
src/vorta/__init__.py | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/vorta/__init__.py
diff --git a/src/vorta/__init__.py b/src/vorta/__init__.py
new file mode 100644
index 000000000..8dee4bf82
--- /dev/null
+++ b/src/vorta/__init__.py
@@ -0,0 +1 @@
+from ._version import __version__
From 5f8c42126650d20dec37c3ef9abda26b33738b57 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 7 Oct 2020 20:11:05 +0000
Subject: [PATCH 37/64] enabled sorting via sort indicator
Currently this is not working as intended when sorting on the "Size" column
---
src/vorta/views/source_tab.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 5f2793e0c..cd8dba55a 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -26,6 +26,7 @@ def __init__(self, parent=None):
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
+ header.sortIndicatorChanged.connect(self.sort_entries_by_column)
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
@@ -36,6 +37,9 @@ def __init__(self, parent=None):
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
+ def sort_entries_by_column(self, column_index, order):
+ self.sourceFilesWidget.model().sort(column_index, order)
+
def set_path_info(self, path, data_size, files_count):
items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
# Conversion int->str->int needed because QT limits int to 32-bit
@@ -108,6 +112,8 @@ def populate_from_profile(self):
for source in SourceFileModel.select().where(SourceFileModel.profile == profile):
self.add_source_to_table(source, False)
+ # Initially, sort entries by path name in ascending order
+ self.sourceFilesWidget.model().sort(0,QtCore.Qt.AscendingOrder)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
From cc0cd26eff919083eb267b68a25a4614a63cd9a0 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Thu, 8 Oct 2020 17:33:00 +0000
Subject: [PATCH 38/64] some cleanups
---
src/vorta/views/source_tab.py | 60 ++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 25 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index cd8dba55a..18f47320a 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -9,10 +9,16 @@
uifile = get_asset('UI/sourcetab.ui')
SourceUI, SourceBase = uic.loadUiType(uifile)
+class SourceColumn:
+ Path = 0
+ Type = 1
+ Size = 2
+ FilesCount = 3
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
+
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
@@ -22,10 +28,10 @@ def __init__(self, parent=None):
header.setVisible(True)
header.setSortIndicatorShown(1)
- header.setSectionResizeMode(0, QHeaderView.Stretch)
- header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
- header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
- header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(SourceColumn.Path, QHeaderView.Stretch)
+ header.setSectionResizeMode(SourceColumn.Type, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(SourceColumn.Size, QHeaderView.ResizeToContents)
+ header.setSectionResizeMode(SourceColumn.FilesCount, QHeaderView.ResizeToContents)
header.sortIndicatorChanged.connect(self.sort_entries_by_column)
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
@@ -38,7 +44,11 @@ def __init__(self, parent=None):
self.populate_from_profile()
def sort_entries_by_column(self, column_index, order):
- self.sourceFilesWidget.model().sort(column_index, order)
+ if column_index == SourceColumn.Size:
+ # todo change this
+ self.sourceFilesWidget.model().sort(column_index, order)
+ else:
+ self.sourceFilesWidget.model().sort(column_index, order)
def set_path_info(self, path, data_size, files_count):
items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
@@ -49,15 +59,15 @@ def set_path_info(self, path, data_size, files_count):
for item in items:
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
- self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("Folder"))
- self.sourceFilesWidget.item(item.row(), 3).setText(format(files_count))
+ self.sourceFilesWidget.setItem(item.row(), SourceColumn.Type, QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText(format(files_count))
db_item.path_isdir = True
else:
- self.sourceFilesWidget.setItem(item.row(), 1, QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(item.row(), SourceColumn.Type, QTableWidgetItem("File"))
# No files count, if entry itself is a file
- self.sourceFilesWidget.item(item.row(), 3).setText("")
+ self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText("")
db_item.path_isdir = False
- self.sourceFilesWidget.item(item.row(), 2).setText(pretty_bytes(data_size))
+ self.sourceFilesWidget.item(item.row(), SourceColumn.Size).setText(pretty_bytes(data_size))
db_item.dir_size = data_size
db_item.dir_files_count = files_count
@@ -68,10 +78,10 @@ def set_path_info(self, path, data_size, files_count):
self.updateThreads.remove(thrd)
def update_path_info(self, index_row):
- path = self.sourceFilesWidget.item(index_row, 0).text()
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem("Calculating..."))
+ path = self.sourceFilesWidget.item(index_row, SourceColumn.Path).text()
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem("Calculating..."))
getDir = FilePathInfoAsync(path)
getDir.signal.connect(self.set_path_info)
getDir.setObjectName(path)
@@ -82,24 +92,24 @@ def add_source_to_table(self, source, update_data):
index_row = self.sourceFilesWidget.rowCount()
self.sourceFilesWidget.insertRow(index_row)
item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row, 0, item_path)
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Path, item_path)
if update_data:
self.update_path_info(index_row)
else: # Use cached data from DB
if source.dir_size < 0:
# Size/count wasn't calculated yet
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(""))
else:
if source.path_isdir:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("Folder"))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(format(source.dir_files_count)))
else:
- self.sourceFilesWidget.setItem(index_row, 1, QTableWidgetItem("File"))
- self.sourceFilesWidget.setItem(index_row, 3, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("File"))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, 2, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem(pretty_bytes(source.dir_size)))
def populate_from_profile(self):
profile = self.profile()
@@ -113,7 +123,7 @@ def populate_from_profile(self):
self.add_source_to_table(source, False)
# Initially, sort entries by path name in ascending order
- self.sourceFilesWidget.model().sort(0,QtCore.Qt.AscendingOrder)
+ self.sourceFilesWidget.model().sort(SourceColumn.Path, QtCore.Qt.AscendingOrder)
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
self.excludePatternsField.textChanged.connect(self.save_exclude_patterns)
@@ -146,7 +156,7 @@ def source_remove(self):
indexes.sort()
# remove each selected row, starting with highest index (otherways, higher indexes become invalid)
for index in reversed(indexes):
- db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), 0).text())
+ db_item = SourceFileModel.get(dir=self.sourceFilesWidget.item(index.row(), SourceColumn.Path).text())
db_item.delete_instance()
self.sourceFilesWidget.removeRow(index.row())
From 2a3031bb1c0080db5c3d2e0e77d3e17f368e6f45 Mon Sep 17 00:00:00 2001
From: samuel-w
Date: Thu, 8 Oct 2020 14:08:01 -0500
Subject: [PATCH 39/64] Sort by file size
Sorting by file/folder count is broken
---
src/vorta/utils.py | 12 ++++++++++++
src/vorta/views/source_tab.py | 25 +++++++++++++------------
2 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 49198f457..452e0b01f 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -20,6 +20,7 @@
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
+from decimal import Decimal
from vorta.borg._compatibility import BorgCompatibility
from vorta.log import logger
@@ -149,6 +150,17 @@ def get_private_keys():
return available_private_keys
+def sort_sizes(size_list):
+ """ Sorts sizes with extensions. Assumes that size is already in largest unit possible """
+ final_list = []
+ for suffix in [" B", " KB", " MB", " GB", " TB"]:
+ sub_list = [Decimal(size[:-len(suffix)])
+ for size in size_list if size.endswith(suffix) and size[:-len(suffix)][-1].isnumeric()]
+ sub_list.sort()
+ final_list += [(str(size) + suffix) for size in sub_list]
+ return final_list
+
+
def pretty_bytes(size):
"""from https://stackoverflow.com/questions/12523586/
python-format-size-application-converting-b-to-kb-mb-gb-tb/37423778"""
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 18f47320a..f2f518a25 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -1,6 +1,6 @@
from PyQt5 import uic
from ..models import SourceFileModel, BackupProfileMixin, SettingsModel
-from ..utils import get_asset, choose_file_dialog, pretty_bytes, FilePathInfoAsync
+from ..utils import get_asset, choose_file_dialog, pretty_bytes, sort_sizes, FilePathInfoAsync
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo
from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QHeaderView
@@ -9,16 +9,22 @@
uifile = get_asset('UI/sourcetab.ui')
SourceUI, SourceBase = uic.loadUiType(uifile)
+
class SourceColumn:
Path = 0
Type = 1
Size = 2
FilesCount = 3
+
+class SizeItem(QTableWidgetItem):
+ def __lt__(self, other):
+ return sort_sizes([self.text(), other.text()]) != [self.text(), other.text()]
+
+
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
-
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
@@ -32,8 +38,8 @@ def __init__(self, parent=None):
header.setSectionResizeMode(SourceColumn.Type, QHeaderView.ResizeToContents)
header.setSectionResizeMode(SourceColumn.Size, QHeaderView.ResizeToContents)
header.setSectionResizeMode(SourceColumn.FilesCount, QHeaderView.ResizeToContents)
- header.sortIndicatorChanged.connect(self.sort_entries_by_column)
+ self.sourceFilesWidget.setSortingEnabled(True)
self.sourceAddFolder.clicked.connect(lambda: self.source_add(want_folder=True))
self.sourceAddFile.clicked.connect(lambda: self.source_add(want_folder=False))
self.sourceRemove.clicked.connect(self.source_remove)
@@ -43,13 +49,6 @@ def __init__(self, parent=None):
self.excludeIfPresentField.textChanged.connect(self.save_exclude_if_present)
self.populate_from_profile()
- def sort_entries_by_column(self, column_index, order):
- if column_index == SourceColumn.Size:
- # todo change this
- self.sourceFilesWidget.model().sort(column_index, order)
- else:
- self.sourceFilesWidget.model().sort(column_index, order)
-
def set_path_info(self, path, data_size, files_count):
items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
# Conversion int->str->int needed because QT limits int to 32-bit
@@ -104,12 +103,14 @@ def add_source_to_table(self, source, update_data):
else:
if source.path_isdir:
self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("Folder"))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount,
+ QTableWidgetItem(format(source.dir_files_count)))
else:
self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("File"))
self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Size,
+ SizeItem(pretty_bytes(source.dir_size)))
def populate_from_profile(self):
profile = self.profile()
From dbaab6755512ace0d0a28e128a323b95805220b9 Mon Sep 17 00:00:00 2001
From: samuel-w
Date: Thu, 8 Oct 2020 19:16:40 -0500
Subject: [PATCH 40/64] Fix
---
src/vorta/utils.py | 3 +++
src/vorta/views/source_tab.py | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 452e0b01f..6a38c6740 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -158,6 +158,9 @@ def sort_sizes(size_list):
for size in size_list if size.endswith(suffix) and size[:-len(suffix)][-1].isnumeric()]
sub_list.sort()
final_list += [(str(size) + suffix) for size in sub_list]
+ # Skip additional loops
+ if len(final_list) == len(size_list):
+ break
return final_list
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index f2f518a25..c8e7c5ed9 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -19,7 +19,7 @@ class SourceColumn:
class SizeItem(QTableWidgetItem):
def __lt__(self, other):
- return sort_sizes([self.text(), other.text()]) != [self.text(), other.text()]
+ return sort_sizes([self.text(), other.text()]) == [self.text(), other.text()]
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
From a0ca73700d35a68ea782a5b1eed1c725044efcdb Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 10 Oct 2020 20:37:46 +0000
Subject: [PATCH 41/64] Fixed sorting
---
src/vorta/views/source_tab.py | 52 +++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 21 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index c8e7c5ed9..47a181b91 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -22,6 +22,20 @@ def __lt__(self, other):
return sort_sizes([self.text(), other.text()]) == [self.text(), other.text()]
+class FilesCount(QTableWidgetItem):
+ def __lt__(self, other):
+ # Verify that conversion is only performed on valid integers
+ # If one of the 2 elements is no number, put these elements at the end
+ # This is important if the text i "Calculating..." or ""
+ if self.text().isdigit() and other.text().isdigit():
+ return int(self.text()) < int(other.text()) # Compare & return result
+ else:
+ if not self.text().isdigit():
+ return 1 # Move one down if current item has no valid count
+ if not other.text().isdigit():
+ return 0
+
+
class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
updateThreads = []
@@ -58,11 +72,11 @@ def set_path_info(self, path, data_size, files_count):
for item in items:
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
- self.sourceFilesWidget.setItem(item.row(), SourceColumn.Type, QTableWidgetItem("Folder"))
+ self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText("Folder")
self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText(format(files_count))
db_item.path_isdir = True
else:
- self.sourceFilesWidget.setItem(item.row(), SourceColumn.Type, QTableWidgetItem("File"))
+ self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText("File")
# No files count, if entry itself is a file
self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText("")
db_item.path_isdir = False
@@ -78,9 +92,9 @@ def set_path_info(self, path, data_size, files_count):
def update_path_info(self, index_row):
path = self.sourceFilesWidget.item(index_row, SourceColumn.Path).text()
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem("Calculating..."))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem("Calculating..."))
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Calculating...")
+ self.sourceFilesWidget.item(index_row, SourceColumn.Size).setText("Calculating...")
+ self.sourceFilesWidget.item(index_row, SourceColumn.FilesCount).setText("Calculating...")
getDir = FilePathInfoAsync(path)
getDir.signal.connect(self.set_path_info)
getDir.setObjectName(path)
@@ -90,27 +104,23 @@ def update_path_info(self, index_row):
def add_source_to_table(self, source, update_data):
index_row = self.sourceFilesWidget.rowCount()
self.sourceFilesWidget.insertRow(index_row)
- item_path = QTableWidgetItem(source.dir)
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Path, item_path)
+ # Insert all items on current row
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Path, QTableWidgetItem(source.dir))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, SizeItem(""))
+ self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, FilesCount(""))
+
if update_data:
self.update_path_info(index_row)
else: # Use cached data from DB
- if source.dir_size < 0:
- # Size/count wasn't calculated yet
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Size, QTableWidgetItem(""))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(""))
- else:
+ if source.dir_size > -1:
+ self.sourceFilesWidget.item(index_row, SourceColumn.Size).setText(pretty_bytes(source.dir_size))
+
if source.path_isdir:
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("Folder"))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount,
- QTableWidgetItem(format(source.dir_files_count)))
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Folder")
+ self.sourceFilesWidget.item(index_row, SourceColumn.FilesCount).setText(format(source.dir_files_count))
else:
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Type, QTableWidgetItem("File"))
- self.sourceFilesWidget.setItem(index_row, SourceColumn.FilesCount, QTableWidgetItem(""))
-
- self.sourceFilesWidget.setItem(index_row, SourceColumn.Size,
- SizeItem(pretty_bytes(source.dir_size)))
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("File")
def populate_from_profile(self):
profile = self.profile()
From d323eb156fb6ae39dc877e2a49afe0d5fc145e34 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sat, 10 Oct 2020 20:39:15 +0000
Subject: [PATCH 42/64] Changed command to get foldersize
As requested for Mac
---
src/vorta/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 6a38c6740..a66b13182 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -58,7 +58,7 @@ def get_directory_size(dirPath):
files_count = int(res.stdout.split(b'\t')[0])
if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
+ res = subprocess.run('du -s -b .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
data_size = int(res.stdout.split(b'\t')[0])
else:
From 84d3d7691430dfe73882efec3df6614747bb7a12 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 11 Oct 2020 09:01:20 +0000
Subject: [PATCH 43/64] GetFolderSize: Add different cmd for MacOS
---
src/vorta/utils.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index a66b13182..c0a4dc8de 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -58,8 +58,13 @@ def get_directory_size(dirPath):
files_count = int(res.stdout.split(b'\t')[0])
if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- res = subprocess.run('du -s -b .', cwd=dirPath, shell=True, check=False,
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+ if sys.platform == 'darwin':
+ res = subprocess.run('du -s -B 1 -A .', cwd=dirPath, shell=True, check=False,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+ else:
+ res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+
data_size = int(res.stdout.split(b'\t')[0])
else:
data_size = 0
From 955c45ddb78982349be57baa3d821f97522bdf3e Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 11 Oct 2020 09:02:00 +0000
Subject: [PATCH 44/64] fix lint
---
src/vorta/views/source_tab.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 47a181b91..0dc813779 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -28,10 +28,10 @@ def __lt__(self, other):
# If one of the 2 elements is no number, put these elements at the end
# This is important if the text i "Calculating..." or ""
if self.text().isdigit() and other.text().isdigit():
- return int(self.text()) < int(other.text()) # Compare & return result
+ return int(self.text()) < int(other.text()) # Compare & return result
else:
if not self.text().isdigit():
- return 1 # Move one down if current item has no valid count
+ return 1 # Move one down if current item has no valid count
if not other.text().isdigit():
return 0
@@ -118,7 +118,8 @@ def add_source_to_table(self, source, update_data):
if source.path_isdir:
self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Folder")
- self.sourceFilesWidget.item(index_row, SourceColumn.FilesCount).setText(format(source.dir_files_count))
+ self.sourceFilesWidget.item(index_row,
+ SourceColumn.FilesCount).setText(format(source.dir_files_count))
else:
self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("File")
From 53c916cd90ff3fe97ed9efd7b9db7285a424db43 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Sun, 11 Oct 2020 09:04:55 +0000
Subject: [PATCH 45/64] fix lint2
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 0dc813779..7b1ecdcb5 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -118,7 +118,7 @@ def add_source_to_table(self, source, update_data):
if source.path_isdir:
self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Folder")
- self.sourceFilesWidget.item(index_row,
+ self.sourceFilesWidget.item(index_row,
SourceColumn.FilesCount).setText(format(source.dir_files_count))
else:
self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("File")
From 2fa600ebe258763d4d8261cfcd33d19e7568dc03 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 12 Oct 2020 17:09:55 +0000
Subject: [PATCH 46/64] Change for Mac OS
Get folder size correctly on MacOS
---
src/vorta/utils.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index c0a4dc8de..54074f9af 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -61,11 +61,11 @@ def get_directory_size(dirPath):
if sys.platform == 'darwin':
res = subprocess.run('du -s -B 1 -A .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+ data_size = int(res.stdout.split())
else:
res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
-
- data_size = int(res.stdout.split(b'\t')[0])
+ data_size = int(res.stdout.split(b'\t')[0])
else:
data_size = 0
files_count = 0
From 78e5f19692559535ed948b5a667b805aad51a787 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 12 Oct 2020 17:11:59 +0000
Subject: [PATCH 47/64] Syntax corrected
---
src/vorta/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 54074f9af..c6affa1a1 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -61,7 +61,7 @@ def get_directory_size(dirPath):
if sys.platform == 'darwin':
res = subprocess.run('du -s -B 1 -A .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- data_size = int(res.stdout.split())
+ data_size = int(res.stdout.split()[0])
else:
res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
From 9776708489c8b37efee5e7745fe4d7ab301a640d Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 12 Oct 2020 17:12:31 +0000
Subject: [PATCH 48/64] typo
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 7b1ecdcb5..db6fa0d09 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -26,7 +26,7 @@ class FilesCount(QTableWidgetItem):
def __lt__(self, other):
# Verify that conversion is only performed on valid integers
# If one of the 2 elements is no number, put these elements at the end
- # This is important if the text i "Calculating..." or ""
+ # This is important if the text is "Calculating..." or ""
if self.text().isdigit() and other.text().isdigit():
return int(self.text()) < int(other.text()) # Compare & return result
else:
From 4f6bbff9e7c150912f43d3e701c7fa2ebc7dd237 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 13 Oct 2020 18:25:51 +0000
Subject: [PATCH 49/64] Changed get_directory_size
Implemented fallback for non-linux OS
---
src/vorta/utils.py | 47 +++++++++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index c6affa1a1..03c1bfb84 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -51,24 +51,41 @@ def run(self):
self.signal.emit(self.path, str(self.size), str(self.files_count))
-def get_directory_size(dirPath):
- res = subprocess.run('find . | wc -l', cwd=dirPath, shell=True, check=False,
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
-
- files_count = int(res.stdout.split(b'\t')[0])
-
- if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- if sys.platform == 'darwin':
- res = subprocess.run('du -s -B 1 -A .', cwd=dirPath, shell=True, check=False,
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- data_size = int(res.stdout.split()[0])
- else:
- res = subprocess.run('du -sb .', cwd=dirPath, shell=True, check=False,
+def get_directory_size(dir_path):
+ if sys.platform.startswith('linux'):
+ res = subprocess.run('find . | wc -l', cwd=dir_path, shell=True, check=False,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+ files_count = int(res.stdout.split(b'\t')[0])
+
+ if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
+ res = subprocess.run('du -sb .', cwd=dir_path, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
data_size = int(res.stdout.split(b'\t')[0])
- else:
+ else:
+ data_size = 0
+ files_count = 0
+ else: # Other platform than linux, use fallback to determine files count and data sizes
+ ''' Get number of files only and total size in bytes from a path.
+ Based off https://stackoverflow.com/a/17936789 '''
data_size = 0
- files_count = 0
+ seen = set()
+
+ for curr_path, _, file_names in os.walk(dir_path):
+ for file_name in file_names:
+ file_path = os.path.join(curr_path, file_name)
+
+ # Ignore symbolic links, since borg doesn't follow them
+ if os.path.islink(file_path):
+ continue
+
+ stat = os.stat(file_path)
+
+ # Visit each file once
+ if stat.st_ino not in seen:
+ seen.add(stat.st_ino)
+ data_size += stat.st_size
+
+ files_count = len(seen)
return data_size, files_count
From 79f7c411eaaea6be11695303132609b6815b1236 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 13 Oct 2020 18:29:38 +0000
Subject: [PATCH 50/64] fix lint
---
src/vorta/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 03c1bfb84..c56847675 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -65,7 +65,7 @@ def get_directory_size(dir_path):
data_size = 0
files_count = 0
else: # Other platform than linux, use fallback to determine files count and data sizes
- ''' Get number of files only and total size in bytes from a path.
+ ''' Get number of files only and total size in bytes from a path.
Based off https://stackoverflow.com/a/17936789 '''
data_size = 0
seen = set()
From 0e4614345bdc2b83875d0b1178e3eef2e490f7cb Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:51:15 +0000
Subject: [PATCH 51/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index db6fa0d09..87c55aeac 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -72,7 +72,7 @@ def set_path_info(self, path, data_size, files_count):
for item in items:
db_item = SourceFileModel.get(dir=path)
if QFileInfo(path).isDir():
- self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText("Folder")
+ self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText(self.tr("Folder"))
self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText(format(files_count))
db_item.path_isdir = True
else:
From 2fd8539b4c2cda3141fa1958b6c563df442112ba Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:51:27 +0000
Subject: [PATCH 52/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 87c55aeac..40fce3178 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -76,7 +76,7 @@ def set_path_info(self, path, data_size, files_count):
self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText(format(files_count))
db_item.path_isdir = True
else:
- self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText("File")
+ self.sourceFilesWidget.item(item.row(), SourceColumn.Type).setText(self.tr("File"))
# No files count, if entry itself is a file
self.sourceFilesWidget.item(item.row(), SourceColumn.FilesCount).setText("")
db_item.path_isdir = False
From 3cda2edd35d276a4e8c678fd909b3646a09a5776 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:51:37 +0000
Subject: [PATCH 53/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel
---
src/vorta/views/source_tab.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 40fce3178..9dcb20d96 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -92,9 +92,9 @@ def set_path_info(self, path, data_size, files_count):
def update_path_info(self, index_row):
path = self.sourceFilesWidget.item(index_row, SourceColumn.Path).text()
- self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Calculating...")
- self.sourceFilesWidget.item(index_row, SourceColumn.Size).setText("Calculating...")
- self.sourceFilesWidget.item(index_row, SourceColumn.FilesCount).setText("Calculating...")
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText(self.tr("Calculating..."))
+ self.sourceFilesWidget.item(index_row, SourceColumn.Size).setText(self.tr("Calculating..."))
+ self.sourceFilesWidget.item(index_row, SourceColumn.FilesCount).setText(self.tr("Calculating..."))
getDir = FilePathInfoAsync(path)
getDir.signal.connect(self.set_path_info)
getDir.setObjectName(path)
From 2dad3fb96cd6dea97002b37ec4b332d3afc2bf21 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:51:50 +0000
Subject: [PATCH 54/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index 9dcb20d96..e8383854c 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -117,7 +117,7 @@ def add_source_to_table(self, source, update_data):
self.sourceFilesWidget.item(index_row, SourceColumn.Size).setText(pretty_bytes(source.dir_size))
if source.path_isdir:
- self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("Folder")
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText(self.tr("Folder"))
self.sourceFilesWidget.item(index_row,
SourceColumn.FilesCount).setText(format(source.dir_files_count))
else:
From 629faeb9c6d0ef8d64756190e203c6a11a5c3a96 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:51:59 +0000
Subject: [PATCH 55/64] Update src/vorta/assets/UI/sourcetab.ui
Co-authored-by: Samuel
---
src/vorta/assets/UI/sourcetab.ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/assets/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui
index 0759ff2c7..2e7d20838 100644
--- a/src/vorta/assets/UI/sourcetab.ui
+++ b/src/vorta/assets/UI/sourcetab.ui
@@ -81,7 +81,7 @@
- File/Folder Count
+ File Count
From 6d9e8479dbabc489325a7dd852e676da8aaa8709 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:52:11 +0000
Subject: [PATCH 56/64] Update src/vorta/views/source_tab.py
Co-authored-by: Samuel
---
src/vorta/views/source_tab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py
index e8383854c..89096fc70 100644
--- a/src/vorta/views/source_tab.py
+++ b/src/vorta/views/source_tab.py
@@ -121,7 +121,7 @@ def add_source_to_table(self, source, update_data):
self.sourceFilesWidget.item(index_row,
SourceColumn.FilesCount).setText(format(source.dir_files_count))
else:
- self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText("File")
+ self.sourceFilesWidget.item(index_row, SourceColumn.Type).setText(self.tr("File"))
def populate_from_profile(self):
profile = self.profile()
From b0d00209fd6e0456f352a77ace697319b5653978 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 18:59:10 +0000
Subject: [PATCH 57/64] Use python method to get folder size
---
src/vorta/utils.py | 49 +++++++++++++++++-----------------------------
1 file changed, 18 insertions(+), 31 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index c56847675..e5aabad65 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -52,40 +52,27 @@ def run(self):
def get_directory_size(dir_path):
- if sys.platform.startswith('linux'):
- res = subprocess.run('find . | wc -l', cwd=dir_path, shell=True, check=False,
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- files_count = int(res.stdout.split(b'\t')[0])
-
- if files_count > 1: # files count on empty directory is still 1 because of '.', ignore it
- res = subprocess.run('du -sb .', cwd=dir_path, shell=True, check=False,
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- data_size = int(res.stdout.split(b'\t')[0])
- else:
- data_size = 0
- files_count = 0
- else: # Other platform than linux, use fallback to determine files count and data sizes
- ''' Get number of files only and total size in bytes from a path.
- Based off https://stackoverflow.com/a/17936789 '''
- data_size = 0
- seen = set()
-
- for curr_path, _, file_names in os.walk(dir_path):
- for file_name in file_names:
- file_path = os.path.join(curr_path, file_name)
-
- # Ignore symbolic links, since borg doesn't follow them
- if os.path.islink(file_path):
- continue
+ ''' Get number of files only and total size in bytes from a path.
+ Based off https://stackoverflow.com/a/17936789 '''
+ data_size = 0
+ seen = set()
+
+ for curr_path, _, file_names in os.walk(dir_path):
+ for file_name in file_names:
+ file_path = os.path.join(curr_path, file_name)
+
+ # Ignore symbolic links, since borg doesn't follow them
+ if os.path.islink(file_path):
+ continue
- stat = os.stat(file_path)
+ stat = os.stat(file_path)
- # Visit each file once
- if stat.st_ino not in seen:
- seen.add(stat.st_ino)
- data_size += stat.st_size
+ # Visit each file once
+ if stat.st_ino not in seen:
+ seen.add(stat.st_ino)
+ data_size += stat.st_size
- files_count = len(seen)
+ files_count = len(seen)
return data_size, files_count
From 8ed9ad96c20a3cd7e02bf4dc3c120344beea7cdd Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 14 Oct 2020 19:01:38 +0000
Subject: [PATCH 58/64] lint
---
src/vorta/utils.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index e5aabad65..9b759d618 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -7,7 +7,6 @@
import re
import sys
import unicodedata
-import subprocess
from collections import defaultdict
from datetime import datetime as dt
from functools import reduce
From 1c88285c41afdb581abeabeea1b88365cc8d8650 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 20 Oct 2020 17:46:11 +0000
Subject: [PATCH 59/64] Update src/vorta/models.py
Co-authored-by: Samuel
---
src/vorta/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 9996158e6..ac6ef79ef 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -221,7 +221,7 @@ def get_misc_settings():
{
'key': 'get_srcpath_datasize', 'value': True, 'type': 'checkbox',
'label': trans_late('settings',
- 'Get size of file/folder when added')
+ 'Get statistics of file/folder when added')
},
{
'key': 'previous_profile_id', 'str_value': '1', 'type': 'internal',
From 87d357aba63967f9cce79c51ac12f183168c69e9 Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 20 Oct 2020 17:46:25 +0000
Subject: [PATCH 60/64] Update src/vorta/utils.py
Co-authored-by: Samuel
---
src/vorta/utils.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 9b759d618..bcef0c1c3 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -28,7 +28,6 @@
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons
-network_status_monitor = NetworkStatusMonitor.get_network_status_monitor()
logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
borg_compat = BorgCompatibility()
From 1704e77a27fb5bdae1ef7d1b11dddbfbc3c13f0b Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Tue, 20 Oct 2020 17:46:37 +0000
Subject: [PATCH 61/64] Update src/vorta/utils.py
Co-authored-by: Samuel
---
src/vorta/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index bcef0c1c3..f202090cd 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -205,7 +205,7 @@ def get_sorted_wifis(profile):
from vorta.models import WifiSettingModel
- system_wifis = network_status_monitor.get_known_wifis()
+ system_wifis = get_network_status_monitor().get_known_wifis()
if system_wifis is None:
# Don't show any networks if we can't get the current list
return []
From 1f59399967a66db2a3ed8d04e2653edb7ffd2f4a Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Wed, 21 Oct 2020 11:30:37 +0000
Subject: [PATCH 62/64] Update src/vorta/utils.py
Co-authored-by: Samuel
---
src/vorta/utils.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index f202090cd..2fd236a31 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -28,8 +28,6 @@
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons
-logger.info('Using %s NetworkStatusMonitor implementation.', network_status_monitor.__class__.__name__)
-
borg_compat = BorgCompatibility()
_network_status_monitor = None
From 1753170df424faaaa921df618941cdcadd4b4bad Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 26 Oct 2020 14:47:35 +0000
Subject: [PATCH 63/64] Update src/vorta/utils.py
Co-authored-by: Samuel
---
src/vorta/utils.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 2fd236a31..d35a0e0c1 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -19,7 +19,6 @@
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
-from decimal import Decimal
from vorta.borg._compatibility import BorgCompatibility
from vorta.log import logger
From 790d9381623ccdbad58f2dcaaba558de6655e02e Mon Sep 17 00:00:00 2001
From: XXXBold <30773753+XXXBold@users.noreply.github.com>
Date: Mon, 26 Oct 2020 14:47:44 +0000
Subject: [PATCH 64/64] Update src/vorta/utils.py
Co-authored-by: Samuel
---
src/vorta/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index d35a0e0c1..c3ae92d57 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -158,7 +158,7 @@ def sort_sizes(size_list):
""" Sorts sizes with extensions. Assumes that size is already in largest unit possible """
final_list = []
for suffix in [" B", " KB", " MB", " GB", " TB"]:
- sub_list = [Decimal(size[:-len(suffix)])
+ sub_list = [float(size[:-len(suffix)])
for size in size_list if size.endswith(suffix) and size[:-len(suffix)][-1].isnumeric()]
sub_list.sort()
final_list += [(str(size) + suffix) for size in sub_list]