|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to show some information about a site. |
|
8 """ |
|
9 |
|
10 import os |
|
11 |
|
12 from PyQt4.QtCore import pyqtSlot, QUrl, Qt, QFile |
|
13 from PyQt4.QtGui import QDialog, QTreeWidgetItem, QPixmap, QGraphicsScene, QMenu, \ |
|
14 QCursor, QApplication, QFileDialog |
|
15 from PyQt4.QtWebKit import QWebSettings |
|
16 |
|
17 from E5Gui import E5MessageBox, E5FileDialog |
|
18 |
|
19 from .Ui_SiteInfoDialog import Ui_SiteInfoDialog |
|
20 |
|
21 from ..Download.DownloadUtilities import dataString |
|
22 |
|
23 import Helpviewer.HelpWindow |
|
24 |
|
25 import UI.PixmapCache |
|
26 |
|
27 |
|
28 class SiteInfoDialog(QDialog, Ui_SiteInfoDialog): |
|
29 """ |
|
30 Class implementing a dialog to show some information about a site. |
|
31 """ |
|
32 okStyle = "QLabel { color : white; background-color : green; }" |
|
33 nokStyle = "QLabel { color : white; background-color : red; }" |
|
34 |
|
35 def __init__(self, browser, parent=None): |
|
36 """ |
|
37 Constructor |
|
38 |
|
39 @param browser reference to the browser window (HelpBrowser) |
|
40 @param parent reference to the parent widget (QWidget) |
|
41 """ |
|
42 super().__init__(parent) |
|
43 self.setupUi(self) |
|
44 |
|
45 # put icons |
|
46 self.tabWidget.setTabIcon(0, UI.PixmapCache.getIcon("siteinfo-general.png")) |
|
47 self.tabWidget.setTabIcon(1, UI.PixmapCache.getIcon("siteinfo-media.png")) |
|
48 self.tabWidget.setTabIcon(2, UI.PixmapCache.getIcon("siteinfo-security.png")) |
|
49 |
|
50 frame = browser.page().mainFrame() |
|
51 title = browser.title() |
|
52 sslInfo = browser.page().getSslInfo() |
|
53 |
|
54 # populate General tab |
|
55 self.heading.setText("<b>{0}</b>".format(title)) |
|
56 self.siteAddressLabel.setText(frame.baseUrl().toString()) |
|
57 self.sizeLabel.setText(dataString(browser.page().totalBytes())) |
|
58 encoding = "" |
|
59 |
|
60 # populate Meta tags |
|
61 meta = frame.findAllElements("meta") |
|
62 for element in meta: |
|
63 content = element.attribute("content") |
|
64 name = element.attribute("name") |
|
65 if not name: |
|
66 name = element.attribute("http-equiv") |
|
67 if element.attribute("charset"): |
|
68 encoding = element.attribute("charset") |
|
69 if "charset=" in content: |
|
70 encoding = content[content.index("charset=") + 8:] |
|
71 |
|
72 if not content or not name: |
|
73 continue |
|
74 |
|
75 QTreeWidgetItem(self.tagsTree, [name, content]) |
|
76 for col in range(self.tagsTree.columnCount()): |
|
77 self.tagsTree.resizeColumnToContents(col) |
|
78 |
|
79 if not encoding: |
|
80 encoding = QWebSettings.globalSettings().defaultTextEncoding() |
|
81 self.encodingLabel.setText(encoding) |
|
82 |
|
83 # populate the Security info and the Security tab |
|
84 if sslInfo is not None and sslInfo.isValid(): |
|
85 self.securityLabel.setStyleSheet(SiteInfoDialog.okStyle) |
|
86 self.securityLabel.setText('<b>Connection is encrypted.</b>') |
|
87 self.sslWidget.showCertificate(sslInfo) |
|
88 self.securityDetailsButton.setEnabled(True) |
|
89 else: |
|
90 self.securityLabel.setStyleSheet(SiteInfoDialog.nokStyle) |
|
91 self.securityLabel.setText('<b>Connection is not encrypted.</b>') |
|
92 self.securityDetailsButton.setEnabled(False) |
|
93 |
|
94 # populate Media tab |
|
95 images = frame.findAllElements("img") |
|
96 for element in images: |
|
97 src = element.attribute("src") |
|
98 alt = element.attribute("alt") |
|
99 if src and src.startswith("data:"): |
|
100 continue |
|
101 if not alt: |
|
102 if src.find("/") == -1: |
|
103 alt = src |
|
104 else: |
|
105 pos = src.find("/") |
|
106 alt = src[pos + 1:] |
|
107 |
|
108 if not src or not alt: |
|
109 continue |
|
110 |
|
111 QTreeWidgetItem(self.imagesTree, [alt, src]) |
|
112 for col in range(self.imagesTree.columnCount()): |
|
113 self.imagesTree.resizeColumnToContents(col) |
|
114 if self.imagesTree.columnWidth(0) > 300: |
|
115 self.imagesTree.setColumnWidth(0, 300) |
|
116 self.imagesTree.setCurrentItem(self.imagesTree.topLevelItem(0)) |
|
117 self.imagesTree.setContextMenuPolicy(Qt.CustomContextMenu) |
|
118 self.imagesTree.customContextMenuRequested.connect( |
|
119 self.__imagesTreeContextMenuRequested) |
|
120 |
|
121 @pyqtSlot() |
|
122 def on_securityDetailsButton_clicked(self): |
|
123 """ |
|
124 Private slot to show security details. |
|
125 """ |
|
126 self.tabWidget.setCurrentIndex(2) |
|
127 |
|
128 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
|
129 def on_imagesTree_currentItemChanged(self, current, previous): |
|
130 """ |
|
131 Private slot to show a preview of the selected image. |
|
132 |
|
133 @param current current image entry (QTreeWidgetItem) |
|
134 @param previous old current entry (QTreeWidgetItem) |
|
135 """ |
|
136 if current is None: |
|
137 return |
|
138 |
|
139 imageUrl = QUrl(current.text(1)) |
|
140 if not imageUrl.host(): |
|
141 imageUrl.setHost(QUrl(self.siteAddressLabel.text()).host()) |
|
142 imageUrl.setScheme(QUrl(self.siteAddressLabel.text()).scheme()) |
|
143 |
|
144 cache = Helpviewer.HelpWindow.HelpWindow.networkAccessManager().cache() |
|
145 cacheData = cache.data(imageUrl) |
|
146 pixmap = QPixmap() |
|
147 invalidPixmap = False |
|
148 scene = QGraphicsScene(self.imagePreview) |
|
149 if not cacheData: |
|
150 invalidPixmap = True |
|
151 else: |
|
152 pixmap.loadFromData(cacheData.readAll()) |
|
153 if pixmap.isNull(): |
|
154 invalidPixmap = True |
|
155 if invalidPixmap: |
|
156 scene.addText(self.trUtf8("Preview not available.")) |
|
157 else: |
|
158 scene.addPixmap(pixmap) |
|
159 self.imagePreview.setScene(scene) |
|
160 |
|
161 def __imagesTreeContextMenuRequested(self, pos): |
|
162 """ |
|
163 Private slot to show a context menu for the images list. |
|
164 |
|
165 @param pos position for the menu (QPoint) |
|
166 """ |
|
167 itm = self.imagesTree.itemAt(pos) |
|
168 if itm is None: |
|
169 return |
|
170 |
|
171 menu = QMenu() |
|
172 act = menu.addAction(self.trUtf8("Copy Image Location to Clipboard"), |
|
173 self.__copyAction) |
|
174 act.setData(itm.text(1)) |
|
175 act = menu.addAction(self.trUtf8("Copy Image Name to Clipboard"), |
|
176 self.__copyAction) |
|
177 act.setData(itm.text(0)) |
|
178 menu.addSeparator() |
|
179 act = menu.addAction(self.trUtf8("Save Image"), self.__saveImage) |
|
180 act.setData(self.imagesTree.indexOfTopLevelItem(itm)) |
|
181 menu.exec_(QCursor.pos()) |
|
182 |
|
183 def __copyAction(self): |
|
184 """ |
|
185 Private slot to copy the image URL or the image name to the clipboard. |
|
186 """ |
|
187 act = self.sender() |
|
188 QApplication.clipboard().setText(act.data()) |
|
189 |
|
190 def __saveImage(self): |
|
191 """ |
|
192 Private slot to save the selected image to disk. |
|
193 """ |
|
194 act = self.sender() |
|
195 index = act.data() |
|
196 itm = self.imagesTree.topLevelItem(index) |
|
197 if itm is None: |
|
198 return |
|
199 |
|
200 imageUrl = QUrl(itm.text(1)) |
|
201 if not imageUrl.host(): |
|
202 imageUrl.setHost(QUrl(self.siteAddressLabel.text()).host()) |
|
203 imageUrl.setScheme(QUrl(self.siteAddressLabel.text()).scheme()) |
|
204 |
|
205 cache = Helpviewer.HelpWindow.HelpWindow.networkAccessManager().cache() |
|
206 cacheData = cache.data(imageUrl) |
|
207 if not cacheData: |
|
208 E5MessageBox.critical(self, |
|
209 self.trUtf8("Save Image"), |
|
210 self.trUtf8("""This image is not available.""")) |
|
211 return |
|
212 |
|
213 downloadDirectory = Helpviewer.HelpWindow.HelpWindow\ |
|
214 .downloadManager().downloadDirectory() |
|
215 fn = os.path.join(downloadDirectory, os.path.basename(itm.text(1))) |
|
216 filename = E5FileDialog.getSaveFileName( |
|
217 self, |
|
218 self.trUtf8("Save Image"), |
|
219 fn, |
|
220 self.trUtf8("All Files (*)"), |
|
221 QFileDialog.Options(QFileDialog.DontConfirmOverwrite)) |
|
222 |
|
223 if not filename: |
|
224 return |
|
225 |
|
226 f = QFile(filename) |
|
227 if not f.open(QFile.WriteOnly): |
|
228 E5MessageBox.critical(self, |
|
229 self.trUtf8("Save Image"), |
|
230 self.trUtf8( |
|
231 """<p>Cannot write to file <b>{0}</b>.</p>""".format(filename))) |
|
232 return |
|
233 f.write(cacheData.readAll()) |
|
234 f.close() |