Symbol margin

self.__editor.setMarginType(n, QsciScintilla.SymbolMargin)
self.__editor.setMarginType(n, QsciScintilla.SymbolMarginDefaultBackgroundColor)
self.__editor.setMarginType(n, QsciScintilla.SymbolMarginDefaultForegroundColor)
self.__editor.setMarginType(n, QsciScintilla.SymbolMarginColor)

All these functions set the type of margin n to SymbolMargin. The difference between them has to do with the background color.

  • The first function displays a symbol margin on the usual grey background. You can change the color, but remember that a call to the function
    setMarginsBackgroundColor(color) changes all margin background colors (including this one).
     
  • The second function displays the symbol margin on what the paper color of the editor is. As such, this margin won’t be affected by a call to
    setMarginsBackgroundColor(color).
     
  • The third function displays the symbol margin on what the font color of the editor is. As such, this margin won’t be affected by a call to
    setMarginsBackgroundColor(color).
     
  • The last function provides most flexibility, but is only available in QScintilla 2.10. The background color of this symbol margin can be chosen regardless of all other settings. You have to use the function setMarginBackgroundColor(margin_nr, color) for that. Notice that this function has no ‘s’ between setMargin and BackgroundColor, and it got two parameters!
     

So right now you have defined a SymbolMargin, and perhaps given it a background color. Great. But eventually you want to display symbols in it. The procedure to do that is quite complicated. Let’s get through it step-by-step.

Creating symbols

To create a symbol, you’ve got 3 options

  • Builtin symbols
    QScintilla has several builtin symbols:

    • – QsciScintilla.Circle
    • – QsciScintilla.Rectangle
    • – QsciScintilla.RightTriangle
    • – QsciScintilla.SmallRectangle
    • – …
  • QPixmap
    Any QPixmap object can be used as a symbol.
     
  • QImage
    Also a QImage object can be used.
     

Let’s create 5 symbols to demonstrate their use:

sym_0 = QImage("green_dot.png").scaled(QSize(16, 16))
sym_1 = QImage("green_arrow.png").scaled(QSize(16, 16))
sym_2 = QImage("red_dot.png").scaled(QSize(16, 16))
sym_3 = QImage("red_arrow.png").scaled(QSize(16, 16))
sym_4 = QsciScintilla.Circle

 

Assigning markers to symbols

Now you need to assign a marker to each of the symbols. Think of a marker as a wrapper around your symbol, whichever mental picture suits you best. Once you’ve assigned the markers, you’ll only interact with them – not with the bare symbols anymore!
Use the function markerDefine(symbol, marker_nr) to assign all the markers:

self.__editor.markerDefine(sym_0, 0)
self.__editor.markerDefine(sym_1, 1)
self.__editor.markerDefine(sym_2, 2)
self.__editor.markerDefine(sym_3, 3)
self.__editor.markerDefine(sym_4, 4)

The assignment should now be like this:

Intermezzo
Please take a step back now. Did you notice? The creation of the symbol-object is something you’ve done yourself explicitly:
sym_0 = QImage("green_dot.png").scaled(QSize(16, 16))
But you did not create the marker-object yourself, did you? When defining a marker, you give it a number and QScintilla creates the marker-object internally:
self.__editor.markerDefine(sym_0, 0)
Okay, that’s it for this short intermezzo. Time to move on..

 

To display a symbol in the margin(s) of a specific line, you’ve got to add the marker of that symbol to that line. The next paragraph digs into that. But first we need to clear out some confusions. Of course you want to add a marker to several codelines. And that’s perfectly possible in QScintilla. The following figure illustrates the green dot marker/symbol added to two codelines. This can lead to some terrible terminology confusion. When I speak about a “marker”, do I refer to the general green dot marker/symbol, or a specific green dot on a specific codeline?

  Unfortunately you’ll have to figure out the meaning of “marker” from the context. It’s vital to know the two distinct meanings:

  • 1. A marker sometimes refers to – for example – the green dot maker/symbol in general. This general meaning was used in this paragraph (Assigning markers to symbols).
    ID: marker_nr          Markers don’t have fancy names. Their names are marker_0, marker_1, … up to marker_31. And as you can already guess, they are identified with numbers 0 -> 31.
     
  • 2. A marker sometimes refers to a specific marker/symbol on a specific codeline.
    ID: marker_handle          Later – in the paragraph about handles – we will see that each such marker has a unique ID number. The number can be any integer 0 -> 9999…

 

Displaying symbols

To display a symbol in the margin(s) of a specific line, you’ve got to add the marker of that symbol to that line with the following function:
markerAdd(line_nr, marker_nr)
Did you notice that this function has NO parameter margin_nr to single out a specific margin? That’s right – the function actually attempts to put the symbol in each symbol margin left to the line. The following figure illustrates the effect of self.__editor.markerAdd(20, 2) which adds marker nr 2 (the red dot) to line nr 20. As you can see, the symbol appears in both symbol margins!

But hey, that is so weird! It doesn’t make sense to define multiple symbol margins – as they are just identical duplicates? Fortunately QScintilla provides a mechanism to filter out some symbols from a margin. This is how you put a filter on a margin:


So let us continue the example. We install a filter on margin 1 and margin 3:

self.__editor.setMarginMarkerMask(1, 0b10101)
self.__editor.setMarginMarkerMask(3, 0b01010)

Time to update the previous figure:

The filter (also called marker mask) can maximally have 32 entries. That’s because the filter is in fact a 32-bit wide binary number. Consequently this is also the limit on the amount of markers (symbols) you can define in your editor.

 

Handles to markers

Suppose you’ve added millions of markers (marker meaning 2.) to your codelines. How on earth do you keep track of them? QScintilla has a convenient mechanism for that. Each marker, when added to a codeline, gets a unique ID number: a handle. To avoid confusion: if you add the same green-dot marker to 2 different codelines, each of them gets a different ID number. So the ID number points to a specific marker on a specific codeline:

The unique ID number (or handle) is given to you once, when you add the marker to the codeline:
integer handle          markerAdd(line_nr, marker_nr)
It returns the handle as an integer. If you want to use it, you’ve got to capture it at this function call!

Useful functions

Let us examine some useful functions for dealing with markers:

  • markerDelete(line_nr, marker_nr)
    This function deletes a marker from a codeline (duh..).
     
  • markerDeleteHandle(marker_handle)
    This function does exactly the same as the previous one. But instead of giving the codeline, you hand over the handle (unique ID number) of the marker that you want to delete. Notice that the term “marker” is used here in the second meaning – the specific one.
     
  • markerDeleteAll(marker_nr)
    Now the term “marker” is used in the first meaning – the general one. You give the marker ID (0 .. 31) number, and the editor will delete all markers of that type.
     
  • markersAtLine(line_number)
    This function returns a 32-bit integer representing a 32-bit mask of all markers added to that line. Imagine that a specific line has a red dot and a red arrow marker in its margins. The function would return the following bit mask: 0b01100.
     
  • markerLine(marker_handle)
    This function returns the line number of a specific marker.
     
  • markerFindNext(starting_line_nr, marker_mask)
    With this function you can search forwards for markers. The marker_mask parameter is a bit mask defining the set of markers you want to search for. If you want to search for red dots and red arrows, then your mask should be 0b01100.
     
  • markerFindPrevious(starting_line_nr, marker_mask)
    Same as previous function – but searches backwards.