16 |
16 |
17 class EricPassivePopupStyle(enum.Enum): |
17 class EricPassivePopupStyle(enum.Enum): |
18 """ |
18 """ |
19 Class defining the popup styles. |
19 Class defining the popup styles. |
20 """ |
20 """ |
21 BOXED = 0 # box with no shadow |
21 |
22 STYLED = 1 # styled panel with no shadow |
22 BOXED = 0 # box with no shadow |
23 CUSTOM = 128 # reserved for extensions |
23 STYLED = 1 # styled panel with no shadow |
|
24 CUSTOM = 128 # reserved for extensions |
24 |
25 |
25 |
26 |
26 class EricPassivePopup(QFrame): |
27 class EricPassivePopup(QFrame): |
27 """ |
28 """ |
28 Class implementing dialog-like popup that displays messages without |
29 Class implementing dialog-like popup that displays messages without |
29 interrupting the user. |
30 interrupting the user. |
30 |
31 |
31 @signal clicked emitted to indicate a mouse button click |
32 @signal clicked emitted to indicate a mouse button click |
32 """ |
33 """ |
33 DefaultPopupTime = 6 * 1000 # time im milliseconds |
34 |
34 |
35 DefaultPopupTime = 6 * 1000 # time im milliseconds |
35 clicked = pyqtSignal((), (QPoint, )) |
36 |
36 |
37 clicked = pyqtSignal((), (QPoint,)) |
|
38 |
37 def __init__(self, style=EricPassivePopupStyle.BOXED, parent=None): |
39 def __init__(self, style=EricPassivePopupStyle.BOXED, parent=None): |
38 """ |
40 """ |
39 Constructor |
41 Constructor |
40 |
42 |
41 @param style style of the popup |
43 @param style style of the popup |
42 @type EricPassivePopupStyle |
44 @type EricPassivePopupStyle |
43 @param parent reference to the parent widget |
45 @param parent reference to the parent widget |
44 @type QWidget |
46 @type QWidget |
45 """ |
47 """ |
46 super().__init__(None) |
48 super().__init__(None) |
47 |
49 |
48 self.__msgView = None |
50 self.__msgView = None |
49 self.__topLayout = None |
51 self.__topLayout = None |
50 self.__hideDelay = EricPassivePopup.DefaultPopupTime |
52 self.__hideDelay = EricPassivePopup.DefaultPopupTime |
51 self.__hideTimer = QTimer(self) |
53 self.__hideTimer = QTimer(self) |
52 self.__autoDelete = False |
54 self.__autoDelete = False |
53 self.__fixedPosition = QPoint() |
55 self.__fixedPosition = QPoint() |
54 |
56 |
55 self.setWindowFlags( |
57 self.setWindowFlags( |
56 Qt.WindowType.Tool | |
58 Qt.WindowType.Tool |
57 Qt.WindowType.X11BypassWindowManagerHint | |
59 | Qt.WindowType.X11BypassWindowManagerHint |
58 Qt.WindowType.WindowStaysOnTopHint | |
60 | Qt.WindowType.WindowStaysOnTopHint |
59 Qt.WindowType.FramelessWindowHint |
61 | Qt.WindowType.FramelessWindowHint |
60 ) |
62 ) |
61 if style == EricPassivePopupStyle.STYLED: |
63 if style == EricPassivePopupStyle.STYLED: |
62 self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain) |
64 self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain) |
63 else: |
65 else: |
64 # default style is Boxed - Plain |
66 # default style is Boxed - Plain |
65 self.setFrameStyle(QFrame.Shape.Box | QFrame.Shadow.Plain) |
67 self.setFrameStyle(QFrame.Shape.Box | QFrame.Shadow.Plain) |
66 self.setLineWidth(2) |
68 self.setLineWidth(2) |
67 self.__hideTimer.timeout.connect(self.hide) |
69 self.__hideTimer.timeout.connect(self.hide) |
68 self.clicked.connect(self.hide) |
70 self.clicked.connect(self.hide) |
69 |
71 |
70 self.__customData = {} # dictionary to store some custom data |
72 self.__customData = {} # dictionary to store some custom data |
71 |
73 |
72 def setView(self, child): |
74 def setView(self, child): |
73 """ |
75 """ |
74 Public method to set the message view. |
76 Public method to set the message view. |
75 |
77 |
76 @param child reference to the widget to set as the message view |
78 @param child reference to the widget to set as the message view |
77 (QWidget) |
79 (QWidget) |
78 """ |
80 """ |
79 self.__msgView = child |
81 self.__msgView = child |
80 self.__topLayout = QVBoxLayout(self) |
82 self.__topLayout = QVBoxLayout(self) |
81 self.__topLayout.addWidget(self.__msgView) |
83 self.__topLayout.addWidget(self.__msgView) |
82 self.__topLayout.activate() |
84 self.__topLayout.activate() |
83 |
85 |
84 def view(self): |
86 def view(self): |
85 """ |
87 """ |
86 Public method to get a reference to the message view. |
88 Public method to get a reference to the message view. |
87 |
89 |
88 @return reference to the message view (QWidget) |
90 @return reference to the message view (QWidget) |
89 """ |
91 """ |
90 return self.__msgView |
92 return self.__msgView |
91 |
93 |
92 def setVisible(self, visible): |
94 def setVisible(self, visible): |
93 """ |
95 """ |
94 Public method to show or hide the popup. |
96 Public method to show or hide the popup. |
95 |
97 |
96 @param visible flag indicating the visibility status (boolean) |
98 @param visible flag indicating the visibility status (boolean) |
97 """ |
99 """ |
98 if not visible: |
100 if not visible: |
99 super().setVisible(visible) |
101 super().setVisible(visible) |
100 return |
102 return |
101 |
103 |
102 if self.size() != self.sizeHint(): |
104 if self.size() != self.sizeHint(): |
103 self.resize(self.sizeHint()) |
105 self.resize(self.sizeHint()) |
104 |
106 |
105 if self.__fixedPosition.isNull(): |
107 if self.__fixedPosition.isNull(): |
106 self.__positionSelf() |
108 self.__positionSelf() |
107 else: |
109 else: |
108 self.move(self.__fixedPosition) |
110 self.move(self.__fixedPosition) |
109 super().setVisible(True) |
111 super().setVisible(True) |
110 |
112 |
111 delay = self.__hideDelay |
113 delay = self.__hideDelay |
112 if delay < 0: |
114 if delay < 0: |
113 delay = EricPassivePopup.DefaultPopupTime |
115 delay = EricPassivePopup.DefaultPopupTime |
114 if delay > 0: |
116 if delay > 0: |
115 self.__hideTimer.start(delay) |
117 self.__hideTimer.start(delay) |
116 |
118 |
117 def show(self, p=None): |
119 def show(self, p=None): |
118 """ |
120 """ |
119 Public slot to show the popup. |
121 Public slot to show the popup. |
120 |
122 |
121 @param p position for the popup (QPoint) |
123 @param p position for the popup (QPoint) |
122 """ |
124 """ |
123 if p is not None: |
125 if p is not None: |
124 self.__fixedPosition = p |
126 self.__fixedPosition = p |
125 super().show() |
127 super().show() |
126 |
128 |
127 def setTimeout(self, delay): |
129 def setTimeout(self, delay): |
128 """ |
130 """ |
129 Public method to set the delay for the popup is removed automatically. |
131 Public method to set the delay for the popup is removed automatically. |
130 |
132 |
131 Setting the delay to 0 disables the timeout. If you're doing this, you |
133 Setting the delay to 0 disables the timeout. If you're doing this, you |
132 may want to connect the clicked() signal to the hide() slot. Setting |
134 may want to connect the clicked() signal to the hide() slot. Setting |
133 the delay to -1 makes it use the default value. |
135 the delay to -1 makes it use the default value. |
134 |
136 |
135 @param delay value for the delay in milliseconds (integer) |
137 @param delay value for the delay in milliseconds (integer) |
136 """ |
138 """ |
137 self.__hideDelay = delay |
139 self.__hideDelay = delay |
138 if self.__hideTimer.isActive(): |
140 if self.__hideTimer.isActive(): |
139 if delay: |
141 if delay: |
140 if delay == -1: |
142 if delay == -1: |
141 delay = EricPassivePopup.DefaultPopupTime |
143 delay = EricPassivePopup.DefaultPopupTime |
142 self.__hideTimer.start(delay) |
144 self.__hideTimer.start(delay) |
143 else: |
145 else: |
144 self.__hideTimer.stop() |
146 self.__hideTimer.stop() |
145 |
147 |
146 def timeout(self): |
148 def timeout(self): |
147 """ |
149 """ |
148 Public method to get the delay before the popup is removed |
150 Public method to get the delay before the popup is removed |
149 automatically. |
151 automatically. |
150 |
152 |
151 @return the delay before the popup is removed automatically (integer) |
153 @return the delay before the popup is removed automatically (integer) |
152 """ |
154 """ |
153 return self.__hideDelay |
155 return self.__hideDelay |
154 |
156 |
155 def mouseReleaseEvent(self, evt): |
157 def mouseReleaseEvent(self, evt): |
156 """ |
158 """ |
157 Protected method to handle a mouse release event. |
159 Protected method to handle a mouse release event. |
158 |
160 |
159 @param evt reference to the mouse event (QMouseEvent) |
161 @param evt reference to the mouse event (QMouseEvent) |
160 """ |
162 """ |
161 self.clicked.emit() |
163 self.clicked.emit() |
162 self.clicked.emit(evt.position().toPoint()) |
164 self.clicked.emit(evt.position().toPoint()) |
163 |
165 |
164 def hideEvent(self, evt): |
166 def hideEvent(self, evt): |
165 """ |
167 """ |
166 Protected method to handle the hide event. |
168 Protected method to handle the hide event. |
167 |
169 |
168 @param evt reference to the hide event (QHideEvent) |
170 @param evt reference to the hide event (QHideEvent) |
169 """ |
171 """ |
170 self.__hideTimer.stop() |
172 self.__hideTimer.stop() |
171 |
173 |
172 def __defaultArea(self): |
174 def __defaultArea(self): |
173 """ |
175 """ |
174 Private method to determine the default rectangle to be passed to |
176 Private method to determine the default rectangle to be passed to |
175 moveNear(). |
177 moveNear(). |
176 |
178 |
177 @return default rectangle (QRect) |
179 @return default rectangle (QRect) |
178 """ |
180 """ |
179 return QRect(100, 100, 200, 200) |
181 return QRect(100, 100, 200, 200) |
180 |
182 |
181 def __positionSelf(self): |
183 def __positionSelf(self): |
182 """ |
184 """ |
183 Private method to position the popup. |
185 Private method to position the popup. |
184 """ |
186 """ |
185 self.__moveNear(self.__defaultArea()) |
187 self.__moveNear(self.__defaultArea()) |
186 |
188 |
187 def __moveNear(self, target): |
189 def __moveNear(self, target): |
188 """ |
190 """ |
189 Private method to move the popup to be adjacent to the specified |
191 Private method to move the popup to be adjacent to the specified |
190 rectangle. |
192 rectangle. |
191 |
193 |
192 @param target rectangle to be placed at (QRect) |
194 @param target rectangle to be placed at (QRect) |
193 """ |
195 """ |
194 pos = self.__calculateNearbyPoint(target) |
196 pos = self.__calculateNearbyPoint(target) |
195 self.move(pos.x(), pos.y()) |
197 self.move(pos.x(), pos.y()) |
196 |
198 |
197 def __calculateNearbyPoint(self, target): |
199 def __calculateNearbyPoint(self, target): |
198 """ |
200 """ |
199 Private method to calculate the position to place the popup near the |
201 Private method to calculate the position to place the popup near the |
200 specified rectangle. |
202 specified rectangle. |
201 |
203 |
202 @param target rectangle to be placed at (QRect) |
204 @param target rectangle to be placed at (QRect) |
203 @return position to place the popup (QPoint) |
205 @return position to place the popup (QPoint) |
204 """ |
206 """ |
205 pos = target.topLeft() |
207 pos = target.topLeft() |
206 x = pos.x() |
208 x = pos.x() |
207 y = pos.y() |
209 y = pos.y() |
208 w = self.minimumSizeHint().width() |
210 w = self.minimumSizeHint().width() |
209 h = self.minimumSizeHint().height() |
211 h = self.minimumSizeHint().height() |
210 |
212 |
211 r = QApplication.screenAt(QPoint(x + w // 2, y + h // 2)).geometry() |
213 r = QApplication.screenAt(QPoint(x + w // 2, y + h // 2)).geometry() |
212 |
214 |
213 if x < r.center().x(): |
215 if x < r.center().x(): |
214 x += target.width() |
216 x += target.width() |
215 else: |
217 else: |
216 x -= w |
218 x -= w |
217 |
219 |
218 # It's apparently trying to go off screen, so display it ALL at the |
220 # It's apparently trying to go off screen, so display it ALL at the |
219 # bottom. |
221 # bottom. |
220 if (y + h) > r.bottom(): |
222 if (y + h) > r.bottom(): |
221 y = r.bottom() - h |
223 y = r.bottom() - h |
222 |
224 |
223 if (x + w) > r.right(): |
225 if (x + w) > r.right(): |
224 x = r.right() - w |
226 x = r.right() - w |
225 |
227 |
226 if y < r.top(): |
228 if y < r.top(): |
227 y = r.top() |
229 y = r.top() |
228 |
230 |
229 if x < r.left(): |
231 if x < r.left(): |
230 x = r.left() |
232 x = r.left() |
231 |
233 |
232 return QPoint(x, y) |
234 return QPoint(x, y) |
233 |
235 |
234 def setCustomData(self, key, data): |
236 def setCustomData(self, key, data): |
235 """ |
237 """ |
236 Public method to set some custom data. |
238 Public method to set some custom data. |
237 |
239 |
238 @param key key for the custom data |
240 @param key key for the custom data |
239 @type str |
241 @type str |
240 @param data data to be stored |
242 @param data data to be stored |
241 @type any |
243 @type any |
242 """ |
244 """ |
243 self.__customData[key] = data |
245 self.__customData[key] = data |
244 |
246 |
245 def getCustomData(self, key): |
247 def getCustomData(self, key): |
246 """ |
248 """ |
247 Public method to get some custom data. |
249 Public method to get some custom data. |
248 |
250 |
249 @param key key for the custom data |
251 @param key key for the custom data |
250 @type str |
252 @type str |
251 @return stored data |
253 @return stored data |
252 @rtype any |
254 @rtype any |
253 """ |
255 """ |