Re: Gtk2::TreeView drag'n drop



* Jens Luedicke <jens gcc dyndns org>:

I would like to enable drag'n drop between
two Gtk2::TreeView's. My code allows
to start dragging, but I can't drop anything.

Any hints?

I've yet to try in Perl, but should be simple.

First af all, you need to enable model drag and drop, by using the

        Gtk2::TreeView::enable_model_drag_source
        
and the

        Gtk2::TreeView::enable_model_drag_dest

methods.  You must specify inside the 'flags' field of the GtkTargetEntry
hashref that the target is within the same application, and not the same
widget (default); use the 'same-app' enum id.

Then, connect the 'drag-data-get' signal to a function that retrieves
the data on the selected row, like this one:

sub on_drag_data_get
{
        my ($treeview, $context, $selection_data, $info, $time) = @_;

        if ($info == ...)       # compare to the 'info' field inside the GtkTargetEntry
        {
                my ($model, $iter) = $treeview->get_selection()->get_selected;
                # get the data at $iter using $model->get...
        
                my $payload = ... # serialize the data
                $selection_data->set($selection_data->target, 8, $payload);
        }
        elsif ($info == ...)
        {
                #...
        }
        #...
}

Finally, connect the 'drag-data-received' signal to a function like this
one:

sub on_drag_data_received
{
        my ($treeview, $context, $x, $y, $selection_data, $info, $time) = @_;
        
        my $model = $treeview->get_model;
        if ($info == ...)
        {
                my $source = $context->get_source_widget;
                my ($target_path, $target_pos) = $treeview->get_dest_row_at_pos($x, $y);
                
                my $target_data;
                if ($source_widget and ($treeview eq $source_widget))
                {
                        # same widget: reordering
                        
                        # there's no point in using the serialized data, since we
                        # can access to the treeview.
                        my $iter_to_copy = $treeview->get_selection->get_selected;
                        
                        # fetch the data from $iter_to_copy inside $target_data
                        # ...
                }
                else
                {
                        # different widget
                        
                        # since the treeview and the model are different, we need to
                        # use the serialized data inside the $selection_data data
                        # structure.
                        if ($selection_data and ($selection_data->format == 8))
                        {
                                # unserialize $selection_data->data inside $target_data
                        }
                }
                
                my $target_iter = $model->get_iter($path);
                
                # drop postion matters.
                if ($target_iter and $target_pos and $target_data)
                {
                        my $new_iter;
                        if ($target_pos eq 'drop-before')
                        {
                                $new_iter = $model->insert_before($target_iter);
                        }
                        elsif ($target_pos eq 'drop-after')
                        {
                                $new_iter = $model->insert_after($target_iter);
                        }
                        else
                        {
                                # fallback
                                $new_iter = $model->insert_after($target_iter);
                        }

                        if ($new_iter)
                        {
                                # put the $target_data in the model.
                        }
                }
                # this ends the d'n'd operations.
                $context->finish(TRUE, TRUE, $time);
        }
        elsif ($info == ...)
        {
                # ...

                $context->finish(TRUE, TRUE, $time);
        }
        else
        {
                # failure.
                $context->(FALSE, TRUE, $time);
        }
}

+++

The code above is untested, but you get the picture.

Regards,
 Emmanuele.

-- 
Emmanuele Bassi (Zefram)                 [ http://www.emmanuelebassi.net ]
GnuPG Key fingerprint = 4DD0 C90D 4070 F071 5738  08BD 8ECC DB8F A432 0FF4



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