15 |
15 |
16 class RestructuredTextProvider(MarkupBase): |
16 class RestructuredTextProvider(MarkupBase): |
17 """ |
17 """ |
18 Class implementing the reStructured Text markup provider. |
18 Class implementing the reStructured Text markup provider. |
19 """ |
19 """ |
|
20 |
20 def __init__(self): |
21 def __init__(self): |
21 """ |
22 """ |
22 Constructor |
23 Constructor |
23 """ |
24 """ |
24 super().__init__() |
25 super().__init__() |
25 |
26 |
26 self.__headerChars = ["=", "-", "~", "+", "#", "^"] |
27 self.__headerChars = ["=", "-", "~", "+", "#", "^"] |
27 |
28 |
28 def kind(self): |
29 def kind(self): |
29 """ |
30 """ |
30 Public method to get the markup kind. |
31 Public method to get the markup kind. |
31 |
32 |
32 @return string with markup kind |
33 @return string with markup kind |
33 @rtype str |
34 @rtype str |
34 """ |
35 """ |
35 return "rest" |
36 return "rest" |
36 |
37 |
37 def hasBold(self): |
38 def hasBold(self): |
38 """ |
39 """ |
39 Public method to indicate the availability of bold markup. |
40 Public method to indicate the availability of bold markup. |
40 |
41 |
41 @return flag indicating the availability of bold markup |
42 @return flag indicating the availability of bold markup |
42 @rtype bool |
43 @rtype bool |
43 """ |
44 """ |
44 return True |
45 return True |
45 |
46 |
46 def bold(self, editor): |
47 def bold(self, editor): |
47 """ |
48 """ |
48 Public method to generate bold text. |
49 Public method to generate bold text. |
49 |
50 |
50 @param editor reference to the editor to work on |
51 @param editor reference to the editor to work on |
51 @type Editor |
52 @type Editor |
52 """ |
53 """ |
53 self.__insertMarkup("**", editor) |
54 self.__insertMarkup("**", editor) |
54 |
55 |
55 def hasItalic(self): |
56 def hasItalic(self): |
56 """ |
57 """ |
57 Public method to indicate the availability of italic markup. |
58 Public method to indicate the availability of italic markup. |
58 |
59 |
59 @return flag indicating the availability of italic markup |
60 @return flag indicating the availability of italic markup |
60 @rtype bool |
61 @rtype bool |
61 """ |
62 """ |
62 return True |
63 return True |
63 |
64 |
64 def italic(self, editor): |
65 def italic(self, editor): |
65 """ |
66 """ |
66 Public method to generate italic text. |
67 Public method to generate italic text. |
67 |
68 |
68 @param editor reference to the editor to work on |
69 @param editor reference to the editor to work on |
69 @type Editor |
70 @type Editor |
70 """ |
71 """ |
71 self.__insertMarkup("*", editor) |
72 self.__insertMarkup("*", editor) |
72 |
73 |
73 def headerLevels(self): |
74 def headerLevels(self): |
74 """ |
75 """ |
75 Public method to determine the available header levels. |
76 Public method to determine the available header levels. |
76 |
77 |
77 @return supported header levels |
78 @return supported header levels |
78 @rtype int |
79 @rtype int |
79 """ |
80 """ |
80 return len(self.__headerChars) |
81 return len(self.__headerChars) |
81 |
82 |
82 def header(self, editor, level): |
83 def header(self, editor, level): |
83 """ |
84 """ |
84 Public method to generate a header. |
85 Public method to generate a header. |
85 |
86 |
86 @param editor reference to the editor to work on |
87 @param editor reference to the editor to work on |
87 @type Editor |
88 @type Editor |
88 @param level header level |
89 @param level header level |
89 @type int |
90 @type int |
90 """ |
91 """ |
91 if editor is None or level > self.headerLevels(): |
92 if editor is None or level > self.headerLevels(): |
92 return |
93 return |
93 |
94 |
94 editor.beginUndoAction() |
95 editor.beginUndoAction() |
95 cline, cindex = editor.getCursorPosition() |
96 cline, cindex = editor.getCursorPosition() |
96 if editor.hasSelection() and cindex == 0: |
97 if editor.hasSelection() and cindex == 0: |
97 cline -= 1 |
98 cline -= 1 |
98 lineSeparator = editor.getLineSeparator() |
99 lineSeparator = editor.getLineSeparator() |
99 if not editor.text(cline).endswith(lineSeparator): |
100 if not editor.text(cline).endswith(lineSeparator): |
100 editor.insertAt(lineSeparator, cline, len(editor.text(cline))) |
101 editor.insertAt(lineSeparator, cline, len(editor.text(cline))) |
101 lineLength = len(editor.text(cline)) - len(lineSeparator) |
102 lineLength = len(editor.text(cline)) - len(lineSeparator) |
102 editor.insertAt( |
103 editor.insertAt( |
103 lineLength * self.__headerChars[level - 1] + lineSeparator, |
104 lineLength * self.__headerChars[level - 1] + lineSeparator, cline + 1, 0 |
104 cline + 1, 0) |
105 ) |
105 editor.setCursorPosition(cline + 2, 0) |
106 editor.setCursorPosition(cline + 2, 0) |
106 editor.endUndoAction() |
107 editor.endUndoAction() |
107 |
108 |
108 def hasCode(self): |
109 def hasCode(self): |
109 """ |
110 """ |
110 Public method to indicate the availability of inline code markup. |
111 Public method to indicate the availability of inline code markup. |
111 |
112 |
112 @return flag indicating the availability of inline code markup |
113 @return flag indicating the availability of inline code markup |
113 @rtype bool |
114 @rtype bool |
114 """ |
115 """ |
115 return True |
116 return True |
116 |
117 |
117 def code(self, editor): |
118 def code(self, editor): |
118 """ |
119 """ |
119 Public method to generate inline code text. |
120 Public method to generate inline code text. |
120 |
121 |
121 @param editor reference to the editor to work on |
122 @param editor reference to the editor to work on |
122 @type Editor |
123 @type Editor |
123 """ |
124 """ |
124 self.__insertMarkup("``", editor) |
125 self.__insertMarkup("``", editor) |
125 |
126 |
126 def hasCodeBlock(self): |
127 def hasCodeBlock(self): |
127 """ |
128 """ |
128 Public method to indicate the availability of code block markup. |
129 Public method to indicate the availability of code block markup. |
129 |
130 |
130 @return flag indicating the availability of code block markup |
131 @return flag indicating the availability of code block markup |
131 @rtype bool |
132 @rtype bool |
132 """ |
133 """ |
133 return True |
134 return True |
134 |
135 |
135 def codeBlock(self, editor): |
136 def codeBlock(self, editor): |
136 """ |
137 """ |
137 Public method to generate code block text. |
138 Public method to generate code block text. |
138 |
139 |
139 @param editor reference to the editor to work on |
140 @param editor reference to the editor to work on |
140 @type Editor |
141 @type Editor |
141 """ |
142 """ |
142 if editor is None: |
143 if editor is None: |
143 return |
144 return |
144 |
145 |
145 lineSeparator = editor.getLineSeparator() |
146 lineSeparator = editor.getLineSeparator() |
146 editor.beginUndoAction() |
147 editor.beginUndoAction() |
147 if editor.hasSelectedText(): |
148 if editor.hasSelectedText(): |
148 sline, sindex, eline, eindex = editor.getSelection() |
149 sline, sindex, eline, eindex = editor.getSelection() |
149 if not editor.text(sline).startswith((" ", "\t")): |
150 if not editor.text(sline).startswith((" ", "\t")): |
156 else: |
157 else: |
157 editor.insert("::{0}{0} ".format(lineSeparator)) |
158 editor.insert("::{0}{0} ".format(lineSeparator)) |
158 cline, cindex = editor.getCursorPosition() |
159 cline, cindex = editor.getCursorPosition() |
159 editor.setCursorPosition(cline + 2, 4) |
160 editor.setCursorPosition(cline + 2, 4) |
160 editor.endUndoAction() |
161 editor.endUndoAction() |
161 |
162 |
162 def __insertMarkup(self, markup, editor): |
163 def __insertMarkup(self, markup, editor): |
163 """ |
164 """ |
164 Private method to insert the specified markup. |
165 Private method to insert the specified markup. |
165 |
166 |
166 If the editor has selected text, this text is enclosed by the given |
167 If the editor has selected text, this text is enclosed by the given |
167 markup. If no text is selected, the markup is inserted at the cursor |
168 markup. If no text is selected, the markup is inserted at the cursor |
168 position and the cursor is positioned in between. |
169 position and the cursor is positioned in between. |
169 |
170 |
170 @param markup markup string to be inserted |
171 @param markup markup string to be inserted |
171 @type str |
172 @type str |
172 @param editor reference to the editor to work on |
173 @param editor reference to the editor to work on |
173 @type Editor |
174 @type Editor |
174 """ |
175 """ |
175 if editor is None: |
176 if editor is None: |
176 return |
177 return |
177 |
178 |
178 editor.beginUndoAction() |
179 editor.beginUndoAction() |
179 if editor.hasSelectedText(): |
180 if editor.hasSelectedText(): |
180 newText = "{0}{1}{0}".format(markup, editor.selectedText()) |
181 newText = "{0}{1}{0}".format(markup, editor.selectedText()) |
181 editor.replaceSelectedText(newText) |
182 editor.replaceSelectedText(newText) |
182 else: |
183 else: |
183 editor.insert(2 * markup) |
184 editor.insert(2 * markup) |
184 cline, cindex = editor.getCursorPosition() |
185 cline, cindex = editor.getCursorPosition() |
185 editor.setCursorPosition(cline, cindex + len(markup)) |
186 editor.setCursorPosition(cline, cindex + len(markup)) |
186 editor.endUndoAction() |
187 editor.endUndoAction() |
187 |
188 |
188 def hasHyperlink(self): |
189 def hasHyperlink(self): |
189 """ |
190 """ |
190 Public method to indicate the availability of hyperlink markup. |
191 Public method to indicate the availability of hyperlink markup. |
191 |
192 |
192 @return flag indicating the availability of hyperlink markup |
193 @return flag indicating the availability of hyperlink markup |
193 @rtype bool |
194 @rtype bool |
194 """ |
195 """ |
195 return True |
196 return True |
196 |
197 |
197 def hyperlink(self, editor): |
198 def hyperlink(self, editor): |
198 """ |
199 """ |
199 Public method to generate hyperlink text. |
200 Public method to generate hyperlink text. |
200 |
201 |
201 @param editor reference to the editor to work on |
202 @param editor reference to the editor to work on |
202 @type Editor |
203 @type Editor |
203 """ |
204 """ |
204 if editor is None: |
205 if editor is None: |
205 return |
206 return |
206 |
207 |
207 from .HyperlinkMarkupDialog import HyperlinkMarkupDialog |
208 from .HyperlinkMarkupDialog import HyperlinkMarkupDialog |
|
209 |
208 dlg = HyperlinkMarkupDialog(False, True, noTitle=True) |
210 dlg = HyperlinkMarkupDialog(False, True, noTitle=True) |
209 if dlg.exec() == QDialog.DialogCode.Accepted: |
211 if dlg.exec() == QDialog.DialogCode.Accepted: |
210 text, target, _ = dlg.getData() |
212 text, target, _ = dlg.getData() |
211 |
213 |
212 link1 = "`{0}`_".format(text) |
214 link1 = "`{0}`_".format(text) |
213 link2 = ".. _`{0}`:".format(text) |
215 link2 = ".. _`{0}`:".format(text) |
214 if target: |
216 if target: |
215 link2 = "{0} {1}".format(link2, target) |
217 link2 = "{0} {1}".format(link2, target) |
216 |
218 |
217 lineSeparator = editor.getLineSeparator() |
219 lineSeparator = editor.getLineSeparator() |
218 editor.beginUndoAction() |
220 editor.beginUndoAction() |
219 cline, cindex = editor.getCursorPosition() |
221 cline, cindex = editor.getCursorPosition() |
220 editor.insert(link1) |
222 editor.insert(link1) |
221 |
223 |
222 line = cline |
224 line = cline |
223 while line < editor.lines(): |
225 while line < editor.lines(): |
224 if editor.text(line).strip() == "": |
226 if editor.text(line).strip() == "": |
225 # found end of block |
227 # found end of block |
226 break |
228 break |
239 if editor.text(line).strip(): |
241 if editor.text(line).strip(): |
240 sep = 2 * lineSeparator |
242 sep = 2 * lineSeparator |
241 else: |
243 else: |
242 sep = lineSeparator |
244 sep = lineSeparator |
243 editor.insertAt("{0}{1}".format(link2, sep), line, 0) |
245 editor.insertAt("{0}{1}".format(link2, sep), line, 0) |
244 |
246 |
245 editor.setCursorPosition(cline, cindex + len(link1)) |
247 editor.setCursorPosition(cline, cindex + len(link1)) |
246 editor.endUndoAction() |
248 editor.endUndoAction() |
247 |
249 |
248 def hasLine(self): |
250 def hasLine(self): |
249 """ |
251 """ |
250 Public method to indicate the availability of a horizontal line markup. |
252 Public method to indicate the availability of a horizontal line markup. |
251 |
253 |
252 @return flag indicating the availability of a horizontal line markup |
254 @return flag indicating the availability of a horizontal line markup |
253 @rtype bool |
255 @rtype bool |
254 """ |
256 """ |
255 return True |
257 return True |
256 |
258 |
257 def line(self, editor): |
259 def line(self, editor): |
258 """ |
260 """ |
259 Public method to generate a horizontal line text. |
261 Public method to generate a horizontal line text. |
260 |
262 |
261 @param editor reference to the editor to work on |
263 @param editor reference to the editor to work on |
262 @type Editor |
264 @type Editor |
263 """ |
265 """ |
264 if editor is None: |
266 if editor is None: |
265 return |
267 return |
266 |
268 |
267 lineSeparator = editor.getLineSeparator() |
269 lineSeparator = editor.getLineSeparator() |
268 editor.beginUndoAction() |
270 editor.beginUndoAction() |
269 markup = "{0}-----{0}{0}".format(lineSeparator) |
271 markup = "{0}-----{0}{0}".format(lineSeparator) |
270 editor.insert(markup) |
272 editor.insert(markup) |
271 cline, cindex = editor.getCursorPosition() |
273 cline, cindex = editor.getCursorPosition() |
272 editor.setCursorPosition(cline + 3, 0) |
274 editor.setCursorPosition(cline + 3, 0) |
273 editor.endUndoAction() |
275 editor.endUndoAction() |
274 |
276 |
275 def hasQuote(self): |
277 def hasQuote(self): |
276 """ |
278 """ |
277 Public method to indicate the availability of block quote markup. |
279 Public method to indicate the availability of block quote markup. |
278 |
280 |
279 @return flag indicating the availability of block quote markup |
281 @return flag indicating the availability of block quote markup |
280 @rtype bool |
282 @rtype bool |
281 """ |
283 """ |
282 return True |
284 return True |
283 |
285 |
284 def quote(self, editor): |
286 def quote(self, editor): |
285 """ |
287 """ |
286 Public method to generate block quote text. |
288 Public method to generate block quote text. |
287 |
289 |
288 @param editor reference to the editor to work on |
290 @param editor reference to the editor to work on |
289 @type Editor |
291 @type Editor |
290 """ |
292 """ |
291 if editor is None: |
293 if editor is None: |
292 return |
294 return |
293 |
295 |
294 lineSeparator = editor.getLineSeparator() |
296 lineSeparator = editor.getLineSeparator() |
295 editor.beginUndoAction() |
297 editor.beginUndoAction() |
296 markup = "> " |
298 markup = "> " |
297 sline, sindex, eline, eindex = editor.getSelection() |
299 sline, sindex, eline, eindex = editor.getSelection() |
298 for line in range(sline, eline + 1 if eindex > 0 else eline): |
300 for line in range(sline, eline + 1 if eindex > 0 else eline): |
299 editor.insertAt(markup, line, 0) |
301 editor.insertAt(markup, line, 0) |
300 editor.insertAt("::{0}{0}".format(lineSeparator), sline, 0) |
302 editor.insertAt("::{0}{0}".format(lineSeparator), sline, 0) |
301 editor.setCursorPosition(eline + 2, eindex) |
303 editor.setCursorPosition(eline + 2, eindex) |
302 editor.endUndoAction() |
304 editor.endUndoAction() |
303 |
305 |
304 def hasImage(self): |
306 def hasImage(self): |
305 """ |
307 """ |
306 Public method to indicate the availability of image markup. |
308 Public method to indicate the availability of image markup. |
307 |
309 |
308 @return flag indicating the availability of image markup |
310 @return flag indicating the availability of image markup |
309 @rtype bool |
311 @rtype bool |
310 """ |
312 """ |
311 return True |
313 return True |
312 |
314 |
313 def image(self, editor): |
315 def image(self, editor): |
314 """ |
316 """ |
315 Public method to generate image text. |
317 Public method to generate image text. |
316 |
318 |
317 @param editor reference to the editor to work on |
319 @param editor reference to the editor to work on |
318 @type Editor |
320 @type Editor |
319 """ |
321 """ |
320 if editor is None: |
322 if editor is None: |
321 return |
323 return |
322 |
324 |
323 from .ImageMarkupDialog import ImageMarkupDialog |
325 from .ImageMarkupDialog import ImageMarkupDialog |
|
326 |
324 dlg = ImageMarkupDialog(ImageMarkupDialog.RestMode) |
327 dlg = ImageMarkupDialog(ImageMarkupDialog.RestMode) |
325 if dlg.exec() == QDialog.DialogCode.Accepted: |
328 if dlg.exec() == QDialog.DialogCode.Accepted: |
326 address, altText, title, originalSize, width, height = ( |
329 address, altText, title, originalSize, width, height = dlg.getData() |
327 dlg.getData() |
330 |
328 ) |
|
329 |
|
330 lineSeparator = editor.getLineSeparator() |
331 lineSeparator = editor.getLineSeparator() |
331 markup = ".. image:: {0}{1}".format(address, lineSeparator) |
332 markup = ".. image:: {0}{1}".format(address, lineSeparator) |
332 lines = 1 |
333 lines = 1 |
333 if altText: |
334 if altText: |
334 markup += " :alt: {0}{1}".format(altText, lineSeparator) |
335 markup += " :alt: {0}{1}".format(altText, lineSeparator) |
335 lines += 1 |
336 lines += 1 |
336 if not originalSize: |
337 if not originalSize: |
337 markup += " :height: {0}px{1}".format(height, lineSeparator) |
338 markup += " :height: {0}px{1}".format(height, lineSeparator) |
338 markup += " :width: {0}px{1}".format(width, lineSeparator) |
339 markup += " :width: {0}px{1}".format(width, lineSeparator) |
339 lines += 2 |
340 lines += 2 |
340 |
341 |
341 editor.beginUndoAction() |
342 editor.beginUndoAction() |
342 editor.insert(markup) |
343 editor.insert(markup) |
343 cline, cindex = editor.getCursorPosition() |
344 cline, cindex = editor.getCursorPosition() |
344 editor.setCursorPosition(cline + lines, 0) |
345 editor.setCursorPosition(cline + lines, 0) |
345 editor.endUndoAction() |
346 editor.endUndoAction() |
346 |
347 |
347 def hasBulletedList(self): |
348 def hasBulletedList(self): |
348 """ |
349 """ |
349 Public method to indicate the availability of bulleted list markup. |
350 Public method to indicate the availability of bulleted list markup. |
350 |
351 |
351 @return flag indicating the availability of bulleted list markup |
352 @return flag indicating the availability of bulleted list markup |
352 @rtype bool |
353 @rtype bool |
353 """ |
354 """ |
354 return True |
355 return True |
355 |
356 |
356 def bulletedList(self, editor): |
357 def bulletedList(self, editor): |
357 """ |
358 """ |
358 Public method to generate bulleted list text. |
359 Public method to generate bulleted list text. |
359 |
360 |
360 @param editor reference to the editor to work on |
361 @param editor reference to the editor to work on |
361 @type Editor |
362 @type Editor |
362 """ |
363 """ |
363 self.__makeList(editor, False) |
364 self.__makeList(editor, False) |
364 |
365 |
365 def hasNumberedList(self): |
366 def hasNumberedList(self): |
366 """ |
367 """ |
367 Public method to indicate the availability of numbered list markup. |
368 Public method to indicate the availability of numbered list markup. |
368 |
369 |
369 @return flag indicating the availability of numbered list markup |
370 @return flag indicating the availability of numbered list markup |
370 @rtype bool |
371 @rtype bool |
371 """ |
372 """ |
372 return True |
373 return True |
373 |
374 |
374 def numberedList(self, editor): |
375 def numberedList(self, editor): |
375 """ |
376 """ |
376 Public method to generate numbered list text. |
377 Public method to generate numbered list text. |
377 |
378 |
378 @param editor reference to the editor to work on |
379 @param editor reference to the editor to work on |
379 @type Editor |
380 @type Editor |
380 """ |
381 """ |
381 self.__makeList(editor, True) |
382 self.__makeList(editor, True) |
382 |
383 |
383 def __makeList(self, editor, numberedList): |
384 def __makeList(self, editor, numberedList): |
384 """ |
385 """ |
385 Private method to generate the desired list markup. |
386 Private method to generate the desired list markup. |
386 |
387 |
387 @param editor reference to the editor to work on |
388 @param editor reference to the editor to work on |
388 @type Editor |
389 @type Editor |
389 @param numberedList flag indicating the generation of a numbered list |
390 @param numberedList flag indicating the generation of a numbered list |
390 @type bool |
391 @type bool |
391 """ |
392 """ |
392 if editor is None: |
393 if editor is None: |
393 return |
394 return |
394 |
395 |
395 markup = " #. " if numberedList else " * " |
396 markup = " #. " if numberedList else " * " |
396 lineSeparator = editor.getLineSeparator() |
397 lineSeparator = editor.getLineSeparator() |
397 editor.beginUndoAction() |
398 editor.beginUndoAction() |
398 if editor.hasSelectedText(): |
399 if editor.hasSelectedText(): |
399 startLine, startIndex, endLine, endIndex = ( |
400 startLine, startIndex, endLine, endIndex = editor.getSelection() |
400 editor.getSelection() |
|
401 ) |
|
402 if endIndex == 0: |
401 if endIndex == 0: |
403 endLine -= 1 |
402 endLine -= 1 |
404 for line in range(startLine, endLine + 1): |
403 for line in range(startLine, endLine + 1): |
405 editor.insertAt(markup, line, 0) |
404 editor.insertAt(markup, line, 0) |
406 editor.setCursorPosition(endLine + 1, 0) |
405 editor.setCursorPosition(endLine + 1, 0) |
407 else: |
406 else: |
408 listElements, ok = QInputDialog.getInt( |
407 listElements, ok = QInputDialog.getInt( |
409 None, |
408 None, |
|
409 QCoreApplication.translate("RestructuredTextProvider", "Create List"), |
410 QCoreApplication.translate( |
410 QCoreApplication.translate( |
411 "RestructuredTextProvider", "Create List"), |
411 "RestructuredTextProvider", "Enter desired number of list elements:" |
412 QCoreApplication.translate( |
412 ), |
413 "RestructuredTextProvider", |
413 0, |
414 "Enter desired number of list elements:"), |
414 0, |
415 0, 0, 99, 1) |
415 99, |
|
416 1, |
|
417 ) |
416 if ok: |
418 if ok: |
417 if listElements == 0: |
419 if listElements == 0: |
418 listElements = 1 |
420 listElements = 1 |
419 cline, cindex = editor.getCursorPosition() |
421 cline, cindex = editor.getCursorPosition() |
420 listBody = ( |
422 listBody = listElements * "{1}{0}".format(lineSeparator, markup) |
421 listElements * "{1}{0}".format(lineSeparator, markup) |
|
422 ) |
|
423 if cindex == 0: |
423 if cindex == 0: |
424 editor.insertAt(listBody, cline, cindex) |
424 editor.insertAt(listBody, cline, cindex) |
425 editor.setCursorPosition(cline, len(markup)) |
425 editor.setCursorPosition(cline, len(markup)) |
426 else: |
426 else: |
427 if cline == editor.lines() - 1: |
427 if cline == editor.lines() - 1: |