Lazy rendering of message contents
Message will render as user is scrolling down. This prevents interface freezes on long messages (such as inline img in text mode). Fixes Bitmessage##366 Also a minor fix in text mode rendering.
This commit is contained in:
parent
6557681a6c
commit
7ef94b446d
|
@ -17,6 +17,11 @@ class MessageView(QtGui.QTextBrowser):
|
||||||
self.setOpenExternalLinks(False)
|
self.setOpenExternalLinks(False)
|
||||||
self.setOpenLinks(False)
|
self.setOpenLinks(False)
|
||||||
self.anchorClicked.connect(self.confirmURL)
|
self.anchorClicked.connect(self.confirmURL)
|
||||||
|
self.out = ""
|
||||||
|
self.outpos = 0
|
||||||
|
self.document().setUndoRedoEnabled(False)
|
||||||
|
self.rendering = False
|
||||||
|
self.verticalScrollBar().valueChanged.connect(self.lazyRender)
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
#text = textCursor.block().text()
|
#text = textCursor.block().text()
|
||||||
|
@ -36,22 +41,49 @@ class MessageView(QtGui.QTextBrowser):
|
||||||
if reply == QtGui.QMessageBox.Yes:
|
if reply == QtGui.QMessageBox.Yes:
|
||||||
QtGui.QDesktopServices.openUrl(link)
|
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):
|
def showPlain(self):
|
||||||
self.mode = MessageView.MODE_PLAIN
|
self.mode = MessageView.MODE_PLAIN
|
||||||
out = self.html.raw
|
out = self.html.raw
|
||||||
if self.html.has_html:
|
if self.html.has_html:
|
||||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_PLAIN) + "</b></div><br/>" + out
|
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_PLAIN)) + "</b></div><br/>" + out
|
||||||
self.setHtml(QtCore.QString(out))
|
self.out = out
|
||||||
|
self.outpos = 0
|
||||||
|
self.setHtml("")
|
||||||
|
self.lazyRender()
|
||||||
|
|
||||||
def showHTML(self):
|
def showHTML(self):
|
||||||
self.mode = MessageView.MODE_HTML
|
self.mode = MessageView.MODE_HTML
|
||||||
out = self.html.sanitised
|
out = self.html.sanitised
|
||||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_HTML) + "</b></div><br/>" + out
|
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_HTML)) + "</b></div><br/>" + out
|
||||||
self.setHtml(QtCore.QString(out))
|
self.out = out
|
||||||
|
self.outpos = 0
|
||||||
|
self.setHtml("")
|
||||||
|
self.lazyRender()
|
||||||
|
|
||||||
def setContent(self, data):
|
def setContent(self, data):
|
||||||
self.html = SafeHTMLParser()
|
self.html = SafeHTMLParser()
|
||||||
self.html.allow_picture = True
|
self.html.allow_picture = True
|
||||||
|
self.html.reset()
|
||||||
|
self.html.reset_safe()
|
||||||
self.html.feed(data)
|
self.html.feed(data)
|
||||||
self.html.close()
|
self.html.close()
|
||||||
self.showPlain()
|
self.showPlain()
|
|
@ -25,8 +25,10 @@ class SafeHTMLParser(HTMLParser):
|
||||||
self.has_html = False
|
self.has_html = False
|
||||||
|
|
||||||
def reset_safe(self):
|
def reset_safe(self):
|
||||||
|
self.elements = set()
|
||||||
self.raw = u""
|
self.raw = u""
|
||||||
self.sanitised = u""
|
self.sanitised = u""
|
||||||
|
self.has_html = False
|
||||||
|
|
||||||
def add_if_acceptable(self, tag, attrs = None):
|
def add_if_acceptable(self, tag, attrs = None):
|
||||||
if not tag in self.acceptable_elements:
|
if not tag in self.acceptable_elements:
|
||||||
|
@ -35,12 +37,12 @@ class SafeHTMLParser(HTMLParser):
|
||||||
if inspect.stack()[1][3] == "handle_endtag":
|
if inspect.stack()[1][3] == "handle_endtag":
|
||||||
self.sanitised += "/"
|
self.sanitised += "/"
|
||||||
self.sanitised += tag
|
self.sanitised += tag
|
||||||
if attrs is not None:
|
if not attrs is None:
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
if tag == "img" and attr[0] == "src" and not self.allow_picture:
|
if tag == "img" and attr[0] == "src" and not self.allow_picture:
|
||||||
attr[1] = ""
|
attr[1] = ""
|
||||||
self.sanitised += " " + quote_plus(attr[0])
|
self.sanitised += " " + quote_plus(attr[0])
|
||||||
if attr[1] is not None:
|
if not (attr[1] is None):
|
||||||
self.sanitised += "=\"" + attr[1] + "\""
|
self.sanitised += "=\"" + attr[1] + "\""
|
||||||
if inspect.stack()[1][3] == "handle_startendtag":
|
if inspect.stack()[1][3] == "handle_startendtag":
|
||||||
self.sanitised += "/"
|
self.sanitised += "/"
|
||||||
|
@ -51,13 +53,13 @@ class SafeHTMLParser(HTMLParser):
|
||||||
if inspect.stack()[1][3] == "handle_endtag":
|
if inspect.stack()[1][3] == "handle_endtag":
|
||||||
self.raw += "/"
|
self.raw += "/"
|
||||||
self.raw += tag
|
self.raw += tag
|
||||||
if attrs is not None:
|
if not attrs is None:
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
if tag == "img" and attr[0] == "src" and not self.allow_picture:
|
if tag == "img" and attr[0] == "src" and not self.allow_picture:
|
||||||
attr[1] = ""
|
attr[1] = ""
|
||||||
self.raw += " " + attr[0]
|
self.raw += " " + attr[0]
|
||||||
if attr[1] is not None:
|
if not (attr[1] is None):
|
||||||
self.raw + "="" + attr[1] + """
|
self.raw += "="" + attr[1] + """
|
||||||
if inspect.stack()[1][3] == "handle_startendtag":
|
if inspect.stack()[1][3] == "handle_startendtag":
|
||||||
self.raw += "/"
|
self.raw += "/"
|
||||||
self.raw += ">"
|
self.raw += ">"
|
||||||
|
|
Reference in New Issue
Block a user