Re: Enable drag and drop for treeview?
- From: Jef Driesen <jefdriesen hotmail com>
- To: gtkmm-list gnome org
- Subject: Re: Enable drag and drop for treeview?
- Date: Tue, 08 May 2007 12:19:57 +0200
Jef Driesen wrote:
Paul Davis wrote:
On 5/2/07, Jef Driesen <jefdriesen hotmail com> wrote:
For my application, I want to be able to re-order rows in a treeview
(treestore model) using drag and drop. According to the gtkmm book, I
can use set_reorderable(). But how can I detect when a drag and drop
operation is finished (to update the underlying database)? I can't find
any signals to connect to. Am I missing something?
I think to do this, you have to subclass Gtk::TreeModel and override
Gtk::TreeDragDest::drag_data_received_vfunc()
I did something similar here:
http://trac.lsdcas.engineering.uiowa.edu/browser/trunk/cas2/plugins/viewer/event_analysis/treemodel.hh
http://trac.lsdcas.engineering.uiowa.edu/browser/trunk/cas2/plugins/viewer/event_analysis/treemodel.cc
There's also an example in the book about doing this stuff which is
what I based my implementation on:
http://www.gtkmm.org/docs/gtkmm-2.4/examples/book/treeview/drag_and_drop/
Does this method also work well with a sorted treemodel? Because the
simple set_reorderable() does not seem to work in that case. Once the
model is sorted (by clicking on a treeview column header), drag and drop
is not possible anymore.
I tried that approach and the row_drop_possible_vfunc is not very
difficult. I ported the default gtk function to gtkmm, disabled the
check for the sorting and added some extra constraints (see code below).
But I'm having problems with implementing drag_data_received_vfunc,
because there is no gtk_tree_store_copy function. And I can't easily
re-use the existing code from gtk+ because it depends on the treestore
(private) internals. Any suggestions?
The changes that are required to make my custom dnd work with a sorted
treestore is not very complicated (I think). Instead of adding the row
to a specific location (using gtk_tree_store_prepend or
gtk_tree_store_insert_after) I would have to add it to a parent. Because
if you do that, the row is automatically sorted, and that is exactly
what I need.
While testing, I also found some very strange behavior for the
row_drop_possible_vfunc. If you have this very simple treestore:
Item 0
Item 1
Item 2
and try to drop item 0 between item 1 and 2, the path passed to the
function is 2, as I expected. But if you drop after item 2, the path is
also 2. But once you drop the item there, drag_data_received_vfunc
receives the path 3. Shouldn't row_drop_possible_vfunc also receive the
path 3?
bool
DndTreeStore::row_drop_possible_vfunc (const Gtk::TreeModel::Path&
dest_path, const Gtk::SelectionData& selection_data) const
{
// don't accept drops if the tree has been sorted
/*if (GTK_TREE_STORE_IS_SORTED (this))
return false;*/
Glib::RefPtr<Gtk::TreeModel> src_model;
Gtk::TreePath src_path;
if (!Gtk::TreePath::get_from_selection_data (selection_data,
src_model,
src_path))
return false;
// can only drag to ourselves
/*if (src_model != GTK_TREE_MODEL (this))
return false;*/
// Can't drop into ourself.
if (src_path.is_ancestor (dest_path))
return false;
// Can't drop if dest_path's parent doesn't exist
if (dest_path.get_depth() > 1) {
Gtk::TreePath tmp = dest_path; tmp.up();
if (!((Gtk::TreeStore*)this)->get_iter (tmp))
return false;
}
// Can't drop into to the same parent.
if (dnd_equal_parent(src_path, dest_path))
return false;
// Allow new parent only
if (dest_path.back() != 0)
return false;
// Can otherwise drop anywhere.
return true;
}
static bool
dnd_equal_parent (const Gtk::TreeModel::Path& src, const
Gtk::TreeModel::Path& dst)
{
// Paths with a different depth never have the same parent.
if (src.size() != dst.size())
return false;
// Top-level paths always have the same parent.
// Note: There is no need to check both depths,
// because they are always equal at this point.
if (src.size() == 1)
return true;
// Compare parent paths for all other cases.
Gtk::TreeModel::Path src_parent = src; src_parent.up();
Gtk::TreeModel::Path dst_parent = dst; dst_parent.up();
return (src_parent == dst_parent);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]