diff --git a/src/vorta/__main__.py b/src/vorta/__main__.py index 29c220ae..3d43186c 100644 --- a/src/vorta/__main__.py +++ b/src/vorta/__main__.py @@ -1,7 +1,7 @@ import sys from PyQt5.QtWidgets import QApplication -from .tray_menu import TrayMenu -from .scheduler import init_scheduler +from vorta.tray_menu import TrayMenu +from vorta.scheduler import init_scheduler app = QApplication(sys.argv) app.thread = None diff --git a/src/vorta/views/UI/mainwindow.ui b/src/vorta/assets/UI/mainwindow.ui similarity index 100% rename from src/vorta/views/UI/mainwindow.ui rename to src/vorta/assets/UI/mainwindow.ui diff --git a/src/vorta/views/UI/repoadd.ui b/src/vorta/assets/UI/repoadd.ui similarity index 100% rename from src/vorta/views/UI/repoadd.ui rename to src/vorta/assets/UI/repoadd.ui diff --git a/src/vorta/views/UI/repotab.ui b/src/vorta/assets/UI/repotab.ui similarity index 100% rename from src/vorta/views/UI/repotab.ui rename to src/vorta/assets/UI/repotab.ui diff --git a/src/vorta/views/UI/snapshottab.ui b/src/vorta/assets/UI/snapshottab.ui similarity index 100% rename from src/vorta/views/UI/snapshottab.ui rename to src/vorta/assets/UI/snapshottab.ui diff --git a/src/vorta/views/UI/sourcetab.ui b/src/vorta/assets/UI/sourcetab.ui similarity index 100% rename from src/vorta/views/UI/sourcetab.ui rename to src/vorta/assets/UI/sourcetab.ui diff --git a/src/vorta/views/UI/sshadd.ui b/src/vorta/assets/UI/sshadd.ui similarity index 100% rename from src/vorta/views/UI/sshadd.ui rename to src/vorta/assets/UI/sshadd.ui diff --git a/src/vorta/views/UI/icons/app-icon.icns b/src/vorta/assets/icons/app-icon.icns similarity index 100% rename from src/vorta/views/UI/icons/app-icon.icns rename to src/vorta/assets/icons/app-icon.icns diff --git a/src/vorta/views/UI/icons/hdd-o.png b/src/vorta/assets/icons/hdd-o.png similarity index 100% rename from src/vorta/views/UI/icons/hdd-o.png rename to src/vorta/assets/icons/hdd-o.png diff --git a/src/vorta/borg_runner.py b/src/vorta/borg_runner.py index 2c445522..dc8fdf8f 100644 --- a/src/vorta/borg_runner.py +++ b/src/vorta/borg_runner.py @@ -38,31 +38,32 @@ class BorgThread(QtCore.QThread): self.env = env self.params = params + self.process = None def run(self): - with Popen(self.cmd, stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True, env=self.env) as p: - for line in p.stderr: - try: - parsed = json.loads(line) - if parsed['type'] == 'log_message': - self.updated.emit(f'{parsed["levelname"]}: {parsed["message"]}') - elif parsed['type'] == 'file_status': - self.updated.emit(f'{parsed["path"]} ({parsed["status"]})') - except json.decoder.JSONDecodeError: - self.updated.emit(line.strip()) - - p.wait() - stdout = p.stdout.read() - result = { - 'params': self.params, - 'returncode': p.returncode, - } + self.process = Popen(self.cmd, stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True, env=self.env) + for line in iter(self.process.stderr.readline, b''): try: - result['data'] = json.loads(stdout) - except: - result['data'] = {} + parsed = json.loads(line) + if parsed['type'] == 'log_message': + self.updated.emit(f'{parsed["levelname"]}: {parsed["message"]}') + elif parsed['type'] == 'file_status': + self.updated.emit(f'{parsed["path"]} ({parsed["status"]})') + except json.decoder.JSONDecodeError: + self.updated.emit(line.strip()) - self.result.emit(result) + self.process.wait() + stdout = self.process.stdout.read() + result = { + 'params': self.params, + 'returncode': self.process.returncode, + } + try: + result['data'] = json.loads(stdout) + except: + result['data'] = {} + + self.result.emit(result) @classmethod def create_thread_factory(cls): diff --git a/src/vorta/scheduler.py b/src/vorta/scheduler.py index 81aae3c7..4cbe09ac 100644 --- a/src/vorta/scheduler.py +++ b/src/vorta/scheduler.py @@ -1,10 +1,12 @@ from apscheduler.schedulers.qt import QtScheduler +from apscheduler.triggers import interval def tick(): print('scheduler') def init_scheduler(): s = QtScheduler() - s.add_job(tick, 'interval', seconds=3) + trigger = interval.IntervalTrigger(seconds=3) + s.add_job(tick, trigger, seconds=3) s.start() return s diff --git a/src/vorta/tray_menu.py b/src/vorta/tray_menu.py index 2467ff97..08347515 100644 --- a/src/vorta/tray_menu.py +++ b/src/vorta/tray_menu.py @@ -3,13 +3,13 @@ from PyQt5.QtWidgets import QMenu, QApplication, QSystemTrayIcon from .views.main_window import MainWindow from PyQt5.QtGui import QIcon -from .utils import get_relative_asset +from .utils import get_asset from .config import remove_config from .borg_runner import BorgThread class TrayMenu(QSystemTrayIcon): def __init__(self, parent=None): - icon = QIcon(get_relative_asset('views/UI/icons/hdd-o.png', __file__)) + icon = QIcon(get_asset('icons/hdd-o.png')) QSystemTrayIcon.__init__(self, icon, parent) self.app = parent menu = QMenu() @@ -59,6 +59,7 @@ class TrayMenu(QSystemTrayIcon): def on_cancel_backup(self): if self.app.thread and self.app.thread.isRunning(): + self.app.thread.process.kill() self.app.thread.terminate() def on_user_click(self): diff --git a/src/vorta/utils.py b/src/vorta/utils.py index 36027245..0f83c937 100644 --- a/src/vorta/utils.py +++ b/src/vorta/utils.py @@ -45,11 +45,11 @@ def prettyBytes(size): return str(round(size))+Dic_powerN[n]+'B' -def get_relative_asset(path, caller): +def get_asset(path): if getattr(sys, 'frozen', False): # we are running in a bundle - bundle_dir = sys._MEIPASS + bundle_dir = os.path.join(sys._MEIPASS, 'assets') else: # we are running in a normal Python environment - bundle_dir = os.path.dirname(os.path.abspath(caller)) + bundle_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets') return os.path.join(bundle_dir, path) diff --git a/src/vorta/views/main_window.py b/src/vorta/views/main_window.py index 0d21f376..f17e55ca 100644 --- a/src/vorta/views/main_window.py +++ b/src/vorta/views/main_window.py @@ -8,10 +8,10 @@ from ..borg_runner import BorgThread from .repo_tab import RepoTab from .source_tab import SourceTab from .snapshots_tab import SnapshotTab -from ..utils import get_relative_asset +from ..utils import get_asset -uifile = get_relative_asset('UI/mainwindow.ui', __file__) +uifile = get_asset('UI/mainwindow.ui') MainWindowUI, MainWindowBase = uic.loadUiType(uifile) @@ -69,6 +69,7 @@ class MainWindow(MainWindowBase, MainWindowUI): def cancel_create_action(self): try: + self.app.thread.process.kill() self.app.thread.terminate() self.app.thread.wait() self.createStartBtn.setEnabled(True) diff --git a/src/vorta/views/repo_add.py b/src/vorta/views/repo_add.py index 046fa572..4e468a81 100644 --- a/src/vorta/views/repo_add.py +++ b/src/vorta/views/repo_add.py @@ -1,8 +1,8 @@ from PyQt5 import uic -from ..utils import get_private_keys, get_relative_asset +from ..utils import get_private_keys, get_asset from ..borg_runner import BorgThread -uifile = get_relative_asset('UI/repoadd.ui', __file__) +uifile = get_asset('UI/repoadd.ui') AddRepoUI, AddRepoBase = uic.loadUiType(uifile) diff --git a/src/vorta/views/repo_tab.py b/src/vorta/views/repo_tab.py index ffc55cdc..a4f8c657 100644 --- a/src/vorta/views/repo_tab.py +++ b/src/vorta/views/repo_tab.py @@ -4,10 +4,10 @@ import keyring from ..models import RepoModel, SnapshotModel from .repo_add import AddRepoWindow, ExistingRepoWindow -from ..utils import prettyBytes, get_private_keys, get_relative_asset +from ..utils import prettyBytes, get_private_keys, get_asset from .ssh_add import SSHAddWindow -uifile = get_relative_asset('UI/repotab.ui', __file__) +uifile = get_asset('UI/repotab.ui') RepoUI, RepoBase = uic.loadUiType(uifile) diff --git a/src/vorta/views/snapshots_tab.py b/src/vorta/views/snapshots_tab.py index 2ba79e72..cd2e1623 100644 --- a/src/vorta/views/snapshots_tab.py +++ b/src/vorta/views/snapshots_tab.py @@ -2,9 +2,9 @@ from PyQt5 import uic from PyQt5.QtWidgets import QFileDialog, QTableWidgetItem, QTableView, QHeaderView from ..borg_runner import BorgThread -from ..utils import get_relative_asset +from ..utils import get_asset -uifile = get_relative_asset('UI/snapshottab.ui', __file__) +uifile = get_asset('UI/snapshottab.ui') SnapshotUI, SnapshotBase = uic.loadUiType(uifile) diff --git a/src/vorta/views/source_tab.py b/src/vorta/views/source_tab.py index 2f0d37f3..f8b4faa7 100644 --- a/src/vorta/views/source_tab.py +++ b/src/vorta/views/source_tab.py @@ -1,9 +1,9 @@ from PyQt5 import uic from PyQt5.QtWidgets import QFileDialog from ..models import SourceDirModel -from ..utils import get_relative_asset +from ..utils import get_asset -uifile = get_relative_asset('UI/sourcetab.ui', __file__) +uifile = get_asset('UI/sourcetab.ui') SourceUI, SourceBase = uic.loadUiType(uifile) diff --git a/src/vorta/views/ssh_add.py b/src/vorta/views/ssh_add.py index 3ce0b4fb..0cc24118 100644 --- a/src/vorta/views/ssh_add.py +++ b/src/vorta/views/ssh_add.py @@ -7,9 +7,9 @@ from paramiko.rsakey import RSAKey from paramiko.ecdsakey import ECDSAKey from paramiko.ed25519key import Ed25519Key -from ..utils import get_relative_asset +from ..utils import get_asset -uifile = get_relative_asset('UI/sshadd.ui', __file__) +uifile = get_asset('UI/sshadd.ui') SSHAddUI, SSHAddBase = uic.loadUiType(uifile) FORMAT_MAPPING = { diff --git a/vorta.spec b/vorta.spec index 35505728..a3defa4d 100644 --- a/vorta.spec +++ b/vorta.spec @@ -2,14 +2,14 @@ block_cipher = None -a = Analysis(['vorta/__main__.py'], - pathex=['/Users/manu/Workspace/vorta'], +a = Analysis(['src/vorta/__main__.py'], + pathex=['/Users/manu/Workspace/vorta/src'], binaries=[ ('bin/macosx64/borg', 'bin') ], datas=[ - ('vorta/UI/*.ui', 'UI'), - ('vorta/UI/icons/*', 'UI/icons'), + ('src/vorta/assets/UI/*', 'assets/UI'), + ('src/vorta/assets/icons/*', 'assets/icons'), ], hiddenimports=[], hookspath=[], @@ -37,7 +37,7 @@ exe = EXE(pyz, app = BUNDLE(exe, name='Vorta.app', - icon='vorta/UI/icons/app-icon.icns', + icon='src/vorta/assets/icons/app-icon.icns', bundle_identifier='com.borgbase.client.macos', info_plist={ 'NSHighResolutionCapable': 'True',