src/eric7/QScintilla/MarkupProviders/HtmlProvider.py

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

eric ide

mercurial