diff --git a/node_launcher/constants.py b/node_launcher/constants.py
index c0b03a26..fde0e7fe 100644
--- a/node_launcher/constants.py
+++ b/node_launcher/constants.py
@@ -3,10 +3,19 @@
import platform
from typing import Dict
-NODE_LAUNCHER_RELEASE = '.'.join(map(str, (6, 0, 4)))
+NODE_LAUNCHER_RELEASE = '.'.join(
+ map(
+ str,
+ (
+ 6,
+ 0,
+ 9
+ )
+ )
+)
-TARGET_BITCOIN_RELEASE = 'v0.17.1'
-TARGET_LND_RELEASE = 'v0.6-beta-rc4'
+TARGET_BITCOIN_RELEASE = 'v0.21.1'
+TARGET_LND_RELEASE = 'v0.13.1-beta'
class StringConstant(object):
@@ -55,7 +64,6 @@ class OperatingSystem(StringConstant):
APPDATA = os.path.abspath(os.environ.get('APPDATA', ''))
PROGRAMS = os.environ.get('Programw6432', '')
-
NODE_LAUNCHER_DATA_PATH: Dict[OperatingSystem, str] = {
DARWIN: expanduser('~/Library/Application Support/Node Launcher/'),
LINUX: expanduser('~/.node_launcher'),
@@ -80,22 +88,25 @@ class OperatingSystem(StringConstant):
}
UPGRADE = 'Please download the latest version of the Node Launcher: ' \
- '' \
- 'https://github.com/PierreRochard/node-launcher/releases' \
- ''
+ '' \
+ 'https://github.com/PierreRochard/node-launcher/releases' \
+ ''
GIGABYTE = 1000000000
if IS_WINDOWS:
from keyring.backends.Windows import WinVaultKeyring
+
keyring = WinVaultKeyring()
if IS_MACOS:
- from keyring.backends.OS_X import Keyring
+ from keyring.backends.macOS import Keyring
+
keyring = Keyring()
if IS_LINUX:
from keyring.backends.SecretService import Keyring
+
keyring = Keyring()
AUTOPRUNE_GB = 150
diff --git a/node_launcher/gui/application.py b/node_launcher/gui/application.py
index 43639128..77f5fbf7 100644
--- a/node_launcher/gui/application.py
+++ b/node_launcher/gui/application.py
@@ -1,6 +1,15 @@
-from PySide2 import QtCore
-from PySide2.QtCore import QCoreApplication, Slot, QTimer, Qt
-from PySide2.QtWidgets import QApplication, QWidget, QMessageBox
+import sys
+
+from node_launcher.gui.qt import (
+ QtCore,
+ QCoreApplication,
+ Slot,
+ QTimer,
+ Qt,
+ QApplication,
+ QWidget,
+ QMessageBox
+)
from node_launcher.constants import NODE_LAUNCHER_RELEASE, UPGRADE
from node_launcher.gui.system_tray import SystemTray
@@ -10,7 +19,7 @@
class Application(QApplication):
def __init__(self):
- super().__init__()
+ super().__init__(sys.argv)
self.node_set = NodeSet()
self.parent = QWidget()
diff --git a/node_launcher/gui/components/copy_button.py b/node_launcher/gui/components/copy_button.py
index 60ec2d91..686f3c41 100644
--- a/node_launcher/gui/components/copy_button.py
+++ b/node_launcher/gui/components/copy_button.py
@@ -1,6 +1,4 @@
-from PySide2.QtCore import QTimer
-from PySide2.QtGui import QClipboard
-from PySide2.QtWidgets import QVBoxLayout, QPushButton
+from node_launcher.gui.qt import QTimer, QGuiApplication, QVBoxLayout, QPushButton
class CopyButton(QVBoxLayout):
@@ -15,7 +13,7 @@ def __init__(self, button_text: str, copy_text: str):
self.timer = QTimer(self.parentWidget())
def copy(self):
- QClipboard().setText(self.copy_text)
+ QGuiApplication.clipboard().setText(self.copy_text)
self.button.setText('Copied!')
self.button.repaint()
self.timer.singleShot(1000, self.remove_text)
diff --git a/node_launcher/gui/components/grid_layout.py b/node_launcher/gui/components/grid_layout.py
index f3a29173..7c3dbee5 100644
--- a/node_launcher/gui/components/grid_layout.py
+++ b/node_launcher/gui/components/grid_layout.py
@@ -1,5 +1,4 @@
-from PySide2 import QtWidgets
-from PySide2.QtWidgets import QWidget
+from node_launcher.gui.qt import QtWidgets, QWidget
class QGridLayout(QtWidgets.QGridLayout):
diff --git a/node_launcher/gui/components/horizontal_line.py b/node_launcher/gui/components/horizontal_line.py
index cdee07df..67713c0c 100644
--- a/node_launcher/gui/components/horizontal_line.py
+++ b/node_launcher/gui/components/horizontal_line.py
@@ -1,4 +1,4 @@
-from PySide2.QtWidgets import QFrame
+from node_launcher.gui.qt import QFrame
class HorizontalLine(QFrame):
diff --git a/node_launcher/gui/components/image_label.py b/node_launcher/gui/components/image_label.py
index 335f0684..664413d5 100644
--- a/node_launcher/gui/components/image_label.py
+++ b/node_launcher/gui/components/image_label.py
@@ -1,6 +1,4 @@
-from PySide2 import QtWidgets
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QPixmap
+from node_launcher.gui.qt import QtWidgets, Qt, QPixmap
from node_launcher.assets.asset_access import asset_access
diff --git a/node_launcher/gui/components/section_name.py b/node_launcher/gui/components/section_name.py
index 6a2429c2..77af2b9c 100644
--- a/node_launcher/gui/components/section_name.py
+++ b/node_launcher/gui/components/section_name.py
@@ -1,4 +1,4 @@
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import QLabel
class SectionName(QLabel):
diff --git a/node_launcher/gui/components/selectable_text.py b/node_launcher/gui/components/selectable_text.py
index 9bc0517b..6ef2156a 100644
--- a/node_launcher/gui/components/selectable_text.py
+++ b/node_launcher/gui/components/selectable_text.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import Qt, QLabel
class SelectableText(QLabel):
diff --git a/node_launcher/gui/components/thread_worker.py b/node_launcher/gui/components/thread_worker.py
index 7a4c903f..27ac6d99 100644
--- a/node_launcher/gui/components/thread_worker.py
+++ b/node_launcher/gui/components/thread_worker.py
@@ -1,11 +1,13 @@
import time
+import traceback
+import sys
-from PySide2.QtCore import QRunnable, Slot, QThreadPool, Signal, QObject, QTimer
+import grpc
-import traceback, sys
-
-from PySide2.QtWidgets import QMainWindow, QVBoxLayout, QLabel, QPushButton, \
- QWidget, QApplication
+from node_launcher.gui.qt import (
+ QMainWindow, QVBoxLayout, QLabel, QPushButton,
+ QWidget, QApplication, QRunnable, Slot, QThreadPool, Signal, QObject, QTimer
+)
class WorkerSignals(QObject):
@@ -28,7 +30,7 @@ class WorkerSignals(QObject):
"""
finished = Signal()
- error = Signal(tuple)
+ error = Signal(str)
result = Signal(object)
progress = Signal(int)
@@ -68,6 +70,8 @@ def run(self):
# Retrieve args/kwargs here; and fire processing using them
try:
result = self.fn(*self.args, **self.kwargs)
+ except grpc.RpcError as e:
+ self.signals.error.emit(e.args[0].details)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
diff --git a/node_launcher/gui/components/warning_text.py b/node_launcher/gui/components/warning_text.py
index aea5b692..6541b326 100644
--- a/node_launcher/gui/components/warning_text.py
+++ b/node_launcher/gui/components/warning_text.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import QLabel
class WarningText(QLabel):
diff --git a/node_launcher/gui/menu.py b/node_launcher/gui/menu.py
index 850f4434..ac04ba4f 100644
--- a/node_launcher/gui/menu.py
+++ b/node_launcher/gui/menu.py
@@ -1,6 +1,4 @@
-from PySide2.QtCore import QCoreApplication
-from PySide2.QtGui import QKeySequence, QClipboard
-from PySide2.QtWidgets import QMenu
+from node_launcher.gui.qt import QCoreApplication, QKeySequence, QMenu, QGuiApplication
from node_launcher.constants import BITCOIN_CLI_COMMANDS, LNCLI_COMMANDS
from node_launcher.gui.system_tray_widgets import (
@@ -15,8 +13,8 @@
class Menu(QMenu):
- def __init__(self, node_set: NodeSet, system_tray):
- super().__init__()
+ def __init__(self, node_set: NodeSet, system_tray, parent):
+ super().__init__(parent=parent)
self.node_set = node_set
self.system_tray = system_tray
@@ -83,7 +81,7 @@ def __init__(self, node_set: NodeSet, system_tray):
self.joule_macaroons_action = self.addAction('Show Macaroons')
self.joule_url_action.triggered.connect(
- lambda: QClipboard().setText(self.node_set.lnd.rest_url)
+ lambda: QGuiApplication.clipboard().setText(self.node_set.lnd.rest_url)
)
self.joule_macaroons_action.triggered.connect(
diff --git a/node_launcher/gui/qt.py b/node_launcher/gui/qt.py
new file mode 100644
index 00000000..ed82d0d2
--- /dev/null
+++ b/node_launcher/gui/qt.py
@@ -0,0 +1,98 @@
+# PyQt5
+from PyQt5 import QtGui, QtWidgets, QtCore
+from PyQt5.QtCore import (
+ QCoreApplication,
+ pyqtSignal as Signal,
+ pyqtSignal as SIGNAL,
+ pyqtSlot as Slot,
+ QTimer,
+ Qt,
+ QProcess,
+ QByteArray,
+ QFileSystemWatcher,
+ QThreadPool,
+ QRunnable,
+ QObject
+)
+from PyQt5.QtWidgets import (
+ QErrorMessage,
+ QApplication,
+ QWidget,
+ QMessageBox,
+ QDialog,
+ QTabWidget,
+ QDialogButtonBox,
+ QVBoxLayout,
+ QFrame,
+ QPushButton,
+ QGridLayout,
+ QGroupBox,
+ QLabel,
+ QFileDialog,
+ QMenu,
+ QTextEdit,
+ QColorDialog,
+ QLineEdit,
+ QSystemTrayIcon,
+ QCheckBox,
+ QCompleter,
+ QMainWindow
+)
+from PyQt5.QtGui import (
+ QPixmap,
+ QFont,
+ QKeySequence,
+ QPalette,
+ QColor,
+ QIcon,
+ QGuiApplication
+)
+ # # PySide2
+ # from PySide2 import QtGui, QtWidgets, QtCore
+ # from PySide2.QtCore import (
+ # QCoreApplication,
+ # Signal,
+ # Slot,
+ # QTimer,
+ # Qt,
+ # QProcess,
+ # QByteArray,
+ # QFileSystemWatcher,
+ # QThreadPool,
+ # QRunnable,
+ # QObject,
+ # SIGNAL
+ # )
+ # from PySide2.QtWidgets import (
+ # QErrorMessage,
+ # QApplication,
+ # QWidget,
+ # QMessageBox,
+ # QDialog,
+ # QTabWidget,
+ # QDialogButtonBox,
+ # QVBoxLayout,
+ # QFrame,
+ # QPushButton,
+ # QGridLayout,
+ # QGroupBox,
+ # QLabel,
+ # QFileDialog,
+ # QMenu,
+ # QTextEdit,
+ # QColorDialog,
+ # QLineEdit,
+ # QSystemTrayIcon,
+ # QCheckBox,
+ # QCompleter,
+ # QMainWindow
+ # )
+ # from PySide2.QtGui import (
+ # QPixmap,
+ # QClipboard,
+ # QFont,
+ # QKeySequence,
+ # QPalette,
+ # QColor,
+ # QIcon
+ # )
diff --git a/node_launcher/gui/system_tray.py b/node_launcher/gui/system_tray.py
index 8cefc5df..939d3cbd 100644
--- a/node_launcher/gui/system_tray.py
+++ b/node_launcher/gui/system_tray.py
@@ -1,5 +1,4 @@
-from PySide2.QtGui import QIcon, QPixmap
-from PySide2.QtWidgets import QSystemTrayIcon, QWidget
+from node_launcher.gui.qt import QIcon, QPixmap, QSystemTrayIcon, QWidget
from node_launcher.assets.asset_access import asset_access
from node_launcher.gui.menu import Menu
@@ -11,7 +10,7 @@ def __init__(self, parent: QWidget, node_set: NodeSet):
super(SystemTray, self).__init__(parent=parent)
self.node_set = node_set
self.set_red()
- self.menu = Menu(node_set=node_set, system_tray=self)
+ self.menu = Menu(node_set=node_set, system_tray=self, parent=parent)
self.setContextMenu(self.menu)
def set_icon(self, color: str):
diff --git a/node_launcher/gui/system_tray_widgets/advanced/advanced_widget.py b/node_launcher/gui/system_tray_widgets/advanced/advanced_widget.py
index 2bdd05f4..7d20573b 100644
--- a/node_launcher/gui/system_tray_widgets/advanced/advanced_widget.py
+++ b/node_launcher/gui/system_tray_widgets/advanced/advanced_widget.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QWidget
+from node_launcher.gui.qt import Qt, QWidget
from .configuration_files_layout import ConfigurationFilesLayout
from .ports_layout import PortsLayout
diff --git a/node_launcher/gui/system_tray_widgets/advanced/configuration_files_layout.py b/node_launcher/gui/system_tray_widgets/advanced/configuration_files_layout.py
index d7e62f26..4c360203 100644
--- a/node_launcher/gui/system_tray_widgets/advanced/configuration_files_layout.py
+++ b/node_launcher/gui/system_tray_widgets/advanced/configuration_files_layout.py
@@ -1,4 +1,4 @@
-from PySide2 import QtWidgets
+from node_launcher.gui.qt import QtWidgets
from node_launcher.gui.components.grid_layout import QGridLayout
from node_launcher.gui.components.section_name import SectionName
diff --git a/node_launcher/gui/system_tray_widgets/advanced/tls_layout.py b/node_launcher/gui/system_tray_widgets/advanced/tls_layout.py
index 7f50dc0e..fe0797ef 100644
--- a/node_launcher/gui/system_tray_widgets/advanced/tls_layout.py
+++ b/node_launcher/gui/system_tray_widgets/advanced/tls_layout.py
@@ -1,6 +1,6 @@
from pprint import pformat
-from PySide2.QtWidgets import QPushButton, QMessageBox
+from node_launcher.gui.qt import QPushButton, QMessageBox
from node_launcher.gui.components.grid_layout import QGridLayout
from node_launcher.gui.components.section_name import SectionName
diff --git a/node_launcher/gui/system_tray_widgets/advanced/zap_layout.py b/node_launcher/gui/system_tray_widgets/advanced/zap_layout.py
index 4966643a..e92b7bca 100644
--- a/node_launcher/gui/system_tray_widgets/advanced/zap_layout.py
+++ b/node_launcher/gui/system_tray_widgets/advanced/zap_layout.py
@@ -1,8 +1,6 @@
import webbrowser
-from PySide2 import QtWidgets
-from PySide2.QtGui import QPixmap
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import QtWidgets, QPixmap, QLabel
from node_launcher.services.lndconnect import get_deprecated_lndconnect_url, \
get_qrcode_img
diff --git a/node_launcher/gui/system_tray_widgets/bitcoind_output_widget.py b/node_launcher/gui/system_tray_widgets/bitcoind_output_widget.py
index 2d19e887..ea3d3e81 100644
--- a/node_launcher/gui/system_tray_widgets/bitcoind_output_widget.py
+++ b/node_launcher/gui/system_tray_widgets/bitcoind_output_widget.py
@@ -1,7 +1,7 @@
from datetime import datetime, timedelta
import humanize
-from PySide2.QtCore import QProcess, QThreadPool, Qt
+from node_launcher.gui.qt import QProcess, QThreadPool, Qt
from node_launcher.gui.system_tray_widgets.output_widget import OutputWidget
from node_launcher.node_set import NodeSet
diff --git a/node_launcher/gui/system_tray_widgets/console_dialog.py b/node_launcher/gui/system_tray_widgets/console_dialog.py
index 0e2f09f1..e37a081b 100644
--- a/node_launcher/gui/system_tray_widgets/console_dialog.py
+++ b/node_launcher/gui/system_tray_widgets/console_dialog.py
@@ -1,16 +1,18 @@
from typing import List
-from PySide2.QtCore import SIGNAL, QProcess, QByteArray, Qt
-from PySide2.QtWidgets import QTextEdit, QLineEdit, QCompleter, QDialog
from pygments import highlight
from pygments.formatters.html import HtmlFormatter
from pygments.lexers.data import JsonLexer
+from node_launcher.gui.qt import (
+ SIGNAL, QProcess, QByteArray, Qt, QTextEdit, QLineEdit, QCompleter, QDialog
+)
from node_launcher.gui.components.grid_layout import QGridLayout
from node_launcher.logging import log
class ConsoleDialog(QDialog):
+
def __init__(self, title: str,
program: str,
args: List[str],
@@ -35,12 +37,8 @@ def __init__(self, title: str,
self.layout.addWidget(self.output)
self.layout.addWidget(self.input)
self.setLayout(self.layout)
-
- self.connect(self.input, SIGNAL("returnPressed(void)"),
- self.execute_user_command)
-
- self.connect(self.completer, SIGNAL("activated(const QString&)"),
- self.input.clear, Qt.QueuedConnection)
+ self.input.returnPressed.connect(self.execute_user_command)
+ self.completer.activated.connect(self.input.clear)
def execute_user_command(self):
cmd = str(self.input.text())
diff --git a/node_launcher/gui/system_tray_widgets/lnd_output_widget.py b/node_launcher/gui/system_tray_widgets/lnd_output_widget.py
index bbc0ed45..7749b01b 100644
--- a/node_launcher/gui/system_tray_widgets/lnd_output_widget.py
+++ b/node_launcher/gui/system_tray_widgets/lnd_output_widget.py
@@ -3,7 +3,7 @@
# noinspection PyPackageRequirements
from grpc._channel import _Rendezvous
import humanize
-from PySide2.QtCore import QThreadPool, Qt, QTimer
+from node_launcher.gui.qt import QThreadPool, Qt, QTimer
from node_launcher.constants import keyring
from node_launcher.gui.components.thread_worker import Worker
@@ -40,12 +40,18 @@ def process_output_line(self, line: str):
self.system_tray.menu.lnd_status_action.setText(
'LND unlocking wallet'
)
+ self.system_tray.set_blue()
QTimer.singleShot(100, self.auto_unlock_wallet)
elif 'Unable to synchronize wallet to chain' in line:
self.process.terminate()
+ elif 'Started rescan from block' in line:
+ self.system_tray.menu.lnd_status_action.setText(
+ 'LND syncing'
+ )
+ self.system_tray.set_blue()
elif 'Unable to complete chain rescan' in line:
self.process.terminate()
- elif 'Starting HTLC Switch' in line:
+ elif 'Initializing peer network bootstrappers!' in line:
self.system_tray.set_green()
self.system_tray.menu.lnd_status_action.setText(
'LND synced'
@@ -74,6 +80,15 @@ def process_output_line(self, line: str):
self.old_height = new_height
self.old_timestamp = new_timestamp
+ elif 'Syncing channel graph from height' in line:
+ self.system_tray.menu.lnd_status_action.setText(
+ 'LND syncing'
+ )
+ self.system_tray.set_blue()
+ elif 'Shutdown complete' in line:
+ self.system_tray.menu.lnd_status_action.setText(
+ 'LND has shutdown'
+ )
def restart_process(self):
QTimer.singleShot(3000, self.process.start)
@@ -90,18 +105,23 @@ def unlock_wallet(lnd, progress_callback, password: str):
details = e.details()
return details
+ @property
+ def keyring_service_name(self):
+ return f'lnd_{self.node_set.bitcoin.network}_wallet_password'
+
def generate_seed(self, new_seed_password: str):
try:
generate_seed_response = self.node_set.lnd_client.generate_seed(
seed_password=new_seed_password
)
- except _Rendezvous:
- log.error('generate_seed error', exc_info=True)
+ except _Rendezvous as e:
+ details = e.details()
+ log.error('generate_seed error', details=details, exc_info=True)
raise
seed = generate_seed_response.cipher_seed_mnemonic
- keyring_service_name = f'lnd_seed'
+ keyring_service_name = f'lnd_seed_{self.node_set.bitcoin.network}'
keyring_user_name = ''.join(seed[0:2])
log.info(
'generate_seed',
@@ -133,15 +153,14 @@ def handle_unlock_wallet(self, details: str):
# User needs to create a new wallet
elif 'wallet not found' in details:
new_wallet_password = get_random_password()
- keyring_service_name = keyring_user_name = f'lnd_wallet_password'
log.info(
'create_wallet',
- keyring_service_name=keyring_service_name,
- keyring_user_name=keyring_user_name
+ keyring_service_name=self.keyring_service_name,
+ keyring_user_name=self.keyring_service_name
)
keyring.set_password(
- service=keyring_service_name,
- username=keyring_user_name,
+ service=self.keyring_service_name,
+ username=self.keyring_service_name,
password=new_wallet_password
)
seed = self.generate_seed(new_wallet_password)
@@ -159,6 +178,10 @@ def handle_unlock_wallet(self, details: str):
username=self.node_set.bitcoin.file['rpcuser'],
password=new_wallet_password
)
+ elif 'invalid passphrase for master public key' in details:
+ self.system_tray.menu.lnd_status_action.setText(
+ 'Invalid LND Password'
+ )
else:
log.warning(
'unlock_wallet failed',
@@ -166,25 +189,41 @@ def handle_unlock_wallet(self, details: str):
exc_info=True
)
+ def get_password(self):
+ passwords = []
+ for service_name in [self.keyring_service_name, 'lnd_wallet_password']:
+ for user_name in [self.keyring_service_name, self.node_set.bitcoin.file['rpcuser'], 'lnd_wallet_password']:
+ log.info(
+ 'auto_unlock_wallet_get_password',
+ keyring_service_name=service_name,
+ keyring_user_name=user_name
+ )
+ password = keyring.get_password(
+ service=service_name,
+ username=user_name,
+ )
+ if password is not None:
+ log.info(
+ 'Successfully got password from',
+ keyring_service_name=service_name,
+ keyring_user_name=user_name
+ )
+ passwords += [password]
+ return passwords
+
def auto_unlock_wallet(self):
- keyring_service_name = f'lnd_{self.node_set.bitcoin.network}_wallet_password'
- keyring_user_name = self.node_set.bitcoin.file['rpcuser']
- log.info(
- 'auto_unlock_wallet_get_password',
- keyring_service_name=keyring_service_name,
- keyring_user_name=keyring_user_name
- )
- password = keyring.get_password(
- service=keyring_service_name,
- username=keyring_user_name,
- )
- worker = Worker(
- fn=self.unlock_wallet,
- lnd=self.node_set.lnd,
- password=password
- )
- worker.signals.result.connect(self.handle_unlock_wallet)
- self.threadpool.start(worker)
+ passwords = self.get_password()
+ for password in passwords:
+ worker = Worker(
+ fn=self.unlock_wallet,
+ lnd=self.node_set.lnd,
+ password=password
+ )
+ worker.signals.result.connect(self.handle_unlock_wallet)
+ worker.signals.error.connect(self.handle_unlock_wallet)
+ self.threadpool.start(worker)
+ if len(passwords) == 0:
+ self.handle_unlock_wallet('wallet not found')
def show(self):
self.showMaximized()
diff --git a/node_launcher/gui/system_tray_widgets/output_widget.py b/node_launcher/gui/system_tray_widgets/output_widget.py
index bae94bcb..9b651f0b 100644
--- a/node_launcher/gui/system_tray_widgets/output_widget.py
+++ b/node_launcher/gui/system_tray_widgets/output_widget.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import QByteArray, QProcess
-from PySide2.QtWidgets import QDialog, QGridLayout, QTextEdit
+from node_launcher.gui.qt import QByteArray, QProcess, QDialog, QGridLayout, QTextEdit
from node_launcher.node_set import NodeSet
@@ -19,11 +18,14 @@ def __init__(self):
self.setLayout(self.layout)
def handle_output(self):
- while self.process.canReadLine():
- line_bytes: QByteArray = self.process.readLine()
- line_str = line_bytes.data().decode('utf-8').strip()
- self.output.append(line_str)
- self.process_output_line(line_str)
+ try:
+ while self.process.canReadLine():
+ line_bytes: QByteArray = self.process.readLine()
+ line_str = line_bytes.data().decode('utf-8').strip()
+ self.output.append(line_str)
+ self.process_output_line(line_str)
+ except RuntimeError:
+ return None
def handle_error(self):
output: QByteArray = self.process.readAllStandardError()
diff --git a/node_launcher/gui/system_tray_widgets/restart_layout.py b/node_launcher/gui/system_tray_widgets/restart_layout.py
index ed2119f3..86058a18 100644
--- a/node_launcher/gui/system_tray_widgets/restart_layout.py
+++ b/node_launcher/gui/system_tray_widgets/restart_layout.py
@@ -1,4 +1,4 @@
-from PySide2.QtCore import QTimer
+from node_launcher.gui.qt import QTimer
from node_launcher.gui.components.grid_layout import QGridLayout
from node_launcher.gui.components.section_name import SectionName
from node_launcher.node_set import NodeSet
diff --git a/node_launcher/gui/system_tray_widgets/settings/alias_layout.py b/node_launcher/gui/system_tray_widgets/settings/alias_layout.py
index 47da50e7..661d0656 100644
--- a/node_launcher/gui/system_tray_widgets/settings/alias_layout.py
+++ b/node_launcher/gui/system_tray_widgets/settings/alias_layout.py
@@ -1,6 +1,4 @@
-from PySide2.QtGui import QPalette, QColor
-from PySide2.QtWidgets import QColorDialog, QLineEdit, QLabel, QPushButton
-from PySide2.QtCore import Signal
+from node_launcher.gui.qt import QPalette, QColor, QColorDialog, QLineEdit, QLabel, QPushButton, Signal
from node_launcher.gui.components.grid_layout import QGridLayout
diff --git a/node_launcher/gui/system_tray_widgets/settings/bitcoin_tab.py b/node_launcher/gui/system_tray_widgets/settings/bitcoin_tab.py
index b6b35f8a..d4f676e1 100644
--- a/node_launcher/gui/system_tray_widgets/settings/bitcoin_tab.py
+++ b/node_launcher/gui/system_tray_widgets/settings/bitcoin_tab.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt, Signal
-from PySide2.QtWidgets import QWidget, QLabel, QCheckBox, QVBoxLayout
+from node_launcher.gui.qt import Qt, Signal, QWidget, QLabel, QCheckBox, QVBoxLayout
from node_launcher.constants import Network
from .data_directories.data_directory_box import DataDirectoryBox
diff --git a/node_launcher/gui/system_tray_widgets/settings/data_directories/data_directory_box.py b/node_launcher/gui/system_tray_widgets/settings/data_directories/data_directory_box.py
index b52eb5e6..b69a9fda 100644
--- a/node_launcher/gui/system_tray_widgets/settings/data_directories/data_directory_box.py
+++ b/node_launcher/gui/system_tray_widgets/settings/data_directories/data_directory_box.py
@@ -1,4 +1,4 @@
-from PySide2.QtWidgets import (
+from node_launcher.gui.qt import (
QGridLayout,
QGroupBox,
QPushButton
diff --git a/node_launcher/gui/system_tray_widgets/settings/data_directories/datadir_label.py b/node_launcher/gui/system_tray_widgets/settings/data_directories/datadir_label.py
index 0d05076c..220054e2 100644
--- a/node_launcher/gui/system_tray_widgets/settings/data_directories/datadir_label.py
+++ b/node_launcher/gui/system_tray_widgets/settings/data_directories/datadir_label.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import Qt, QLabel
class DatadirLabel(QLabel):
diff --git a/node_launcher/gui/system_tray_widgets/settings/data_directories/prune_warning_label.py b/node_launcher/gui/system_tray_widgets/settings/data_directories/prune_warning_label.py
index 926644c8..6ff706d2 100644
--- a/node_launcher/gui/system_tray_widgets/settings/data_directories/prune_warning_label.py
+++ b/node_launcher/gui/system_tray_widgets/settings/data_directories/prune_warning_label.py
@@ -1,6 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QFont
-from PySide2.QtWidgets import QLabel
+from node_launcher.gui.qt import Qt, QFont, QLabel
class PruneWarningLabel(QLabel):
diff --git a/node_launcher/gui/system_tray_widgets/settings/data_directories/select_directory_dialog.py b/node_launcher/gui/system_tray_widgets/settings/data_directories/select_directory_dialog.py
index 530dc548..fc9d9268 100644
--- a/node_launcher/gui/system_tray_widgets/settings/data_directories/select_directory_dialog.py
+++ b/node_launcher/gui/system_tray_widgets/settings/data_directories/select_directory_dialog.py
@@ -1,7 +1,6 @@
import os
-from PySide2.QtCore import Signal
-from PySide2.QtWidgets import QFileDialog, QWidget, QErrorMessage
+from node_launcher.gui.qt import Signal, QFileDialog, QWidget, QErrorMessage
class SelectDirectoryDialog(QFileDialog):
diff --git a/node_launcher/gui/system_tray_widgets/settings/lnd_tab.py b/node_launcher/gui/system_tray_widgets/settings/lnd_tab.py
index f7ef1d21..a324e264 100644
--- a/node_launcher/gui/system_tray_widgets/settings/lnd_tab.py
+++ b/node_launcher/gui/system_tray_widgets/settings/lnd_tab.py
@@ -1,4 +1,4 @@
-from PySide2.QtWidgets import QWidget
+from node_launcher.gui.qt import QWidget
from node_launcher.gui.components.grid_layout import QGridLayout
from .alias_layout import AliasLayout
diff --git a/node_launcher/gui/system_tray_widgets/settings/settings_tab_dialog.py b/node_launcher/gui/system_tray_widgets/settings/settings_tab_dialog.py
index df5b24bd..15b79fdc 100644
--- a/node_launcher/gui/system_tray_widgets/settings/settings_tab_dialog.py
+++ b/node_launcher/gui/system_tray_widgets/settings/settings_tab_dialog.py
@@ -1,5 +1,4 @@
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QDialog, QTabWidget, QDialogButtonBox, QVBoxLayout
+from node_launcher.gui.qt import Qt, QDialog, QTabWidget, QDialogButtonBox, QVBoxLayout
from .bitcoin_tab import BitcoinTab
from .lnd_tab import LndTab
diff --git a/node_launcher/gui/utilities.py b/node_launcher/gui/utilities.py
index 0e4c4fca..4f0d72f6 100644
--- a/node_launcher/gui/utilities.py
+++ b/node_launcher/gui/utilities.py
@@ -2,7 +2,7 @@
import subprocess
from pathlib import Path
-from PySide2.QtWidgets import QErrorMessage
+from node_launcher.gui.qt import QErrorMessage
from node_launcher.constants import IS_MACOS, IS_LINUX, IS_WINDOWS, OPERATING_SYSTEM
diff --git a/node_launcher/node_set/bitcoin.py b/node_launcher/node_set/bitcoin.py
index 973a8336..abc63883 100644
--- a/node_launcher/node_set/bitcoin.py
+++ b/node_launcher/node_set/bitcoin.py
@@ -2,7 +2,7 @@
from typing import List
import psutil
-from PySide2.QtCore import QProcess
+from node_launcher.gui.qt import QProcess
from node_launcher.constants import (BITCOIN_DATA_PATH,
BITCOIN_MAINNET_PEER_PORT,
diff --git a/node_launcher/node_set/lnd.py b/node_launcher/node_set/lnd.py
index ba06361c..a7b775a8 100644
--- a/node_launcher/node_set/lnd.py
+++ b/node_launcher/node_set/lnd.py
@@ -3,7 +3,7 @@
import ssl
from typing import List
-from PySide2.QtCore import QProcess
+from node_launcher.gui.qt import QProcess
from node_launcher.constants import (
IS_WINDOWS,
diff --git a/node_launcher/services/configuration_file.py b/node_launcher/services/configuration_file.py
index f21ee484..e73b9711 100644
--- a/node_launcher/services/configuration_file.py
+++ b/node_launcher/services/configuration_file.py
@@ -4,7 +4,7 @@
from node_launcher.constants import NODE_LAUNCHER_RELEASE
from node_launcher.logging import log
-from PySide2.QtCore import QFileSystemWatcher
+from node_launcher.gui.qt import QFileSystemWatcher
class ConfigurationFile(dict):
diff --git a/node_launcher/utilities/except_hook.py b/node_launcher/utilities/except_hook.py
index 06873cf6..148479ee 100644
--- a/node_launcher/utilities/except_hook.py
+++ b/node_launcher/utilities/except_hook.py
@@ -2,8 +2,7 @@
import traceback
from io import StringIO
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QMessageBox
+from node_launcher.gui.qt import Qt, QMessageBox
from node_launcher.constants import NODE_LAUNCHER_RELEASE
@@ -36,7 +35,7 @@ def except_hook(exception_type, exception_value, traceback_object):
if __name__ == '__main__':
- from PySide2 import QtWidgets
+ from node_launcher.gui.qt import QtWidgets
sys.excepthook = except_hook
app = QtWidgets.QApplication([])
diff --git a/requirements.txt b/requirements.txt
index 3a63e927..cab0109c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
colorama
dataclasses
+google-api-core
googleapis-common-protos
grpcio
grpcio-tools
@@ -11,12 +12,11 @@ protobuf
psutil
pygments
pyinstaller
-PySide2<=5.12.0
+PyQt5
PyTest
pytest-qt
qrcode
requests
-shiboken2<=5.12.0
structlog
webassets
wtforms
diff --git a/run-mac.spec b/run-mac.spec
index 817b87a9..6ddd685b 100644
--- a/run-mac.spec
+++ b/run-mac.spec
@@ -7,10 +7,7 @@ a = Analysis(
['run.py'],
pathex=['/Users/pierre/src/node-launcher'],
binaries=[],
- datas=[
- ('node_launcher/assets/*.png', 'assets')
- ] + collect_data_files('shiboken2', include_py_files=True, subdir='support')
- + collect_data_files('PySide2', include_py_files=True, subdir='support'),
+ datas=[('node_launcher/assets/*.png', 'assets')],
hiddenimports=['setuptools'],
hookspath=[],
runtime_hooks=[],
diff --git a/run-windows.spec b/run-windows.spec
index b2269cfa..57e38a1a 100644
--- a/run-windows.spec
+++ b/run-windows.spec
@@ -9,14 +9,13 @@ a = Analysis(['run.py'],
binaries=[],
datas=[
('node_launcher/assets/*.png', 'assets')
- ] + collect_data_files('shiboken2', include_py_files=True, subdir='support')
- + collect_data_files('PySide2', include_py_files=True, subdir='support'),
+ ],
hiddenimports=['setuptools', 'pypiwin32', 'win32timezone'],
hookspath=[],
runtime_hooks=[],
excludes=[],
- win_no_prefer_redirects=False,
- win_private_assemblies=False,
+ win_no_prefer_redirects=True,
+ win_private_assemblies=True,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,