Re: call for FAQ topics and content



On 14 Aug 2003 23:25:17 -0400, Ross McFarland wrote:

think back to what it took you forever to figure out, to things you
couldn't find information on no matter how hard you looked, or things
you figured out that you want the rest of the world to know.

This one took me forever to figure out, I couldn't for the life of me
find documentation on it and I for sure want the rest of the world to
know it:

Q: How do you serialise (and reload) a tree withouth the need to keep a
   parallel data structure?

A:

This is from a todo list manager with two relevant columns.

sub save {
  my ($view) = @_;
  my $model = $view -> get_model();

  # ~/.odot is where we store the data
  open(ODOT, ">$ENV{ HOME }/.odot") or return
    error("Could not open '$ENV{ HOME }/.odot' for writing: $!.");

  # recurse the tree
  $model -> foreach(sub {
    my ($model, $path, $iterator) = @_;

    # save the stringified path and the expansion state of the row and
    # its textual contents
    print ODOT join("\t",
      $path -> to_string(),
      $view -> row_expanded($path) || 0,
      $model -> get_value($iterator, COLUMN_TASK),
      $model -> get_value($iterator, COLUMN_DUE_DATE)), "\n";

    # return 0 to make $model -> foreach() go on
    return 0;
  });

  close(ODOT) or return 0;

  return 1;
}

sub load {
  my ($view) = @_;

  my $model = $view -> get_model();
  my @expanded = ();

  open(ODOT, "$ENV{ HOME }/.odot") or return
    error("Could not open '$ENV{ HOME }/.odot' for reading: $!.");

  while (<ODOT>) {
    chomp();

    my ($path_string, $path_state, $task, $due_date) = split(/\t/);
    my $path = Gtk2::TreePath -> new($path_string);

    # save a copy of the path for later if it was expanded; we can't
    # just expand the row at this point, since the rows were saved in a
    # "depth-first fashion" - so, even if this row had children, they
    # wouldn't be there yet and our expansion would've no effect
    push(@expanded, $path -> copy()) if($path_state == 1);

    # if $path has a parent, $path -> up() changes $path to point to
    # that parent and additionally returns 1 - so, depending on this
    # return value, we set the parent of our row
    my $parent_iterator = $path -> up() ?
                            $model -> get_iter($path) :
                            undef;

    $model -> set($model -> append($parent_iterator),                 
                  COLUMN_TASK, $task,
                  COLUMN_DUE_DATE, $due_date);
  }

  close(ODOT);

  foreach (@expanded) {
    $view -> expand_row($_, 0);
  }

  return 1;
}

Kudos to Tim Müller who helped me with this.

Bye,
-Torsten



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]