1

I have been trying to find a way to use Pango markup with Gtk.TextView and Gtk.TextBuffer in Python GObject, but it seems like this functionality is only available for tooltips and labels. Gtk.TextBuffer has the insert_markup method, but requires Gtk.TextIter as input, and must be of specified length.

The issue here is that I want to use Gtk.TextView only for displaying text without it being editable. So while I think I understood how you use Gtk.TextTag with editable/selectable text to change its appearance (and even behaviour) substantially, I am not entirely sure how you do the same with static text. What is the simplest way of applying markup to such?

For example: turning "<b>Some text</b>" into "Some text" (or whichever tags would be used)

Holsterbau
  • 87
  • 1
  • 7
  • As it says in the docs for `insert_markup`, you can use `-1` for the length and get a textiter with `Gtk.TextBuffer.get_start_iter()` for example. I don't understand your problem with that approach. – elya5 Jan 04 '17 at 14:53
  • I don't know how to place a `Gtk.TextIter` in front of a "" and at the end of an "" is the problem. I grasp the concept of the relationship between `Gtk.TextBuffer`, `Gtk.TextTag` and `Gtk.TextIter` just fine otherwise, I think, but it seems to be more complicated when the text is read-only. I hope that makes it more comprehensive. – Holsterbau Jan 04 '17 at 15:02
  • But if you want to show the whole text with the markup applied, you don't need to put the `TextIter` in front of the individual markup tags – elya5 Jan 04 '17 at 16:28
  • Aaah, that makes a lot more sense now. I knew there was something somewhat obvious I was missing. I wish I could mark your comment as the answer. Thanks a whole lot, that cleared it up. – Holsterbau Jan 04 '17 at 16:40
  • I don't understand, my answer does not answer you question? Even with a complete running example? – gianmt Jan 07 '17 at 15:07

1 Answers1

6

There is a nice example in the Python GTK+ 3 Tutorial, TextView Example

But to make it clearer (hopefully) on the important parts, as you have guessed you have to use text tags, you have to define those in the TextBuffer, not in the TextView, e.g.

self.tag_bold = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD)

and then you can apply your tag to the portion of text that you want to make bold, in order to do that you will have to provide to the TextBuffer.apply_tag() method the bounds (start, end) of that portion of text, like:

start, end = self.textbuffer.get_selection_bounds()
self.textbuffer.apply_tag(self.tag_bold, start, end)

and you will be all set.

In the above example the bounds are taken by the portion of text selected by the user, but of course if you are displaying a read-only text you can provide the bounds yourself in the code, look at the TextBuffer documentation.

You can also add the text with valid pango markup by the method:

self.textbuffer.insert_markup(iter, markup)

Would be nice if the method could return the new iter pointing at the end of the inserted text, which would makes life a lot easier, but the method comes from plain introspection, it would require an override to act like that.

See the minimal example here below (you can make it way nicer):

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango

class TextViewWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="TextView Example")

        self.set_default_size(-1, 350)

        self.grid = Gtk.Grid()
        self.add(self.grid)

        self.create_textview()

    def create_textview(self):
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 1, 3, 1)

        self.textview = Gtk.TextView()
        self.textbuffer = self.textview.get_buffer()
        start_iter = self.textbuffer.get_start_iter()

        self.textbuffer.insert(start_iter, "This is some text ")
        self.textbuffer.insert_markup(self.textbuffer.get_end_iter(), "<b>and some bold text</b>", -1)

        scrolledwindow.add(self.textview)

win = TextViewWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
gianmt
  • 1,162
  • 8
  • 15
  • Ah, yes, I probably should have said that I already have come to roughly the same conclusion before. I made a more "general question" in case I have missed something more obvious that Stack fellows could propose. However, if this is the only way of going about tagging read-only text in `Gtk.TextBuffer`, then I simply don't know how you place `Gtk.TextIter` in the desired places to tag specific sections of the text. – Holsterbau Jan 04 '17 at 12:20
  • 1
    I've added a sample using iters and setting the markup – gianmt Jan 04 '17 at 20:58
  • Well done, shame you didn't get your answer accepted, sure helped me. – andy.holmes Jul 25 '17 at 05:27