eric7/WebBrowser/AutoScroll/AutoScroller.py

branch
eric7
changeset 8312
800c432b34c8
parent 8228
772103b14c18
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the automatic scroller.
8 """
9
10 #
11 # This module is based on the Qupzilla auto scroller.
12 # Copyright (C) 2014 David Rosca <nowrep@gmail.com>
13 #
14
15 from PyQt5.QtCore import Qt, QObject, QRect, QEvent, QPoint
16 from PyQt5.QtWidgets import QApplication, QLabel
17
18 from .FrameScroller import FrameScroller
19
20 import Preferences
21 import UI.PixmapCache
22
23
24 class AutoScroller(QObject):
25 """
26 Class implementing the automatic scroller.
27 """
28 def __init__(self, parent=None):
29 """
30 Constructor
31
32 @param parent reference to the parent object
33 @type QObject
34 """
35 super().__init__(parent)
36
37 self.__view = None
38
39 self.__indicator = QLabel()
40 self.__indicator.resize(32, 32)
41 self.__indicator.setContentsMargins(0, 0, 0, 0)
42 self.__indicator.installEventFilter(self)
43
44 self.__scroller = FrameScroller(self)
45 self.__scroller.setScrollDivider(
46 Preferences.getWebBrowser("AutoScrollDivider"))
47
48 self.__enabled = Preferences.getWebBrowser("AutoScrollEnabled")
49
50 def isEnabled(self):
51 """
52 Public method to get the enabled state.
53
54 @return enabled state
55 @rtype bool
56 """
57 return self.__enabled
58
59 def mouseMove(self, evt):
60 """
61 Public method to handle mouse move events.
62
63 @param evt reference to the mouse move event
64 @type QMouseEvent
65 @return flag indicating, that the event was handled
66 @rtype bool
67 """
68 if self.__enabled and self.__indicator.isVisible():
69 rect = self.__indicatorGlobalRect()
70 xlen = 0
71 ylen = 0
72 egp = evt.globalPos()
73
74 if rect.left() > egp.x():
75 xlen = egp.x() - rect.left()
76 elif rect.right() < egp.x():
77 xlen = egp.x() - rect.right()
78
79 if rect.top() > egp.y():
80 ylen = egp.y() - rect.top()
81 elif rect.bottom() < egp.y():
82 ylen = egp.y() - rect.bottom()
83
84 self.__scroller.startScrolling(xlen, ylen)
85
86 return False
87
88 def mousePress(self, view, evt):
89 """
90 Public method to handle mouse button presses.
91
92 @param view reference to the web view the button was pressed on
93 @type WebBrowserView
94 @param evt reference to the mouse button press event
95 @type QMouseEvent
96 @return flag indicating, that the event was handled
97 @rtype bool
98 """
99 if self.__enabled:
100 middleButton = evt.buttons() == Qt.MouseButton.MiddleButton
101
102 if view:
103 # test for start
104 if (
105 middleButton and
106 (self.__view != view or not self.__indicator.isVisible())
107 ):
108 return self.__showIndicator(view, evt.pos())
109
110 # test for stop
111 if self.__indicator.isVisible():
112 self.__stopScrolling()
113 return True
114
115 return False
116
117 def mouseRelease(self, evt):
118 """
119 Public method to handle mouse button releases.
120
121 @param evt reference to the mouse button release event
122 @type QMouseEvent
123 @return flag indicating, that the event was handled
124 @rtype bool
125 """
126 if self.__enabled and self.__indicator.isVisible():
127 if not self.__indicatorGlobalRect().contains(
128 evt.globalPos()):
129 self.__stopScrolling()
130 return True
131
132 return False
133
134 def wheel(self):
135 """
136 Public method to handle a mouse wheel event.
137
138 @return flag indicating, that the event was handled
139 @rtype bool
140 """
141 if self.__enabled and self.__indicator.isVisible():
142 self.__stopScrolling()
143 return True
144
145 return False
146
147 def preferencesChanged(self):
148 """
149 Public method to handle a change of the settings.
150 """
151 enabled = Preferences.getWebBrowser("AutoScrollEnabled")
152 if enabled != self.__enabled:
153 if self.__indicator.isVisible():
154 self.__stopScrolling()
155 self.__enabled = enabled
156
157 self.__scroller.setScrollDivider(
158 Preferences.getWebBrowser("AutoScrollDivider"))
159
160 def eventFilter(self, obj, evt):
161 """
162 Public method to handle event for an object.
163
164 @param obj refernce to the object sending the event
165 @type QObject
166 @param evt reference to the event to be handled
167 @type QEvent
168 @return flag indicating, that the event was handled
169 @rtype bool
170 """
171 if obj == self.__indicator:
172 if evt.type() == QEvent.Type.Enter:
173 self.__scroller.stopScrolling()
174 elif evt.type() in [QEvent.Type.Wheel, QEvent.Type.Hide,
175 QEvent.Type.MouseButtonPress]:
176 self.__stopScrolling()
177
178 return False
179
180 def __showIndicator(self, view, pos):
181 """
182 Private method to show the auto scroll indicator.
183
184 @param view reference to the view to show the indicator on
185 @type WebBrowserView
186 @param pos position to show the indicator at
187 @type QPoint
188 @return flag indicating, that the indicator is shown
189 @rtype bool
190 """
191 hit = view.page().hitTestContent(pos)
192
193 if hit.isContentEditable() or not hit.linkUrl().isEmpty():
194 return False
195
196 jsSource = """
197 var out = {
198 vertical:
199 window.innerWidth > document.documentElement.clientWidth,
200 horizontal:
201 window.innerHeight > document.documentElement.clientHeight
202 };
203 out;"""
204
205 res = view.page().execJavaScript(jsSource)
206 if res is None:
207 return False
208
209 vertical = res["vertical"]
210 horizontal = res["horizontal"]
211 if not vertical and not horizontal:
212 return False
213
214 if vertical and horizontal:
215 self.__indicator.setPixmap(
216 UI.PixmapCache.getPixmap("scrollAll"))
217 elif vertical:
218 self.__indicator.setPixmap(
219 UI.PixmapCache.getPixmap("scrollVertical"))
220 else:
221 self.__indicator.setPixmap(
222 UI.PixmapCache.getPixmap("scrollHorizontal"))
223
224 self.__view = view
225 p = QPoint(
226 pos.x() - self.__indicator.pixmap().width() // 2,
227 pos.y() - self.__indicator.pixmap().height() // 2
228 )
229
230 self.__indicator.setParent(self.__view)
231 self.__indicator.move(p)
232 self.__indicator.show()
233
234 self.__scroller.setPage(view.page())
235
236 self.__view.inputWidget().grabMouse()
237 QApplication.setOverrideCursor(Qt.CursorShape.ArrowCursor)
238
239 return True
240
241 def __stopScrolling(self):
242 """
243 Private method to stop scrolling.
244 """
245 self.__view.inputWidget().releaseMouse()
246 QApplication.restoreOverrideCursor()
247
248 self.__indicator.hide()
249 self.__indicator.setParent(None)
250 self.__scroller.stopScrolling()
251
252 def __indicatorGlobalRect(self):
253 """
254 Private method to calculate the global indicator parameters.
255
256 @return global indicator parameters
257 @rtype QRect
258 """
259 pos = self.__indicator.parentWidget().mapToGlobal(
260 self.__indicator.geometry().topLeft())
261 return QRect(pos.x(), pos.y(),
262 self.__indicator.width(), self.__indicator.height())

eric ide

mercurial