Browse Source

Merge pull request #8737 from accumulator/welcome_page

qt,qml: add a welcome page as initial page for server connect wizard
master
accumulator 2 years ago committed by GitHub
parent
commit
9ea15a1c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. BIN
      electrum/gui/icons/electrum_darkblue_1.png
  2. BIN
      electrum/gui/icons/electrum_text.png
  3. 49
      electrum/gui/qml/components/wizard/WCAutoConnect.qml
  4. 43
      electrum/gui/qml/components/wizard/WCProxyAsk.qml
  5. 1
      electrum/gui/qml/components/wizard/WCProxyConfig.qml
  6. 3
      electrum/gui/qml/components/wizard/WCServerConfig.qml
  7. 59
      electrum/gui/qml/components/wizard/WCWelcome.qml
  8. 3
      electrum/gui/qml/components/wizard/Wizard.qml
  9. 1
      electrum/gui/qml/components/wizard/WizardComponent.qml
  10. 3
      electrum/gui/qml/qewizard.py
  11. 99
      electrum/gui/qt/wizard/server_connect.py
  12. 3
      electrum/gui/qt/wizard/wallet.py
  13. 18
      electrum/gui/qt/wizard/wizard.py
  14. 41
      electrum/wizard.py

BIN
electrum/gui/icons/electrum_darkblue_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
electrum/gui/icons/electrum_text.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

49
electrum/gui/qml/components/wizard/WCAutoConnect.qml

@ -1,49 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../controls"
WizardComponent {
valid: true
function apply() {
wizard_data['autoconnect'] = serverconnectgroup.checkedButton.connecttype === 'auto'
}
ColumnLayout {
width: parent.width
Label {
Layout.fillWidth: true
text: qsTr('How do you want to connect to a server?')
wrapMode: Text.Wrap
}
InfoTextArea {
Layout.fillWidth: true
text: qsTr('Electrum communicates with remote servers to get information about your transactions and addresses. The servers all fulfill the same purpose only differing in hardware. In most cases you simply want to let Electrum pick one at random. However if you prefer feel free to select a server manually.')
}
ButtonGroup {
id: serverconnectgroup
onCheckedButtonChanged: checkIsLast()
}
ElRadioButton {
Layout.fillWidth: true
ButtonGroup.group: serverconnectgroup
property string connecttype: 'auto'
text: qsTr('Auto connect')
checked: true
}
ElRadioButton {
Layout.fillWidth: true
ButtonGroup.group: serverconnectgroup
property string connecttype: 'manual'
text: qsTr('Select servers manually')
}
}
}

43
electrum/gui/qml/components/wizard/WCProxyAsk.qml

@ -1,43 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Controls.Material
import "../controls"
WizardComponent {
valid: true
function apply() {
wizard_data['want_proxy'] = wantproxygroup.checkedButton.wantproxy
}
ColumnLayout {
width: parent.width
Label {
Layout.fillWidth: true
text: qsTr('Do you use a local proxy service such as TOR to reach the internet?')
wrapMode: Text.Wrap
}
ButtonGroup {
id: wantproxygroup
onCheckedButtonChanged: checkIsLast()
}
ElRadioButton {
ButtonGroup.group: wantproxygroup
property bool wantproxy: true
text: qsTr('Yes')
}
ElRadioButton {
ButtonGroup.group: wantproxygroup
property bool wantproxy: false
text: qsTr('No')
checked: true
}
}
}

1
electrum/gui/qml/components/wizard/WCProxyConfig.qml

@ -6,6 +6,7 @@ import "../controls"
WizardComponent { WizardComponent {
valid: true valid: true
title: qsTr('Proxy')
function apply() { function apply() {
wizard_data['proxy'] = pc.toProxyDict() wizard_data['proxy'] = pc.toProxyDict()

3
electrum/gui/qml/components/wizard/WCServerConfig.qml

@ -7,9 +7,10 @@ import "../controls"
WizardComponent { WizardComponent {
valid: true valid: true
last: true last: true
title: qsTr('Server')
function apply() { function apply() {
wizard_data['autoconnect'] = sc.address == "" wizard_data['autoconnect'] = sc.address.trim() == ""
wizard_data['server'] = sc.address wizard_data['server'] = sc.address
} }

59
electrum/gui/qml/components/wizard/WCWelcome.qml

@ -0,0 +1,59 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../controls"
WizardComponent {
valid: true
wizard_title: qsTr('Electrum Bitcoin Wallet')
function apply() {
wizard_data['use_defaults'] = !config_advanced.checked
wizard_data['want_proxy'] = config_advanced.checked && config_proxy.checked
wizard_data['autoconnect'] = !config_server.checked || !config_advanced.checked
}
ColumnLayout {
width: parent.width
Image {
Layout.fillWidth: true
fillMode: Image.PreserveAspectFit
source: Qt.resolvedUrl('../../../icons/electrum_presplash.png')
// reduce spacing a bit
Layout.topMargin: -50
Layout.bottomMargin: -120
}
CheckBox {
id: config_advanced
Layout.alignment: Qt.AlignHCenter
text: qsTr('Advanced network settings')
checked: false
onCheckedChanged: checkIsLast()
}
ColumnLayout {
Layout.alignment: Qt.AlignHCenter
opacity: config_advanced.checked ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: 300 }
}
CheckBox {
id: config_proxy
text: qsTr('Configure Proxy')
checked: false
onCheckedChanged: checkIsLast()
}
CheckBox {
id: config_server
text: qsTr('Select Server')
checked: false
onCheckedChanged: checkIsLast()
}
}
}
}

3
electrum/gui/qml/components/wizard/Wizard.qml

@ -15,7 +15,8 @@ ElDialog {
padding: 0 padding: 0
title: wizardTitle + (pages.currentItem.title ? ' - ' + pages.currentItem.title : '') title: (pages.currentItem.wizard_title ? pages.currentItem.wizard_title : wizardTitle) +
(pages.currentItem.title ? ' - ' + pages.currentItem.title : '')
iconSource: '../../../icons/electrum.png' iconSource: '../../../icons/electrum.png'
// android back button triggers close() on Popups. Disabling close here, // android back button triggers close() on Popups. Disabling close here,

1
electrum/gui/qml/components/wizard/WizardComponent.qml

@ -10,6 +10,7 @@ Pane {
property var wizard_data : ({}) property var wizard_data : ({})
property bool valid property bool valid
property bool last: false property bool last: false
property string wizard_title: ''
property string title: '' property string title: ''
property bool securePage: false property bool securePage: false

3
electrum/gui/qml/qewizard.py

@ -147,8 +147,7 @@ class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard):
# attach view names # attach view names
self.navmap_merge({ self.navmap_merge({
'autoconnect': {'gui': 'WCAutoConnect'}, 'welcome': {'gui': 'WCWelcome'},
'proxy_ask': {'gui': 'WCProxyAsk'},
'proxy_config': {'gui': 'WCProxyConfig'}, 'proxy_config': {'gui': 'WCProxyConfig'},
'server_config': {'gui': 'WCServerConfig'}, 'server_config': {'gui': 'WCServerConfig'},
}) })

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

@ -1,9 +1,13 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QCheckBox, QLabel, QHBoxLayout, QVBoxLayout, QWidget
from electrum.i18n import _ from electrum.i18n import _
from electrum.wizard import ServerConnectWizard from electrum.wizard import ServerConnectWizard
from electrum.gui.qt.network_dialog import ProxyWidget, ServerWidget from electrum.gui.qt.network_dialog import ProxyWidget, ServerWidget
from electrum.gui.qt.util import ChoiceWidget from electrum.gui.qt.util import icon_path
from .wizard import QEAbstractWizard, WizardComponent from .wizard import QEAbstractWizard, WizardComponent
if TYPE_CHECKING: if TYPE_CHECKING:
@ -18,59 +22,72 @@ class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard):
def __init__(self, config: 'SimpleConfig', app: 'QElectrumApplication', plugins: 'Plugins', daemon: 'Daemon', parent=None): def __init__(self, config: 'SimpleConfig', app: 'QElectrumApplication', plugins: 'Plugins', daemon: 'Daemon', parent=None):
ServerConnectWizard.__init__(self, daemon) ServerConnectWizard.__init__(self, daemon)
QEAbstractWizard.__init__(self, config, app) QEAbstractWizard.__init__(self, config, app)
self.window_title = _('Network and server configuration')
self.setWindowTitle(_('Network and server configuration')) self.finish_label = _('Next')
# attach gui classes # attach gui classes
self.navmap_merge({ self.navmap_merge({
'autoconnect': { 'gui': WCAutoConnect }, 'welcome': {'gui': WCWelcome, 'params': {'icon': ''}},
'proxy_ask': { 'gui': WCProxyAsk }, 'proxy_config': {'gui': WCProxyConfig},
'proxy_config': { 'gui': WCProxyConfig }, 'server_config': {'gui': WCServerConfig},
'server_config': { 'gui': WCServerConfig },
}) })
class WCAutoConnect(WizardComponent): class WCWelcome(WizardComponent):
def __init__(self, parent, wizard): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, wizard, title=_("How do you want to connect to a server? ")) WizardComponent.__init__(self, parent, wizard, title='')
message = _("Electrum communicates with remote servers to get " self.wizard_title = _('Electrum Bitcoin Wallet')
"information about your transactions and addresses. The " self.use_advanced_w = QCheckBox(_('Advanced network settings'))
"servers all fulfill the same purpose only differing in " self.use_advanced_w.setChecked(False)
"hardware. In most cases you simply want to let Electrum " self.use_advanced_w.stateChanged.connect(self.on_advanced_changed)
"pick one at random. However if you prefer feel free to "
"select a server manually.") self.img_label = QLabel()
choices = [('autoconnect', _("Auto connect")), pixmap = QPixmap(icon_path('electrum_darkblue_1.png'))
('select', _("Select server manually"))] self.img_label.setPixmap(pixmap)
self.choice_w = ChoiceWidget(message=message, choices=choices, selected='autoconnect') self.img_label2 = QLabel()
self.choice_w.itemSelected.connect(self.on_updated) pixmap = QPixmap(icon_path('electrum_text.png'))
self.layout().addWidget(self.choice_w) self.img_label2.setPixmap(pixmap)
self.layout().addStretch(1) hbox_img = QHBoxLayout()
hbox_img.addStretch(1)
hbox_img.addWidget(self.img_label)
hbox_img.addWidget(self.img_label2)
hbox_img.addStretch(1)
self.config_proxy_w = QCheckBox(_('Configure Proxy'))
self.config_proxy_w.setChecked(False)
self.config_proxy_w.setVisible(False)
self.config_proxy_w.stateChanged.connect(self.on_updated)
self.config_server_w = QCheckBox(_('Select Server'))
self.config_server_w.setChecked(False)
self.config_server_w.setVisible(False)
self.config_server_w.stateChanged.connect(self.on_updated)
options_w = QWidget()
vbox = QVBoxLayout()
vbox.addWidget(self.config_proxy_w)
vbox.addWidget(self.config_server_w)
vbox.addStretch(1)
options_w.setLayout(vbox)
self.layout().addLayout(hbox_img)
self.layout().addSpacing(50)
self.layout().addWidget(self.use_advanced_w, False, Qt.AlignHCenter)
self.layout().addWidget(options_w, False, Qt.AlignHCenter)
self._valid = True self._valid = True
def apply(self): def on_advanced_changed(self):
self.wizard_data['autoconnect'] = (self.choice_w.selected_item[0] == 'autoconnect') self.config_proxy_w.setVisible(self.use_advanced_w.isChecked())
self.config_server_w.setVisible(self.use_advanced_w.isChecked())
self.on_updated()
class WCProxyAsk(WizardComponent):
def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, wizard, title=_("Proxy"))
message = _("Do you use a local proxy service such as TOR to reach the internet?")
choices = [
('no', _("No")),
('yes', _("Yes")),
]
self.choice_w = ChoiceWidget(message=message, choices=choices, selected='no')
self.layout().addWidget(self.choice_w)
self.layout().addStretch(1)
self._valid = True
def apply(self): def apply(self):
self.wizard_data['want_proxy'] = (self.choice_w.selected_item[0] == 'yes') self.wizard_data['use_defaults'] = not self.use_advanced_w.isChecked()
self.wizard_data['want_proxy'] = self.use_advanced_w.isChecked() and self.config_proxy_w.isChecked()
self.wizard_data['autoconnect'] = not self.use_advanced_w.isChecked() or not self.config_server_w.isChecked()
class WCProxyConfig(WizardComponent): class WCProxyConfig(WizardComponent):
def __init__(self, parent, wizard): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, wizard, title=_("Proxy")) WizardComponent.__init__(self, parent, wizard, title=_('Proxy'))
self.pw = ProxyWidget(self) self.pw = ProxyWidget(self)
self.pw.proxy_cb.setChecked(True) self.pw.proxy_cb.setChecked(True)
self.pw.proxy_host.setText('localhost') self.pw.proxy_host.setText('localhost')
@ -85,11 +102,11 @@ class WCProxyConfig(WizardComponent):
class WCServerConfig(WizardComponent): class WCServerConfig(WizardComponent):
def __init__(self, parent, wizard): def __init__(self, parent, wizard):
WizardComponent.__init__(self, parent, wizard, title=_("Server")) WizardComponent.__init__(self, parent, wizard, title=_('Server'))
self.sw = ServerWidget(wizard._daemon.network, self) self.sw = ServerWidget(wizard._daemon.network, self)
self.layout().addWidget(self.sw) self.layout().addWidget(self.sw)
self._valid = True self._valid = True
def apply(self): def apply(self):
self.wizard_data['autoconnect'] = self.sw.autoconnect_cb.isChecked() self.wizard_data['autoconnect'] = self.sw.server_e.text().strip() == ''
self.wizard_data['server'] = self.sw.server_e.text() self.wizard_data['server'] = self.sw.server_e.text()

3
electrum/gui/qt/wizard/wallet.py

@ -55,8 +55,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard, MessageBoxMixin):
def __init__(self, config: 'SimpleConfig', app: 'QElectrumApplication', plugins: 'Plugins', daemon: Daemon, path, *, start_viewstate=None): def __init__(self, config: 'SimpleConfig', app: 'QElectrumApplication', plugins: 'Plugins', daemon: Daemon, path, *, start_viewstate=None):
NewWalletWizard.__init__(self, daemon, plugins) NewWalletWizard.__init__(self, daemon, plugins)
QEAbstractWizard.__init__(self, config, app, start_viewstate=start_viewstate) QEAbstractWizard.__init__(self, config, app, start_viewstate=start_viewstate)
self.window_title = _('Create/Restore wallet')
self.setWindowTitle(_('Create/Restore wallet'))
self._path = path self._path = path
self._password = None self._password = None

18
electrum/gui/qt/wizard/wizard.py

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtSlot, QSize from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtSlot, QSize
from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (QDialog, QPushButton, QWidget, QLabel, QVBoxLayout, QScrollArea, from PyQt5.QtWidgets import (QDialog, QPushButton, QWidget, QLabel, QVBoxLayout, QScrollArea,
QHBoxLayout, QLayout, QStackedWidget) QHBoxLayout, QLayout)
from electrum.i18n import _ from electrum.i18n import _
from electrum.logging import get_logger from electrum.logging import get_logger
@ -39,6 +39,8 @@ class QEAbstractWizard(QDialog, MessageBoxMixin):
self.setMinimumSize(600, 400) self.setMinimumSize(600, 400)
self.title = QLabel() self.title = QLabel()
self.window_title = ''
self.finish_label = _('Finish')
self.main_widget = ResizableStackedWidget(self) self.main_widget = ResizableStackedWidget(self)
@ -63,9 +65,6 @@ class QEAbstractWizard(QDialog, MessageBoxMixin):
error_layout = QVBoxLayout() error_layout = QVBoxLayout()
error_layout.addStretch(1) error_layout.addStretch(1)
# error_l = QLabel(_("Error!"))
# error_l.setAlignment(Qt.AlignCenter)
# error_layout.addWidget(error_l)
self.error_msg = WWLabel() self.error_msg = WWLabel()
self.error_msg.setAlignment(Qt.AlignCenter) self.error_msg.setAlignment(Qt.AlignCenter)
error_layout.addWidget(self.error_msg) error_layout.addWidget(self.error_msg)
@ -125,7 +124,7 @@ class QEAbstractWizard(QDialog, MessageBoxMixin):
viewstate = self._current = self.start_viewstate viewstate = self._current = self.start_viewstate
else: else:
viewstate = self.start_wizard() viewstate = self.start_wizard()
self.load_next_component(viewstate.view, viewstate.wizard_data) self.load_next_component(viewstate.view, viewstate.wizard_data, viewstate.params)
def load_next_component(self, view, wdata=None, params=None): def load_next_component(self, view, wdata=None, params=None):
if wdata is None: if wdata is None:
@ -167,10 +166,11 @@ class QEAbstractWizard(QDialog, MessageBoxMixin):
def update(self): def update(self):
page = self.main_widget.currentWidget() page = self.main_widget.currentWidget()
self.setWindowTitle(page.wizard_title if page.wizard_title else self.window_title)
self.title.setText(f'<b>{page.title}</b>' if page.title else '') self.title.setText(f'<b>{page.title}</b>' if page.title else '')
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.back_button.setEnabled(not page.busy) self.back_button.setEnabled(not page.busy)
self.next_button.setText(_('Next') if not self.is_last(page.wizard_data) else _('Finish')) self.next_button.setText(_('Next') if not self.is_last(page.wizard_data) else self.finish_label)
self.next_button.setEnabled(not page.busy and page.valid) self.next_button.setEnabled(not page.busy and page.valid)
self.main_widget.setVisible(not page.busy and not bool(page.error)) self.main_widget.setVisible(not page.busy and not bool(page.error))
self.please_wait.setVisible(page.busy) self.please_wait.setVisible(page.busy)
@ -178,8 +178,11 @@ class QEAbstractWizard(QDialog, MessageBoxMixin):
self.error_msg.setText(str(page.error)) self.error_msg.setText(str(page.error))
self.error.setVisible(not page.busy and bool(page.error)) self.error.setVisible(not page.busy and bool(page.error))
icon = page.params.get('icon', icon_path('electrum.png')) icon = page.params.get('icon', icon_path('electrum.png'))
if icon != self.icon_filename: if icon and icon != self.icon_filename:
self.set_icon(icon) self.set_icon(icon)
self.logo.setVisible(True)
else:
self.logo.setVisible(False)
def on_back_button_clicked(self): def on_back_button_clicked(self):
if self.can_go_back(): if self.can_go_back():
@ -238,6 +241,7 @@ class WizardComponent(QWidget):
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_title = None
self.busy_msg = '' self.busy_msg = ''
self.wizard = wizard self.wizard = wizard
self._error = '' self._error = ''

41
electrum/wizard.py

@ -264,7 +264,9 @@ class NewWalletWizard(AbstractWizard):
if initial_data is None: if initial_data is None:
initial_data = {} initial_data = {}
self.reset() self.reset()
self._current = WizardViewState('wallet_name', initial_data, {}) start_view = 'wallet_name'
params = self.navmap[start_view].get('params', {})
self._current = WizardViewState(start_view, initial_data, params)
return self._current return self._current
def is_single_password(self) -> bool: def is_single_password(self) -> bool:
@ -652,17 +654,15 @@ class ServerConnectWizard(AbstractWizard):
def __init__(self, daemon: 'Daemon'): def __init__(self, daemon: 'Daemon'):
AbstractWizard.__init__(self) AbstractWizard.__init__(self)
self.navmap = { self.navmap = {
'autoconnect': { 'welcome': {
'next': 'server_config', 'next': lambda d: 'proxy_config' if d['want_proxy'] else 'server_config',
'accept': self.do_configure_autoconnect, 'accept': self.do_configure_autoconnect,
'last': lambda d: d['autoconnect'] 'last': lambda d: bool(d['autoconnect'] and not d['want_proxy'])
},
'proxy_ask': {
'next': lambda d: 'proxy_config' if d['want_proxy'] else 'autoconnect'
}, },
'proxy_config': { 'proxy_config': {
'next': 'autoconnect', 'next': 'server_config',
'accept': self.do_configure_proxy 'accept': self.do_configure_proxy,
'last': lambda d: bool(d['autoconnect'])
}, },
'server_config': { 'server_config': {
'accept': self.do_configure_server, 'accept': self.do_configure_server,
@ -680,29 +680,34 @@ class ServerConnectWizard(AbstractWizard):
net_params = self._daemon.network.get_parameters() net_params = self._daemon.network.get_parameters()
if not proxy_settings['enabled']: if not proxy_settings['enabled']:
proxy_settings = None proxy_settings = None
net_params = net_params._replace(proxy=proxy_settings) net_params = net_params._replace(proxy=proxy_settings, auto_connect=bool(wizard_data['autoconnect']))
self._daemon.network.run_from_another_thread(self._daemon.network.set_parameters(net_params)) self._daemon.network.run_from_another_thread(self._daemon.network.set_parameters(net_params))
def do_configure_server(self, wizard_data: dict): def do_configure_server(self, wizard_data: dict):
self._logger.debug(f'configuring server: {wizard_data!r}') self._logger.debug(f'configuring server: {wizard_data!r}')
net_params = self._daemon.network.get_parameters() net_params = self._daemon.network.get_parameters()
try: server = ''
server = ServerAddr.from_str_with_inference(wizard_data['server']) if not wizard_data['autoconnect']:
if not server: try:
raise Exception('failed to parse server %s' % wizard_data['server']) server = ServerAddr.from_str_with_inference(wizard_data['server'])
except Exception: if not server:
return raise Exception('failed to parse server %s' % wizard_data['server'])
except Exception:
return
net_params = net_params._replace(server=server, auto_connect=wizard_data['autoconnect']) net_params = net_params._replace(server=server, auto_connect=wizard_data['autoconnect'])
self._daemon.network.run_from_another_thread(self._daemon.network.set_parameters(net_params)) self._daemon.network.run_from_another_thread(self._daemon.network.set_parameters(net_params))
def do_configure_autoconnect(self, wizard_data: dict): def do_configure_autoconnect(self, wizard_data: dict):
self._logger.debug(f'configuring autoconnect: {wizard_data!r}') self._logger.debug(f'configuring autoconnect: {wizard_data!r}')
if self._daemon.config.cv.NETWORK_AUTO_CONNECT.is_modifiable(): if self._daemon.config.cv.NETWORK_AUTO_CONNECT.is_modifiable():
self._daemon.config.NETWORK_AUTO_CONNECT = wizard_data['autoconnect'] if wizard_data.get('autoconnect') is not None:
self._daemon.config.NETWORK_AUTO_CONNECT = wizard_data.get('autoconnect')
def start(self, initial_data: dict = None) -> WizardViewState: def start(self, initial_data: dict = None) -> WizardViewState:
if initial_data is None: if initial_data is None:
initial_data = {} initial_data = {}
self.reset() self.reset()
self._current = WizardViewState('proxy_ask', initial_data, {}) start_view = 'welcome'
params = self.navmap[start_view].get('params', {})
self._current = WizardViewState(start_view, initial_data, params)
return self._current return self._current

Loading…
Cancel
Save