26 QTimer, |
26 QTimer, |
27 QUrl, |
27 QUrl, |
28 pyqtSignal, |
28 pyqtSignal, |
29 pyqtSlot, |
29 pyqtSlot, |
30 ) |
30 ) |
31 from PyQt6.QtGui import ( |
31 from PyQt6.QtGui import QClipboard, QCursor, QDesktopServices, QIcon, QPixmap |
32 QClipboard, |
|
33 QContextMenuEvent, |
|
34 QCursor, |
|
35 QDesktopServices, |
|
36 QIcon, |
|
37 QPixmap, |
|
38 ) |
|
39 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage |
32 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage |
40 from PyQt6.QtWebEngineWidgets import QWebEngineView |
33 from PyQt6.QtWebEngineWidgets import QWebEngineView |
41 from PyQt6.QtWidgets import QApplication, QDialog, QMenu, QStyle |
34 from PyQt6.QtWidgets import QApplication, QDialog, QMenu, QStyle |
42 |
35 |
43 from eric7 import Preferences |
36 from eric7 import Preferences |
139 self.__preview = QPixmap() |
132 self.__preview = QPixmap() |
140 |
133 |
141 self.__currentZoom = 100 |
134 self.__currentZoom = 100 |
142 self.__zoomLevels = WebBrowserView.ZoomLevels[:] |
135 self.__zoomLevels = WebBrowserView.ZoomLevels[:] |
143 |
136 |
|
137 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) |
|
138 self.customContextMenuRequested.connect(self.__showContextMenu) |
|
139 |
144 self.iconUrlChanged.connect(self.__iconUrlChanged) |
140 self.iconUrlChanged.connect(self.__iconUrlChanged) |
145 self.urlChanged.connect(self.__urlChanged) |
141 self.urlChanged.connect(self.__urlChanged) |
146 self.page().linkHovered.connect(self.__linkHovered) |
142 self.page().linkHovered.connect(self.__linkHovered) |
147 |
143 |
148 self.loadStarted.connect(self.__loadStarted) |
144 self.loadStarted.connect(self.__loadStarted) |
180 self.setPage(self.__page) |
176 self.setPage(self.__page) |
181 |
177 |
182 self.__page.safeBrowsingAbort.connect(self.safeBrowsingAbort) |
178 self.__page.safeBrowsingAbort.connect(self.safeBrowsingAbort) |
183 self.__page.safeBrowsingBad.connect(self.safeBrowsingBad) |
179 self.__page.safeBrowsingBad.connect(self.safeBrowsingBad) |
184 self.__page.printPageRequested.connect(self.__printPage) |
180 self.__page.printPageRequested.connect(self.__printPage) |
185 self.__page.quotaRequested.connect(self.__quotaRequested) |
181 with contextlib.suppress(AttributeError): |
|
182 # deprecated with Qt 6.5+ |
|
183 self.__page.quotaRequested.connect(self.__quotaRequested) |
186 with contextlib.suppress(AttributeError): |
184 with contextlib.suppress(AttributeError): |
187 # Qt 6.4+ |
185 # Qt 6.4+ |
188 self.__page.fileSystemAccessRequested.connect( |
186 self.__page.fileSystemAccessRequested.connect( |
189 self.__fileSystemAccessRequested |
187 self.__fileSystemAccessRequested |
190 ) |
188 ) |
555 self.tr("Match {0} of {1}").format( |
553 self.tr("Match {0} of {1}").format( |
556 result.activeMatch(), result.numberOfMatches() |
554 result.activeMatch(), result.numberOfMatches() |
557 ) |
555 ) |
558 ) |
556 ) |
559 |
557 |
560 def contextMenuEvent(self, evt): |
558 @pyqtSlot(QPoint) |
561 """ |
559 def __showContextMenu(self, pos): |
562 Protected method called to create a context menu. |
560 """ |
563 |
561 Private slot to show a context menu. |
564 This method is overridden from QWebEngineView. |
562 |
565 |
563 @param pos position for the context menu |
566 @param evt reference to the context menu event object |
564 @type QPoint |
567 (QContextMenuEvent) |
|
568 """ |
|
569 pos = evt.pos() |
|
570 reason = evt.reason() |
|
571 QTimer.singleShot( |
|
572 0, functools.partial(self._contextMenuEvent, QContextMenuEvent(reason, pos)) |
|
573 ) |
|
574 # needs to be done this way because contextMenuEvent is blocking |
|
575 # the main loop |
|
576 |
|
577 def _contextMenuEvent(self, evt): |
|
578 """ |
|
579 Protected method called to create a context menu. |
|
580 |
|
581 @param evt reference to the context menu event object |
|
582 (QContextMenuEvent) |
|
583 """ |
565 """ |
584 self.__menu.clear() |
566 self.__menu.clear() |
585 |
567 |
586 hitTest = self.page().hitTestContent(evt.pos()) |
568 hitTest = self.page().hitTestContent(pos) |
587 |
569 |
588 self.__createContextMenu(self.__menu, hitTest) |
570 self.__createContextMenu(self.__menu, hitTest) |
589 |
571 |
590 if not hitTest.isContentEditable() and not hitTest.isContentSelected(): |
572 if not hitTest.isContentEditable() and not hitTest.isContentSelected(): |
591 self.__menu.addSeparator() |
573 self.__menu.addSeparator() |
597 self.tr("Inspect Element..."), |
579 self.tr("Inspect Element..."), |
598 self.__webInspector, |
580 self.__webInspector, |
599 ) |
581 ) |
600 |
582 |
601 if not self.__menu.isEmpty(): |
583 if not self.__menu.isEmpty(): |
602 pos = evt.globalPos() |
584 self.__menu.popup(self.mapToGlobal(pos)) |
603 self.__menu.popup(QPoint(pos.x(), pos.y() + 1)) |
|
604 |
585 |
605 def __createContextMenu(self, menu, hitTest): |
586 def __createContextMenu(self, menu, hitTest): |
606 """ |
587 """ |
607 Private method to populate the context menu. |
588 Private method to populate the context menu. |
608 |
589 |
2301 |
2282 |
2302 ########################################################################### |
2283 ########################################################################### |
2303 ## Methods below implement slots for Qt 5.11+ |
2284 ## Methods below implement slots for Qt 5.11+ |
2304 ########################################################################### |
2285 ########################################################################### |
2305 |
2286 |
|
2287 # deprecated with Qt 6.5+ |
2306 @pyqtSlot("QWebEngineQuotaRequest") |
2288 @pyqtSlot("QWebEngineQuotaRequest") |
2307 def __quotaRequested(self, quotaRequest): |
2289 def __quotaRequested(self, quotaRequest): |
2308 """ |
2290 """ |
2309 Private slot to handle quota requests of the web page. |
2291 Private slot to handle quota requests of the web page. |
2310 |
2292 |