qml: dashboard
Balance details are shown if the user presses and holds the balance area; the idea is that this should be less chaotic than if the popup is triggerred by a simple click. However, we might as well try with a simple click, because we already do it with transaction details; I am not sure what is the best option, we should try both. This also makes 'new channel' and 'swap' buttons available from theBalance details, so that users do not need to visit the channels list.
This commit is contained in:
227
electrum/gui/qml/components/BalanceDetails.qml
Normal file
227
electrum/gui/qml/components/BalanceDetails.qml
Normal file
@@ -0,0 +1,227 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "controls"
|
||||
|
||||
Pane {
|
||||
id: rootItem
|
||||
objectName: 'BalanceDetails'
|
||||
|
||||
padding: 0
|
||||
|
||||
property bool _is2fa: Daemon.currentWallet && Daemon.currentWallet.walletType == '2fa'
|
||||
|
||||
function enableLightning() {
|
||||
var dialog = app.messageDialog.createObject(rootItem,
|
||||
{'text': qsTr('Enable Lightning for this wallet?'), 'yesno': true})
|
||||
dialog.yesClicked.connect(function() {
|
||||
Daemon.currentWallet.enableLightning()
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
|
||||
function deleteWallet() {
|
||||
var dialog = app.messageDialog.createObject(rootItem,
|
||||
{'text': qsTr('Really delete this wallet?'), 'yesno': true})
|
||||
dialog.yesClicked.connect(function() {
|
||||
Daemon.checkThenDeleteWallet(Daemon.currentWallet)
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
|
||||
function changePassword() {
|
||||
// trigger dialog via wallet (auth then signal)
|
||||
Daemon.startChangePassword()
|
||||
}
|
||||
|
||||
function importAddressesKeys() {
|
||||
var dialog = importAddressesKeysDialog.createObject(rootItem)
|
||||
dialog.open()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Flickable {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
contentHeight: flickableRoot.height
|
||||
clip:true
|
||||
interactive: height < contentHeight
|
||||
|
||||
Pane {
|
||||
id: flickableRoot
|
||||
width: parent.width
|
||||
padding: constants.paddingLarge
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
spacing: constants.paddingLarge
|
||||
|
||||
Heading {
|
||||
text: qsTr('Wallet balance')
|
||||
}
|
||||
|
||||
Piechart {
|
||||
id: piechart
|
||||
visible: Daemon.currentWallet.totalBalance.satsInt > 0
|
||||
Layout.preferredWidth: parent.width
|
||||
implicitHeight: 220 // TODO: sane value dependent on screen
|
||||
innerOffset: 6
|
||||
function updateSlices() {
|
||||
var totalB = Daemon.currentWallet.totalBalance.satsInt
|
||||
var onchainB = Daemon.currentWallet.confirmedBalance.satsInt
|
||||
var frozenB = Daemon.currentWallet.frozenBalance.satsInt
|
||||
var lnB = Daemon.currentWallet.lightningBalance.satsInt
|
||||
piechart.slices = [
|
||||
{ v: lnB/totalB, color: constants.colorPiechartLightning, text: 'Lightning' },
|
||||
{ v: (onchainB-frozenB)/totalB, color: constants.colorPiechartOnchain, text: 'On-chain' },
|
||||
{ v: frozenB/totalB, color: constants.colorPiechartFrozen, text: 'On-chain (frozen)' },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: Daemon.currentWallet
|
||||
columns: 3
|
||||
|
||||
Item {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
Layout.preferredWidth: 1; Layout.preferredHeight: 1
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
text: qsTr('Total')
|
||||
}
|
||||
FormattedAmount {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
amount: Daemon.currentWallet.totalBalance
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartLightning
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
text: qsTr('Lightning')
|
||||
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.lightningBalance
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartOnchain
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
text: qsTr('On-chain')
|
||||
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.confirmedBalance
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartFrozen
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
text: qsTr('Frozen')
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.frozenBalance
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
text: qsTr('Lightning swap');
|
||||
visible: Daemon.currentWallet.lightningCanSend.satsInt > 0 || Daemon.currentWallet.lightningCanReceive.satInt > 0
|
||||
icon.source: Qt.resolvedUrl('../../icons/update.png')
|
||||
onClicked: {
|
||||
var swaphelper = app.swaphelper.createObject(app)
|
||||
swaphelper.swapStarted.connect(function() {
|
||||
var dialog = swapProgressDialog.createObject(app, { swaphelper: swaphelper })
|
||||
dialog.open()
|
||||
})
|
||||
var dialog = swapDialog.createObject(rootItem, { swaphelper: swaphelper })
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
text: qsTr('Open Channel')
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
onClicked: {
|
||||
var dialog = openChannelDialog.createObject(rootItem)
|
||||
dialog.open()
|
||||
}
|
||||
icon.source: '../../icons/lightning.png'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: swapDialog
|
||||
SwapDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: swapProgressDialog
|
||||
SwapProgressDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: openChannelDialog
|
||||
OpenChannelDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Daemon.currentWallet
|
||||
function onBalanceChanged() {
|
||||
piechart.updateSlices()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
piechart.updateSlices()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -117,60 +117,6 @@ Pane {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
text: qsTr('Swap');
|
||||
visible: Daemon.currentWallet.lightningCanSend.satsInt > 0 || Daemon.currentWallet.lightningCanReceive.satInt > 0
|
||||
icon.source: Qt.resolvedUrl('../../icons/update.png')
|
||||
onClicked: {
|
||||
var swaphelper = app.swaphelper.createObject(app)
|
||||
swaphelper.swapStarted.connect(function() {
|
||||
var dialog = swapProgressDialog.createObject(app, { swaphelper: swaphelper })
|
||||
dialog.open()
|
||||
})
|
||||
var dialog = swapDialog.createObject(root, { swaphelper: swaphelper })
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
text: qsTr('Open Channel')
|
||||
onClicked: {
|
||||
var dialog = openChannelDialog.createObject(root)
|
||||
dialog.open()
|
||||
}
|
||||
icon.source: '../../icons/lightning.png'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: swapDialog
|
||||
SwapDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: swapProgressDialog
|
||||
SwapProgressDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: openChannelDialog
|
||||
OpenChannelDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: importChannelBackupDialog
|
||||
|
||||
@@ -135,91 +135,6 @@ Pane {
|
||||
}
|
||||
}
|
||||
|
||||
Piechart {
|
||||
id: piechart
|
||||
visible: Daemon.currentWallet.totalBalance.satsInt > 0
|
||||
Layout.preferredWidth: parent.width
|
||||
implicitHeight: 220 // TODO: sane value dependent on screen
|
||||
innerOffset: 6
|
||||
function updateSlices() {
|
||||
var totalB = Daemon.currentWallet.totalBalance.satsInt
|
||||
var onchainB = Daemon.currentWallet.confirmedBalance.satsInt
|
||||
var frozenB = Daemon.currentWallet.frozenBalance.satsInt
|
||||
var lnB = Daemon.currentWallet.lightningBalance.satsInt
|
||||
piechart.slices = [
|
||||
{ v: lnB/totalB, color: constants.colorPiechartLightning, text: 'Lightning' },
|
||||
{ v: (onchainB-frozenB)/totalB, color: constants.colorPiechartOnchain, text: 'On-chain' },
|
||||
{ v: frozenB/totalB, color: constants.colorPiechartFrozen, text: 'On-chain (frozen)' },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: Daemon.currentWallet
|
||||
columns: 3
|
||||
|
||||
Item {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
Layout.preferredWidth: 1; Layout.preferredHeight: 1
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
text: qsTr('Total')
|
||||
}
|
||||
FormattedAmount {
|
||||
visible: !Daemon.currentWallet.totalBalance.isEmpty
|
||||
amount: Daemon.currentWallet.totalBalance
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartLightning
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
text: qsTr('Lightning')
|
||||
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.lightningBalance
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartOnchain
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
text: qsTr('On-chain')
|
||||
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.confirmedBalance
|
||||
visible: !Daemon.currentWallet.lightningBalance.isEmpty || !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
Layout.preferredWidth: constants.iconSizeXSmall
|
||||
Layout.preferredHeight: constants.iconSizeXSmall
|
||||
color: constants.colorPiechartFrozen
|
||||
}
|
||||
Label {
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
text: qsTr('Frozen')
|
||||
}
|
||||
FormattedAmount {
|
||||
amount: Daemon.currentWallet.frozenBalance
|
||||
visible: !Daemon.currentWallet.frozenBalance.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.preferredWidth: parent.width
|
||||
visible: Daemon.currentWallet
|
||||
@@ -591,9 +506,6 @@ Pane {
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
function onBalanceChanged() {
|
||||
piechart.updateSlices()
|
||||
}
|
||||
function onSeedRetrieved() {
|
||||
seedText.visible = true
|
||||
showSeedText.visible = false
|
||||
|
||||
@@ -23,17 +23,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
state: 'fiat'
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: 'fiat'
|
||||
},
|
||||
State {
|
||||
name: 'btc'
|
||||
}
|
||||
]
|
||||
|
||||
TextHighlightPane {
|
||||
id: balancePane
|
||||
leftPadding: constants.paddingXLarge
|
||||
@@ -63,28 +52,28 @@ Item {
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: Daemon.fx.enabled && root.state == 'fiat'
|
||||
visible: Daemon.fx.enabled
|
||||
// attempt at making fiat state as tall as btc state:
|
||||
Layout.preferredHeight: fontMetrics.lineSpacing * 2 + balanceLayout.rowSpacing + 2
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
visible: Daemon.fx.enabled && root.state == 'fiat'
|
||||
visible: Daemon.fx.enabled
|
||||
font.pixelSize: constants.fontSizeLarge
|
||||
font.family: FixedFont
|
||||
color: constants.mutedForeground
|
||||
text: formattedTotalBalanceFiat
|
||||
}
|
||||
Label {
|
||||
visible: Daemon.fx.enabled && root.state == 'fiat'
|
||||
visible: Daemon.fx.enabled
|
||||
font.pixelSize: constants.fontSizeLarge
|
||||
color: constants.mutedForeground
|
||||
text: Daemon.fx.fiatCurrency
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: Daemon.currentWallet.isLightning && root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
Image {
|
||||
Layout.preferredWidth: constants.iconSizeSmall
|
||||
Layout.preferredHeight: constants.iconSizeSmall
|
||||
@@ -97,20 +86,20 @@ Item {
|
||||
}
|
||||
}
|
||||
Label {
|
||||
visible: Daemon.currentWallet.isLightning && root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: formattedLightningBalance
|
||||
font.family: FixedFont
|
||||
}
|
||||
Label {
|
||||
visible: Daemon.currentWallet.isLightning && root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
font.pixelSize: constants.fontSizeSmall
|
||||
color: Material.accentColor
|
||||
text: Config.baseUnit
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
Image {
|
||||
Layout.preferredWidth: constants.iconSizeSmall
|
||||
Layout.preferredHeight: constants.iconSizeSmall
|
||||
@@ -124,13 +113,13 @@ Item {
|
||||
}
|
||||
Label {
|
||||
id: formattedConfirmedBalanceLabel
|
||||
visible: root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: formattedConfirmedBalance
|
||||
font.family: FixedFont
|
||||
}
|
||||
Label {
|
||||
visible: root.state == 'btc'
|
||||
visible: Daemon.currentWallet.isLightning
|
||||
font.pixelSize: constants.fontSizeSmall
|
||||
color: Material.accentColor
|
||||
text: Config.baseUnit
|
||||
@@ -157,8 +146,8 @@ Item {
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.state = root.state == 'fiat' && Daemon.currentWallet.isLightning ? 'btc' : 'fiat'
|
||||
onPressAndHold: {
|
||||
app.stack.push(Qt.resolvedUrl('../BalanceDetails.qml'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +163,6 @@ Item {
|
||||
target: Daemon
|
||||
function onWalletLoaded() {
|
||||
setBalances()
|
||||
if (!Daemon.currentWallet.isLightning)
|
||||
root.state = 'fiat'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user