Beispiel #1
0
/* FIXME: maybe we can support different encoding for different mount points? */
char* fm_path_display_basename(FmPath* path)
{
    if(G_UNLIKELY(!path->parent)) /* root element */
    {
        if( !fm_path_is_native(path) && fm_path_is_virtual(path) )
        {
            if(fm_path_is_trash_root(path))
                return g_strdup(_("Trash Can"));
            if(g_str_has_prefix(path->name, "computer:/"))
                return g_strdup(_("My Computer"));
            if(g_str_has_prefix(path->name, "applications:/"))
                return g_strdup(_("Applications"));
            if(g_str_has_prefix(path->name, "network:/"))
                return g_strdup(_("Network"));
        }
    }
    return g_filename_display_name(path->name);
}
Beispiel #2
0
gboolean fm_dnd_dest_files_dropped(FmDndDest* dd, GdkDragAction action,
                                   int info_type, FmList* files)
{
    FmPath* dest;
    GtkWidget* parent;
    dest = fm_dnd_dest_get_dest_path(dd);
    if(!dest)
        return FALSE;
    g_debug("%d files-dropped!, info_type: %d", fm_list_get_length(files), info_type);

    if(fm_list_is_file_info_list(files))
        files = fm_path_list_new_from_file_info_list(files);
    else
        fm_list_ref(files);

    parent = gtk_widget_get_toplevel(dd->widget);
    switch(action)
    {
    case GDK_ACTION_MOVE:
        if(fm_path_is_trash_root(fm_dnd_dest_get_dest_path(dd)))
            fm_trash_files(GTK_WINDOW(parent), files);
        else
            fm_move_files(GTK_WINDOW(parent), files, fm_dnd_dest_get_dest_path(dd));
        break;
    case GDK_ACTION_COPY:
        fm_copy_files(GTK_WINDOW(parent), files, fm_dnd_dest_get_dest_path(dd));
        break;
    case GDK_ACTION_LINK:
        // fm_link_files(parent, files, fm_dnd_dest_get_dest_path(dd));
        break;
    case GDK_ACTION_ASK:
        g_debug("TODO: GDK_ACTION_ASK");
        break;
    }
    fm_list_unref(files);
    return TRUE;
}
Beispiel #3
0
void on_dnd_dest_files_dropped(FmDndDest* dd, GdkDragAction action,
                               int info_type, FmList* files, FmPlacesView* view)
{
	FmPath* dest;
    GList* l;

	dest = fm_dnd_dest_get_dest_path(dd);
    g_debug("action= %d, %d files-dropped!, info_type: %d", action, fm_list_get_length(files), info_type);

    if(action != GDK_ACTION_LINK)
    {
        if(fm_list_is_file_info_list(files))
            files = fm_path_list_new_from_file_info_list(files);
        else
            fm_list_ref(files);
    }

    switch(action)
    {
    case GDK_ACTION_MOVE:
        if(fm_path_is_trash_root(dest))
            fm_trash_files(files);
        else
            fm_move_files(files, dest);
        break;
    case GDK_ACTION_COPY:
        fm_copy_files(files, dest);
        break;
    case GDK_ACTION_LINK:
        {
            GtkTreePath* tp = view->dest_row;
            if(tp)
            {
                GtkTreePath* sep = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &sep_it);
                int idx = gtk_tree_path_get_indices(tp)[0] - gtk_tree_path_get_indices(sep)[0];
                gtk_tree_path_free(sep);
                if(view->dest_pos == GTK_TREE_VIEW_DROP_BEFORE)
                    --idx;
                for( l=fm_list_peek_head_link(files); l; l=l->next, ++idx )
                {
                    FmBookmarkItem* item;
                    if(fm_list_is_file_info_list(files))
                    {
                        FmFileInfo* fi = (FmFileInfo*)l->data;
                        item = fm_bookmarks_insert( bookmarks, fi->path, fi->disp_name, idx);
                    }
                    else
                    {
                        FmPath* path = (FmPath*)l->data;
                        char* disp_name = g_filename_display_name(path->name);
                        item = fm_bookmarks_insert( bookmarks, path, disp_name, idx);
                        g_free(disp_name);
                    }
                    /* we don't need to add item to places view. Later the bookmarks will be reloaded. */
                }
            }
        }
        break;
    }
    fm_list_unref(files);

    if(view->dest_row)
    {
        gtk_tree_path_free(view->dest_row);
        view->dest_row = NULL;
    }
}
Beispiel #4
0
GtkWidget* place_item_get_menu(PlaceItem* item)
{
    GtkWidget* menu = NULL;
    FmFileMenu* file_menu;
    GtkUIManager* ui = gtk_ui_manager_new();
    GtkActionGroup* act_grp = act_grp = gtk_action_group_new("Popup");
    gtk_action_group_set_translation_domain(act_grp, GETTEXT_PACKAGE);

    /* FIXME: merge with FmFileMenu when possible */
    if(item->type == PLACE_PATH)
    {
        if(item->bm_item)
        {
            gtk_action_group_add_actions(act_grp, bm_menu_actions, G_N_ELEMENTS(bm_menu_actions), item);
            gtk_ui_manager_add_ui_from_string(ui, bookmark_menu_xml, -1, NULL);
        }
        else if(fm_path_is_trash_root(item->path))
        {
            gtk_action_group_add_actions(act_grp, trash_menu_actions, G_N_ELEMENTS(trash_menu_actions), item);
            gtk_ui_manager_add_ui_from_string(ui, trash_menu_xml, -1, NULL);
        }
    }
    else if(item->type == PLACE_VOL)
    {
        GtkAction* act;
        GMount* mnt;
        gtk_action_group_add_actions(act_grp, vol_menu_actions, G_N_ELEMENTS(vol_menu_actions), item);
        gtk_ui_manager_add_ui_from_string(ui, vol_menu_xml, -1, NULL);

        mnt = g_volume_get_mount(item->vol);
        if(mnt) /* mounted */
        {
            g_object_unref(mnt);
            act = gtk_action_group_get_action(act_grp, "Mount");
            gtk_action_set_sensitive(act, FALSE);
        }
        else /* not mounted */
        {
            act = gtk_action_group_get_action(act_grp, "Unmount");
            gtk_action_set_sensitive(act, FALSE);
        }

        if(g_volume_can_eject(item->vol))
            act = gtk_action_group_get_action(act_grp, "Unmount");
        else
            act = gtk_action_group_get_action(act_grp, "Eject");
        gtk_action_set_visible(act, FALSE);
    }
    else
        goto _out;
    gtk_ui_manager_insert_action_group(ui, act_grp, 0);

    menu = gtk_ui_manager_get_widget(ui, "/popup");
    if(menu)
    {
        g_signal_connect(menu, "selection-done", G_CALLBACK(gtk_widget_destroy), NULL);
        g_object_weak_ref(G_OBJECT(menu), g_object_unref, g_object_ref(ui));
    }

_out:
    g_object_unref(act_grp);
    g_object_unref(ui);
    return menu;
}
Beispiel #5
0
/**
 * fm_dnd_dest_get_default_action
 * @dd FmDndDest object
 * @target GdkTarget of the target data type
 * @dest FmFileInfo of the destination file at drop site.
 *
 * Returns the default action to take for the dragged files.
 */
GdkDragAction fm_dnd_dest_get_default_action(FmDndDest* dd,
                                             GdkDragContext* drag_context,
                                             GdkTarget target)
{
    GdkDragAction action;
    FmFileInfo* dest = dd->dest_file;

    if(!dest || !dest->path)
        return FALSE;

    /* this is XDirectSave */
    if(target == xds_target_atom)
        return GDK_ACTION_COPY;

    if(dd->src_files) /* we have got drag source files */
    {
        FmPath* dest_path = dest->path;
        if(fm_path_is_trash(dest_path))
        {
            if(fm_path_is_trash_root(dest_path)) /* we can only move files to trash can */
                action = GDK_ACTION_MOVE;
            else /* files inside trash are read only */
                action = 0;
        }
        else if(fm_path_is_virtual(dest_path))
        {
            /* computer:/// and network:/// shouldn't received dropped files. */
            /* FIXME: some special handling can be done with menu:// */
            action = 0;
        }
        else if(list_contains_path(dd->src_files, dest_path)) {
            /* don't allow dropping files into themselves */
            action = 0;
        }
        else /* dest is a ordinary path */
        {
            /* determine if the dragged files are on the same device as destination file */
            /* Here we only check the first dragged file since checking all of them can
             * make the operation very slow. */
            gboolean same_fs;
            if(dd->src_dev || dd->src_fs_id) /* we know the device of dragged source files */
            {
                /* compare the device/filesystem id against that of destination file */
                if(fm_path_is_native(dest_path))
                    same_fs = dd->src_dev && (dd->src_dev == dest->dev);
                else /* FIXME: can we use direct comparison here? */
                    same_fs = dd->src_fs_id && (0 == g_strcmp0(dd->src_fs_id, dest->fs_id));
                action = same_fs ? GDK_ACTION_MOVE : GDK_ACTION_COPY;
            }
            else /* we don't know on which device the dragged source files are. */
                action = 0;
        }
    }
    else /* we didn't have any data */
    {
        action = 0;
        if(!dd->waiting_data) /* we're still waiting for "drag-data-received" signal */
        {
            /* retrieve the source files */
            gtk_drag_get_data(dd->widget, drag_context, target, time);
            dd->waiting_data = TRUE;
        }
    }

    if( action && 0 == (drag_context->actions & action) )
        action = drag_context->suggested_action;

    return action;
}
Beispiel #6
0
static gboolean deep_count_gio(FmDeepCountJob* job, GFileInfo* inf, GFile* gf)
{
    FmJob* fmjob = FM_JOB(job);
    GError* err = NULL;
    GFileType type;
    const char* fs_id;
    gboolean descend;

    if(inf)
        g_object_ref(inf);
    else
    {
_retry_query_info:
        inf = g_file_query_info(gf, query_str,
                    (job->flags & FM_DC_JOB_FOLLOW_LINKS) ? 0 : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                    fm_job_get_cancellable(fmjob), &err);
        if(!inf)
        {
            FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
            g_error_free(err);
            err = NULL;
            if(act == FM_JOB_RETRY)
                goto _retry_query_info;
            return FALSE;
        }
    }
    if(fm_job_is_cancelled(fmjob))
    {
        g_object_unref(inf);
        return FALSE;
    }

    type = g_file_info_get_file_type(inf);
    descend = TRUE;

    ++job->count;
    job->total_size += g_file_info_get_size(inf);
    job->total_ondisk_size += g_file_info_get_attribute_uint64(inf, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);

    /* prepare for moving across different devices */
    if( job->flags & FM_DC_JOB_PREPARE_MOVE )
    {
        fs_id = g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
        if( g_strcmp0(fs_id, job->dest_fs_id) != 0 )
        {
            /* files on different device requires an additional 'delete' for the source file. */
            ++job->total_size; /* this is for the additional delete */
            ++job->total_ondisk_size;
            ++job->count;
        }
        else
            descend = FALSE;
    }

    if( type == G_FILE_TYPE_DIRECTORY )
    {
        FmPath* fm_path = fm_path_new_for_gfile(gf);
        /* check if we need to decends into the dir. */
        /* trash:/// doesn't support deleting files recursively */
        if(job->flags & FM_DC_JOB_PREPARE_DELETE && fm_path_is_trash(fm_path) && ! fm_path_is_trash_root(fm_path))
            descend = FALSE;
        else
        {
            /* only descends into files on the same filesystem */
            if( job->flags & FM_DC_JOB_SAME_FS )
            {
                fs_id = g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM);
                descend = (g_strcmp0(fs_id, job->dest_fs_id) == 0);
            }
        }
        fm_path_unref(fm_path);
        g_object_unref(inf);
        inf = NULL;

        if(descend)
        {
            GFileEnumerator* enu;
        _retry_enum_children:
            enu = g_file_enumerate_children(gf, query_str,
                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                fm_job_get_cancellable(fmjob), &err);
            if(enu)
            {
                while( !fm_job_is_cancelled(fmjob) )
                {
                    inf = g_file_enumerator_next_file(enu, fm_job_get_cancellable(fmjob), &err);
                    if(inf)
                    {
                        GFile* child = g_file_get_child(gf, g_file_info_get_name(inf));
                        deep_count_gio(job, inf, child);
                        g_object_unref(child);
                        g_object_unref(inf);
                        inf = NULL;
                    }
                    else
                    {
                        if(err) /* error! */
                        {
                            /* FM_JOB_RETRY is not supported */
                            /*FmJobErrorAction act = */
                            fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                            g_error_free(err);
                            err = NULL;
                        }
                        else
                        {
                            /* EOF is reached, do nothing. */
                            break;
                        }
                    }
                }
                g_file_enumerator_close(enu, NULL, NULL);
                g_object_unref(enu);
            }
            else
            {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                    goto _retry_enum_children;
            }
        }
    }
    else
        g_object_unref(inf);

    return TRUE;
}