1
0

qml: also show coins in Addresses page, and add a few filter options. Additionally, long press

now activates multi-select mode, and add action to (un)freeze selection.
This commit is contained in:
Sander van Grieken
2023-10-13 17:41:21 +02:00
parent ec8500bd55
commit cf91d2e5cc
6 changed files with 516 additions and 61 deletions

View File

@@ -2,6 +2,7 @@ import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQml.Models 2.2
import org.electrum 1.0
@@ -14,34 +15,246 @@ Pane {
padding: 0
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 0
ElListView {
id: listview
ColumnLayout {
id: layout
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: Daemon.currentWallet.addressModel
currentIndex: -1
Pane {
id: filtersPane
Layout.fillWidth: true
GridLayout {
columns: 3
width: parent.width
section.property: 'type'
section.criteria: ViewSection.FullString
section.delegate: sectionDelegate
CheckBox {
id: showUsed
text: qsTr('Show Used')
enabled: listview.filterModel.showAddressesCoins != 2
onCheckedChanged: listview.filterModel.showUsed = checked
Component.onCompleted: checked = listview.filterModel.showUsed
}
delegate: AddressDelegate {
onClicked: {
var page = app.stack.push(Qt.resolvedUrl('AddressDetails.qml'), {'address': model.address})
page.addressDetailsChanged.connect(function() {
// update listmodel when details change
listview.model.updateAddress(model.address)
})
RowLayout {
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.alignment: Qt.AlignRight
Label {
text: qsTr('Show')
}
ElComboBox {
id: showCoinsAddresses
textRole: 'text'
valueRole: 'value'
model: ListModel {
id: showCoinsAddressesModel
Component.onCompleted: {
// we need to fill the model like this, as ListElement can't evaluate script
showCoinsAddressesModel.append({'text': qsTr('Addresses'), 'value': 1})
showCoinsAddressesModel.append({'text': qsTr('Coins'), 'value': 2})
showCoinsAddressesModel.append({'text': qsTr('Both'), 'value': 3})
showCoinsAddresses.currentIndex = 0
for (let i=0; i < showCoinsAddressesModel.count; i++) {
if (showCoinsAddressesModel.get(i).value == listview.filterModel.showAddressesCoins) {
showCoinsAddresses.currentIndex = i
break
}
}
}
}
onCurrentValueChanged: {
if (activeFocus && currentValue) {
listview.filterModel.showAddressesCoins = currentValue
}
}
}
}
RowLayout {
Layout.columnSpan: 3
Layout.fillWidth: true
TextField {
id: searchEdit
Layout.fillWidth: true
placeholderText: qsTr('text search')
onTextChanged: listview.filterModel.filterText = text
}
Image {
source: Qt.resolvedUrl('../../icons/zoom.png')
sourceSize.width: constants.iconSizeMedium
sourceSize.height: constants.iconSizeMedium
}
}
}
}
ScrollIndicator.vertical: ScrollIndicator { }
Frame {
id: channelsFrame
Layout.fillWidth: true
Layout.fillHeight: true
verticalPadding: 0
horizontalPadding: 0
background: PaneInsetBackground {}
ElListView {
id: listview
anchors.fill: parent
clip: true
property QtObject backingModel: Daemon.currentWallet.addressCoinModel
property QtObject filterModel: Daemon.currentWallet.addressCoinModel.filterModel
property bool selectMode: false
property bool freeze: true
model: visualModel
currentIndex: -1
section.property: 'type'
section.criteria: ViewSection.FullString
section.delegate: sectionDelegate
function getSelectedItems() {
var items = []
for (let i = 0; i < selectedGroup.count; i++) {
let modelitem = selectedGroup.get(i).model
if (modelitem.outpoint)
items.push(modelitem.outpoint)
else
items.push(modelitem.address)
}
return items
}
DelegateModel {
id: visualModel
model: listview.filterModel
groups: [
DelegateModelGroup {
id: selectedGroup;
name: 'selected'
onCountChanged: {
if (count == 0)
listview.selectMode = false
}
}
]
delegate: Loader {
id: loader
width: parent.width
sourceComponent: model.outpoint ? _coinDelegate : _addressDelegate
function toggle() {
loader.DelegateModel.inSelected = !loader.DelegateModel.inSelected
}
Component {
id: _addressDelegate
AddressDelegate {
id: addressDelegate
width: parent.width
property bool selected: loader.DelegateModel.inSelected
highlighted: selected
onClicked: {
if (!listview.selectMode) {
var page = app.stack.push(Qt.resolvedUrl('AddressDetails.qml'), {
address: model.address
})
page.addressDetailsChanged.connect(function() {
// update listmodel when details change
listview.backingModel.updateAddress(model.address)
})
} else {
loader.toggle()
}
}
onPressAndHold: {
loader.toggle()
if (!listview.selectMode && selectedGroup.count > 0)
listview.selectMode = true
}
}
}
Component {
id: _coinDelegate
Pane {
height: coinDelegate.height
padding: 0
background: Rectangle {
color: Qt.darker(constants.darkerBackground, 1.10)
}
CoinDelegate {
id: coinDelegate
width: parent.width
property bool selected: loader.DelegateModel.inSelected
highlighted: selected
onClicked: {
if (!listview.selectMode) {
var page = app.stack.push(Qt.resolvedUrl('TxDetails.qml'), {
txid: model.txid
})
} else {
loader.toggle()
}
}
onPressAndHold: {
loader.toggle()
if (!listview.selectMode && selectedGroup.count > 0)
listview.selectMode = true
}
}
}
}
}
}
add: Transition {
NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: 300
easing.type: Easing.OutQuad
}
}
onSelectModeChanged: {
if (selectMode) {
listview.freeze = !selectedGroup.get(0).model.held
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
}
ButtonContainer {
Layout.fillWidth: true
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
text: listview.freeze ? qsTr('Freeze') : qsTr('Unfreeze')
icon.source: '../../icons/seal.png'
visible: listview.selectMode
onClicked: {
var items = listview.getSelectedItems()
listview.backingModel.setFrozenForItems(listview.freeze, items)
selectedGroup.remove(0, selectedGroup.count)
}
}
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
text: qsTr('Pay from...')
icon.source: '../../icons/tab_send.png'
visible: listview.selectMode
enabled: false // TODO
onClicked: {
//
}
}
}
}
@@ -52,7 +265,6 @@ Pane {
id: root
width: ListView.view.width
height: childrenRect.height
required property string section
property string section_label: section == 'receive'
? qsTr('receive addresses')
@@ -74,6 +286,6 @@ Pane {
}
Component.onCompleted: {
Daemon.currentWallet.addressModel.initModel()
Daemon.currentWallet.addressCoinModel.initModel()
}
}

View File

@@ -27,9 +27,9 @@ ItemDelegate {
Label {
id: indexLabel
font.bold: true
text: model.iaddr < 10
? '#' + ('0'+model.iaddr).slice(-2)
: '#' + model.iaddr
text: model.addridx < 10
? '#' + ('0'+model.addridx).slice(-2)
: '#' + model.addridx
Layout.fillWidth: true
}
Label {

View File

@@ -0,0 +1,97 @@
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
ItemDelegate {
id: delegate
width: ListView.view.width
height: delegateLayout.height
highlighted: ListView.isCurrentItem
font.pixelSize: constants.fontSizeMedium // set default font size for child controls
ColumnLayout {
id: delegateLayout
width: parent.width
spacing: 0
GridLayout {
columns: 3
Layout.topMargin: constants.paddingSmall
Layout.leftMargin: constants.paddingLarge + 2*constants.paddingLarge
Layout.rightMargin: constants.paddingLarge
Rectangle {
id: useIndicator
Layout.rowSpan: 2
Layout.preferredWidth: constants.iconSizeSmall
Layout.preferredHeight: constants.iconSizeSmall
Layout.alignment: Qt.AlignTop
color: model.held
? constants.colorAddressFrozen
: constants.colorAddressUsedWithBalance
}
RowLayout {
Layout.fillWidth: true
Label {
font.family: FixedFont
text: model.outpoint
elide: Text.ElideMiddle
Layout.preferredWidth: implicitWidth + constants.paddingMedium
}
Label {
Layout.fillWidth: true
visible: model.short_id
font.family: FixedFont
font.pixelSize: constants.fontSizeSmall
text: '[' + model.short_id + ']'
}
Item {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
visible: !model.short_id
Image {
source: Qt.resolvedUrl('../../../icons/unconfirmed.png')
sourceSize.width: constants.iconSizeSmall
sourceSize.height: constants.iconSizeSmall
}
}
}
RowLayout {
Label {
font.family: FixedFont
text: Config.formatSats(model.amount, false)
visible: model.amount.satsInt != 0
}
Label {
color: Material.accentColor
text: Config.baseUnit
visible: model.amount.satsInt != 0
}
}
Label {
id: labelLabel
Layout.fillWidth: true
Layout.columnSpan: 2
visible: model.label
font.pixelSize: constants.fontSizeMedium
text: model.label
elide: Text.ElideRight
maximumLineCount: 2
wrapMode: Text.WordWrap
}
}
Item {
Layout.preferredWidth: 1
Layout.preferredHeight: constants.paddingSmall
}
}
}