Gtk2::Ex::TreeModelBits - miscellaneous TreeModel helpers


Gtk2-Ex-WidgetBits documentation Contained in the Gtk2-Ex-WidgetBits distribution.

Index


Code Index:

NAME

Top

Gtk2::Ex::TreeModelBits - miscellaneous TreeModel helpers

SYNOPSIS

Top

 use Gtk2::Ex::TreeModelBits;

FUNCTIONS

Top

@types = Gtk2::Ex::TreeModelBits::all_column_types ($model)

Return a list of all the column types in $model. For example to create another ListStore with the same types as an existing one,

    my $new_store = Gtk2::ListStore->new
      (Gtk2::Ex::TreeModelBits::all_column_types ($old_store));

@values = Gtk2::Ex::TreeModelBits::column_contents ($model, $col)

Return a list of all the values in column number $col of a Gtk2::TreeModel object $model.

Any tree structure in the model is flattened out for the return. A parent row's column value comes first, followed by the column values from its children, recursively, as per $model->foreach.

Gtk2::Ex::TreeModelBits::remove_matching_rows ($store, $subr, ...)

Remove from $store all rows passing $subr. $store can be a Gtk2::TreeStore, a Gtk2::ListStore, or another type with the same style $store->remove method. $subr is called

    $want_remove = &$subr ($store, $iter, ...)

where $iter is the row being considered, and any extra arguments to remove_matching_rows are passed on to $subr. $subr should return true if it wants to remove the row.

The order rows are considered and removed is unspecified except that a parent row is tested before its children, and the children of course are not tested if the parent is removed.

If you use an old Gtk 2.0.x and might pass a Gtk2::ListStore or Gtk2::TreeStore to remove_matching_rows then get Perl-Gtk 1.240 or higher to have the remove method on those classes return a flag the same as in Gtk 2.2 and up. Otherwise on those stores remove_matching_rows will stop after the first row removed.

$iter = Gtk2::Ex::TreeModelBits::iter_prev ($model, $iter)

Return a new Gtk2::TreeIter which is the row preceding the given $iter, at the same depth. If $iter is the first element at its depth then the return is undef.

This is like a reverse of iter_next. Going to the previous row is not a native operation and might be a touch slow if a model uses say a linked list and so must chase through data for a path lookup.

EXPORTS

Top

Nothing is exported by default, but the functions can be requested in usual Exporter style,

    use Gtk2::Ex::TreeModelBits 'remove_matching_rows';
    remove_matching_rows ($store, sub { ... });

There's no :all tag since this module is meant as a grab-bag of functions and to import as-yet unknown things would be asking for name clashes.

SEE ALSO

Top

Gtk2::ListStore, Gtk2::TreeModel, Gtk2::Ex::WidgetBits, Gtk2::Ex::TreeModel::ImplBits

HOME PAGE

Top

http://user42.tuxfamily.org/gtk2-ex-widgetbits/index.html

LICENSE

Top

Copyright 2007, 2008, 2009, 2010, 2011 Kevin Ryde

Gtk2-Ex-WidgetBits is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

Gtk2-Ex-WidgetBits is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Gtk2-Ex-WidgetBits. If not, see http://www.gnu.org/licenses/.


Gtk2-Ex-WidgetBits documentation Contained in the Gtk2-Ex-WidgetBits distribution.

# Copyright 2007, 2008, 2009, 2010, 2011 Kevin Ryde

# This file is part of Gtk2-Ex-WidgetBits.
#
# Gtk2-Ex-WidgetBits is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3, or (at your option) any
# later version.
#
# Gtk2-Ex-WidgetBits is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetBits.  If not, see <http://www.gnu.org/licenses/>.

package Gtk2::Ex::TreeModelBits;
use 5.008;
use strict;
use warnings;
use Gtk2;

use Exporter;
our @ISA = ('Exporter');
our @EXPORT_OK = qw(column_contents
                    remove_matching_rows
                    all_column_types
                    iter_prev);

our $VERSION = 43;

# uncomment this to run the ### lines
#use Smart::Comments;

sub column_contents {
  my ($model, $column) = @_;
  my @ret;

  # pre-extend, helpful for a list model style, likely to do little for an
  # actual tree
  $#ret = $model->iter_n_children(undef) - 1;

  my $pos = 0;
  $model->foreach (sub {
                     my ($model, $path, $iter) = @_;
                     $ret[$pos++] = $model->get_value ($iter, $column);
                     return 0; # keep walking
                   });
  # iterating should give n_children, trim @ret if it doesn't
  ### assert: $pos >= scalar(@ret)
  $#ret = $pos-1;

  return @ret;
}

# If a remove() might end up removing more than one row then it's expected
# to leave $iter at whatever next row then exists (at the same depth).
# A multi-remove happens for instance in Gtk2::Ex::ListModelConcat when it's
# presenting two or more copies of one submodel.
# Gtk2::Ex::TreeModelFilter::Change::remove() asks for similar from its
# child remove().
#
sub remove_matching_rows {
  my $model = shift;
  my $subr = shift;

  my @pending;
  my $iter = $model->get_iter_first;

  for (;;) {
    # undef at end of one level, pop to upper level, or finished if no upper
    $iter ||= pop @pending || last;
    ### looking at: $model->get_path($iter)->to_string

    if ($subr->($model, $iter, @_)) {
      if (! $model->remove ($iter)) {
        $iter = undef; # no more at this depth
      }
      # otherwise $iter updated to next row
      next;
    }

    my $child = $model->iter_children ($iter);
    $iter = $model->iter_next ($iter);

    if ($child) {
      ### descend to child: $model->get_path($child)->to_string
      push @pending, $iter;
      $iter = $child;
    }
  }
}

sub all_column_types {
  my ($model) = @_;
  return map { $model->get_column_type($_) } 0 .. $model->get_n_columns - 1;
}

sub iter_prev {
  my ($model, $iter) = @_;
  my $path = $model->get_path ($iter);
  return ($path->prev
          ? $model->get_iter ($path)  # path moved
          : undef); # no more nodes (last path index was 0)
}

1;
__END__