src/eric7/QScintilla/QsciScintillaCompat.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) 2004 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a compatability interface class to QsciScintilla.
8 """
9
10 import contextlib
11
12 from PyQt6.QtCore import pyqtSignal, Qt, QPoint
13 from PyQt6.QtGui import QPalette, QColor
14 from PyQt6.QtWidgets import QApplication, QListWidget
15 from PyQt6.Qsci import (
16 QsciScintillaBase, QsciScintilla,
17 QSCINTILLA_VERSION as QSCIQSCINTILLA_VERSION
18 )
19
20 ###############################################################################
21
22
23 def QSCINTILLA_VERSION():
24 """
25 Module function to return the QScintilla version.
26
27 @return QScintilla version (integer)
28 """
29 return QSCIQSCINTILLA_VERSION
30
31 ###############################################################################
32
33
34 class QsciScintillaCompat(QsciScintilla):
35 """
36 Class implementing a compatability interface to QsciScintilla.
37
38 This class implements all the functions, that were added to
39 QsciScintilla incrementally. This class ensures compatibility
40 to older versions of QsciScintilla.
41
42 @signal zoomValueChanged(int) emitted to signal a change of the zoom value
43 """
44 zoomValueChanged = pyqtSignal(int)
45
46 ArrowFoldStyle = QsciScintilla.FoldStyle.BoxedTreeFoldStyle.value + 1
47 ArrowTreeFoldStyle = ArrowFoldStyle + 1
48
49 UserSeparator = '\x04'
50
51 IndicatorStyleMax = QsciScintilla.INDIC_GRADIENTCENTRE
52
53 # Maps PyQt6.QFont.Weight to the weights used by QScintilla
54 QFontWeightMapping = {
55 100: 0,
56 200: 12,
57 300: 25,
58 400: 50,
59 500: 57,
60 600: 63,
61 700: 75,
62 800: 81,
63 900: 87,
64 }
65
66 def __init__(self, parent=None):
67 """
68 Constructor
69
70 @param parent parent widget (QWidget)
71 """
72 super().__init__(parent)
73
74 self.zoom = 0
75
76 self.__targetSearchFlags = 0
77 self.__targetSearchExpr = ""
78 self.__targetSearchStart = 0
79 self.__targetSearchEnd = -1
80 self.__targetSearchActive = False
81
82 self.__modified = False
83
84 self.userListActivated.connect(self.__completionListSelected)
85 self.modificationChanged.connect(self.__modificationChanged)
86
87 self.setAutoCompletionWidgetSize(40, 5)
88
89 def __modificationChanged(self, m):
90 """
91 Private slot to handle the modificationChanged signal.
92
93 @param m modification status (boolean)
94 """
95 self.__modified = m
96
97 def isModified(self):
98 """
99 Public method to return the modification status.
100
101 @return flag indicating the modification status (boolean)
102 """
103 return self.__modified
104
105 def setModified(self, m):
106 """
107 Public slot to set the modification status.
108
109 @param m new modification status (boolean)
110 """
111 self.__modified = m
112 super().setModified(m)
113 self.modificationChanged.emit(m)
114
115 def setLexer(self, lex=None):
116 """
117 Public method to set the lexer.
118
119 @param lex the lexer to be set or None to reset it.
120 """
121 super().setLexer(lex)
122 if lex is None:
123 self.clearStyles()
124
125 def clearStyles(self):
126 """
127 Public method to set the styles according the selected Qt style.
128 """
129 palette = QApplication.palette()
130 self.SendScintilla(QsciScintilla.SCI_STYLESETFORE,
131 QsciScintilla.STYLE_DEFAULT,
132 palette.color(QPalette.ColorRole.Text))
133 self.SendScintilla(QsciScintilla.SCI_STYLESETBACK,
134 QsciScintilla.STYLE_DEFAULT,
135 palette.color(QPalette.ColorRole.Base))
136 self.SendScintilla(QsciScintilla.SCI_STYLECLEARALL)
137 self.SendScintilla(QsciScintilla.SCI_CLEARDOCUMENTSTYLE)
138
139 def monospacedStyles(self, font):
140 """
141 Public method to set the current style to be monospaced.
142
143 @param font font to be used (QFont)
144 """
145 try:
146 rangeLow = list(range(self.STYLE_DEFAULT))
147 except AttributeError:
148 rangeLow = list(range(32))
149 try:
150 rangeHigh = list(range(self.STYLE_LASTPREDEFINED + 1,
151 self.STYLE_MAX + 1))
152 except AttributeError:
153 rangeHigh = list(range(40, 128))
154
155 f = font.family().encode("utf-8")
156 ps = font.pointSize()
157 weight = -QsciScintillaCompat.QFontWeightMapping[font.weight()]
158 italic = font.italic()
159 underline = font.underline()
160 bold = font.bold()
161 for style in rangeLow + rangeHigh:
162 self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, style, f)
163 self.SendScintilla(QsciScintilla.SCI_STYLESETSIZE, style, ps)
164 try:
165 self.SendScintilla(
166 QsciScintilla.SCI_STYLESETWEIGHT, style, weight)
167 except AttributeError:
168 self.SendScintilla(QsciScintilla.SCI_STYLESETBOLD, style, bold)
169 self.SendScintilla(QsciScintilla.SCI_STYLESETITALIC, style, italic)
170 self.SendScintilla(
171 QsciScintilla.SCI_STYLESETUNDERLINE, style, underline)
172
173 def linesOnScreen(self):
174 """
175 Public method to get the amount of visible lines.
176
177 @return amount of visible lines (integer)
178 """
179 return self.SendScintilla(QsciScintilla.SCI_LINESONSCREEN)
180
181 def lineAt(self, pos):
182 """
183 Public method to calculate the line at a position.
184
185 This variant is able to calculate the line for positions in the
186 margins and for empty lines.
187
188 @param pos position to calculate the line for (integer or QPoint)
189 @return linenumber at position or -1, if there is no line at pos
190 (integer, zero based)
191 """
192 scipos = (
193 pos
194 if isinstance(pos, int) else
195 self.SendScintilla(QsciScintilla.SCI_POSITIONFROMPOINT,
196 pos.x(), pos.y())
197 )
198 line = self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, scipos)
199 if line >= self.lines():
200 line = -1
201 return line
202
203 def currentPosition(self):
204 """
205 Public method to get the current position.
206
207 @return absolute position of the cursor (integer)
208 """
209 return self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS)
210
211 def styleAt(self, pos):
212 """
213 Public method to get the style at a position in the text.
214
215 @param pos position in the text (integer)
216 @return style at the requested position or 0, if the position
217 is negative or past the end of the document (integer)
218 """
219 return self.SendScintilla(QsciScintilla.SCI_GETSTYLEAT, pos)
220
221 def currentStyle(self):
222 """
223 Public method to get the style at the current position.
224
225 @return style at the current position (integer)
226 """
227 return self.styleAt(self.currentPosition())
228
229 def getSubStyleRange(self, styleNr):
230 """
231 Public method to get the sub style range for given style number.
232
233 @param styleNr Number of the base style
234 @type int
235 @return start index of the sub style and their count
236 @rtype int, int
237 """
238 start = self.SendScintilla(QsciScintilla.SCI_GETSUBSTYLESSTART,
239 styleNr)
240 count = self.SendScintilla(QsciScintilla.SCI_GETSUBSTYLESLENGTH,
241 styleNr)
242 return start, count
243
244 def getEndStyled(self):
245 """
246 Public method to get the last styled position.
247
248 @return end position of the last styling run (integer)
249 """
250 return self.SendScintilla(QsciScintilla.SCI_GETENDSTYLED)
251
252 def startStyling(self, pos, mask):
253 """
254 Public method to prepare styling.
255
256 @param pos styling positition to start at (integer)
257 @param mask mask of bits to use for styling (integer)
258 """
259 self.SendScintilla(QsciScintilla.SCI_STARTSTYLING, pos, mask)
260
261 def setStyling(self, length, style):
262 """
263 Public method to style some text.
264
265 @param length length of text to style (integer)
266 @param style style to set for text (integer)
267 """
268 self.SendScintilla(QsciScintilla.SCI_SETSTYLING, length, style)
269
270 def charAt(self, pos):
271 """
272 Public method to get the character at a position in the text observing
273 multibyte characters.
274
275 @param pos position in the text (integer)
276 @return character at the requested position or empty string, if the
277 position is negative or past the end of the document (string)
278 """
279 ch = self.byteAt(pos)
280 if ch and ord(ch) > 127 and self.isUtf8():
281 if (ch[0] & 0xF0) == 0xF0:
282 utf8Len = 4
283 elif (ch[0] & 0xE0) == 0xE0:
284 utf8Len = 3
285 elif (ch[0] & 0xC0) == 0xC0:
286 utf8Len = 2
287 else:
288 utf8Len = 1
289 while len(ch) < utf8Len:
290 pos += 1
291 ch += self.byteAt(pos)
292 try:
293 return ch.decode('utf8')
294 except UnicodeDecodeError:
295 if pos > 0:
296 # try it one position before; maybe we are in the
297 # middle of a unicode character
298 return self.charAt(pos - 1)
299 else:
300 return ""
301 else:
302 return ch.decode()
303
304 def byteAt(self, pos):
305 """
306 Public method to get the raw character (bytes) at a position in the
307 text.
308
309 @param pos position in the text (integer)
310 @return raw character at the requested position or empty bytes, if the
311 position is negative or past the end of the document (bytes)
312 """
313 char = self.SendScintilla(QsciScintilla.SCI_GETCHARAT, pos)
314 if char == 0:
315 return bytearray()
316 if char < 0:
317 char += 256
318 return bytearray((char,))
319
320 def foldLevelAt(self, line):
321 """
322 Public method to get the fold level of a line of the document.
323
324 @param line line number (integer)
325 @return fold level of the given line (integer)
326 """
327 lvl = self.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, line)
328 return (
329 (lvl & QsciScintilla.SC_FOLDLEVELNUMBERMASK) -
330 QsciScintilla.SC_FOLDLEVELBASE
331 )
332
333 def foldFlagsAt(self, line):
334 """
335 Public method to get the fold flags of a line of the document.
336
337 @param line line number (integer)
338 @return fold flags of the given line (integer)
339 """
340 lvl = self.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, line)
341 return lvl & ~QsciScintilla.SC_FOLDLEVELNUMBERMASK
342
343 def foldHeaderAt(self, line):
344 """
345 Public method to determine, if a line of the document is a fold header
346 line.
347
348 @param line line number (integer)
349 @return flag indicating a fold header line (boolean)
350 """
351 lvl = self.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, line)
352 return lvl & QsciScintilla.SC_FOLDLEVELHEADERFLAG
353
354 def foldExpandedAt(self, line):
355 """
356 Public method to determine, if a fold is expanded.
357
358 @param line line number (integer)
359 @return flag indicating the fold expansion state of the line (boolean)
360 """
361 return self.SendScintilla(QsciScintilla.SCI_GETFOLDEXPANDED, line)
362
363 def setIndentationGuideView(self, view):
364 """
365 Public method to set the view of the indentation guides.
366
367 @param view view of the indentation guides (SC_IV_NONE, SC_IV_REAL,
368 SC_IV_LOOKFORWARD or SC_IV_LOOKBOTH)
369 """
370 self.SendScintilla(QsciScintilla.SCI_SETINDENTATIONGUIDES, view)
371
372 def indentationGuideView(self):
373 """
374 Public method to get the indentation guide view.
375
376 @return indentation guide view (SC_IV_NONE, SC_IV_REAL,
377 SC_IV_LOOKFORWARD or SC_IV_LOOKBOTH)
378 """
379 return self.SendScintilla(QsciScintilla.SCI_GETINDENTATIONGUIDES)
380
381 ###########################################################################
382 ## methods below are missing from QScintilla
383 ###########################################################################
384
385 def setAutoCompletionWidgetSize(self, chars, lines):
386 """
387 Public method to set the size of completion and user lists.
388
389 @param chars max. number of chars to show
390 @type int
391 @param lines max. number of lines to show
392 @type int
393 """
394 self.SendScintilla(QsciScintilla.SCI_AUTOCSETMAXWIDTH, chars)
395 self.SendScintilla(QsciScintilla.SCI_AUTOCSETMAXHEIGHT, lines)
396
397 def zoomIn(self, zoom=1):
398 """
399 Public method used to increase the zoom factor.
400
401 @param zoom zoom factor increment (integer)
402 """
403 super().zoomIn(zoom)
404
405 def zoomOut(self, zoom=1):
406 """
407 Public method used to decrease the zoom factor.
408
409 @param zoom zoom factor decrement (integer)
410 """
411 super().zoomOut(zoom)
412
413 def zoomTo(self, zoom):
414 """
415 Public method used to zoom to a specific zoom factor.
416
417 @param zoom zoom factor (integer)
418 """
419 self.zoom = zoom
420 super().zoomTo(zoom)
421 self.zoomValueChanged.emit(self.zoom)
422
423 def getZoom(self):
424 """
425 Public method used to retrieve the current zoom factor.
426
427 @return zoom factor (integer)
428 """
429 return self.zoom
430
431 def editorCommand(self, cmd):
432 """
433 Public method to perform a simple editor command.
434
435 @param cmd the scintilla command to be performed (integer)
436 """
437 self.SendScintilla(cmd)
438
439 def scrollVertical(self, lines):
440 """
441 Public method to scroll the text area.
442
443 @param lines number of lines to scroll (negative scrolls up,
444 positive scrolls down) (integer)
445 """
446 self.SendScintilla(QsciScintilla.SCI_LINESCROLL, 0, lines)
447
448 def moveCursorToEOL(self):
449 """
450 Public method to move the cursor to the end of line.
451 """
452 self.SendScintilla(QsciScintilla.SCI_LINEEND)
453
454 def moveCursorLeft(self):
455 """
456 Public method to move the cursor left.
457 """
458 self.SendScintilla(QsciScintilla.SCI_CHARLEFT)
459
460 def moveCursorRight(self):
461 """
462 Public method to move the cursor right.
463 """
464 self.SendScintilla(QsciScintilla.SCI_CHARRIGHT)
465
466 def moveCursorWordLeft(self):
467 """
468 Public method to move the cursor left one word.
469 """
470 self.SendScintilla(QsciScintilla.SCI_WORDLEFT)
471
472 def moveCursorWordRight(self):
473 """
474 Public method to move the cursor right one word.
475 """
476 self.SendScintilla(QsciScintilla.SCI_WORDRIGHT)
477
478 def newLineBelow(self):
479 """
480 Public method to insert a new line below the current one.
481 """
482 self.SendScintilla(QsciScintilla.SCI_LINEEND)
483 self.SendScintilla(QsciScintilla.SCI_NEWLINE)
484
485 def deleteBack(self):
486 """
487 Public method to delete the character to the left of the cursor.
488 """
489 self.SendScintilla(QsciScintilla.SCI_DELETEBACK)
490
491 def delete(self):
492 """
493 Public method to delete the character to the right of the cursor.
494 """
495 self.SendScintilla(QsciScintilla.SCI_CLEAR)
496
497 def deleteWordLeft(self):
498 """
499 Public method to delete the word to the left of the cursor.
500 """
501 self.SendScintilla(QsciScintilla.SCI_DELWORDLEFT)
502
503 def deleteWordRight(self):
504 """
505 Public method to delete the word to the right of the cursor.
506 """
507 self.SendScintilla(QsciScintilla.SCI_DELWORDRIGHT)
508
509 def deleteLineLeft(self):
510 """
511 Public method to delete the line to the left of the cursor.
512 """
513 self.SendScintilla(QsciScintilla.SCI_DELLINELEFT)
514
515 def deleteLineRight(self):
516 """
517 Public method to delete the line to the right of the cursor.
518 """
519 self.SendScintilla(QsciScintilla.SCI_DELLINERIGHT)
520
521 def extendSelectionLeft(self):
522 """
523 Public method to extend the selection one character to the left.
524 """
525 self.SendScintilla(QsciScintilla.SCI_CHARLEFTEXTEND)
526
527 def extendSelectionRight(self):
528 """
529 Public method to extend the selection one character to the right.
530 """
531 self.SendScintilla(QsciScintilla.SCI_CHARRIGHTEXTEND)
532
533 def extendSelectionWordLeft(self):
534 """
535 Public method to extend the selection one word to the left.
536 """
537 self.SendScintilla(QsciScintilla.SCI_WORDLEFTEXTEND)
538
539 def extendSelectionWordRight(self):
540 """
541 Public method to extend the selection one word to the right.
542 """
543 self.SendScintilla(QsciScintilla.SCI_WORDRIGHTEXTEND)
544
545 def extendSelectionToBOL(self):
546 """
547 Public method to extend the selection to the beginning of the line.
548 """
549 self.SendScintilla(QsciScintilla.SCI_VCHOMEEXTEND)
550
551 def extendSelectionToEOL(self):
552 """
553 Public method to extend the selection to the end of the line.
554 """
555 self.SendScintilla(QsciScintilla.SCI_LINEENDEXTEND)
556
557 def hasSelection(self):
558 """
559 Public method to check for a selection.
560
561 @return flag indicating the presence of a selection (boolean)
562 """
563 return self.getSelection()[0] != -1
564
565 def hasSelectedText(self):
566 """
567 Public method to indicate the presence of selected text.
568
569 This is an overriding method to cope with a bug in QsciScintilla.
570
571 @return flag indicating the presence of selected text (boolean)
572 """
573 return bool(self.selectedText())
574
575 def selectionIsRectangle(self):
576 """
577 Public method to check, if the current selection is rectangular.
578
579 @return flag indicating a rectangular selection (boolean)
580 """
581 startLine, startIndex, endLine, endIndex = self.getSelection()
582 return (
583 startLine != -1 and
584 startLine != endLine and
585 self.SendScintilla(QsciScintilla.SCI_SELECTIONISRECTANGLE)
586 )
587
588 def getRectangularSelection(self):
589 """
590 Public method to retrieve the start and end of a rectangular selection.
591
592 @return tuple with start line and index and end line and index
593 (tuple of four int)
594 """
595 if not self.selectionIsRectangle():
596 return (-1, -1, -1, -1)
597
598 startPos = self.SendScintilla(
599 QsciScintilla.SCI_GETRECTANGULARSELECTIONANCHOR)
600 endPos = self.SendScintilla(
601 QsciScintilla.SCI_GETRECTANGULARSELECTIONCARET)
602 startLine, startIndex = self.lineIndexFromPosition(startPos)
603 endLine, endIndex = self.lineIndexFromPosition(endPos)
604
605 return (startLine, startIndex, endLine, endIndex)
606
607 def setRectangularSelection(self, startLine, startIndex, endLine,
608 endIndex):
609 """
610 Public method to set a rectangular selection.
611
612 @param startLine line number of the start of the selection (int)
613 @param startIndex index number of the start of the selection (int)
614 @param endLine line number of the end of the selection (int)
615 @param endIndex index number of the end of the selection (int)
616 """
617 startPos = self.positionFromLineIndex(startLine, startIndex)
618 endPos = self.positionFromLineIndex(endLine, endIndex)
619
620 self.SendScintilla(
621 QsciScintilla.SCI_SETRECTANGULARSELECTIONANCHOR, startPos)
622 self.SendScintilla(
623 QsciScintilla.SCI_SETRECTANGULARSELECTIONCARET, endPos)
624
625 def getSelectionCount(self):
626 """
627 Public method to get the number of active selections.
628
629 @return number of active selection (integer)
630 """
631 return self.SendScintilla(QsciScintilla.SCI_GETSELECTIONS)
632
633 def getSelectionN(self, index):
634 """
635 Public method to get the start and end of a selection given by its
636 index.
637
638 @param index index of the selection (integer)
639 @return tuple with start line and index and end line and index
640 (tuple of four int) for the given selection
641 """
642 startPos = self.SendScintilla(
643 QsciScintilla.SCI_GETSELECTIONNSTART, index)
644 endPos = self.SendScintilla(QsciScintilla.SCI_GETSELECTIONNEND, index)
645 startLine, startIndex = self.lineIndexFromPosition(startPos)
646 endLine, endIndex = self.lineIndexFromPosition(endPos)
647
648 return (startLine, startIndex, endLine, endIndex)
649
650 def getSelections(self):
651 """
652 Public method to get the start and end coordinates of all active
653 selections.
654
655 @return list of tuples with start line and index and end line and index
656 of each active selection (list of tuples of four int)
657 """
658 selections = []
659 for index in range(self.getSelectionCount()):
660 selections.append(self.getSelectionN(index))
661 return selections
662
663 def addCursor(self, line, index):
664 """
665 Public method to add an additional cursor.
666
667 @param line line number for the cursor
668 @type int
669 @param index index number for the cursor
670 @type int
671 """
672 pos = self.positionFromLineIndex(line, index)
673
674 if self.getSelectionCount() == 0:
675 self.SendScintilla(QsciScintilla.SCI_SETSELECTION, pos, pos)
676 else:
677 self.SendScintilla(QsciScintilla.SCI_ADDSELECTION, pos, pos)
678
679 def enableMultiCursorSupport(self):
680 """
681 Public method to enable support for multi cursor editing.
682 """
683 # typing should insert in all selections at the same time
684 self.SendScintilla(QsciScintilla.SCI_SETMULTIPLESELECTION, True)
685 self.SendScintilla(QsciScintilla.SCI_SETADDITIONALSELECTIONTYPING,
686 True)
687
688 def setVirtualSpaceOptions(self, options):
689 """
690 Public method to set the virtual space usage options.
691
692 @param options usage options to set (integer, 0 to 3)
693 """
694 self.SendScintilla(QsciScintilla.SCI_SETVIRTUALSPACEOPTIONS, options)
695
696 def getLineSeparator(self):
697 """
698 Public method to get the line separator for the current eol mode.
699
700 @return eol string (string)
701 """
702 m = self.eolMode()
703 if m == QsciScintilla.EolMode.EolWindows:
704 eol = '\r\n'
705 elif m == QsciScintilla.EolMode.EolUnix:
706 eol = '\n'
707 elif m == QsciScintilla.EolMode.EolMac:
708 eol = '\r'
709 else:
710 eol = ''
711 return eol
712
713 def getEolIndicator(self):
714 """
715 Public method to get the eol indicator for the current eol mode.
716
717 @return eol indicator (string)
718 """
719 m = self.eolMode()
720 if m == QsciScintilla.EolMode.EolWindows:
721 eol = 'CRLF'
722 elif m == QsciScintilla.EolMode.EolUnix:
723 eol = 'LF'
724 elif m == QsciScintilla.EolMode.EolMac:
725 eol = 'CR'
726 else:
727 eol = ''
728 return eol
729
730 def setEolModeByEolString(self, eolStr):
731 """
732 Public method to set the eol mode given the eol string.
733
734 @param eolStr eol string (string)
735 """
736 if eolStr == '\r\n':
737 self.setEolMode(QsciScintilla.EolMode.EolWindows)
738 elif eolStr == '\n':
739 self.setEolMode(QsciScintilla.EolMode.EolUnix)
740 elif eolStr == '\r':
741 self.setEolMode(QsciScintilla.EolMode.EolMac)
742
743 def detectEolString(self, txt):
744 """
745 Public method to determine the eol string used.
746
747 @param txt text from which to determine the eol string (string)
748 @return eol string (string)
749 """
750 if len(txt.split("\r\n", 1)) == 2:
751 return '\r\n'
752 elif len(txt.split("\n", 1)) == 2:
753 return '\n'
754 elif len(txt.split("\r", 1)) == 2:
755 return '\r'
756 else:
757 return None
758
759 def getCursorFlashTime(self):
760 """
761 Public method to get the flash (blink) time of the cursor in
762 milliseconds.
763
764 The flash time is the time required to display, invert and restore the
765 caret display. Usually the text cursor is displayed for half the cursor
766 flash time, then hidden for the same amount of time.
767
768 @return flash time of the cursor in milliseconds (integer)
769 """
770 return 2 * self.SendScintilla(QsciScintilla.SCI_GETCARETPERIOD)
771
772 def setCursorFlashTime(self, time):
773 """
774 Public method to set the flash (blink) time of the cursor in
775 milliseconds.
776
777 The flash time is the time required to display, invert and restore the
778 caret display. Usually the text cursor is displayed for half the cursor
779 flash time, then hidden for the same amount of time.
780
781 @param time flash time of the cursor in milliseconds (integer)
782 """
783 self.SendScintilla(QsciScintilla.SCI_SETCARETPERIOD, time // 2)
784
785 def getCaretLineAlwaysVisible(self):
786 """
787 Public method to determine, if the caret line is visible even if
788 the editor doesn't have the focus.
789
790 @return flag indicating an always visible caret line (boolean)
791 """
792 try:
793 return self.SendScintilla(
794 QsciScintilla.SCI_GETCARETLINEVISIBLEALWAYS)
795 except AttributeError:
796 return False
797
798 def setCaretLineAlwaysVisible(self, alwaysVisible):
799 """
800 Public method to set the caret line visible even if the editor doesn't
801 have the focus.
802
803 @param alwaysVisible flag indicating that the caret line shall be
804 visible even if the editor doesn't have the focus (boolean)
805 """
806 with contextlib.suppress(AttributeError):
807 self.SendScintilla(
808 QsciScintilla.SCI_SETCARETLINEVISIBLEALWAYS, alwaysVisible)
809
810 def canPaste(self):
811 """
812 Public method to test, if the paste action is available (i.e. if the
813 clipboard contains some text).
814
815 @return flag indicating the availability of 'paste'
816 @rtype bool
817 """
818 return self.SendScintilla(QsciScintilla.SCI_CANPASTE)
819
820 ###########################################################################
821 ## methods to perform searches in target range
822 ###########################################################################
823
824 def positionFromPoint(self, point):
825 """
826 Public method to calculate the scintilla position from a point in the
827 window.
828
829 @param point point in the window (QPoint)
830 @return scintilla position (integer) or -1 to indicate, that the point
831 is not near any character
832 """
833 return self.SendScintilla(QsciScintilla.SCI_POSITIONFROMPOINTCLOSE,
834 point.x(), point.y())
835
836 def positionBefore(self, pos):
837 """
838 Public method to get the position before the given position taking into
839 account multibyte characters.
840
841 @param pos position (integer)
842 @return position before the given one (integer)
843 """
844 return self.SendScintilla(QsciScintilla.SCI_POSITIONBEFORE, pos)
845
846 def positionAfter(self, pos):
847 """
848 Public method to get the position after the given position taking into
849 account multibyte characters.
850
851 @param pos position (integer)
852 @return position after the given one (integer)
853 """
854 return self.SendScintilla(QsciScintilla.SCI_POSITIONAFTER, pos)
855
856 def lineEndPosition(self, line):
857 """
858 Public method to determine the line end position of the given line.
859
860 @param line line number (integer)
861 @return position of the line end disregarding line end characters
862 (integer)
863 """
864 return self.SendScintilla(QsciScintilla.SCI_GETLINEENDPOSITION, line)
865
866 def __doSearchTarget(self):
867 """
868 Private method to perform the search in target.
869
870 @return flag indicating a successful search (boolean)
871 """
872 if self.__targetSearchStart == self.__targetSearchEnd:
873 self.__targetSearchActive = False
874 return False
875
876 self.SendScintilla(QsciScintilla.SCI_SETTARGETSTART,
877 self.__targetSearchStart)
878 self.SendScintilla(QsciScintilla.SCI_SETTARGETEND,
879 self.__targetSearchEnd)
880 self.SendScintilla(QsciScintilla.SCI_SETSEARCHFLAGS,
881 self.__targetSearchFlags)
882 targetSearchExpr = self._encodeString(self.__targetSearchExpr)
883 pos = self.SendScintilla(QsciScintilla.SCI_SEARCHINTARGET,
884 len(targetSearchExpr),
885 targetSearchExpr)
886
887 if pos == -1:
888 self.__targetSearchActive = False
889 return False
890
891 targend = self.SendScintilla(QsciScintilla.SCI_GETTARGETEND)
892 self.__targetSearchStart = targend
893
894 return True
895
896 def getFoundTarget(self):
897 """
898 Public method to get the recently found target.
899
900 @return found target as a tuple of starting position and target length
901 (integer, integer)
902 """
903 if self.__targetSearchActive:
904 spos = self.SendScintilla(QsciScintilla.SCI_GETTARGETSTART)
905 epos = self.SendScintilla(QsciScintilla.SCI_GETTARGETEND)
906 return (spos, epos - spos)
907 else:
908 return (0, 0)
909
910 def findFirstTarget(self, expr_, re_, cs_, wo_,
911 begline=-1, begindex=-1, endline=-1, endindex=-1,
912 ws_=False, posix=False, cxx11=False):
913 """
914 Public method to search in a specified range of text without
915 setting the selection.
916
917 @param expr_ search expression
918 @type str
919 @param re_ flag indicating a regular expression
920 @type bool
921 @param cs_ flag indicating a case sensitive search
922 @type bool
923 @param wo_ flag indicating a word only search
924 @type bool
925 @param begline line number to start from (-1 to indicate current
926 position)
927 @type int
928 @param begindex index to start from (-1 to indicate current position)
929 @type int
930 @param endline line number to stop at (-1 to indicate end of document)
931 @type int
932 @param endindex index number to stop at (-1 to indicate end of
933 document)
934 @type int
935 @param ws_ flag indicating a word start search (boolean)
936 @type bool
937 @param posix
938 @type bool
939 @param cxx11
940 @type bool
941 @return flag indicating a successful search
942 @rtype bool
943 """
944 self.__targetSearchFlags = 0
945 if re_:
946 self.__targetSearchFlags |= QsciScintilla.SCFIND_REGEXP
947 if cs_:
948 self.__targetSearchFlags |= QsciScintilla.SCFIND_MATCHCASE
949 if wo_:
950 self.__targetSearchFlags |= QsciScintilla.SCFIND_WHOLEWORD
951 if ws_:
952 self.__targetSearchFlags |= QsciScintilla.SCFIND_WORDSTART
953 if posix:
954 self.__targetSearchFlags |= QsciScintilla.SCFIND_POSIX
955 with contextlib.suppress(AttributeError):
956 if cxx11:
957 self.__targetSearchFlags |= QsciScintilla.SCFIND_CXX11REGEX
958 # defined for QScintilla >= 2.11.0
959
960 if begline < 0 or begindex < 0:
961 self.__targetSearchStart = self.SendScintilla(
962 QsciScintilla.SCI_GETCURRENTPOS)
963 else:
964 self.__targetSearchStart = self.positionFromLineIndex(
965 begline, begindex)
966
967 if endline < 0 or endindex < 0:
968 self.__targetSearchEnd = self.SendScintilla(
969 QsciScintilla.SCI_GETTEXTLENGTH)
970 else:
971 self.__targetSearchEnd = self.positionFromLineIndex(
972 endline, endindex)
973
974 self.__targetSearchExpr = expr_
975
976 if self.__targetSearchExpr:
977 self.__targetSearchActive = True
978
979 return self.__doSearchTarget()
980
981 return False
982
983 def findNextTarget(self):
984 """
985 Public method to find the next occurrence in the target range.
986
987 @return flag indicating a successful search (boolean)
988 """
989 if not self.__targetSearchActive:
990 return False
991
992 return self.__doSearchTarget()
993
994 def replaceTarget(self, replaceStr):
995 """
996 Public method to replace the string found by the last search in target.
997
998 @param replaceStr replacement string or regexp (string)
999 """
1000 if not self.__targetSearchActive:
1001 return
1002
1003 cmd = (
1004 QsciScintilla.SCI_REPLACETARGETRE
1005 if self.__targetSearchFlags & QsciScintilla.SCFIND_REGEXP else
1006 QsciScintilla.SCI_REPLACETARGET
1007 )
1008 r = self._encodeString(replaceStr)
1009
1010 start = self.SendScintilla(QsciScintilla.SCI_GETTARGETSTART)
1011 self.SendScintilla(cmd, len(r), r)
1012
1013 self.__targetSearchStart = start + len(r)
1014
1015 ###########################################################################
1016 ## indicator handling methods
1017 ###########################################################################
1018
1019 def indicatorDefine(self, indicator, style, color):
1020 """
1021 Public method to define the appearance of an indicator.
1022
1023 @param indicator number of the indicator (integer,
1024 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1025 @param style style to be used for the indicator
1026 (QsciScintilla.INDIC_PLAIN, QsciScintilla.INDIC_SQUIGGLE,
1027 QsciScintilla.INDIC_TT, QsciScintilla.INDIC_DIAGONAL,
1028 QsciScintilla.INDIC_STRIKE, QsciScintilla.INDIC_HIDDEN,
1029 QsciScintilla.INDIC_BOX, QsciScintilla.INDIC_ROUNDBOX,
1030 QsciScintilla.INDIC_STRAIGHTBOX, QsciScintilla.INDIC_FULLBOX,
1031 QsciScintilla.INDIC_DASH, QsciScintilla.INDIC_DOTS,
1032 QsciScintilla.INDIC_SQUIGGLELOW, QsciScintilla.INDIC_DOTBOX,
1033 QsciScintilla.INDIC_GRADIENT, QsciScintilla.INDIC_GRADIENTCENTRE,
1034 QsciScintilla.INDIC_SQUIGGLEPIXMAP,
1035 QsciScintilla.INDIC_COMPOSITIONTHICK,
1036 QsciScintilla.INDIC_COMPOSITIONTHIN, QsciScintilla.INDIC_TEXTFORE,
1037 QsciScintilla.INDIC_POINT, QsciScintilla.INDIC_POINTCHARACTER
1038 depending upon QScintilla version)
1039 @param color color to be used by the indicator (QColor)
1040 @exception ValueError the indicator or style are not valid
1041 """
1042 if (
1043 indicator < QsciScintilla.INDIC_CONTAINER or
1044 indicator > QsciScintilla.INDIC_MAX
1045 ):
1046 raise ValueError("indicator number out of range")
1047
1048 if (
1049 style < QsciScintilla.INDIC_PLAIN or
1050 style > self.IndicatorStyleMax
1051 ):
1052 raise ValueError("style out of range")
1053
1054 self.SendScintilla(QsciScintilla.SCI_INDICSETSTYLE, indicator, style)
1055 self.SendScintilla(QsciScintilla.SCI_INDICSETFORE, indicator, color)
1056 with contextlib.suppress(AttributeError):
1057 self.SendScintilla(QsciScintilla.SCI_INDICSETALPHA, indicator,
1058 color.alpha())
1059 if style in (
1060 QsciScintilla.INDIC_ROUNDBOX, QsciScintilla.INDIC_STRAIGHTBOX,
1061 QsciScintilla.INDIC_DOTBOX, QsciScintilla.INDIC_FULLBOX,
1062 ):
1063 # set outline alpha less transparent
1064 self.SendScintilla(QsciScintilla.SCI_INDICSETOUTLINEALPHA,
1065 indicator, color.alpha() + 20)
1066
1067 def setCurrentIndicator(self, indicator):
1068 """
1069 Public method to set the current indicator.
1070
1071 @param indicator number of the indicator (integer,
1072 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1073 @exception ValueError the indicator or style are not valid
1074 """
1075 if (
1076 indicator < QsciScintilla.INDIC_CONTAINER or
1077 indicator > QsciScintilla.INDIC_MAX
1078 ):
1079 raise ValueError("indicator number out of range")
1080
1081 self.SendScintilla(QsciScintilla.SCI_SETINDICATORCURRENT, indicator)
1082
1083 def setIndicatorRange(self, indicator, spos, length):
1084 """
1085 Public method to set an indicator for the given range.
1086
1087 @param indicator number of the indicator (integer,
1088 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1089 @param spos position of the indicator start (integer)
1090 @param length length of the indicator (integer)
1091 """
1092 self.setCurrentIndicator(indicator)
1093 self.SendScintilla(QsciScintilla.SCI_INDICATORFILLRANGE, spos, length)
1094
1095 def setIndicator(self, indicator, sline, sindex, eline, eindex):
1096 """
1097 Public method to set an indicator for the given range.
1098
1099 @param indicator number of the indicator (integer,
1100 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1101 @param sline line number of the indicator start (integer)
1102 @param sindex index of the indicator start (integer)
1103 @param eline line number of the indicator end (integer)
1104 @param eindex index of the indicator end (integer)
1105 """
1106 spos = self.positionFromLineIndex(sline, sindex)
1107 epos = self.positionFromLineIndex(eline, eindex)
1108 self.setIndicatorRange(indicator, spos, epos - spos)
1109
1110 def clearIndicatorRange(self, indicator, spos, length):
1111 """
1112 Public method to clear an indicator for the given range.
1113
1114 @param indicator number of the indicator (integer,
1115 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1116 @param spos position of the indicator start (integer)
1117 @param length length of the indicator (integer)
1118 """
1119 self.setCurrentIndicator(indicator)
1120 self.SendScintilla(QsciScintilla.SCI_INDICATORCLEARRANGE, spos, length)
1121
1122 def clearIndicator(self, indicator, sline, sindex, eline, eindex):
1123 """
1124 Public method to clear an indicator for the given range.
1125
1126 @param indicator number of the indicator (integer,
1127 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1128 @param sline line number of the indicator start (integer)
1129 @param sindex index of the indicator start (integer)
1130 @param eline line number of the indicator end (integer)
1131 @param eindex index of the indicator end (integer)
1132 """
1133 spos = self.positionFromLineIndex(sline, sindex)
1134 epos = self.positionFromLineIndex(eline, eindex)
1135 self.clearIndicatorRange(indicator, spos, epos - spos)
1136
1137 def clearAllIndicators(self, indicator):
1138 """
1139 Public method to clear all occurrences of an indicator.
1140
1141 @param indicator number of the indicator (integer,
1142 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1143 """
1144 self.clearIndicatorRange(indicator, 0, self.length())
1145
1146 def hasIndicator(self, indicator, pos):
1147 """
1148 Public method to test for the existence of an indicator.
1149
1150 @param indicator number of the indicator (integer,
1151 QsciScintilla.INDIC_CONTAINER .. QsciScintilla.INDIC_MAX)
1152 @param pos position to test (integer)
1153 @return flag indicating the existence of the indicator (boolean)
1154 """
1155 res = self.SendScintilla(QsciScintilla.SCI_INDICATORVALUEAT,
1156 indicator, pos)
1157 return res
1158
1159 def showFindIndicator(self, sline, sindex, eline, eindex):
1160 """
1161 Public method to show the find indicator for the given range.
1162
1163 @param sline line number of the indicator start (integer)
1164 @param sindex index of the indicator start (integer)
1165 @param eline line number of the indicator end (integer)
1166 @param eindex index of the indicator end (integer)
1167 """
1168 if hasattr(QsciScintilla, "SCI_FINDINDICATORSHOW"):
1169 spos = self.positionFromLineIndex(sline, sindex)
1170 epos = self.positionFromLineIndex(eline, eindex)
1171 self.SendScintilla(QsciScintilla.SCI_FINDINDICATORSHOW, spos, epos)
1172
1173 def flashFindIndicator(self, sline, sindex, eline, eindex):
1174 """
1175 Public method to flash the find indicator for the given range.
1176
1177 @param sline line number of the indicator start (integer)
1178 @param sindex index of the indicator start (integer)
1179 @param eline line number of the indicator end (integer)
1180 @param eindex index of the indicator end (integer)
1181 """
1182 if hasattr(QsciScintilla, "SCI_FINDINDICATORFLASH"):
1183 spos = self.positionFromLineIndex(sline, sindex)
1184 epos = self.positionFromLineIndex(eline, eindex)
1185 self.SendScintilla(QsciScintilla.SCI_FINDINDICATORFLASH,
1186 spos, epos)
1187
1188 def hideFindIndicator(self):
1189 """
1190 Public method to hide the find indicator.
1191 """
1192 if hasattr(QsciScintilla, "SCI_FINDINDICATORHIDE"):
1193 self.SendScintilla(QsciScintilla.SCI_FINDINDICATORHIDE)
1194
1195 def getIndicatorStartPos(self, indicator, pos):
1196 """
1197 Public method to get the start position of an indicator at a position.
1198
1199 @param indicator ID of the indicator (integer)
1200 @param pos position within the indicator (integer)
1201 @return start position of the indicator (integer)
1202 """
1203 return self.SendScintilla(QsciScintilla.SCI_INDICATORSTART,
1204 indicator, pos)
1205
1206 def getIndicatorEndPos(self, indicator, pos):
1207 """
1208 Public method to get the end position of an indicator at a position.
1209
1210 @param indicator ID of the indicator (integer)
1211 @param pos position within the indicator (integer)
1212 @return end position of the indicator (integer)
1213 """
1214 return self.SendScintilla(QsciScintilla.SCI_INDICATOREND,
1215 indicator, pos)
1216
1217 def gotoPreviousIndicator(self, indicator, wrap):
1218 """
1219 Public method to move the cursor to the previous position of an
1220 indicator.
1221
1222 This method ensures, that the position found is visible (i.e. unfolded
1223 and inside the visible range). The text containing the indicator is
1224 selected.
1225
1226 @param indicator ID of the indicator to search (integer)
1227 @param wrap flag indicating to wrap around at the beginning of the
1228 text (boolean)
1229 @return flag indicating if the indicator was found (boolean)
1230 """
1231 pos = self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS)
1232 docLen = self.SendScintilla(QsciScintilla.SCI_GETTEXTLENGTH)
1233 isInIndicator = self.hasIndicator(indicator, pos)
1234 posStart = self.getIndicatorStartPos(indicator, pos)
1235 posEnd = self.getIndicatorEndPos(indicator, pos)
1236
1237 if posStart == 0 and posEnd == docLen - 1:
1238 # indicator does not exist
1239 return False
1240
1241 if posStart <= 0:
1242 if not wrap:
1243 return False
1244
1245 isInIndicator = self.hasIndicator(indicator, docLen - 1)
1246 posStart = self.getIndicatorStartPos(indicator, docLen - 1)
1247
1248 if isInIndicator:
1249 # get out of it
1250 posStart = self.getIndicatorStartPos(indicator, posStart - 1)
1251 if posStart <= 0:
1252 if not wrap:
1253 return False
1254
1255 posStart = self.getIndicatorStartPos(indicator, docLen - 1)
1256
1257 newPos = posStart - 1
1258 posStart = self.getIndicatorStartPos(indicator, newPos)
1259 posEnd = self.getIndicatorEndPos(indicator, newPos)
1260
1261 if self.hasIndicator(indicator, posStart):
1262 # found it
1263 line, index = self.lineIndexFromPosition(posEnd)
1264 self.ensureLineVisible(line)
1265 self.SendScintilla(QsciScintilla.SCI_SETSEL, posEnd, posStart)
1266 self.SendScintilla(QsciScintilla.SCI_SCROLLCARET)
1267 return True
1268
1269 return False
1270
1271 def gotoNextIndicator(self, indicator, wrap):
1272 """
1273 Public method to move the cursor to the next position of an indicator.
1274
1275 This method ensures, that the position found is visible (i.e. unfolded
1276 and inside the visible range). The text containing the indicator is
1277 selected.
1278
1279 @param indicator ID of the indicator to search (integer)
1280 @param wrap flag indicating to wrap around at the beginning of the
1281 text (boolean)
1282 @return flag indicating if the indicator was found (boolean)
1283 """
1284 pos = self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS)
1285 docLen = self.SendScintilla(QsciScintilla.SCI_GETTEXTLENGTH)
1286 isInIndicator = self.hasIndicator(indicator, pos)
1287 posStart = self.getIndicatorStartPos(indicator, pos)
1288 posEnd = self.getIndicatorEndPos(indicator, pos)
1289
1290 if posStart == 0 and posEnd == docLen - 1:
1291 # indicator does not exist
1292 return False
1293
1294 if posEnd >= docLen:
1295 if not wrap:
1296 return False
1297
1298 isInIndicator = self.hasIndicator(indicator, 0)
1299 posEnd = self.getIndicatorEndPos(indicator, 0)
1300
1301 if isInIndicator:
1302 # get out of it
1303 posEnd = self.getIndicatorEndPos(indicator, posEnd)
1304 if posEnd >= docLen:
1305 if not wrap:
1306 return False
1307
1308 posEnd = self.getIndicatorEndPos(indicator, 0)
1309
1310 newPos = posEnd + 1
1311 posStart = self.getIndicatorStartPos(indicator, newPos)
1312 posEnd = self.getIndicatorEndPos(indicator, newPos)
1313
1314 if self.hasIndicator(indicator, posStart):
1315 # found it
1316 line, index = self.lineIndexFromPosition(posEnd)
1317 self.ensureLineVisible(line)
1318 self.SendScintilla(QsciScintilla.SCI_SETSEL, posStart, posEnd)
1319 self.SendScintilla(QsciScintilla.SCI_SCROLLCARET)
1320 return True
1321
1322 return False
1323
1324 ###########################################################################
1325 ## methods to perform folding related stuff
1326 ###########################################################################
1327
1328 def __setFoldMarker(self, marknr, mark=QsciScintilla.SC_MARK_EMPTY):
1329 """
1330 Private method to define a fold marker.
1331
1332 @param marknr marker number to define (integer)
1333 @param mark fold mark symbol to be used (integer)
1334 """
1335 self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, marknr, mark)
1336
1337 if mark != QsciScintilla.SC_MARK_EMPTY:
1338 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1339 marknr, QColor(Qt.GlobalColor.white))
1340 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1341 marknr, QColor(Qt.GlobalColor.black))
1342
1343 def setFolding(self, style, margin=2):
1344 """
1345 Public method to set the folding style and margin.
1346
1347 @param style folding style to set (integer)
1348 @param margin margin number (integer)
1349 """
1350 if isinstance(style, QsciScintilla.FoldStyle):
1351 super().setFolding(QsciScintilla.FoldStyle(style), margin)
1352 else:
1353 super().setFolding(
1354 QsciScintilla.FoldStyle.PlainFoldStyle, margin)
1355
1356 if style == self.ArrowFoldStyle:
1357 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDER,
1358 QsciScintilla.SC_MARK_ARROW)
1359 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPEN,
1360 QsciScintilla.SC_MARK_ARROWDOWN)
1361 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERSUB)
1362 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERTAIL)
1363 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEREND)
1364 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPENMID)
1365 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL)
1366 elif style == self.ArrowTreeFoldStyle:
1367 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDER,
1368 QsciScintilla.SC_MARK_ARROW)
1369 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPEN,
1370 QsciScintilla.SC_MARK_ARROWDOWN)
1371 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERSUB,
1372 QsciScintilla.SC_MARK_VLINE)
1373 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERTAIL,
1374 QsciScintilla.SC_MARK_LCORNER)
1375 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEREND,
1376 QsciScintilla.SC_MARK_ARROW)
1377 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPENMID,
1378 QsciScintilla.SC_MARK_ARROWDOWN)
1379 self.__setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL,
1380 QsciScintilla.SC_MARK_TCORNER)
1381
1382 def setFoldMarkersColors(self, foreColor, backColor):
1383 """
1384 Public method to set the foreground and background colors of the
1385 fold markers.
1386
1387 @param foreColor foreground color (QColor)
1388 @param backColor background color (QColor)
1389 """
1390 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1391 QsciScintilla.SC_MARKNUM_FOLDER, foreColor)
1392 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1393 QsciScintilla.SC_MARKNUM_FOLDER, backColor)
1394
1395 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1396 QsciScintilla.SC_MARKNUM_FOLDEROPEN, foreColor)
1397 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1398 QsciScintilla.SC_MARKNUM_FOLDEROPEN, backColor)
1399
1400 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1401 QsciScintilla.SC_MARKNUM_FOLDEROPENMID, foreColor)
1402 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1403 QsciScintilla.SC_MARKNUM_FOLDEROPENMID, backColor)
1404
1405 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1406 QsciScintilla.SC_MARKNUM_FOLDERSUB, foreColor)
1407 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1408 QsciScintilla.SC_MARKNUM_FOLDERSUB, backColor)
1409
1410 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1411 QsciScintilla.SC_MARKNUM_FOLDERTAIL, foreColor)
1412 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1413 QsciScintilla.SC_MARKNUM_FOLDERTAIL, backColor)
1414
1415 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1416 QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL, foreColor)
1417 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1418 QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL, backColor)
1419
1420 self.SendScintilla(QsciScintilla.SCI_MARKERSETFORE,
1421 QsciScintilla.SC_MARKNUM_FOLDEREND, foreColor)
1422 self.SendScintilla(QsciScintilla.SCI_MARKERSETBACK,
1423 QsciScintilla.SC_MARKNUM_FOLDEREND, backColor)
1424
1425 def getVisibleLineFromDocLine(self, docLine):
1426 """
1427 Public method to convert a document line number to a visible line
1428 number (i.e. respect folded lines and annotations).
1429
1430 @param docLine document line number to be converted
1431 @type int
1432 @return visible line number
1433 @rtype int
1434 """
1435 return self.SendScintilla(QsciScintilla.SCI_VISIBLEFROMDOCLINE,
1436 docLine)
1437
1438 def getDocLineFromVisibleLine(self, displayLine):
1439 """
1440 Public method to convert a visible line number to a document line
1441 number (i.e. respect folded lines and annotations).
1442
1443 @param displayLine display line number to be converted
1444 @type int
1445 @return document line number
1446 @rtype int
1447 """
1448 return self.SendScintilla(QsciScintilla.SCI_DOCLINEFROMVISIBLE,
1449 displayLine)
1450
1451 ###########################################################################
1452 ## interface methods to the standard keyboard command set
1453 ###########################################################################
1454
1455 def clearKeys(self):
1456 """
1457 Public method to clear the key commands.
1458 """
1459 # call into the QsciCommandSet
1460 self.standardCommands().clearKeys()
1461
1462 def clearAlternateKeys(self):
1463 """
1464 Public method to clear the alternate key commands.
1465 """
1466 # call into the QsciCommandSet
1467 self.standardCommands().clearAlternateKeys()
1468
1469 ###########################################################################
1470 ## specialized event handlers
1471 ###########################################################################
1472
1473 def focusOutEvent(self, event):
1474 """
1475 Protected method called when the editor loses focus.
1476
1477 @param event event object (QFocusEvent)
1478 """
1479 if self.isListActive():
1480 if event.reason() in [
1481 Qt.FocusReason.ActiveWindowFocusReason,
1482 Qt.FocusReason.OtherFocusReason
1483 ]:
1484 aw = QApplication.activeWindow()
1485 if aw is None or aw.parent() is not self:
1486 self.cancelList()
1487 else:
1488 self.cancelList()
1489
1490 if self.isCallTipActive():
1491 if event.reason() in [
1492 Qt.FocusReason.ActiveWindowFocusReason,
1493 Qt.FocusReason.OtherFocusReason
1494 ]:
1495 aw = QApplication.activeWindow()
1496 if aw is None or aw.parent() is not self:
1497 self.cancelCallTips()
1498 else:
1499 self.cancelCallTips()
1500
1501 super().focusOutEvent(event)
1502
1503 def event(self, evt):
1504 """
1505 Public method to handle events.
1506
1507 Note: We are not interested in the standard QsciScintilla event
1508 handling because we do it ourselves.
1509
1510 @param evt event object to handle (QEvent)
1511 @return result of the event handling (boolean)
1512 """
1513 return QsciScintillaBase.event(self, evt)
1514
1515 ###########################################################################
1516 ## interface methods to the mini editor
1517 ###########################################################################
1518
1519 def getFileName(self):
1520 """
1521 Public method to return the name of the file being displayed.
1522
1523 @return filename of the displayed file (string)
1524 """
1525 p = self.parent()
1526 if p is None:
1527 return ""
1528 else:
1529 try:
1530 return p.getFileName()
1531 except AttributeError:
1532 return ""
1533
1534 ###########################################################################
1535 ## replacements for buggy methods
1536 ###########################################################################
1537
1538 def showUserList(self, listId, lst):
1539 """
1540 Public method to show a user supplied list.
1541
1542 @param listId id of the list (integer)
1543 @param lst list to be show (list of strings)
1544 """
1545 if listId <= 0:
1546 return
1547
1548 # Setup seperator for user lists
1549 self.SendScintilla(
1550 QsciScintilla.SCI_AUTOCSETSEPARATOR, ord(self.UserSeparator))
1551 self.SendScintilla(
1552 QsciScintilla.SCI_USERLISTSHOW, listId,
1553 self._encodeString(self.UserSeparator.join(lst)))
1554
1555 self.updateUserListSize()
1556
1557 def autoCompleteFromDocument(self):
1558 """
1559 Public method to resize list box after creation.
1560 """
1561 super().autoCompleteFromDocument()
1562 self.updateUserListSize()
1563
1564 def autoCompleteFromAPIs(self):
1565 """
1566 Public method to resize list box after creation.
1567 """
1568 super().autoCompleteFromAPIs()
1569 self.updateUserListSize()
1570
1571 def autoCompleteFromAll(self):
1572 """
1573 Public method to resize list box after creation.
1574 """
1575 super().autoCompleteFromAll()
1576 self.updateUserListSize()
1577
1578 ###########################################################################
1579 ## work-around for buggy behavior
1580 ###########################################################################
1581
1582 def updateUserListSize(self):
1583 """
1584 Public method to resize the completion list to fit with contents.
1585 """
1586 children = self.findChildren(QListWidget)
1587 if children:
1588 userListWidget = children[-1]
1589 hScrollbar = userListWidget.horizontalScrollBar()
1590 if hScrollbar.isVisible():
1591 hScrollbarHeight = hScrollbar.sizeHint().height()
1592
1593 geom = userListWidget.geometry()
1594 geom.setHeight(geom.height() + hScrollbarHeight)
1595
1596 charPos = self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS)
1597 currentYPos = self.SendScintilla(
1598 QsciScintilla.SCI_POINTYFROMPOSITION, 0, charPos)
1599 if geom.y() < currentYPos:
1600 geom.setY(geom.y() - hScrollbarHeight)
1601 moveY = True
1602 else:
1603 moveY = False
1604
1605 userListWidget.setGeometry(geom)
1606 if moveY:
1607 userListWidget.move(geom.x(), geom.y() - hScrollbarHeight)
1608
1609 def __completionListSelected(self, listId, txt):
1610 """
1611 Private slot to handle the selection from the completion list.
1612
1613 Note: This works around an issue of some window managers taking
1614 focus away from the application when clicked inside a completion
1615 list but not giving it back when an item is selected via a
1616 double-click.
1617
1618 @param listId the ID of the user list (integer)
1619 @param txt the selected text (string)
1620 """
1621 self.activateWindow()
1622
1623 def updateVerticalScrollBar(self):
1624 """
1625 Public method to update the vertical scroll bar to reflect the
1626 additional lines added by annotations.
1627 """
1628 # Workaround because Scintilla.Redraw isn't implemented
1629 self.SendScintilla(QsciScintilla.SCI_SETVSCROLLBAR, 0)
1630 self.SendScintilla(QsciScintilla.SCI_SETVSCROLLBAR, 1)
1631
1632 ###########################################################################
1633 ## utility methods
1634 ###########################################################################
1635
1636 def _encodeString(self, string):
1637 """
1638 Protected method to encode a string depending on the current mode.
1639
1640 @param string string to be encoded (str)
1641 @return encoded string (bytes)
1642 """
1643 if isinstance(string, bytes):
1644 return string
1645 else:
1646 if self.isUtf8():
1647 return string.encode("utf-8")
1648 else:
1649 return string.encode("latin-1")
1650
1651 #########################################################################
1652 ## Methods below are missing from QScintilla.
1653 #########################################################################
1654
1655 if "setWrapStartIndent" not in QsciScintilla.__dict__:
1656 def setWrapStartIndent(self, indent):
1657 """
1658 Public method to set a the amount of characters wrapped sublines
1659 shall be indented.
1660
1661 @param indent amount of characters to indent
1662 @type int
1663 """
1664 self.SendScintilla(QsciScintilla.SCI_SETWRAPSTARTINDENT, indent)
1665
1666 if "getGlobalCursorPosition" not in QsciScintilla.__dict__:
1667 def getGlobalCursorPosition(self):
1668 """
1669 Public method to determine the point of the cursor.
1670
1671 @return point of the cursor
1672 @rtype QPoint
1673 """
1674 pos = self.currentPosition()
1675 x = self.SendScintilla(QsciScintilla.SCI_POINTXFROMPOSITION,
1676 0, pos)
1677 y = self.SendScintilla(QsciScintilla.SCI_POINTYFROMPOSITION,
1678 0, pos)
1679 return QPoint(x, y)
1680
1681 if "cancelCallTips" not in QsciScintilla.__dict__:
1682 def cancelCallTips(self):
1683 """
1684 Public method to cancel displayed call tips.
1685 """
1686 self.SendScintilla(QsciScintilla.SCI_CALLTIPCANCEL)
1687
1688 if "lineIndexFromPoint" not in QsciScintilla.__dict__:
1689 def lineIndexFromPoint(self, point):
1690 """
1691 Public method to convert a point to line and index.
1692
1693 @param point point to be converted
1694 @type QPoin
1695 @return tuple containing the line number and index number
1696 @rtype tuple of (int, int)
1697 """
1698 pos = self.positionFromPoint(point)
1699 return self.lineIndexFromPosition(pos)
1700
1701 ## #########################################################################
1702 ## ## Methods below have been added to QScintilla starting with version 2.x.
1703 ## #########################################################################
1704 ##
1705 ## if "newMethod" not in QsciScintilla.__dict__:
1706 ## def newMethod(self, param):
1707 ## """
1708 ## Public method to do something.
1709 ##
1710 ## @param param parameter for method
1711 ## """
1712 ## pass
1713 ##

eric ide

mercurial