Sun, 29 Jul 2012 18:05:03 +0200
Fixed some PEP-8 related issues.
# -*- coding: utf-8 -*- # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the Flash blocker. """ from PyQt4.QtCore import pyqtSlot, QUrl, Qt, QByteArray, QTimer from PyQt4.QtGui import QWidget, QMenu, QCursor, QDialog, QLabel, QFormLayout from PyQt4.QtNetwork import QNetworkRequest from PyQt4.QtWebKit import QWebHitTestResult, QWebElement, QWebView, QWebElementCollection from .Ui_ClickToFlash import Ui_ClickToFlash import UI.PixmapCache import Helpviewer.HelpWindow class ClickToFlash(QWidget, Ui_ClickToFlash): """ Class implementing the Flash blocker. """ _acceptedUrl = QUrl() _acceptedArgNames = [] _acceptedArgValues = [] def __init__(self, plugin, mimeType, url, argumentNames, argumentValues, parent=None): """ Constructor @param plugin reference to the plug-in (ClickToFlashPlugin) @param mimeType MIME type for the plug-in (string) @param url requested URL (QUrl) @param argumentNames list of argument names (list of strings) @param argumentValues list of argument values (list of strings) @param parent reference to the parent widget (QWidget) """ super().__init__(parent) # Check AdBlock first manager = Helpviewer.HelpWindow.HelpWindow.adblockManager() if manager.isEnabled(): urlString = bytes(url.toEncoded()).decode() urlDomain = url.host() for subscription in manager.subscriptions(): blockedRule = subscription.match( QNetworkRequest(url), urlDomain, urlString) if blockedRule: QTimer.singleShot(200, self.__hideAdBlocked) return self.setupUi(self) self.__swapping = False self.__element = QWebElement() self.__plugin = plugin self.__url = QUrl(url) self.__argumentNames = argumentNames[:] self.__argumentValues = argumentValues[:] self.__mimeType = mimeType self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.__showContextMenu) self.setToolTip(self.__url.toString()) iconName = plugin.getIconName(mimeType) if iconName: self.loadFlashButton.setIcon(UI.PixmapCache.getIcon(iconName)) else: self.loadFlashButton.setText(self.trUtf8("Load")) @pyqtSlot() def on_loadFlashButton_clicked(self): """ Private slot handling the flash activation. """ self.__load() def __showContextMenu(self): """ Private slot to show the context menu. """ menu = QMenu() act = menu.addAction(self.trUtf8("Object blocked by ClickToFlash")) font = act.font() font.setBold(True) act.setFont(font) menu.addAction(self.trUtf8("Show information about object"), self.__showInfo) menu.addSeparator() menu.addAction(self.trUtf8("Load"), self.__load) menu.addAction(self.trUtf8("Delete object"), self.__hideAdBlocked) menu.addSeparator() host = self.__url.host() add = menu.addAction(self.trUtf8("Add '{0}' to Whitelist".format(host)), self.__addToWhitelist) remove = menu.addAction(self.trUtf8("Remove '{0}' from Whitelist".format(host)), self.__removeFromWhitelist) onWhitelist = self.__plugin.onWhitelist(host) add.setEnabled(not onWhitelist) remove.setEnabled(onWhitelist) menu.addSeparator() menu.addAction(self.trUtf8("Configure Whitelist"), self.__configure) menu.actions()[0].setEnabled(False) menu.exec_(QCursor.pos()) def swapping(self): """ Public method to check, if the plug-in is swapping. @return flag indicating the swapping status (boolean) """ return self.__swapping def __configure(self): """ Private slot to configure the whitelist. """ self.__plugin.configure() def __addToWhitelist(self): """ Private slot to add the host to the whitelist. """ self.__plugin.addToWhitelist(self.__url.host()) def __removeFromWhitelist(self): """ Private slot to remove the host from the whitelist. """ self.__plugin.removeFromWhitelist(self.__url.host()) def __load(self, all=False): """ Private slot to load the flash content. @param all flag indicating to load all flash players. (boolean) """ self.__findElement() if not self.__element.isNull(): substitute = self.__element.clone() substitute.setAttribute("type", self.__mimeType) self.__element.replace(substitute) ClickToFlash._acceptedUrl = self.__url ClickToFlash._acceptedArgNames = self.__argumentNames ClickToFlash._acceptedArgValues = self.__argumentValues def __findElement(self): """ Private method to find the element belonging to this ClickToFlash instance. """ parent = self.parentWidget() view = None while parent is not None: if isinstance(parent, QWebView): view = parent break parent = parent.parentWidget() if view is None: return objectPos = view.mapFromGlobal(self.loadFlashButton.mapToGlobal( self.loadFlashButton.pos())) objectFrame = view.page().frameAt(objectPos) hitResult = QWebHitTestResult() hitElement = QWebElement() if objectFrame is not None: hitResult = objectFrame.hitTestContent(objectPos) hitElement = hitResult.element() if not hitElement.isNull() and \ hitElement.tagName().lower() in ["embed", "object"]: self.__element = hitElement return # hit test failed, trying to find element by src # attribute in elements of all frames on page (although less accurate frames = [] frames.append(view.page().mainFrame()) while frames: frame = frames.pop(0) if not frame: continue docElement = frame.documentElement() elements = QWebElementCollection() elements.append(docElement.findAll("embed")) elements.append(docElement.findAll("object")) for element in elements: if not self.__checkElement(element) and \ not self.__checkUrlOnElement(element, view): continue self.__element = element return frames.extend(frame.childFrames()) def __checkUrlOnElement(self, element, view): """ Private slot to check the URL of an element. @param element reference to the element to check (QWebElement) @param view reference to the view object (QWebView) @return flag indicating a positive result (boolean) """ checkString = element.attribute("src") if checkString == "": checkString = element.attribute("data") if checkString == "": checkString = element.attribute("value") checkString = view.url().resolved(QUrl(checkString)).toString(QUrl.RemoveQuery) return self.__url.toEncoded().contains(QByteArray(checkString.encode("utf-8"))) def __checkElement(self, element): """ Private slot to check an element against the saved arguments. @param element reference to the element to check (QWebElement) @return flag indicating a positive result (boolean) """ if self.__argumentNames == element.attributeNames(): for name in self.__argumentNames: if element.attribute(name) not in self.__argumentValues: return False return True return False def __hideAdBlocked(self): """ Private slot to hide the object. """ self.__findElement() if not self.__element.isNull(): self.__element.setStyleProperty("display", "none") else: self.hide() def __showInfo(self): """ Private slot to show information about the blocked object. """ dlg = QDialog() dlg.setWindowTitle(self.trUtf8("Flash Object")) dlg.setSizeGripEnabled(True) layout = QFormLayout(dlg) layout.addRow(QLabel(self.trUtf8("<b>Attribute Name</b>")), QLabel(self.trUtf8("<b>Value</b>"))) index = 0 for name in self.__argumentNames: nameLabel = QLabel(self.__elide(name, length=30)) value = self.__argumentValues[index] valueLabel = QLabel(self.__elide(value, length=60)) valueLabel.setTextInteractionFlags( Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse) layout.addRow(nameLabel, valueLabel) index += 1 if index == 0: layout.addRow(QLabel(self.trUtf8("No information available."))) dlg.setMaximumHeight(500) dlg.setMaximumWidth(500) dlg.exec_() def __elide(self, txt, mode=Qt.ElideMiddle, length=40): """ Private method to elide some text. @param txt text to be elided (string) @keyparam mode elide mode (Qt.TextElideMode) @keyparam length amount of characters to be used (integer) @return the elided text (string) """ if mode == Qt.ElideNone or len(txt) < length: return txt elif mode == Qt.ElideLeft: return "...{0}".format(txt[-length:]) elif mode == Qt.ElideMiddle: return "{0}...{1}".format(txt[:length // 2], txt[-(length // 2):]) elif mode == Qt.ElideRight: return "{0}...".format(txt[:length]) else: # just in case return txt @classmethod def isAlreadyAccepted(cls, url, argumentNames, argumentValues): """ Class method to check, if the given parameter combination is being accepted. @param url URL to be checked for (QUrl) @param argumentNames argument names to be checked for (list of strings) @param argumentValues argument values to be checked for (list of strings) """ return url == cls._acceptedUrl and \ argumentNames == cls._acceptedArgNames and \ argumentValues == cls._acceptedArgValues