示例#1
0
/* Given a drop path retrieved by gtk_tree_view_get_dest_row_at_pos, this function
 * determines whether dropping a bookmark item at the specified path is allow.
 * If dropping is not allowed, this function tries to choose an alternative position
 * for the bookmark item and modified the tree path @tp passed into this function. */
static gboolean get_bookmark_drag_dest(FmPlacesView* view, GtkTreePath** tp, GtkTreeViewDropPosition* pos)
{
    gboolean ret = TRUE;
    if(*tp)
    {
        /* if the drop site is below the separator (in the bookmark area) */
        if(fm_places_model_path_is_bookmark(FM_PLACES_MODEL(model), *tp))
        {
            /* we cannot drop into a item */
            if(*pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
               *pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
                ret = FALSE;
            else
                ret = TRUE;
        }
        else /* the drop site is above the separator (in the places area containing volumes) */
        {
            const GtkTreePath* sep = fm_places_model_get_separator_path(FM_PLACES_MODEL(model));
            /* set drop site at the first bookmark item */
            gtk_tree_path_get_indices(*tp)[0] = gtk_tree_path_get_indices(sep)[0] + 1;
            *pos = GTK_TREE_VIEW_DROP_BEFORE;
            ret = TRUE;
        }
    }
    else
    {
        /* drop at end of the bookmarks list instead */
        *tp = gtk_tree_path_new_from_indices(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(model), NULL) - 1, -1);
        *pos = GTK_TREE_VIEW_DROP_AFTER;
        ret = TRUE;
    }
    g_debug("path: %s", gtk_tree_path_to_string(*tp));
    return ret;
}
示例#2
0
static gboolean row_draggable(GtkTreeDragSource* drag_source, GtkTreePath* tp)
{
    FmPlacesModel* model = FM_PLACES_MODEL(drag_source);
    return fm_places_model_path_is_bookmark(model, tp);
}
示例#3
0
static void on_drag_data_received ( GtkWidget *dest_widget,
                GdkDragContext *drag_context, gint x, gint y,
                GtkSelectionData *sel_data, guint info, guint time)
{
    FmPlacesView* view = FM_PLACES_VIEW(dest_widget);
    GtkTreePath* dest_tp = NULL;
    GtkTreeViewDropPosition pos;

    gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(view), x, y, &dest_tp, &pos);
    switch(info)
    {
    case FM_DND_DEST_TARGET_BOOOKMARK:
        if(get_bookmark_drag_dest(view, &dest_tp, &pos)) /* got the drop position */
        {
            GtkTreePath* src_tp;
            /* get the source row */
            gboolean ret = gtk_tree_get_row_drag_data(sel_data, NULL, &src_tp);
            if(ret)
            {
                /* don't do anything if source and dest are the same row */
                if(G_UNLIKELY(gtk_tree_path_compare(src_tp, dest_tp) == 0))
                    ret = FALSE;
                else
                {
                    /* don't do anything if this is not a bookmark item */
                    if(!fm_places_model_path_is_bookmark(FM_PLACES_MODEL(model), src_tp))
                        ret = FALSE;
                }
                if(ret)
                {
                    GtkTreeIter src_it, dest_it;
                    FmPlaceItem* item = NULL;
                    ret = FALSE;
                    /* get the source bookmark item */
                    if(gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &src_it, src_tp))
                        gtk_tree_model_get(GTK_TREE_MODEL(model), &src_it, FM_PLACES_MODEL_COL_INFO, &item, -1);
                    if(item)
                    {
                        /* move it to destination position */
                        if(gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &dest_it, dest_tp))
                        {
                            int new_pos, sep_pos;
                            /* get index of the separator */
                            const GtkTreePath* sep_tp = fm_places_model_get_separator_path(FM_PLACES_MODEL(model));
                            sep_pos = gtk_tree_path_get_indices(sep_tp)[0];

                            if(pos == GTK_TREE_VIEW_DROP_BEFORE)
                                gtk_list_store_move_before(model, &src_it, &dest_it);
                            else
                                gtk_list_store_move_after(model, &src_it, &dest_it);
                            new_pos = gtk_tree_path_get_indices(dest_tp)[0] - sep_pos - 1;
                            /* reorder the bookmark item */
                            fm_bookmarks_reorder(FM_PLACES_MODEL(model)->bookmarks, item->bm_item, new_pos);
                            ret = TRUE;
                        }
                    }
                }
                gtk_tree_path_free(src_tp);
            }
            gtk_drag_finish(drag_context, ret, FALSE, time);
        }
        break;
    default:
        /* check if files are received. */
        fm_dnd_dest_drag_data_received(view->dnd_dest, drag_context, x, y, sel_data, info, time);
        break;
    }
    if(dest_tp)
        gtk_tree_path_free(dest_tp);
}
示例#4
0
static gboolean on_drag_motion (GtkWidget *dest_widget,
                    GdkDragContext *drag_context, gint x, gint y, guint time)
{
    FmPlacesView* view = FM_PLACES_VIEW(dest_widget);
    /* fm_drag_context_has_target_name(drag_context, "GTK_TREE_MODEL_ROW"); */
    GdkAtom target;
    GtkTreeViewDropPosition pos;
    GtkTreePath* tp, *sep;
    gboolean ret = FALSE;
    GdkDragAction action = 0;

    target = gtk_drag_dest_find_target(dest_widget, drag_context, NULL);
    if(target == GDK_NONE)
        return FALSE;

    gtk_tree_view_get_dest_row_at_pos((GtkTreeView*)view, x, y, &tp, &pos);

    /* handle reordering bookmark items first */
    if(target == gdk_atom_intern_static_string("GTK_TREE_MODEL_ROW"))
    {
        /* bookmark item is being dragged */
        ret = get_bookmark_drag_dest(view, &tp, &pos);
        action = ret ? GDK_ACTION_MOVE : 0; /* bookmark items can only be moved */
    }
    /* try FmDndDest */
    else if(fm_dnd_dest_is_target_supported(view->dnd_dest, target))
    {
        /* the user is dragging files. get FmFileInfo of drop site. */
        if(pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER) /* drag into items */
        {
            FmPlaceItem* item = NULL;
            GtkTreeIter it;
            /* FIXME: handle adding bookmarks with Dnd */
            if(tp && gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &it, tp))
                gtk_tree_model_get(GTK_TREE_MODEL(model), &it, FM_PLACES_MODEL_COL_INFO, &item, -1);

            fm_dnd_dest_set_dest_file(view->dnd_dest, item && item->fi ? item->fi : NULL);
            action = fm_dnd_dest_get_default_action(view->dnd_dest, drag_context, target);
            ret = action != 0;
        }
        else /* drop between items, create bookmark items for dragged files */
        {
            if( (!tp || fm_places_model_path_is_bookmark(FM_PLACES_MODEL(model), tp))
               && get_bookmark_drag_dest(view, &tp, &pos)) /* tp is after separator */
            {
                action = GDK_ACTION_LINK;
                ret = TRUE;
            }
            else
            {
                action = 0;
                ret = FALSE;
            }
        }
    }
    gdk_drag_status(drag_context, action, time);

    if(ret)
        gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(view), tp, pos);
    else
        gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(view), NULL, 0);

    if(tp)
        gtk_tree_path_free(tp);

    return ret;
}