mirror of
https://github.com/borgbase/vorta
synced 2025-02-27 08:32:34 +00:00
Replace peewee_migrate with native solution. Fix window activation.
This commit is contained in:
parent
8bf2c54c38
commit
3a5eafd061
18 changed files with 246 additions and 222 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@ __pycache__
|
|||
Makefile
|
||||
.eggs
|
||||
vorta.egg-info
|
||||
.coverage
|
||||
|
|
14
README.md
14
README.md
|
@ -19,9 +19,9 @@ Missing features: (PRs welcome)
|
|||
|
||||
- [ ] Repo pruning
|
||||
- [ ] Repo checking
|
||||
- [ ] Full test coverage
|
||||
- [ ] Use static type checks via mypy
|
||||
- [ ] Packaging for Linux
|
||||
- [ ] Full test coverage (currently: 65%)
|
||||
- [ ] Use static type checks via mypy?
|
||||
- [ ] Packaging for Linux? How?
|
||||
|
||||
## Installation and Download
|
||||
### macOS
|
||||
|
@ -55,8 +55,6 @@ $ brew cask install qt-creator
|
|||
$ brew install qt
|
||||
```
|
||||
|
||||
[Peewee Migrate](https://github.com/klen/peewee_migrate) is used to manage database migrations. Add them to the `vorta.migrations` package.
|
||||
|
||||
To build a binary package:
|
||||
```
|
||||
$ pyinstaller --clean --noconfirm vorta.spec
|
||||
|
@ -68,6 +66,12 @@ Tests are in the folder `/tests`. Testing happens at the level of UI components.
|
|||
$ pytest
|
||||
```
|
||||
|
||||
To update and view coverage information
|
||||
```
|
||||
$ coverage run -m pytest
|
||||
$ coverage report
|
||||
```
|
||||
|
||||
## Privacy Policy
|
||||
- No personal data is ever stored or transmitted by this application.
|
||||
- During beta, crash reports are sent to [Sentry](https://sentry.io) to quickly find bugs.
|
||||
|
|
|
@ -41,7 +41,6 @@ install_requires =
|
|||
python-dateutil
|
||||
keyring
|
||||
borgbackup
|
||||
peewee_migrate
|
||||
|
||||
[options.extras_require]
|
||||
tests =
|
||||
|
@ -51,6 +50,7 @@ tests =
|
|||
pytest-faulthandler
|
||||
mypy
|
||||
mypy-extensions
|
||||
coverage
|
||||
|
||||
[options.entry_points]
|
||||
gui_scripts =
|
||||
|
@ -64,4 +64,7 @@ qt_default_raising = true
|
|||
filterwarnings =
|
||||
ignore::DeprecationWarning
|
||||
|
||||
[coverage:run]
|
||||
source = src
|
||||
|
||||
[tox:tox]
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import peewee
|
||||
|
||||
import vorta.models
|
||||
import vorta.migrations
|
||||
from vorta.application import VortaApp
|
||||
from vorta.config import SETTINGS_DIR
|
||||
|
||||
|
@ -16,10 +15,5 @@
|
|||
sqlite_db = peewee.SqliteDatabase(os.path.join(SETTINGS_DIR, 'settings.db'))
|
||||
vorta.models.init_db(sqlite_db)
|
||||
|
||||
# Run migrations
|
||||
from peewee_migrate.cli import get_router
|
||||
router = get_router(os.path.dirname(vorta.migrations.__file__), sqlite_db, True)
|
||||
router.run()
|
||||
|
||||
app = VortaApp(sys.argv)
|
||||
sys.exit(app.exec_())
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
|
||||
import os
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
|
@ -47,8 +47,8 @@ def create_backup(self):
|
|||
return msg
|
||||
|
||||
def on_open_main_window(self):
|
||||
self.main_window = MainWindow(self)
|
||||
self.main_window.show()
|
||||
self.main_window.raise_()
|
||||
|
||||
def create_backup_result(self, result):
|
||||
self.backup_done.emit()
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>801</width>
|
||||
<height>561</height>
|
||||
<height>571</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
|
@ -154,6 +154,11 @@
|
|||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="createProgressText">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>SSH account with Borg installed server-side. Also try <a href="https://www.borgbase.com"><span style=" text-decoration: underline; color:#0000ff;">BorgBase.</span></a> 100GB free during Beta.</p></body></html></string>
|
||||
<string><html><head/><body><p>SSH account with Borg installed server-side. Also try <a href="https://www.borgbase.com?utm_source=vorta"><span style=" text-decoration: underline; color:#0000ff;">BorgBase</span></a>. 100GB free during Beta.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -47,6 +47,16 @@
|
|||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import appdirs
|
||||
import os
|
||||
import shutil
|
||||
|
||||
APP_NAME = 'Vorta'
|
||||
APP_AUTHOR = 'BorgBase'
|
||||
|
@ -8,6 +7,3 @@
|
|||
|
||||
if not os.path.exists(SETTINGS_DIR):
|
||||
os.makedirs(SETTINGS_DIR)
|
||||
|
||||
def remove_config():
|
||||
shutil.rmtree(SETTINGS_DIR)
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
"""Peewee migrations -- 001_add-snapshot-size.py.
|
||||
|
||||
Some examples (model - class or model name)::
|
||||
|
||||
> Model = migrator.orm['model_name'] # Return model in current state by name
|
||||
|
||||
> migrator.sql(sql) # Run custom SQL
|
||||
> migrator.python(func, *args, **kwargs) # Run python code
|
||||
> migrator.create_model(Model) # Create a model (could be used as decorator)
|
||||
> migrator.remove_model(model, cascade=True) # Remove a model
|
||||
> migrator.add_fields(model, **fields) # Add fields to a model
|
||||
> migrator.change_fields(model, **fields) # Change fields
|
||||
> migrator.remove_fields(model, *field_names, cascade=True)
|
||||
> migrator.rename_field(model, old_field_name, new_field_name)
|
||||
> migrator.rename_table(model, new_table_name)
|
||||
> migrator.add_index(model, *col_names, unique=False)
|
||||
> migrator.drop_index(model, *col_names)
|
||||
> migrator.add_not_null(model, *field_names)
|
||||
> migrator.drop_not_null(model, *field_names)
|
||||
> migrator.add_default(model, field_name, default)
|
||||
|
||||
"""
|
||||
|
||||
import peewee as pw
|
||||
from vorta.models import *
|
||||
|
||||
SQL = pw.SQL
|
||||
|
||||
|
||||
def migrate(migrator, database, fake=False, **kwargs):
|
||||
migrator.add_fields(SnapshotModel, duration=pw.FloatField(null=True))
|
||||
migrator.add_fields(SnapshotModel, size=pw.IntegerField(null=True))
|
||||
|
||||
|
||||
|
||||
def rollback(migrator, database, fake=False, **kwargs):
|
||||
"""Write your rollback migrations here."""
|
||||
|
|
@ -1,11 +1,20 @@
|
|||
import peewee
|
||||
"""
|
||||
This module provides the app's data store using Peewee with SQLite.
|
||||
|
||||
At the bottom there is a simple schema migration system.
|
||||
"""
|
||||
|
||||
import peewee as pw
|
||||
import json
|
||||
from datetime import datetime
|
||||
from playhouse.migrate import SqliteMigrator, migrate
|
||||
|
||||
db = peewee.Proxy()
|
||||
SCHEMA_VERSION = 4
|
||||
|
||||
db = pw.Proxy()
|
||||
|
||||
|
||||
class JSONField(peewee.TextField):
|
||||
class JSONField(pw.TextField):
|
||||
"""
|
||||
Class to "fake" a JSON field with a text field. Not efficient but works nicely
|
||||
|
||||
|
@ -21,65 +30,65 @@ def python_value(self, value):
|
|||
|
||||
|
||||
|
||||
class RepoModel(peewee.Model):
|
||||
class RepoModel(pw.Model):
|
||||
"""A single remote repo with unique URL."""
|
||||
url = peewee.CharField(unique=True)
|
||||
added_at = peewee.DateTimeField(default=datetime.utcnow)
|
||||
encryption = peewee.CharField(null=True)
|
||||
unique_size = peewee.IntegerField(null=True)
|
||||
unique_csize = peewee.IntegerField(null=True)
|
||||
total_size = peewee.IntegerField(null=True)
|
||||
total_unique_chunks = peewee.IntegerField(null=True)
|
||||
url = pw.CharField(unique=True)
|
||||
added_at = pw.DateTimeField(default=datetime.utcnow)
|
||||
encryption = pw.CharField(null=True)
|
||||
unique_size = pw.IntegerField(null=True)
|
||||
unique_csize = pw.IntegerField(null=True)
|
||||
total_size = pw.IntegerField(null=True)
|
||||
total_unique_chunks = pw.IntegerField(null=True)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class BackupProfileModel(peewee.Model):
|
||||
class BackupProfileModel(pw.Model):
|
||||
"""Allows the user to switch between different configurations."""
|
||||
name = peewee.CharField()
|
||||
added_at = peewee.DateTimeField(default=datetime.now)
|
||||
repo = peewee.ForeignKeyField(RepoModel, default=None, null=True)
|
||||
ssh_key = peewee.CharField(default=None, null=True)
|
||||
compression = peewee.CharField(default='lz4')
|
||||
exclude_patterns = peewee.TextField(null=True)
|
||||
exclude_if_present = peewee.TextField(null=True)
|
||||
schedule_mode = peewee.CharField(default='off')
|
||||
schedule_interval_hours = peewee.IntegerField(default=3)
|
||||
schedule_interval_minutes = peewee.IntegerField(default=42)
|
||||
schedule_fixed_hour = peewee.IntegerField(default=3)
|
||||
schedule_fixed_minute = peewee.IntegerField(default=42)
|
||||
validation_on = peewee.BooleanField(default=True)
|
||||
validation_weeks = peewee.IntegerField(default=3)
|
||||
prune_on = peewee.BooleanField(default=False)
|
||||
prune_hour = peewee.IntegerField(default=2)
|
||||
prune_day = peewee.IntegerField(default=7)
|
||||
prune_week = peewee.IntegerField(default=4)
|
||||
prune_month = peewee.IntegerField(default=6)
|
||||
prune_year = peewee.IntegerField(default=2)
|
||||
name = pw.CharField()
|
||||
added_at = pw.DateTimeField(default=datetime.now)
|
||||
repo = pw.ForeignKeyField(RepoModel, default=None, null=True)
|
||||
ssh_key = pw.CharField(default=None, null=True)
|
||||
compression = pw.CharField(default='lz4')
|
||||
exclude_patterns = pw.TextField(null=True)
|
||||
exclude_if_present = pw.TextField(null=True)
|
||||
schedule_mode = pw.CharField(default='off')
|
||||
schedule_interval_hours = pw.IntegerField(default=3)
|
||||
schedule_interval_minutes = pw.IntegerField(default=42)
|
||||
schedule_fixed_hour = pw.IntegerField(default=3)
|
||||
schedule_fixed_minute = pw.IntegerField(default=42)
|
||||
validation_on = pw.BooleanField(default=True)
|
||||
validation_weeks = pw.IntegerField(default=3)
|
||||
prune_on = pw.BooleanField(default=False)
|
||||
prune_hour = pw.IntegerField(default=2)
|
||||
prune_day = pw.IntegerField(default=7)
|
||||
prune_week = pw.IntegerField(default=4)
|
||||
prune_month = pw.IntegerField(default=6)
|
||||
prune_year = pw.IntegerField(default=2)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class SourceDirModel(peewee.Model):
|
||||
class SourceDirModel(pw.Model):
|
||||
"""A folder to be backed up, related to a Backup Configuration."""
|
||||
dir = peewee.CharField()
|
||||
config = peewee.ForeignKeyField(BackupProfileModel, default=1)
|
||||
added_at = peewee.DateTimeField(default=datetime.utcnow)
|
||||
dir = pw.CharField()
|
||||
config = pw.ForeignKeyField(BackupProfileModel, default=1)
|
||||
added_at = pw.DateTimeField(default=datetime.utcnow)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class SnapshotModel(peewee.Model):
|
||||
class SnapshotModel(pw.Model):
|
||||
"""A snapshot to a specific remote repository."""
|
||||
snapshot_id = peewee.CharField(unique=True)
|
||||
name = peewee.CharField()
|
||||
repo = peewee.ForeignKeyField(RepoModel, backref='snapshots')
|
||||
time = peewee.DateTimeField()
|
||||
duration = peewee.FloatField(null=True)
|
||||
size = peewee.IntegerField(null=True)
|
||||
snapshot_id = pw.CharField(unique=True)
|
||||
name = pw.CharField()
|
||||
repo = pw.ForeignKeyField(RepoModel, backref='snapshots')
|
||||
time = pw.DateTimeField()
|
||||
duration = pw.FloatField(null=True)
|
||||
size = pw.IntegerField(null=True)
|
||||
|
||||
def formatted_time(self):
|
||||
return
|
||||
|
@ -88,26 +97,35 @@ class Meta:
|
|||
database = db
|
||||
|
||||
|
||||
class WifiSettingModel(peewee.Model):
|
||||
class WifiSettingModel(pw.Model):
|
||||
"""Save Wifi Settings"""
|
||||
ssid = peewee.CharField()
|
||||
last_connected = peewee.DateTimeField()
|
||||
allowed = peewee.BooleanField(default=True)
|
||||
profile = peewee.ForeignKeyField(BackupProfileModel, default=1)
|
||||
ssid = pw.CharField()
|
||||
last_connected = pw.DateTimeField()
|
||||
allowed = pw.BooleanField(default=True)
|
||||
profile = pw.ForeignKeyField(BackupProfileModel, default=1)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class EventLogModel(peewee.Model):
|
||||
class EventLogModel(pw.Model):
|
||||
"""Keep a log of background jobs."""
|
||||
start_time = peewee.DateTimeField(default=datetime.now)
|
||||
category = peewee.CharField()
|
||||
subcommand = peewee.CharField(null=True)
|
||||
message = peewee.CharField(null=True)
|
||||
returncode = peewee.IntegerField(default=1)
|
||||
start_time = pw.DateTimeField(default=datetime.now)
|
||||
category = pw.CharField()
|
||||
subcommand = pw.CharField(null=True)
|
||||
message = pw.CharField(null=True)
|
||||
returncode = pw.IntegerField(default=1)
|
||||
params = JSONField(null=True)
|
||||
profile = peewee.ForeignKeyField(BackupProfileModel, default=1)
|
||||
profile = pw.ForeignKeyField(BackupProfileModel, default=1)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class SchemaVersion(pw.Model):
|
||||
"""Keep DB version to apply the correct migrations."""
|
||||
version = pw.IntegerField()
|
||||
changed_at = pw.DateTimeField(default=datetime.now)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
@ -115,16 +133,43 @@ class Meta:
|
|||
|
||||
class BackupProfileMixin:
|
||||
"""Extend to support multiple profiles later."""
|
||||
|
||||
@property
|
||||
def profile(self):
|
||||
return BackupProfileModel.get(id=1)
|
||||
|
||||
|
||||
def _apply_schema_update(current_schema, version_after, *operations):
|
||||
with db.atomic():
|
||||
migrate(*operations)
|
||||
current_schema.version = version_after
|
||||
current_schema.changed_at = datetime.now()
|
||||
current_schema.save()
|
||||
|
||||
|
||||
def init_db(con):
|
||||
db.initialize(con)
|
||||
db.connect()
|
||||
db.create_tables([RepoModel, BackupProfileModel, SourceDirModel,
|
||||
SnapshotModel, WifiSettingModel, EventLogModel])
|
||||
SnapshotModel, WifiSettingModel, EventLogModel, SchemaVersion])
|
||||
|
||||
BackupProfileModel.get_or_create(id=1, name='Default')
|
||||
|
||||
# Migrations
|
||||
# See http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#schema-migrations
|
||||
current_schema, created = SchemaVersion.get_or_create(id=1, defaults={'version': SCHEMA_VERSION})
|
||||
current_schema.save()
|
||||
if created or current_schema.version == SCHEMA_VERSION:
|
||||
return
|
||||
else:
|
||||
migrator = SqliteMigrator(con)
|
||||
|
||||
if current_schema.version < 3: # version 2 to 3
|
||||
pass
|
||||
|
||||
if current_schema.version < 4: # version 3 to 4
|
||||
_apply_schema_update(
|
||||
current_schema, 4,
|
||||
migrator.add_column(SnapshotModel._meta.table_name, 'duration', pw.FloatField(null=True)),
|
||||
migrator.add_column(SnapshotModel._meta.table_name, 'size', pw.IntegerField(null=True))
|
||||
)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
from PyQt5.QtGui import QIcon
|
||||
|
||||
from .utils import get_asset
|
||||
from .config import remove_config
|
||||
from .borg_runner import BorgThread
|
||||
|
||||
|
||||
|
@ -29,9 +28,6 @@ def __init__(self, parent=None):
|
|||
|
||||
menu.addSeparator()
|
||||
|
||||
exit_action = menu.addAction("Factory Reset")
|
||||
exit_action.triggered.connect(self.on_reset)
|
||||
|
||||
exit_action = menu.addAction("Exit")
|
||||
exit_action.triggered.connect(self.on_exit_action)
|
||||
|
||||
|
@ -44,15 +40,11 @@ def __init__(self, parent=None):
|
|||
def on_exit_action(self):
|
||||
self.app.quit()
|
||||
|
||||
def on_reset(self):
|
||||
remove_config()
|
||||
self.app.quit()
|
||||
|
||||
def on_user_click(self):
|
||||
"""Adjust labels to reflect current status."""
|
||||
if BorgThread.is_running():
|
||||
self.status.setText('Backup in Progress')
|
||||
self.create_action.setText('Cancel Backup')
|
||||
else:
|
||||
self.status.setText(self.app.scheduler.next_job)
|
||||
self.status.setText(f'Next Task: {self.app.scheduler.next_job}')
|
||||
self.create_action.setText('Backup Now')
|
||||
|
|
|
@ -49,7 +49,7 @@ def get_private_keys():
|
|||
return available_private_keys
|
||||
|
||||
|
||||
def prettyBytes(size):
|
||||
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:
|
||||
|
|
|
@ -9,6 +9,42 @@
|
|||
from PyQt5 import QtCore
|
||||
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x02\x12\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
|
||||
\x2d\x38\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\
|
||||
\x3d\x22\x31\x37\x39\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
|
||||
\x31\x37\x39\x32\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\
|
||||
\x20\x30\x20\x31\x37\x39\x32\x20\x31\x37\x39\x32\x22\x20\x78\x6d\
|
||||
\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
|
||||
\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\
|
||||
\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\x32\x34\x20\
|
||||
\x31\x34\x30\x38\x68\x36\x34\x30\x76\x2d\x31\x32\x38\x68\x2d\x36\
|
||||
\x34\x30\x76\x31\x32\x38\x7a\x6d\x2d\x33\x38\x34\x2d\x35\x31\x32\
|
||||
\x68\x31\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\
|
||||
\x76\x31\x32\x38\x7a\x6d\x36\x34\x30\x2d\x35\x31\x32\x68\x33\x38\
|
||||
\x34\x76\x2d\x31\x32\x38\x68\x2d\x33\x38\x34\x76\x31\x32\x38\x7a\
|
||||
\x6d\x35\x31\x32\x20\x38\x33\x32\x76\x32\x35\x36\x71\x30\x20\x32\
|
||||
\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\x31\x39\x68\x2d\
|
||||
\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\x35\x2d\x31\x39\
|
||||
\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\x71\x30\x2d\x32\
|
||||
\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\x39\x68\x31\x36\
|
||||
\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\x39\x74\x31\x39\
|
||||
\x20\x34\x35\x7a\x6d\x30\x2d\x35\x31\x32\x76\x32\x35\x36\x71\x30\
|
||||
\x20\x32\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\x31\x39\
|
||||
\x68\x2d\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\x35\x2d\
|
||||
\x31\x39\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\x71\x30\
|
||||
\x2d\x32\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\x39\x68\
|
||||
\x31\x36\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\x39\x74\
|
||||
\x31\x39\x20\x34\x35\x7a\x6d\x30\x2d\x35\x31\x32\x76\x32\x35\x36\
|
||||
\x71\x30\x20\x32\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\
|
||||
\x31\x39\x68\x2d\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\
|
||||
\x35\x2d\x31\x39\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\
|
||||
\x71\x30\x2d\x32\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\
|
||||
\x39\x68\x31\x36\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\
|
||||
\x39\x74\x31\x39\x20\x34\x35\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\
|
||||
\x3e\
|
||||
\x00\x00\x01\x89\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
|
@ -46,40 +82,6 @@
|
|||
\x20\x30\x20\x31\x37\x39\x32\x20\x31\x37\x39\x32\x22\x20\x78\x6d\
|
||||
\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
|
||||
\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\
|
||||
\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x32\x38\x20\x31\
|
||||
\x34\x30\x38\x68\x31\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\
|
||||
\x30\x32\x34\x76\x31\x32\x38\x7a\x6d\x30\x2d\x35\x31\x32\x68\x31\
|
||||
\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\x76\x31\
|
||||
\x32\x38\x7a\x6d\x31\x35\x36\x38\x20\x34\x34\x38\x71\x30\x2d\x34\
|
||||
\x30\x2d\x32\x38\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\
|
||||
\x38\x20\x32\x38\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\
|
||||
\x20\x36\x38\x20\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\
|
||||
\x36\x38\x7a\x6d\x2d\x31\x35\x36\x38\x2d\x39\x36\x30\x68\x31\x30\
|
||||
\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\x76\x31\x32\
|
||||
\x38\x7a\x6d\x31\x35\x36\x38\x20\x34\x34\x38\x71\x30\x2d\x34\x30\
|
||||
\x2d\x32\x38\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\x38\
|
||||
\x20\x32\x38\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\x20\
|
||||
\x36\x38\x20\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\x36\
|
||||
\x38\x7a\x6d\x30\x2d\x35\x31\x32\x71\x30\x2d\x34\x30\x2d\x32\x38\
|
||||
\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\x38\x20\x32\x38\
|
||||
\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\x20\x36\x38\x20\
|
||||
\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\x36\x38\x7a\x6d\
|
||||
\x39\x36\x20\x38\x33\x32\x76\x33\x38\x34\x68\x2d\x31\x37\x39\x32\
|
||||
\x76\x2d\x33\x38\x34\x68\x31\x37\x39\x32\x7a\x6d\x30\x2d\x35\x31\
|
||||
\x32\x76\x33\x38\x34\x68\x2d\x31\x37\x39\x32\x76\x2d\x33\x38\x34\
|
||||
\x68\x31\x37\x39\x32\x7a\x6d\x30\x2d\x35\x31\x32\x76\x33\x38\x34\
|
||||
\x68\x2d\x31\x37\x39\x32\x76\x2d\x33\x38\x34\x68\x31\x37\x39\x32\
|
||||
\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
|
||||
\x00\x00\x01\xfb\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
|
||||
\x2d\x38\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\
|
||||
\x3d\x22\x31\x37\x39\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
|
||||
\x31\x37\x39\x32\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\
|
||||
\x20\x30\x20\x31\x37\x39\x32\x20\x31\x37\x39\x32\x22\x20\x78\x6d\
|
||||
\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
|
||||
\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\
|
||||
\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\x32\x34\x20\
|
||||
\x35\x34\x34\x76\x34\x34\x38\x71\x30\x20\x31\x34\x2d\x39\x20\x32\
|
||||
\x33\x74\x2d\x32\x33\x20\x39\x68\x2d\x33\x32\x30\x71\x2d\x31\x34\
|
||||
|
@ -104,6 +106,40 @@
|
|||
\x20\x33\x38\x35\x2e\x35\x20\x31\x30\x33\x20\x32\x37\x39\x2e\x35\
|
||||
\x20\x32\x37\x39\x2e\x35\x20\x31\x30\x33\x20\x33\x38\x35\x2e\x35\
|
||||
\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
|
||||
\x00\x00\x01\xfb\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
|
||||
\x2d\x38\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\
|
||||
\x3d\x22\x31\x37\x39\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
|
||||
\x31\x37\x39\x32\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\
|
||||
\x20\x30\x20\x31\x37\x39\x32\x20\x31\x37\x39\x32\x22\x20\x78\x6d\
|
||||
\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
|
||||
\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\
|
||||
\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x32\x38\x20\x31\
|
||||
\x34\x30\x38\x68\x31\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\
|
||||
\x30\x32\x34\x76\x31\x32\x38\x7a\x6d\x30\x2d\x35\x31\x32\x68\x31\
|
||||
\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\x76\x31\
|
||||
\x32\x38\x7a\x6d\x31\x35\x36\x38\x20\x34\x34\x38\x71\x30\x2d\x34\
|
||||
\x30\x2d\x32\x38\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\
|
||||
\x38\x20\x32\x38\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\
|
||||
\x20\x36\x38\x20\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\
|
||||
\x36\x38\x7a\x6d\x2d\x31\x35\x36\x38\x2d\x39\x36\x30\x68\x31\x30\
|
||||
\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\x76\x31\x32\
|
||||
\x38\x7a\x6d\x31\x35\x36\x38\x20\x34\x34\x38\x71\x30\x2d\x34\x30\
|
||||
\x2d\x32\x38\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\x38\
|
||||
\x20\x32\x38\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\x20\
|
||||
\x36\x38\x20\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\x36\
|
||||
\x38\x7a\x6d\x30\x2d\x35\x31\x32\x71\x30\x2d\x34\x30\x2d\x32\x38\
|
||||
\x2d\x36\x38\x74\x2d\x36\x38\x2d\x32\x38\x2d\x36\x38\x20\x32\x38\
|
||||
\x2d\x32\x38\x20\x36\x38\x20\x32\x38\x20\x36\x38\x20\x36\x38\x20\
|
||||
\x32\x38\x20\x36\x38\x2d\x32\x38\x20\x32\x38\x2d\x36\x38\x7a\x6d\
|
||||
\x39\x36\x20\x38\x33\x32\x76\x33\x38\x34\x68\x2d\x31\x37\x39\x32\
|
||||
\x76\x2d\x33\x38\x34\x68\x31\x37\x39\x32\x7a\x6d\x30\x2d\x35\x31\
|
||||
\x32\x76\x33\x38\x34\x68\x2d\x31\x37\x39\x32\x76\x2d\x33\x38\x34\
|
||||
\x68\x31\x37\x39\x32\x7a\x6d\x30\x2d\x35\x31\x32\x76\x33\x38\x34\
|
||||
\x68\x2d\x31\x37\x39\x32\x76\x2d\x33\x38\x34\x68\x31\x37\x39\x32\
|
||||
\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
|
||||
\x00\x00\x03\x19\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
|
@ -156,42 +192,6 @@
|
|||
\x31\x30\x20\x31\x30\x20\x32\x33\x20\x30\x20\x31\x38\x2d\x37\x35\
|
||||
\x2e\x35\x20\x39\x33\x74\x2d\x39\x32\x2e\x35\x20\x37\x35\x7a\x22\
|
||||
\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
|
||||
\x00\x00\x02\x12\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
|
||||
\x2d\x38\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\
|
||||
\x3d\x22\x31\x37\x39\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
|
||||
\x31\x37\x39\x32\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\
|
||||
\x20\x30\x20\x31\x37\x39\x32\x20\x31\x37\x39\x32\x22\x20\x78\x6d\
|
||||
\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
|
||||
\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\
|
||||
\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\x32\x34\x20\
|
||||
\x31\x34\x30\x38\x68\x36\x34\x30\x76\x2d\x31\x32\x38\x68\x2d\x36\
|
||||
\x34\x30\x76\x31\x32\x38\x7a\x6d\x2d\x33\x38\x34\x2d\x35\x31\x32\
|
||||
\x68\x31\x30\x32\x34\x76\x2d\x31\x32\x38\x68\x2d\x31\x30\x32\x34\
|
||||
\x76\x31\x32\x38\x7a\x6d\x36\x34\x30\x2d\x35\x31\x32\x68\x33\x38\
|
||||
\x34\x76\x2d\x31\x32\x38\x68\x2d\x33\x38\x34\x76\x31\x32\x38\x7a\
|
||||
\x6d\x35\x31\x32\x20\x38\x33\x32\x76\x32\x35\x36\x71\x30\x20\x32\
|
||||
\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\x31\x39\x68\x2d\
|
||||
\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\x35\x2d\x31\x39\
|
||||
\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\x71\x30\x2d\x32\
|
||||
\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\x39\x68\x31\x36\
|
||||
\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\x39\x74\x31\x39\
|
||||
\x20\x34\x35\x7a\x6d\x30\x2d\x35\x31\x32\x76\x32\x35\x36\x71\x30\
|
||||
\x20\x32\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\x31\x39\
|
||||
\x68\x2d\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\x35\x2d\
|
||||
\x31\x39\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\x71\x30\
|
||||
\x2d\x32\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\x39\x68\
|
||||
\x31\x36\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\x39\x74\
|
||||
\x31\x39\x20\x34\x35\x7a\x6d\x30\x2d\x35\x31\x32\x76\x32\x35\x36\
|
||||
\x71\x30\x20\x32\x36\x2d\x31\x39\x20\x34\x35\x74\x2d\x34\x35\x20\
|
||||
\x31\x39\x68\x2d\x31\x36\x36\x34\x71\x2d\x32\x36\x20\x30\x2d\x34\
|
||||
\x35\x2d\x31\x39\x74\x2d\x31\x39\x2d\x34\x35\x76\x2d\x32\x35\x36\
|
||||
\x71\x30\x2d\x32\x36\x20\x31\x39\x2d\x34\x35\x74\x34\x35\x2d\x31\
|
||||
\x39\x68\x31\x36\x36\x34\x71\x32\x36\x20\x30\x20\x34\x35\x20\x31\
|
||||
\x39\x74\x31\x39\x20\x34\x35\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\
|
||||
\x3e\
|
||||
"
|
||||
|
||||
qt_resource_name = b"\
|
||||
|
@ -199,37 +199,37 @@
|
|||
\x00\x6f\xa6\x53\
|
||||
\x00\x69\
|
||||
\x00\x63\x00\x6f\x00\x6e\x00\x73\
|
||||
\x00\x09\
|
||||
\x0a\x26\xaf\xc7\
|
||||
\x00\x74\
|
||||
\x00\x61\x00\x73\x00\x6b\x00\x73\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x12\
|
||||
\x05\x98\xe2\x07\
|
||||
\x00\x77\
|
||||
\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x2d\x00\x72\x00\x65\x00\x73\x00\x74\x00\x6f\x00\x72\x00\x65\x00\x2e\x00\x73\x00\x76\
|
||||
\x00\x67\
|
||||
\x00\x0a\
|
||||
\x0c\xca\x63\xe7\
|
||||
\x00\x73\
|
||||
\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x0b\
|
||||
\x0f\x16\x31\xe7\
|
||||
\x00\x63\
|
||||
\x00\x6c\x00\x6f\x00\x63\x00\x6b\x00\x2d\x00\x6f\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x0a\
|
||||
\x0c\xca\x63\xe7\
|
||||
\x00\x73\
|
||||
\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x08\
|
||||
\x0f\xcc\x55\x67\
|
||||
\x00\x77\
|
||||
\x00\x69\x00\x66\x00\x69\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x09\
|
||||
\x0a\x26\xaf\xc7\
|
||||
\x00\x74\
|
||||
\x00\x61\x00\x73\x00\x6b\x00\x73\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
"
|
||||
|
||||
qt_resource_struct_v1 = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x02\x16\
|
||||
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x08\xa8\
|
||||
\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x01\x8d\
|
||||
\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x03\x8c\
|
||||
\x00\x00\x00\x70\x00\x00\x00\x00\x00\x01\x00\x00\x05\x8b\
|
||||
\x00\x00\x00\x6e\x00\x00\x00\x00\x00\x01\x00\x00\x05\xa2\
|
||||
\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x03\xa3\
|
||||
\x00\x00\x00\x88\x00\x00\x00\x00\x00\x01\x00\x00\x07\xa1\
|
||||
"
|
||||
|
||||
qt_resource_struct_v2 = b"\
|
||||
|
@ -237,15 +237,15 @@
|
|||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x02\x16\
|
||||
\x00\x00\x01\x66\xbf\xa1\xb1\x2c\
|
||||
\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x08\xa8\
|
||||
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x01\x66\xbf\x9f\xde\x3e\
|
||||
\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x01\x8d\
|
||||
\x00\x00\x00\x6e\x00\x00\x00\x00\x00\x01\x00\x00\x05\xa2\
|
||||
\x00\x00\x01\x66\xbf\xa1\x0f\xda\
|
||||
\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x03\x8c\
|
||||
\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x03\xa3\
|
||||
\x00\x00\x01\x66\xbf\x9d\x97\x00\
|
||||
\x00\x00\x00\x70\x00\x00\x00\x00\x00\x01\x00\x00\x05\x8b\
|
||||
\x00\x00\x00\x88\x00\x00\x00\x00\x00\x01\x00\x00\x07\xa1\
|
||||
\x00\x00\x01\x66\xbf\x9f\x19\x44\
|
||||
"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from ..models import RepoModel, SnapshotModel, BackupProfileMixin
|
||||
from .repo_add import AddRepoWindow, ExistingRepoWindow
|
||||
from ..utils import prettyBytes, get_private_keys, get_asset, keyring
|
||||
from ..utils import pretty_bytes, get_private_keys, get_asset, keyring
|
||||
from .ssh_add import SSHAddWindow
|
||||
|
||||
uifile = get_asset('UI/repotab.ui')
|
||||
|
@ -40,9 +40,9 @@ def __init__(self, parent=None):
|
|||
|
||||
def init_repo_stats(self):
|
||||
repo = self.profile.repo
|
||||
self.sizeCompressed.setText(prettyBytes(repo.unique_csize))
|
||||
self.sizeDeduplicated.setText(prettyBytes(repo.unique_size))
|
||||
self.sizeOriginal.setText(prettyBytes(repo.total_size))
|
||||
self.sizeCompressed.setText(pretty_bytes(repo.unique_csize))
|
||||
self.sizeDeduplicated.setText(pretty_bytes(repo.unique_size))
|
||||
self.sizeOriginal.setText(pretty_bytes(repo.total_size))
|
||||
self.repoEncryption.setText(str(repo.encryption))
|
||||
self.repo_changed.emit(repo.id)
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from datetime import timedelta
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtWidgets import QFileDialog, QTableWidgetItem, QTableView, QHeaderView
|
||||
|
||||
from ..borg_runner import BorgThread
|
||||
from ..utils import get_asset, keyring
|
||||
from ..utils import get_asset, keyring, pretty_bytes
|
||||
from ..models import BackupProfileMixin
|
||||
|
||||
uifile = get_asset('UI/snapshottab.ui')
|
||||
|
@ -18,6 +19,8 @@ def __init__(self, parent=None):
|
|||
header.setVisible(True)
|
||||
header.setSectionResizeMode(0, QHeaderView.Stretch)
|
||||
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
|
||||
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
|
||||
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
|
||||
|
||||
self.snapshotTable.setSelectionBehavior(QTableView.SelectRows)
|
||||
self.snapshotTable.setEditTriggers(QTableView.NoEditTriggers)
|
||||
|
@ -39,8 +42,14 @@ def populate(self):
|
|||
for row, snapshot in enumerate(snapshots):
|
||||
self.snapshotTable.insertRow(row)
|
||||
self.snapshotTable.setItem(row, 0, QTableWidgetItem(snapshot.name))
|
||||
self.snapshotTable.setItem(row, 1, QTableWidgetItem(pretty_bytes(snapshot.size)))
|
||||
if snapshot.duration:
|
||||
formatted_duration = str(timedelta(seconds=round(snapshot.duration)))
|
||||
else:
|
||||
formatted_duration = 'N/A'
|
||||
self.snapshotTable.setItem(row, 2, QTableWidgetItem(formatted_duration))
|
||||
formatted_time = snapshot.time.strftime('%Y-%m-%d %H:%M')
|
||||
self.snapshotTable.setItem(row, 1, QTableWidgetItem(formatted_time))
|
||||
self.snapshotTable.setItem(row, 3, QTableWidgetItem(formatted_time))
|
||||
self.snapshotTable.setRowCount(len(snapshots))
|
||||
|
||||
def snapshot_mount(self):
|
||||
|
@ -67,7 +76,8 @@ def snapshot_mount(self):
|
|||
|
||||
self.set_status('Mounting snapshot into folder...')
|
||||
params = {'password': keyring.get_password("vorta-repo", profile.repo.url)}
|
||||
thread = BorgThread(self, cmd, params, parent=self)
|
||||
self.snapshotMountButton.setEnabled(False)
|
||||
thread = BorgThread(cmd, params, parent=self)
|
||||
thread.updated.connect(self.mount_update_log)
|
||||
thread.result.connect(self.mount_get_result)
|
||||
thread.start()
|
||||
|
@ -76,5 +86,7 @@ def mount_update_log(self, text):
|
|||
self.mountErrors.setText(text)
|
||||
|
||||
def mount_get_result(self, result):
|
||||
self.snapshotMountButton.setEnabled(True)
|
||||
if result['returncode'] == 0:
|
||||
self.set_status('Mounted successfully.')
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import pytest
|
||||
from datetime import datetime as dt, date, time
|
||||
from PyQt5 import QtCore
|
||||
|
||||
from vorta.views.schedule_tab import ScheduleTab
|
||||
|
||||
from .fixtures import app, main
|
||||
from .fixtures import *
|
||||
|
||||
def test_schedule_tab(main, qtbot):
|
||||
tab = ScheduleTab(main.scheduleTabSlot)
|
||||
qtbot.addWidget(tab)
|
||||
# qtbot.addWidget(tab)
|
||||
qtbot.mouseClick(tab.scheduleApplyButton, QtCore.Qt.LeftButton)
|
||||
assert tab.nextBackupDateTimeLabel.text() == 'Manual Backups'
|
||||
|
||||
|
@ -26,4 +27,3 @@ def test_schedule_tab(main, qtbot):
|
|||
qtbot.mouseClick(tab.scheduleApplyButton, QtCore.Qt.LeftButton)
|
||||
next_backup = dt.combine(date.today(), time(23, 59))
|
||||
assert tab.nextBackupDateTimeLabel.text() == next_backup.strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
|
|
Loading…
Reference in a new issue