Browse Source

plugins dialog: show description and enable buttons in the same dialog

master
ThomasV 1 year ago
parent
commit
7c6ff6757c
  1. 158
      electrum/gui/qt/plugins_dialog.py
  2. 4
      electrum/plugin.py

158
electrum/gui/qt/plugins_dialog.py

@ -1,20 +1,87 @@
from typing import TYPE_CHECKING, Optional
from functools import partial
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QGridLayout, QPushButton, QComboBox, QLineEdit, QSpacerItem, QWidget, QHBoxLayout, QScrollArea, QCheckBox
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QGridLayout, QPushButton, QComboBox, QLineEdit, QSpacerItem, QWidget, QHBoxLayout, QScrollArea, QCheckBox, QFormLayout
from electrum.i18n import _
from electrum.gui import messages
from electrum.plugin import run_hook, BasePlugin
from . import util
from .util import WindowModalDialog, Buttons, CloseButton, HelpButton
from .util import WindowModalDialog, Buttons, CloseButton, HelpButton, WWLabel
if TYPE_CHECKING:
from .main_window import ElectrumWindow
class PluginDialog(WindowModalDialog):
def __init__(self, name, metadata, cb: 'QCheckBox', window: 'ElectrumWindow', index:int):
display_name = metadata.get('display_name', '')
author = metadata.get('author', '')
description = metadata.get('description', '')
requires = metadata.get('requires')
version = metadata.get('version', 'n/a')
WindowModalDialog.__init__(self, window, 'Plugin')
self.setMinimumSize(400,250)
self.index = index
self.window = window
self.metadata = metadata
self.plugins = self.window.plugins
self.name = name
self.cb = cb
p = self.plugins.get(name) # is installed
vbox = QVBoxLayout(self)
form = QFormLayout(None)
form.addRow(QLabel(_('Name') + ':'), QLabel(display_name))
form.addRow(QLabel(_('Author') + ':'), QLabel(author))
form.addRow(QLabel(_('Description') + ':'), WWLabel(description))
form.addRow(QLabel(_('Version') + ':'), QLabel(version))
if requires:
msg = '\n'.join(map(lambda x: x[1], requires))
form.addRow(QLabel(_('Requires') + ':'), WWLabel(msg))
vbox.addLayout(form)
if name in self.plugins.internal_plugin_metadata:
text = _('Disable') if p else _('Enable')
else:
text = _('Remove') if p else _('Install')
toggle_button = QPushButton(text)
toggle_button.clicked.connect(partial(self.do_toggle, toggle_button, name))
close_button = CloseButton(self)
close_button.setText(_('Cancel'))
buttons = [toggle_button, close_button]
vbox.addLayout(Buttons(*buttons))
def do_toggle(self, button, name):
button.setEnabled(False)
if name in self.plugins.internal_plugin_metadata:
p = self.plugins.toggle(name)
self.cb.setChecked(bool(p))
else:
p = self.plugins.get(name)
if not p:
#if not self.window.window.question("Install plugin '%s'?"%name):
# return
coro = self.plugins.download_external_plugin(name)
def on_success(x):
self.plugins.enable(name)
p = self.plugins.get(name)
self.cb.setChecked(bool(p))
self.window.window.run_coroutine_from_thread(coro, "Downloading '%s' "%name, on_result=on_success)
else:
#if not self.window.window.question("Remove plugin '%s'?"%name):
# return
self.plugins.disable(name)
self.cb.setChecked(False)
self.plugins.remove_external_plugin(name)
self.close()
self.window.enable_settings_widget(name, self.index)
# note: all enabled plugins will receive this hook:
run_hook('init_qt', self.window.window.gui_object)
class PluginsDialog(WindowModalDialog):
@ -23,27 +90,24 @@ class PluginsDialog(WindowModalDialog):
self.window = window
self.wallet = self.window.wallet
self.config = window.config
self.plugins = self.window.gui_object.plugins
self.settings_widgets = {}
vbox = QVBoxLayout(self)
# plugins
scroll = QScrollArea()
scroll.setEnabled(True)
scroll.setWidgetResizable(True)
scroll.setMinimumSize(400,250)
self.scroll_w = QWidget()
scroll.setWidget(self.scroll_w)
vbox.addWidget(scroll)
vbox.addLayout(Buttons(CloseButton(self)))
self.settings_widgets = {}
scroll_w = QWidget()
scroll.setWidget(scroll_w)
self.grid = QGridLayout()
self.grid.setColumnStretch(0,1)
self.scroll_w.setLayout(self.grid)
scroll_w.setLayout(self.grid)
vbox.addWidget(scroll)
vbox.addLayout(Buttons(CloseButton(self)))
self.show_list()
def enable_settings_widget(self, p: Optional['BasePlugin'], name: str, i: int):
def enable_settings_widget(self, name: str, i: int):
p = self.plugins.get(name)
widget = self.settings_widgets.get(name) # type: Optional[QWidget]
if widget and not p:
# plugin got disabled, rm widget
@ -55,50 +119,34 @@ class PluginsDialog(WindowModalDialog):
widget = self.settings_widgets[name] = p.settings_widget(self)
self.grid.addWidget(widget, i, 1)
def do_toggle(self, cb, name, i):
if self.plugins.requires_download(name):
cb.setChecked(False)
self.download_plugin_dialog(cb, name, i)
return
p = self.plugins.toggle(name)
cb.setChecked(bool(p))
self.enable_settings_widget(p, name, i)
# note: all enabled plugins will receive this hook:
run_hook('init_qt', self.window.gui_object)
def download_plugin_dialog(self, cb, name, i):
import asyncio
if not self.window.question("Download plugin '%s'?"%name):
return
coro = self.plugins.download_external_plugin(name)
def on_success(x):
self.do_toggle(cb, name, i)
self.window.run_coroutine_dialog(coro, "Downloading '%s' "%name, on_result=on_success, on_cancelled=None)
def show_list(self):
descriptions = sorted(self.plugins.descriptions.items())
descriptions = self.plugins.descriptions
descriptions = sorted(descriptions.items())
grid = self.grid
i = 0
for name, descr in descriptions:
for name, metadata in descriptions:
i += 1
p = self.plugins.get(name)
if descr.get('registers_keystore'):
if metadata.get('registers_keystore'):
continue
try:
cb = QCheckBox(descr['display_name'])
plugin_is_loaded = p is not None
cb_enabled = (not plugin_is_loaded and self.plugins.is_available(name, self.wallet)
or plugin_is_loaded and p.can_user_disable())
cb.setEnabled(cb_enabled)
cb.setChecked(plugin_is_loaded and p.is_enabled())
self.grid.addWidget(cb, i, 0)
self.enable_settings_widget(p, name, i)
cb.clicked.connect(partial(self.do_toggle, cb, name, i))
msg = descr['description']
if descr.get('requires'):
msg += '\n\n' + _('Requires') + ':\n' + '\n'.join(map(lambda x: x[1], descr.get('requires')))
self.grid.addWidget(HelpButton(msg), i, 2)
except Exception:
self.window.logger.exception(f"cannot display plugin {name}")
self.grid.setRowStretch(len(descriptions), 1)
display_name = metadata.get('display_name')
if not display_name:
continue
#try:
cb = QCheckBox(display_name)
plugin_is_loaded = p is not None
cb_enabled = (not plugin_is_loaded and self.plugins.is_available(name, self.wallet)
or plugin_is_loaded and p.can_user_disable())
cb.setEnabled(cb_enabled)
cb.setChecked(plugin_is_loaded and p.is_enabled())
grid.addWidget(cb, i, 0)
self.enable_settings_widget(name, i)
cb.clicked.connect(partial(self.show_plugin_dialog, name, metadata, cb, i))
#grid.setRowStretch(len(descriptions), 1)
def show_plugin_dialog(self, name, metadata, cb, i):
p = self.plugins.get(name)
cb.setChecked(p is not None and p.is_enabled())
d = PluginDialog(name, metadata, cb, self, i)
d.exec()

4
electrum/plugin.py

@ -178,6 +178,10 @@ class Plugins(DaemonThread):
os.unlink(filename)
raise Exception(f"wrong plugin hash {name}")
def remove_external_plugin(self, name):
filename = self.external_plugin_path(name)
os.unlink(filename)
def load_external_plugin(self, name):
if name in self.plugins:
return self.plugins[name]

Loading…
Cancel
Save