Sat, 23 Dec 2023 15:48:12 +0100
Updated copyright for 2024.
9797 | 1 | # -*- coding: utf-8 -*- |
2 | ||
10439
21c28b0f9e41
Updated copyright for 2024.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10024
diff
changeset
|
3 | # Copyright (c) 2023 - 2024 Detlev Offenbach <detlev@die-offenbachs.de> |
9797 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing a widget to enter an IPv4 address. | |
8 | """ | |
9 | ||
10 | import ipaddress | |
11 | ||
9830
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
12 | from PyQt6.QtCore import QEvent, QRegularExpression, Qt, pyqtSignal, pyqtSlot |
9797 | 13 | from PyQt6.QtGui import QRegularExpressionValidator |
14 | from PyQt6.QtWidgets import QWidget | |
15 | ||
16 | from eric7.EricGui import EricPixmapCache | |
17 | ||
18 | from .Ui_EricIPv4InputWidget import Ui_EricIPv4InputWidget | |
19 | ||
20 | ||
21 | class EricIPv4InputWidget(QWidget, Ui_EricIPv4InputWidget): | |
22 | """ | |
23 | Class implementing a widget to enter an IPv4 address. | |
24 | ||
25 | @signal addressChanged() emitted to indicate a change of the entered IPv4 address | |
26 | """ | |
9830
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
27 | |
9797 | 28 | addressChanged = pyqtSignal() |
29 | ||
30 | def __init__(self, parent=None): | |
31 | """ | |
32 | Constructor | |
33 | ||
34 | @param parent reference to the parent widget (defaults to None) | |
35 | @type QWidget (optional) | |
36 | """ | |
37 | super().__init__(parent) | |
38 | self.setupUi(self) | |
39 | ||
40 | self.clearButton.setIcon(EricPixmapCache.getIcon("clearLeft")) | |
41 | self.clearButton.clicked.connect(self.__clear) | |
42 | ||
43 | ipRange = r"(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" | |
44 | ||
45 | self.ip1Edit.setValidator( | |
46 | QRegularExpressionValidator(QRegularExpression(ipRange)) | |
47 | ) | |
48 | self.ip2Edit.setValidator( | |
49 | QRegularExpressionValidator(QRegularExpression(ipRange)) | |
50 | ) | |
51 | self.ip3Edit.setValidator( | |
52 | QRegularExpressionValidator(QRegularExpression(ipRange)) | |
53 | ) | |
54 | self.ip4Edit.setValidator( | |
55 | QRegularExpressionValidator(QRegularExpression(ipRange)) | |
56 | ) | |
57 | ||
58 | self.ip1Edit.installEventFilter(self) | |
59 | self.ip2Edit.installEventFilter(self) | |
60 | self.ip3Edit.installEventFilter(self) | |
61 | ||
62 | self.ip1Edit.textChanged.connect(self.addressChanged) | |
63 | self.ip2Edit.textChanged.connect(self.addressChanged) | |
64 | self.ip3Edit.textChanged.connect(self.addressChanged) | |
65 | self.ip4Edit.textChanged.connect(self.addressChanged) | |
66 | ||
67 | def eventFilter(self, obj, evt): | |
68 | """ | |
69 | Public method to filter pressing '.' to give focus to the next input field. | |
70 | ||
71 | @param obj reference to the object | |
72 | @type QObject | |
73 | @param evt reference to the event object | |
74 | @type QEvent | |
9830
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
75 | @return flag indicating, that the event was handled |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
76 | @rtype bool |
9797 | 77 | """ |
9830
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
78 | if evt.type() == QEvent.Type.KeyPress and evt.text() == ".": |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
79 | if obj is self.ip1Edit: |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
80 | nextWidget = self.ip2Edit |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
81 | elif obj is self.ip2Edit: |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
82 | nextWidget = self.ip3Edit |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
83 | elif obj is self.ip3Edit: |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
84 | nextWidget = self.ip4Edit |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
85 | else: |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
86 | nextWidget = None |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
87 | if nextWidget: |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
88 | nextWidget.setFocus(Qt.FocusReason.TabFocusReason) |
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
89 | return True |
9797 | 90 | |
91 | return super().eventFilter(obj, evt) | |
92 | ||
93 | def hasAcceptableInput(self): | |
94 | """ | |
95 | Public method to check, if the input is acceptable. | |
96 | ||
97 | @return flag indicating acceptable input | |
98 | @rtype bool | |
99 | """ | |
100 | try: | |
101 | ipaddress.IPv4Address(self.text()) | |
102 | except ipaddress.AddressValueError: | |
103 | # leading zeros are not allowed | |
104 | return False | |
105 | ||
106 | return ( | |
107 | self.ip1Edit.hasAcceptableInput() | |
108 | and self.ip2Edit.hasAcceptableInput() | |
109 | and self.ip3Edit.hasAcceptableInput() | |
110 | and self.ip4Edit.hasAcceptableInput() | |
111 | ) | |
112 | ||
113 | def text(self): | |
114 | """ | |
115 | Public method to get the IPv4 address as a string. | |
116 | ||
117 | @return IPv4 address | |
118 | @rtype str | |
119 | """ | |
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
120 | ip1 = self.ip1Edit.text() |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
121 | ip2 = self.ip2Edit.text() |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
122 | ip3 = self.ip3Edit.text() |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
123 | ip4 = self.ip4Edit.text() |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
124 | |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
125 | if not all(bool(ip) for ip in (ip1, ip2, ip3, ip4)): |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
126 | return "" |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
127 | |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
128 | return "{0}.{1}.{2}.{3}".format(ip1, ip2, ip3, ip4) |
9797 | 129 | |
130 | def setText(self, address): | |
131 | """ | |
132 | Public method to set the IPv4 address given a string. | |
133 | ||
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
134 | Note: If an invalid address is given, the input is cleared. |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
135 | |
9797 | 136 | @param address IPv4 address |
137 | @type str | |
138 | """ | |
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
139 | if address and address != "...": # '...' is empty as well |
9797 | 140 | try: |
141 | ipaddress.IPv4Address(address) | |
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
142 | except ipaddress.AddressValueError: |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
143 | self.clear() |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
144 | return |
9797 | 145 | |
146 | addressParts = address.split(".") | |
147 | self.ip1Edit.setText(addressParts[0]) | |
148 | self.ip2Edit.setText(addressParts[1]) | |
149 | self.ip3Edit.setText(addressParts[2]) | |
150 | self.ip4Edit.setText(addressParts[3]) | |
151 | else: | |
152 | self.clear() | |
153 | ||
154 | def address(self): | |
155 | """ | |
156 | Public method to get the IPv4 address as an ipaddress.IPv4Address object. | |
157 | ||
158 | @return IPv4 address | |
159 | @rtype ipaddress.IPv4Address | |
9830
6c91fdb0e55b
Fixed some code style and formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9797
diff
changeset
|
160 | @exception ValueError raised to indicate an invalid IPv4 address |
9797 | 161 | """ |
162 | try: | |
163 | return ipaddress.IPv4Address(self.text()) | |
164 | except ipaddress.AddressValueError as err: | |
165 | raise ValueError(str(err)) | |
166 | ||
167 | def setAddress(self, address): | |
168 | """ | |
169 | Public method to set the IPv4 address given an ipaddress.IPv4Address object. | |
170 | ||
171 | @param address IPv4 address | |
172 | @type ipaddress.IPv4Address | |
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
173 | @exception ValueError raised to indicate an invalid IPv4 address |
9797 | 174 | """ |
10024
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
175 | if address and address != "...": # '...' is empty as well |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
176 | try: |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
177 | ipaddress.IPv4Address(address) |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
178 | except ipaddress.AddressValueError as err: |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
179 | raise ValueError(str(err)) |
3bbf6dbec0bd
Fixed an issue related to the IPv4 address widget.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9830
diff
changeset
|
180 | |
9797 | 181 | self.setText(str(address)) |
182 | else: | |
183 | self.clear() | |
184 | ||
185 | @pyqtSlot() | |
186 | def clear(self): | |
187 | """ | |
188 | Public slot to clear the input fields. | |
189 | """ | |
190 | self.ip1Edit.clear() | |
191 | self.ip2Edit.clear() | |
192 | self.ip3Edit.clear() | |
193 | self.ip4Edit.clear() | |
194 | ||
195 | @pyqtSlot() | |
196 | def __clear(self): | |
197 | """ | |
198 | Private slot to handle the clear button press. | |
199 | """ | |
200 | self.clear() | |
201 | self.ip1Edit.setFocus(Qt.FocusReason.OtherFocusReason) |