Create  Edit  FrontPage  Index  Search  Changes  History  RSS  Login

tut-gtk2-treev-etr

Editable Text Renderers

treev-etr-01.png

It would be very helpful to allow the user to edit the contents of the tree view. As it turns out, GTK+ provides a simple way to edit textual components of the tree view. To accomplish this you employ the Gtk::CellRendererText's edited signal. When a user clicks on a cell in the selected row that is marked as editable, the Gtk::Entry widget is placed in that cell. After the user presses the Enter key or removes the focus from the text entry, the edited signal is emitted. Let's have a look at the following program listing of the application demonstrating this:


editable_cell.rb

#!/usr/bin/env ruby
require 'gtk2'

# Add three columns to the GtkTreeView. All three of the
# columns will be displayed as text, although one is a boolean
# value and another is an integer.
def setup_tree_view(treeview)
  # Create a new GtkCellRendererText, add it to the tree
  # view column and append the column to the tree view.
  renderer = Gtk::CellRendererText.new
  column = Gtk::TreeViewColumn.new("Buy", renderer, "text" => BUY_COLUMN)
  treeview.append_column(column)
  renderer = Gtk::CellRendererText.new
  column = Gtk::TreeViewColumn.new("Count", renderer, "text" => QTY_COLUMN)
  treeview.append_column(column)

  #  Setup the third column in the tree view to be editable.
  renderer = Gtk::CellRendererText.new
  renderer.editable = true
  renderer.signal_connect('edited') do |w, path, fld_value|
    cell_edited(path, fld_value, treeview)
  end
  column = Gtk::TreeViewColumn.new("Product", renderer, "text" => PROD_COLUMN)
  treeview.append_column(column)
end

# Apply the changed text to the cell.
def cell_edited(path, str, trvu)
  if str != ""
    iter = trvu.model.get_iter(path)
    iter[PROD_COLUMN] = str
  end
end

window = Gtk::Window.new("Grocery List")
window.resizable = true
window.border_width = 10
window.signal_connect('destroy') { Gtk.main_quit }
window.set_size_request(275, 300)

class GroceryItem
  attr_accessor :product_type, :buy, :quantity, :product
  def initialize(t,b,q,p)
    @product_type, @buy, @quantity, @product = t, b, q, p
  end
end
BUY_COLUMN = 0; QTY_COLUMN = 1; PROD_COLUMN = 2
P_CATG = 0; P_CHILD = 1

list = Array.new
list[0] = GroceryItem.new(P_CATG,     true,  0, "Cleaning Supplies")
list[1] = GroceryItem.new(P_CHILD,    true,  1, "Paper Towels")
list[2] = GroceryItem.new(P_CHILD,    true,  3, "Toilet Paper")
list[3] = GroceryItem.new(P_CATG,     true,  0, "Food")
list[4] = GroceryItem.new(P_CHILD,    true,  2, "Bread")
list[5] = GroceryItem.new(P_CHILD,    false, 1, "Butter")
list[6] = GroceryItem.new(P_CHILD,    true,  1, "Milk")
list[7] = GroceryItem.new(P_CHILD,    false, 3, "Chips")
list[8] = GroceryItem.new(P_CHILD,    true,  4, "Soda")

treeview = Gtk::TreeView.new
setup_tree_view(treeview)

# Create a new tree model with three columns, as Boolean, 
# integer and string.
store = Gtk::TreeStore.new(TrueClass, Integer, String)

# Avoid creation of iterators on every iteration, since they
# need to provide state information for all iterations. Hence:
# establish closure variables for iterators parent and child.
parent = child = nil

# Add all of the products to the GtkListStore.
list.each_with_index do |e, i|

  # If the product type is a category, count the quantity
  # of all of the products in the category that are going
  # to be bought.
  if (e.product_type == P_CATG)
    j = i + 1

    # Calculate how many products will be bought in
    # the category.
    while j < list.size && list[j].product_type != P_CATG
      list[i].quantity += list[j].quantity if list[j].buy
      j += 1
    end

    # Add the category as a new root (parent) row (element).
    parent = store.append(nil)
    # store.set_value(parent, BUY_COLUMN, list[i].buy) # <= same as below
    parent[BUY_COLUMN]  = list[i].buy
    parent[QTY_COLUMN]  = list[i].quantity
    parent[PROD_COLUMN] = list[i].product

  # Otherwise, add the product as a child row of the category.
  else
    child = store.append(parent)
    # store.set_value(child, BUY_COLUMN, list[i].buy) # <= same as below
    child[BUY_COLUMN]  = list[i].buy
    child[QTY_COLUMN]  = list[i].quantity
    child[PROD_COLUMN] = list[i].product
  end
end

# Add the tree model to the tree view
treeview.model = store
treeview.expand_all

scrolled_win = Gtk::ScrolledWindow.new
scrolled_win.add(treeview)
scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
window.add(scrolled_win)
window.show_all
Gtk.main
Last modified:2012/10/04 09:57:22
Keyword(s):
References:[tut-gtk] [tut-gtk2-treev]