How to let Gtk CellRendererText display newlines during edit?

Viewed 46

My Gtk app currently reads data from an external database/file, then add it to a Gtk Treeview. One of the columns allows newlines, which is correctly displayed in the Treeview when single-paragraph-mode is false.

cell with newlines

However, when I double click to edit, the cell turns into a single line entry box where a carriage return symbol (like ⤶) replaces the newlines.

cell with newlines being edited

This makes it impossible to edit a cell with lots of newlines because they appear as one single line. Is it possible to render the newlines as actual newlines during editing? In other words, I want single-paragraph-mode=false to apply to the cell when it is being edited

I've read the documentation for CellRendererText and CellRenderer, but it is rather lacking. Things like max-width-chars apply to the cell whether editing or not.

This code demonstrates what I mean. (It uses gtk-rs but an answer using C is fine too):

use gtk::glib;
use gtk::prelude::*;

fn main() {
    let application = gtk::Application::new(
        Some("com.example.xyz"),
        Default::default(),
    );
    application.connect_activate(build_ui);
    application.run();
}

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_title(Some("App"));
    window.set_default_size(800, 800);

    let grid = gtk::Grid::builder()
        .column_spacing(5)
        .row_spacing(10)
        .build();

    window.set_child(Some(&grid));

    let (treeview, _treestore) = build_treeview();

    let sw = gtk::ScrolledWindow::builder()
        .child(&treeview)
        .vexpand(false)
        .vexpand_set(false)
        .max_content_height(10)
        .build();

    // column, row, width, height
    grid.attach(&sw, 0, 0, 1, 1);

    window.show();
}

fn build_treeview() -> (gtk::TreeView, gtk::TreeStore) {
    let treestore = gtk::TreeStore::new(&[glib::Type::STRING].repeat(4));
    let treeview = gtk::TreeView::builder()
        .hexpand(true)
        .vexpand(true)
        .enable_grid_lines(gtk::TreeViewGridLines::Both)
        .model(&treestore)
        .build();

    for (i, title) in ["Title", "Description", "Path1", "Path2"]
        .iter()
        .enumerate()
    {
        let cell_renderer = gtk::CellRendererText::builder()
            .editable(true)
            .xalign(0.0)
            .single_paragraph_mode(false)
            .build();
        treeview.insert_column_with_attributes(
            i.try_into().unwrap(),
            title,
            &cell_renderer,
            &[(&"text", i.try_into().unwrap())],
        );
        let ts = treestore.clone();
        cell_renderer.connect_edited(move |_renderer, row, text| {
            ts.set_value(
                &ts.iter(&row).unwrap(),
                i.try_into().unwrap(),
                &text.to_value()
            );
        });
    }

    treestore.insert_with_values(
        None,
        None,
        &[
            (0, &"one"),
            (1, &"two\ntwo\ntwo\ntwo"),
            (2, &"three"),
            (3, &"four"),
        ],
    );
    (treeview, treestore)
}
0 Answers
Related