9 changed files with 416 additions and 161 deletions
@ -0,0 +1,45 @@ |
|||||||
|
import QtQuick 2.6 |
||||||
|
import QtQuick.Layouts 1.0 |
||||||
|
import QtQuick.Controls 2.14 |
||||||
|
import QtQuick.Controls.Material 2.0 |
||||||
|
|
||||||
|
import org.electrum 1.0 |
||||||
|
|
||||||
|
//import "controls" |
||||||
|
|
||||||
|
Item { |
||||||
|
width: parent.width |
||||||
|
height: rootLayout.height |
||||||
|
|
||||||
|
property QtObject plugin |
||||||
|
|
||||||
|
RowLayout { |
||||||
|
id: rootLayout |
||||||
|
Button { |
||||||
|
text: 'Force upload' |
||||||
|
enabled: !plugin.busy |
||||||
|
onClicked: plugin.upload() |
||||||
|
} |
||||||
|
Button { |
||||||
|
text: 'Force download' |
||||||
|
enabled: !plugin.busy |
||||||
|
onClicked: plugin.download() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Connections { |
||||||
|
target: plugin |
||||||
|
function onUploadSuccess() { |
||||||
|
console.log('upload success') |
||||||
|
} |
||||||
|
function onUploadFailed() { |
||||||
|
console.log('upload failed') |
||||||
|
} |
||||||
|
function onDownloadSuccess() { |
||||||
|
console.log('download success') |
||||||
|
} |
||||||
|
function onDownloadFailed() { |
||||||
|
console.log('download failed') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,138 @@ |
|||||||
|
import threading |
||||||
|
|
||||||
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot |
||||||
|
|
||||||
|
from electrum.i18n import _ |
||||||
|
from electrum.plugin import hook |
||||||
|
|
||||||
|
from electrum.gui.qml.qewallet import QEWallet |
||||||
|
|
||||||
|
from .labels import LabelsPlugin |
||||||
|
|
||||||
|
class Plugin(LabelsPlugin): |
||||||
|
|
||||||
|
class QSignalObject(QObject): |
||||||
|
pluginChanged = pyqtSignal() |
||||||
|
pluginEnabledChanged = pyqtSignal() |
||||||
|
labelsChanged = pyqtSignal() |
||||||
|
busyChanged = pyqtSignal() |
||||||
|
uploadSuccess = pyqtSignal() |
||||||
|
uploadFailed = pyqtSignal() |
||||||
|
downloadSuccess = pyqtSignal() |
||||||
|
downloadFailed = pyqtSignal() |
||||||
|
|
||||||
|
_busy = False |
||||||
|
|
||||||
|
def __init__(self, plugin, parent = None): |
||||||
|
super().__init__(parent) |
||||||
|
self.plugin = plugin |
||||||
|
|
||||||
|
@pyqtProperty(str, notify=pluginChanged) |
||||||
|
def name(self): return _('Labels Plugin') |
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=busyChanged) |
||||||
|
def busy(self): return self._busy |
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=pluginEnabledChanged) |
||||||
|
def pluginEnabled(self): return self.plugin.is_enabled() |
||||||
|
|
||||||
|
@pyqtSlot(result=str) |
||||||
|
def settingsComponent(self): return '../../../plugins/labels/Labels.qml' |
||||||
|
|
||||||
|
@pyqtSlot() |
||||||
|
def upload(self): |
||||||
|
assert self.plugin |
||||||
|
|
||||||
|
self._busy = True |
||||||
|
self.busyChanged.emit() |
||||||
|
|
||||||
|
self.plugin.push_async() |
||||||
|
|
||||||
|
def upload_finished(self, result): |
||||||
|
if result: |
||||||
|
self.uploadSuccess.emit() |
||||||
|
else: |
||||||
|
self.uploadFailed.emit() |
||||||
|
self._busy = False |
||||||
|
self.busyChanged.emit() |
||||||
|
|
||||||
|
@pyqtSlot() |
||||||
|
def download(self): |
||||||
|
assert self.plugin |
||||||
|
|
||||||
|
self._busy = True |
||||||
|
self.busyChanged.emit() |
||||||
|
|
||||||
|
self.plugin.pull_async() |
||||||
|
|
||||||
|
def download_finished(self, result): |
||||||
|
if result: |
||||||
|
self.downloadSuccess.emit() |
||||||
|
else: |
||||||
|
self.downloadFailed.emit() |
||||||
|
self._busy = False |
||||||
|
self.busyChanged.emit() |
||||||
|
|
||||||
|
def __init__(self, *args): |
||||||
|
LabelsPlugin.__init__(self, *args) |
||||||
|
|
||||||
|
@hook |
||||||
|
def load_wallet(self, wallet): |
||||||
|
self.logger.info(f'load_wallet hook for wallet {str(type(wallet))}') |
||||||
|
self.start_wallet(wallet) |
||||||
|
|
||||||
|
def push_async(self): |
||||||
|
if not self._app.daemon.currentWallet: |
||||||
|
self.logger.error('No current wallet') |
||||||
|
self.so.download_finished(False) |
||||||
|
return |
||||||
|
|
||||||
|
wallet = self._app.daemon.currentWallet.wallet |
||||||
|
|
||||||
|
def push_thread(wallet): |
||||||
|
try: |
||||||
|
self.push(wallet) |
||||||
|
self.so.upload_finished(True) |
||||||
|
self._app.appController.userNotify.emit(_('Labels uploaded')) |
||||||
|
except Exception as e: |
||||||
|
self.logger.error(repr(e)) |
||||||
|
self.so.upload_finished(False) |
||||||
|
self._app.appController.userNotify.emit(repr(e)) |
||||||
|
|
||||||
|
threading.Thread(target=push_thread,args=[wallet]).start() |
||||||
|
|
||||||
|
def pull_async(self): |
||||||
|
if not self._app.daemon.currentWallet: |
||||||
|
self.logger.error('No current wallet') |
||||||
|
self.so.download_finished(False) |
||||||
|
return |
||||||
|
|
||||||
|
wallet = self._app.daemon.currentWallet.wallet |
||||||
|
def pull_thread(wallet): |
||||||
|
try: |
||||||
|
self.pull(wallet, True) |
||||||
|
self.so.download_finished(True) |
||||||
|
self._app.appController.userNotify.emit(_('Labels downloaded')) |
||||||
|
except Exception as e: |
||||||
|
self.logger.error(repr(e)) |
||||||
|
self.so.download_finished(False) |
||||||
|
self._app.appController.userNotify.emit(repr(e)) |
||||||
|
|
||||||
|
threading.Thread(target=pull_thread,args=[wallet]).start() |
||||||
|
|
||||||
|
|
||||||
|
def on_pulled(self, wallet): |
||||||
|
self.logger.info('on pulled') |
||||||
|
_wallet = QEWallet.getInstanceFor(wallet) |
||||||
|
self.logger.debug('wallet ' + ('found' if _wallet else 'not found')) |
||||||
|
if _wallet: |
||||||
|
_wallet.labelsUpdated.emit() |
||||||
|
|
||||||
|
@hook |
||||||
|
def init_qml(self, gui: 'ElectrumGui'): |
||||||
|
self.logger.debug('init_qml hook called') |
||||||
|
self.logger.debug(f'gui={str(type(gui))}') |
||||||
|
self._app = gui.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) |
||||||
Loading…
Reference in new issue