qml: add LabelSync toggle
This commit is contained in:
@@ -41,6 +41,7 @@ class ElectrumTranslator(QTranslator):
|
||||
def translate(self, context, source_text, disambiguation, n):
|
||||
return _(source_text, context=context)
|
||||
|
||||
|
||||
class ElectrumGui(BaseElectrumGui, Logger):
|
||||
|
||||
@profiler
|
||||
@@ -91,7 +92,7 @@ class ElectrumGui(BaseElectrumGui, Logger):
|
||||
Exception_Hook.maybe_setup(config=config, slot=self.app.appController.crash)
|
||||
|
||||
# Initialize any QML plugins
|
||||
run_hook('init_qml', self)
|
||||
run_hook('init_qml', self.app)
|
||||
self.app.engine.load('electrum/gui/qml/components/main.qml')
|
||||
|
||||
def close(self):
|
||||
|
||||
@@ -217,6 +217,25 @@ Pane {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: -constants.paddingSmall
|
||||
spacing: 0
|
||||
Switch {
|
||||
id: syncLabels
|
||||
onCheckedChanged: {
|
||||
if (activeFocus)
|
||||
AppController.setPluginEnabled('labels', checked)
|
||||
}
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Synchronize labels')
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
PrefsHeading {
|
||||
Layout.columnSpan: 2
|
||||
text: qsTr('Wallet behavior')
|
||||
@@ -384,5 +403,6 @@ Pane {
|
||||
useFallbackAddress.checked = Config.useFallbackAddress
|
||||
enableDebugLogs.checked = Config.enableDebugLogs
|
||||
useRecoverableChannels.checked = Config.useRecoverableChannels
|
||||
syncLabels.checked = AppController.isPluginEnabled('labels')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ from electrum.logging import Logger, get_logger
|
||||
from electrum.bip21 import BITCOIN_BIP21_URI_SCHEME, LIGHTNING_URI_SCHEME
|
||||
from electrum.base_crash_reporter import BaseCrashReporter, EarlyExceptionsQueue
|
||||
from electrum.network import Network
|
||||
from electrum.plugin import run_hook
|
||||
|
||||
from .qeconfig import QEConfig
|
||||
from .qedaemon import QEDaemon
|
||||
@@ -70,10 +71,11 @@ class QEAppController(BaseCrashReporter, QObject):
|
||||
sendingBugreportFailure = pyqtSignal(str)
|
||||
secureWindowChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, qedaemon: 'QEDaemon', plugins: 'Plugins'):
|
||||
def __init__(self, qeapp: 'ElectrumQmlApplication', qedaemon: 'QEDaemon', plugins: 'Plugins'):
|
||||
BaseCrashReporter.__init__(self, None, None, None)
|
||||
QObject.__init__(self)
|
||||
|
||||
self._app = qeapp
|
||||
self._qedaemon = qedaemon
|
||||
self._plugins = plugins
|
||||
self.config = qedaemon.daemon.config
|
||||
@@ -224,12 +226,18 @@ class QEAppController(BaseCrashReporter, QObject):
|
||||
return s
|
||||
|
||||
@pyqtSlot(str, bool)
|
||||
def setPluginEnabled(self, plugin, enabled):
|
||||
def setPluginEnabled(self, plugin: str, enabled: bool):
|
||||
if enabled:
|
||||
self._plugins.enable(plugin)
|
||||
# note: all enabled plugins will receive this hook:
|
||||
run_hook('init_qml', self._app)
|
||||
else:
|
||||
self._plugins.disable(plugin)
|
||||
|
||||
@pyqtSlot(str, result=bool)
|
||||
def isPluginEnabled(self, plugin: str):
|
||||
return bool(self._plugins.get(plugin))
|
||||
|
||||
@pyqtSlot(result=bool)
|
||||
def isAndroid(self):
|
||||
return 'ANDROID_DATA' in os.environ
|
||||
@@ -369,7 +377,7 @@ class ElectrumQmlApplication(QGuiApplication):
|
||||
self._qeconfig = QEConfig(config)
|
||||
self._qenetwork = QENetwork(daemon.network, self._qeconfig)
|
||||
self.daemon = QEDaemon(daemon)
|
||||
self.appController = QEAppController(self.daemon, self.plugins)
|
||||
self.appController = QEAppController(self, self.daemon, self.plugins)
|
||||
self._maxAmount = QEAmount(is_max=True)
|
||||
self.context.setContextProperty('AppController', self.appController)
|
||||
self.context.setContextProperty('Config', self._qeconfig)
|
||||
|
||||
@@ -218,6 +218,7 @@ def hook(func):
|
||||
hook_names.add(func.__name__)
|
||||
return func
|
||||
|
||||
|
||||
def run_hook(name, *args):
|
||||
results = []
|
||||
f_list = hooks.get(name, [])
|
||||
|
||||
@@ -134,9 +134,11 @@ class LabelsPlugin(BasePlugin):
|
||||
response = await self.do_get("/labels/since/%d/for/%s" % (nonce, wallet_id))
|
||||
except Exception as e:
|
||||
raise ErrorConnectingServer(e) from e
|
||||
if response["labels"] is None:
|
||||
if response["labels"] is None or len(response["labels"]) == 0:
|
||||
self.logger.info('no new labels')
|
||||
return
|
||||
self.logger.debug(f"labels received {response!r}")
|
||||
self.logger.info(f'received {len(response["labels"])} labels')
|
||||
result = {}
|
||||
for label in response["labels"]:
|
||||
try:
|
||||
@@ -157,7 +159,6 @@ class LabelsPlugin(BasePlugin):
|
||||
if force or not wallet._get_label(key):
|
||||
wallet._set_label(key, value)
|
||||
|
||||
self.logger.info(f"received {len(response)} labels")
|
||||
self.set_nonce(wallet, response["nonce"] + 1)
|
||||
self.on_pulled(wallet)
|
||||
|
||||
@@ -173,15 +174,18 @@ class LabelsPlugin(BasePlugin):
|
||||
self.logger.info(repr(e))
|
||||
|
||||
def pull(self, wallet: 'Abstract_Wallet', force: bool):
|
||||
if not wallet.network: raise Exception(_('You are offline.'))
|
||||
if not wallet.network:
|
||||
raise Exception(_('You are offline.'))
|
||||
return asyncio.run_coroutine_threadsafe(self.pull_thread(wallet, force), wallet.network.asyncio_loop).result()
|
||||
|
||||
def push(self, wallet: 'Abstract_Wallet'):
|
||||
if not wallet.network: raise Exception(_('You are offline.'))
|
||||
if not wallet.network:
|
||||
raise Exception(_('You are offline.'))
|
||||
return asyncio.run_coroutine_threadsafe(self.push_thread(wallet), wallet.network.asyncio_loop).result()
|
||||
|
||||
def start_wallet(self, wallet: 'Abstract_Wallet'):
|
||||
if not wallet.network: return # 'offline' mode
|
||||
if not wallet.network:
|
||||
return # 'offline' mode
|
||||
mpk = wallet.get_fingerprint()
|
||||
if not mpk:
|
||||
return
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import threading
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.plugin import hook
|
||||
@@ -10,6 +10,7 @@ from electrum.gui.qml.plugins import PluginQObject
|
||||
|
||||
from .labels import LabelsPlugin
|
||||
|
||||
|
||||
class Plugin(LabelsPlugin):
|
||||
|
||||
class QSignalObject(PluginQObject):
|
||||
@@ -63,6 +64,8 @@ class Plugin(LabelsPlugin):
|
||||
|
||||
def __init__(self, *args):
|
||||
LabelsPlugin.__init__(self, *args)
|
||||
self._app = None
|
||||
self.so = None
|
||||
|
||||
@hook
|
||||
def load_wallet(self, wallet):
|
||||
@@ -77,9 +80,9 @@ class Plugin(LabelsPlugin):
|
||||
|
||||
wallet = self._app.daemon.currentWallet.wallet
|
||||
|
||||
def push_thread(wallet):
|
||||
def push_thread(_wallet):
|
||||
try:
|
||||
self.push(wallet)
|
||||
self.push(_wallet)
|
||||
self.so.upload_finished(True)
|
||||
self._app.appController.userNotify.emit(_('Labels uploaded'))
|
||||
except Exception as e:
|
||||
@@ -87,7 +90,7 @@ class Plugin(LabelsPlugin):
|
||||
self.so.upload_finished(False)
|
||||
self._app.appController.userNotify.emit(repr(e))
|
||||
|
||||
threading.Thread(target=push_thread,args=[wallet]).start()
|
||||
threading.Thread(target=push_thread, args=[wallet]).start()
|
||||
|
||||
def pull_async(self):
|
||||
if not self._app.daemon.currentWallet:
|
||||
@@ -96,9 +99,10 @@ class Plugin(LabelsPlugin):
|
||||
return
|
||||
|
||||
wallet = self._app.daemon.currentWallet.wallet
|
||||
def pull_thread(wallet):
|
||||
|
||||
def pull_thread(_wallet):
|
||||
try:
|
||||
self.pull(wallet, True)
|
||||
self.pull(_wallet, True)
|
||||
self.so.download_finished(True)
|
||||
self._app.appController.userNotify.emit(_('Labels downloaded'))
|
||||
except Exception as e:
|
||||
@@ -106,8 +110,7 @@ class Plugin(LabelsPlugin):
|
||||
self.so.download_finished(False)
|
||||
self._app.appController.userNotify.emit(repr(e))
|
||||
|
||||
threading.Thread(target=pull_thread,args=[wallet]).start()
|
||||
|
||||
threading.Thread(target=pull_thread, args=[wallet]).start()
|
||||
|
||||
def on_pulled(self, wallet):
|
||||
self.logger.info('on pulled')
|
||||
@@ -117,9 +120,15 @@ class Plugin(LabelsPlugin):
|
||||
_wallet.labelsUpdated.emit()
|
||||
|
||||
@hook
|
||||
def init_qml(self, gui):
|
||||
self.logger.debug(f'init_qml hook called, gui={str(type(gui))}')
|
||||
self._app = gui.app
|
||||
def init_qml(self, app):
|
||||
self.logger.debug(f'init_qml hook called, gui={str(type(app))}')
|
||||
self.logger.debug(f'app={self._app!r}, so={self.so!r}')
|
||||
self._app = app
|
||||
# important: QSignalObject needs to be parented, as keeping a ref
|
||||
# in the plugin is not enough to avoid gc
|
||||
self.so = Plugin.QSignalObject(self, self._app)
|
||||
|
||||
# If the user just enabled the plugin, the 'load_wallet' hook would not
|
||||
# get called for already loaded wallets, hence we call it manually for those:
|
||||
for wallet_name, wallet in app.daemon.daemon._wallets.items():
|
||||
self.load_wallet(wallet)
|
||||
|
||||
@@ -19,9 +19,10 @@ from .trustedcoin import (TrustedCoinPlugin, server, ErrorConnectingServer,
|
||||
TrustedCoinException, make_xpub)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from electrum.gui.qml import ElectrumGui
|
||||
from electrum.gui.qml import ElectrumQmlApplication
|
||||
from electrum.wallet import Abstract_Wallet
|
||||
|
||||
|
||||
class Plugin(TrustedCoinPlugin):
|
||||
|
||||
class QSignalObject(PluginQObject):
|
||||
@@ -287,9 +288,9 @@ class Plugin(TrustedCoinPlugin):
|
||||
self.start_request_thread(wallet)
|
||||
|
||||
@hook
|
||||
def init_qml(self, gui: 'ElectrumGui'):
|
||||
self.logger.debug(f'init_qml hook called, gui={str(type(gui))}')
|
||||
self._app = gui.app
|
||||
def init_qml(self, app: 'ElectrumQmlApplication'):
|
||||
self.logger.debug(f'init_qml hook called, gui={str(type(app))}')
|
||||
self._app = app
|
||||
# important: QSignalObject needs to be parented, as keeping a ref
|
||||
# in the plugin is not enough to avoid gc
|
||||
self.so = Plugin.QSignalObject(self, self._app)
|
||||
|
||||
Reference in New Issue
Block a user