PyBitmessage-2021-04-27/src/bitmessageqt/messageview.py
Peter Surda 96a1726426 Clickable email and http links in plain text
Email addresses and URIs are now clickable when viewing a message in
plain text mode. Clicking an email address moves to the Send tab, while
clicking an URI has the same result as clicking an URI in html mode, it
will ask for confirmation before opening it in external handler.
2016-05-02 15:00:24 +02:00

109 lines
4.9 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)
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 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().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 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()