I didn't manage to subclass CellRendererText but I got the job done the hard way with GenericCellRenderer. Below is the code for an editable multiline text cell renderer.

If you try it, use shift/ctrl/alt + return/keypad enter for linebreaking while editing the text in a cell.

It seems to work well. However, since I'm new to python and pygtk, any corrections or suggestions will be apprechiated.

Osmo


#!/usr/bin/env python # -*- coding: utf8 -*-

import pygtk
import gtk
import gobject
import pango


class CellTextView(gtk.TextView, gtk.CellEditable):


def set_text(self, text):

        text_buffer = self.get_buffer()
        text_buffer.set_text(text)


def get_text(self, *args):

        text_buffer = self.get_buffer()
        start = text_buffer.get_start_iter()
        end   = text_buffer.get_end_iter()
        return text_buffer.get_text(start, end, True)


def do_editing_done(*args): pass def do_remove_widget(*args): pass def do_start_editing(*args): pass


class CellRendererMultilineText(gtk.GenericCellRenderer):


__gproperties__ = { 'text': (gobject.TYPE_STRING, 'text', 'text displayed', '', gobject.PARAM_READWRITE) }

    __gsignals__ = {
        'edited': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
                   (gobject.TYPE_STRING, gobject.TYPE_STRING))
    }

    property_names = __gproperties__.keys()


def __init__(self):

        self.__gobject_init__()
        self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE)


def __getattr__(self, name):

        try:
            return self.get_property(name)
        except TypeError:
            raise AttributeError


def __setattr__(self, name, value):

        try:
            self.set_property(name, value)
        except TypeError:
            self.__dict__[name] = value


def do_get_property(self, property):

        if property.name not in self.property_names:
            raise TypeError('No property named %s' % (property.name,))
        return self.__dict__[property.name]


def do_set_property(self, property, value):

        if property.name not in self.property_names:
            raise TypeError('No property named %s' % (property.name,))
        self.__dict__[property.name] = value


def on_render(self, window, widget, bg_area, cell_area, exp_area, flags):

        x_offset, y_offset, width, height = self.on_get_size(widget, cell_area)
        layout = self.get_layout(widget)

        # Determine state to get text color right.
        if flags & gtk.CELL_RENDERER_SELECTED:
            if widget.get_property('has-focus'):
                state = gtk.STATE_SELECTED
            else:
                state = gtk.STATE_ACTIVE
        else:
            state = gtk.STATE_NORMAL

        widget.style.paint_layout(
            window, state, True, cell_area, widget, 'foo',
            cell_area.x + x_offset, cell_area.y + y_offset, layout
        )


def get_layout(self, widget): '''Gets the Pango layout used in the cell in a TreeView widget.'''

        layout = pango.Layout(widget.get_pango_context())
        layout.set_width(-1)    # Do not wrap text.

        if self.text:
            layout.set_text(self.text)
        else:
            layout.set_text('')

        return layout


def on_get_size(self, widget, cell_area):

        # The following size calculations have tested so that the TextView
        # will fully fit in the cell when editing and it will be the same
        # size as a CellRendererText cell with same amount or rows.

        xpad = 2
        ypad = 2

        xalign = 0
        yalign = 0.5

        layout = self.get_layout(widget)
        width, height = layout.get_pixel_size()

        x_offset = xpad
        y_offset = ypad

        if cell_area:

            x_offset = xalign * (cell_area.width - width)
            x_offset = max(x_offset, xpad)
            x_offset = int(round(x_offset, 0))

            y_offset = yalign * (cell_area.height - height)
            y_offset = max(y_offset, ypad)
            y_offset = int(round(y_offset, 0))

        width  = width  + (xpad * 2)
        height = height + (ypad * 2)

        return x_offset, y_offset, width, height


def on_start_editing(self, event, widget, path, bg_area, cell_area, flags):

        editor = CellTextView()
        editor.set_wrap_mode(gtk.WRAP_NONE)
        editor.connect('key-press-event', self.on_key_press_event, path)

        if self.text:
            editor.set_text(self.text)

        editor.grab_focus()
        editor.show()

        return editor


def on_key_press_event(self, widget, event, path): '''Catch pressing Enter keys.

        Shift, Ctrl or Alt combined with Return or Keypad Enter can be used
        for linebreaking. Pressing Return or Keypad Enter alone will finish
        editing.'''

        mask     = event.state
        keyname = gtk.gdk.keyval_name(event.keyval)

        accel_masks    = (gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK | \
                          gtk.gdk.MOD1_MASK)
        enter_keynames = ('Return', 'KP_Enter')

        if (keyname in enter_keynames) and not (mask & accel_masks):
            self.emit('edited', path, widget.get_text())
            widget.destroy()


gobject.type_register(CellTextView) gobject.type_register(CellRendererMultilineText)


def on_edited(widget, path, new_value, store, column):

    iter = store.get_iter(str(path))
    store.set(iter, column, new_value)


if __name__ == '__main__':

    store = gtk.ListStore(str, str)
    tree = gtk.TreeView()
    tree.set_model(store)

    tree.set_size_request(360, 140)
    tree.set_headers_visible(True)

    cr = gtk.CellRendererText()
    cr.connect('edited', on_edited, store, 0)
    cr.set_property('editable', True)
    column = gtk.TreeViewColumn('gtk.CellRendererText', cr, text = 0)
    tree.append_column(column)

    cr = CellRendererMultilineText()
    cr.connect('edited', on_edited, store, 1)
    column = gtk.TreeViewColumn('CellRendererMultilineText', cr, text = 1)
    tree.append_column(column)

    store.append(['Phou flou\nghou fhou.', 'Phou flou\nghou fhou.'])
    store.append(['Bhuu fvou\nghaa neff.', 'Bhuu fvou\nghaa neff.'])

    window = gtk.Window()
    window.set_position(gtk.WIN_POS_CENTER)
    window.connect('delete-event', gtk.main_quit)
    window.add(tree)

    window.show_all()
    gtk.main()


_______________________________________________ pygtk mailing list [email protected] http://www.daa.com.au/mailman/listinfo/pygtk Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to