mirror of
https://github.com/borgbase/vorta
synced 2025-01-03 05:36:19 +00:00
commit
470a1cd2f2
6 changed files with 79 additions and 56 deletions
|
@ -230,24 +230,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mountErrors">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>To mount archives, first install &quot;FUSE for macOS&quot; from <a href="https://osxfuse.github.io/"><span style=" text-decoration: underline; color:#0000ff;">here</span></a>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
|
@ -338,6 +320,24 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mountErrors">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>To mount archives, first install &quot;FUSE for macOS&quot; from <a href="https://osxfuse.github.io/"><span style=" text-decoration: underline; color:#0000ff;">here</span></a>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
|
|
|
@ -181,7 +181,7 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>35</height>
|
||||
<height>45</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../icons/collection.qrc">
|
||||
<normaloff>:/icons/unlink.svg</normaloff>:/icons/unlink.svg</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
|
@ -115,6 +115,9 @@
|
|||
<property name="text">
|
||||
<string><html><head/><body><p>Remote or local backup repository. For secure remote backups, try <a href="https://www.borgbase.com/?utm_source=vorta&utm_medium=app"><span style=" text-decoration: underline; color:#0000ff;">BorgBase</span></a>. 100GB free during Beta.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -157,7 +160,7 @@
|
|||
<string>Copy</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../icons/collection.qrc">
|
||||
<normaloff>:/icons/copy.svg</normaloff>:/icons/copy.svg</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -183,6 +186,9 @@
|
|||
<property name="text">
|
||||
<string>To securely access remote repositories. Keep default to use all your existing keys. Or create new key.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -45,6 +45,8 @@ def __init__(self, cmd, params, parent=None):
|
|||
password = params.get('password')
|
||||
if password is not None:
|
||||
env['BORG_PASSPHRASE'] = password
|
||||
else:
|
||||
env['BORG_PASSPHRASE'] = '9999999' # Set dummy password to avoid prompt.
|
||||
|
||||
env['BORG_RSH'] = 'ssh -oStrictHostKeyChecking=no'
|
||||
ssh_key = params.get('ssh_key')
|
||||
|
@ -93,11 +95,18 @@ def prepare(cls, profile):
|
|||
ret['message'] = 'Add a backup repository first.'
|
||||
return ret
|
||||
|
||||
# Try to get password from chosen keyring backend.
|
||||
try:
|
||||
ret['password'] = keyring.get_password("vorta-repo", profile.repo.url)
|
||||
except keyring.backends._OS_X_API.Error:
|
||||
ret['message'] = 'Please make sure you grant Vorta permission to use the Keychain.'
|
||||
return ret
|
||||
|
||||
ret['ssh_key'] = profile.ssh_key
|
||||
ret['repo_id'] = profile.repo.id
|
||||
ret['repo_url'] = profile.repo.url
|
||||
ret['profile_name'] = profile.name
|
||||
ret['password'] = keyring.get_password("vorta-repo", profile.repo.url) # None if no password.
|
||||
|
||||
ret['ok'] = True
|
||||
|
||||
return ret
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
class BorgCreateThread(BorgThread):
|
||||
def process_result(self, result):
|
||||
if result['returncode'] in [0, 1]:
|
||||
if result['returncode'] in [0, 1] and 'archive' in result['data']:
|
||||
new_snapshot, created = ArchiveModel.get_or_create(
|
||||
snapshot_id=result['data']['archive']['id'],
|
||||
defaults={
|
||||
|
@ -32,6 +32,8 @@ def process_result(self, result):
|
|||
repo.total_unique_chunks = stats['total_unique_chunks']
|
||||
repo.save()
|
||||
|
||||
self.app.backup_log_event.emit('Backup finished.')
|
||||
|
||||
def log_event(self, msg):
|
||||
self.app.backup_log_event.emit(msg)
|
||||
|
||||
|
@ -41,7 +43,6 @@ def started_event(self):
|
|||
|
||||
def finished_event(self, result):
|
||||
self.app.backup_finished_event.emit(result)
|
||||
self.app.backup_log_event.emit('Backup finished.')
|
||||
|
||||
@classmethod
|
||||
def prepare(cls, profile):
|
||||
|
@ -102,7 +103,7 @@ def prepare(cls, profile):
|
|||
cmd.extend(['--exclude-if-present', f.strip()])
|
||||
|
||||
# Add repo url and source dirs.
|
||||
cmd.append(f'{profile.repo.url}::{platform.node()}-{dt.now().isoformat()}')
|
||||
cmd.append(f"{profile.repo.url}::{platform.node()}-{profile.id}-{dt.now().isoformat(timespec='seconds')}")
|
||||
|
||||
for f in SourceDirModel.select().where(SourceDirModel.profile == profile.id):
|
||||
cmd.append(f.dir)
|
||||
|
|
|
@ -13,23 +13,6 @@ def __init__(self, parent=None):
|
|||
self.app = parent
|
||||
menu = QMenu()
|
||||
|
||||
self.status = menu.addAction(self.app.scheduler.next_job)
|
||||
self.status.setEnabled(False)
|
||||
|
||||
self.profile_menu = menu.addMenu('Backup Now')
|
||||
|
||||
self.cancel_action = menu.addAction("Cancel Backup")
|
||||
self.cancel_action.triggered.connect(self.app.backup_cancelled_event.emit)
|
||||
|
||||
settings_action = menu.addAction("Settings")
|
||||
settings_action.triggered.connect(self.app.open_main_window_action)
|
||||
|
||||
menu.addSeparator()
|
||||
|
||||
exit_action = menu.addAction("Exit")
|
||||
exit_action.triggered.connect(self.app.quit)
|
||||
|
||||
self.on_user_click()
|
||||
# https://stackoverflow.com/questions/43657890/pyqt5-qsystemtrayicon-activated-signal-not-working
|
||||
menu.aboutToShow.connect(self.on_user_click)
|
||||
|
||||
|
@ -38,18 +21,42 @@ def __init__(self, parent=None):
|
|||
self.show()
|
||||
|
||||
def on_user_click(self):
|
||||
"""Adjust labels to reflect current status."""
|
||||
if BorgThread.is_running():
|
||||
self.status.setText('Backup in Progress')
|
||||
self.profile_menu.setEnabled(False)
|
||||
self.cancel_action.setVisible(True)
|
||||
else:
|
||||
self.status.setText(f'Next Task: {self.app.scheduler.next_job}')
|
||||
self.profile_menu.setEnabled(True)
|
||||
self.cancel_action.setVisible(False)
|
||||
"""
|
||||
Build system tray menu based on current status.
|
||||
|
||||
self.profile_menu.clear()
|
||||
for profile in BackupProfileModel.select():
|
||||
new_item = self.profile_menu.addAction(profile.name)
|
||||
new_item.setData(profile.id)
|
||||
new_item.triggered.connect(lambda profile_id=profile.id: self.app.create_backup_action(profile_id))
|
||||
"""
|
||||
|
||||
menu = self.contextMenu()
|
||||
menu.clear()
|
||||
|
||||
status = menu.addAction(self.app.scheduler.next_job)
|
||||
status.setEnabled(False)
|
||||
|
||||
profiles = BackupProfileModel.select()
|
||||
if profiles.count() > 1:
|
||||
profile_menu = menu.addMenu('Backup Now')
|
||||
for profile in profiles:
|
||||
new_item = profile_menu.addAction(profile.name)
|
||||
new_item.setData(profile.id)
|
||||
new_item.triggered.connect(lambda profile_id=profile.id: self.app.create_backup_action(profile_id))
|
||||
else:
|
||||
profile = profiles.first()
|
||||
profile_menu = menu.addAction('Backup Now')
|
||||
profile_menu.triggered.connect((lambda profile_id=profile.id: self.app.create_backup_action(profile_id)))
|
||||
|
||||
if BorgThread.is_running():
|
||||
status.setText('Backup in Progress')
|
||||
profile_menu.setVisible(False)
|
||||
cancel_action = menu.addAction("Cancel Backup")
|
||||
cancel_action.triggered.connect(self.app.backup_cancelled_event.emit)
|
||||
else:
|
||||
status.setText(f'Next Task: {self.app.scheduler.next_job}')
|
||||
profile_menu.setEnabled(True)
|
||||
|
||||
settings_action = menu.addAction("Settings")
|
||||
settings_action.triggered.connect(self.app.open_main_window_action)
|
||||
|
||||
menu.addSeparator()
|
||||
|
||||
exit_action = menu.addAction("Exit")
|
||||
exit_action.triggered.connect(self.app.quit)
|
||||
|
|
Loading…
Reference in a new issue