Skip to content

Commit a46d12d

Browse files
committed
qml: Add sorting bar to Peers page
1 parent bb4e261 commit a46d12d

File tree

6 files changed

+226
-41
lines changed

6 files changed

+226
-41
lines changed

src/Makefile.qt.include

+1
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ QML_RES_QML = \
361361
qml/controls/Setting.qml \
362362
qml/controls/TextButton.qml \
363363
qml/controls/Theme.qml \
364+
qml/controls/ToggleButton.qml \
364365
qml/controls/ValueInput.qml \
365366
qml/pages/initerrormessage.qml \
366367
qml/pages/main.qml \

src/qml/bitcoin_qml.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<file>controls/Setting.qml</file>
3232
<file>controls/TextButton.qml</file>
3333
<file>controls/Theme.qml</file>
34+
<file>controls/ToggleButton.qml</file>
3435
<file>controls/ValueInput.qml</file>
3536
<file>pages/initerrormessage.qml</file>
3637
<file>pages/main.qml</file>

src/qml/controls/ToggleButton.qml

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) 2023 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
import QtQuick 2.15
6+
import QtQuick.Controls 2.15
7+
8+
Button {
9+
property color bgDefaultColor: Theme.color.neutral2
10+
property color bgHoverColor: Theme.color.neutral2
11+
property color bgActiveColor: Theme.color.neutral5
12+
property color textColor: Theme.color.neutral7
13+
property color textHoverColor: Theme.color.orangeLight1
14+
property color textActiveColor: Theme.color.neutral9
15+
id: root
16+
checkable: true
17+
hoverEnabled: true
18+
leftPadding: 12
19+
rightPadding: 12
20+
topPadding: 5
21+
bottomPadding: 5
22+
23+
contentItem: CoreText {
24+
id: buttonText
25+
text: parent.text
26+
font.pixelSize: 13
27+
color: root.textColor
28+
29+
Behavior on color {
30+
ColorAnimation { duration: 150 }
31+
}
32+
}
33+
34+
background: Rectangle {
35+
id: bg
36+
color: root.bgDefaultColor
37+
radius: 5
38+
39+
Behavior on color {
40+
ColorAnimation { duration: 150 }
41+
}
42+
}
43+
44+
states: [
45+
State {
46+
name: "CHECKED"; when: root.checked
47+
PropertyChanges { target: bg; color: root.bgActiveColor }
48+
PropertyChanges { target: buttonText; color: root.textActiveColor }
49+
},
50+
State {
51+
name: "HOVER"; when: root.hovered
52+
PropertyChanges { target: bg; color: root.bgHoverColor }
53+
PropertyChanges { target: buttonText; color: root.textHoverColor }
54+
}
55+
]
56+
}

src/qml/pages/node/Peers.qml

+131-41
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,98 @@ Page {
1616
id: navbar
1717
}
1818

19-
Text {
19+
CoreText {
2020
anchors.top: parent.top
2121
anchors.horizontalCenter: parent.horizontalCenter
2222
id: description
23-
height: 75
2423
width: Math.min(parent.width - 40, 450)
25-
wrapMode: Text.WordWrap
2624
text: qsTr("Peers are nodes you are connected to. You want to ensure that you are connected to x, y and z, but not a, b, and c. Learn more.")
27-
font.family: "Inter"
28-
font.styleName: "Regular"
2925
font.pixelSize: 13
3026
color: Theme.color.neutral7
31-
horizontalAlignment: Text.AlignHCenter
27+
}
28+
29+
Flow {
30+
id: sortSelection
31+
anchors.top: description.bottom
32+
anchors.topMargin: 20
33+
anchors.horizontalCenter: parent.horizontalCenter
34+
width: Math.min(parent.width - 40, 450)
35+
spacing: 10
36+
ToggleButton {
37+
text: qsTr("ID")
38+
autoExclusive: true
39+
checked: true
40+
onClicked: {
41+
peerListModelProxy.sortBy = "nodeId"
42+
}
43+
}
44+
ToggleButton {
45+
text: qsTr("Direction")
46+
autoExclusive: true
47+
onClicked: {
48+
peerListModelProxy.sortBy = "direction"
49+
}
50+
}
51+
ToggleButton {
52+
text: qsTr("User Agent")
53+
autoExclusive: true
54+
onClicked: {
55+
peerListModelProxy.sortBy = "subversion"
56+
}
57+
}
58+
ToggleButton {
59+
text: qsTr("Type")
60+
autoExclusive: true
61+
onClicked: {
62+
peerListModelProxy.sortBy = "connectionType"
63+
}
64+
}
65+
ToggleButton {
66+
text: qsTr("Ip")
67+
autoExclusive: true
68+
onClicked: {
69+
peerListModelProxy.sortBy = "address"
70+
}
71+
}
72+
ToggleButton {
73+
text: qsTr("Network")
74+
autoExclusive: true
75+
onClicked: {
76+
peerListModelProxy.sortBy = "network"
77+
}
78+
}
3279
}
3380

3481
ListView {
3582
id: listView
3683
clip: true
3784
width: Math.min(parent.width - 40, 450)
38-
anchors.top: description.bottom
85+
anchors.top: sortSelection.bottom
86+
anchors.topMargin: 30
3987
anchors.bottom: parent.bottom
4088
anchors.horizontalCenter: parent.horizontalCenter
4189
model: peerListModelProxy
4290
spacing: 15
4391

4492
footer: Loader {
45-
anchors.centerIn: parent
4693
height: 75
4794
active: nodeModel.numOutboundPeers < nodeModel.maxNumOutboundPeers
95+
width: listView.width
4896
visible: active
49-
sourceComponent: RowLayout {
50-
spacing: 20
51-
PeersIndicator {
52-
Layout.alignment: Qt.AlignHCenter
53-
numOutboundPeers: nodeModel.numOutboundPeers
54-
maxNumOutboundPeers: nodeModel.maxNumOutboundPeers
55-
}
56-
Text {
57-
Layout.alignment: Qt.AlignHCenter
58-
text: qsTr("Looking for %1 more peer(s)").arg(
59-
nodeModel.maxNumOutboundPeers - nodeModel.numOutboundPeers)
60-
font.family: "Inter"
61-
font.styleName: "Regular"
62-
font.pixelSize: 15
63-
color: Theme.color.neutral7
97+
sourceComponent: Item {
98+
RowLayout {
99+
anchors.centerIn: parent
100+
spacing: 20
101+
PeersIndicator {
102+
numOutboundPeers: nodeModel.numOutboundPeers
103+
maxNumOutboundPeers: nodeModel.maxNumOutboundPeers
104+
}
105+
CoreText {
106+
text: qsTr("Looking for %1 more peer(s)").arg(
107+
nodeModel.maxNumOutboundPeers - nodeModel.numOutboundPeers)
108+
font.pixelSize: 15
109+
color: Theme.color.neutral7
110+
}
64111
}
65112
}
66113
}
@@ -70,47 +117,90 @@ Page {
70117
required property string address;
71118
required property string subversion;
72119
required property string direction;
73-
implicitHeight: 65
120+
required property string connectionType;
121+
required property string network;
122+
implicitHeight: 60
74123
implicitWidth: listView.width
75124

125+
Connections {
126+
target: peerListModelProxy
127+
function onSortByChanged(roleName) {
128+
setTextByRole(roleName)
129+
}
130+
function onDataChanged(startIndex, endIndex) {
131+
setTextByRole(peerListModelProxy.sortBy)
132+
}
133+
}
134+
135+
Component.onCompleted: {
136+
setTextByRole(peerListModelProxy.sortBy)
137+
}
138+
139+
function setTextByRole(roleName) {
140+
if (roleName == "nodeId") {
141+
primary.text = "#" + nodeId
142+
secondary.text = direction
143+
tertiary.text = address
144+
quaternary.text = subversion
145+
} else if (roleName == "direction") {
146+
primary.text = direction
147+
secondary.text = "#" + nodeId
148+
tertiary.text = address
149+
quaternary.text = subversion
150+
} else if (roleName == "subversion") {
151+
primary.text = subversion
152+
secondary.text = "#" + nodeId
153+
tertiary.text = address
154+
quaternary.text = direction
155+
} else if (roleName == "address") {
156+
primary.text = address
157+
secondary.text = direction
158+
tertiary.text = "#" + nodeId
159+
quaternary.text = subversion
160+
} else if (roleName == "connectionType") {
161+
primary.text = connectionType
162+
secondary.text = direction
163+
tertiary.text = address
164+
quaternary.text = subversion
165+
} else if (roleName == "network") {
166+
primary.text = network
167+
secondary.text = direction
168+
tertiary.text = address
169+
quaternary.text = subversion
170+
} else {
171+
primary.text = "#" + nodeId
172+
secondary.text = direction
173+
tertiary.text = address
174+
quaternary.text = subversion
175+
}
176+
}
177+
76178
ColumnLayout {
77179
anchors.left: parent.left
78-
Label {
180+
CoreText {
79181
Layout.alignment: Qt.AlignLeft
80182
id: primary
81-
text: "#" + nodeId
82-
font.family: "Inter"
83-
font.styleName: "Regular"
84183
font.pixelSize: 18
85184
color: Theme.color.neutral9
86185
}
87-
Label {
186+
CoreText {
88187
Layout.alignment: Qt.AlignLeft
89188
id: tertiary
90-
text: address
91-
font.family: "Inter"
92-
font.styleName: "Regular"
93189
font.pixelSize: 15
94190
color: Theme.color.neutral7
95191
}
96192
}
97193
ColumnLayout {
98194
anchors.right: parent.right
99-
Label {
195+
CoreText {
100196
Layout.alignment: Qt.AlignRight
101-
id:secondary
102-
text: direction
103-
font.family: "Inter"
104-
font.styleName: "Regular"
197+
id: secondary
105198
font.pixelSize: 18
106199
color: Theme.color.neutral9
107200
}
108-
Label {
201+
CoreText {
109202
Layout.alignment: Qt.AlignRight
110203
id: quaternary
111-
text: subversion
112-
font.family: "Inter"
113-
font.styleName: "Regular"
114204
font.pixelSize: 15
115205
color: Theme.color.neutral7
116206
}

src/qml/peerlistsortproxy.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ QHash<int, QByteArray> PeerListSortProxy::roleNames() const
2626
return roles;
2727
}
2828

29+
int PeerListSortProxy::RoleNameToIndex(const QString & name) const
30+
{
31+
auto role_names = roleNames();
32+
auto keys = role_names.keys(name.toUtf8());
33+
if (!keys.empty()) {
34+
return keys.first();
35+
} else {
36+
return PeerTableModel::NetNodeId;
37+
}
38+
}
39+
2940
QVariant PeerListSortProxy::data(const QModelIndex& index, int role) const
3041
{
3142
if (role == PeerTableModel::StatsRole) {
@@ -35,3 +46,17 @@ QVariant PeerListSortProxy::data(const QModelIndex& index, int role) const
3546
QModelIndex converted_index = PeerTableSortProxy::index(index.row(), role);
3647
return PeerTableSortProxy::data(converted_index, Qt::DisplayRole);
3748
}
49+
50+
QString PeerListSortProxy::sortBy() const
51+
{
52+
return m_sort_by;
53+
}
54+
55+
void PeerListSortProxy::setSortBy(const QString & roleName)
56+
{
57+
if (m_sort_by != roleName) {
58+
m_sort_by = roleName;
59+
sort(RoleNameToIndex(roleName));
60+
Q_EMIT sortByChanged(roleName);
61+
}
62+
}

src/qml/peerlistsortproxy.h

+12
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,25 @@
1414
class PeerListSortProxy : public PeerTableSortProxy
1515
{
1616
Q_OBJECT
17+
Q_PROPERTY(QString sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged)
1718

1819
public:
1920
explicit PeerListSortProxy(QObject* parent);
2021
~PeerListSortProxy() = default;
2122

2223
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
2324
QHash<int, QByteArray> roleNames() const override;
25+
QString sortBy() const;
26+
27+
public Q_SLOTS:
28+
void setSortBy(const QString & roleName);
29+
30+
Q_SIGNALS:
31+
void sortByChanged(const QString & roleName);
32+
33+
private:
34+
int RoleNameToIndex(const QString & name) const;
35+
QString m_sort_by;
2436
};
2537

2638
#endif // BITCOIN_QML_PEERLISTSORTPROXY_H

0 commit comments

Comments
 (0)