diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 96416c04c3..29c329028f 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -43,6 +43,7 @@ QT_MOC_CPP = \ qml/models/moc_options_model.cpp \ qml/models/moc_peerlistsortproxy.cpp \ qml/moc_appmode.cpp \ + qml/moc_walletcontroller.cpp \ qt/moc_addressbookpage.cpp \ qt/moc_addresstablemodel.cpp \ qt/moc_askpassphrasedialog.cpp \ @@ -126,6 +127,7 @@ BITCOIN_QT_H = \ qml/guiconstants.h \ qml/imageprovider.h \ qml/util.h \ + qml/walletcontroller.h \ qt/addressbookpage.h \ qt/addresstablemodel.h \ qt/askpassphrasedialog.h \ @@ -310,13 +312,15 @@ BITCOIN_QML_BASE_CPP = \ qml/models/options_model.cpp \ qml/models/peerlistsortproxy.cpp \ qml/imageprovider.cpp \ - qml/util.cpp + qml/util.cpp \ + qml/walletcontroller.cpp QML_RES_FONTS = \ qml/res/fonts/Inter-Regular.otf \ qml/res/fonts/Inter-SemiBold.otf QML_RES_ICONS = \ + qml/res/icons/add-wallet-dark.png \ qml/res/icons/arrow-down.png \ qml/res/icons/arrow-up.png \ qml/res/icons/bitcoin-circle.png \ @@ -331,6 +335,7 @@ QML_RES_ICONS = \ qml/res/icons/export.png \ qml/res/icons/gear.png \ qml/res/icons/gear-outline.png \ + qml/res/icons/hidden.png \ qml/res/icons/info.png \ qml/res/icons/network-dark.png \ qml/res/icons/network-light.png \ @@ -339,7 +344,9 @@ QML_RES_ICONS = \ qml/res/icons/storage-dark.png \ qml/res/icons/storage-light.png \ qml/res/icons/tooltip-arrow-dark.png \ - qml/res/icons/tooltip-arrow-light.png + qml/res/icons/tooltip-arrow-light.png \ + qml/res/icons/wallet.png \ + qml/res/icons/visible.png QML_QRC_CPP = qml/qrc_bitcoin.cpp QML_QRC = qml/bitcoin_qml.qrc @@ -348,7 +355,6 @@ QML_RES_QML = \ qml/components/BlockClock.qml \ qml/components/BlockClockDisplayMode.qml \ qml/components/BlockCounter.qml \ - qml/controls/CaretRightIcon.qml \ qml/components/ConnectionOptions.qml \ qml/components/ConnectionSettings.qml \ qml/components/DeveloperOptions.qml \ @@ -364,8 +370,10 @@ QML_RES_QML = \ qml/components/ThemeSettings.qml \ qml/components/TotalBytesIndicator.qml \ qml/components/Tooltip.qml \ + qml/controls/CaretRightIcon.qml \ qml/controls/ContinueButton.qml \ qml/controls/CoreText.qml \ + qml/controls/CoreTextField.qml \ qml/controls/ExternalLink.qml \ qml/controls/FocusBorder.qml \ qml/controls/Header.qml \ @@ -409,6 +417,12 @@ QML_RES_QML = \ qml/pages/settings/SettingsProxy.qml \ qml/pages/settings/SettingsStorage.qml \ qml/pages/settings/SettingsTheme.qml \ + qml/pages/wallet/AddWallet.qml \ + qml/pages/wallet/CreateBackup.qml \ + qml/pages/wallet/CreateConfirm.qml \ + qml/pages/wallet/CreateIntro.qml \ + qml/pages/wallet/CreateName.qml \ + qml/pages/wallet/CreatePassword.qml \ qml/pages/wallet/DesktopWallets.qml if TARGET_ANDROID diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index bb3a368e47..80c38e7f95 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -20,6 +20,7 @@ #endif #include #include +#include #include #include #include @@ -27,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -286,6 +287,8 @@ int QmlGuiMain(int argc, char* argv[]) GUIUtil::LoadFont(":/fonts/inter/regular"); GUIUtil::LoadFont(":/fonts/inter/semibold"); + WalletController wallet_controller(*node); + QQmlApplicationEngine engine; QScopedPointer network_style{NetworkStyle::instantiate(Params().GetChainType())}; @@ -297,6 +300,7 @@ int QmlGuiMain(int argc, char* argv[]) engine.rootContext()->setContextProperty("chainModel", &chain_model); engine.rootContext()->setContextProperty("peerTableModel", &peer_model); engine.rootContext()->setContextProperty("peerListModelProxy", &peer_model_sort_proxy); + engine.rootContext()->setContextProperty("walletController", &wallet_controller); OptionsQmlModel options_model(*node, !need_onboarding.toBool()); engine.rootContext()->setContextProperty("optionsModel", &options_model); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 3f89b0dbf7..2f36fe8776 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -22,6 +22,7 @@ components/Tooltip.qml controls/ContinueButton.qml controls/CoreText.qml + controls/CoreTextField.qml controls/ExternalLink.qml controls/FocusBorder.qml controls/Header.qml @@ -65,9 +66,16 @@ pages/settings/SettingsProxy.qml pages/settings/SettingsStorage.qml pages/settings/SettingsTheme.qml + pages/wallet/AddWallet.qml + pages/wallet/CreateBackup.qml + pages/wallet/CreateConfirm.qml + pages/wallet/CreateIntro.qml + pages/wallet/CreateName.qml + pages/wallet/CreatePassword.qml pages/wallet/DesktopWallets.qml + res/icons/add-wallet-dark.png res/icons/arrow-down.png res/icons/arrow-up.png res/icons/bitcoin-circle.png @@ -83,6 +91,7 @@ res/icons/export.png res/icons/gear.png res/icons/gear-outline.png + res/icons/hidden.png res/icons/info.png res/icons/network-dark.png res/icons/network-light.png @@ -92,6 +101,8 @@ res/icons/storage-light.png res/icons/tooltip-arrow-dark.png res/icons/tooltip-arrow-light.png + res/icons/wallet.png + res/icons/visible.png res/fonts/Inter-Regular.otf diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 454ff7524d..9651298b3c 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -9,25 +9,44 @@ import org.bitcoincore.qt 1.0 Button { id: root hoverEnabled: AppMode.isDesktop + + property color textColor: Theme.color.white + property color backgroundColor: Theme.color.orange + property color backgroundHoverColor: Theme.color.orangeLight1 + property color backgroundPressedColor: Theme.color.orangeLight2 + property color borderColor: "transparent" + property color borderHoverColor: "transparent" + property color borderPressedColor: "transparent" + contentItem: CoreText { text: parent.text + color: root.textColor bold: true font.pixelSize: 18 } background: Rectangle { id: bg implicitHeight: 46 - color: Theme.color.orange + color: backgroundColor + border.color: borderColor radius: 5 states: [ + State { + name: "DISABLED"; when: !root.enabled + PropertyChanges { target: bg; color: Theme.color.neutral2 } + PropertyChanges { target: bg; border.color: Theme.color.neutral2 } + PropertyChanges { target: root; textColor: Theme.color.neutral5 } + }, State { name: "PRESSED"; when: root.pressed - PropertyChanges { target: bg; color: Theme.color.orangeLight2 } + PropertyChanges { target: bg; color: backgroundPressedColor } + PropertyChanges { target: bg; border.color: borderPressedColor } }, State { name: "HOVER"; when: root.hovered - PropertyChanges { target: bg; color: Theme.color.orangeLight1 } + PropertyChanges { target: bg; color: backgroundHoverColor } + PropertyChanges { target: bg; border.color: borderHoverColor } } ] diff --git a/src/qml/controls/CoreTextField.qml b/src/qml/controls/CoreTextField.qml new file mode 100644 index 0000000000..fe2b196bec --- /dev/null +++ b/src/qml/controls/CoreTextField.qml @@ -0,0 +1,50 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +TextField { + id: root + + property bool hideText: false + + implicitHeight: 56 + implicitWidth: 450 + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: 18 + color: Theme.color.neutral9 + placeholderTextColor: Theme.color.neutral5 + echoMode: hideText ? TextInput.Password : TextInput.Normal + rightPadding: hideText ? 46 : 20 + leftPadding: 20 + background: Rectangle { + border.color: Theme.color.neutral5 + border.width: 1 + color: "transparent" + radius: 5 + + Icon { + id: visibleIcon + enabled: hideText + visible: hideText + anchors.right: parent.right + anchors.rightMargin: 12 + size: 24 + anchors.verticalCenter: parent.verticalCenter + source: "qrc:/icons/visible" + color: Theme.color.neutral5 + onClicked: { + if (root.echoMode == TextInput.Password) { + root.echoMode = TextInput.Normal + visibleIcon.source = "qrc:/icons/hidden" + } else { + root.echoMode = TextInput.Password + visibleIcon.source = "qrc:/icons/visible" + } + } + } + } +} \ No newline at end of file diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 37bc50387c..303e3c7678 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -10,7 +10,7 @@ import org.bitcoincore.qt 1.0 AbstractButton { id: root - required property string header + property string header property alias actionItem: action_loader.sourceComponent property alias loadedItem: action_loader.item property string description diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index b3b041c9eb..1804c37171 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -142,5 +142,25 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/tooltip-arrow-light").pixmap(requested_size); } + if (id == "add-wallet-dark") { + *size = requested_size; + return QIcon(":/icons/add-wallet-dark").pixmap(requested_size); + } + + if (id == "wallet") { + *size = requested_size; + return QIcon(":/icons/wallet").pixmap(requested_size); + } + + if (id == "visible") { + *size = requested_size; + return QIcon(":/icons/visible").pixmap(requested_size); + } + + if (id == "hidden") { + *size = requested_size; + return QIcon(":/icons/hidden").pixmap(requested_size); + } + return {}; } diff --git a/src/qml/pages/main.qml b/src/qml/pages/main.qml index 471fe127c0..67526c80ae 100644 --- a/src/qml/pages/main.qml +++ b/src/qml/pages/main.qml @@ -81,6 +81,7 @@ ApplicationWindow { optionsModel.onboard() if (AppMode.walletEnabled && AppMode.isDesktop) { main.push(desktopWallets) + main.push(addWallet) } else { main.push(node) } @@ -93,6 +94,15 @@ ApplicationWindow { DesktopWallets {} } + Component { + id: addWallet + AddWallet { + onFinished: { + main.pop() + } + } + } + Component { id: shutdown Shutdown {} diff --git a/src/qml/pages/wallet/AddWallet.qml b/src/qml/pages/wallet/AddWallet.qml new file mode 100644 index 0000000000..8fc4fc749f --- /dev/null +++ b/src/qml/pages/wallet/AddWallet.qml @@ -0,0 +1,82 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" +import "../settings" +import "../wallet" + +StackView { + id: addWalletStack + + signal finished() + + initialItem: Page { + background: null + + header: NavigationBar2 { + id: navbar + rightItem: NavButton { + text: qsTr("Skip") + onClicked: { + addWalletStack.finished() + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + anchors.horizontalCenter: parent.horizontalCenter + + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/add-wallet-dark" + + sourceSize.width: 200 + sourceSize.height: 200 + } + + Header { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + header: qsTr("Add a wallet") + description: qsTr("In this early stage of development, only wallet.dat files are supported.") + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 40 + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.bottomMargin: 20 + Layout.alignment: Qt.AlignCenter + text: qsTr("Create wallet") + onClicked: { + addWalletStack.push("qrc:/qml/pages/wallet/CreateIntro.qml"); + } + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.alignment: Qt.AlignCenter + text: qsTr("Import wallet") + borderColor: Theme.color.neutral6 + borderHoverColor: Theme.color.orangeLight1 + borderPressedColor: Theme.color.orangeLight2 + textColor: Theme.color.orange + backgroundColor: "transparent" + backgroundHoverColor: "transparent" + backgroundPressedColor: "transparent" + } + } + } +} + diff --git a/src/qml/pages/wallet/CreateBackup.qml b/src/qml/pages/wallet/CreateBackup.qml new file mode 100644 index 0000000000..7f691a971c --- /dev/null +++ b/src/qml/pages/wallet/CreateBackup.qml @@ -0,0 +1,89 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import "../../controls" +import "../../components" +import "../settings" + +Page { + id: root + background: null + + header: NavigationBar2 { + id: navbar + leftItem: NavButton { + iconSource: "image://images/caret-left" + text: qsTr("Back") + onClicked: { + root.StackView.view.pop() + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + anchors.horizontalCenter: parent.horizontalCenter + + Item { + Layout.alignment: Qt.AlignCenter + Layout.preferredHeight: circle.height + Layout.preferredWidth: circle.width + Rectangle { + id: circle + width: 60 + height: width + radius: width / 2 + color: Theme.color.blue + } + Icon { + source: "image://images/wallet" + color: Theme.color.white + width: 30 + height: width + anchors.centerIn: circle + } + } + + Header { + Layout.topMargin: 20 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + header: qsTr("Back up your wallet") + description: qsTr("Your wallet is a file stored on your hard disk.\nTo prevent accidental loss, it is recommended you keep a copy of your wallet file in a secure place, like a dedicated USB Drive.") + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 30 + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.alignment: Qt.AlignCenter + text: qsTr("View file") + borderColor: Theme.color.neutral6 + borderHoverColor: Theme.color.orangeLight1 + borderPressedColor: Theme.color.orangeLight2 + textColor: Theme.color.orange + backgroundColor: "transparent" + backgroundHoverColor: "transparent" + backgroundPressedColor: "transparent" + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 30 + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.alignment: Qt.AlignCenter + text: qsTr("Done") + onClicked: { + root.StackView.view.finished() + } + } + } +} \ No newline at end of file diff --git a/src/qml/pages/wallet/CreateConfirm.qml b/src/qml/pages/wallet/CreateConfirm.qml new file mode 100644 index 0000000000..bd1e95ecd9 --- /dev/null +++ b/src/qml/pages/wallet/CreateConfirm.qml @@ -0,0 +1,73 @@ + // Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import "../../controls" +import "../../components" +import "../settings" + +Page { + id: root + background: null + + header: NavigationBar2 { + id: navbar + leftItem: NavButton { + iconSource: "image://images/caret-left" + text: qsTr("Back") + onClicked: { + root.StackView.view.pop() + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + anchors.horizontalCenter: parent.horizontalCenter + + Item { + Layout.alignment: Qt.AlignCenter + Layout.preferredHeight: circle.height + Layout.preferredWidth: circle.width + Rectangle { + id: circle + width: 60 + height: width + radius: width / 2 + color: Theme.color.green + } + Icon { + source: "image://images/wallet" + color: Theme.color.white + width: 30 + height: width + anchors.centerIn: circle + } + } + + Header { + Layout.topMargin: 20 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + header: qsTr("Your wallet has been created") + description: qsTr("It is good practice to make a small test transaction before you actively use this wallet for larger amounts.") + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 30 + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.alignment: Qt.AlignCenter + text: qsTr("Next") + onClicked: { + root.StackView.view.push("qrc:/qml/pages/wallet/CreateBackup.qml") + } + } + } +} \ No newline at end of file diff --git a/src/qml/pages/wallet/CreateIntro.qml b/src/qml/pages/wallet/CreateIntro.qml new file mode 100644 index 0000000000..11bf996eff --- /dev/null +++ b/src/qml/pages/wallet/CreateIntro.qml @@ -0,0 +1,114 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import "../../controls" +import "../../components" +import "../settings" + +Page { + id: root + background: null + + header: NavigationBar2 { + id: navbar + leftItem: NavButton { + iconSource: "image://images/caret-left" + text: qsTr("Back") + onClicked: { + root.StackView.view.pop() + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + anchors.horizontalCenter: parent.horizontalCenter + + Item { + Layout.alignment: Qt.AlignCenter + Layout.preferredHeight: circle.height + Layout.preferredWidth: circle.width + Rectangle { + id: circle + width: 60 + height: width + radius: width / 2 + color: Theme.color.blue + } + Icon { + source: "image://images/wallet" + color: Theme.color.white + width: 30 + height: width + anchors.centerIn: circle + } + } + + CoreText { + Layout.topMargin: 25 + Layout.alignment: Qt.AlignCenter + text: qsTr("You are about to create \na single-key bitcoin wallet") + font.pixelSize: 21 + bold: true + color: Theme.color.neutral9 + } + + CoreText { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter + text: qsTr("You can fully control it in this application.") + font.pixelSize: 18 + color: Theme.color.neutral7 + } + + Separator { + Layout.topMargin: 10 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + Layout.fillWidth: true + color: Theme.color.neutral7 + } + + CoreText { + Layout.topMargin: 10 + Layout.alignment: Qt.AlignCenter + text: qsTr("Wallet data will be stored locally on your hard drive.") + font.pixelSize: 18 + color: Theme.color.neutral7 + } + + Separator { + Layout.topMargin: 10 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + Layout.fillWidth: true + color: Theme.color.neutral7 + } + + CoreText { + Layout.topMargin: 10 + Layout.alignment: Qt.AlignCenter + text: qsTr("You can optionally protect it with a password.") + font.pixelSize: 18 + color: Theme.color.neutral7 + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 30 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + Layout.alignment: Qt.AlignCenter + text: qsTr("Start") + onClicked: { + root.StackView.view.push("qrc:/qml/pages/wallet/CreateName.qml") + } + } + } +} \ No newline at end of file diff --git a/src/qml/pages/wallet/CreateName.qml b/src/qml/pages/wallet/CreateName.qml new file mode 100644 index 0000000000..d261c9d5c5 --- /dev/null +++ b/src/qml/pages/wallet/CreateName.qml @@ -0,0 +1,74 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import "../../controls" +import "../../components" +import "../settings" + +Page { + id: root + background: null + + header: NavigationBar2 { + id: navbar + leftItem: NavButton { + iconSource: "image://images/caret-left" + text: qsTr("Back") + onClicked: { + root.StackView.view.pop() + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + spacing: 30 + anchors.horizontalCenter: parent.horizontalCenter + + Header { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + header: qsTr("Choose a wallet name") + } + + CoreTextField { + id: walletNameInput + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + placeholderText: qsTr("Eg. My bitcoin wallet...") + validator: RegExpValidator { regExp: /^[a-zA-Z0-9_]{1,20}$/ } + onTextChanged: { + continueButton.enabled = walletNameInput.text.length > 0 + } + } + + ContinueButton { + id: continueButton + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.leftMargin: 20 + Layout.rightMargin: 20 + Layout.alignment: Qt.AlignCenter + enabled: walletNameInput.text.length > 0 + text: qsTr("Continue") + onClicked: { + console.log("Creating wallet with name: " + walletNameInput.text) + root.StackView.view.push(createPassword) + } + } + + Component { + id: createPassword + CreatePassword { + walletName: walletNameInput.text + } + } + } +} \ No newline at end of file diff --git a/src/qml/pages/wallet/CreatePassword.qml b/src/qml/pages/wallet/CreatePassword.qml new file mode 100644 index 0000000000..ed3fbde8ad --- /dev/null +++ b/src/qml/pages/wallet/CreatePassword.qml @@ -0,0 +1,113 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import "../../controls" +import "../../components" +import "../settings" + +Page { + id: root + background: null + + required property string walletName; + + header: NavigationBar2 { + id: navbar + leftItem: NavButton { + iconSource: "image://images/caret-left" + text: qsTr("Back") + onClicked: { + root.StackView.view.pop() + } + } + rightItem: NavButton { + text: qsTr("Skip") + onClicked: { + walletController.createSingleSigWallet(walletName, "") + root.StackView.view.push("qrc:/qml/pages/wallet/CreateConfirm.qml") + } + } + } + + ColumnLayout { + id: columnLayout + width: Math.min(parent.width, 450) + anchors.horizontalCenter: parent.horizontalCenter + + Header { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + header: qsTr("Choose a password") + description: qsTr("It is recommended to set a password to protect your wallet file from unwanted access from others.") + } + + CoreText { + Layout.topMargin: 30 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + font.pixelSize: 15 + color: Theme.color.neutral9 + text: qsTr("Choose a password") + } + + CoreTextField { + id: password + Layout.fillWidth: true + Layout.topMargin: 5 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + hideText: true + placeholderText: qsTr("Enter password...") + } + CoreText { + Layout.topMargin: 20 + Layout.leftMargin: 20 + Layout.rightMargin: 20 + font.pixelSize: 15 + color: Theme.color.neutral9 + text: qsTr("Confirm password") + } + CoreTextField { + id: passwordRepeat + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + hideText: true + placeholderText: qsTr("Enter password again...") + } + + Setting { + id: confirmToggle + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + description: qsTr("I understand that if I lose or forget this password I might lose access to the bitcoin stored in this wallet.") + actionItem: OptionSwitch { + } + onClicked: { + loadedItem.toggle() + loadedItem.toggled() + } + } + + ContinueButton { + Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin) + Layout.topMargin: 40 + Layout.leftMargin: 20 + Layout.rightMargin: Layout.leftMargin + Layout.alignment: Qt.AlignCenter + text: qsTr("Continue") + enabled: password.text != "" && passwordRepeat.text != "" && password.text == passwordRepeat.text && confirmToggle.loadedItem.checked + onClicked: { + walletController.createSingleSigWallet(walletName, password.text) + root.StackView.view.push("qrc:/qml/pages/wallet/CreateConfirm.qml") + } + } + } +} \ No newline at end of file diff --git a/src/qml/res/icons/add-wallet-dark.png b/src/qml/res/icons/add-wallet-dark.png new file mode 100644 index 0000000000..7b45c4f6bd Binary files /dev/null and b/src/qml/res/icons/add-wallet-dark.png differ diff --git a/src/qml/res/icons/hidden.png b/src/qml/res/icons/hidden.png new file mode 100644 index 0000000000..47c412e2a9 Binary files /dev/null and b/src/qml/res/icons/hidden.png differ diff --git a/src/qml/res/icons/shield.png b/src/qml/res/icons/shield.png new file mode 100644 index 0000000000..de748566b4 Binary files /dev/null and b/src/qml/res/icons/shield.png differ diff --git a/src/qml/res/icons/visible.png b/src/qml/res/icons/visible.png new file mode 100644 index 0000000000..f91ad6643c Binary files /dev/null and b/src/qml/res/icons/visible.png differ diff --git a/src/qml/res/icons/wallet.png b/src/qml/res/icons/wallet.png new file mode 100644 index 0000000000..843e9eab40 Binary files /dev/null and b/src/qml/res/icons/wallet.png differ diff --git a/src/qml/res/src/add-wallet-dark.svg b/src/qml/res/src/add-wallet-dark.svg new file mode 100644 index 0000000000..6e31fe38cc --- /dev/null +++ b/src/qml/res/src/add-wallet-dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/qml/res/src/hidden.svg b/src/qml/res/src/hidden.svg new file mode 100644 index 0000000000..68f236d922 --- /dev/null +++ b/src/qml/res/src/hidden.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/qml/res/src/shield.svg b/src/qml/res/src/shield.svg new file mode 100644 index 0000000000..22c311f9e9 --- /dev/null +++ b/src/qml/res/src/shield.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/qml/res/src/visible.svg b/src/qml/res/src/visible.svg new file mode 100644 index 0000000000..a0b5c28fa1 --- /dev/null +++ b/src/qml/res/src/visible.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/qml/res/src/wallet.svg b/src/qml/res/src/wallet.svg new file mode 100644 index 0000000000..f83d21bc61 --- /dev/null +++ b/src/qml/res/src/wallet.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/qml/walletcontroller.cpp b/src/qml/walletcontroller.cpp new file mode 100644 index 0000000000..7726bf5187 --- /dev/null +++ b/src/qml/walletcontroller.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + + +WalletController::WalletController(interfaces::Node& node) + : m_node(node) +{ +} + +void WalletController::createSingleSigWallet(const QString& name, const QString& passphrase) +{ + uint64_t flags = 0; + std::vector warning_message; + SecureString secure_passphrase; + flags |= wallet::WALLET_FLAG_DESCRIPTORS; + secure_passphrase.assign(passphrase.toStdString()); + m_node.walletLoader().createWallet(name.toStdString(), secure_passphrase, flags, warning_message); +} diff --git a/src/qml/walletcontroller.h b/src/qml/walletcontroller.h new file mode 100644 index 0000000000..9258895556 --- /dev/null +++ b/src/qml/walletcontroller.h @@ -0,0 +1,26 @@ +// Copyright (c) 2024 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QML_WALLETCONTROLLER_H +#define BITCOIN_QML_WALLETCONTROLLER_H + +#include + +#include +#include + +class WalletController : public QObject +{ + Q_OBJECT + +public: + explicit WalletController(interfaces::Node& node); + Q_INVOKABLE void createSingleSigWallet(const QString& name, const QString& passphrase); + +private: + interfaces::Node& m_node; +}; + + +#endif // BITCOIN_QML_WALLETCONTROLLER_H diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 1f5e3d8f3b..557bb42acc 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -622,7 +622,7 @@ int GuiMain(int argc, char* argv[]) qApp->installNativeEventFilter(new WinShutdownMonitor()); #endif // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); + //qInstallMessageHandler(DebugMessageHandler); // Allow parameter interaction before we create the options model app.parameterSetup(); GUIUtil::LogQtInfo();