eric6/WebBrowser/UrlBar/UrlBar.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7192
a22eee00b052
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the URL bar widget.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_EXCEPTION__
13 except NameError:
14 pass
15
16 from PyQt5.QtCore import pyqtSlot, Qt, QPointF, QUrl, QDateTime, QTimer, QPoint
17 from PyQt5.QtGui import QColor, QPalette, QLinearGradient, QIcon
18 from PyQt5.QtWidgets import QDialog, QApplication
19 from PyQt5.QtWebEngineWidgets import QWebEnginePage
20
21 from E5Gui.E5LineEdit import E5LineEdit
22 from E5Gui.E5LineEditButton import E5LineEditButton
23
24 from WebBrowser.WebBrowserWindow import WebBrowserWindow
25
26 from WebBrowser.SafeBrowsing.SafeBrowsingLabel import SafeBrowsingLabel
27
28 from .FavIconLabel import FavIconLabel
29
30 import UI.PixmapCache
31 import Preferences
32
33
34 class UrlBar(E5LineEdit):
35 """
36 Class implementing a line edit for entering URLs.
37 """
38 def __init__(self, mainWindow, parent=None):
39 """
40 Constructor
41
42 @param mainWindow reference to the main window (HelpWindow)
43 @param parent reference to the parent widget (HelpBrowser)
44 """
45 E5LineEdit.__init__(self, parent)
46 self.setInactiveText(self.tr("Enter the URL here."))
47 self.setWhatsThis(self.tr("Enter the URL here."))
48
49 self.__mw = mainWindow
50 self.__browser = None
51 self.__privateMode = WebBrowserWindow.isPrivate()
52
53 self.__bmActiveIcon = UI.PixmapCache.getIcon("bookmark16.png")
54 self.__bmInactiveIcon = QIcon(
55 self.__bmActiveIcon.pixmap(16, 16, QIcon.Disabled))
56
57 self.__safeBrowsingLabel = SafeBrowsingLabel(self)
58 self.addWidget(self.__safeBrowsingLabel, E5LineEdit.LeftSide)
59 self.__safeBrowsingLabel.setVisible(False)
60
61 self.__favicon = FavIconLabel(self)
62 self.addWidget(self.__favicon, E5LineEdit.LeftSide)
63
64 self.__rssButton = E5LineEditButton(self)
65 self.__rssButton.setIcon(UI.PixmapCache.getIcon("rss16.png"))
66 self.addWidget(self.__rssButton, E5LineEdit.RightSide)
67 self.__rssButton.setVisible(False)
68
69 self.__bookmarkButton = E5LineEditButton(self)
70 self.addWidget(self.__bookmarkButton, E5LineEdit.RightSide)
71 self.__bookmarkButton.setVisible(False)
72
73 self.__clearButton = E5LineEditButton(self)
74 self.__clearButton.setIcon(UI.PixmapCache.getIcon("clearLeft.png"))
75 self.addWidget(self.__clearButton, E5LineEdit.RightSide)
76 self.__clearButton.setVisible(False)
77
78 self.__safeBrowsingLabel.clicked.connect(self.__showThreatInfo)
79 self.__bookmarkButton.clicked.connect(self.__showBookmarkInfo)
80 self.__rssButton.clicked.connect(self.__rssClicked)
81 self.__clearButton.clicked.connect(self.clear)
82 self.textChanged.connect(self.__textChanged)
83
84 self.__mw.bookmarksManager().entryChanged.connect(
85 self.__bookmarkChanged)
86 self.__mw.bookmarksManager().entryAdded.connect(
87 self.__bookmarkChanged)
88 self.__mw.bookmarksManager().entryRemoved.connect(
89 self.__bookmarkChanged)
90 self.__mw.speedDial().pagesChanged.connect(
91 self.__bookmarkChanged)
92
93 def setBrowser(self, browser):
94 """
95 Public method to set the browser connection.
96
97 @param browser reference to the browser widget (WebBrowserView)
98 """
99 self.__browser = browser
100 self.__favicon.setBrowser(browser)
101
102 self.__browser.urlChanged.connect(self.__browserUrlChanged)
103 self.__browser.loadProgress.connect(self.update)
104 self.__browser.loadFinished.connect(self.__loadFinished)
105 self.__browser.loadStarted.connect(self.__loadStarted)
106
107 self.__browser.safeBrowsingBad.connect(
108 self.__safeBrowsingLabel.setThreatInfo)
109
110 def browser(self):
111 """
112 Public method to get the associated browser.
113
114 @return reference to the associated browser (HelpBrowser)
115 """
116 return self.__browser
117
118 def __browserUrlChanged(self, url):
119 """
120 Private slot to handle a URL change of the associated browser.
121
122 @param url new URL of the browser (QUrl)
123 """
124 strUrl = url.toString()
125 if strUrl in ["eric:speeddial", "eric:home",
126 "about:blank", "about:config"]:
127 strUrl = ""
128
129 if self.text() != strUrl:
130 self.setText(strUrl)
131 self.setCursorPosition(0)
132
133 def __loadStarted(self):
134 """
135 Private slot to perform actions before the page is loaded.
136 """
137 self.__bookmarkButton.setVisible(False)
138 self.__rssButton.setVisible(False)
139
140 def __checkBookmark(self):
141 """
142 Private slot to check the current URL for the bookmarked state.
143 """
144 manager = self.__mw.bookmarksManager()
145 if manager.bookmarkForUrl(self.__browser.url()) is not None:
146 self.__bookmarkButton.setIcon(self.__bmActiveIcon)
147 bookmarks = manager.bookmarksForUrl(self.__browser.url())
148 from WebBrowser.Bookmarks.BookmarkNode import BookmarkNode
149 for bookmark in bookmarks:
150 manager.setTimestamp(bookmark, BookmarkNode.TsVisited,
151 QDateTime.currentDateTime())
152 elif self.__mw.speedDial()\
153 .pageForUrl(self.__browser.url()).url != "":
154 self.__bookmarkButton.setIcon(self.__bmActiveIcon)
155 else:
156 self.__bookmarkButton.setIcon(self.__bmInactiveIcon)
157
158 def __loadFinished(self, ok):
159 """
160 Private slot to set some data after the page was loaded.
161
162 @param ok flag indicating a successful load (boolean)
163 """
164 if self.__browser.url().scheme() in ["eric", "about"]:
165 self.__bookmarkButton.setVisible(False)
166 else:
167 self.__checkBookmark()
168 self.__bookmarkButton.setVisible(True)
169
170 self.__browserUrlChanged(self.__browser.url())
171 self.__safeBrowsingLabel.setVisible(
172 not self.__browser.getSafeBrowsingStatus())
173
174 if ok:
175 QTimer.singleShot(0, self.__setRssButton)
176
177 def __textChanged(self, txt):
178 """
179 Private slot to handle changes of the text.
180
181 @param txt current text (string)
182 """
183 self.__clearButton.setVisible(txt != "")
184
185 def preferencesChanged(self):
186 """
187 Public slot to handle a change of preferences.
188 """
189 self.update()
190
191 def __showBookmarkInfo(self):
192 """
193 Private slot to show a dialog with some bookmark info.
194 """
195 from .BookmarkActionSelectionDialog import \
196 BookmarkActionSelectionDialog
197 url = self.__browser.url()
198 dlg = BookmarkActionSelectionDialog(url)
199 if dlg.exec_() == QDialog.Accepted:
200 action = dlg.getAction()
201 if action == BookmarkActionSelectionDialog.AddBookmark:
202 self.__browser.addBookmark()
203 elif action == BookmarkActionSelectionDialog.EditBookmark:
204 bookmark = self.__mw.bookmarksManager()\
205 .bookmarkForUrl(url)
206 from .BookmarkInfoDialog import BookmarkInfoDialog
207 dlg = BookmarkInfoDialog(bookmark, self.__browser)
208 dlg.exec_()
209 elif action == BookmarkActionSelectionDialog.AddSpeeddial:
210 self.__mw.speedDial().addPage(
211 url, self.__browser.title())
212 elif action == BookmarkActionSelectionDialog.RemoveSpeeddial:
213 self.__mw.speedDial().removePage(url)
214
215 @pyqtSlot()
216 def __bookmarkChanged(self):
217 """
218 Private slot to handle bookmark or speed dial changes.
219 """
220 self.__checkBookmark()
221
222 def paintEvent(self, evt):
223 """
224 Protected method handling a paint event.
225
226 @param evt reference to the paint event (QPaintEvent)
227 """
228 if self.__privateMode:
229 backgroundColor = QColor(220, 220, 220) # light gray
230 foregroundColor = Qt.black
231 else:
232 backgroundColor = QApplication.palette().color(QPalette.Base)
233 foregroundColor = QApplication.palette().color(QPalette.Text)
234
235 if self.__browser is not None:
236 p = self.palette()
237 progress = self.__browser.progress()
238
239 if not self.__browser.getSafeBrowsingStatus():
240 # malicious web site
241 backgroundColor = QColor(170, 0, 0)
242 foregroundColor = QColor(Qt.white)
243 elif self.__browser.url().scheme() == "https":
244 backgroundColor = Preferences.getWebBrowser(
245 "SaveUrlColor")
246
247 if progress == 0 or progress == 100:
248 p.setBrush(QPalette.Base, backgroundColor)
249 p.setBrush(QPalette.Text, foregroundColor)
250 else:
251 highlight = QApplication.palette().color(QPalette.Highlight)
252 r = (highlight.red() + 2 * backgroundColor.red()) // 3
253 g = (highlight.green() + 2 * backgroundColor.green()) // 3
254 b = (highlight.blue() + 2 * backgroundColor.blue()) // 3
255
256 loadingColor = QColor(r, g, b)
257 if abs(loadingColor.lightness() -
258 backgroundColor.lightness()) < 20:
259 # special handling for special color schemes (e.g Gaia)
260 r = (2 * highlight.red() + backgroundColor.red()) // 3
261 g = (2 * highlight.green() + backgroundColor.green()) // 3
262 b = (2 * highlight.blue() + backgroundColor.blue()) // 3
263 loadingColor = QColor(r, g, b)
264
265 gradient = QLinearGradient(
266 QPointF(0, 0), QPointF(self.width(), 0))
267 gradient.setColorAt(0, loadingColor)
268 gradient.setColorAt(progress / 100.0 - 0.000001, loadingColor)
269 gradient.setColorAt(progress / 100.0, backgroundColor)
270 p.setBrush(QPalette.Base, gradient)
271
272 self.setPalette(p)
273
274 E5LineEdit.paintEvent(self, evt)
275
276 def focusOutEvent(self, evt):
277 """
278 Protected method to handle focus out event.
279
280 @param evt reference to the focus event (QFocusEvent)
281 """
282 if self.text() == "" and self.__browser is not None:
283 self.__browserUrlChanged(self.__browser.url())
284 E5LineEdit.focusOutEvent(self, evt)
285
286 def mousePressEvent(self, evt):
287 """
288 Protected method called by a mouse press event.
289
290 @param evt reference to the mouse event (QMouseEvent)
291 """
292 if evt.button() == Qt.XButton1:
293 self.__mw.currentBrowser().triggerPageAction(
294 QWebEnginePage.Back)
295 elif evt.button() == Qt.XButton2:
296 self.__mw.currentBrowser().triggerPageAction(
297 QWebEnginePage.Forward)
298 else:
299 super(UrlBar, self).mousePressEvent(evt)
300
301 def mouseDoubleClickEvent(self, evt):
302 """
303 Protected method to handle mouse double click events.
304
305 @param evt reference to the mouse event (QMouseEvent)
306 """
307 if evt.button() == Qt.LeftButton:
308 self.selectAll()
309 else:
310 E5LineEdit.mouseDoubleClickEvent(self, evt)
311
312 def keyPressEvent(self, evt):
313 """
314 Protected method to handle key presses.
315
316 @param evt reference to the key press event (QKeyEvent)
317 """
318 if evt.key() == Qt.Key_Escape:
319 if self.__browser is not None:
320 self.setText(
321 str(self.__browser.url().toEncoded(), encoding="utf-8"))
322 self.selectAll()
323 completer = self.completer()
324 if completer:
325 completer.popup().hide()
326 return
327
328 currentText = self.text().strip()
329 if evt.key() in [Qt.Key_Enter, Qt.Key_Return] and \
330 not currentText.lower().startswith("http://"):
331 append = ""
332 if evt.modifiers() == Qt.KeyboardModifiers(Qt.ControlModifier):
333 append = ".com"
334 elif evt.modifiers() == Qt.KeyboardModifiers(
335 Qt.ControlModifier | Qt.ShiftModifier):
336 append = ".org"
337 elif evt.modifiers() == Qt.KeyboardModifiers(Qt.ShiftModifier):
338 append = ".net"
339
340 if append != "":
341 url = QUrl("http://www." + currentText)
342 host = url.host()
343 if not host.lower().endswith(append):
344 host += append
345 url.setHost(host)
346 self.setText(url.toString())
347
348 E5LineEdit.keyPressEvent(self, evt)
349
350 def dragEnterEvent(self, evt):
351 """
352 Protected method to handle drag enter events.
353
354 @param evt reference to the drag enter event (QDragEnterEvent)
355 """
356 mimeData = evt.mimeData()
357 if mimeData.hasUrls() or mimeData.hasText():
358 evt.acceptProposedAction()
359
360 E5LineEdit.dragEnterEvent(self, evt)
361
362 def dropEvent(self, evt):
363 """
364 Protected method to handle drop events.
365
366 @param evt reference to the drop event (QDropEvent)
367 """
368 mimeData = evt.mimeData()
369
370 url = QUrl()
371 if mimeData.hasUrls():
372 url = mimeData.urls()[0]
373 elif mimeData.hasText():
374 url = QUrl.fromEncoded(mimeData.text().encode("utf-8"),
375 QUrl.TolerantMode)
376
377 if url.isEmpty() or not url.isValid():
378 E5LineEdit.dropEvent(self, evt)
379 return
380
381 self.setText(str(url.toEncoded(), encoding="utf-8"))
382 self.selectAll()
383
384 evt.acceptProposedAction()
385
386 def __setRssButton(self):
387 """
388 Private slot to show the RSS button.
389 """
390 self.__rssButton.setVisible(self.__browser.checkRSS())
391
392 def __rssClicked(self):
393 """
394 Private slot to handle clicking the RSS icon.
395 """
396 from WebBrowser.Feeds.FeedsDialog import FeedsDialog
397 feeds = self.__browser.getRSS()
398 dlg = FeedsDialog(feeds, self.__browser)
399 dlg.exec_()
400
401 @pyqtSlot(QPoint)
402 def __showThreatInfo(self, pos):
403 """
404 Private slot to show the threat info widget.
405
406 @param pos position to show the info at
407 @type QPoint
408 """
409 threatInfo = self.__safeBrowsingLabel.getThreatInfo()
410 if threatInfo:
411 from WebBrowser.SafeBrowsing.SafeBrowsingInfoWidget import \
412 SafeBrowsingInfoWidget
413 widget = SafeBrowsingInfoWidget(threatInfo, self.__browser)
414 widget.showAt(pos)

eric ide

mercurial