Skip to content

Commit

Permalink
qml, control: new IPAddressValueInput
Browse files Browse the repository at this point in the history
Adding a new improved ValueInput control to handle both IP address and port values
combined in the same field with the correct visual formatting (255.255.255.255:65535).

In this iteration, validation for this control is implemented using both a function
within the control itself focused solely on ensuring correct formatting and a simple regex
validator for the valid input characters.
Future versions will see integration with network model classes, enabling parsing of IP
addresses and ports and additional checks, such as those outlined in doc/p2p-bad-ports.md.
  • Loading branch information
pablomartin4btc committed Mar 22, 2024
1 parent 9db473a commit a4f4263
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/qml/bitcoin_qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<file>controls/Header.qml</file>
<file>controls/Icon.qml</file>
<file>controls/InformationPage.qml</file>
<file>controls/IPAddressValueInput.qml</file>
<file>controls/NavButton.qml</file>
<file>controls/PageIndicator.qml</file>
<file>controls/NavigationBar.qml</file>
Expand Down
31 changes: 25 additions & 6 deletions src/qml/components/ProxySettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,25 @@ ColumnLayout {
Layout.fillWidth: true
header: qsTr("IP and Port")
errorText: qsTr("Invalid IP address or port format. Please use the format '255.255.255.255:65535'.")
showErrorText: !loadedItem.isValidIPPort(loadedItem.description)
state: !defaultProxyEnable.loadedItem.checked ? "DISABLED" : "ACTIVE"
actionItem: ValueInput {
actionItem: IPAddressValueInput {
parentState: defaultProxy.state
description: "127.0.0.1:9050"
activeFocusOnTab: true
onEditingFinished: {
defaultProxy.forceActiveFocus()
if (isValidIPPort(text)) {
defaultProxy.forceActiveFocus()
defaultProxy.showErrorText = false
} else {
defaultProxy.showErrorText = true
}
}
}
onClicked: loadedItem.forceActiveFocus()
onClicked: {
loadedItem.filled = true
loadedItem.forceActiveFocus()
}
}
Separator { Layout.fillWidth: true }
Header {
Expand Down Expand Up @@ -90,15 +100,24 @@ ColumnLayout {
Layout.fillWidth: true
header: qsTr("IP and Port")
errorText: qsTr("Invalid IP address or port format. Please use the format '255.255.255.255:65535'.")
showErrorText: !loadedItem.isValidIPPort(loadedItem.description)
state: !torProxyEnable.loadedItem.checked ? "DISABLED" : "ACTIVE"
actionItem: ValueInput {
actionItem: IPAddressValueInput {
parentState: torProxy.state
description: "127.0.0.1:9050"
onEditingFinished: {
torProxy.forceActiveFocus()
if (isValidIPPort(text)) {
torProxy.forceActiveFocus()
torProxy.showErrorText = false
} else {
torProxy.showErrorText = true
}
}
}
onClicked: loadedItem.forceActiveFocus()
onClicked: {
loadedItem.filled = true
loadedItem.forceActiveFocus()
}
}
Separator { Layout.fillWidth: true }
}
72 changes: 72 additions & 0 deletions src/qml/controls/IPAddressValueInput.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2024 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

import QtQuick 2.15
import QtQuick.Controls 2.15

TextInput {
id: root
required property string parentState
property string description: ""
property bool filled: false
property int descriptionSize: 18
property color textColor: root.filled ? Theme.color.neutral9 : Theme.color.neutral5
enabled: true
state: root.parentState
validator: RegExpValidator { regExp: /[0-9.:]*/ } // Allow only digits, dots, and colons
selectByMouse: true // Enable text selection with the mouse

maximumLength: 21

states: [
State {
name: "ACTIVE"
PropertyChanges { target: root; textColor: Theme.color.orange }
},
State {
name: "HOVER"
PropertyChanges {
target: root
textColor: root.filled ? Theme.color.orangeLight1 : Theme.color.neutral5
}
},
State {
name: "DISABLED"
PropertyChanges {
target: root
enabled: false
textColor: Theme.color.neutral4
}
}
]

font.family: "Inter"
font.styleName: "Regular"
font.pixelSize: root.descriptionSize
color: root.textColor
text: root.description
horizontalAlignment: Text.AlignRight
wrapMode: Text.WordWrap

Behavior on color {
ColorAnimation { duration: 150 }
}

function isValidIPPort(input)
{
var parts = input.split(":");
if (parts.length !== 2) return false;
if (parts[1].length === 0) return false; // port part is empty
var ipAddress = parts[0];
var ipAddressParts = ipAddress.split(".");
if (ipAddressParts.length !== 4) return false;
for (var i = 0; (i < ipAddressParts.length); i++) {
if (ipAddressParts[i].length === 0) return false; // ip group number part is empty
if (parseInt(ipAddressParts[i]) > 255) return false;
}
var port = parseInt(parts[1]);
if (port < 1 || port > 65535) return false;
return true;
}
}

0 comments on commit a4f4263

Please sign in to comment.