WebBrowser/SiteInfo/SiteInfoDialog.py

branch
QtWebEngine
changeset 4783
7de17766a5df
parent 4631
5c1a96925da4
child 4917
682750cc7bd5
equal deleted inserted replaced
4782:4ad656e4ebec 4783:7de17766a5df
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show some information about a site.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import pyqtSlot, QUrl, Qt
13 from PyQt5.QtGui import QPixmap, QImage
14 from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
15 from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QGraphicsScene, QMenu, \
16 QApplication, QGraphicsPixmapItem
17
18 from E5Gui import E5MessageBox, E5FileDialog
19
20 from .Ui_SiteInfoDialog import Ui_SiteInfoDialog
21
22 from ..Tools import Scripts, WebBrowserTools
23
24 import UI.PixmapCache
25
26
27 class SiteInfoDialog(QDialog, Ui_SiteInfoDialog):
28 """
29 Class implementing a dialog to show some information about a site.
30 """
31 okStyle = "QLabel { color : white; background-color : green; }"
32 nokStyle = "QLabel { color : white; background-color : red; }"
33
34 def __init__(self, browser, parent=None):
35 """
36 Constructor
37
38 @param browser reference to the browser window (HelpBrowser)
39 @param parent reference to the parent widget (QWidget)
40 """
41 super(SiteInfoDialog, self).__init__(parent)
42 self.setupUi(self)
43 self.setWindowFlags(Qt.Window)
44
45 # put icons
46 self.tabWidget.setTabIcon(
47 0, UI.PixmapCache.getIcon("siteinfo-general.png"))
48 self.tabWidget.setTabIcon(
49 1, UI.PixmapCache.getIcon("siteinfo-media.png"))
50
51 self.__imageReply = None
52
53 self.__baseUrl = browser.url()
54 title = browser.title()
55
56 # populate General tab
57 self.heading.setText("<b>{0}</b>".format(title))
58 self.siteAddressLabel.setText(self.__baseUrl.toString())
59 if self.__baseUrl.scheme() in ["https"]:
60 self.securityLabel.setStyleSheet(SiteInfoDialog.okStyle)
61 self.securityLabel.setText('<b>Connection is encrypted.</b>')
62 else:
63 self.securityLabel.setStyleSheet(SiteInfoDialog.nokStyle)
64 self.securityLabel.setText('<b>Connection is not encrypted.</b>')
65 browser.page().runJavaScript(
66 "document.charset",
67 lambda res: self.encodingLabel.setText(res))
68
69 # populate Meta tags
70 browser.page().runJavaScript(Scripts.getAllMetaAttributes(),
71 self.__processMetaAttributes)
72
73 # populate Media tab
74 browser.page().runJavaScript(Scripts.getAllImages(),
75 self.__processImageTags)
76
77 def __processImageTags(self, res):
78 """
79 Private method to process the image tags.
80
81 @param res result of the JavaScript script
82 @type list of dict
83 """
84 for img in res:
85 src = img["src"]
86 alt = img["alt"]
87 if not alt:
88 if src.find("/") == -1:
89 alt = src
90 else:
91 pos = src.rfind("/")
92 alt = src[pos + 1:]
93
94 if not src or not alt:
95 continue
96
97 QTreeWidgetItem(self.imagesTree, [alt, src])
98
99 for col in range(self.imagesTree.columnCount()):
100 self.imagesTree.resizeColumnToContents(col)
101 if self.imagesTree.columnWidth(0) > 300:
102 self.imagesTree.setColumnWidth(0, 300)
103 self.imagesTree.setCurrentItem(self.imagesTree.topLevelItem(0))
104 self.imagesTree.setContextMenuPolicy(Qt.CustomContextMenu)
105 self.imagesTree.customContextMenuRequested.connect(
106 self.__imagesTreeContextMenuRequested)
107
108 def __processMetaAttributes(self, res):
109 """
110 Private method to process the meta attributes.
111
112 @param res result of the JavaScript script
113 @type list of dict
114 """
115 for meta in res:
116 content = meta["content"]
117 name = meta["name"]
118 if not name:
119 name = meta["httpequiv"]
120
121 if not name or not content:
122 continue
123
124 if meta["charset"]:
125 self.encodingLabel.setText(meta["charset"])
126 if "charset=" in content:
127 self.encodingLabel.setText(
128 content[content.index("charset=") + 8:])
129
130 QTreeWidgetItem(self.tagsTree, [name, content])
131 for col in range(self.tagsTree.columnCount()):
132 self.tagsTree.resizeColumnToContents(col)
133
134 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
135 def on_imagesTree_currentItemChanged(self, current, previous):
136 """
137 Private slot to show a preview of the selected image.
138
139 @param current current image entry (QTreeWidgetItem)
140 @param previous old current entry (QTreeWidgetItem)
141 """
142 if current is None:
143 return
144
145 imageUrl = QUrl(current.text(1))
146 if imageUrl.isRelative():
147 imageUrl = self.__baseUrl.resolved(imageUrl)
148
149 pixmap = QPixmap()
150 loading = False
151
152 if imageUrl.scheme() == "data":
153 encodedUrl = current.text(1).encode("utf-8")
154 imageData = encodedUrl[encodedUrl.find(",") + 1:]
155 pixmap = WebBrowserTools.pixmapFromByteArray(imageData)
156 elif imageUrl.scheme() == "file":
157 pixmap = QPixmap(imageUrl.toLocalFile())
158 elif imageUrl.scheme() == "qrc":
159 pixmap = QPixmap(imageUrl.toString()[3:])
160 else:
161 if self.__imageReply is not None:
162 self.__imageReply.deleteLater()
163 self.__imageReply = None
164
165 from WebBrowser.WebBrowserWindow import WebBrowserWindow
166 self.__imageReply = WebBrowserWindow.networkManager().get(
167 QNetworkRequest(imageUrl))
168 self.__imageReply.finished.connect(self.__imageReplyFinished)
169 loading = True
170 self.__showLoadingText()
171
172 if not loading:
173 self.__showPixmap(pixmap)
174
175 @pyqtSlot()
176 def __imageReplyFinished(self):
177 """
178 Private slot handling the loading of an image.
179 """
180 if self.__imageReply.error() != QNetworkReply.NoError:
181 return
182
183 data = self.__imageReply.readAll()
184 self.__showPixmap(QPixmap.fromImage(QImage.fromData(data)))
185
186 def __showPixmap(self, pixmap):
187 """
188 Private method to show a pixmap in the preview pane.
189
190 @param pixmap pixmap to be shown
191 @type QPixmap
192 """
193 scene = QGraphicsScene(self.imagePreview)
194 if pixmap.isNull():
195 scene.addText(self.tr("Preview not available."))
196 else:
197 scene.addPixmap(pixmap)
198 self.imagePreview.setScene(scene)
199
200 def __showLoadingText(self):
201 """
202 Private method to show some text while loading an image.
203 """
204 scene = QGraphicsScene(self.imagePreview)
205 scene.addText(self.tr("Loading..."))
206 self.imagePreview.setScene(scene)
207
208 def __imagesTreeContextMenuRequested(self, pos):
209 """
210 Private slot to show a context menu for the images list.
211
212 @param pos position for the menu (QPoint)
213 """
214 itm = self.imagesTree.itemAt(pos)
215 if itm is None:
216 return
217
218 menu = QMenu()
219 menu.addAction(
220 self.tr("Copy Image Location to Clipboard"),
221 self.__copyAction).setData(itm.text(1))
222 menu.addAction(
223 self.tr("Copy Image Name to Clipboard"),
224 self.__copyAction).setData(itm.text(0))
225 menu.addSeparator()
226 menu.addAction(
227 self.tr("Save Image"),
228 self.__saveImage).setData(self.imagesTree.indexOfTopLevelItem(itm))
229 menu.exec_(self.imagesTree.viewport().mapToGlobal(pos))
230
231 def __copyAction(self):
232 """
233 Private slot to copy the image URL or the image name to the clipboard.
234 """
235 act = self.sender()
236 QApplication.clipboard().setText(act.data())
237
238 def __saveImage(self):
239 """
240 Private slot to save the selected image to disk.
241 """
242 act = self.sender()
243 index = act.data()
244 itm = self.imagesTree.topLevelItem(index)
245 if itm is None:
246 return
247
248 if not self.imagePreview.scene() or \
249 len(self.imagePreview.scene().items()) == 0:
250 return
251
252 pixmapItem = self.imagePreview.scene().items()[0]
253 if not isinstance(pixmapItem, QGraphicsPixmapItem):
254 return
255
256 if pixmapItem.pixmap().isNull():
257 E5MessageBox.warning(
258 self,
259 self.tr("Save Image"),
260 self.tr(
261 """<p>This preview is not available.</p>"""))
262 return
263
264 imageFileName = WebBrowserTools.getFileNameFromUrl(QUrl(itm.text(1)))
265 index = imageFileName.rfind(".")
266 if index != -1:
267 imageFileName = imageFileName[:index] + ".png"
268
269 filename = E5FileDialog.getSaveFileName(
270 self,
271 self.tr("Save Image"),
272 imageFileName,
273 self.tr("All Files (*)"),
274 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
275
276 if not filename:
277 return
278
279 if not pixmapItem.pixmap().save(filename, "PNG"):
280 E5MessageBox.critical(
281 self,
282 self.tr("Save Image"),
283 self.tr(
284 """<p>Cannot write to file <b>{0}</b>.</p>""")
285 .format(filename))
286 return

eric ide

mercurial