Browse Source

qt wizardcomponent receives qeabstractwizard instance

master
Sander van Grieken 2 years ago
parent
commit
1440eab5bf
  1. 27
      electrum/gui/qt/wizard/server_connect.py
  2. 58
      electrum/gui/qt/wizard/wizard.py

27
electrum/gui/qt/wizard/server_connect.py

@ -4,8 +4,8 @@ from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from electrum.i18n import _ from electrum.i18n import _
from .wizard import QEAbstractWizard, WizardComponent from .wizard import QEAbstractWizard, WizardComponent
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum import mnemonic
from electrum.wizard import ServerConnectWizard from electrum.wizard import ServerConnectWizard
from ..network_dialog import ProxyWidget, ServerWidget
from ..util import ChoicesLayout from ..util import ChoicesLayout
@ -26,8 +26,8 @@ class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard):
class WCAutoConnect(WizardComponent): class WCAutoConnect(WizardComponent):
def __init__(self, parent=None): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, title=_("How do you want to connect to a server? ")) WizardComponent.__init__(self, parent, wizard, title=_("How do you want to connect to a server? "))
message = _("Electrum communicates with remote servers to get " message = _("Electrum communicates with remote servers to get "
"information about your transactions and addresses. The " "information about your transactions and addresses. The "
"servers all fulfill the same purpose only differing in " "servers all fulfill the same purpose only differing in "
@ -35,8 +35,7 @@ class WCAutoConnect(WizardComponent):
"pick one at random. However if you prefer feel free to " "pick one at random. However if you prefer feel free to "
"select a server manually.") "select a server manually.")
choices = [_("Auto connect"), _("Select server manually")] choices = [_("Auto connect"), _("Select server manually")]
self.clayout = ChoicesLayout(message, choices) self.clayout = ChoicesLayout(message, choices, on_clicked=self.on_updated)
self.clayout.group.buttonClicked.connect(self.on_updated)
self.layout().addLayout(self.clayout.layout()) self.layout().addLayout(self.clayout.layout())
self._valid = True self._valid = True
@ -54,8 +53,8 @@ class WCAutoConnect(WizardComponent):
class WCProxyAsk(WizardComponent): class WCProxyAsk(WizardComponent):
def __init__(self, parent=None): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, title=_("Proxy")) WizardComponent.__init__(self, parent, wizard, title=_("Proxy"))
message = _("Do you use a local proxy service such as TOR to reach the internet?") message = _("Do you use a local proxy service such as TOR to reach the internet?")
choices = [_("Yes"), _("No")] choices = [_("Yes"), _("No")]
self.clayout = ChoicesLayout(message, choices) self.clayout = ChoicesLayout(message, choices)
@ -67,16 +66,22 @@ class WCProxyAsk(WizardComponent):
class WCProxyConfig(WizardComponent): class WCProxyConfig(WizardComponent):
def __init__(self, parent=None): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, title=_("Proxy")) WizardComponent.__init__(self, parent, wizard, title=_("Proxy"))
pw = ProxyWidget(self)
self.layout().addWidget(pw)
def apply(self): def apply(self):
# TODO
pass pass
class WCServerConfig(WizardComponent): class WCServerConfig(WizardComponent):
def __init__(self, parent=None): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, title=_("Server")) WizardComponent.__init__(self, parent, wizard, title=_("Server"))
sw = ServerWidget(self)
self.layout().addWidget(sw)
def apply(self): def apply(self):
# TODO
pass pass

58
electrum/gui/qt/wizard/wizard.py

@ -1,6 +1,7 @@
from abc import abstractmethod from abc import abstractmethod
from typing import Dict, Any
from PyQt5.QtCore import Qt, QVariant, QTimer, pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (QDialog, QApplication, QPushButton, QWidget, QLabel, QVBoxLayout, QScrollArea, from PyQt5.QtWidgets import (QDialog, QApplication, QPushButton, QWidget, QLabel, QVBoxLayout, QScrollArea,
QHBoxLayout, QLayout, QStackedWidget) QHBoxLayout, QLayout, QStackedWidget)
@ -77,18 +78,22 @@ class QEAbstractWizard(QDialog):
def load_next_component(self, view, wdata={}): def load_next_component(self, view, wdata={}):
comp = self.view_to_component(view) comp = self.view_to_component(view)
page = comp(self.main_widget) page = comp(self.main_widget, self)
page.wizard_data = wdata page.wizard_data = wdata
page.config = self.config
page.updated.connect(self.on_page_updated) page.updated.connect(self.on_page_updated)
self._logger.debug(f'{page!r}') self._logger.debug(f'{page!r}')
# add to stack and update wizard
self.main_widget.setCurrentIndex(self.main_widget.addWidget(page)) self.main_widget.setCurrentIndex(self.main_widget.addWidget(page))
page.apply() page.apply()
self.update(page.wizard_data) self.update()
@pyqtSlot(object) @pyqtSlot(object)
def on_page_updated(self, page): def on_page_updated(self, page):
page.apply() page.apply()
self.update(page.wizard_data) if page == self.main_widget.currentWidget():
self.update()
def set_icon(self, filename): def set_icon(self, filename):
prior_filename, self.icon_filename = self.icon_filename, filename prior_filename, self.icon_filename = self.icon_filename, filename
@ -96,25 +101,30 @@ class QEAbstractWizard(QDialog):
.scaledToWidth(60, mode=Qt.SmoothTransformation)) .scaledToWidth(60, mode=Qt.SmoothTransformation))
return prior_filename return prior_filename
def can_go_back(self): def can_go_back(self) -> bool:
return len(self._stack) > 0 return len(self._stack) > 0
def update(self, wdata: dict): def update(self):
page = self.main_widget.currentWidget()
self.title.setText(page.title)
self.back_button.setText(_('Back') if self.can_go_back() else _('Cancel')) self.back_button.setText(_('Back') if self.can_go_back() else _('Cancel'))
self.next_button.setText(_('Next') if not self.is_last(wdata) else _('Finish')) self.next_button.setText(_('Next') if not self.is_last(page.wizard_data) else _('Finish'))
self.next_button.setEnabled(page.valid)
self.main_widget.setVisible(not page.busy)
self.please_wait.setVisible(page.busy)
def on_back_button_clicked(self): def on_back_button_clicked(self):
if self.can_go_back(): if self.can_go_back():
wdata = self.prev() self.prev()
self.main_widget.removeWidget(self.main_widget.currentWidget()) self.main_widget.removeWidget(self.main_widget.currentWidget())
self.update(wdata) self.update()
else: else:
self.close() self.close()
def on_next_button_clicked(self): def on_next_button_clicked(self):
wc = self.main_widget.currentWidget() page = self.main_widget.currentWidget()
wc.apply() page.apply()
wd = wc.wizard_data.copy() wd = page.wizard_data.copy()
if self.is_last(wd): if self.is_last(wd):
self.finished(wd) self.finished(wd)
self.close() self.close()
@ -131,7 +141,6 @@ class QEAbstractWizard(QDialog):
def submit(self, wizard_data) -> dict: def submit(self, wizard_data) -> dict:
wdata = wizard_data.copy() wdata = wizard_data.copy()
self.log_state(wdata)
view = self.resolve_next(self._current.view, wdata) view = self.resolve_next(self._current.view, wdata)
return { return {
'view': view.view, 'view': view.view,
@ -147,23 +156,38 @@ class QEAbstractWizard(QDialog):
return self.is_last_view(self._current.view, wdata) return self.is_last_view(self._current.view, wdata)
### support classes
class WizardComponent(QWidget): class WizardComponent(QWidget):
updated = pyqtSignal(object) updated = pyqtSignal(object)
def __init__(self, parent: QWidget = None, *, title: str = None, layout: QLayout = None): def __init__(self, parent: QWidget, wizard: QEAbstractWizard, *, title: str = None, layout: QLayout = None):
super().__init__(parent) super().__init__(parent)
self.setLayout(layout if layout else QVBoxLayout(self)) self.setLayout(layout if layout else QVBoxLayout(self))
self.wizard_data = {} self.wizard_data = {}
self.title = title if title is not None else 'No title' self.title = title if title is not None else 'No title'
self.wizard = wizard
self._valid = False self._valid = False
self._busy = False
@property @property
def valid(self): def valid(self):
return self._valid return self._valid
@valid.setter
def valid(self, is_valid):
if self._valid != is_valid:
self._valid = is_valid
self.on_updated()
@property
def busy(self):
return self._busy
@busy.setter
def busy(self, is_busy):
if self._busy != is_busy:
self._busy = is_busy
self.on_updated()
@abstractmethod @abstractmethod
def apply(self): def apply(self):
pass pass

Loading…
Cancel
Save