61 width = 0 |
62 width = 0 |
62 if self.__rightSide: |
63 if self.__rightSide: |
63 self._master.setViewportMargins(0, 0, width, 0) |
64 self._master.setViewportMargins(0, 0, width, 0) |
64 else: |
65 else: |
65 self._master.setViewportMargins(width, 0, 0, 0) |
66 self._master.setViewportMargins(width, 0, 0, 0) |
66 |
67 |
67 def setMaster(self, master): |
68 def setMaster(self, master): |
68 """ |
69 """ |
69 Public method to set the map master widget. |
70 Public method to set the map master widget. |
70 |
71 |
71 @param master map master widget (QAbstractScrollArea) |
72 @param master map master widget (QAbstractScrollArea) |
72 """ |
73 """ |
73 self._master = master |
74 self._master = master |
74 self._master.setVerticalScrollBarPolicy( |
75 self._master.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) |
75 Qt.ScrollBarPolicy.ScrollBarAlwaysOn) |
|
76 self._master.verticalScrollBar().valueChanged.connect(self.update) |
76 self._master.verticalScrollBar().valueChanged.connect(self.update) |
77 self._master.verticalScrollBar().rangeChanged.connect(self.update) |
77 self._master.verticalScrollBar().rangeChanged.connect(self.update) |
78 self.__updateMasterViewportWidth() |
78 self.__updateMasterViewportWidth() |
79 |
79 |
80 def setWidth(self, width): |
80 def setWidth(self, width): |
81 """ |
81 """ |
82 Public method to set the widget width. |
82 Public method to set the widget width. |
83 |
83 |
84 @param width widget width (integer) |
84 @param width widget width (integer) |
85 """ |
85 """ |
86 if width != self.__width: |
86 if width != self.__width: |
87 self.__width = max(6, width) # minimum width 6 pixels |
87 self.__width = max(6, width) # minimum width 6 pixels |
88 self.__updateMasterViewportWidth() |
88 self.__updateMasterViewportWidth() |
89 self.update() |
89 self.update() |
90 |
90 |
91 def width(self): |
91 def width(self): |
92 """ |
92 """ |
93 Public method to get the widget's width. |
93 Public method to get the widget's width. |
94 |
94 |
95 @return widget width (integer) |
95 @return widget width (integer) |
96 """ |
96 """ |
97 return self.__width |
97 return self.__width |
98 |
98 |
99 def setMapPosition(self, onRight): |
99 def setMapPosition(self, onRight): |
100 """ |
100 """ |
101 Public method to set, whether the map should be shown to the right or |
101 Public method to set, whether the map should be shown to the right or |
102 left of the master widget. |
102 left of the master widget. |
103 |
103 |
104 @param onRight flag indicating to show the map on the right side of |
104 @param onRight flag indicating to show the map on the right side of |
105 the master widget |
105 the master widget |
106 @type bool |
106 @type bool |
107 """ |
107 """ |
108 if onRight != self.__rightSide: |
108 if onRight != self.__rightSide: |
109 self.__rightSide = onRight |
109 self.__rightSide = onRight |
110 self.__updateMasterViewportWidth() |
110 self.__updateMasterViewportWidth() |
111 self.update() |
111 self.update() |
112 |
112 |
113 def isOnRightSide(self): |
113 def isOnRightSide(self): |
114 """ |
114 """ |
115 Public method to test, if the map is shown on the right side of the |
115 Public method to test, if the map is shown on the right side of the |
116 master widget. |
116 master widget. |
117 |
117 |
118 @return flag indicating that the map is to the right of the master |
118 @return flag indicating that the map is to the right of the master |
119 widget |
119 widget |
120 @rtype bool |
120 @rtype bool |
121 """ |
121 """ |
122 return self.__rightSide |
122 return self.__rightSide |
123 |
123 |
124 def setLineDimensions(self, border, height): |
124 def setLineDimensions(self, border, height): |
125 """ |
125 """ |
126 Public method to set the line (indicator) dimensions. |
126 Public method to set the line (indicator) dimensions. |
127 |
127 |
128 @param border border width on each side in x-direction (integer) |
128 @param border border width on each side in x-direction (integer) |
129 @param height height of the line in pixels (integer) |
129 @param height height of the line in pixels (integer) |
130 """ |
130 """ |
131 if border != self.__lineBorder or height != self.__lineHeight: |
131 if border != self.__lineBorder or height != self.__lineHeight: |
132 self.__lineBorder = max(1, border) # min border 1 pixel |
132 self.__lineBorder = max(1, border) # min border 1 pixel |
133 self.__lineHeight = max(1, height) # min height 1 pixel |
133 self.__lineHeight = max(1, height) # min height 1 pixel |
134 self.update() |
134 self.update() |
135 |
135 |
136 def lineDimensions(self): |
136 def lineDimensions(self): |
137 """ |
137 """ |
138 Public method to get the line (indicator) dimensions. |
138 Public method to get the line (indicator) dimensions. |
139 |
139 |
140 @return tuple with border width (integer) and line height (integer) |
140 @return tuple with border width (integer) and line height (integer) |
141 """ |
141 """ |
142 return self.__lineBorder, self.__lineHeight |
142 return self.__lineBorder, self.__lineHeight |
143 |
143 |
144 def setEnabled(self, enable): |
144 def setEnabled(self, enable): |
145 """ |
145 """ |
146 Public method to set the enabled state. |
146 Public method to set the enabled state. |
147 |
147 |
148 @param enable flag indicating the enabled state (boolean) |
148 @param enable flag indicating the enabled state (boolean) |
149 """ |
149 """ |
150 if enable != self.__enabled: |
150 if enable != self.__enabled: |
151 self.__enabled = enable |
151 self.__enabled = enable |
152 self.setVisible(enable) |
152 self.setVisible(enable) |
153 self.__updateMasterViewportWidth() |
153 self.__updateMasterViewportWidth() |
154 |
154 |
155 def isEnabled(self): |
155 def isEnabled(self): |
156 """ |
156 """ |
157 Public method to check the enabled state. |
157 Public method to check the enabled state. |
158 |
158 |
159 @return flag indicating the enabled state (boolean) |
159 @return flag indicating the enabled state (boolean) |
160 """ |
160 """ |
161 return self.__enabled |
161 return self.__enabled |
162 |
162 |
163 def setBackgroundColor(self, color): |
163 def setBackgroundColor(self, color): |
164 """ |
164 """ |
165 Public method to set the widget background color. |
165 Public method to set the widget background color. |
166 |
166 |
167 @param color color for the background (QColor) |
167 @param color color for the background (QColor) |
168 """ |
168 """ |
169 if color != self.__backgroundColor: |
169 if color != self.__backgroundColor: |
170 self.__backgroundColor = color |
170 self.__backgroundColor = color |
171 self.__setSliderColor() |
171 self.__setSliderColor() |
172 self.update() |
172 self.update() |
173 |
173 |
174 def backgroundColor(self): |
174 def backgroundColor(self): |
175 """ |
175 """ |
176 Public method to get the background color. |
176 Public method to get the background color. |
177 |
177 |
178 @return background color (QColor) |
178 @return background color (QColor) |
179 """ |
179 """ |
180 return QColor(self.__backgroundColor) |
180 return QColor(self.__backgroundColor) |
181 |
181 |
182 def sizeHint(self): |
182 def sizeHint(self): |
183 """ |
183 """ |
184 Public method to give an indication about the preferred size. |
184 Public method to give an indication about the preferred size. |
185 |
185 |
186 @return preferred size (QSize) |
186 @return preferred size (QSize) |
187 """ |
187 """ |
188 return QSize(self.__width, 0) |
188 return QSize(self.__width, 0) |
189 |
189 |
190 def paintEvent(self, event): |
190 def paintEvent(self, event): |
191 """ |
191 """ |
192 Protected method to handle a paint event. |
192 Protected method to handle a paint event. |
193 |
193 |
194 @param event paint event (QPaintEvent) |
194 @param event paint event (QPaintEvent) |
195 """ |
195 """ |
196 # step 1: fill the whole painting area |
196 # step 1: fill the whole painting area |
197 painter = QPainter(self) |
197 painter = QPainter(self) |
198 painter.fillRect(event.rect(), self.__backgroundColor) |
198 painter.fillRect(event.rect(), self.__backgroundColor) |
199 |
199 |
200 # step 2: paint the indicators |
200 # step 2: paint the indicators |
201 self._paintIt(painter) |
201 self._paintIt(painter) |
202 |
202 |
203 # step 3: paint the slider |
203 # step 3: paint the slider |
204 if self._master: |
204 if self._master: |
205 penColor = self.__sliderColor |
205 penColor = self.__sliderColor |
206 painter.setPen(penColor) |
206 painter.setPen(penColor) |
207 brushColor = Qt.GlobalColor.transparent |
207 brushColor = Qt.GlobalColor.transparent |
208 painter.setBrush(QBrush(brushColor)) |
208 painter.setBrush(QBrush(brushColor)) |
209 painter.drawRect(self.__generateSliderRange( |
209 painter.drawRect( |
210 self._master.verticalScrollBar())) |
210 self.__generateSliderRange(self._master.verticalScrollBar()) |
211 |
211 ) |
|
212 |
212 def _paintIt(self, painter): |
213 def _paintIt(self, painter): |
213 """ |
214 """ |
214 Protected method for painting the widget's indicators. |
215 Protected method for painting the widget's indicators. |
215 |
216 |
216 Note: This method should be implemented by subclasses. |
217 Note: This method should be implemented by subclasses. |
217 |
218 |
218 @param painter reference to the painter object (QPainter) |
219 @param painter reference to the painter object (QPainter) |
219 """ |
220 """ |
220 pass |
221 pass |
221 |
222 |
222 def mousePressEvent(self, event): |
223 def mousePressEvent(self, event): |
223 """ |
224 """ |
224 Protected method to handle a mouse button press. |
225 Protected method to handle a mouse button press. |
225 |
226 |
226 @param event reference to the mouse event (QMouseEvent) |
227 @param event reference to the mouse event (QMouseEvent) |
227 """ |
228 """ |
228 if event.button() == Qt.MouseButton.LeftButton and self._master: |
229 if event.button() == Qt.MouseButton.LeftButton and self._master: |
229 vsb = self._master.verticalScrollBar() |
230 vsb = self._master.verticalScrollBar() |
230 value = self.position2Value(event.position().toPoint().y() - 1) |
231 value = self.position2Value(event.position().toPoint().y() - 1) |
231 vsb.setValue(int(value - 0.5 * vsb.pageStep())) # center on page |
232 vsb.setValue(int(value - 0.5 * vsb.pageStep())) # center on page |
232 self.__mousePressPos = None |
233 self.__mousePressPos = None |
233 |
234 |
234 def mouseMoveEvent(self, event): |
235 def mouseMoveEvent(self, event): |
235 """ |
236 """ |
236 Protected method to handle a mouse moves. |
237 Protected method to handle a mouse moves. |
237 |
238 |
238 @param event reference to the mouse event (QMouseEvent) |
239 @param event reference to the mouse event (QMouseEvent) |
239 """ |
240 """ |
240 if event.buttons() & Qt.MouseButton.LeftButton and self._master: |
241 if event.buttons() & Qt.MouseButton.LeftButton and self._master: |
241 vsb = self._master.verticalScrollBar() |
242 vsb = self._master.verticalScrollBar() |
242 value = self.position2Value(event.position().toPoint().y() - 1) |
243 value = self.position2Value(event.position().toPoint().y() - 1) |
243 vsb.setValue(int(value - 0.5 * vsb.pageStep())) # center on page |
244 vsb.setValue(int(value - 0.5 * vsb.pageStep())) # center on page |
244 |
245 |
245 def wheelEvent(self, event): |
246 def wheelEvent(self, event): |
246 """ |
247 """ |
247 Protected slot handling mouse wheel events. |
248 Protected slot handling mouse wheel events. |
248 |
249 |
249 @param event reference to the wheel event (QWheelEvent) |
250 @param event reference to the wheel event (QWheelEvent) |
250 """ |
251 """ |
251 isVertical = event.angleDelta().x() == 0 |
252 isVertical = event.angleDelta().x() == 0 |
252 if ( |
253 if ( |
253 self._master and |
254 self._master |
254 event.modifiers() == Qt.KeyboardModifier.NoModifier and |
255 and event.modifiers() == Qt.KeyboardModifier.NoModifier |
255 isVertical |
256 and isVertical |
256 ): |
257 ): |
257 QCoreApplication.sendEvent(self._master.verticalScrollBar(), event) |
258 QCoreApplication.sendEvent(self._master.verticalScrollBar(), event) |
258 |
259 |
259 def calculateGeometry(self): |
260 def calculateGeometry(self): |
260 """ |
261 """ |
261 Public method to recalculate the map widget's geometry. |
262 Public method to recalculate the map widget's geometry. |
262 """ |
263 """ |
263 if self._master: |
264 if self._master: |
293 posHeight = vsb.height() - delta - 1 |
298 posHeight = vsb.height() - delta - 1 |
294 valHeight = vsb.maximum() - vsb.minimum() + vsb.pageStep() |
299 valHeight = vsb.maximum() - vsb.minimum() + vsb.pageStep() |
295 return float(posHeight) / valHeight |
300 return float(posHeight) / valHeight |
296 else: |
301 else: |
297 return 1.0 |
302 return 1.0 |
298 |
303 |
299 def value2Position(self, value, slider=False): |
304 def value2Position(self, value, slider=False): |
300 """ |
305 """ |
301 Public method to convert a scrollbar value into a position. |
306 Public method to convert a scrollbar value into a position. |
302 |
307 |
303 @param value value to convert (integer) |
308 @param value value to convert (integer) |
304 @param slider flag indicating to calculate the result for the slider |
309 @param slider flag indicating to calculate the result for the slider |
305 (boolean) |
310 (boolean) |
306 @return position (integer) |
311 @return position (integer) |
307 """ |
312 """ |
308 if self._master: |
313 if self._master: |
309 offset = 0 if slider else 1 |
314 offset = 0 if slider else 1 |
310 vsb = self._master.verticalScrollBar() |
315 vsb = self._master.verticalScrollBar() |
311 return int((value - vsb.minimum()) * self.scaleFactor(slider) + |
316 return int((value - vsb.minimum()) * self.scaleFactor(slider) + offset) |
312 offset) |
|
313 else: |
317 else: |
314 return value |
318 return value |
315 |
319 |
316 def position2Value(self, position, slider=False): |
320 def position2Value(self, position, slider=False): |
317 """ |
321 """ |
318 Public method to convert a position into a scrollbar value. |
322 Public method to convert a position into a scrollbar value. |
319 |
323 |
320 @param position scrollbar position to convert (integer) |
324 @param position scrollbar position to convert (integer) |
321 @param slider flag indicating to calculate the result for the slider |
325 @param slider flag indicating to calculate the result for the slider |
322 (boolean) |
326 (boolean) |
323 @return scrollbar value (integer) |
327 @return scrollbar value (integer) |
324 """ |
328 """ |
325 if self._master: |
329 if self._master: |
326 offset = 0 if slider else 1 |
330 offset = 0 if slider else 1 |
327 vsb = self._master.verticalScrollBar() |
331 vsb = self._master.verticalScrollBar() |
328 return vsb.minimum() + max( |
332 return vsb.minimum() + max( |
329 0, (position - offset) / self.scaleFactor(slider)) |
333 0, (position - offset) / self.scaleFactor(slider) |
|
334 ) |
330 else: |
335 else: |
331 return position |
336 return position |
332 |
337 |
333 def generateIndicatorRect(self, position): |
338 def generateIndicatorRect(self, position): |
334 """ |
339 """ |
335 Public method to generate an indicator rectangle. |
340 Public method to generate an indicator rectangle. |
336 |
341 |
337 @param position indicator position (integer) |
342 @param position indicator position (integer) |
338 @return indicator rectangle (QRect) |
343 @return indicator rectangle (QRect) |
339 """ |
344 """ |
340 return QRect(self.__lineBorder, position - self.__lineHeight // 2, |
345 return QRect( |
341 self.__width - self.__lineBorder, self.__lineHeight) |
346 self.__lineBorder, |
342 |
347 position - self.__lineHeight // 2, |
|
348 self.__width - self.__lineBorder, |
|
349 self.__lineHeight, |
|
350 ) |
|
351 |
343 def __generateSliderRange(self, scrollbar): |
352 def __generateSliderRange(self, scrollbar): |
344 """ |
353 """ |
345 Private method to generate the slider rectangle. |
354 Private method to generate the slider rectangle. |
346 |
355 |
347 @param scrollbar reference to the vertical scrollbar (QScrollBar) |
356 @param scrollbar reference to the vertical scrollbar (QScrollBar) |
348 @return slider rectangle (QRect) |
357 @return slider rectangle (QRect) |
349 """ |
358 """ |
350 pos1 = self.value2Position(scrollbar.value(), slider=True) |
359 pos1 = self.value2Position(scrollbar.value(), slider=True) |
351 pos2 = self.value2Position(scrollbar.value() + scrollbar.pageStep(), |
360 pos2 = self.value2Position( |
352 slider=True) |
361 scrollbar.value() + scrollbar.pageStep(), slider=True |
|
362 ) |
353 return QRect(0, pos1, self.__width - 1, pos2 - pos1) |
363 return QRect(0, pos1, self.__width - 1, pos2 - pos1) |