5 |
5 |
6 """ |
6 """ |
7 Module implementing specialized line edits. |
7 Module implementing specialized line edits. |
8 """ |
8 """ |
9 |
9 |
10 from PyQt4.QtCore import Qt |
10 from PyQt4.QtCore import pyqtSignal, Qt, QEvent |
11 from PyQt4.QtGui import QLineEdit, QStyleOptionFrameV2, QStyle, QPainter, QPalette |
11 from PyQt4.QtGui import QLineEdit, QStyleOptionFrameV2, QStyle, QPainter, QPalette, \ |
|
12 QWidget, QHBoxLayout, QBoxLayout, QLayout, QApplication, QSpacerItem, QSizePolicy |
|
13 |
|
14 class SideWidget(QWidget): |
|
15 """ |
|
16 Class implementing the side widgets for the line edit class. |
|
17 """ |
|
18 sizeHintChanged = pyqtSignal() |
|
19 |
|
20 def __init__(self, parent = None): |
|
21 """ |
|
22 Constructor |
|
23 |
|
24 @param parent reference to the parent widget (QWidget) |
|
25 """ |
|
26 QWidget.__init__(self, parent) |
|
27 |
|
28 def event(self, evt): |
|
29 """ |
|
30 Protected method to handle events. |
|
31 |
|
32 @param reference to the event (QEvent) |
|
33 @return flag indicating, whether the event was recognized (boolean) |
|
34 """ |
|
35 if evt.type() == QEvent.LayoutRequest: |
|
36 self.sizeHintChanged.emit() |
|
37 return QWidget.event(self, evt) |
12 |
38 |
13 class E5LineEdit(QLineEdit): |
39 class E5LineEdit(QLineEdit): |
14 """ |
40 """ |
15 Class implementing a line edit widget showing some inactive text. |
41 Class implementing a line edit widget showing some inactive text. |
16 """ |
42 """ |
|
43 LeftSide = 0 |
|
44 RightSide = 1 |
|
45 |
17 def __init__(self, parent = None, inactiveText = ""): |
46 def __init__(self, parent = None, inactiveText = ""): |
18 """ |
47 """ |
19 Constructor |
48 Constructor |
20 |
49 |
21 @param parent reference to the parent widget (QWidget) |
50 @param parent reference to the parent widget (QWidget) |
22 @param inactiveText text to be shown on inactivity (string) |
51 @param inactiveText text to be shown on inactivity (string) |
23 """ |
52 """ |
24 QLineEdit.__init__(self, parent) |
53 QLineEdit.__init__(self, parent) |
25 |
54 |
|
55 self.setMinimumHeight(22) |
|
56 |
26 self.__inactiveText = inactiveText |
57 self.__inactiveText = inactiveText |
27 |
58 |
28 def inactiveText(self): |
59 self.__leftWidget = SideWidget(self) |
29 """ |
60 self.__leftWidget.resize(0, 0) |
30 Public method to get the inactive text. |
61 self.__leftLayout = QHBoxLayout(self.__leftWidget) |
31 |
62 self.__leftLayout.setContentsMargins(0, 0, 0, 0) |
32 return inactive text (string) |
63 if QApplication.isRightToLeft(): |
33 """ |
64 self.__leftLayout.setDirection(QBoxLayout.RightToLeft) |
34 return self.__inactiveText |
65 else: |
35 |
66 self.__leftLayout.setDirection(QBoxLayout.LeftToRight) |
36 def setInactiveText(self, inactiveText): |
67 self.__leftLayout.setSizeConstraint(QLayout.SetFixedSize) |
37 """ |
68 |
38 Public method to set the inactive text. |
69 self.__rightWidget = SideWidget(self) |
39 |
70 self.__rightWidget.resize(0, 0) |
40 @param inactiveText text to be shown on inactivity (string) |
71 self.__rightLayout = QHBoxLayout(self.__rightWidget) |
41 """ |
72 self.__rightLayout.setContentsMargins(0, 0, 0, 0) |
42 self.__inactiveText = inactiveText |
73 if self.isRightToLeft(): |
43 self.update() |
74 self.__rightLayout.setDirection(QBoxLayout.RightToLeft) |
|
75 else: |
|
76 self.__rightLayout.setDirection(QBoxLayout.LeftToRight) |
|
77 horizontalSpacer = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) |
|
78 self.__rightLayout.addItem(horizontalSpacer) |
|
79 |
|
80 self.setWidgetSpacing(3) |
|
81 self.__leftWidget.sizeHintChanged.connect(self._updateTextMargins) |
|
82 self.__rightWidget.sizeHintChanged.connect(self._updateTextMargins) |
|
83 |
|
84 def event(self, evt): |
|
85 """ |
|
86 Protected method to handle events. |
|
87 |
|
88 @param reference to the event (QEvent) |
|
89 @return flag indicating, whether the event was recognized (boolean) |
|
90 """ |
|
91 if evt.type() == QEvent.LayoutDirectionChange: |
|
92 if self.isRightToLeft(): |
|
93 self.__leftLayout.setDirection(QBoxLayout.RightToLeft) |
|
94 self.__rightLayout.setDirection(QBoxLayout.RightToLeft) |
|
95 else: |
|
96 self.__leftLayout.setDirection(QBoxLayout.LeftToRight) |
|
97 self.__rightLayout.setDirection(QBoxLayout.LeftToRight) |
|
98 return QLineEdit.event(self, evt) |
|
99 |
|
100 def resizeEvent(self, evt): |
|
101 """ |
|
102 Protected method to handle resize events. |
|
103 |
|
104 @param evt reference to the resize event (QResizeEvent) |
|
105 """ |
|
106 self.__updateSideWidgetLocations() |
|
107 QLineEdit.resizeEvent(self, evt) |
44 |
108 |
45 def paintEvent(self, evt): |
109 def paintEvent(self, evt): |
46 """ |
110 """ |
47 Protected method handling a paint event. |
111 Protected method handling a paint event. |
48 |
112 |
55 panel = QStyleOptionFrameV2() |
119 panel = QStyleOptionFrameV2() |
56 self.initStyleOption(panel) |
120 self.initStyleOption(panel) |
57 textRect = \ |
121 textRect = \ |
58 self.style().subElementRect(QStyle.SE_LineEditContents, panel, self) |
122 self.style().subElementRect(QStyle.SE_LineEditContents, panel, self) |
59 textRect.adjust(2, 0, 0, 0) |
123 textRect.adjust(2, 0, 0, 0) |
|
124 left = self.textMargin(self.LeftSide) |
|
125 right = self.textMargin(self.RightSide) |
|
126 textRect.adjust(left, 0, -right, 0) |
60 painter = QPainter(self) |
127 painter = QPainter(self) |
61 painter.setPen(self.palette().brush(QPalette.Disabled, QPalette.Text).color()) |
128 painter.setPen(self.palette().brush(QPalette.Disabled, QPalette.Text).color()) |
62 painter.drawText(textRect, Qt.AlignLeft | Qt.AlignVCenter, self.__inactiveText) |
129 painter.drawText( |
|
130 textRect, Qt.AlignLeft | Qt.AlignVCenter, self.__inactiveText) |
|
131 |
|
132 def __updateSideWidgetLocations(self): |
|
133 """ |
|
134 Private method to update the side widget locations. |
|
135 """ |
|
136 opt = QStyleOptionFrameV2() |
|
137 self.initStyleOption(opt) |
|
138 textRect = \ |
|
139 self.style().subElementRect(QStyle.SE_LineEditContents, opt, self) |
|
140 textRect.adjust(2, 0, 0, 0) |
|
141 |
|
142 left = self.textMargin(self.LeftSide) |
|
143 |
|
144 midHeight = textRect.center().y() + 1 |
|
145 |
|
146 if self.__leftLayout.count() > 0: |
|
147 leftHeight = midHeight - self.__leftWidget.height() // 2 |
|
148 leftWidth = self.__leftWidget.width() |
|
149 if leftWidth == 0: |
|
150 leftHeight = midHeight - self.__leftWidget.sizeHint().height() // 2 |
|
151 self.__leftWidget.move(textRect.x(), leftHeight) |
|
152 |
|
153 textRect.setX(left) |
|
154 textRect.setY(midHeight - self.__rightWidget.sizeHint().height() // 2) |
|
155 textRect.setHeight(self.__rightWidget.sizeHint().height()) |
|
156 self.__rightWidget.setGeometry(textRect) |
|
157 |
|
158 def _updateTextMargins(self): |
|
159 """ |
|
160 Protected slot to update the text margins. |
|
161 """ |
|
162 left = self.textMargin(self.LeftSide) |
|
163 right = self.textMargin(self.RightSide) |
|
164 self.setTextMargins(left, 0, right, 0) |
|
165 self.__updateSideWidgetLocations() |
|
166 |
|
167 def addWidget(self, widget, position): |
|
168 """ |
|
169 Public method to add a widget to a side. |
|
170 |
|
171 @param widget reference to the widget to add (QWidget) |
|
172 @param position position to add to (E5LineEdit.LeftSide, E5LineEdit.RightSide) |
|
173 """ |
|
174 if widget is None: |
|
175 return |
|
176 |
|
177 if self.isRightToLeft(): |
|
178 if position == self.LeftSide: |
|
179 position = self.RightSide |
|
180 else: |
|
181 position = self.LeftSide |
|
182 if position == self.LeftSide: |
|
183 self.__leftLayout.addWidget(widget) |
|
184 else: |
|
185 self.__rightLayout.insertWidget(1, widget) |
|
186 |
|
187 def removeWidget(self, widget): |
|
188 """ |
|
189 Public method to remove a widget from a side. |
|
190 |
|
191 @param widget reference to the widget to remove (QWidget) |
|
192 """ |
|
193 if widget is None: |
|
194 return |
|
195 |
|
196 self.__leftLayout.removeWidget(widget) |
|
197 self.__rightLayout.removeWidget(widget) |
|
198 widget.hide() |
|
199 |
|
200 def widgetSpacing(self): |
|
201 """ |
|
202 Public method to get the side widget spacing. |
|
203 |
|
204 @return side widget spacing (integer) |
|
205 """ |
|
206 return self.__leftLayout.spacing() |
|
207 |
|
208 def setWidgetSpacing(self, spacing): |
|
209 """ |
|
210 Public method to set the side widget spacing. |
|
211 |
|
212 @param spacing side widget spacing (integer) |
|
213 """ |
|
214 self.__leftLayout.setSpacing(spacing) |
|
215 self.__rightLayout.setSpacing(spacing) |
|
216 self._updateTextMargins() |
|
217 |
|
218 def textMargin(self, position): |
|
219 """ |
|
220 Public method to get the text margin for a side. |
|
221 |
|
222 @param position side to get margin for (E5LineEdit.LeftSide, E5LineEdit.RightSide) |
|
223 """ |
|
224 spacing = self.__rightLayout.spacing() |
|
225 w = 0 |
|
226 if position == self.LeftSide: |
|
227 w = self.__leftWidget.sizeHint().width() |
|
228 else: |
|
229 w = self.__rightWidget.sizeHint().width() |
|
230 if w == 0: |
|
231 return 0 |
|
232 return w + spacing * 2 |
|
233 |
|
234 def inactiveText(self): |
|
235 """ |
|
236 Public method to get the inactive text. |
|
237 |
|
238 return inactive text (string) |
|
239 """ |
|
240 return self.__inactiveText |
|
241 |
|
242 def setInactiveText(self, inactiveText): |
|
243 """ |
|
244 Public method to set the inactive text. |
|
245 |
|
246 @param inactiveText text to be shown on inactivity (string) |
|
247 """ |
|
248 self.__inactiveText = inactiveText |
|
249 self.update() |