Hello community,

here is the log from the commit of package vorta for openSUSE:Factory checked 
in at 2020-05-28 09:13:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/vorta (Old)
 and      /work/SRC/openSUSE:Factory/.vorta.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "vorta"

Thu May 28 09:13:42 2020 rev:8 rq:809083 version:0.6.26

Changes:
--------
--- /work/SRC/openSUSE:Factory/vorta/vorta.changes      2020-05-19 
14:47:13.991909952 +0200
+++ /work/SRC/openSUSE:Factory/.vorta.new.3606/vorta.changes    2020-05-28 
09:14:07.948681217 +0200
@@ -1,0 +2,9 @@
+Tue May 26 07:09:27 UTC 2020 - Antonio Larrosa <[email protected]>
+
+- Update to version 0.6.26
+  * Fixes some issues when no known Wifis are available on macOS.
+  * Starts with the correct window size for high-res displays on Linux.
+  * Test- and linting fixes.
+- Version 0.6.25 wasn't released by upstream.
+
+-------------------------------------------------------------------

Old:
----
  v0.6.24.tar.gz

New:
----
  v0.6.26.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ vorta.spec ++++++
--- /var/tmp/diff_new_pack.Zgmgc0/_old  2020-05-28 09:14:10.408681885 +0200
+++ /var/tmp/diff_new_pack.Zgmgc0/_new  2020-05-28 09:14:10.412681887 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           vorta
-Version:        0.6.24
+Version:        0.6.26
 Release:        0
 Summary:        Desktop Backup Client based on BorgBackup
 License:        GPL-3.0-only

++++++ v0.6.24.tar.gz -> v0.6.26.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/.bumpversion.cfg 
new/vorta-0.6.26/.bumpversion.cfg
--- old/vorta-0.6.24/.bumpversion.cfg   2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/.bumpversion.cfg   2020-05-26 05:30:06.000000000 +0200
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.6.24
+current_version = 0.6.26
 tag = True
 
 [bumpversion:file:Makefile]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/Makefile new/vorta-0.6.26/Makefile
--- old/vorta-0.6.24/Makefile   2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/Makefile   2020-05-26 05:30:06.000000000 +0200
@@ -29,8 +29,8 @@
        sh package/macos-package-app.sh
 
 github-release: dist/Vorta.dmg
-       cp dist/Vorta.dmg dist/dist/vorta-0.6.24.dmg
-       hub release create --attach=dist/vorta-0.6.24.dmg v0.6.24
+       cp dist/Vorta.dmg dist/dist/vorta-0.6.26.dmg
+       hub release create --attach=dist/vorta-0.6.26.dmg v0.6.26
        git checkout gh-pages
        git commit -m 'rebuild pages' --allow-empty
        git push upstream gh-pages
@@ -38,7 +38,7 @@
 
 pypi-release: translations-to-qm
        python setup.py sdist
-       twine upload dist/vorta-0.6.24.tar.gz
+       twine upload dist/vorta-0.6.26.tar.gz
 
 bump-version:  ## Add new version tag and push to upstream repo.
        bumpversion patch
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/setup.cfg new/vorta-0.6.26/setup.cfg
--- old/vorta-0.6.24/setup.cfg  2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/setup.cfg  2020-05-26 05:30:06.000000000 +0200
@@ -2,7 +2,7 @@
 name = vorta
 author = Manuel Riel
 description = A GUI for BorgBackup
-version = 0.6.24
+version = 0.6.26
 url = https://github.com/borgbase/vorta
 keywords =
   backup
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/_version.py 
new/vorta-0.6.26/src/vorta/_version.py
--- old/vorta-0.6.24/src/vorta/_version.py      2020-03-03 06:29:20.000000000 
+0100
+++ new/vorta-0.6.26/src/vorta/_version.py      2020-05-26 05:30:06.000000000 
+0200
@@ -1 +1 @@
-__version__ = '0.6.24'
+__version__ = '0.6.26'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vorta-0.6.24/src/vorta/assets/icons/scalable/com.borgbase.Vorta.svg 
new/vorta-0.6.26/src/vorta/assets/icons/scalable/com.borgbase.Vorta.svg
--- old/vorta-0.6.24/src/vorta/assets/icons/scalable/com.borgbase.Vorta.svg     
2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/assets/icons/scalable/com.borgbase.Vorta.svg     
2020-05-26 05:30:06.000000000 +0200
@@ -1 +1,77 @@
-<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 576 
384"><defs><style>.cls-1{fill:#515151;}.cls-2{fill:#e65100;}.cls-3{fill:#ff9800;}</style></defs><title>vorta</title><path
 class="cls-1" 
d="M586.52,335.52v96a48,48,0,0,1-48,48h-480a48,48,0,0,1-48-48v-96a48,48,0,0,1,48-48h480A48,48,0,0,1,586.52,335.52Zm-48-80a79.47,79.47,0,0,1,30.77,6.16L472.77,116.89a48,48,0,0,0-39.94-21.37H164.2a48,48,0,0,0-39.93,21.37L27.74,261.68a79.52,79.52,0,0,1,30.78-6.16Zm-48,96a32,32,0,1,0,32,32A32,32,0,0,0,490.52,351.52Zm-96,0a32,32,0,1,0,32,32A32,32,0,0,0,394.52,351.52Z"
 transform="translate(-10.52 -95.52)"/><circle class="cls-2" cx="384.5" 
cy="288" r="32"/><circle class="cls-3" cx="480" cy="288" r="32"/></svg>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   id="Layer_1"
+   data-name="Layer 1"
+   viewBox="0 0 576 576"
+   version="1.1"
+   sodipodi:docname="com.borgbase.Vorta.svg"
+   width="576"
+   height="576"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14">
+  <metadata
+     id="metadata17">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title>vorta</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1600"
+     inkscape:window-height="836"
+     id="namedview15"
+     showgrid="false"
+     inkscape:zoom="0.61458333"
+     inkscape:cx="291.25424"
+     inkscape:cy="192"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="Layer_1" />
+  <defs
+     id="defs4">
+    <style
+       
id="style2">.cls-1{fill:#515151;}.cls-2{fill:#e65100;}.cls-3{fill:#ff9800;}</style>
+  </defs>
+  <title
+     id="title6">vorta</title>
+  <path
+     class="cls-1"
+     d="m 576,342 v 96 a 48,48 0 0 1 -48,48 H 48 A 48,48 0 0 1 0,438 v -96 a 
48,48 0 0 1 48,-48 h 480 a 48,48 0 0 1 48,48 z m -48,-80 a 79.47,79.47 0 0 1 
30.77,6.16 L 462.25,123.37 A 48,48 0 0 0 422.31,102 H 153.68 a 48,48 0 0 0 
-39.93,21.37 L 17.22,268.16 A 79.52,79.52 0 0 1 48,262 Z m -48,96 a 32,32 0 1 0 
32,32 32,32 0 0 0 -32,-32 z m -96,0 a 32,32 0 1 0 32,32 32,32 0 0 0 -32,-32 z"
+     id="path8"
+     inkscape:connector-curvature="0"
+     style="fill:#515151" />
+  <circle
+     class="cls-2"
+     cx="384.5"
+     cy="390"
+     r="32"
+     id="circle10"
+     style="fill:#e65100" />
+  <circle
+     class="cls-3"
+     cx="480"
+     cy="390"
+     r="32"
+     id="circle12"
+     style="fill:#ff9800" />
+</svg>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vorta-0.6.24/src/vorta/assets/metadata/com.borgbase.Vorta.appdata.xml 
new/vorta-0.6.26/src/vorta/assets/metadata/com.borgbase.Vorta.appdata.xml
--- old/vorta-0.6.24/src/vorta/assets/metadata/com.borgbase.Vorta.appdata.xml   
2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/assets/metadata/com.borgbase.Vorta.appdata.xml   
2020-05-26 05:30:06.000000000 +0200
@@ -4,7 +4,9 @@
   <name>Vorta</name>
   <project_license>GPL-3.0</project_license>
   <metadata_license>CC0-1.0</metadata_license>
-  <content_rating type="oars-1.1"/>
+  <content_rating type="oars-1.1">
+    <content_attribute id="money-purchasing">mild</content_attribute>
+  </content_rating>
   <summary>Backup client</summary>
   <description>
     <p>
@@ -38,7 +40,7 @@
     </screenshot>
   </screenshots>
   <releases>
-    <release version="v0.6.24" date="2020-03-03">
+    <release version="v0.6.26" date="2020-05-26">
     </release>
   </releases>
   <url type="bugtracker">https://github.com/borgbase/vorta/issues</url>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vorta-0.6.24/src/vorta/assets/metadata/com.borgbase.Vorta.desktop 
new/vorta-0.6.26/src/vorta/assets/metadata/com.borgbase.Vorta.desktop
--- old/vorta-0.6.24/src/vorta/assets/metadata/com.borgbase.Vorta.desktop       
2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/assets/metadata/com.borgbase.Vorta.desktop       
2020-05-26 05:30:06.000000000 +0200
@@ -5,3 +5,4 @@
 Type=Application
 Icon=com.borgbase.Vorta
 Categories=Utility
+StartupWMClass=vorta
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/borg/borg_thread.py 
new/vorta-0.6.26/src/vorta/borg/borg_thread.py
--- old/vorta-0.6.24/src/vorta/borg/borg_thread.py      2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/borg/borg_thread.py      2020-05-26 
05:30:06.000000000 +0200
@@ -234,7 +234,7 @@
     def cancel(self):
         if self.isRunning():
             mutex.unlock()
-            os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
+            self.process.send_signal(signal.SIGINT)
             self.terminate()
 
     def process_result(self, result):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/utils.py 
new/vorta-0.6.26/src/vorta/utils.py
--- old/vorta-0.6.24/src/vorta/utils.py 2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/utils.py 2020-05-26 05:30:06.000000000 +0200
@@ -27,6 +27,9 @@
 from vorta.keyring.abc import VortaKeyring
 from vorta.log import logger
 
+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__)
 
@@ -102,7 +105,12 @@
     while size >= power:
         size /= power
         n += 1
-    return f'{round(size, 1)} {Dic_powerN[n]}B'
+    try:
+        unit = Dic_powerN[n]
+        return f'{round(size, 1)} {unit}B'
+    except KeyError as e:
+        logger.error(e)
+        return "NaN"
 
 
 def get_asset(path):
@@ -128,12 +136,16 @@
             wifis = plistlib.load(plist_file).get('KnownNetworks')
         except xml.parsers.expat.ExpatError:
             logger.error('Unable to parse list of Wifi networks.')
-            return
+            return []
 
         if wifis is not None:
             for wifi in wifis.values():
                 timestamp = wifi.get('LastConnected', None)
-                ssid = wifi['SSIDString']
+                ssid = wifi.get('SSIDString', None)
+
+                if ssid is None:
+                    continue
+
                 db_wifi, created = WifiSettingModel.get_or_create(
                     ssid=ssid,
                     profile=profile.id,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/archive_tab.py 
new/vorta-0.6.26/src/vorta/views/archive_tab.py
--- old/vorta-0.6.24/src/vorta/views/archive_tab.py     2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/archive_tab.py     2020-05-26 
05:30:06.000000000 +0200
@@ -76,6 +76,8 @@
 
         self.populate_from_profile()
 
+        self.selected_archives = None
+
     def _set_status(self, text):
         self.mountErrors.setText(text)
         self.mountErrors.repaint()
@@ -429,9 +431,10 @@
         window.show()
 
         if window.exec_():
-            selected_archives = window.selected_archives
-            archive_cell_newer = self.archiveTable.item(selected_archives[0], 
4)
-            archive_cell_older = self.archiveTable.item(selected_archives[1], 
4)
+            if window.selected_archives:
+                self.selected_archives = window.selected_archives
+            archive_cell_newer = 
self.archiveTable.item(self.selected_archives[0], 4)
+            archive_cell_older = 
self.archiveTable.item(self.selected_archives[1], 4)
             if archive_cell_older and archive_cell_newer:
                 archive_name_newer = archive_cell_newer.text()
                 archive_name_older = archive_cell_older.text()
@@ -457,5 +460,5 @@
             window = DiffResult(result['data'], archive_newer, archive_older)
             self._toggle_all_buttons(True)
             window.setParent(self, QtCore.Qt.Sheet)
-            self._window = window  # for testing
+            self._resultwindow = window  # for testing
             window.show()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/diff_dialog.py 
new/vorta-0.6.26/src/vorta/views/diff_dialog.py
--- old/vorta-0.6.24/src/vorta/views/diff_dialog.py     2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/diff_dialog.py     2020-05-26 
05:30:06.000000000 +0200
@@ -3,12 +3,11 @@
 
 from vorta.utils import get_asset
 
-uifile = get_asset('UI/diffdialog.ui')
+uifile = get_asset("UI/diffdialog.ui")
 DiffDialogUI, DiffDialogBase = uic.loadUiType(uifile)
 
 
 class DiffDialog(DiffDialogBase, DiffDialogUI):
-
     def __init__(self, archiveTable):
         super().__init__()
         self.setupUi(self)
@@ -38,7 +37,7 @@
                     text = archiveTable.item(row, column).text()
                     self.archiveTable.setItem(row, column, 
QTableWidgetItem(text))
                 except AttributeError:
-                    self.archiveTable.setItem(row, column, 
QTableWidgetItem(''))
+                    self.archiveTable.setItem(row, column, 
QTableWidgetItem(""))
 
         self.diffButton.setEnabled(False)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/diff_result.py 
new/vorta-0.6.26/src/vorta/views/diff_result.py
--- old/vorta-0.6.24/src/vorta/views/diff_result.py     2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/diff_result.py     2020-05-26 
05:30:06.000000000 +0200
@@ -1,34 +1,28 @@
 import os
+import re
 
 from PyQt5 import uic
-from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant
+from PyQt5.QtCore import Qt, QVariant
 from PyQt5.QtGui import QColor
 from PyQt5.QtWidgets import QHeaderView
 
-from vorta.utils import (get_asset, get_dict_from_list, nested_dict,
-                         pretty_bytes)
+from vorta.utils import (get_asset, get_dict_from_list, nested_dict)
+
+from vorta.views.tree_view import TreeModel
 
 uifile = get_asset('UI/diffresult.ui')
 DiffResultUI, DiffResultBase = uic.loadUiType(uifile)
 
-files_with_attributes = None
-nested_file_list = None
-selected_files_folders = None
-
 
 class DiffResult(DiffResultBase, DiffResultUI):
     def __init__(self, fs_data, archive_newer, archive_older):
         super().__init__()
         self.setupUi(self)
-        global files_with_attributes, nested_file_list, selected_files_folders
 
-        # Clear global file lists
         files_with_attributes = []
         nested_file_list = nested_dict()
-        selected_files_folders = set()
 
         def parse_line(line):
-
             if line:
                 line_split = line.split()
             else:
@@ -36,59 +30,48 @@
 
             if line_split[0] == 'added' or line_split[0] == 'removed':
                 change_type = line_split[0]
-                size = line_split[1]
-                unit = line_split[2]
+                if line_split[1] in ['directory', 'link']:
+                    size = 0
+                    full_path = re.search(r'^\w+ \w+ +(.*)', line).group(1)
+                else:
+                    significand = line_split[1]
+                    unit = line_split[2]
+                    size = calc_size(significand, unit)
+                    full_path = re.search(r'^\w+ +\S+ \w?B (.*)', 
line).group(1)
             else:
-                change_type = "modified"
-                size = line_split[0]
-                unit = line_split[1]
-                # If present remove '+' or '-' sign at the front
-                if size[0] in ('+', '-'):
-                    size = size[1:]
-
-            if line_split[0].startswith("["):
-                size = 0
-                change_type = line[:line.find(line_split[3])]
-                full_path = line[line.find(line_split[3]):]
-                dir, name = os.path.split(full_path)
-                # add to nested dict of folders to find nested dirs.
-                d = get_dict_from_list(nested_file_list, full_path.split('/'))
-            elif line_split[1] not in ['directory', 'link']:
-                if unit == 'B':
-                    size = int(size)
-                elif unit == 'kB':
-                    size = int(float(size) * 10**3)
-                elif unit == 'MB':
-                    size = int(float(size) * 10**6)
-                elif unit == 'GB':
-                    size = int(float(size) * 10**9)
-                elif unit == 'TB':
-                    size = int(float(size) * 10**12)
-
-                if change_type == 'added' or change_type == 'removed':
-                    full_path = line[line.find(line_split[3]):]
-                elif change_type == "modified":
-                    full_path = line[line.find(line_split[4]):]
-
-                dir, name = os.path.split(full_path)
-                # add to nested dict of folders to find nested dirs.
-                d = get_dict_from_list(nested_file_list, dir.split('/'))
-                if name not in d:
-                    d[name] = {}
-            else:
-                size = 0
-                full_path = line[line.find(line_split[2]):]
-
-                dir, name = os.path.split(full_path)
-                # add to nested dict of folders to find nested dirs.
-                d = get_dict_from_list(nested_file_list, full_path.split('/'))
+                size_change = re.search(r' *[\+-]?(\d+\.*\d*) (\w?B) 
+[\+-]?.+\w?B ', line)
+                if size_change:
+                    significand = size_change.group(1)
+                    unit = size_change.group(2)
+                    size = calc_size(significand, unit)
+                    full_path_index = size_change.end(0)
+                else:
+                    size = 0
+
+                permission_change = re.search(r' *(\[.{24}\]) ', line)
+                if permission_change:
+                    change_type = permission_change.group(1)
+                    full_path_index = permission_change.end(0)
+                else:
+                    change_type = "modified"
+
+                if size_change and permission_change:
+                    full_path_index = max(size_change.end(0), 
permission_change.end(0))
+                full_path = line[full_path_index:]
+
+            dir, name = os.path.split(full_path)
+
+            # add to nested dict of folders to find nested dirs.
+            d = get_dict_from_list(nested_file_list, dir.split('/'))
+            if name not in d:
+                d[name] = {}
 
             return size, change_type, name, dir
 
-        for l in fs_data.split('\n'):
-            files_with_attributes.append(parse_line(l))
+        for line in fs_data.split('\n'):
+            files_with_attributes.append(parse_line(line))
 
-        model = TreeModel()
+        model = DiffTree(files_with_attributes, nested_file_list)
 
         view = self.treeView
         view.setAlternatingRowColors(True)
@@ -103,113 +86,31 @@
         self.archiveNameLabel_1.setText(f'{archive_newer.name}')
         self.archiveNameLabel_2.setText(f'{archive_older.name}')
         self.okButton.clicked.connect(self.accept)
-        self.selected = selected_files_folders
-
-
-class FolderItem:
-    def __init__(self, path, name, modified, parent=None):
-        self.parentItem = parent
-        self.path = path
-        self.itemData = [name, modified]
-        self.childItems = []
-
-        # Pre-filter children
-        self._filtered_children = []
-        search_path = os.path.join(self.path, name)
-        if parent is None:  # Find path for root folder
-            for root_folder in nested_file_list.keys():
-                self._filtered_children.append((0, '', root_folder, '', ))
-        else:
-
-            # This adds direct children.
-            self._filtered_children = [f for f in files_with_attributes if 
search_path == f[3]]
-
-            # Add nested folders.
-            for immediate_child in get_dict_from_list(nested_file_list, 
search_path.split('/')).keys():
-                if not [True for child in self._filtered_children if child[2] 
== immediate_child]:
-                    self._filtered_children.append((0, '', immediate_child, 
search_path))
-
-        self.is_loaded = False
-
-    def load_children(self):
-        for child_item in self._filtered_children:
-            if child_item[0] > 0:  # This is a file
-                self.childItems.append(FileItem(
-                    name=child_item[2],
-                    modified=child_item[1],
-                    size=child_item[0],
-                    parent=self))
-            else:  # Folder
-                self.childItems.append(
-                    FolderItem(
-                        path=child_item[3],
-                        name=child_item[2],
-                        modified=child_item[1],
-                        parent=self))
-        self.is_loaded = True
-
-    def child(self, row):
-        return self.childItems[row]
-
-    def childCount(self):
-        return len(self._filtered_children)
-
-    def columnCount(self):
-        return 3
-
-    def data(self, column):
-        if column <= 1:
-            return self.itemData[column]
-        else:
-            return None
-
-    def parent(self):
-        return self.parentItem
-
-    def row(self):
-        if self.parentItem:
-            return self.parentItem.childItems.index(self)
-
-        return 0
-
-
-class FileItem(FolderItem):
-    def __init__(self, name, modified, size, parent=None):
-        self.parentItem = parent
-        self.itemData = [name, modified, size]
-
-    def childCount(self):
-        return 0
-
-    def columnCount(self):
-        return 3
-
-    def data(self, column):
-        if column == 1:
-            return self.itemData[column]
-        elif column == 2:
-            return pretty_bytes(self.itemData[column])
-        elif column == 0:
-            return self.itemData[column]
-
-    def parent(self):
-        return self.parentItem
-
-    def row(self):
-        return self.parentItem.childItems.index(self)
 
 
-class TreeModel(QAbstractItemModel):
-    column_names = ['Name', 'Modified', 'Size']
-
-    def __init__(self, parent=None):
-        super(TreeModel, self).__init__(parent)
-
-        self.rootItem = FolderItem(path='', name='', modified=None)
-        self.rootItem.load_children()
-
-    def columnCount(self, parent):
-        return 3
+def calc_size(significand, unit):
+    if unit == 'B':
+        return int(significand)
+    elif unit == 'kB':
+        return int(float(significand) * 10**3)
+    elif unit == 'MB':
+        return int(float(significand) * 10**6)
+    elif unit == 'GB':
+        return int(float(significand) * 10**9)
+    elif unit == 'TB':
+        return int(float(significand) * 10**12)
+
+
+class DiffTree(TreeModel):
+    def __init__(
+        self,
+        files_with_attributes,
+        nested_file_list,
+        parent=None,
+    ):
+        super().__init__(
+            files_with_attributes, nested_file_list, parent=parent
+        )
 
     def data(self, index, role):
         if not index.isValid():
@@ -230,61 +131,7 @@
         else:
             return None
 
-    def canFetchMore(self, index):
-        if not index.isValid():
-            return False
-        item = index.internalPointer()
-        return not item.is_loaded
-
-    def fetchMore(self, index):
-        item = index.internalPointer()
-        item.load_children()
-
     def flags(self, index):
         if not index.isValid():
             return Qt.NoItemFlags
         return Qt.ItemIsEnabled
-
-    def headerData(self, section, orientation, role):
-        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
-            return self.column_names[section]
-
-        return None
-
-    def index(self, row, column, parent):
-        if not self.hasIndex(row, column, parent):
-            return QModelIndex()
-
-        if not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        childItem = parentItem.child(row)
-        if childItem:
-            return self.createIndex(row, column, childItem)
-        else:
-            return QModelIndex()
-
-    def parent(self, index):
-        if not index.isValid():
-            return QModelIndex()
-
-        childItem = index.internalPointer()
-        parentItem = childItem.parent()
-
-        if parentItem == self.rootItem:
-            return QModelIndex()
-
-        return self.createIndex(parentItem.row(), 0, parentItem)
-
-    def rowCount(self, parent):
-        if parent.column() > 0:
-            return 0
-
-        if not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        return parentItem.childCount()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/extract_dialog.py 
new/vorta-0.6.26/src/vorta/views/extract_dialog.py
--- old/vorta-0.6.24/src/vorta/views/extract_dialog.py  2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/extract_dialog.py  2020-05-26 
05:30:06.000000000 +0200
@@ -4,50 +4,45 @@
 from collections import namedtuple
 
 from PyQt5 import uic
-from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
+from PyQt5.QtCore import Qt
 from PyQt5.QtWidgets import QApplication, QHeaderView
 
-from vorta.utils import get_asset, pretty_bytes, get_dict_from_list, 
nested_dict
+from vorta.utils import get_asset, get_dict_from_list, nested_dict
+from vorta.views.tree_view import TreeModel
 
-uifile = get_asset('UI/extractdialog.ui')
+uifile = get_asset("UI/extractdialog.ui")
 ExtractDialogUI, ExtractDialogBase = uic.loadUiType(uifile)
-ISO_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
-
-files_with_attributes = None
-nested_file_list = None
-selected_files_folders = None
+ISO_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
 
 
 class ExtractDialog(ExtractDialogBase, ExtractDialogUI):
     def __init__(self, fs_data, archive):
         super().__init__()
         self.setupUi(self)
-        global files_with_attributes, nested_file_list, selected_files_folders
 
-        # Clear global file lists
         files_with_attributes = []
         nested_file_list = nested_dict()
-        selected_files_folders = set()
+        self.selected = set()
 
         def parse_line(line):
-            size, modified, full_path = line.split('\t')
+            size, modified, full_path = line.split("\t")
             size = int(size)
             dir, name = os.path.split(full_path)
 
             # add to nested dict of folders to find nested dirs.
-            d = get_dict_from_list(nested_file_list, dir.split('/'))
+            d = get_dict_from_list(nested_file_list, dir.split("/"))
             if name not in d:
                 d[name] = {}
 
             return size, modified, name, dir
 
-        for l in fs_data.split('\n'):
+        for line in fs_data.split("\n"):
             try:
-                files_with_attributes.append(parse_line(l))
+                files_with_attributes.append(parse_line(line))
             except ValueError:
                 pass
 
-        model = TreeModel()
+        model = ExtractTree(files_with_attributes, nested_file_list, 
self.selected)
 
         view = self.treeView
         view.setAlternatingRowColors(True)
@@ -59,141 +54,22 @@
         header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
         header.setSectionResizeMode(0, QHeaderView.Stretch)
 
-        self.archiveNameLabel.setText(f'{archive.name}, {archive.time}')
+        self.archiveNameLabel.setText(f"{archive.name}, {archive.time}")
         self.cancelButton.clicked.connect(self.close)
         self.extractButton.clicked.connect(self.accept)
-        self.selected = selected_files_folders
-
-
-class FolderItem:
-    def __init__(self, path, name, modified, parent=None):
-        self.parentItem = parent
-        self.path = path
-        self.itemData = [name, modified]
-        self.childItems = []
-        self.checkedState = False
-
-        # Pre-filter children
-        self._filtered_children = []
-        search_path = os.path.join(self.path, name)
-        if parent is None:  # Find path for root folder
-            for root_folder in nested_file_list.keys():
-                self._filtered_children.append((0, '', root_folder, '', ))
-        else:
-            self.checkedState = parent.checkedState  # If there is a parent, 
use its checked-status.
-
-            # This adds direct children.
-            self._filtered_children = [f for f in files_with_attributes if 
search_path == f[3]]
-
-            # Add nested folders.
-            for immediate_child in get_dict_from_list(nested_file_list, 
search_path.split('/')).keys():
-                if not [True for child in self._filtered_children if child[2] 
== immediate_child]:
-                    self._filtered_children.append((0, '', immediate_child, 
search_path))
-
-        self.is_loaded = False
-
-    def load_children(self):
-        for child_item in self._filtered_children:
-            if child_item[0] > 0:  # This is a file
-                self.childItems.append(FileItem(
-                    name=child_item[2],
-                    modified=child_item[1],
-                    size=child_item[0],
-                    parent=self))
-            else:  # Folder
-                self.childItems.append(
-                    FolderItem(
-                        path=child_item[3],
-                        name=child_item[2],
-                        modified=child_item[1],
-                        parent=self))
-
-        self.is_loaded = True
-
-    def setCheckedState(self, value):
-        if value == 2:
-            self.checkedState = True
-            selected_files_folders.add(
-                os.path.join(self.parentItem.path, self.parentItem.data(0), 
self.itemData[0]))
-        else:
-            self.checkedState = False
-            path_to_remove = os.path.join(self.parentItem.path, 
self.parentItem.data(0), self.itemData[0])
-            if path_to_remove in selected_files_folders:
-                selected_files_folders.remove(path_to_remove)
-
-        if hasattr(self, 'childItems'):
-            for child in self.childItems:
-                child.setCheckedState(value)
-
-    def getCheckedState(self):
-        if self.checkedState:
-            return Qt.Checked
-        else:
-            return Qt.Unchecked
-
-    def child(self, row):
-        return self.childItems[row]
-
-    def childCount(self):
-        return len(self._filtered_children)
-
-    def columnCount(self):
-        return 3
-
-    def data(self, column):
-        if column <= 1:
-            return self.itemData[column]
-        else:
-            return None
-
-    def parent(self):
-        return self.parentItem
-
-    def row(self):
-        if self.parentItem:
-            return self.parentItem.childItems.index(self)
-
-        return 0
-
-
-class FileItem(FolderItem):
-    def __init__(self, name, modified, size, parent=None):
-        self.parentItem = parent
-        self.itemData = [name, modified, size]  # dt.strptime(modified, 
ISO_FORMAT)
-        self.checkedState = parent.checkedState
-
-    def childCount(self):
-        return 0
-
-    def columnCount(self):
-        return 3
-
-    def data(self, column):
-        if column == 1:
-            return self.itemData[column]  # .strftime('%Y-%m-%dT%H:%M')
-        elif column == 2:
-            return pretty_bytes(self.itemData[column])
-        elif column == 0:
-            return self.itemData[column]
-
-    def parent(self):
-        return self.parentItem
-
-    def row(self):
-        return self.parentItem.childItems.index(self)
 
 
-class TreeModel(QAbstractItemModel):
-    column_names = ['Name', 'Modified', 'Size']
-
-    def __init__(self, parent=None):
-        super(TreeModel, self).__init__(parent)
-
-        self.rootItem = FolderItem(path='', name='', modified=None)
-        self.rootItem.load_children()
-
-    def columnCount(self, parent):
-        return 3
+class ExtractTree(TreeModel):
+    def __init__(
+        self,
+        files_with_attributes,
+        nested_file_list,
+        selected_files_folders,
+        parent=None,
+    ):
+        super().__init__(
+            files_with_attributes, nested_file_list, selected_files_folders, 
parent
+        )
 
     def data(self, index, role):
         if not index.isValid():
@@ -208,86 +84,24 @@
         else:
             return None
 
-    def setData(self, index, value, role=Qt.EditRole):
-        if role == Qt.CheckStateRole:
-            item = index.internalPointer()
-            item.setCheckedState(value)
-            self.dataChanged.emit(QModelIndex(), QModelIndex(), [])
-
-        return True
-
-    def canFetchMore(self, index):
-        if not index.isValid():
-            return False
-        item = index.internalPointer()
-        return not item.is_loaded
-
-    def fetchMore(self, index):
-        item = index.internalPointer()
-        item.load_children()
-
     def flags(self, index):
         if not index.isValid():
             return Qt.NoItemFlags
 
         return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable
 
-    def headerData(self, section, orientation, role):
-        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
-            return self.column_names[section]
-
-        return None
-
-    def index(self, row, column, parent):
-        if not self.hasIndex(row, column, parent):
-            return QModelIndex()
-
-        if not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        childItem = parentItem.child(row)
-        if childItem:
-            return self.createIndex(row, column, childItem)
-        else:
-            return QModelIndex()
-
-    def parent(self, index):
-        if not index.isValid():
-            return QModelIndex()
-
-        childItem = index.internalPointer()
-        parentItem = childItem.parent()
-
-        if parentItem == self.rootItem:
-            return QModelIndex()
-
-        return self.createIndex(parentItem.row(), 0, parentItem)
-
-    def rowCount(self, parent):
-        if parent.column() > 0:
-            return 0
-
-        if not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        return parentItem.childCount()
-
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     """
     For local testing:
 
     borg list --progress --info --log-json 
--format="{size:8d}{TAB}{mtime}{TAB}{path}{NL}"
     """
-    FakeArchive = namedtuple('Archive', ['name', 'time'])
+    FakeArchive = namedtuple("Archive", ["name", "time"])
     app = QApplication(sys.argv)
-    test_list = open('/Users/manu/Downloads/nyx2-list.txt').read()
+    test_list = open("/Users/manu/Downloads/nyx2-list.txt").read()
 
-    archive = FakeArchive('test-archive', datetime.datetime.now())
+    archive = FakeArchive("test-archive", datetime.datetime.now())
     view = ExtractDialog(test_list, archive)
     view.show()
     sys.exit(app.exec_())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/main_window.py 
new/vorta-0.6.26/src/vorta/views/main_window.py
--- old/vorta-0.6.24/src/vorta/views/main_window.py     2020-03-03 
06:29:20.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/main_window.py     2020-05-26 
05:30:06.000000000 +0200
@@ -1,12 +1,12 @@
 import sys
 
 from PyQt5 import QtCore, uic
+from PyQt5.QtWidgets import QShortcut, QMessageBox
 from PyQt5.QtGui import QKeySequence
-from PyQt5.QtWidgets import QMessageBox, QShortcut
 
 from vorta.borg.borg_thread import BorgThread
 from vorta.i18n import trans_late
-from vorta.models import BackupProfileModel
+from vorta.models import BackupProfileModel, SettingsModel
 from vorta.utils import borg_compat, get_asset, is_system_tray_available
 from vorta.views.utils import get_theme_class
 
@@ -31,6 +31,20 @@
         self.current_profile = 
BackupProfileModel.select().order_by('id').first()
         self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | 
QtCore.Qt.WindowMinimizeButtonHint)
 
+        # Temporary fix for QT Darkstyle dropdown issue.
+        # See https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/200
+        if SettingsModel.get(key='use_dark_theme').value:
+            self.setStyleSheet("""
+            QComboBox::item:checked {
+            height: 12px;
+            border: 1px solid #32414B;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            padding: 4px;
+            padding-left: 0px;
+            }
+            """)
+
         # Load tab models
         self.repoTab = RepoTab(self.repoTabSlot)
         self.sourceTab = SourceTab(self.sourceTabSlot)
@@ -114,12 +128,17 @@
 
             # Remove pending background jobs
             to_delete_id = str(to_delete.id)
-            if self.app.scheduler.get_job(to_delete_id):
-                self.app.scheduler.remove_job(to_delete_id)
-
-            to_delete.delete_instance(recursive=True)
-            
self.profileSelector.removeItem(self.profileSelector.currentIndex())
-            self.profile_select_action(0)
+            msg = self.tr("Are you sure you want to delete profile 
'{}'?".format(to_delete.name))
+            reply = QMessageBox.question(self, self.tr("Confirm deletion"),
+                                         msg, QMessageBox.Yes | 
QMessageBox.No, QMessageBox.No)
+
+            if reply == QMessageBox.Yes:
+                if self.app.scheduler.get_job(to_delete_id):
+                    self.app.scheduler.remove_job(to_delete_id)
+
+                to_delete.delete_instance(recursive=True)
+                
self.profileSelector.removeItem(self.profileSelector.currentIndex())
+                self.profile_select_action(0)
 
     def profile_add_action(self):
         window = AddProfileWindow()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/src/vorta/views/tree_view.py 
new/vorta-0.6.26/src/vorta/views/tree_view.py
--- old/vorta-0.6.24/src/vorta/views/tree_view.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/vorta-0.6.26/src/vorta/views/tree_view.py       2020-05-26 
05:30:06.000000000 +0200
@@ -0,0 +1,273 @@
+from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
+
+import os
+import abc
+
+from vorta.utils import get_dict_from_list, pretty_bytes
+
+
+class FolderItem:
+    def __init__(
+        self,
+        path,
+        name,
+        modified,
+        files_with_attributes,
+        nested_file_list,
+        selected_files_folders=None,
+        parent=None,
+    ):
+        self.parentItem = parent
+        self.path = path
+        self.itemData = [name, modified]
+        self.childItems = []
+        self.checkedState = False
+        self.files_with_attributes = files_with_attributes
+        self.nested_file_list = nested_file_list
+        self.selected_files_folders = selected_files_folders
+
+        # Pre-filter children
+        self._filtered_children = []
+        search_path = os.path.join(self.path, name)
+        if parent is None:  # Find path for root folder
+            for root_folder in nested_file_list.keys():
+                self._filtered_children.append((0, "", root_folder, "",))
+        else:
+            self.checkedState = (
+                parent.checkedState
+            )  # If there is a parent, use its checked-status.
+
+            # This adds direct children.
+            self._filtered_children = [
+                f for f in files_with_attributes if search_path == f[3]
+            ]
+
+            # Add nested folders.
+            for immediate_child in get_dict_from_list(
+                nested_file_list, search_path.split("/")
+            ).keys():
+                if not [
+                    True
+                    for child in self._filtered_children
+                    if child[2] == immediate_child
+                ]:
+                    self._filtered_children.append(
+                        (0, "", immediate_child, search_path)
+                    )
+
+        self.is_loaded = False
+
+    def load_children(self):
+        for child_item in self._filtered_children:
+            if child_item[0] > 0:  # This is a file
+                self.childItems.append(
+                    FileItem(
+                        name=child_item[2],
+                        modified=child_item[1],
+                        size=child_item[0],
+                        files_with_attributes=self.files_with_attributes,
+                        nested_file_list=self.nested_file_list,
+                        selected_files_folders=self.selected_files_folders,
+                        parent=self,
+                    )
+                )
+            else:  # Folder
+                self.childItems.append(
+                    FolderItem(
+                        path=child_item[3],
+                        name=child_item[2],
+                        modified=child_item[1],
+                        files_with_attributes=self.files_with_attributes,
+                        nested_file_list=self.nested_file_list,
+                        selected_files_folders=self.selected_files_folders,
+                        parent=self,
+                    )
+                )
+        self.is_loaded = True
+
+    def setCheckedState(self, value):
+        if value == 2:
+            self.checkedState = True
+            self.selected_files_folders.add(
+                os.path.join(
+                    self.parentItem.path, self.parentItem.data(0), 
self.itemData[0]
+                )
+            )
+        else:
+            self.checkedState = False
+            path_to_remove = os.path.join(
+                self.parentItem.path, self.parentItem.data(0), self.itemData[0]
+            )
+            if path_to_remove in self.selected_files_folders:
+                self.selected_files_folders.remove(path_to_remove)
+
+        if hasattr(self, "childItems"):
+            for child in self.childItems:
+                child.setCheckedState(value)
+
+    def getCheckedState(self):
+        if self.checkedState:
+            return Qt.Checked
+        else:
+            return Qt.Unchecked
+
+    def child(self, row):
+        return self.childItems[row]
+
+    def childCount(self):
+        return len(self._filtered_children)
+
+    def columnCount(self):
+        return 3
+
+    def data(self, column):
+        if column <= 1:
+            return self.itemData[column]
+        else:
+            return None
+
+    def parent(self):
+        return self.parentItem
+
+    def row(self):
+        if self.parentItem:
+            return self.parentItem.childItems.index(self)
+
+        return 0
+
+
+class FileItem(FolderItem):
+    def __init__(
+        self,
+        name,
+        modified,
+        size,
+        files_with_attributes,
+        nested_file_list,
+        selected_files_folders=None,
+        parent=None,
+    ):
+        self.parentItem = parent
+        self.itemData = [name, modified, size]
+        self.checkedState = parent.checkedState
+        self.files_with_attributes = files_with_attributes
+        self.nested_file_list = nested_file_list
+        self.selected_files_folders = selected_files_folders
+
+    def childCount(self):
+        return 0
+
+    def columnCount(self):
+        return 3
+
+    def data(self, column):
+        if column == 1:
+            return self.itemData[column]
+        elif column == 2:
+            return pretty_bytes(self.itemData[column])
+        elif column == 0:
+            return self.itemData[column]
+
+    def parent(self):
+        return self.parentItem
+
+    def row(self):
+        return self.parentItem.childItems.index(self)
+
+
+class TreeModel(QAbstractItemModel):
+    __metaclass__ = abc.ABCMeta
+
+    column_names = ["Name", "Modified", "Size"]
+
+    def __init__(
+        self,
+        files_with_attributes,
+        nested_file_list,
+        selected_files_folders=None,
+        parent=None,
+    ):
+        super(TreeModel, self).__init__(parent)
+
+        self.rootItem = FolderItem(
+            path="",
+            name="",
+            files_with_attributes=files_with_attributes,
+            nested_file_list=nested_file_list,
+            selected_files_folders=selected_files_folders,
+            modified=None,
+        )
+        self.rootItem.load_children()
+
+    def columnCount(self, parent):
+        return 3
+
+    @abc.abstractmethod
+    def data(self, index, role):
+        return
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if role == Qt.CheckStateRole:
+            item = index.internalPointer()
+            item.setCheckedState(value)
+            self.dataChanged.emit(QModelIndex(), QModelIndex(), [])
+
+        return True
+
+    def canFetchMore(self, index):
+        if not index.isValid():
+            return False
+        item = index.internalPointer()
+        return not item.is_loaded
+
+    def fetchMore(self, index):
+        item = index.internalPointer()
+        item.load_children()
+
+    @abc.abstractmethod
+    def flags(self, index):
+        return
+
+    def headerData(self, section, orientation, role):
+        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
+            return self.column_names[section]
+
+        return None
+
+    def index(self, row, column, parent):
+        if not self.hasIndex(row, column, parent):
+            return QModelIndex()
+
+        if not parent.isValid():
+            parentItem = self.rootItem
+        else:
+            parentItem = parent.internalPointer()
+
+        childItem = parentItem.child(row)
+        if childItem:
+            return self.createIndex(row, column, childItem)
+        else:
+            return QModelIndex()
+
+    def parent(self, index):
+        if not index.isValid():
+            return QModelIndex()
+
+        childItem = index.internalPointer()
+        parentItem = childItem.parent()
+
+        if parentItem == self.rootItem:
+            return QModelIndex()
+
+        return self.createIndex(parentItem.row(), 0, parentItem)
+
+    def rowCount(self, parent):
+        if parent.column() > 0:
+            return 0
+
+        if not parent.isValid():
+            parentItem = self.rootItem
+        else:
+            parentItem = parent.internalPointer()
+
+        return parentItem.childCount()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vorta-0.6.24/tests/borg_json_output/diff_archives_stdout.json 
new/vorta-0.6.26/tests/borg_json_output/diff_archives_stdout.json
--- old/vorta-0.6.24/tests/borg_json_output/diff_archives_stdout.json   
1970-01-01 01:00:00.000000000 +0100
+++ new/vorta-0.6.26/tests/borg_json_output/diff_archives_stdout.json   
2020-05-26 05:30:06.000000000 +0200
@@ -0,0 +1,2 @@
+     +7 B       0 B [-rw-rw-r-- -> -rw-rw-rw-] test/hallo
+added           0 B test/tschüss
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/tests/conftest.py 
new/vorta-0.6.26/tests/conftest.py
--- old/vorta-0.6.24/tests/conftest.py  2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/tests/conftest.py  2020-05-26 05:30:06.000000000 +0200
@@ -32,6 +32,9 @@
     test_archive = ArchiveModel(snapshot_id='99999', name='test-archive', 
time=dt(2000, 1, 1, 0, 0), repo=1)
     test_archive.save()
 
+    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.save()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/tests/test_archives.py 
new/vorta-0.6.26/tests/test_archives.py
--- old/vorta-0.6.24/tests/test_archives.py     2020-03-03 06:29:20.000000000 
+0100
+++ new/vorta-0.6.26/tests/test_archives.py     2020-05-26 05:30:06.000000000 
+0200
@@ -101,12 +101,10 @@
     )
 
     qtbot.mouseClick(tab.mountButton, QtCore.Qt.LeftButton)
-    qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Mounted'), 
timeout=5000)
+    qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Mounted'), 
timeout=10000)
 
     qtbot.mouseClick(tab.mountButton, QtCore.Qt.LeftButton)
-    # qtbot.waitUntil(lambda: tab.mountErrors.text() == 'No active Borg mounts 
found.')
-
-    qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Un-mounted 
successfully.'), timeout=5000)
+    qtbot.waitUntil(lambda: tab.mountErrors.text().startswith('Un-mounted 
successfully.'), timeout=10000)
 
 
 def test_archive_extract(qapp, qtbot, mocker, borg_json_output, monkeypatch):
@@ -115,7 +113,7 @@
     main.tabWidget.setCurrentIndex(3)
 
     tab.populate_from_profile()
-    qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 1)
+    qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2)
 
     monkeypatch.setattr(
         vorta.views.extract_dialog.ExtractDialog, "exec_", lambda *args: True
@@ -127,10 +125,43 @@
     mocker.patch.object(vorta.borg.borg_thread, 'Popen', 
return_value=popen_result)
     qtbot.mouseClick(tab.extractButton, QtCore.Qt.LeftButton)
 
-    qtbot.waitUntil(lambda: hasattr(tab, '_window'), timeout=5000)
+    qtbot.waitUntil(lambda: hasattr(tab, '_window'), timeout=10000)
 
     assert tab._window.treeView.model().rootItem.childItems[0].data(0) == 
'Users'
     tab._window.treeView.model().rootItem.childItems[0].load_children()
-
     assert tab._window.archiveNameLabel.text().startswith('test-archive, 2000')
-    tab._window.accept()
+
+
+def test_archive_diff(qapp, qtbot, mocker, borg_json_output, monkeypatch):
+    main = qapp.main_window
+    tab = main.archiveTab
+    main.tabWidget.setCurrentIndex(3)
+
+    tab.populate_from_profile()
+    qtbot.waitUntil(lambda: tab.archiveTable.rowCount() == 2)
+
+    monkeypatch.setattr(
+        vorta.views.diff_dialog.DiffDialog, "exec_", lambda *args: True
+    )
+
+    monkeypatch.setattr(
+        tab, "selected_archives", (0, 1)
+    )
+
+    stdout, stderr = borg_json_output('diff_archives')
+    popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
+    mocker.patch.object(vorta.borg.borg_thread, 'Popen', 
return_value=popen_result)
+
+    qtbot.mouseClick(tab.diffButton, QtCore.Qt.LeftButton)
+    qtbot.waitUntil(lambda: hasattr(tab, '_window'), timeout=5000)
+
+    monkeypatch.setattr(
+        vorta.views.diff_result.DiffResult, "exec_", lambda *args: True
+    )
+    qtbot.waitUntil(lambda: hasattr(tab, '_resultwindow'), timeout=5000)
+
+    assert tab._resultwindow.treeView.model().rootItem.childItems[0].data(0) 
== 'test'
+    tab._resultwindow.treeView.model().rootItem.childItems[0].load_children()
+
+    assert tab._resultwindow.archiveNameLabel_1.text() == 'test-archive'
+    tab._resultwindow.accept()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vorta-0.6.24/tests/test_repo.py 
new/vorta-0.6.26/tests/test_repo.py
--- old/vorta-0.6.24/tests/test_repo.py 2020-03-03 06:29:20.000000000 +0100
+++ new/vorta-0.6.26/tests/test_repo.py 2020-05-26 05:30:06.000000000 +0200
@@ -101,8 +101,8 @@
     qtbot.waitUntil(lambda: main.createProgressText.text().startswith('Backup 
finished.'), timeout=3000)
     qtbot.waitUntil(lambda: main.createStartBtn.isEnabled(), timeout=3000)
     assert EventLogModel.select().count() == 1
-    assert ArchiveModel.select().count() == 2
+    assert ArchiveModel.select().count() == 3
     assert RepoModel.get(id=1).unique_size == 15520474
     assert main.createStartBtn.isEnabled()
-    assert main.archiveTab.archiveTable.rowCount() == 2
+    assert main.archiveTab.archiveTable.rowCount() == 3
     assert main.scheduleTab.logTableWidget.rowCount() == 1


Reply via email to