X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/e4afc73a345f54f278134db0a9641394411410be..700b0908d71f64c9449ba372d0b9a8363257afb1:/src/viktreeview.c diff --git a/src/viktreeview.c b/src/viktreeview.c index b698d020..9eb401dd 100644 --- a/src/viktreeview.c +++ b/src/viktreeview.c @@ -67,8 +67,8 @@ static void treeview_init ( VikTreeview *vt ); static void treeview_finalize ( GObject *gob ); static void treeview_add_columns ( VikTreeview *vt ); -static gboolean vik_drag_data_received ( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data ); -static gboolean vik_drag_data_delete ( GtkTreeDragSource *drag_source, GtkTreePath *path ); +static gboolean treeview_drag_data_received ( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data ); +static gboolean treeview_drag_data_delete ( GtkTreeDragSource *drag_source, GtkTreePath *path ); GType vik_treeview_get_type (void) { @@ -172,9 +172,9 @@ gpointer vik_treeview_item_get_parent ( VikTreeview *vt, GtkTreeIter *iter ) return rv; } -void vik_treeview_get_iter_from_path_str ( VikTreeview *vt, GtkTreeIter *iter, const gchar *path_str ) +gboolean vik_treeview_get_iter_from_path_str ( VikTreeview *vt, GtkTreeIter *iter, const gchar *path_str ) { - gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(vt->model), iter, path_str ); + return gtk_tree_model_get_iter_from_string ( GTK_TREE_MODEL(vt->model), iter, path_str ); } static void treeview_add_columns ( VikTreeview *vt ) @@ -245,6 +245,30 @@ static void treeview_add_columns ( VikTreeview *vt ) } +static void select_cb(GtkTreeSelection *selection, gpointer data) +{ + VikTreeview *vt = data; + gint type; + GtkTreeIter iter, parent; + VikLayer *vl; + VikWindow * vw; + + if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return; + type = vik_treeview_item_get_type( vt, &iter); + + while ( type != VIK_TREEVIEW_TYPE_LAYER ) { + if ( ! vik_treeview_item_get_parent_iter ( vt, &iter, &parent ) ) + return; + iter = parent; + type = vik_treeview_item_get_type (vt, &iter ); + } + + vl = VIK_LAYER( vik_treeview_item_get_pointer ( vt, &iter ) ); + + vw = VIK_GTK_WINDOW_FROM_LAYER(vl); + vik_window_selected_layer(vw, vl); +} + void treeview_init ( VikTreeview *vt ) { guint16 i; @@ -269,16 +293,18 @@ void treeview_init ( VikTreeview *vt ) GtkTreeDragDestIface *idest; isrc = g_type_interface_peek (g_type_class_peek(G_OBJECT_TYPE(vt->model)), GTK_TYPE_TREE_DRAG_SOURCE); - isrc->drag_data_delete = vik_drag_data_delete; + isrc->drag_data_delete = treeview_drag_data_delete; idest = g_type_interface_peek (g_type_class_peek(G_OBJECT_TYPE(vt->model)), GTK_TYPE_TREE_DRAG_DEST); - idest->drag_data_received = vik_drag_data_received; + idest->drag_data_received = treeview_drag_data_received; } for ( i = 0; i < VIK_LAYER_NUM_TYPES; i++ ) vt->layer_type_icons[i] = vik_layer_load_icon ( i ); /* if icon can't be loaded, it will be null and simply not be shown. */ gtk_tree_view_set_reorderable (GTK_TREE_VIEW(vt), TRUE); + g_signal_connect(gtk_tree_view_get_selection (GTK_TREE_VIEW (vt)), "changed", + G_CALLBACK(select_cb), vt); } @@ -388,7 +414,12 @@ void vik_treeview_insert_layer ( VikTreeview *vt, GtkTreeIter *parent_iter, GtkT { g_assert ( iter != NULL ); g_assert ( icon_type < VIK_LAYER_NUM_TYPES ); - gtk_tree_store_insert_before ( GTK_TREE_STORE(vt->model), iter, parent_iter, sibling ); + if (sibling) { + gtk_tree_store_insert_before ( GTK_TREE_STORE(vt->model), iter, parent_iter, sibling ); + } else { + gtk_tree_store_append ( GTK_TREE_STORE(vt->model), iter, parent_iter ); + } + gtk_tree_store_set ( GTK_TREE_STORE(vt->model), iter, NAME_COLUMN, name, VISIBLE_COLUMN, TRUE, TYPE_COLUMN, VIK_TREEVIEW_TYPE_LAYER, ITEM_PARENT_COLUMN, parent, ITEM_POINTER_COLUMN, item, ITEM_DATA_COLUMN, data, HAS_VISIBLE_COLUMN, TRUE, EDITABLE_COLUMN, TRUE, @@ -473,14 +504,14 @@ static void treeview_finalize ( GObject *gob ) G_OBJECT_CLASS(parent_class)->finalize(gob); } -static gboolean vik_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data) +static gboolean treeview_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data) { GtkTreeModel *tree_model; GtkTreeStore *tree_store; GtkTreeModel *src_model = NULL; GtkTreePath *src_path = NULL, *dest_cp = NULL; gboolean retval = FALSE; - GtkTreeIter src_iter, root_iter, dest_iter; + GtkTreeIter src_iter, root_iter, dest_iter, dest_parent; guint *i_src = NULL; VikTreeview *vt; VikLayer *vl; @@ -505,6 +536,13 @@ static gboolean vik_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath * and call the move method of that layer type. * */ + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) { + goto out; + } + if (!gtk_tree_path_compare(src_path, dest)) { + goto out; + } + i_src = gtk_tree_path_get_indices (src_path); dest_cp = gtk_tree_path_copy (dest); @@ -512,68 +550,35 @@ static gboolean vik_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath TREEVIEW_GET(tree_model, &root_iter, ITEM_POINTER_COLUMN, &vl); vt = vl->vt; - if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) { - goto out; - } - switch(vik_treeview_item_get_type(vt, &src_iter)) { - case VIK_TREEVIEW_TYPE_LAYER: - /* dest_cp is the future new path as envisioned by Gtk, and may not exist yet. - * We are interested in the future parent, which must be an aggregate layer. - * Therefore, we need to find the first ancestor who is an aggregate layer. - */ - gtk_tree_path_up(dest_cp); - while (gtk_tree_model_get_iter (src_model, &dest_iter, dest_cp) && - (vik_treeview_item_get_type(vt, &dest_iter) != VIK_TREEVIEW_TYPE_LAYER || - !IS_VIK_AGGREGATE_LAYER(vik_treeview_item_get_pointer (vt, &dest_iter)))) { - gtk_tree_path_up(dest_cp); - fprintf(stderr, "up\n"); - } - if (gtk_tree_model_get_iter (src_model, &dest_iter, dest_cp)) { - VikLayer *vl_src, *vl_dest; - vl_src = vik_treeview_item_get_pointer(vt, &src_iter); - vl_dest = vik_treeview_item_get_pointer(vt, &dest_iter); - printf("moving layer '%s' into layer '%s'\n", vl_src->name, vl_dest->name); - - /* - * FIXME: ..._layer_delete unrefs the given layer, causing it to be destroyed. - * However, ..._add_layer doesn't increase the ref count, so regardless of order - * without the explicit g_object_ref this wouldn't work. - */ - g_object_ref(vl_src); - vik_aggregate_layer_delete(vik_treeview_item_get_parent(vt, &src_iter), &src_iter); - vik_aggregate_layer_add_layer(VIK_AGGREGATE_LAYER(vl_dest), vl_src); - } - break; - case VIK_TREEVIEW_TYPE_SUBLAYER: - /* - * If we're moving a sublayer, handle all known types separately. For now that - * is only TRW. This might be done more elegantly through an interface. - */ - if (IS_VIK_TRW_LAYER(vik_treeview_item_get_parent(vt, &src_iter))) { - VikTrwLayer *vtl_src, *vtl_dest; + if (gtk_tree_path_get_depth(dest_cp)>1) { /* can't be sibling of top layer */ + VikLayer *vl_src, *vl_dest; + /* Find the first ancestor that is a full layer, and store in dest_parent. + * In addition, put in dest_iter where Gtk wants us to insert the dragged object. + * (Note that this may end up being an invalid iter). + */ + do { gtk_tree_path_up(dest_cp); - while (gtk_tree_path_get_depth(dest_cp)>0 && - gtk_tree_model_get_iter (src_model, &dest_iter, dest_cp) && - (vik_treeview_item_get_type(vt, &dest_iter) != VIK_TREEVIEW_TYPE_LAYER || - !IS_VIK_TRW_LAYER(vik_treeview_item_get_pointer (vt, &dest_iter)))) { - gtk_tree_path_up(dest_cp); - } - vtl_src = vik_treeview_item_get_parent(vt, &src_iter); - vtl_dest = vik_treeview_item_get_pointer(vt, &dest_iter); - if (IS_VIK_TRW_LAYER(vtl_dest)) { - vik_trw_layer_move_iter(vtl_src, vtl_dest, &src_iter, &dest_iter); - } - } - break; - - default: - printf(" Problem.\n"); + dest_iter = dest_parent; + gtk_tree_model_get_iter (src_model, &dest_parent, dest_cp); + } while (gtk_tree_path_get_depth(dest_cp)>1 && + vik_treeview_item_get_type(vt, &dest_parent) != VIK_TREEVIEW_TYPE_LAYER); + + + g_assert ( vik_treeview_item_get_parent(vt, &src_iter) ); + vl_src = vik_treeview_item_get_parent(vt, &src_iter); + vl_dest = vik_treeview_item_get_pointer(vt, &dest_parent); + + /* TODO: might want to allow different types, and let the clients handle how they want */ + if (vl_src->type == vl_dest->type && vik_layer_get_interface(vl_dest->type)->drag_drop_request) { + // g_print("moving an item from layer '%s' into layer '%s'\n", vl_src->name, vl_dest->name); + vik_layer_get_interface(vl_dest->type)->drag_drop_request(vl_src, vl_dest, &src_iter, dest); + } } } - out: + out: if (dest_cp) gtk_tree_path_free(dest_cp); if (src_path) @@ -585,10 +590,10 @@ static gboolean vik_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath /* * This may not be necessary. */ -static gboolean vik_drag_data_delete ( GtkTreeDragSource *drag_source, GtkTreePath *path ) +static gboolean treeview_drag_data_delete ( GtkTreeDragSource *drag_source, GtkTreePath *path ) { gchar *s_dest = gtk_tree_path_to_string(path); - printf("delete data from %s\n", s_dest); + g_print("delete data from %s\n", s_dest); g_free(s_dest); return FALSE; }