PyBitmessage/src/bitmessageqt/messageview.py

136 lines
6.0 KiB
Python

from PyQt4 import QtCore, QtGui
from urlparse import urlparse
from safehtmlparser import *
class MessageView(QtGui.QTextBrowser):
MODE_PLAIN = 0
MODE_HTML = 1
TEXT_PLAIN = "HTML detected, click here to display"
TEXT_HTML = "Click here to disable HTML"
CONFIRM_TITLE = "Follow external link"
CONFIRM_TEXT = "The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you or download malicious data. Are you sure?"
def __init__(self, parent = 0):
super(MessageView, self).__init__(parent)
self.mode = MessageView.MODE_PLAIN
self.html = None
self.setOpenExternalLinks(False)
self.setOpenLinks(False)
self.anchorClicked.connect(self.confirmURL)
self.out = ""
self.outpos = 0
self.document().setUndoRedoEnabled(False)
self.rendering = False
self.defaultFontPointSize = self.currentFont().pointSize()
self.verticalScrollBar().valueChanged.connect(self.lazyRender)
self.setWrappingWidth()
def resizeEvent(self, event):
super(MessageView, self).resizeEvent(event)
self.setWrappingWidth(event.size().width())
def mousePressEvent(self, event):
#text = textCursor.block().text()
if event.button() == QtCore.Qt.LeftButton and self.html and self.html.has_html and self.cursorForPosition(event.pos()).block().blockNumber() == 0:
if self.mode == MessageView.MODE_PLAIN:
self.showHTML()
else:
self.showPlain()
else:
super(MessageView, self).mousePressEvent(event)
def wheelEvent(self, event):
# super will actually automatically take care of zooming
super(MessageView, self).wheelEvent(event)
if (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical:
zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize
QtGui.QApplication.activeWindow().statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg(str(zoom)))
def setWrappingWidth(self, width=None):
self.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth)
if width is None:
width = self.width()
self.setLineWrapColumnOrWidth(width)
def confirmURL(self, link):
if link.scheme() == "mailto":
QtGui.QApplication.activeWindow().ui.lineEditTo.setText(link.path())
if link.hasQueryItem("subject"):
QtGui.QApplication.activeWindow().ui.lineEditSubject.setText(link.queryItemValue("subject"))
if link.hasQueryItem("body"):
QtGui.QApplication.activeWindow().ui.textEditMessage.setText(link.queryItemValue("body"))
QtGui.QApplication.activeWindow().setSendFromComboBox()
QtGui.QApplication.activeWindow().ui.tabWidgetSend.setCurrentIndex(0)
QtGui.QApplication.activeWindow().ui.tabWidget.setCurrentIndex(1)
QtGui.QApplication.activeWindow().ui.textEditMessage.setFocus()
return
reply = QtGui.QMessageBox.warning(self,
QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TITLE),
QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TEXT).arg(str(link.toString())),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QDesktopServices.openUrl(link)
def loadResource (self, restype, name):
if restype == QtGui.QTextDocument.ImageResource and name.scheme() == "bmmsg":
pass
# QImage correctImage;
# lookup the correct QImage from a cache
# return QVariant::fromValue(correctImage);
# elif restype == QtGui.QTextDocument.HtmlResource:
# elif restype == QtGui.QTextDocument.ImageResource:
# elif restype == QtGui.QTextDocument.StyleSheetResource:
# elif restype == QtGui.QTextDocument.UserResource:
else:
pass
# by default, this will interpret it as a local file
# QtGui.QTextBrowser.loadResource(restype, name)
def lazyRender(self):
if self.rendering:
return
self.rendering = True
position = self.verticalScrollBar().value()
cursor = QtGui.QTextCursor(self.document())
while self.outpos < len(self.out) and self.verticalScrollBar().value() >= self.document().size().height() - 2 * self.size().height():
startpos = self.outpos
self.outpos += 10240
# find next end of tag
if self.mode == MessageView.MODE_HTML:
pos = self.out.find(">", self.outpos)
if pos > self.outpos:
self.outpos = pos
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor)
cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos]))
self.verticalScrollBar().setValue(position)
self.rendering = False
def showPlain(self):
self.mode = MessageView.MODE_PLAIN
out = self.html.raw
if self.html.has_html:
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_PLAIN)) + "</b></div><br/>" + out
self.out = out
self.outpos = 0
self.setHtml("")
self.lazyRender()
def showHTML(self):
self.mode = MessageView.MODE_HTML
out = self.html.sanitised
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_HTML)) + "</b></div><br/>" + out
self.out = out
self.outpos = 0
self.setHtml("")
self.lazyRender()
def setContent(self, data):
self.html = SafeHTMLParser()
self.html.reset()
self.html.reset_safe()
self.html.allow_picture = True
self.html.feed(data)
self.html.close()
self.showPlain()