qml: add word picker to SeedTextArea
This commit is contained in:
@@ -1,20 +1,102 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
TextArea {
|
||||
id: seedtext
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 80
|
||||
rightPadding: constants.paddingLarge
|
||||
leftPadding: constants.paddingLarge
|
||||
wrapMode: TextInput.WordWrap
|
||||
font.bold: true
|
||||
font.pixelSize: constants.fontSizeLarge
|
||||
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhPreferLowercase | Qt.ImhNoPredictiveText
|
||||
import org.electrum 1.0
|
||||
|
||||
Pane {
|
||||
id: root
|
||||
implicitHeight: rootLayout.height
|
||||
padding: 0
|
||||
|
||||
property alias readOnly: seedtextarea.readOnly
|
||||
property alias text: seedtextarea.text
|
||||
property alias placeholderText: seedtextarea.placeholderText
|
||||
|
||||
property var _suggestions: []
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: Material.accentColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
Flickable {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.minimumHeight: fontMetrics.lineSpacing + 2*constants.paddingXXSmall + 2*constants.paddingXSmall + 2
|
||||
implicitHeight: wordsLayout.height
|
||||
|
||||
visible: !readOnly
|
||||
flickableDirection: Flickable.HorizontalFlick
|
||||
contentWidth: wordsLayout.width
|
||||
interactive: wordsLayout.width > width
|
||||
|
||||
RowLayout {
|
||||
id: wordsLayout
|
||||
Repeater {
|
||||
model: _suggestions
|
||||
Rectangle {
|
||||
Layout.margins: constants.paddingXXSmall
|
||||
width: suggestionLabel.width
|
||||
height: suggestionLabel.height
|
||||
color: constants.lighterBackground
|
||||
radius: constants.paddingXXSmall
|
||||
Label {
|
||||
id: suggestionLabel
|
||||
text: modelData
|
||||
padding: constants.paddingXSmall
|
||||
leftPadding: constants.paddingSmall
|
||||
rightPadding: constants.paddingSmall
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
var words = seedtextarea.text.split(' ')
|
||||
words.pop()
|
||||
words.push(modelData)
|
||||
seedtextarea.text = words.join(' ') + ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: seedtextarea
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: fontMetrics.height * 3 + topPadding + bottomPadding
|
||||
|
||||
rightPadding: constants.paddingLarge
|
||||
leftPadding: constants.paddingLarge
|
||||
|
||||
wrapMode: TextInput.WordWrap
|
||||
font.bold: true
|
||||
font.pixelSize: constants.fontSizeLarge
|
||||
font.family: FixedFont
|
||||
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhPreferLowercase | Qt.ImhNoPredictiveText
|
||||
|
||||
background: Rectangle {
|
||||
color: constants.darkerBackground
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
_suggestions = bitcoin.mnemonicsFor(seedtextarea.text.split(' ').pop())
|
||||
// TODO: cursorPosition only on suggestion apply
|
||||
cursorPosition = text.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontMetrics {
|
||||
id: fontMetrics
|
||||
font: seedtextarea.font
|
||||
}
|
||||
|
||||
Bitcoin {
|
||||
id: bitcoin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ WizardComponent {
|
||||
SeedTextArea {
|
||||
id: confirm
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr('Enter your seed')
|
||||
onTextChanged: checkValid()
|
||||
}
|
||||
|
||||
|
||||
@@ -165,16 +165,13 @@ WizardComponent {
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.topMargin: constants.paddingMedium
|
||||
Layout.columnSpan: 2
|
||||
text: cosigner ? qsTr('Enter cosigner seed') : qsTr('Enter your seed')
|
||||
}
|
||||
|
||||
SeedTextArea {
|
||||
id: seedtext
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
|
||||
placeholderText: cosigner ? qsTr('Enter cosigner seed') : qsTr('Enter your seed')
|
||||
|
||||
onTextChanged: {
|
||||
validationTimer.restart()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ from electrum.logging import get_logger
|
||||
from electrum.slip39 import decode_mnemonic, Slip39Error
|
||||
from electrum.util import parse_URI, create_bip21_uri, InvalidBitcoinURI, get_asyncio_loop
|
||||
from electrum.transaction import tx_from_any
|
||||
from electrum.mnemonic import is_any_2fa_seed_type
|
||||
from electrum.mnemonic import Mnemonic, is_any_2fa_seed_type
|
||||
from electrum.old_mnemonic import wordlist as old_wordlist
|
||||
|
||||
from .qetypes import QEAmount
|
||||
|
||||
@@ -26,6 +27,8 @@ class QEBitcoin(QObject):
|
||||
validationMessageChanged = pyqtSignal()
|
||||
_validationMessage = ''
|
||||
|
||||
_words = None
|
||||
|
||||
def __init__(self, config, parent=None):
|
||||
super().__init__(parent)
|
||||
self.config = config
|
||||
@@ -165,3 +168,11 @@ class QEBitcoin(QObject):
|
||||
@pyqtSlot(str, result=bool)
|
||||
def isPrivateKeyList(self, csv: str):
|
||||
return keystore.is_private_key_list(csv)
|
||||
|
||||
@pyqtSlot(str, result='QVariantList')
|
||||
def mnemonicsFor(self, fragment):
|
||||
if not fragment:
|
||||
return []
|
||||
if not self._words:
|
||||
self._words = set(Mnemonic('en').wordlist).union(set(old_wordlist))
|
||||
return sorted(filter(lambda x: x.startswith(fragment), self._words))
|
||||
|
||||
Reference in New Issue
Block a user