Skip to content

Commit 159bc04

Browse files
committed
qml: Add sorting bar to Peers page
1 parent 37c4d37 commit 159bc04

File tree

6 files changed

+232
-23
lines changed

6 files changed

+232
-23
lines changed

src/Makefile.qt.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ QML_RES_QML = \
358358
qml/controls/Setting.qml \
359359
qml/controls/TextButton.qml \
360360
qml/controls/Theme.qml \
361+
qml/controls/ToggleButton.qml \
361362
qml/controls/ValueInput.qml \
362363
qml/pages/initerrormessage.qml \
363364
qml/pages/main.qml \

src/qml/bitcoin_qml.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<file>controls/Setting.qml</file>
2929
<file>controls/TextButton.qml</file>
3030
<file>controls/Theme.qml</file>
31+
<file>controls/ToggleButton.qml</file>
3132
<file>controls/ValueInput.qml</file>
3233
<file>pages/initerrormessage.qml</file>
3334
<file>pages/main.qml</file>

src/qml/controls/ToggleButton.qml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 defaultColor: Theme.color.neutral2
10+
property color hoverColor: Theme.color.neutral2
11+
property color activeColor: 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+
font.family: "Inter"
19+
font.styleName: "Regular"
20+
font.pixelSize: 13
21+
leftPadding: 12
22+
rightPadding: 12
23+
topPadding: 5
24+
bottomPadding: 5
25+
26+
contentItem: Text {
27+
id: buttonText
28+
text: parent.text
29+
font: parent.font
30+
color: Theme.color.white
31+
horizontalAlignment: Text.AlignHCenter
32+
verticalAlignment: Text.AlignVCenter
33+
34+
Behavior on color {
35+
ColorAnimation { duration: 150 }
36+
}
37+
}
38+
background: Rectangle {
39+
id: bg
40+
color: root.defaultColor
41+
radius: 5
42+
43+
Behavior on color {
44+
ColorAnimation { duration: 150 }
45+
}
46+
}
47+
48+
state:"DEFAULT"
49+
50+
states: [
51+
State {
52+
name: "DEFAULT"
53+
PropertyChanges { target: bg; color: root.defaultColor }
54+
},
55+
State {
56+
name: "CHECKED"
57+
when: root.checked
58+
PropertyChanges { target: bg; color: root.activeColor }
59+
PropertyChanges { target: buttonText; color: root.textActiveColor }
60+
},
61+
State {
62+
name: "HOVER"
63+
when: root.hovered
64+
PropertyChanges { target: bg; color: root.hoverColor }
65+
PropertyChanges { target: buttonText; color: root.textHoverColor }
66+
}
67+
]
68+
}

src/qml/pages/node/Peers.qml

Lines changed: 125 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ Page {
2020
anchors.top: parent.top
2121
anchors.horizontalCenter: parent.horizontalCenter
2222
id: description
23-
height: 75
2423
width: Math.min(parent.width - 40, 450)
2524
wrapMode: Text.WordWrap
2625
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.")
@@ -31,36 +30,88 @@ Page {
3130
horizontalAlignment: Text.AlignHCenter
3231
}
3332

33+
RowLayout {
34+
id: sortSelection
35+
anchors.top: description.bottom
36+
anchors.topMargin: 20
37+
anchors.horizontalCenter: parent.horizontalCenter
38+
spacing: 10
39+
ToggleButton {
40+
text: qsTr("ID")
41+
autoExclusive: true
42+
onClicked: {
43+
peerListModelProxy.sortBy = "nodeId"
44+
}
45+
}
46+
ToggleButton {
47+
text: qsTr("Direction")
48+
autoExclusive: true
49+
onClicked: {
50+
peerListModelProxy.sortBy = "direction"
51+
}
52+
}
53+
ToggleButton {
54+
text: qsTr("User Agent")
55+
autoExclusive: true
56+
onClicked: {
57+
peerListModelProxy.sortBy = "subversion"
58+
}
59+
}
60+
ToggleButton {
61+
text: qsTr("Type")
62+
autoExclusive: true
63+
onClicked: {
64+
peerListModelProxy.sortBy = "connectionType"
65+
}
66+
}
67+
ToggleButton {
68+
text: qsTr("Ip")
69+
autoExclusive: true
70+
onClicked: {
71+
peerListModelProxy.sortBy = "address"
72+
}
73+
}
74+
ToggleButton {
75+
text: qsTr("Network")
76+
autoExclusive: true
77+
onClicked: {
78+
peerListModelProxy.sortBy = "network"
79+
}
80+
}
81+
}
82+
3483
ListView {
3584
id: listView
3685
clip: true
3786
width: Math.min(parent.width - 40, 450)
38-
anchors.top: description.bottom
87+
anchors.top: sortSelection.bottom
88+
anchors.topMargin: 35
3989
anchors.bottom: parent.bottom
4090
anchors.horizontalCenter: parent.horizontalCenter
4191
model: peerListModelProxy
4292
spacing: 15
4393

4494
footer: Loader {
45-
anchors.centerIn: parent
4695
height: 75
4796
active: nodeModel.numOutboundPeers < nodeModel.maxNumOutboundPeers
97+
width: listView.width
4898
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
99+
sourceComponent: Item {
100+
RowLayout {
101+
anchors.centerIn: parent
102+
spacing: 20
103+
PeersIndicator {
104+
numOutboundPeers: nodeModel.numOutboundPeers
105+
maxNumOutboundPeers: nodeModel.maxNumOutboundPeers
106+
}
107+
Text {
108+
text: qsTr("Looking for %1 more peer(s)").arg(
109+
nodeModel.maxNumOutboundPeers - nodeModel.numOutboundPeers)
110+
font.family: "Inter"
111+
font.styleName: "Regular"
112+
font.pixelSize: 15
113+
color: Theme.color.neutral7
114+
}
64115
}
65116
}
66117
}
@@ -70,15 +121,69 @@ Page {
70121
required property string address;
71122
required property string subversion;
72123
required property string direction;
124+
required property string connectionType;
125+
required property string network;
73126
implicitHeight: 65
74127
implicitWidth: listView.width
75128

129+
Connections {
130+
target: peerListModelProxy
131+
function onSortByChanged(roleName) {
132+
setTextByRole(roleName)
133+
}
134+
function onDataChanged(startIndex, endIndex) {
135+
setTextByRole(peerListModelProxy.sortBy)
136+
}
137+
}
138+
139+
Component.onCompleted: {
140+
setTextByRole(peerListModelProxy.sortBy)
141+
}
142+
143+
function setTextByRole(roleName) {
144+
if (roleName == "nodeId") {
145+
primary.text = "#" + nodeId
146+
secondary.text = direction
147+
tertiary.text = address
148+
quaternary.text = subversion
149+
} else if (roleName == "direction") {
150+
primary.text = direction
151+
secondary.text = "#" + nodeId
152+
tertiary.text = address
153+
quaternary.text = subversion
154+
} else if (roleName == "subversion") {
155+
primary.text = subversion
156+
secondary.text = "#" + nodeId
157+
tertiary.text = address
158+
quaternary.text = direction
159+
} else if (roleName == "address") {
160+
primary.text = address
161+
secondary.text = direction
162+
tertiary.text = "#" + nodeId
163+
quaternary.text = subversion
164+
} else if (roleName == "connectionType") {
165+
primary.text = connectionType
166+
secondary.text = direction
167+
tertiary.text = address
168+
quaternary.text = subversion
169+
} else if (roleName == "network") {
170+
primary.text = network
171+
secondary.text = direction
172+
tertiary.text = address
173+
quaternary.text = subversion
174+
} else {
175+
primary.text = "#" + nodeId
176+
secondary.text = direction
177+
tertiary.text = address
178+
quaternary.text = subversion
179+
}
180+
}
181+
76182
ColumnLayout {
77183
anchors.left: parent.left
78184
Label {
79185
Layout.alignment: Qt.AlignLeft
80186
id: primary
81-
text: "#" + nodeId
82187
font.family: "Inter"
83188
font.styleName: "Regular"
84189
font.pixelSize: 18
@@ -87,7 +192,6 @@ Page {
87192
Label {
88193
Layout.alignment: Qt.AlignLeft
89194
id: tertiary
90-
text: address
91195
font.family: "Inter"
92196
font.styleName: "Regular"
93197
font.pixelSize: 15
@@ -98,8 +202,7 @@ Page {
98202
anchors.right: parent.right
99203
Label {
100204
Layout.alignment: Qt.AlignRight
101-
id:secondary
102-
text: direction
205+
id: secondary
103206
font.family: "Inter"
104207
font.styleName: "Regular"
105208
font.pixelSize: 18
@@ -108,7 +211,6 @@ Page {
108211
Label {
109212
Layout.alignment: Qt.AlignRight
110213
id: quaternary
111-
text: subversion
112214
font.family: "Inter"
113215
font.styleName: "Regular"
114216
font.pixelSize: 15

src/qml/peerlistsortproxy.cpp

Lines changed: 25 additions & 0 deletions
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

Lines changed: 12 additions & 0 deletions
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)