예제 #1
0
// FIXME_pcm: maybe we can support different encoding for different mount points?
char *fm_path_display_basename (FmPath *path)
{
    if (G_UNLIKELY (!path->parent)) // root_path element
    {
        if (!fm_path_is_native (path) && fm_path_is_virtual (path))
        {
            if (fm_path_is_root (path) && fm_path_is_trash (path))
                return g_strdup (_("Trash Can"));
            
            //~ if (g_str_has_prefix (path->name, "computer:/"))
                //~ return g_strdup (_("My Computer"));
            
            if (fm_path_is_computer (path))
                return g_strdup (_("My Computer"));
            
            if (g_str_has_prefix (path->name, "menu:/"))
            {
                // FIXME_pcm: this should be more flexible
                const char *p = path->name + 5;
                
                while (p[0] == '/')
                    ++p;
                
                if (g_str_has_prefix (p, "applications.menu"))
                    return g_strdup (_("Applications"));
            }
            
            if (g_str_has_prefix (path->name, "network:/"))
                return g_strdup (_("Network"));
        }
    }
    return g_filename_display_name (path->name);
}
예제 #2
0
static void fm_dir_tree_model_add_place_holder_child_item (FmDirTreeModel *dir_tree_model, GList *parent_node,
                                                           GtkTreePath *tree_path, gboolean emit_signal)
{
    FmDirTreeItem *parent_item = (FmDirTreeItem*) parent_node->data;
    
    // Check if the parent node can expand...
    FmFileInfo *file_info = parent_item->file_info;
    FmPath *path = fm_file_info_get_path (file_info);
    
    TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_add_place_holder_child_item: file = %s\t emit_signal = %d\n",
                    fm_file_info_get_name (file_info), emit_signal);
    
    
    // don't expand the trash can...
    // TODO_axl: add a can_expand flag into the file_info
    if (fm_path_is_trash (path) && fm_path_is_root (path))
        return;
    
    TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_add_place_holder_child_item: create place holder\n\n");
    
    FmDirTreeItem *dir_tree_item = fm_dir_tree_item_new (dir_tree_model, parent_node, NULL);
    
    parent_item->children = g_list_prepend (parent_item->children, dir_tree_item);

    if (!emit_signal)
        return;
        
    GtkTreeIter it;
    fm_dir_tree_model_item_to_tree_iter (dir_tree_model, parent_item->children, &it);
    
    gtk_tree_path_append_index (tree_path, 0);
    
    gtk_tree_model_row_inserted (GTK_TREE_MODEL (dir_tree_model), tree_path, &it);
    gtk_tree_path_up (tree_path);
}
예제 #3
0
파일: fm-gtk-utils.c 프로젝트: lxde/libfm
/**
 * fm_trash_or_delete_files
 * @parent: a window to place progress dialog over it
 * @files: list of files to delete
 *
 * Removes files into trash can if that operation is supported.
 * Otherwise erases them. If that operation takes some time then progress
 * dialog will be opened.
 *
 * Before 0.1.15 this call had different arguments.
 *
 * Since: 0.1.0
 */
void fm_trash_or_delete_files(GtkWindow* parent, FmPathList* files)
{
    if( !fm_path_list_is_empty(files) )
    {
        gboolean all_in_trash = TRUE;
        if(fm_config->use_trash)
        {
            GList* l = fm_path_list_peek_head_link(files);
            for(;l;l=l->next)
            {
                FmPath* path = FM_PATH(l->data);
                if(!fm_path_is_trash(path))
                    all_in_trash = FALSE;
            }
        }

        /* files already in trash:/// should only be deleted and cannot be trashed again. */
        if(fm_config->use_trash && !all_in_trash)
            fm_trash_files(parent, files);
        else
            fm_delete_files(parent, files);
    }
}
예제 #4
0
/* translate gvfs trash:///path to real path of the trashed file on disk.
 * this only works when path is a trashed file and gvfs is active.
 */
char* fm_path_get_trash_real_path(FmPath* path)
{
    char* path_str, *p;
    GString* result;
    /* The filenames listed in trash:/// by gvfs are carefully encoded 
     * to carry important information.
     * Handling of trashed file name can be found in gvfs source code:
     * gvfs/daemon/trashlib/trashitem.c: trash_item_escape_name().
     * The filename listed under trash:/// are encoded according to the 
     * real path on disk. */
    
    if(!fm_path_is_trash(path)) /* this only works for files in trash:/// */
        return NULL;

	/* converting it to string first for ease of handling */
    path_str = fm_path_to_str(path);
    p = path_str + 9; /* skip "trash:///" */
    result = g_string_sized_new(1024);
    if(*p == '\\') /* files not in home trash */
    {
		/* the basename is an encoded full path */
		for(; *p; ++p)
		{
			if(*p == '\\') /* translate all \ to / */
				g_string_append_c(result, '/');
			else if(*p == '`') /* special handling for ` */
			{
				++p;
				if(*p == '\\') /* translate `\ to \ */
					g_string_append_c(result, '\\');
				else if(*p == '`') /* translate `` to ` */
					g_string_append_c(result, '`');
				else
				{
					g_string_append_c(result, '`');
					g_string_append_c(result, *p);
				}
			}
			else
				g_string_append_c(result, *p);			
		}
	}
	else /* files in home trash */
	{
		g_string_append(result, g_get_user_data_dir());
		g_string_append_c(result, '/');
		g_string_append(result, "Trash/files/");
		if(*p == '`') /* special handling of the first character */
		{
			++p;
			if(*p == '`') /* translate `` to ` */
			{
				g_string_append_c(result, '`');
				++p;
			}
			else if(*p == '\\') /* translate `\ to \ */
			{
				g_string_append_c(result, '\\');
				++p;
			}
			else
				g_string_append_c(result, '`'); /* don't translate anything */
		}
		g_string_append(result, p); /* append the remaining part */
	}
    return g_string_free(result, FALSE);
}
예제 #5
0
파일: fm-dnd-dest.c 프로젝트: engla/libfm
/**
 * 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;
}
예제 #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;
}