eric6/Helpviewer/SiteInfo/SiteInfoDialog.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
diff -r f99d60d6b59b -r 2602857055c5 eric6/Helpviewer/SiteInfo/SiteInfoDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Helpviewer/SiteInfo/SiteInfoDialog.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,325 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show some information about a site.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import pyqtSlot, QUrl, Qt, QFile
+from PyQt5.QtGui import QPixmap, QCursor, QPainter, QColor, QBrush
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QGraphicsScene, QMenu, \
+    QApplication, QListWidgetItem
+from PyQt5.QtWebKit import QWebSettings
+
+from E5Gui import E5MessageBox, E5FileDialog
+
+try:
+    from .Ui_SiteInfoDialog import Ui_SiteInfoDialog       # __IGNORE_WARNING__
+    SSL = True
+except ImportError:
+    from .Ui_SiteInfoNoSslDialog import Ui_SiteInfoDialog  # __IGNORE_WARNING__
+    SSL = False
+
+from ..Download.DownloadUtilities import dataString
+
+import UI.PixmapCache
+from Globals import qVersionTuple
+
+
+class SiteInfoDialog(QDialog, Ui_SiteInfoDialog):
+    """
+    Class implementing a dialog to show some information about a site.
+    """
+    okStyle = "QLabel { color : white; background-color : green; }"
+    nokStyle = "QLabel { color : white; background-color : red; }"
+    
+    def __init__(self, browser, parent=None):
+        """
+        Constructor
+        
+        @param browser reference to the browser window (HelpBrowser)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(SiteInfoDialog, self).__init__(parent)
+        self.setupUi(self)
+        self.setWindowFlags(Qt.Window)
+        
+        # put icons
+        self.tabWidget.setTabIcon(
+            0, UI.PixmapCache.getIcon("siteinfo-general.png"))
+        self.tabWidget.setTabIcon(
+            1, UI.PixmapCache.getIcon("siteinfo-media.png"))
+        self.tabWidget.setTabIcon(
+            2, UI.PixmapCache.getIcon("siteinfo-databases.png"))
+        if SSL:
+            self.tabWidget.setTabIcon(
+                3, UI.PixmapCache.getIcon("siteinfo-security.png"))
+        
+        self.__mainFrame = browser.page().mainFrame()
+        self.__baseUrl = browser.url()
+        title = browser.title()
+        sslInfo = browser.page().getSslCertificateChain()
+        
+        #prepare background of image preview
+        self.__imagePreviewStandardBackground = \
+            self.imagePreview.backgroundBrush()
+        color1 = QColor(220, 220, 220)
+        color2 = QColor(160, 160, 160)
+        self.__tilePixmap = QPixmap(8, 8)
+        self.__tilePixmap.fill(color1)
+        tilePainter = QPainter(self.__tilePixmap)
+        tilePainter.fillRect(0, 0, 4, 4, color2)
+        tilePainter.fillRect(4, 4, 4, 4, color2)
+        tilePainter.end()
+        
+        # populate General tab
+        self.heading.setText("<b>{0}</b>".format(title))
+        self.siteAddressLabel.setText(self.__mainFrame.baseUrl().toString())
+        self.sizeLabel.setText(dataString(browser.page().totalBytes()))
+        encoding = ""
+        
+        # populate Meta tags
+        meta = self.__mainFrame.findAllElements("meta")
+        for element in meta:
+            content = element.attribute("content")
+            name = element.attribute("name")
+            if not name:
+                name = element.attribute("http-equiv")
+            if element.attribute("charset"):
+                encoding = element.attribute("charset")
+            if "charset=" in content:
+                encoding = content[content.index("charset=") + 8:]
+            
+            if not content or not name:
+                continue
+            
+            QTreeWidgetItem(self.tagsTree, [name, content])
+        for col in range(self.tagsTree.columnCount()):
+            self.tagsTree.resizeColumnToContents(col)
+        
+        if not encoding:
+            encoding = QWebSettings.globalSettings().defaultTextEncoding()
+        self.encodingLabel.setText(encoding)
+        
+        # populate the Security info and the Security tab
+        if sslInfo and \
+           ((qVersionTuple() >= (5, 0, 0) and
+             not sslInfo[0].isBlacklisted()) or
+                (qVersionTuple() < (5, 0, 0) and sslInfo[0].isValid())):
+            self.securityLabel.setStyleSheet(SiteInfoDialog.okStyle)
+            self.securityLabel.setText('<b>Connection is encrypted.</b>')
+            if SSL:
+                self.sslWidget.showCertificateChain(sslInfo)
+                self.securityDetailsButton.setEnabled(True)
+            else:
+                self.securityDetailsButton.setEnabled(False)
+        else:
+            self.securityLabel.setStyleSheet(SiteInfoDialog.nokStyle)
+            self.securityLabel.setText('<b>Connection is not encrypted.</b>')
+            self.securityDetailsButton.setEnabled(False)
+            self.tabWidget.setTabEnabled(
+                self.tabWidget.indexOf(self.securityTab), False)
+        
+        # populate Media tab
+        images = self.__mainFrame.findAllElements("img")
+        for element in images:
+            src = element.attribute("src")
+            alt = element.attribute("alt")
+            if src and src.startswith("data:"):
+                continue
+            if not alt:
+                if src.find("/") == -1:
+                    alt = src
+                else:
+                    pos = src.find("/")
+                    alt = src[pos + 1:]
+            
+            if not src or not alt:
+                continue
+            
+            QTreeWidgetItem(self.imagesTree, [alt, src])
+        for col in range(self.imagesTree.columnCount()):
+            self.imagesTree.resizeColumnToContents(col)
+        if self.imagesTree.columnWidth(0) > 300:
+            self.imagesTree.setColumnWidth(0, 300)
+        self.imagesTree.setCurrentItem(self.imagesTree.topLevelItem(0))
+        self.imagesTree.setContextMenuPolicy(Qt.CustomContextMenu)
+        self.imagesTree.customContextMenuRequested.connect(
+            self.__imagesTreeContextMenuRequested)
+        
+        # populate the Databases tab
+        databases = self.__mainFrame.securityOrigin().databases()
+        counter = 0
+        for database in databases:
+            itm = QListWidgetItem(self.databasesList)
+            itm.setText(database.displayName())
+            itm.setData(Qt.UserRole, counter)
+            counter += 1
+        
+        if counter == 0:
+            itm = QListWidgetItem(self.databasesList)
+            itm.setText(self.tr("No databases are used by this page."))
+            itm.setFlags(itm.flags() & Qt.ItemIsSelectable)
+    
+    @pyqtSlot()
+    def on_securityDetailsButton_clicked(self):
+        """
+        Private slot to show security details.
+        """
+        self.tabWidget.setCurrentIndex(
+            self.tabWidget.indexOf(self.securityTab))
+    
+    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
+    def on_imagesTree_currentItemChanged(self, current, previous):
+        """
+        Private slot to show a preview of the selected image.
+        
+        @param current current image entry (QTreeWidgetItem)
+        @param previous old current entry (QTreeWidgetItem)
+        """
+        if current is None:
+            return
+        
+        imageUrl = QUrl(current.text(1))
+        if imageUrl.isRelative():
+            imageUrl = self.__baseUrl.resolved(imageUrl)
+        
+        import Helpviewer.HelpWindow
+        cache = Helpviewer.HelpWindow.HelpWindow.networkAccessManager().cache()
+        if cache:
+            cacheData = cache.data(imageUrl)
+        else:
+            cacheData = None
+        pixmap = QPixmap()
+        invalidPixmap = False
+        scene = QGraphicsScene(self.imagePreview)
+        if not cacheData:
+            invalidPixmap = True
+        else:
+            pixmap.loadFromData(cacheData.readAll())
+            if pixmap.isNull():
+                invalidPixmap = True
+        if invalidPixmap:
+            self.imagePreview.setBackgroundBrush(
+                self.__imagePreviewStandardBackground)
+            scene.addText(self.tr("Preview not available."))
+        else:
+            self.imagePreview.setBackgroundBrush(QBrush(self.__tilePixmap))
+            scene.addPixmap(pixmap)
+        self.imagePreview.setScene(scene)
+    
+    def __imagesTreeContextMenuRequested(self, pos):
+        """
+        Private slot to show a context menu for the images list.
+        
+        @param pos position for the menu (QPoint)
+        """
+        itm = self.imagesTree.itemAt(pos)
+        if itm is None:
+            return
+        
+        menu = QMenu()
+        act = menu.addAction(self.tr("Copy Image Location to Clipboard"))
+        act.setData(itm.text(1))
+        act.triggered.connect(lambda: self.__copyAction(act))
+        act = menu.addAction(self.tr("Copy Image Name to Clipboard"))
+        act.setData(itm.text(0))
+        act.triggered.connect(lambda: self.__copyAction(act))
+        menu.addSeparator()
+        act = menu.addAction(self.tr("Save Image"))
+        act.setData(self.imagesTree.indexOfTopLevelItem(itm))
+        act.triggered.connect(lambda: self.__saveImage(act))
+        menu.exec_(QCursor.pos())
+    
+    def __copyAction(self, act):
+        """
+        Private slot to copy the image URL or the image name to the clipboard.
+        
+        @param act reference to the action that triggered
+        @type QAction
+        """
+        QApplication.clipboard().setText(act.data())
+    
+    def __saveImage(self, act):
+        """
+        Private slot to save the selected image to disk.
+        
+        @param act reference to the action that triggered
+        @type QAction
+        """
+        index = act.data()
+        itm = self.imagesTree.topLevelItem(index)
+        if itm is None:
+            return
+        
+        imageUrl = QUrl(itm.text(1))
+        if not imageUrl.host():
+            imageUrl.setHost(QUrl(self.siteAddressLabel.text()).host())
+            imageUrl.setScheme(QUrl(self.siteAddressLabel.text()).scheme())
+        
+        import Helpviewer.HelpWindow
+        cache = Helpviewer.HelpWindow.HelpWindow.networkAccessManager().cache()
+        if cache:
+            cacheData = cache.data(imageUrl)
+        else:
+            cacheData = None
+        if not cacheData:
+            E5MessageBox.critical(
+                self,
+                self.tr("Save Image"),
+                self.tr("""This image is not available."""))
+            return
+        
+        downloadDirectory = Helpviewer.HelpWindow.HelpWindow\
+            .downloadManager().downloadDirectory()
+        fn = os.path.join(downloadDirectory, os.path.basename(itm.text(1)))
+        filename = E5FileDialog.getSaveFileName(
+            self,
+            self.tr("Save Image"),
+            fn,
+            self.tr("All Files (*)"),
+            E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
+        
+        if not filename:
+            return
+        
+        f = QFile(filename)
+        if not f.open(QFile.WriteOnly):
+            E5MessageBox.critical(
+                self,
+                self.tr("Save Image"),
+                self.tr(
+                    """<p>Cannot write to file <b>{0}</b>.</p>""")
+                .format(filename))
+            return
+        f.write(cacheData.readAll())
+        f.close()
+    
+    @pyqtSlot(QListWidgetItem, QListWidgetItem)
+    def on_databasesList_currentItemChanged(self, current, previous):
+        """
+        Private slot to show data about the selected database.
+        
+        @param current current database entry (QTreeWidgetItem)
+        @param previous old current entry (QTreeWidgetItem)
+        """
+        if current is None:
+            return
+        
+        dbId = current.data(Qt.UserRole)
+        databases = self.__mainFrame.securityOrigin().databases()
+        
+        if dbId >= len(databases):
+            return
+        
+        db = databases[dbId]
+        self.databaseName.setText(
+            "{0} ({1})".format(db.displayName(), db.name()))
+        self.databasePath.setText(db.fileName())
+        self.databaseSize.setText(dataString(db.size()))

eric ide

mercurial