Coverage for C:\Repos\leo-editor\leo\core\leoPrinting.py: 43%
172 statements
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
1#@+leo-ver=5-thin
2#@+node:ekr.20150419124739.1: * @file leoPrinting.py
3"""
4Support the commands in Leo's File:Print menu.
5Adapted from printing plugin.
6"""
7from leo.core import leoGlobals as g
8#
9# Qt imports. May fail from the bridge.
10try: # #1973
11 from leo.core.leoQt import printsupport, QtGui
12 from leo.core.leoQt import DialogCode
13except Exception:
14 printsupport = QtGui = None # type:ignore
15 DialogCode = None # type:ignore
16#@+others
17#@+node:ekr.20150509035503.1: ** cmd (decorator)
18def cmd(name):
19 """Command decorator for the PrintingController class."""
20 return g.new_cmd_decorator(name, ['c', 'printingController',])
21#@+node:ekr.20150420120520.1: ** class PrintingController
22class PrintingController:
23 """A class supporting the commands in Leo's File:Print menu."""
24 #@+others
25 #@+node:ekr.20150419124739.6: *3* pr.__init__ & helpers
26 def __init__(self, c):
27 """Ctor for PrintingController class."""
28 self.c = c
29 self.reload_settings()
31 def reload_settings(self):
32 c = self.c
33 self.font_size = c.config.getString('printing-font-size') or '12'
34 self.font_family = c.config.getString('printing-font-family') or 'DejaVu Sans Mono'
35 self.stylesheet = self.construct_stylesheet()
37 reloadSettings = reload_settings
38 #@+node:ekr.20150419124739.8: *4* pr.construct stylesheet
39 def construct_stylesheet(self):
40 """Return the Qt stylesheet to be used for printing."""
41 family, size = self.font_family, self.font_size
42 table = (
43 # Clearer w/o f-strings.
44 f"h1 {{font-family: {family}}}",
45 f"pre {{font-family: {family}; font-size: {size}px}}",
46 )
47 return '\n'.join(table)
48 #@+node:ekr.20150420072955.1: *3* pr.Doc constructors
49 #@+node:ekr.20150419124739.11: *4* pr.complex document
50 def complex_document(self, nodes, heads=False):
51 """Create a complex document."""
52 doc = QtGui.QTextDocument()
53 doc.setDefaultStyleSheet(self.stylesheet)
54 contents = ''
55 for n in nodes:
56 if heads:
57 contents += f"<h1>{self.sanitize_html(n.h)}</h1>\n"
58 contents += f"<pre>{self.sanitize_html(n.b)}</pre>\n"
59 doc.setHtml(contents)
60 return doc
61 #@+node:ekr.20150419124739.9: *4* pr.document
62 def document(self, text, head=None):
63 """Create a Qt document."""
64 doc = QtGui.QTextDocument()
65 doc.setDefaultStyleSheet(self.stylesheet)
66 text = self.sanitize_html(text)
67 if head:
68 head = self.sanitize_html(head)
69 contents = f"<h1>{head}</h1>\n<pre>{text}</pre>"
70 else:
71 contents = f"<pre>{text}<pre>"
72 doc.setHtml(contents)
73 return doc
74 #@+node:ekr.20150419124739.10: *4* pr.html_document
75 def html_document(self, text):
76 """Create an HTML document."""
77 doc = QtGui.QTextDocument()
78 doc.setDefaultStyleSheet(self.stylesheet)
79 doc.setHtml(text)
80 return doc
81 #@+node:ekr.20150420073201.1: *3* pr.Helpers
82 #@+node:peckj.20150421084046.1: *4* pr.expand
83 def expand(self, p):
84 """Return the entire script at node p."""
85 return p.script
86 #@+node:ekr.20150419124739.15: *4* pr.getBodies
87 def getBodies(self, p):
88 """Return a concatenated version of the tree at p"""
89 return '\n'.join([p2.b for p2 in p.self_and_subtree(copy=False)])
90 #@+node:ekr.20150420085602.1: *4* pr.getNodes
91 def getNodes(self, p):
92 """Return the entire script at node p."""
93 result = [p.b]
94 for p in p.subtree():
95 result.extend(['', f"Node: {p.h}", ''])
96 result.append(p.b)
97 return '\n'.join(result)
98 #@+node:ekr.20150419124739.14: *4* pr.sanitize html
99 def sanitize_html(self, html):
100 """Generate html escapes."""
101 return html.replace('&', '&').replace('<', '<').replace('>', '>')
102 #@+node:ekr.20150420081215.1: *3* pr.Preview
103 #@+node:ekr.20150419124739.21: *4* pr.preview_body
104 @cmd('preview-body')
105 def preview_body(self, event=None):
106 """Preview the body of the selected node."""
107 doc = self.document(self.c.p.b)
108 self.preview_doc(doc)
109 #@+node:ekr.20150419124739.19: *4* pr.preview_html
110 @cmd('preview-html')
111 def preview_html(self, event=None):
112 """
113 Preview the body of the selected text as html. The body must be valid
114 html, including <html> and <body> elements.
115 """
116 doc = self.html_document(self.c.p.b)
117 self.preview_doc(doc)
118 #@+node:peckj.20150421084706.1: *4* pr.preview_expanded_body
119 @cmd('preview-expanded-body')
120 def preview_expanded_body(self, event=None):
121 """Preview the selected node's body, expanded"""
122 doc = self.document(self.expand(self.c.p))
123 self.preview_doc(doc)
124 #@+node:peckj.20150421084719.1: *4* pr.preview_expanded_html
125 @cmd('preview-expanded-html')
126 def preview_expanded_html(self, event=None):
127 """
128 Preview all the expanded bodies of the selected node as html. The
129 expanded text must be valid html, including <html> and <body> elements.
130 """
131 doc = self.html_document(self.expand(self.c.p))
132 self.preview_doc(doc)
133 #@+node:ekr.20150419124739.31: *4* pr.preview_marked_bodies
134 @cmd('preview-marked-bodies')
135 def preview_marked_bodies(self, event=None):
136 """Preview the bodies of the marked nodes."""
137 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
138 doc = self.complex_document(nodes)
139 self.preview_doc(doc)
140 #@+node:ekr.20150420081906.1: *4* pr.preview_marked_html
141 @cmd('preview-marked-html')
142 def preview_marked_html(self, event=None):
143 """
144 Preview the concatenated bodies of the marked nodes. The concatenated
145 bodies must be valid html, including <html> and <body> elements.
146 """
147 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
148 s = '\n'.join([z.b for z in nodes])
149 doc = self.html_document(s)
150 self.preview_doc(doc)
151 #@+node:ekr.20150419124739.33: *4* pr.preview_marked_nodes
152 @cmd('preview-marked-nodes')
153 def preview_marked_nodes(self, event=None):
154 """Preview the marked nodes."""
155 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
156 doc = self.complex_document(nodes, heads=True)
157 self.preview_doc(doc)
158 #@+node:ekr.20150419124739.23: *4* pr.preview_node
159 @cmd('preview-node')
160 def preview_node(self, event=None):
161 """Preview the selected node."""
162 p = self.c.p
163 doc = self.document(p.b, head=p.h)
164 self.preview_doc(doc)
165 #@+node:ekr.20150419124739.26: *4* pr.preview_tree_bodies
166 @cmd('preview-tree-bodies')
167 def preview_tree_bodies(self, event=None):
168 """Preview the bodies in the selected tree."""
169 doc = self.document(self.getBodies(self.c.p))
170 self.preview_doc(doc)
171 #@+node:ekr.20150419124739.28: *4* pr.preview_tree_nodes
172 @cmd('preview-tree-nodes')
173 def preview_tree_nodes(self, event=None):
174 """Preview the entire tree."""
175 p = self.c.p
176 doc = self.document(self.getNodes(p), head=p.h)
177 self.preview_doc(doc)
178 #@+node:ekr.20150420081923.1: *4* pr_preview_tree_html
179 @cmd('preview-tree-html')
180 def preview_tree_html(self, event=None):
181 """
182 Preview all the bodies of the selected node as html. The concatenated
183 bodies must valid html, including <html> and <body> elements.
184 """
185 doc = self.html_document(self.getBodies(self.c.p))
186 self.preview_doc(doc)
187 #@+node:ekr.20150420073128.1: *3* pr.Print
188 #@+node:ekr.20150419124739.20: *4* pr.print_body
189 @cmd('print-body')
190 def print_body(self, event=None):
191 """Print the selected node's body"""
192 doc = self.document(self.c.p.b)
193 self.print_doc(doc)
194 #@+node:ekr.20150419124739.18: *4* pr.print_html
195 @cmd('print-html')
196 def print_html(self, event=None):
197 """
198 Print the body of the selected text as html. The body must be valid
199 html, including <html> and <body> elements.
200 """
201 doc = self.html_document(self.c.p.b)
202 self.print_doc(doc)
203 #@+node:peckj.20150421084548.1: *4* pr.print_expanded_body
204 @cmd('print-expanded-body')
205 def print_expanded_body(self, event=None):
206 """Print the selected node's body, expanded"""
207 doc = self.document(self.expand(self.c.p))
208 self.print_doc(doc)
209 #@+node:peckj.20150421084636.1: *4* pr.print_expanded_html
210 @cmd('print-expanded-html')
211 def print_expanded_html(self, event=None):
212 """
213 Preview all the expanded bodies of the selected node as html. The
214 expanded text must be valid html, including <html> and <body> elements.
215 """
216 doc = self.html_document(self.expand(self.c.p))
217 self.print_doc(doc)
218 #@+node:ekr.20150419124739.30: *4* pr.print_marked_bodies
219 @cmd('print-marked-bodies')
220 def print_marked_bodies(self, event=None):
221 """Print the body text of marked nodes."""
222 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
223 doc = self.complex_document(nodes)
224 self.print_doc(doc)
225 #@+node:ekr.20150420085054.1: *4* pr.print_marked_html
226 @cmd('print-marked-html')
227 def print_marked_html(self, event=None):
228 """
229 Print the concatenated bodies of the marked nodes. The concatenated
230 bodies must be valid html, including <html> and <body> elements.
231 """
232 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
233 s = '\n'.join([z.b for z in nodes])
234 doc = self.html_document(s)
235 self.print_doc(doc)
236 #@+node:ekr.20150419124739.32: *4* pr.print_marked_nodes
237 @cmd('print-marked-nodes')
238 def print_marked_nodes(self, event=None):
239 """Print all the marked nodes"""
240 nodes = [p.v for p in self.c.all_positions() if p.isMarked()]
241 doc = self.complex_document(nodes, heads=True)
242 self.print_doc(doc)
243 #@+node:ekr.20150419124739.22: *4* pr.print_node
244 @cmd('print-node')
245 def print_node(self, event=None):
246 """Print the selected node """
247 doc = self.document(self.c.p.b, head=self.c.p.h)
248 self.print_doc(doc)
249 #@+node:ekr.20150419124739.25: *4* pr.print_tree_bodies
250 @cmd('print-tree-bodies')
251 def print_tree_bodies(self, event=None):
252 """Print all the bodies in the selected tree."""
253 doc = self.document(self.getBodies(self.c.p))
254 self.print_doc(doc)
255 #@+node:ekr.20150420084948.1: *4* pr.print_tree_html
256 @cmd('print-tree-html')
257 def print_tree_html(self, event=None):
258 """
259 Print all the bodies of the selected node as html. The concatenated
260 bodies must valid html, including <html> and <body> elements.
261 """
262 doc = self.html_document(self.getBodies(self.c.p))
263 self.print_doc(doc)
264 #@+node:ekr.20150419124739.27: *4* pr.print_tree_nodes
265 @cmd('print-tree-nodes')
266 def print_tree_nodes(self, event=None):
267 """Print all the nodes of the selected tree."""
268 doc = self.document(self.getNodes(self.c.p), head=self.c.p.h)
269 self.print_doc(doc)
270 #@+node:ekr.20150419124739.7: *3* pr.Top level
271 #@+node:ekr.20150419124739.12: *4* pr.print_doc
272 def print_doc(self, doc):
273 """Print the document."""
274 if not printsupport:
275 g.trace('Qt.printsupport not found.')
276 return
277 # pylint: disable=no-member
278 dialog = printsupport.QPrintDialog()
279 result = dialog.exec_()
280 if result == DialogCode.Accepted:
281 doc.print_(dialog.printer())
282 #@+node:ekr.20150419124739.13: *4* pr.preview_doc
283 def preview_doc(self, doc):
284 """Preview the document."""
285 # pylint: disable=no-member
286 dialog = printsupport.QPrintPreviewDialog()
287 dialog.setSizeGripEnabled(True)
288 dialog.paintRequested.connect(doc.print)
289 dialog.exec_()
290 #@-others
291#@-others
292#@@language python
293#@@tabwidth -4
294#@-leo