I want to save textview's buffer in pdf format. I can do it using reportlab if it's just a simple text. But, what if I want to save everything, from text with its tags and also images?
from gi.repository import Gtk, GdkPixbuf
import pango
from reportlab.pdfgen import canvas
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.textview = Gtk.TextView()
self.textbuffer = self.textview.get_buffer()
self.tag_bold = self.textbuffer.create_tag("bold",
weight=pango.WEIGHT_BOLD)
self.tag_italic = self.textbuffer.create_tag("italic",
style=pango.STYLE_ITALIC)
pix = GdkPixbuf.Pixbuf.new_from_file_at_size('baby.jpg', 50, 50)
tag = [self.tag_bold,
self.tag_italic]
self.textbuffer.insert_pixbuf(self.textbuffer.get_end_iter(), pix)
for i in range(20):
self.textbuffer.insert_with_tags(self.textbuffer.get_end_iter(),
'line%d\n' % (i+1),
tag[i % 2])
self.box.pack_start(self.textview, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
Gtk.main()
def on_button_clicked(self, widget):
canv = canvas.Canvas('tes.pdf')
for i in range(self.textbuffer.get_line_count()):
a = self.textbuffer.get_iter_at_line(i)
b = self.textbuffer.get_iter_at_line(i+1).get_offset()
c = self.textbuffer.get_iter_at_offset(b - 1)
t = self.textbuffer.get_text(a, b, True)
line = 750 - (15 * l)
canv.drawString(40, line, t)
canv.save()
if __name__ == '__main__':
gui = gui()
EDIT: drahnr suggest to use cairo instead. Okay, I think it's a better idea since reportlab coordinate start from bottom left and cairo coordinate start from top left. Below is my code using cairo.
from gi.repository import Gtk, GdkPixbuf, Gdk
import pango
import cairo
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.textview = Gtk.TextView()
self.window.add(self.textview)
self.initText()
self.createPDF()
self.window.show_all()
Gtk.main()
def initText(self):
self.tag_bold = self.textview.get_buffer().create_tag("bold", weight=pango.WEIGHT_BOLD)
self.tag_italic = self.textview.get_buffer().create_tag("italic", style=pango.STYLE_ITALIC)
pix = GdkPixbuf.Pixbuf.new_from_file_at_size('baby.png', 50, 50)
tag = [self.tag_bold, self.tag_italic]
self.textview.get_buffer().insert_pixbuf(self.textview.get_buffer().get_end_iter(), pix)
self.textview.get_buffer().insert(self.textview.get_buffer().get_end_iter(), '\n')
for i in range(20):
self.textview.get_buffer().insert_with_tags(self.textview.get_buffer().get_end_iter(), 'line%d' % (i+1), tag[i % 2])
self.textview.get_buffer().insert(self.textview.get_buffer().get_end_iter(), '\n')
def createPDF(self):
line = 30
row = 5
pos = 0
ps = cairo.PDFSurface('tes.pdf', 600, 770)
cr = cairo.Context(ps)
while pos != self.textview.get_buffer().get_end_iter().get_offset():
if self.textview.get_buffer().get_iter_at_offset(pos).has_tag(self.tag_bold):
cr.select_font_face('Times', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
elif self.textview.get_buffer().get_iter_at_offset(pos).has_tag(self.tag_italic):
cr.select_font_face('Times', cairo.FONT_SLANT_ITALIC, cairo.FONT_WEIGHT_NORMAL)
else:
cr.select_font_face('Times', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
t = self.textview.get_buffer().get_slice(self.textview.get_buffer().get_iter_at_offset(pos), self.textview.get_buffer().get_iter_at_offset(pos+1), False)
if t == '\n':
line += 12
row = 5
elif t == unichr(0xFFFC):
pix = self.textview.get_buffer().get_iter_at_offset(pos).get_pixbuf()
Gdk.cairo_set_source_pixbuf(cr, pix, 8 * row, line)
line += pix.get_width()
cr.paint()
else:
cr.move_to(8 * row, line)
cr.show_text(t)
pos=pos+1
row += 1
if __name__ == '__main__':
gui()
literally it's still the same. I should hardcode it to draw everything. and drahnr suggest to use gtk_widget_draw to render it to cairo surface.