Skip to content

Commit f56921f

Browse files
committed
Fixes #2120
1 parent 64586df commit f56921f

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

src/vorta/application.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import sys
44
from pathlib import Path
5+
from threading import Thread
56
from typing import Any, Dict, List, Tuple
67

78
from PyQt6 import QtCore
@@ -42,6 +43,9 @@ class VortaApp(QtSingleApplication):
4243
backup_log_event = QtCore.pyqtSignal(str, dict)
4344
backup_progress_event = QtCore.pyqtSignal(str)
4445
check_failed_event = QtCore.pyqtSignal(dict)
46+
create_backup_event = QtCore.pyqtSignal()
47+
pre_backup_event = QtCore.pyqtSignal(int)
48+
post_backup_event = QtCore.pyqtSignal(int, bool)
4549

4650
def __init__(self, args_raw, single_app=False):
4751
super().__init__(str(APP_ID), args_raw)
@@ -84,6 +88,9 @@ def __init__(self, args_raw, single_app=False):
8488
self.message_received_event.connect(self.message_received_event_response)
8589
self.check_failed_event.connect(self.check_failed_response)
8690
self.backup_log_event.connect(self.react_to_log)
91+
self.create_backup_event.connect(lambda: Thread(target=self.create_backup_action).start())
92+
self.pre_backup_event.connect(self.pre_backup_event_response)
93+
self.post_backup_event.connect(self.post_backup_event_response)
8794
self.aboutToQuit.connect(self.quit_app_action)
8895
self.set_borg_details_action()
8996
if sys.platform == 'darwin':
@@ -94,7 +101,7 @@ def create_backups_cmdline(self, profile_name):
94101
if profile is not None:
95102
if profile.repo is None:
96103
logger.warning(f"Add a repository to {profile_name}")
97-
self.create_backup_action(profile_id=profile.id)
104+
Thread(target=self.create_backup_action, kwargs={'profile_id': profile.id}).start()
98105
else:
99106
logger.warning(f"Invalid profile name {profile_name}")
100107

@@ -110,7 +117,7 @@ def create_backup_action(self, profile_id=None):
110117
profile_id = self.main_window.current_profile.id
111118

112119
profile = BackupProfileModel.get(id=profile_id)
113-
msg = BorgCreateJob.prepare(profile)
120+
msg = BorgCreateJob.prepare(profile, app=self)
114121
if msg['ok']:
115122
job = BorgCreateJob(msg['cmd'], msg, profile.repo.id)
116123
self.jobs_manager.add_job(job)
@@ -146,6 +153,13 @@ def backup_cancelled_event_response(self):
146153
self.jobs_manager.cancel_all_jobs()
147154
self.tray.set_tray_icon()
148155

156+
def pre_backup_event_response(self, pid):
157+
self.tray.set_tray_icon(active=True)
158+
159+
def post_backup_event_response(self, pid, active=False):
160+
if not active:
161+
self.tray.set_tray_icon()
162+
149163
def message_received_event_response(self, message):
150164
if message == "open main window":
151165
self.open_main_window_action()

src/vorta/borg/create.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def process_result(self, result):
5353
self.app.backup_log_event.emit('', {})
5454
self.app.backup_progress_event.emit(f"[{self.params['profile_name']}] {self.tr('Backup finished.')}")
5555

56-
def progress_event(self, fmt):
56+
def progress_event(self, fmt=None):
5757
self.app.backup_progress_event.emit(f"[{self.params['profile_name']}] {fmt}")
5858

5959
def started_event(self):
@@ -63,26 +63,34 @@ def started_event(self):
6363
def finished_event(self, result):
6464
self.app.backup_finished_event.emit(result)
6565
self.result.emit(result)
66-
self.pre_post_backup_cmd(self.params, cmd='post_backup_cmd', returncode=result['returncode'])
66+
self.pre_post_backup_cmd(self.params, context='post_backup_cmd', app=self.app, returncode=result['returncode'])
6767

6868
@classmethod
69-
def pre_post_backup_cmd(cls, params, cmd='pre_backup_cmd', returncode=0):
70-
cmd = getattr(params['profile'], cmd)
69+
def pre_post_backup_cmd(cls, params, context='pre_backup_cmd', app=None, returncode=0):
70+
cmd = getattr(params['profile'], context)
7171
if cmd:
72+
profile_name = getattr(params['profile'], 'name')
7273
env = {
7374
**os.environ.copy(),
7475
'repo_url': params['repo'].url,
7576
'profile_name': params['profile'].name,
7677
'profile_slug': params['profile'].slug(),
7778
'returncode': str(returncode),
7879
}
79-
proc = subprocess.run(cmd, shell=True, env=env)
80+
proc = subprocess.Popen(cmd, shell=True, env=env)
81+
if context.startswith('pre'):
82+
app.backup_progress_event.emit(f"[{profile_name}] {trans_late('messages', 'Waiting to start backup')}")
83+
app.pre_backup_event.emit(proc.pid)
84+
else:
85+
app.post_backup_event.emit(proc.pid, True)
86+
proc.wait()
87+
app.post_backup_event.emit(None, False)
8088
return proc.returncode
8189
else:
8290
return 0 # 0 if no command was run.
8391

8492
@classmethod
85-
def prepare(cls, profile):
93+
def prepare(cls, profile, app=None):
8694
"""
8795
`borg create` is called from different places and needs some preparation.
8896
Centralize it here and return the required arguments to the caller.
@@ -133,7 +141,7 @@ def prepare(cls, profile):
133141
ret['repo'] = profile.repo
134142

135143
# Run user-supplied pre-backup command
136-
if cls.pre_post_backup_cmd(ret) != 0:
144+
if cls.pre_post_backup_cmd(ret, app=app) != 0:
137145
ret['message'] = trans_late('messages', 'Pre-backup command returned non-zero exit code.')
138146
return ret
139147

src/vorta/scheduler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ def set_timer_for_profile(self, profile_id: int):
301301
profile.name,
302302
profile_id,
303303
)
304-
self.create_backup(profile_id)
304+
threading.Thread(target=self.create_backup, args=(profile_id,)).start()
305305
finally:
306306
self.lock.acquire() # with-statement will try to release
307307

@@ -337,7 +337,7 @@ def set_timer_for_profile(self, profile_id: int):
337337
timer = QTimer()
338338
timer.setSingleShot(True)
339339
timer.setInterval(int(timer_ms))
340-
timer.timeout.connect(lambda: self.create_backup(profile_id))
340+
timer.timeout.connect(lambda: threading.Thread(target=self.create_backup, args=(profile_id,)).start())
341341
timer.start()
342342

343343
self.timers[profile_id] = {
@@ -410,7 +410,7 @@ def create_backup(self, profile_id):
410410
self.tr('Starting background backup for %s.') % profile.name,
411411
level='info',
412412
)
413-
msg = BorgCreateJob.prepare(profile)
413+
msg = BorgCreateJob.prepare(profile, app=self.app)
414414
if msg['ok']:
415415
logger.info('Preparation for backup successful.')
416416
msg['category'] = 'scheduled'

src/vorta/views/main_window.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def __init__(self, parent=None):
8888
self.miscTab.refresh_archive.connect(self.archiveTab.populate_from_profile)
8989

9090
self.miscButton.clicked.connect(self.toggle_misc_visibility)
91-
self.createStartBtn.clicked.connect(self.app.create_backup_action)
91+
self.createStartBtn.clicked.connect(self.app.create_backup_event.emit)
9292
self.cancelButton.clicked.connect(self.app.backup_cancelled_event.emit)
9393

9494
QShortcut(QKeySequence("Ctrl+W"), self).activated.connect(self.on_close_window)
@@ -99,6 +99,8 @@ def __init__(self, parent=None):
9999
self.app.backup_log_event.connect(self.set_log)
100100
self.app.backup_progress_event.connect(self.set_progress)
101101
self.app.backup_cancelled_event.connect(self.backup_cancelled_event)
102+
self.app.pre_backup_event.connect(self.pre_backup_event)
103+
self.app.post_backup_event.connect(self.post_backup_event)
102104

103105
# Init profile list
104106
self.populate_profile_selector()
@@ -339,6 +341,17 @@ def backup_cancelled_event(self):
339341
self.set_log(self.tr('Task cancelled'))
340342
self.archiveTab.cancel_action()
341343

344+
def pre_backup_event(self, pid):
345+
self._toggle_buttons(create_enabled=False)
346+
self.set_log(self.tr(f"Running pre backup commands [PID: {pid}]"))
347+
348+
def post_backup_event(self, pid, active=True):
349+
if active:
350+
self.set_log(self.tr(f"Running post backup commands [PID: {pid}]"))
351+
else:
352+
self._toggle_buttons(create_enabled=True)
353+
self.set_log('')
354+
342355
def closeEvent(self, event):
343356
# Save window state in SettingsModel
344357
SettingsModel.update({SettingsModel.str_value: str(self.width())}).where(

0 commit comments

Comments
 (0)