Skip to content

Instantly share code, notes, and snippets.

@otsaloma
Created February 26, 2012 01:43
Show Gist options
  • Save otsaloma/1912166 to your computer and use it in GitHub Desktop.
Save otsaloma/1912166 to your computer and use it in GitHub Desktop.
Line numbers in Gtk3 text view margin
#!/usr/bin/env python3
from gi.repository import Gtk
from gi.repository import Pango
def on_text_view_draw(text_view, cairoc):
print("Drawing...")
# XXX: Rest of function not yet ported.
text_buffer = text_view.get_buffer()
bounds = text_buffer.get_bounds()
text = text_buffer.get_text(*bounds)
nlines = text.count("\n") + 1
layout = pango.Layout(text_view.get_pango_context())
layout.set_markup("\n".join([str(x + 1) for x in range(nlines)]))
layout.set_alignment(Pango.Alignment.RIGHT)
width = layout.get_pixel_size()[0]
text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, width + 4)
y = -text_view.window_to_buffer_coords(Gtk.TextWindowType.RIGHT, 2, 0)[1]
window = text_view.get_window(Gtk.TextWindowType.RIGHT)
window.clear()
text_view.style.paint_layout(window=window,
state_type=Gtk.STATE_NORMAL,
use_text=True,
area=None,
widget=text_view,
detail=None,
x=2,
y=y,
layout=layout)
text_view = Gtk.TextView()
text_buffer = text_view.get_buffer()
text_buffer.insert_at_cursor("ABC\nabc")
text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, 24)
text_view.connect("draw", on_text_view_draw)
scroller = Gtk.ScrolledWindow()
scroller.set_shadow_type(Gtk.ShadowType.IN)
scroller.add(text_view)
window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)
window.set_position(Gtk.WindowPosition.CENTER)
window.set_default_size(300, 100)
window.set_border_width(12)
window.add(scroller)
window.show_all()
Gtk.main()
@refi64
Copy link

refi64 commented Dec 28, 2014

To get the number of lines, you can just use text_buffer.get_line_count(). Also, the paint_layout line should be:

Gtk.render_layout(text_view.get_style_context(), cairoc, 2, y, layout)

window.clear() also doesn't work and needs to be removed.

And, line 12 uses the lowercase pango instead of the first letter being capitalized (Pango).

@otsaloma
Copy link
Author

otsaloma commented Mar 2, 2015

I'm a bit late to respond, I haven't apparently gotten notifications of comments. Anyway, this was some half-ported code while struggling to port to PyGI while marred by PyGI and Python 3 packaging bugs in Debian. All is well for me since and, while it's not far off, I hope no one considers this a tutorial.

https://bugzilla.gnome.org/show_bug.cgi?id=671318

@muflone
Copy link

muflone commented Nov 22, 2015

Hi

do you have a working solution to add line numbers to a Gtk.TextView?

@turboiii
Copy link

I found a solution to display lines number in gtk3

#!/usr/bin/env python
# coding: utf-8 
from gi.repository import Gtk,Gdk
from gi.repository import Pango


def recup_lignes(textbuffer,premier_y, dernier_y, coords_buffer, numeros):
    # On recupere l'iterateur du premier y.
    iter, top = textbuffer.get_line_at_y(premier_y)

    # On recupere la position de chaque iterateur et on l'ajoute 
    # a la liste. On s'arrete apres dernier_y.
    nombre,taille = 0,0
    while not iter.is_end():
        y, hauteur = textbuffer.get_line_yrange(iter)
        coords_buffer.append(y)
        num_ligne = iter.get_line()
        numeros.append(num_ligne)
        nombre += 1
        # suite nouvelle étude je le remet
        if (y + hauteur) >= dernier_y:
            break        
        iter.forward_line()
    return nombre

def on_text_view_draw(text_view, cairo_context):
    text_buffer = text_view.get_buffer()
    start,end = text_buffer.get_bounds()
    text = text_buffer.get_text(start,end,False)

    nlines = text.count("\n") + 1


    #collect size of visible part of window
    rectangle_visible = text_view.get_visible_rect()
    premier_y = rectangle_visible.y
    dernier_y = premier_y +rectangle_visible.height 

    # collect numeros & pixels to be display 
    numeros = []
    pixels = []    
    nombre = recup_lignes(text_view,premier_y, dernier_y, pixels, numeros)
    # Affichage de numéros internationalises !
    layout = text_view.create_pango_layout("")

    pos_horizontal = 2
    for i in range(nombre):
        x, pos = text_view.buffer_to_window_coords(Gtk.TextWindowType.RIGHT, 0, pixels[i])
        chaine = "<span weight='bold' foreground='red'>%d </span>" % numeros[i]
        layout.set_markup(chaine,len(chaine))
        # met les numeros dans la zone texte
        Gtk.render_layout(text_view.get_style_context(), cairo_context, pos_horizontal, pos, layout)

long_text = u"0 Your Answer\n\
 1 Thanks for contributing an answer to Stack Overflow!\n\
 2   Please be sure to answer the question. Provide details and share your research!\n\
 3\n\
 4 But avoid …\n\
 5\n\
 6  Asking for help, clarification, or responding to other answers.\n\
 7  Making statements based on opinion; back them up with references or personal experience.\n\
 8\n\
 9To learn more, see our tips on writing great answers.\n\
10 Your Answer\n\
11Thanks for contributing an answer to Stack Overflow!\n\
12    Please be sure to answer the question. Provide details and share your research!\n\
13 \n\
14 But avoid …\n\
15\n\
16   Asking for help, clarification, or responding to other answers.\n\
17    Making statements based on opinion; back them up with references or personal experience.\n\
18 \n\
19 To learn more, see our tips on writing great answers.\n"

tooltip = u'textview avec numérotation de ligne\n\
<b>Warning</b> la numérotation ne fonctionne correctement que si on ne fait pas circuler le scrolling'


text_view = Gtk.TextView()    
text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, 54)
text_view.set_border_window_size(Gtk.TextWindowType.LEFT,54)
text_view.set_editable(True)
text_view.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse('light green'))# non OK change marg like in gtk2
text_view.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse('orange'))#background text OK
text_view.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse('green'))# modifie la couleur du texte OK
text_view.modify_font( Pango.FontDescription('Arial normal 10'))# OK
text_view.set_tooltip_markup(tooltip)
text_view.connect("draw", on_text_view_draw)

text_buffer = text_view.get_buffer()
text_buffer.insert_at_cursor(long_text) #sympath pour inserer la où est le curseur mais pas nécessaire ici
#text_buffer.insert_markup(long_text)

scroller = Gtk.ScrolledWindow()
scroller.set_hexpand(True)
scroller.set_vexpand(True)
scroller.set_shadow_type(Gtk.ShadowType.IN)
scroller.add(text_view)

window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)
window.set_position(Gtk.WindowPosition.CENTER)
window.set_default_size(300, 200)
window.set_border_width(12)
window.add(scroller)
window.show_all()

demo = False
if demo:
    for i in dir(Gtk.TextBuffer):
        print i
Gtk.main()

@tclsteixeira
Copy link

Gtk 3 - Doesn't work. No numbers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment