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