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:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
97
electrum/gui/qml/components/controls/CoinDelegate.qml
Normal file
97
electrum/gui/qml/components/controls/CoinDelegate.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user