eric6/E5Gui/E5LineEdit.py

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

eric ide

mercurial