diff --git a/electrum/gui/qml/components/BalanceSummary.qml b/electrum/gui/qml/components/BalanceSummary.qml new file mode 100644 index 000000000..9c452f75b --- /dev/null +++ b/electrum/gui/qml/components/BalanceSummary.qml @@ -0,0 +1,31 @@ +import QtQuick 2.6 +import QtQuick.Layouts 1.0 +import QtQuick.Controls 2.0 + +Item { + height: layout.height + + GridLayout { + id: layout + + columns: 3 + Label { + Layout.columnSpan: 3 + font.pointSize: 14 + text: 'Balance: ' + Daemon.currentWallet.confirmedBalance //'5.6201 mBTC' + } + Label { + font.pointSize: 8 + text: 'Confirmed: ' + Daemon.currentWallet.confirmedBalance + } + Label { + font.pointSize: 8 + text: 'Unconfirmed: ' + Daemon.currentWallet.unconfirmedBalance + } + Label { + font.pointSize: 8 + text: 'Lightning: ?' + } + } + +} diff --git a/electrum/gui/qml/components/History.qml b/electrum/gui/qml/components/History.qml index cc7f898c6..4579603df 100644 --- a/electrum/gui/qml/components/History.qml +++ b/electrum/gui/qml/components/History.qml @@ -2,132 +2,146 @@ import QtQuick 2.6 import QtQuick.Layouts 1.0 import QtQuick.Controls 2.0 -Item { - id: rootItem +import Electrum 1.0 - property string title: 'History' +Pane { + id: rootItem + visible: Daemon.currentWallet !== undefined + clip: true - Column { + ListView { + id: listview width: parent.width + height: parent.height - ListView { - width: parent.width - height: 200 + model: Daemon.currentWallet.historyModel - model: Daemon.currentWallet.historyModel - delegate: Item { - id: delegate - width: ListView.view.width - height: txinfo.height + header: Item { + id: header + width: ListView.view.width + height: balance.height - MouseArea { - anchors.fill: delegate - onClicked: extinfo.visible = !extinfo.visible - } + BalanceSummary { + id: balance + width: parent.width + } - GridLayout { - id: txinfo - columns: 4 - - x: 6 - width: delegate.width - 12 - - Item { - id: indicator - Layout.fillHeight: true - Layout.rowSpan: 2 - Rectangle { - width: 3 - color: model.incoming ? 'green' : 'red' - y: 2 - height: parent.height - 4 - } - } + } - Image { - readonly property variant tx_icons : [ - "../../../gui/icons/unconfirmed.png", - "../../../gui/icons/clock1.png", - "../../../gui/icons/clock2.png", - "../../../gui/icons/clock3.png", - "../../../gui/icons/clock4.png", - "../../../gui/icons/clock5.png", - "../../../gui/icons/confirmed.png" - ] - - sourceSize.width: 32 - sourceSize.height: 32 - Layout.alignment: Qt.AlignVCenter - source: tx_icons[Math.min(6,model.confirmations)] + delegate: Item { + id: delegate + width: ListView.view.width + height: txinfo.height + + MouseArea { + anchors.fill: delegate + onClicked: extinfo.visible = !extinfo.visible + } + + GridLayout { + id: txinfo + columns: 4 + + x: 6 + width: delegate.width - 12 + + Item { + id: indicator + Layout.fillHeight: true + Layout.rowSpan: 2 + Rectangle { + width: 3 + color: model.incoming ? 'green' : 'red' + y: 2 + height: parent.height - 4 } + } - Column { - Layout.fillWidth: true + Image { + readonly property variant tx_icons : [ + "../../../gui/icons/unconfirmed.png", + "../../../gui/icons/clock1.png", + "../../../gui/icons/clock2.png", + "../../../gui/icons/clock3.png", + "../../../gui/icons/clock4.png", + "../../../gui/icons/clock5.png", + "../../../gui/icons/confirmed.png" + ] + + sourceSize.width: 48 + sourceSize.height: 48 + Layout.alignment: Qt.AlignVCenter + source: tx_icons[Math.min(6,model.confirmations)] + } - Label { - text: model.label !== '' ? model.label : '' - color: model.label !== '' ? 'black' : 'gray' - font.bold: model.label !== '' ? true : false - } - Label { - font.pointSize: 7 - text: model.date - } + Column { + Layout.fillWidth: true + + Label { + font.pointSize: 12 + text: model.label !== '' ? model.label : '' + color: model.label !== '' ? 'black' : 'gray' + font.bold: model.label !== '' ? true : false + } + Label { + font.pointSize: 7 + text: model.date } + } - Column { - id: valuefee - Label { - text: model.bc_value - font.bold: true - } - Label { - font.pointSize: 6 - text: 'fee: ' + (model.fee !== undefined ? model.fee : '0') - } + Column { + id: valuefee + Label { + font.pointSize: 12 + text: model.bc_value + font.bold: true + } + Label { + font.pointSize: 6 + text: 'fee: ' + (model.fee !== undefined ? model.fee : '0') } + } - GridLayout { - id: extinfo - visible: false - columns: 2 - Layout.columnSpan: 3 - - Label { text: 'txid' } - Label { - font.pointSize: 6 - text: model.txid - elide: Text.ElideMiddle - Layout.fillWidth: true - } - Label { text: 'height' } - Label { - font.pointSize: 7 - text: model.height - } - Label { text: 'confirmations' } - Label { - font.pointSize: 7 - text: model.confirmations - } - Label { text: 'address' } - Label { - font.pointSize: 7 - elide: Text.ElideMiddle - Layout.fillWidth: true - text: { - for (var i=0; i < Object.keys(model.outputs).length; i++) { - if (model.outputs[i].value === model.bc_value) { - return model.outputs[i].address - } + GridLayout { + id: extinfo + visible: false + columns: 2 + Layout.columnSpan: 3 + + Label { text: 'txid' } + Label { + font.pointSize: 6 + text: model.txid + elide: Text.ElideMiddle + Layout.fillWidth: true + } + Label { text: 'height' } + Label { + font.pointSize: 7 + text: model.height + } + Label { text: 'confirmations' } + Label { + font.pointSize: 7 + text: model.confirmations + } + Label { text: 'address' } + Label { + font.pointSize: 7 + elide: Text.ElideMiddle + Layout.fillWidth: true + text: { + for (var i=0; i < Object.keys(model.outputs).length; i++) { + if (model.outputs[i].value === model.bc_value) { + return model.outputs[i].address } } } } - } - } // delegate - } + + } + } // delegate } diff --git a/electrum/gui/qml/components/NetworkStats.qml b/electrum/gui/qml/components/NetworkStats.qml index ef650cd1e..dff5f391d 100644 --- a/electrum/gui/qml/components/NetworkStats.qml +++ b/electrum/gui/qml/components/NetworkStats.qml @@ -3,12 +3,14 @@ import QtQuick.Layouts 1.0 import QtQuick.Controls 2.0 import QtQuick.Controls.Material 2.0 -Item { +Pane { property string title: qsTr('Network') GridLayout { columns: 2 + Label { text: qsTr("Network: "); color: Material.primaryHighlightedTextColor; font.bold: true } + Label { text: Network.networkName } Label { text: qsTr("Server: "); color: Material.primaryHighlightedTextColor; font.bold: true } Label { text: Network.server } Label { text: qsTr("Local Height: "); color: Material.primaryHighlightedTextColor; font.bold: true } diff --git a/electrum/gui/qml/components/Scan.qml b/electrum/gui/qml/components/Scan.qml index 61b8d179a..734e7d6a5 100644 --- a/electrum/gui/qml/components/Scan.qml +++ b/electrum/gui/qml/components/Scan.qml @@ -4,11 +4,10 @@ import QtQuick.Controls 2.0 Item { property bool toolbar: false - property string title: 'scan' QRScan { anchors.top: parent.top - anchors.bottom: button.top + anchors.bottom: parent.bottom width: parent.width } diff --git a/electrum/gui/qml/components/Send.qml b/electrum/gui/qml/components/Send.qml index 81e27890f..e7f033031 100644 --- a/electrum/gui/qml/components/Send.qml +++ b/electrum/gui/qml/components/Send.qml @@ -2,20 +2,16 @@ import QtQuick 2.6 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 -Item { +Pane { id: rootItem - property string title: 'Send' - GridLayout { - width: rootItem.width - 12 - anchors.horizontalCenter: parent.horizontalCenter + width: parent.width columns: 4 - Label { + BalanceSummary { Layout.columnSpan: 4 - Layout.alignment: Qt.AlignHCenter - text: "Current Balance: 0 mBTC" + //Layout.alignment: Qt.AlignHCenter } Label { @@ -47,20 +43,31 @@ Item { placeholderText: 'sat/vB' } - Column { + Item { Layout.fillWidth: true Layout.columnSpan: 4 - Button { + Row { + spacing: 10 anchors.horizontalCenter: parent.horizontalCenter - text: 'Pay' - onClicked: { - var i_amount = parseInt(amount.text) - if (isNaN(i_amount)) - return - var result = Daemon.currentWallet.send_onchain(address.text, i_amount, undefined, false) - if (result) - app.stack.pop() + Button { +// anchors.horizontalCenter: parent.horizontalCenter + text: 'Pay' + enabled: address.text != '' && amount.text != '' && fee.text != '' // TODO proper validation + onClicked: { + var i_amount = parseInt(amount.text) + if (isNaN(i_amount)) + return + var result = Daemon.currentWallet.send_onchain(address.text, i_amount, undefined, false) + if (result) + app.stack.pop() + } + } + + Button { + text: 'Scan QR Code' + Layout.alignment: Qt.AlignHCenter + onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml')) } } } diff --git a/electrum/gui/qml/components/Wallets.qml b/electrum/gui/qml/components/Wallets.qml index 7dafba18b..6fa0195de 100644 --- a/electrum/gui/qml/components/Wallets.qml +++ b/electrum/gui/qml/components/Wallets.qml @@ -2,42 +2,104 @@ import QtQuick 2.6 import QtQuick.Layouts 1.0 import QtQuick.Controls 2.0 -Item { - property string title: 'Wallets' +Pane { + id: rootItem - anchors.fill: parent + property string title: 'Wallets' - ListView { + ColumnLayout { + id: layout width: parent.width height: parent.height - model: Daemon.availableWallets - delegate: Item { - width: ListView.view.width - height: 50 + Item { + width: parent.width + height: detailsLayout.height + + + GridLayout { + id: detailsLayout + width: parent.width + columns: 4 + + Label { text: 'Wallet'; Layout.columnSpan: 2 } + Label { text: Daemon.walletName; Layout.columnSpan: 2 } + + Label { text: 'txinType' } + Label { text: Daemon.currentWallet.txinType } + + Label { text: 'is deterministic' } + Label { text: Daemon.currentWallet.isDeterministic } + + Label { text: 'is watch only' } + Label { text: Daemon.currentWallet.isWatchOnly } - RowLayout { - x: 20 - spacing: 20 + Label { text: 'is Encrypted' } + Label { text: Daemon.currentWallet.isEncrypted } - Image { - source: "../../../gui/kivy/theming/light/wallet.png" + Label { text: 'is Hardware' } + Label { text: Daemon.currentWallet.isHardware } + + Label { text: 'derivation path (BIP32)'; visible: Daemon.currentWallet.isDeterministic } + Label { text: Daemon.currentWallet.derivationPath; visible: Daemon.currentWallet.isDeterministic } } + } +// } + + Item { + width: parent.width +// height: detailsFrame.height + Layout.fillHeight: true + Frame { + id: detailsFrame + width: parent.width + height: parent.height + + ListView { + id: listview + width: parent.width +// Layout.fillHeight: true + height: parent.height + clip:true + model: Daemon.availableWallets - Label { - font.pointSize: model.active ? 14 : 13 - font.bold: model.active - text: model.name - Layout.fillWidth: true + // header: sadly seems to be buggy + + delegate: AbstractButton { + width: ListView.view.width + height: 50 + onClicked: console.log('delegate clicked') + RowLayout { + x: 20 + spacing: 20 + + Image { + source: "../../../gui/kivy/theming/light/wallet.png" + } + + Label { + font.pointSize: 12 + text: model.name + Layout.fillWidth: true + } + Button { + text: 'Load' + onClicked: { + Daemon.load_wallet(model.path, null) + } + } } } + }}} - MouseArea { - anchors.fill: parent - onClicked: openMenu() + Button { + Layout.alignment: Qt.AlignHCenter + text: 'Create Wallet' + onClicked: { + var dialog = app.newWalletWizard.createObject(rootItem) + dialog.open() } } } - } diff --git a/electrum/gui/qml/components/landing.qml b/electrum/gui/qml/components/landing.qml index 55c32c145..302d586a1 100644 --- a/electrum/gui/qml/components/landing.qml +++ b/electrum/gui/qml/components/landing.qml @@ -1,59 +1,87 @@ import QtQuick 2.6 import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.0 import QtQml 2.6 Item { id: rootItem - property string title: 'Network' + property string title: Daemon.walletName property QtObject menu: Menu { MenuItem { text: 'Wallets'; onTriggered: stack.push(Qt.resolvedUrl('Wallets.qml')) } MenuItem { text: 'Network'; onTriggered: stack.push(Qt.resolvedUrl('NetworkStats.qml')) } } - Column { - width: parent.width + ColumnLayout { + anchors.fill: parent - Button { - text: 'Scan QR Code' - onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml')) + TabBar { + id: tabbar + Layout.fillWidth: true + currentIndex: swipeview.currentIndex + TabButton { + text: qsTr('Receive') + } + TabButton { + text: qsTr('History') + } + TabButton { + enabled: !Daemon.currentWallet.isWatchOnly + text: qsTr('Send') + } } - Button { - text: 'Send' - onClicked: app.stack.push(Qt.resolvedUrl('Send.qml')) - } + SwipeView { + id: swipeview - Button { - text: 'Show TX History' - onClicked: app.stack.push(Qt.resolvedUrl('History.qml')) - } + Layout.fillHeight: true + Layout.fillWidth: true + currentIndex: tabbar.currentIndex + + Item { + + ColumnLayout { + width: parent.width + y: 20 + spacing: 20 + + Button { + onClicked: stack.push(Qt.resolvedUrl('Wallets.qml')) + text: 'Wallets' + Layout.alignment: Qt.AlignHCenter + } - Button { - text: 'Create Wallet' - onClicked: { - var dialog = newWalletWizard.createObject(rootItem) - dialog.open() + Button { + text: 'Create Wallet' + Layout.alignment: Qt.AlignHCenter + onClicked: { + var dialog = app.newWalletWizard.createObject(rootItem) + dialog.open() + } + } + + } } - } - } + Item { + History { + id: history + anchors.fill: parent + } + } - Component { - id: newWalletWizard - NewWalletWizard { - parent: Overlay.overlay - x: 12 - y: 12 - width: parent.width - 24 - height: parent.height - 24 - - Overlay.modal: Rectangle { - color: "#aa000000" + + Item { + enabled: !Daemon.currentWallet.isWatchOnly + Send { + anchors.fill: parent + } } } + } + } diff --git a/electrum/gui/qml/components/main.qml b/electrum/gui/qml/components/main.qml index bcbaeb002..b23cd8b26 100644 --- a/electrum/gui/qml/components/main.qml +++ b/electrum/gui/qml/components/main.qml @@ -1,5 +1,5 @@ import QtQuick 2.6 -import QtQuick.Controls 2.0 +import QtQuick.Controls 2.3 import QtQuick.Layouts 1.0 import QtQuick.Controls.Material 2.0 @@ -25,15 +25,50 @@ ApplicationWindow anchors.fill: parent ToolButton { text: qsTr("‹") - enabled: stack.currentItem.StackView.index > 0 + enabled: stack.depth > 1 onClicked: stack.pop() } + Item { + width: column.width + height: column.height + MouseArea { + anchors.fill: parent + onClicked: { + var dialog = app.messageDialog.createObject(app, {'message': + 'Electrum is currently on ' + Network.networkName + '' + }) + dialog.open() + } + + } + + Column { + id: column + visible: Network.isTestNet + Image { + anchors.horizontalCenter: parent.horizontalCenter + width: 16 + height: 16 + source: "../../icons/info.png" + } + + Label { + id: networkNameLabel + text: Network.networkName + color: Material.accentColor //'orange' + font.pointSize: 5 + } + } + } + Label { text: stack.currentItem.title elide: Label.ElideRight horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter Layout.fillWidth: true + font.pointSize: 10 + font.bold: true } ToolButton { text: qsTr("⋮") @@ -55,7 +90,7 @@ ApplicationWindow Timer { id: splashTimer - interval: 1000 + interval: 10 onTriggered: { splash.opacity = 0 } @@ -73,8 +108,49 @@ ApplicationWindow } } + property alias newWalletWizard: _newWalletWizard + Component { + id: _newWalletWizard + NewWalletWizard { + parent: Overlay.overlay + x: 12 + y: 12 + width: parent.width - 24 + height: parent.height - 24 + + Overlay.modal: Rectangle { + color: "#aa000000" + } + } + } + + property alias messageDialog: _messageDialog + Component { + id: _messageDialog + Dialog { + parent: Overlay.overlay + modal: true + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + title: "Message" + property alias message: messageLabel.text + Label { + id: messageLabel + text: "Lorem ipsum dolor sit amet..." + } + + } + } + Component.onCompleted: { Daemon.load_wallet() splashTimer.start() } + + onClosing: { + // destroy most GUI components so that we don't dump so many null reference warnings on exit + app.header.visible = false + mainStackView.clear() + } }