1
+ """
2
+ src/bitmessageqt/messageview.py
3
+ ===============================
4
+
5
+ """
6
+
1
7
from PyQt4 import QtCore , QtGui
2
8
3
- import multiprocessing
4
- import Queue
5
- from urlparse import urlparse
6
- from safehtmlparser import *
9
+ from safehtmlparser import SafeHTMLParser
10
+
7
11
8
12
class MessageView (QtGui .QTextBrowser ):
13
+ """Message content viewer class, can switch between plaintext and HTML"""
9
14
MODE_PLAIN = 0
10
15
MODE_HTML = 1
11
-
12
- def __init__ (self , parent = 0 ):
16
+
17
+ def __init__ (self , parent = 0 ):
13
18
super (MessageView , self ).__init__ (parent )
14
- self .mode = MessageView .MODE_PLAIN
19
+ self .mode = MessageView .MODE_PLAIN
15
20
self .html = None
16
21
self .setOpenExternalLinks (False )
17
22
self .setOpenLinks (False )
@@ -25,12 +30,14 @@ def __init__(self, parent = 0):
25
30
self .setWrappingWidth ()
26
31
27
32
def resizeEvent (self , event ):
33
+ """View resize event handler"""
28
34
super (MessageView , self ).resizeEvent (event )
29
35
self .setWrappingWidth (event .size ().width ())
30
-
36
+
31
37
def mousePressEvent (self , event ):
32
- #text = textCursor.block().text()
33
- if event .button () == QtCore .Qt .LeftButton and self .html and self .html .has_html and self .cursorForPosition (event .pos ()).block ().blockNumber () == 0 :
38
+ """Mouse press button event handler"""
39
+ if event .button () == QtCore .Qt .LeftButton and self .html and self .html .has_html and self .cursorForPosition (
40
+ event .pos ()).block ().blockNumber () == 0 :
34
41
if self .mode == MessageView .MODE_PLAIN :
35
42
self .showHTML ()
36
43
else :
@@ -39,19 +46,24 @@ def mousePressEvent(self, event):
39
46
super (MessageView , self ).mousePressEvent (event )
40
47
41
48
def wheelEvent (self , event ):
49
+ """Mouse wheel scroll event handler"""
42
50
# super will actually automatically take care of zooming
43
51
super (MessageView , self ).wheelEvent (event )
44
- if (QtGui .QApplication .queryKeyboardModifiers () & QtCore .Qt .ControlModifier ) == QtCore .Qt .ControlModifier and event .orientation () == QtCore .Qt .Vertical :
52
+ if (QtGui .QApplication .queryKeyboardModifiers () &
53
+ QtCore .Qt .ControlModifier ) == QtCore .Qt .ControlModifier and event .orientation () == QtCore .Qt .Vertical :
45
54
zoom = self .currentFont ().pointSize () * 100 / self .defaultFontPointSize
46
- QtGui .QApplication .activeWindow ().statusBar ().showMessage (QtGui .QApplication .translate ("MainWindow" , "Zoom level %1%" ).arg (str (zoom )))
55
+ QtGui .QApplication .activeWindow ().statusBar ().showMessage (
56
+ QtGui .QApplication .translate ("MainWindow" , "Zoom level %1%" ).arg (str (zoom )))
47
57
48
58
def setWrappingWidth (self , width = None ):
59
+ """Set word-wrapping width"""
49
60
self .setLineWrapMode (QtGui .QTextEdit .FixedPixelWidth )
50
61
if width is None :
51
62
width = self .width ()
52
63
self .setLineWrapColumnOrWidth (width )
53
64
54
65
def confirmURL (self , link ):
66
+ """Show a dialog requesting URL opening confirmation"""
55
67
if link .scheme () == "mailto" :
56
68
window = QtGui .QApplication .activeWindow ()
57
69
window .ui .lineEditTo .setText (link .path ())
@@ -68,35 +80,39 @@ def confirmURL(self, link):
68
80
)
69
81
window .ui .textEditMessage .setFocus ()
70
82
return
71
- reply = QtGui .QMessageBox .warning (self ,
72
- QtGui .QApplication .translate ("MessageView" , "Follow external link" ),
73
- QtGui .QApplication .translate ("MessageView" , "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?" ).arg (unicode (link .toString ())),
74
- QtGui .QMessageBox .Yes , QtGui .QMessageBox .No )
83
+ reply = QtGui .QMessageBox .warning (
84
+ self ,
85
+ QtGui .QApplication .translate (
86
+ "MessageView" ,
87
+ "Follow external link" ),
88
+ QtGui .QApplication .translate (
89
+ "MessageView" ,
90
+ "The link \" %1\" will open in a browser. It may be a security risk, it could de-anonymise you"
91
+ " or download malicious data. Are you sure?" ).arg (unicode (link .toString ())),
92
+ QtGui .QMessageBox .Yes ,
93
+ QtGui .QMessageBox .No )
75
94
if reply == QtGui .QMessageBox .Yes :
76
95
QtGui .QDesktopServices .openUrl (link )
77
96
78
- def loadResource (self , restype , name ):
79
- if restype == QtGui .QTextDocument .ImageResource and name .scheme () == "bmmsg" :
80
- pass
81
- # QImage correctImage;
82
- # lookup the correct QImage from a cache
83
- # return QVariant::fromValue(correctImage);
84
- # elif restype == QtGui.QTextDocument.HtmlResource:
85
- # elif restype == QtGui.QTextDocument.ImageResource:
86
- # elif restype == QtGui.QTextDocument.StyleSheetResource:
87
- # elif restype == QtGui.QTextDocument.UserResource:
88
- else :
89
- pass
90
- # by default, this will interpret it as a local file
91
- # QtGui.QTextBrowser.loadResource(restype, name)
97
+ def loadResource (self , restype , name ):
98
+ """
99
+ Callback for loading referenced objects, such as an image. For security reasons at the moment doesn't do
100
+ anything)
101
+ """
102
+ pass
92
103
93
104
def lazyRender (self ):
105
+ """
106
+ Partially render a message. This is to avoid UI freezing when loading huge messages. It continues loading as
107
+ you scroll down.
108
+ """
94
109
if self .rendering :
95
110
return
96
111
self .rendering = True
97
112
position = self .verticalScrollBar ().value ()
98
113
cursor = QtGui .QTextCursor (self .document ())
99
- while self .outpos < len (self .out ) and self .verticalScrollBar ().value () >= self .document ().size ().height () - 2 * self .size ().height ():
114
+ while self .outpos < len (self .out ) and self .verticalScrollBar ().value (
115
+ ) >= self .document ().size ().height () - 2 * self .size ().height ():
100
116
startpos = self .outpos
101
117
self .outpos += 10240
102
118
# find next end of tag
@@ -108,27 +124,33 @@ def lazyRender(self):
108
124
cursor .insertHtml (QtCore .QString (self .out [startpos :self .outpos ]))
109
125
self .verticalScrollBar ().setValue (position )
110
126
self .rendering = False
111
-
127
+
112
128
def showPlain (self ):
129
+ """Render message as plain text."""
113
130
self .mode = MessageView .MODE_PLAIN
114
131
out = self .html .raw
115
132
if self .html .has_html :
116
- out = "<div align=\" center\" style=\" text-decoration: underline;\" ><b>" + unicode (QtGui .QApplication .translate ("MessageView" , "HTML detected, click here to display" )) + "</b></div><br/>" + out
133
+ out = "<div align=\" center\" style=\" text-decoration: underline;\" ><b>" + unicode (
134
+ QtGui .QApplication .translate (
135
+ "MessageView" , "HTML detected, click here to display" )) + "</b></div><br/>" + out
117
136
self .out = out
118
137
self .outpos = 0
119
138
self .setHtml ("" )
120
139
self .lazyRender ()
121
140
122
141
def showHTML (self ):
142
+ """Render message as HTML"""
123
143
self .mode = MessageView .MODE_HTML
124
144
out = self .html .sanitised
125
- out = "<div align=\" center\" style=\" text-decoration: underline;\" ><b>" + unicode (QtGui .QApplication .translate ("MessageView" , "Click here to disable HTML" )) + "</b></div><br/>" + out
145
+ out = "<div align=\" center\" style=\" text-decoration: underline;\" ><b>" + unicode (
146
+ QtGui .QApplication .translate ("MessageView" , "Click here to disable HTML" )) + "</b></div><br/>" + out
126
147
self .out = out
127
148
self .outpos = 0
128
149
self .setHtml ("" )
129
150
self .lazyRender ()
130
151
131
152
def setContent (self , data ):
153
+ """Set message content from argument"""
132
154
self .html = SafeHTMLParser ()
133
155
self .html .reset ()
134
156
self .html .reset_safe ()
0 commit comments