Bug in Gtk::TreeView#set_cursor?

Below an example program in which I try to make something like an
editable grid.

If you edit a field and press Enter or Tab, it should start editing the
next cell to the right.
From the documentation:
http://ruby-gnome2.sourceforge.jp/hiki.cgi?Gtk%3A%3ATreeView#set_cursor

"Additionally, if column is specified, and start_editing is true, then
editing should be started in the specified cell. "

I tried this in method connect_edit. I supplied both, the TreePath and
the “next” TreeViewColumn. Regardless how if the third option is true or
false, the next cell will only start editing after pressing spacebar.

Anyone has an idea what’s wrong?


#!/usr/bin/ruby

require ‘gtk2’

def connect_edit(renderer,i,view)
renderer.signal_connect(“edited”) do |rendr, row, new_text, model|
iter = view.model.get_iter(row)
iter[i] = new_text
view.set_cursor(Gtk::TreePath.new(row.to_s),view.get_column(i+1),true)
# if 3rd option ‘start_editing’ set to false it has the same effect
view.grab_focus
end
end

liststore = Gtk::ListStore.new(String, String, String, String, String,
String)
5.times do
iter = liststore.append
i = 0
6.times do
iter[i] = “bla”
i = i + 1
end
end

view = Gtk::TreeView.new(liststore)

i = 0
[“foo”,“bar”,“blah”,“more”,“spaceholder”,“stuff”].each do |c|

renderer = Gtk::CellRendererText.new
renderer.editable = true
connect_edit(renderer,i,view)

col = Gtk::TreeViewColumn.new(c, renderer, :text => i)
view.append_column col
i = i + 1
end

w = Gtk::Window.new
w << view
w.show_all
Gtk.main

hi, i looked at it, we share common interests :slight_smile:
the attached one works. i disabled the grab.

Dobai-Pataky Bálint wrote:

hi, i looked at it, we share common interests :slight_smile:
the attached one works. i disabled the grab.

Interestingly it works if you use Enter-Key. There is some wired
behaviour when using the tab key for changing columns. Try it out.

Dobai-Pataky Bálint wrote:

hmm, yeah.
but at least we know now: treeview.grab stops the editing, which was
started by set_cursor

The question is why. The manual says
“This method is often followed by Gtk::Widget#grab_focus in order to
give keyboard focus to the widget.”

So, what, instead of the treeview, should I focus to get the next cell
focused (must be not stop editing)?

hmm, yeah.
but at least we know now: treeview.grab stops the editing, which was
started by set_cursor

i have edited your script to the point where i found out what is
happening, but i lost it :(.
basically i disabled the treeview’s focusing ability, thus it did not do
the tab trick(but did not focus on cells).
i changed your TreeView.grab_focus to
nextCellRenderer_to_edit.grab_focus (this solved the problem of
grab_focus forces the CellRenderer to exit editing mode)
and i hooked the editing-canceled and editing-started signals to see
what is happening, and i found out that when that strange behavior
occurs it’s because of a premature editing-canceled event is called on
the second CellRenderer.

and i concluded that if you want to imitate an excel-like grid object
than you’ll end up writing your own CellRenderer object, better your own
TreeView, which will not be a TreeView, but probably a Gtk::Layout or a
Table with Labels/Entries(in editing mode) on it.
for one reason, TreeView has a row selection mechanism, and it’ll not
emit the editing signal to the CellRenderer if the row is not selected
first, which means at least two mouse clicks to enter a Renderer’s
editing mode which was not in the selected row.

Dobai-Pataky Bálint wrote:

i changed your TreeView.grab_focus to
nextCellRenderer_to_edit.grab_focus (this solved the problem of
grab_focus forces the CellRenderer to exit editing mode)
Huh? How did you do that, since the CellRenderer is not a Gtk::Widget
…?

and i concluded that if you want to imitate an excel-like grid object
than you’ll end up writing your own CellRenderer object, better your own
TreeView, which will not be a TreeView, but probably a Gtk::Layout or a
Table with Labels/Entries(in editing mode) on it.
I suppose that won’t be a trivial task using a Gtk::Layout and create a
Treeview “from the scratch”.

Joachim G. wrote:

Dobai-Pataky Bálint wrote:

i changed your TreeView.grab_focus to
nextCellRenderer_to_edit.grab_focus (this solved the problem of
grab_focus forces the CellRenderer to exit editing mode)

Huh? How did you do that, since the CellRenderer is not a Gtk::Widget
…?

sorry, i wasn’t precise.
http://ruby-gnome2.sourceforge.jp/hiki.cgi?Gtk%3A%3ACellRenderer#editing-started%3A+self%2C+editable%2C+path
i figured the editable is the widget which appears when a CellRenderer
enters editing mode.
that’s a widget, and can grab_focus.

Ok, I think I got the state you were describing now, see attachment.

When pressing tab without a change, editing-canceled is emitted shortly
after editing-started is.

When changing the text, the behaviour gets more strange and I get
outputs like
GLib-GObject-WARNING
**:/build/buildd/glib2.0-2.14.1/gobject/gsignal.c:1741: instance
0x8405460' has no handler with id632’

When uncommenting the line
view.grab_focus = false

Tab doesn’t work anymore.

The editable widget which is created by Gtk::CellRendererText is a
Gtk::Entry, so since the Entry is a Gtk::Widget I could catch a
key-press-event and check for the Tab key… what do you think?

I wonder if I can change the widget which is spawned by the
CellRendererText or if I need to write my own CellRenderer?

Joachim G. wrote:

Ok, I think I got the state you were describing now, see attachment.

there is none.

When pressing tab without a change, editing-canceled is emitted shortly
after editing-started is.

yup

When changing the text, the behaviour gets more strange and I get
outputs like
GLib-GObject-WARNING
**:/build/buildd/glib2.0-2.14.1/gobject/gsignal.c:1741: instance
0x8405460' has no handler with id632’

yup

When uncommenting the line
view.grab_focus = false

Tab doesn’t work anymore.

yup, becouse TreeView is not changing it’s childs’ focus.

The editable widget which is created by Gtk::CellRendererText is a
Gtk::Entry, so since the Entry is a Gtk::Widget I could catch a
key-press-event and check for the Tab key… what do you think?

i agree, i thought of that. something like this(i haven’t tested it):

renderer.signal_connect(“editing-started”){|me,ewidget,pa|
ewidged.signal_connect(“key-release-event”){|me,event|
if event.keyval == Gdk::Keyval::Gdk_Tab
}

I wonder if I can change the widget which is spawned by the
CellRendererText or if I need to write my own CellRenderer?

i don’t know anything about writing a CellRenderer, but i’m interested
in it (i’d need a CellRendererButton).

i think i solved the problem.
you should jump to the next column, only when Enter was pressed on the
editable_widget.
that will not change the Treeview’s behavior, will not jump forward on
editing-cancelled ny any mode(ESC or TAB)

Joachim G. wrote:

Dobai-Pataky Bálint wrote:

i think i solved the problem.
you should jump to the next column, only when Enter was pressed on the
editable_widget.

So as I understand you correctly you say that I should fix the problem
by not pressing Tab to get to the next column? But I want to…

try out my suggestion.
here is a simplified version of the CellRenderer i’m talking about. -
simplified on the fly, not tested, but you should get the idea.
currently does not jump on tab, but should be not too hard to modify.
please let me know, if/how you did it.

class MyCellRendererText < Gtk::CellRendererText
def initialize(view,model_col_num)
@view=view
@model_col_num=model_col_num
@jump_to_next=false
super()
set_editable_set(true)
set_editable(true)
signal_connect(“edited”) do |me,path,new_value|
[email protected]_iter(path)
if @jump_to_next
if next_col=view.get_column(model_col_num+1)
view.set_cursor(Gtk::TreePath.new(path),next_col,true)
end
@jump_to_next=false
end
true
end
signal_connect(“editing-started”){|cell, editable_widget, path|
editable_widget.signal_connect(“key-press-event”){|me,event|
@jump_to_next= Gdk::Keyval.to_name(event.keyval) ==
“Return”
false
}
}
end
attr_accessor :model_col_num
attr_accessor :view

end

Dobai-Pataky Bálint wrote:

i think i solved the problem.
you should jump to the next column, only when Enter was pressed on the
editable_widget.
So as I understand you correctly you say that I should fix the problem
by not pressing Tab to get to the next column? But I want to…

simplified on the fly, not tested, but you should get the idea.
I made it, thanks to your ideas. See attachment for code.

My renderer now looks like this
class MyCellRendererText < Gtk::CellRendererText
def initialize
super()
set_editable_set(true)
set_editable(true)
signal_connect(“editing-started”){|cell, editable_widget, path|
editable_widget.signal_connect(“key-press-event”){|me,event|
key = Gdk::Keyval.to_name(event.keyval)
if key == “Tab”
me.editing_done
me.remove_widget
end
false
}
}
end
end

The only thing I’ve not yet implemented is to jump to the next row/first
column when finished editing of the last column. But that’s a trivial
thing to do.

Maybe one could re-pack the edited signal to the renderer.