Browse Source

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

(still quite crude impl, dynamic enable/disable plugin gui is misaligned
with backend)
patch-4
Sander van Grieken 2 years ago
parent
commit
27999a9583
  1. 35
      electrum/gui/qml/components/Preferences.qml
  2. 1
      electrum/gui/qml/components/main.qml
  3. 40
      electrum/gui/qml/plugins.py
  4. 33
      electrum/gui/qml/qeapp.py
  5. 27
      electrum/plugins/labels/qml.py

35
electrum/gui/qml/components/Preferences.qml

@ -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 })
}
}
}
}

1
electrum/gui/qml/components/main.qml

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

40
electrum/gui/qml/plugins.py

@ -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()

33
electrum/gui/qml/qeapp.py

@ -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)

27
electrum/plugins/labels/qml.py

@ -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

Loading…
Cancel
Save