RE: GtkTreeView column right-click
- From: "Brian" <bmcandrews efs-us com>
- To: "'Murray Cumming'" <murrayc murrayc com>, "'gtk-list'" <gtk-list gnome org>
- Subject: RE: GtkTreeView column right-click
- Date: Wed, 28 Apr 2004 13:58:42 -0500
-----Original Message-----
I'd like to popup a menu when the user right-clicks on a GtkTreeView's
column header. Does anyone know of any example code for that, or even
an app that does that?
Obviously I don't want to access the private GtkTreeViewColumn::button.
--
This was discussed recently. Unfortunately you have to bring your own
button. Muppet rigged up an example, here's the relavent code followed
by the complete example:
#
# We must start off by setting a custom widget into the column.
# get_widget() will return undef unless we've previously called
set_widget(),
# so let's create a label we can use as the heading label. This is
good,
# anyway, because we'll want to mangle the text of the heading to show
which
# virtual column is selected for sorting.
#
my $label = Gtk2::Label->new ($col->get_title." (0)");
$col->set_widget ($label);
$label->show; # very important, show_all doesn't get this widget!
#
# And now, we need to find the button. To avoid problems in the future
# should the actual layout of widgets change, we'll seek instead of just
# assuming it's always three layers deep. If you're really paranoid,
# you can modify this to avoid the possibility of infinite looping, but
# we know there's a button in the tree, so i won't muddy the code.
#
my $button = $col->get_widget; # not a button
do {
$button = $button->get_parent;
} until ($button->isa ('Gtk2::Button'));
$button->signal_connect (button_release_event => sub {
my (undef, $event) = @_;
# Do completely normal things unless this is a right-button
click.
return FALSE unless $event->button == 3;
# otherwise, pop up a context menu that lets the user select the
# virtual column on which to sort.
my $menu = Gtk2::Menu->new;
foreach (0, 1, 2) {
my $item = Gtk2::MenuItem->new ($_);
$menu->append ($item);
$item->show;
$item->signal_connect (activate => sub {
my (undef, $sortkey) = @_;
$col->set_sort_column_id ($sortkey);
$model->set_sort_column_id ($sortkey,
$col->get_sort_order);
$model->sort_column_changed;
# update the column heading to show which
virtual
# column is active.
$label->set_text ($col->get_title."
($sortkey)");
}, $_);
}
$menu->popup (undef, undef, undef, undef,
$event->button, $event->time);
return TRUE; # stop propagation!
});
_______________________________________________
#!/bin/env perl -
=doc
Say you have some sophisticated sort algorithm you need to apply to a
column
of data in a tree, and the sort algorithm takes parameters that you can
tweak.
You'd like to allow the user to select those parameters from a context
menu
that pops up from the header button, that same button you click to
change
sort column and sort order.
That's getting into some deep arcana, so here's a contrived example.
-- muppet, 30 mar 04
=cut
use strict;
use Glib qw(TRUE FALSE);
use Gtk2 -init;
#
# We'll start with a single-column model with some "interesting" data.
# This data is three "virtual" columns that can be sorted. There are
# plenty of ways we could store this that would be easier, but they'd
# also make it pointless to do what we're about to do, so bear with me.
#
my $model = Gtk2::ListStore->new (qw(Glib::String));
for (my $i = 0; $i < 5 ; $i++) {
for (my $j = 0; $j < 5 ; $j++) {
for (my $k = 0; $k < 5 ; $k++) {
$model->set ($model->append, 0, "$i, $j, $k");
}
}
}
#
# And a custom sort func that sorts on the virtual column.
# Yes, this is very slow. Like i said, it's a contrived example.
#
sub foosort {
my ($liststore, $itera, $iterb, $sortkey) = @_;
my @a = split /,\s*/, $liststore->get ($itera, 0);
my @b = split /,\s*/, $liststore->get ($iterb, 0);
return $a[$sortkey] <=> $b[$sortkey];
}
# Use different sort column ids for the different sort options.
$model->set_sort_func (0, \&foosort, 0);
$model->set_sort_func (1, \&foosort, 1);
$model->set_sort_func (2, \&foosort, 2);
#
# Now put that model into a view... mostly boilerplate here.
#
my $treeview = Gtk2::TreeView->new ($model);
$treeview->set_headers_visible (1);
my $col = Gtk2::TreeViewColumn->new_with_attributes
('Fancy sortable column',
Gtk2::CellRendererText->new,
text => 0);
$treeview->append_column ($col);
# Select the initial sort id.
$col->set_sort_column_id (0);
#
# Now, here comes the heavy wizardry. We want to allow the user to
# right-click on the column heading to pop up a context menu. To do
# this, we need to get a hold of the button that's used as the column
# header. I've looked far and wide and have not found a sanctioned
# "clean" way to get this button, but as mentioned here:
# http://mail.gnome.org/archives/gtk-list/2003-November/msg00175.html
# we can cheat by seeking up the widget hierarchy for it.
#
# We must start off by setting a custom widget into the column.
# get_widget() will return undef unless we've previously called
set_widget(),
# so let's create a label we can use as the heading label. This is
good,
# anyway, because we'll want to mangle the text of the heading to show
which
# virtual column is selected for sorting.
#
my $label = Gtk2::Label->new ($col->get_title." (0)");
$col->set_widget ($label);
$label->show; # very important, show_all doesn't get this widget!
#
# And now, we need to find the button. To avoid problems in the future
# should the actual layout of widgets change, we'll seek instead of just
# assuming it's always three layers deep. If you're really paranoid,
# you can modify this to avoid the possibility of infinite looping, but
# we know there's a button in the tree, so i won't muddy the code.
#
my $button = $col->get_widget; # not a button
do {
$button = $button->get_parent;
} until ($button->isa ('Gtk2::Button'));
$button->signal_connect (button_release_event => sub {
my (undef, $event) = @_;
# Do completely normal things unless this is a right-button
click.
return FALSE unless $event->button == 3;
# otherwise, pop up a context menu that lets the user select the
# virtual column on which to sort.
my $menu = Gtk2::Menu->new;
foreach (0, 1, 2) {
my $item = Gtk2::MenuItem->new ($_);
$menu->append ($item);
$item->show;
$item->signal_connect (activate => sub {
my (undef, $sortkey) = @_;
$col->set_sort_column_id ($sortkey);
$model->set_sort_column_id ($sortkey,
$col->get_sort_order);
$model->sort_column_changed;
# update the column heading to show which
virtual
# column is active.
$label->set_text ($col->get_title."
($sortkey)");
}, $_);
}
$menu->popup (undef, undef, undef, undef,
$event->button, $event->time);
return TRUE; # stop propagation!
});
# The rest is just boilerplate to get everything onscreen.
my $scroller = Gtk2::ScrolledWindow->new;
$scroller->set_policy ('never', 'always');
$scroller->add ($treeview);
my $win = Gtk2::Window->new;
$win->signal_connect (destroy => sub {Gtk2->main_quit});
$win->add ($scroller);
$win->set_default_size (75, 150);
$win->show_all;
Gtk2->main;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]