1
0

qml: clean up, generalize plugin gui base, enumerate plugins in gui

(still quite crude impl, dynamic enable/disable plugin gui is misaligned
with backend)
This commit is contained in:
Sander van Grieken
2022-09-08 15:15:46 +02:00
parent 32a81d8ee7
commit 27999a9583
5 changed files with 101 additions and 35 deletions

View File

@@ -217,6 +217,7 @@ Pane {
Pane {
ColumnLayout {
x: constants.paddingXXLarge
id: pluginsRootLayout
}
}
@@ -232,12 +233,23 @@ Pane {
Component {
id: pluginHeader
RowLayout {
property QtObject plugin
Layout.leftMargin: -constants.paddingXXLarge
property string name
property string fullname
property bool pluginEnabled
Switch {
checked: plugin.pluginEnabled
checked: pluginEnabled
onCheckedChanged: {
if (activeFocus)
pluginEnabled = checked
}
}
Label {
text: plugin.name
text: fullname
}
onPluginEnabledChanged: {
console.log('!')
AppController.setPluginEnabled(name, pluginEnabled)
}
}
}
@@ -252,13 +264,16 @@ Pane {
spendUnconfirmed.checked = Config.spendUnconfirmed
lnRoutingType.currentIndex = Config.useGossip ? 0 : 1
var labelsPlugin = AppController.plugin('labels')
if (labelsPlugin) {
pluginHeader.createObject(pluginsRootLayout, { plugin: labelsPlugin })
// console.log(Qt.resolvedUrl(labelsPlugin.settingsComponent()))
if (labelsPlugin.settingsComponent()) {
var component = Qt.createComponent(Qt.resolvedUrl(labelsPlugin.settingsComponent()))
component.createObject(pluginsRootLayout, {plugin: labelsPlugin})
var plugins = AppController.plugins
for (var i=0; i<plugins.length; i++) {
var p = plugins[i]
pluginHeader.createObject(pluginsRootLayout, { name: p['name'], fullname: p['fullname'], pluginEnabled: p['enabled'] })
var labelsPlugin = AppController.plugin(p['name'])
if (labelsPlugin) {
if (labelsPlugin.settingsComponent()) {
var component = Qt.createComponent(Qt.resolvedUrl(labelsPlugin.settingsComponent()))
component.createObject(pluginsRootLayout, { plugin: labelsPlugin })
}
}
}
}

View File

@@ -349,7 +349,6 @@ ApplicationWindow
property bool _lockDialogShown: false
onActiveChanged: {
console.log('active='+active)
if (!active) {
// deactivated
_lastActive = Date.now()

View File

@@ -0,0 +1,40 @@
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, QObject
from electrum.i18n import _
from electrum.logging import get_logger
class PluginQObject(QObject):
logger = get_logger(__name__)
pluginChanged = pyqtSignal()
busyChanged = pyqtSignal()
pluginEnabledChanged = pyqtSignal()
_busy = False
def __init__(self, plugin, parent: 'ElectrumGuiApplication'):
super().__init__(parent)
self.plugin = plugin
self.app = parent
@pyqtProperty(str, notify=pluginChanged)
def name(self): return self._name
@pyqtProperty(bool, notify=busyChanged)
def busy(self): return self._busy
@pyqtProperty(bool, notify=pluginEnabledChanged)
def pluginEnabled(self): return self.plugin.is_enabled()
@pluginEnabled.setter
def pluginEnabled(self, enabled):
if enabled != self.plugin.is_enabled():
self.logger.debug(f'can {self.plugin.can_user_disable()}, {self.plugin.is_available()}')
if not self.plugin.can_user_disable() and not enabled:
return
if enabled:
self.app.plugins.enable(self.plugin.name)
else:
self.app.plugins.disable(self.plugin.name)
self.pluginEnabledChanged.emit()

View File

@@ -3,7 +3,7 @@ import queue
import time
import os
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QUrl, QLocale, qInstallMessageHandler, QTimer
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty, QObject, QUrl, QLocale, qInstallMessageHandler, QTimer
from PyQt5.QtGui import QGuiApplication, QFontDatabase
from PyQt5.QtQml import qmlRegisterType, qmlRegisterUncreatableType, QQmlApplicationEngine
@@ -34,6 +34,8 @@ notification = None
class QEAppController(QObject):
userNotify = pyqtSignal(str)
_dummy = pyqtSignal()
def __init__(self, qedaemon, plugins):
super().__init__()
self.logger = get_logger(__name__)
@@ -134,15 +136,37 @@ class QEAppController(QObject):
@pyqtSlot(str, result=QObject)
def plugin(self, plugin_name):
self.logger.warning(f'now {self._plugins.count()} plugins loaded')
self.logger.debug(f'now {self._plugins.count()} plugins loaded')
plugin = self._plugins.get(plugin_name)
self.logger.debug(f'plugin with name {plugin_name} is {str(type(plugin))}')
if plugin:
if plugin and hasattr(plugin,'so'):
return plugin.so
else:
self.logger.debug('None!')
return None
@pyqtProperty('QVariant', notify=_dummy)
def plugins(self):
s = []
for item in self._plugins.descriptions:
self.logger.info(item)
s.append({
'name': item,
'fullname': self._plugins.descriptions[item]['fullname'],
'enabled': bool(self._plugins.get(item))
})
self.logger.debug(f'{str(s)}')
return s
@pyqtSlot(str, bool)
def setPluginEnabled(self, plugin, enabled):
if enabled:
self._plugins.enable(plugin)
else:
self._plugins.disable(plugin)
class ElectrumQmlApplication(QGuiApplication):
_valid = True
@@ -190,10 +214,11 @@ class ElectrumQmlApplication(QGuiApplication):
self.fixedFont = 'Monospace' # hope for the best
self.context = self.engine.rootContext()
self.plugins = plugins
self._qeconfig = QEConfig(config)
self._qenetwork = QENetwork(daemon.network, self._qeconfig)
self.daemon = QEDaemon(daemon)
self.appController = QEAppController(self.daemon, plugins)
self.appController = QEAppController(self.daemon, self.plugins)
self._maxAmount = QEAmount(is_max=True)
self.context.setContextProperty('AppController', self.appController)
self.context.setContextProperty('Config', self._qeconfig)

View File

@@ -6,35 +6,23 @@ from electrum.i18n import _
from electrum.plugin import hook
from electrum.gui.qml.qewallet import QEWallet
from electrum.gui.qml.plugins import PluginQObject
from .labels import LabelsPlugin
class Plugin(LabelsPlugin):
class QSignalObject(QObject):
pluginChanged = pyqtSignal()
pluginEnabledChanged = pyqtSignal()
class QSignalObject(PluginQObject):
labelsChanged = pyqtSignal()
busyChanged = pyqtSignal()
uploadSuccess = pyqtSignal()
uploadFailed = pyqtSignal()
downloadSuccess = pyqtSignal()
downloadFailed = pyqtSignal()
_busy = False
_name = _('LabelSync Plugin')
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()
def __init__(self, plugin, parent):
super().__init__(plugin, parent)
@pyqtSlot(result=str)
def settingsComponent(self): return '../../../plugins/labels/Labels.qml'
@@ -78,7 +66,7 @@ class Plugin(LabelsPlugin):
@hook
def load_wallet(self, wallet):
self.logger.info(f'load_wallet hook for wallet {str(type(wallet))}')
self.logger.debug(f'plugin enabled for wallet "{str(wallet)}"')
self.start_wallet(wallet)
def push_async(self):
@@ -130,8 +118,7 @@ class Plugin(LabelsPlugin):
@hook
def init_qml(self, gui: 'ElectrumGui'):
self.logger.debug('init_qml hook called')
self.logger.debug(f'gui={str(type(gui))}')
self.logger.debug(f'init_qml hook called, 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