WebBrowser/Tools/WebHitTestResult.py

branch
QtWebEngine
changeset 4728
0367675d783d
child 4917
682750cc7bd5
equal deleted inserted replaced
4727:62b50a24fb59 4728:0367675d783d
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing an object for testing certain aspects of a web page.
8 """
9
10 #
11 # This code was ported from QupZilla.
12 # Copyright (C) David Rosca <nowrep@gmail.com>
13 #
14
15 from __future__ import unicode_literals
16
17 from PyQt5.QtCore import QPoint, QRect, QUrl
18
19 class WebHitTestResult(object):
20 """
21 Class implementing an object for testing certain aspects of a web page.
22 """
23 def __init__(self, page, pos):
24 """
25 Constructor
26
27 @param page reference to the web page
28 @type WebBrowserPage
29 @param pos position to be tested
30 @type QPoint
31 """
32 self.__isNull = True
33 self.__isContentEditable = False
34 self.__isContentSelected = False
35 self.__isMediaPaused = False
36 self.__isMediaMuted = False
37 self.__pos = QPoint(pos)
38 self.__alternateText = ""
39 self.__boundingRect = QRect()
40 self.__imageUrl = QUrl()
41 self.__linkTitle = ""
42 self.__linkUrl = QUrl()
43 self.__mediaUrl = QUrl()
44 self.__tagName = ""
45
46 script = """
47 (function() {{
48 var e = document.elementFromPoint({0}, {1});
49 if (!e)
50 return;
51 function isMediaElement(e) {{
52 return e.tagName == 'AUDIO' || e.tagName == 'VIDEO';
53 }}
54 function isEditableElement(e) {{
55 if (e.isContentEditable)
56 return true;
57 if (e.tagName == 'INPUT' || e.tagName == 'TEXTAREA')
58 return e.getAttribute('readonly') != 'readonly';
59 return false;
60 }}
61 function isSelected(e) {{
62 var selection = window.getSelection();
63 if (selection.type != 'Range')
64 return false;
65 return window.getSelection().containsNode(e, true);
66 }}
67 var res = {{
68 alternateText: e.getAttribute('alt'),
69 boundingRect: '',
70 imageUrl: '',
71 contentEditable: isEditableElement(e),
72 contentSelected: isSelected(e),
73 linkTitle: '',
74 linkUrl: '',
75 mediaUrl: '',
76 mediaPaused: false,
77 mediaMuted: false,
78 tagName: e.tagName.toLowerCase()
79 }};
80 var r = e.getBoundingClientRect();
81 res.boundingRect = [r.top, r.left, r.width, r.height];
82 if (e.tagName == 'IMG')
83 res.imageUrl = e.getAttribute('src');
84 if (e.tagName == 'A') {{
85 res.linkTitle = e.text;
86 res.linkUrl = e.getAttribute('href');
87 }}
88 while (e) {{
89 if (res.linkTitle == '' && e.tagName == 'A')
90 res.linkTitle = e.text;
91 if (res.linkUrl == '' && e.tagName == 'A')
92 res.linkUrl = e.getAttribute('href');
93 if (res.mediaUrl == '' && isMediaElement(e)) {{
94 res.mediaUrl = e.currentSrc;
95 res.mediaPaused = e.paused;
96 res.mediaMuted = e.muted;
97 }}
98 e = e.parentElement;
99 }}
100 return res;
101 }})()
102 """.format(pos.x(), pos.y())
103 self.__populate(page.url(), page.execJavaScript(script))
104
105 def alternateText(self):
106 """
107 Public method to get the alternate text.
108
109 @return alternate text
110 @rtype str
111 """
112 return self.__alternateText
113
114 def boundingRect(self):
115 """
116 Public method to get the bounding rectangle.
117
118 @return bounding rectangle
119 @rtype QRect
120 """
121 return QRect(self.__boundingRect)
122
123 def imageUrl(self):
124 """
125 Public method to get the URL of an image.
126
127 @return image URL
128 @rtype QUrl
129 """
130 return self.__imageUrl
131
132 def isContentEditable(self):
133 """
134 Public method to check for editable content.
135
136 @return flag indicating editable content
137 @rtype bool
138 """
139 return self.__isContentEditable
140
141 def isContentSelected(self):
142 """
143 Public method to check for selected content.
144
145 @return flag indicating selected content
146 @rtype bool
147 """
148 return self.__isContentSelected
149
150 def isNull(self):
151 """
152 Public method to test, if the hit test is empty.
153
154 @return flag indicating an empty object
155 @rtype bool
156 """
157 return self.__isNull
158
159 def linkTitle(self):
160 """
161 Public method to get the title for a link element.
162
163 @return title for a link element
164 @rtype str
165 """
166 return self.__linkTitle
167
168 def linkUrl(self):
169 """
170 Public method to get the URL for a link element.
171
172 @return URL for a link element
173 @rtype QUrl
174 """
175 return self.__linkUrl
176
177 def mediaUrl(self):
178 """
179 Public method to get the URL for a media element.
180
181 @return URL for a media element
182 @rtype QUrl
183 """
184 return self.__mediaUrl
185
186 def mediaPaused(self):
187 """
188 Public method to check, if a media element is paused.
189
190 @return flag indicating a paused media element
191 @rtype bool
192 """
193 return self.__isMediaPaused
194
195 def mediaMuted(self):
196 """
197 Public method to check, if a media element is muted.
198
199 @return flag indicating a muted media element
200 @rtype bool
201 """
202 return self.__isMediaMuted
203
204 def pos(self):
205 """
206 Public method to get the position of the hit test.
207
208 @return position of hit test
209 @rtype QPoint
210 """
211 return QPoint(self.__pos)
212
213 def tagName(self):
214 """
215 Public method to get the name of the tested tag.
216
217 @return name of the tested tag
218 @rtype str
219 """
220 return self.__tagName
221
222 def __populate(self, url, res):
223 """
224 Private method to populate the object.
225
226 @param url URL of the tested page
227 @type QUrl
228 @param res dictionary with result data from JavaScript
229 @type dict
230 """
231 if not res:
232 return
233
234 self.__alternateText = res["alternateText"]
235 self.__imageUrl = QUrl(res["imageUrl"])
236 self.__isContentEditable = res["contentEditable"]
237 self.__isContentSelected = res["contentSelected"]
238 self.__linkTitle = res["linkTitle"]
239 self.__linkUrl = QUrl(res["linkUrl"])
240 self.__mediaUrl = QUrl(res["mediaUrl"])
241 self.__isMediaPaused = res["mediaPaused"]
242 self.__isMediaMuted = res["mediaMuted"]
243 self.__tagName = res["tagName"]
244
245 rect = res["boundingRect"]
246 if len(rect) == 4:
247 self.__boundingRect = QRect(int(rect[0]), int(rect[1]),
248 int(rect[2]), int(rect[3]))
249
250 if not self.__imageUrl.isEmpty():
251 self.__imageUrl = url.resolved(self.__imageUrl)
252 if not self.__linkUrl.isEmpty():
253 self.__linkUrl = url.resolved(self.__linkUrl)
254 if not self.__mediaUrl.isEmpty():
255 self.__mediaUrl = url.resolved(self.__mediaUrl)

eric ide

mercurial