eric7/E5Gui/E5LineEdit.py

branch
eric7
changeset 8312
800c432b34c8
parent 8268
6b8128e0c9d1
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing specialized line edits.
8 """
9
10 import enum
11
12 from PyQt5.QtCore import pyqtSignal, Qt, QEvent
13 from PyQt5.QtWidgets import (
14 QLineEdit, QWidget, QHBoxLayout, QBoxLayout, QLayout, QApplication,
15 QSpacerItem, QSizePolicy
16 )
17
18 import UI.PixmapCache
19
20
21 class E5LineEditSideWidget(QWidget):
22 """
23 Class implementing the side widgets for the line edit class.
24
25 @signal sizeHintChanged() emitted to indicate a change of the size hint
26 """
27 sizeHintChanged = pyqtSignal()
28
29 def __init__(self, parent=None):
30 """
31 Constructor
32
33 @param parent reference to the parent widget (QWidget)
34 """
35 super().__init__(parent)
36
37 def event(self, evt):
38 """
39 Public method to handle events.
40
41 @param evt reference to the event (QEvent)
42 @return flag indicating, whether the event was recognized (boolean)
43 """
44 if evt.type() == QEvent.Type.LayoutRequest:
45 self.sizeHintChanged.emit()
46 return QWidget.event(self, evt)
47
48
49 class E5LineEditSide(enum.Enum):
50 """
51 Class defining the line edit sides.
52 """
53 LEFT = 0
54 RIGHT = 1
55
56
57 class E5LineEdit(QLineEdit):
58 """
59 Class implementing a line edit widget showing some inactive text.
60 """
61 def __init__(self, parent=None, inactiveText=""):
62 """
63 Constructor
64
65 @param parent reference to the parent widget (QWidget)
66 @param inactiveText text to be shown on inactivity (string)
67 """
68 super().__init__(parent)
69
70 self.setMinimumHeight(22)
71
72 self.setPlaceholderText(inactiveText)
73
74 self.__mainLayout = QHBoxLayout(self)
75 self.__mainLayout.setContentsMargins(0, 0, 0, 0)
76 self.__mainLayout.setSpacing(0)
77
78 self.__leftMargin = 0
79 self.__leftWidget = E5LineEditSideWidget(self)
80 self.__leftWidget.resize(0, 0)
81 self.__leftLayout = QHBoxLayout(self.__leftWidget)
82 self.__leftLayout.setContentsMargins(0, 0, 2, 0)
83 if QApplication.isRightToLeft():
84 self.__leftLayout.setDirection(QBoxLayout.Direction.RightToLeft)
85 else:
86 self.__leftLayout.setDirection(QBoxLayout.Direction.LeftToRight)
87 self.__leftLayout.setSizeConstraint(
88 QLayout.SizeConstraint.SetFixedSize)
89
90 self.__rightWidget = E5LineEditSideWidget(self)
91 self.__rightWidget.resize(0, 0)
92 self.__rightLayout = QHBoxLayout(self.__rightWidget)
93 self.__rightLayout.setContentsMargins(0, 0, 2, 0)
94 if self.isRightToLeft():
95 self.__rightLayout.setDirection(QBoxLayout.Direction.RightToLeft)
96 else:
97 self.__rightLayout.setDirection(QBoxLayout.Direction.LeftToRight)
98
99 horizontalSpacer = QSpacerItem(
100 0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
101 self.__mainLayout.addWidget(
102 self.__leftWidget, 0,
103 Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft)
104 self.__mainLayout.addItem(horizontalSpacer)
105 self.__mainLayout.addWidget(
106 self.__rightWidget, 0,
107 Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignRight)
108 if self.isRightToLeft():
109 self.__mainLayout.setDirection(QBoxLayout.Direction.RightToLeft)
110 else:
111 self.__mainLayout.setDirection(QBoxLayout.Direction.LeftToRight)
112
113 self.setWidgetSpacing(3)
114 self.__leftWidget.sizeHintChanged.connect(self._updateTextMargins)
115 self.__rightWidget.sizeHintChanged.connect(self._updateTextMargins)
116
117 def setLeftMargin(self, margin):
118 """
119 Public method to set the left margin.
120
121 @param margin left margin in pixel (integer)
122 """
123 self.__leftMargin = margin
124
125 def leftMargin(self):
126 """
127 Public method to get the size of the left margin.
128
129 @return left margin in pixel (integer)
130 """
131 return self.__leftMargin
132
133 def event(self, evt):
134 """
135 Public method to handle events.
136
137 @param evt reference to the event (QEvent)
138 @return flag indicating, whether the event was recognized (boolean)
139 """
140 if evt.type() == QEvent.Type.LayoutDirectionChange:
141 if self.isRightToLeft():
142 self.__mainLayout.setDirection(
143 QBoxLayout.Direction.RightToLeft)
144 self.__leftLayout.setDirection(
145 QBoxLayout.Direction.RightToLeft)
146 self.__rightLayout.setDirection(
147 QBoxLayout.Direction.RightToLeft)
148 else:
149 self.__mainLayout.setDirection(
150 QBoxLayout.Direction.LeftToRight)
151 self.__leftLayout.setDirection(
152 QBoxLayout.Direction.LeftToRight)
153 self.__rightLayout.setDirection(
154 QBoxLayout.Direction.LeftToRight)
155 return QLineEdit.event(self, evt)
156
157 def _updateTextMargins(self):
158 """
159 Protected slot to update the text margins.
160 """
161 left = (
162 self.__leftWidget.sizeHint().width()
163 if self.__leftMargin == 0 else
164 self.__leftMargin
165 )
166 right = self.__rightWidget.sizeHint().width()
167 top = 0
168 bottom = 0
169 self.setTextMargins(left, top, right, bottom)
170
171 def addWidget(self, widget, position):
172 """
173 Public method to add a widget to a side.
174
175 @param widget reference to the widget to add
176 @type QWidget
177 @param position position to add to
178 @type E5LineEditSide
179 """
180 if widget is None:
181 return
182
183 if self.isRightToLeft():
184 if position == E5LineEditSide.LEFT:
185 position = E5LineEditSide.RIGHT
186 else:
187 position = E5LineEditSide.LEFT
188 if position == E5LineEditSide.LEFT:
189 self.__leftLayout.addWidget(widget)
190 else:
191 self.__rightLayout.insertWidget(1, widget)
192
193 def removeWidget(self, widget):
194 """
195 Public method to remove a widget from a side.
196
197 @param widget reference to the widget to remove
198 @type QWidget
199 """
200 if widget is None:
201 return
202
203 self.__leftLayout.removeWidget(widget)
204 self.__rightLayout.removeWidget(widget)
205 widget.hide()
206
207 def widgetSpacing(self):
208 """
209 Public method to get the side widget spacing.
210
211 @return side widget spacing (integer)
212 """
213 return self.__leftLayout.spacing()
214
215 def setWidgetSpacing(self, spacing):
216 """
217 Public method to set the side widget spacing.
218
219 @param spacing side widget spacing (integer)
220 """
221 self.__leftLayout.setSpacing(spacing)
222 self.__rightLayout.setSpacing(spacing)
223 self._updateTextMargins()
224
225 def textMargin(self, position):
226 """
227 Public method to get the text margin for a side.
228
229 @param position side to get margin for
230 @type E5LineEditSide
231 @return text margin
232 @rtype int
233 """
234 spacing = self.__rightLayout.spacing()
235 w = 0
236 w = (
237 self.__leftWidget.sizeHint().width()
238 if position == E5LineEditSide.LEFT else
239 self.__rightWidget.sizeHint().width()
240 )
241 if w == 0:
242 return 0
243 return w + spacing * 2
244
245 def inactiveText(self):
246 """
247 Public method to get the inactive text.
248
249 @return inactive text (string)
250 """
251 return self.placeholderText()
252
253 def setInactiveText(self, inactiveText):
254 """
255 Public method to set the inactive text.
256
257 @param inactiveText text to be shown on inactivity (string)
258 """
259 self.setPlaceholderText(inactiveText)
260
261
262 class E5ClearableLineEdit(E5LineEdit):
263 """
264 Class implementing a line edit widget showing some inactive text and a
265 clear button, if it has some contents.
266 """
267 def __init__(self, parent=None, inactiveText="",
268 side=E5LineEditSide.RIGHT):
269 """
270 Constructor
271
272 @param parent reference to the parent widget
273 @type QWidget
274 @param inactiveText text to be shown on inactivity
275 @type str
276 @param side side the clear button should be shown at
277 @type E5LineEditSide
278 """
279 super().__init__(parent, inactiveText)
280
281 from E5Gui.E5LineEditButton import E5LineEditButton
282 self.__clearButton = E5LineEditButton(self)
283 self.__clearButton.setIcon(UI.PixmapCache.getIcon("clearLeft"))
284 self.addWidget(self.__clearButton, side)
285 self.__clearButton.setVisible(False)
286
287 self.__clearButton.clicked.connect(self.clear)
288 self.textChanged.connect(self.__textChanged)
289
290 def __textChanged(self, txt):
291 """
292 Private slot to handle changes of the text.
293
294 @param txt text (string)
295 """
296 self.__clearButton.setVisible(txt != "")

eric ide

mercurial