Ejemplo n.º 1
0
/**
 * fm_launch_paths
 * @ctx: (allow-none): a launch context
 * @paths: (element-type FmPath): files to launch
 * @launcher: #FmFileLauncher with callbacks
 * @user_data: data supplied for callbacks
 *
 * Launches files using callbacks in @launcher.
 *
 * Returns: %TRUE in case of success.
 *
 * Since: 0.1.0
 */
gboolean fm_launch_paths(GAppLaunchContext* ctx, GList* paths, FmFileLauncher* launcher, gpointer user_data)
{
    FmFileInfoJob* job = fm_file_info_job_new(NULL, 0);
    GList* l;
    QueryErrorData data;
    gboolean ret;
    for(l=paths;l;l=l->next)
        fm_file_info_job_add(job, (FmPath*)l->data);
    data.ctx = ctx;
    data.launcher = launcher;
    data.user_data = user_data;
    g_signal_connect(job, "error", G_CALLBACK(on_query_target_info_error), &data);
    ret = fm_job_run_sync_with_mainloop(FM_JOB(job));
    g_signal_handlers_disconnect_by_func(job, on_query_target_info_error, &data);
    if(ret)
    {
        GList* file_infos = fm_file_info_list_peek_head_link(job->file_infos);
        if(file_infos)
            ret = fm_launch_files(ctx, file_infos, launcher, user_data);
        else
            ret = FALSE;
    }
    g_object_unref(job);
    return ret;
}
Ejemplo n.º 2
0
/**
 * fm_file_ops_job_run_with_progress
 * @parent: parent window to show dialog over it
 * @job: (transfer full): job descriptor to run
 *
 * Runs the file operation job with a progress dialog.
 * The returned data structure will be freed in idle handler automatically
 * when it's not needed anymore.
 *
 * NOTE: INCONSISTENCY: it takes a reference from job
 *
 * Before 0.1.15 this call had different arguments.
 *
 * Return value: (transfer none): progress data; not usable; caller should not free it either.
 *
 * Since: 0.1.0
 */
FmProgressDisplay* fm_file_ops_job_run_with_progress(GtkWindow* parent, FmFileOpsJob* job)
{
    FmProgressDisplay* data;

    g_return_val_if_fail(job != NULL, NULL);

    data = g_slice_new0(FmProgressDisplay);
    data->job = job;
    if(parent)
        data->parent = g_object_ref(parent);
    data->delay_timeout = g_timeout_add(SHOW_DLG_DELAY, on_show_dlg, data);

    g_signal_connect(job, "ask", G_CALLBACK(on_ask), data);
    g_signal_connect(job, "ask-rename", G_CALLBACK(on_ask_rename), data);
    g_signal_connect(job, "error", G_CALLBACK(on_error), data);
    g_signal_connect(job, "prepared", G_CALLBACK(on_prepared), data);
    g_signal_connect(job, "cur-file", G_CALLBACK(on_cur_file), data);
    g_signal_connect(job, "percent", G_CALLBACK(on_percent), data);
    g_signal_connect(job, "finished", G_CALLBACK(on_finished), data);
    g_signal_connect(job, "cancelled", G_CALLBACK(on_cancelled), data);

    fm_job_run_async(FM_JOB(job));

    return data;
}
Ejemplo n.º 3
0
void fm_progress_display_destroy(FmProgressDisplay* data)
{
    if(data->job)
    {
        fm_job_cancel(FM_JOB(data->job));

        g_signal_handlers_disconnect_by_func(data->job, on_ask, data);
        g_signal_handlers_disconnect_by_func(data->job, on_ask_rename, data);
        g_signal_handlers_disconnect_by_func(data->job, on_error, data);
        g_signal_handlers_disconnect_by_func(data->job, on_cur_file, data);
        g_signal_handlers_disconnect_by_func(data->job, on_percent, data);
        g_signal_handlers_disconnect_by_func(data->job, on_finished, data);

        g_object_unref(data->job);
    }

    g_free(data->cur_file);

    if(data->delay_timeout)
        g_source_remove(data->delay_timeout);

    if(data->update_timeout)
        g_source_remove(data->update_timeout);

    if(data->dlg)
        gtk_widget_destroy(data->dlg);

    g_slice_free(FmProgressDisplay, data);
}
Ejemplo n.º 4
0
static FmFileInfo *_fetch_file_info_for_shortcut(const char *target,
                                                 GAppLaunchContext* ctx,
                                                 FmFileLauncher* launcher,
                                                 gpointer user_data)
{
    FmFileInfoJob *job;
    QueryErrorData data;
    FmFileInfo *fi;
    FmPath *path;

    job = fm_file_info_job_new(NULL, 0);
    /* bug #3614794: the shortcut target is a commandline argument */
    path = fm_path_new_for_commandline_arg(target);
    fm_file_info_job_add(job, path);
    fm_path_unref(path);
    data.ctx = ctx;
    data.launcher = launcher;
    data.user_data = user_data;
    g_signal_connect(job, "error", G_CALLBACK(on_query_target_info_error), &data);
    fi = NULL;
    if (fm_job_run_sync_with_mainloop(FM_JOB(job)))
        fi = fm_file_info_ref(fm_file_info_list_peek_head(job->file_infos));
    g_signal_handlers_disconnect_by_func(job, on_query_target_info_error, &data);
    g_object_unref(job);
    return fi;
}
Ejemplo n.º 5
0
static gboolean _fm_file_ops_job_check_paths(FmFileOpsJob* job, GFile* src, GFileInfo* src_inf, GFile* dest)
{
    GError* err = NULL;
    FmJob* fmjob = FM_JOB(job);
    if(job->type == FM_FILE_OP_MOVE && g_file_equal(src, dest))
    {
        err = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_FAILED,
            _("Source and destination are the same."));
    }
    else if(g_file_info_get_file_type(src_inf) == G_FILE_TYPE_DIRECTORY
            && g_file_has_prefix(dest, src) )
    {
        const char* msg = NULL;
        if(job->type == FM_FILE_OP_MOVE)
            msg = _("Cannot move a folder into its sub folder");
        else if(job->type == FM_FILE_OP_COPY)
            msg = _("Cannot copy a folder into its sub folder");
        else
            msg = _("Destination is a sub folder of source");
        err = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_FAILED, msg);
    }
    if(err)
    {
        if(!fm_job_is_cancelled(fmjob))
        {
            fm_file_ops_job_emit_cur_file(job, g_file_info_get_display_name(src_inf));
            fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
        }
        g_error_free(err);
    }
    return (err == NULL);
}
Ejemplo n.º 6
0
static void fm_progress_display_destroy(FmProgressDisplay* data)
{
    g_signal_handlers_disconnect_by_func(data->job, on_cancelled, data);

    fm_job_cancel(FM_JOB(data->job));
    if (data->suspended)
        fm_job_resume(FM_JOB(data->job));

    g_signal_handlers_disconnect_by_func(data->job, on_ask, data);
    g_signal_handlers_disconnect_by_func(data->job, on_ask_rename, data);
    g_signal_handlers_disconnect_by_func(data->job, on_error, data);
    g_signal_handlers_disconnect_by_func(data->job, on_prepared, data);
    g_signal_handlers_disconnect_by_func(data->job, on_cur_file, data);
    g_signal_handlers_disconnect_by_func(data->job, on_percent, data);
    g_signal_handlers_disconnect_by_func(data->job, on_finished, data);

    g_object_unref(data->job);

    if(data->timer)
        g_timer_destroy(data->timer);

    if(data->parent)
        g_object_unref(data->parent);

    g_free(data->cur_file);
    g_free(data->old_cur_file);

    if(data->delay_timeout)
        g_source_remove(data->delay_timeout);

    if(data->update_timeout)
        g_source_remove(data->update_timeout);

    if(data->dlg)
    {
        g_object_weak_unref(G_OBJECT(data->dlg), on_progress_dialog_destroy, data);
        g_object_unref(data->error_buf);
        g_object_unref(data->bold_tag);
        gtk_widget_destroy(GTK_WIDGET(data->dlg));
    }

    if (data->str)
        g_string_free(data->str, TRUE);

    g_slice_free(FmProgressDisplay, data);
}
Ejemplo n.º 7
0
static void on_response(GtkDialog* dlg, gint id, FmProgressDisplay* data)
{
    /* cancel the job */
    if(id == GTK_RESPONSE_CANCEL || id == GTK_RESPONSE_DELETE_EVENT)
    {
        if(data->job)
            fm_job_cancel(FM_JOB(data->job));
        gtk_widget_destroy(GTK_WIDGET(dlg));
    }
}
Ejemplo n.º 8
0
static void update_vol(FmPlacesModel* model, FmPlaceItem* item, GtkTreeIter* it, FmFileInfoJob* job)
{
    FmIcon* icon;
    GIcon* gicon;
    char* name;
    GdkPixbuf* pix;
    GMount* mount;
    FmPath* path;

    name = g_volume_get_name(item->vol);
    if(item->fi->icon)
        fm_icon_unref(item->fi->icon);
    gicon = g_volume_get_icon(item->vol);
    icon = fm_icon_from_gicon(gicon);
    item->fi->icon = icon;
    g_object_unref(gicon);

    mount = g_volume_get_mount(item->vol);
    if(mount)
    {
        GFile* gf = g_mount_get_root(mount);
        path = fm_path_new_for_gfile(gf);
        g_object_unref(gf);
        g_object_unref(mount);
        item->vol_mounted = TRUE;
    }
    else
    {
        path = NULL;
        item->vol_mounted = FALSE;
    }

    if(!fm_path_equal(item->fi->path, path))
    {
        fm_file_info_set_path(item->fi, path);
        if(path)
        {
            if(job)
                fm_file_info_job_add(job, path);
            else
            {
                job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_FOLLOW_SYMLINK);
                model->jobs = g_slist_prepend(model->jobs, job);
                g_signal_connect(job, "finished", G_CALLBACK(on_file_info_job_finished), model);
                fm_job_run_async(FM_JOB(job));
            }
            fm_path_unref(path);
        }
    }

    pix = fm_icon_get_pixbuf(item->fi->icon, fm_config->pane_icon_size);
    gtk_list_store_set(GTK_LIST_STORE(model), it, FM_PLACES_MODEL_COL_ICON, pix, FM_PLACES_MODEL_COL_LABEL, name, -1);
    g_object_unref(pix);
    g_free(name);
}
Ejemplo n.º 9
0
static void fm_places_model_finalize(GObject *object)
{
    FmPlacesModel *self;
    GtkTreeIter it;

    g_return_if_fail(object != NULL);
    g_return_if_fail(FM_IS_PLACES_MODEL(object));

    self = FM_PLACES_MODEL(object);

    if(self->jobs)
    {
        GSList* l;
        for(l = self->jobs; l; l=l->next)
        {
            fm_job_cancel(FM_JOB(l->data));
            g_object_unref(l->data);
        }
        g_slist_free(self->jobs);
    }

    if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(self), &it))
    {
        do
        {
            FmPlaceItem* item;
            gtk_tree_model_get(GTK_TREE_MODEL(self), &it, FM_PLACES_MODEL_COL_INFO, &item, -1);
            if(G_LIKELY(item))
                place_item_free(item);
        }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(self), &it));
    }

    gtk_tree_path_free(self->sep_tp);

    g_signal_handler_disconnect(gtk_icon_theme_get_default(), self->theme_change_handler);
    g_signal_handler_disconnect(fm_config, self->use_trash_change_handler);
    g_signal_handler_disconnect(fm_config, self->pane_icon_size_change_handler);

    g_signal_handlers_disconnect_by_func(self->vol_mon, on_vol_added, self);
    g_signal_handlers_disconnect_by_func(self->vol_mon, on_vol_removed, self);
    g_signal_handlers_disconnect_by_func(self->vol_mon, on_vol_changed, self);
    g_signal_handlers_disconnect_by_func(self->vol_mon, on_mount_added, self);
    g_object_unref(self->vol_mon);

    if(self->trash_monitor)
    {
        g_signal_handlers_disconnect_by_func(self->trash_monitor, on_trash_changed, self);
        g_object_unref(self->trash_monitor);
    }
    if(self->trash_idle)
        g_source_remove(self->trash_idle);

    G_OBJECT_CLASS(fm_places_model_parent_class)->finalize(object);
}
Ejemplo n.º 10
0
static void on_response(GtkDialog* dlg, gint id, FmProgressDisplay* data)
{
    /* cancel the job */
    if(id == GTK_RESPONSE_CANCEL)
    {
        fm_job_cancel(FM_JOB(data->job));
        if (data->suspended)
        {
            fm_job_resume(FM_JOB(data->job));
            data->suspended = FALSE;
        }
    }
    else if(id == GTK_RESPONSE_CLOSE || id == GTK_RESPONSE_DELETE_EVENT)
        fm_progress_display_destroy(data);
    else if (id == 1 && data->suspend)
    {
        if (data->suspended)
        {
            data->suspended = FALSE;
            fm_job_resume(FM_JOB(data->job));
            gtk_button_set_label(data->suspend, _("_Pause"));
            gtk_button_set_image(data->suspend,
                                 gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,
                                                          GTK_ICON_SIZE_BUTTON));
        }
        else if (fm_job_pause(FM_JOB(data->job)))
        {
            data->suspended = TRUE;
            gtk_button_set_label(data->suspend, _("_Resume"));
            gtk_button_set_image(data->suspend,
                                 gtk_image_new_from_stock(GTK_STOCK_MEDIA_FORWARD,
                                                          GTK_ICON_SIZE_BUTTON));

        }
        else
            g_warning("FmJob failed to pause");
    }
}
Ejemplo n.º 11
0
static inline FmFileInfo *_new_info_for_native_file(FmDirListJob* job, FmPath* path, const char* path_str, GError** err)
{
    FmFileInfo *fi;

    if (fm_job_is_cancelled(FM_JOB(job)))
        return NULL;
    if (!(job->flags & FM_DIR_LIST_JOB_DETAILED))
        return fm_file_info_new_from_native_file(path, path_str, err);
    fi = fm_file_info_new();
    fm_file_info_set_path(fi, path);
    if (fm_file_info_set_from_native_file(fi, path_str, err))
        return fi;
    fm_file_info_unref(fi);
    return NULL;
}
Ejemplo n.º 12
0
static void on_response(GtkDialog* dlg, gint id, FmProgressDisplay* data)
{
    /* cancel the job */
    if(id == GTK_RESPONSE_CANCEL || id == GTK_RESPONSE_DELETE_EVENT)
    {
        if(data->job)
        {
            fm_job_cancel(FM_JOB(data->job));
            if(id != GTK_RESPONSE_CANCEL)
                fm_progress_display_destroy(data);
        }
    }
    else if(id == GTK_RESPONSE_CLOSE)
        fm_progress_display_destroy(data);
}
Ejemplo n.º 13
0
static void on_bookmarks_changed(FmBookmarks* bm, gpointer user_data)
{
    FmPlacesModel* model = FM_PLACES_MODEL(user_data);
    FmFileInfoJob* job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_FOLLOW_SYMLINK);
    GtkTreeIter it = model->sep_it;
    /* remove all old bookmarks */
    if(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &it))
    {
        while(gtk_list_store_remove(GTK_LIST_STORE(model), &it))
            continue;
    }
    add_bookmarks(model, job);

    g_signal_connect(job, "finished", G_CALLBACK(on_file_info_job_finished), model);
    model->jobs = g_slist_prepend(model->jobs, job);
    fm_job_run_async(FM_JOB(job));
}
Ejemplo n.º 14
0
void SidePane::initDirTree() {
  // TODO
  DirTreeModel* model = new DirTreeModel(view_);
  FmFileInfoJob* job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_NONE);
  model->setShowHidden(showHidden_);

  GList* l;
  /* query FmFileInfo for home dir and root dir, and then,
    * add them to dir tree model */
  fm_file_info_job_add(job, fm_path_get_home());
  fm_file_info_job_add(job, fm_path_get_root());
  /* FIXME: maybe it's cleaner to use run_async here? */
  fm_job_run_sync_with_mainloop(FM_JOB(job));
  for(l = fm_file_info_list_peek_head_link(job->file_infos); l; l = l->next) {
      FmFileInfo* fi = FM_FILE_INFO(l->data);
      model->addRoot(fi);
  }
  g_object_unref(job);

  static_cast<DirTreeView*>(view_)->setModel(model);
}
Ejemplo n.º 15
0
/* unref finished job objects in main thread on idle */
static gboolean on_idle_cleanup(gpointer unused)
{
    GSList* jobs;
    GSList* l;

    G_LOCK(idle_handler);
    jobs = finished;
    finished = NULL;
    idle_handler = 0;
    G_UNLOCK(idle_handler);

    for(l = jobs; l; l=l->next)
    {
        FmJob* job = FM_JOB(l->data);
        if(job->cancel)
            fm_job_emit_cancelled(job);
        fm_job_emit_finished(job);
        g_object_unref(job);
    }
    g_slist_free(jobs);
    return FALSE;
}
Ejemplo n.º 16
0
void fm_folder_reload(FmFolder* folder)
{
    /* FIXME: remove all items and re-run a dir list job. */
    GSList* files_to_del = NULL;
    GList* l = fm_list_peek_head_link(folder->files);
    if(l)
    {
        for(;l;l=l->next)
        {
            FmFileInfo* fi = (FmFileInfo*)l->data;
            files_to_del = g_slist_prepend(files_to_del, fi);
        }
        g_signal_emit(folder, signals[FILES_REMOVED], 0, files_to_del);
        fm_list_clear(folder->files); /* fm_file_info_unref will be invoked. */
        g_slist_free(files_to_del);
    }

    folder->job = fm_dir_list_job_new(folder->dir_path, FALSE);
    g_signal_connect(folder->job, "finished", G_CALLBACK(on_job_finished), folder);
    g_signal_connect(folder->job, "error", G_CALLBACK(on_job_err), folder);
    fm_job_run_async(FM_JOB(folder->job));
}
Ejemplo n.º 17
0
static gboolean on_timeout (FmFilePropData *data)
{
    char size_str[128];
    FmDeepCountJob *dc = (FmDeepCountJob*) data->dc_job;

    //gdk_threads_enter ();

    if (G_LIKELY (dc && !fm_job_is_cancelled (FM_JOB (dc))))
    {
        char *str;
        fm_file_size_to_str (size_str, dc->total_size, TRUE);
        str = g_strdup_printf ("%s  (%'llu %s)", size_str, dc->total_size, ngettext ("byte", "bytes", dc->total_size));
        gtk_label_set_text (GTK_LABEL (data->total_size), str);
        g_free (str);

        fm_file_size_to_str (size_str, dc->total_block_size, TRUE);
        str = g_strdup_printf ("%s  (%'llu %s)", size_str, dc->total_block_size, ngettext ("byte", "bytes", dc->total_block_size));
        gtk_label_set_text (GTK_LABEL (data->size_on_disk), str);
        g_free (str);
    }
    //gdk_threads_leave ();
    return TRUE;
}
Ejemplo n.º 18
0
void FilePropsDialog::onFileSizeTimerTimeout() {
  if(deepCountJob && !fm_job_is_cancelled(FM_JOB(deepCountJob))) {
    char size_str[128];
    fm_file_size_to_str(size_str, sizeof(size_str), deepCountJob->total_size,
                        fm_config->si_unit);
    // FIXME:
    // OMG! It's really unbelievable that Qt developers only implement
    // QObject::tr(... int n). GNU gettext developers are smarter and
    // they use unsigned long instead of int.
    // We cannot use Qt here to handle plural forms. So sad. :-(
    QString str = QString::fromUtf8(size_str) %
      QString(" (%1 B)").arg(deepCountJob->total_size);
      // tr(" (%n) byte(s)", "", deepCountJob->total_size);
    ui->fileSize->setText(str);

    fm_file_size_to_str(size_str, sizeof(size_str), deepCountJob->total_ondisk_size,
                        fm_config->si_unit);
    str = QString::fromUtf8(size_str) %
      QString(" (%1 B)").arg(deepCountJob->total_ondisk_size);
      // tr(" (%n) byte(s)", "", deepCountJob->total_ondisk_size);
    ui->onDiskSize->setText(str);
  }
}
Ejemplo n.º 19
0
static void on_finished (FmFileOpsJob *job, FmProgressDisplay *data)
{
    GtkWidget *parent;
    if (data->update_timeout)
    {
        g_source_remove (data->update_timeout);
        data->update_timeout = 0;
    }

    parent = data->parent;
    
    if (data->dlg)
    {
        // errors happened
        if (data->has_error && data->dlg)
        {
            gtk_label_set_text (GTK_LABEL (data->current), "");
            gtk_label_set_text (GTK_LABEL (data->remaining_time), "00:00:00");
            gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dlg), GTK_RESPONSE_CANCEL, FALSE);
            gtk_dialog_add_button (GTK_DIALOG (data->dlg), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);

            gtk_image_set_from_stock (GTK_IMAGE (data->icon), GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);

            gtk_widget_show (data->msg);
            if (fm_job_is_cancelled (FM_JOB (data->job)))
            {
                gtk_label_set_text (GTK_LABEL (data->msg), _("The file operation is cancelled and there are some errors."));
                gtk_window_set_title (GTK_WINDOW (data->dlg),
                                     _("Cancelled"));
            }
            else
            {
                gtk_label_set_text (GTK_LABEL (data->msg), _("The file operation is finished, but there are some errors."));
                gtk_window_set_title (GTK_WINDOW (data->dlg),
                                     _("Finished"));
            }
        }
        else
            fm_progress_display_destroy (data);
        
        g_debug ("file operation is finished!");
    }
    else
        fm_progress_display_destroy (data);

    /* sepcial handling for trash
     * FIXME_pcm: need to refactor this to use a more elegant way later. */
    
    if (job->type == FM_FILE_OP_TRASH)
    {
        FmPathList *unsupported =  (FmPathList*)g_object_get_data (G_OBJECT (job), "trash-unsupported");
        // some files cannot be trashed because underlying filesystems don't support it.
        // delete them instead
        if (unsupported)
        {
            if (fm_yes_no (GTK_WINDOW (parent), NULL,
                        _("Some files cannot be moved to trash can because "
                        "the underlying file systems don't support this operation.\n"
                        "Do you want to delete them instead?"), TRUE))
            {
                FmJob *job = fm_file_ops_job_new (FM_FILE_OP_DELETE, unsupported);
                fm_file_ops_job_run_with_progress (GTK_WINDOW (data->parent), (FmFileOpsJob*) job);
            }
        }
    }
}
Ejemplo n.º 20
0
static void fm_file_info_job_init(FmFileInfoJob *self)
{
    self->file_infos = fm_file_info_list_new();
    fm_job_init_cancellable(FM_JOB(self));
}
Ejemplo n.º 21
0
static void fm_places_model_init(FmPlacesModel *self)
{
    GType types[] = {GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER};
    GtkTreeIter it;
    GtkTreePath* tp;
    FmPlaceItem* item;
    GList *vols, *l;
    GIcon* gicon;
    FmIcon* icon;
    GFile* gf;
    GdkPixbuf* pix;
    FmFileInfoJob* job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_FOLLOW_SYMLINK);
    GtkListStore* model = GTK_LIST_STORE(self);

    gtk_list_store_set_column_types(GTK_LIST_STORE(self), FM_PLACES_MODEL_N_COLS, types);

    self->theme_change_handler = g_signal_connect_swapped(gtk_icon_theme_get_default(), "changed",
                                            G_CALLBACK(update_icons), self);

    self->use_trash_change_handler = g_signal_connect(fm_config, "changed::use_trash",
                                             G_CALLBACK(on_use_trash_changed), self);

    self->pane_icon_size_change_handler = g_signal_connect(fm_config, "changed::pane_icon_size",
                                             G_CALLBACK(on_pane_icon_size_changed), self);
    icon = fm_icon_from_name("media-eject");
    pix = fm_icon_get_pixbuf(icon, fm_config->pane_icon_size);
    fm_icon_unref(icon);
    self->eject_icon = pix;

    item = g_slice_new0(FmPlaceItem);
    item->type = FM_PLACES_ITEM_PATH;
    item->fi = fm_file_info_new();
    item->fi->path = fm_path_ref(fm_path_get_home());
    item->fi->icon = fm_icon_from_name("user-home");
    gtk_list_store_append(model, &it);
    pix = fm_icon_get_pixbuf(item->fi->icon, fm_config->pane_icon_size);
    gtk_list_store_set(model, &it, FM_PLACES_MODEL_COL_ICON, pix, FM_PLACES_MODEL_COL_LABEL, item->fi->path->name, FM_PLACES_MODEL_COL_INFO, item, -1);
    g_object_unref(pix);
    fm_file_info_job_add(job, item->fi->path);

    /* Only show desktop in side pane when the user has a desktop dir. */
    if(g_file_test(g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP), G_FILE_TEST_IS_DIR))
    {
        item = g_slice_new0(FmPlaceItem);
        item->type = FM_PLACES_ITEM_PATH;
        item->fi = fm_file_info_new();
        item->fi->path = fm_path_ref(fm_path_get_desktop());
        item->fi->icon = fm_icon_from_name("user-desktop");
        gtk_list_store_append(model, &it);
        pix = fm_icon_get_pixbuf(item->fi->icon, fm_config->pane_icon_size);
        gtk_list_store_set(model, &it, FM_PLACES_MODEL_COL_ICON, pix, FM_PLACES_MODEL_COL_LABEL, _("Desktop"), FM_PLACES_MODEL_COL_INFO, item, -1);
        g_object_unref(pix);
        fm_file_info_job_add(job, item->fi->path);
    }

    if(fm_config->use_trash)
        create_trash_item(self); /* FIXME: how to handle trash can? */

    item = g_slice_new0(FmPlaceItem);
    item->type = FM_PLACES_ITEM_PATH;
    item->fi = fm_file_info_new();
    item->fi->path = fm_path_ref(fm_path_get_apps_menu());
    item->fi->icon = fm_icon_from_name("system-software-install");
    gtk_list_store_append(model, &it);
    pix = fm_icon_get_pixbuf(item->fi->icon, fm_config->pane_icon_size);
    gtk_list_store_set(model, &it, FM_PLACES_MODEL_COL_ICON, pix, FM_PLACES_MODEL_COL_LABEL, _("Applications"), FM_PLACES_MODEL_COL_INFO, item, -1);
    g_object_unref(pix);
    /* fm_file_info_job_add(job, item->fi->path); */

    /* volumes */
    self->vol_mon = g_volume_monitor_get();
    g_signal_connect(self->vol_mon, "volume-added", G_CALLBACK(on_vol_added), self);
    g_signal_connect(self->vol_mon, "volume-removed", G_CALLBACK(on_vol_removed), self);
    g_signal_connect(self->vol_mon, "volume-changed", G_CALLBACK(on_vol_changed), self);
    g_signal_connect(self->vol_mon, "mount-added", G_CALLBACK(on_mount_added), self);

    /* separator */
    gtk_list_store_append(model, &self->sep_it);

    /* add volumes to side-pane */
    vols = g_volume_monitor_get_volumes(self->vol_mon);
    for(l=vols;l;l=l->next)
    {
        GVolume* vol = G_VOLUME(l->data);
        add_vol(self, vol, job);
        g_object_unref(vol);
    }
    g_list_free(vols);

    /* get the path of separator */
    self->sep_tp = gtk_tree_model_get_path(GTK_TREE_MODEL(self), &self->sep_it);

    self->bookmarks = fm_bookmarks_get(); /* bookmarks */
    g_signal_connect(self->bookmarks, "changed", G_CALLBACK(on_bookmarks_changed), self);

    /* add bookmarks to side pane */
    add_bookmarks(self, job);

    g_signal_connect(job, "finished", G_CALLBACK(on_file_info_job_finished), self);
    self->jobs = g_slist_prepend(self->jobs, job);
    fm_job_run_async(FM_JOB(job));
}
Ejemplo n.º 22
0
static void fm_deep_count_job_init(FmDeepCountJob *self)
{
    fm_job_init_cancellable(FM_JOB(self));
}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
static void on_finished(FmFileOpsJob* job, FmProgressDisplay* data)
{
    GtkWindow* parent = NULL;

    /* preserve pointers that fm_progress_display_destroy() will unreference
       as they may be requested by trash support below */
    if(data->parent)
        parent = g_object_ref(data->parent);
    g_object_ref(job);

    if(data->dlg)
    {
        /* errors happened */
        if(data->has_error)
        {
            gtk_label_set_text(data->current, "");
            gtk_label_set_text(data->remaining_time, "00:00:00");
            gtk_dialog_set_response_sensitive(data->dlg, GTK_RESPONSE_CANCEL, FALSE);
            gtk_dialog_add_button(data->dlg, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);

            gtk_image_set_from_stock(data->icon, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);

            gtk_widget_show(GTK_WIDGET(data->msg));
            if(fm_job_is_cancelled(FM_JOB(job)))
            {
                gtk_label_set_text(data->msg, _("The file operation is cancelled and there are some errors."));
                gtk_window_set_title(GTK_WINDOW(data->dlg),
                                     _("Cancelled"));
            }
            else
            {
                gtk_label_set_text(data->msg, _("The file operation is finished, but there are some errors."));
                gtk_window_set_title(GTK_WINDOW(data->dlg),
                                     _("Finished"));
            }
        }
        else
            fm_progress_display_destroy(data);
        g_debug("file operation is finished!");
    }
    else
        fm_progress_display_destroy(data);
    /* if it's not destroyed yet then it will be destroyed with dialog window */

    /* sepcial handling for trash
     * FIXME: need to refactor this to use a more elegant way later. */
    if(job->type == FM_FILE_OP_TRASH) /* FIXME: direct access to job struct! */
    {
        FmPathList* unsupported = (FmPathList*)g_object_get_data(G_OBJECT(job), "trash-unsupported");
        /* some files cannot be trashed because underlying filesystems don't support it. */
        g_object_unref(job);
        if(unsupported) /* delete them instead */
        {
            /* FIXME: parent window might be already destroyed! */
            if(fm_yes_no(parent, NULL,
                        _("Some files cannot be moved to trash can because "
                        "the underlying file systems don't support this operation.\n"
                        "Do you want to delete them instead?"), TRUE))
            {
                job = fm_file_ops_job_new(FM_FILE_OP_DELETE, unsupported);
                fm_file_ops_job_run_with_progress(parent, job);
                                                        /* it eats reference! */
            }
        }
    }
    else
        g_object_unref(job);
    if(parent)
        g_object_unref(parent);
}
Ejemplo n.º 25
0
gboolean on_idle(FmFolder* folder)
{
    GSList* l;
    FmFileInfoJob* job = NULL;
    FmPath* path;
    folder->idle_handler = 0;
    if(folder->files_to_update || folder->files_to_add)
        job = (FmFileInfoJob*)fm_file_info_job_new(NULL, 0);

    if(folder->files_to_update)
    {
        GSList* prev = NULL;
        for(l=folder->files_to_update;l;)
        {
            /* if a file is already in files_to_add, remove it. */
            if(g_slist_find_custom(folder->files_to_add, l->data, (GCompareFunc)strcmp))
            {
                GSList* tmp = l;
                l=l->next;
                if(G_LIKELY(prev))
                    prev->next = l;
                g_free(tmp->data);
                g_slist_free_1(tmp);
                if(G_UNLIKELY(tmp == folder->files_to_update))
                    folder->files_to_update = l;
                continue;
            }
            path = fm_path_new_child(folder->dir_path, (char*)l->data);
            fm_file_info_job_add(job, path);
            fm_path_unref(path);
            g_free(l->data);

            prev = l;
            l=l->next;
        }
        g_slist_free(folder->files_to_update);
        folder->files_to_update = NULL;
    }

    if(folder->files_to_add)
    {
        for(l=folder->files_to_add;l;l=l->next)
        {
            path = fm_path_new_child(folder->dir_path, (char*)l->data);
            fm_file_info_job_add(job, path);
            fm_path_unref(path);
            g_free(l->data);
        }
        g_slist_free(folder->files_to_add);
        folder->files_to_add = NULL;
    }

    if(job)
    {
        g_signal_connect(job, "finished", on_file_info_finished, folder);
        folder->pending_jobs = g_slist_prepend(folder->pending_jobs, job);
        fm_job_run_async(FM_JOB(job));
    }

    if(folder->files_to_del)
    {
        GSList* ll;
        for(ll=folder->files_to_del;ll;ll=ll->next)
        {
            GList* l= (GList*)ll->data;
            ll->data = l->data;
            fm_list_delete_link_nounref(folder->files , l);
        }
        g_signal_emit(folder, signals[FILES_REMOVED], 0, folder->files_to_del);
        g_slist_foreach(folder->files_to_del, (GFunc)fm_file_info_unref, NULL);
        g_slist_free(folder->files_to_del);
        folder->files_to_del = NULL;
    }

    return FALSE;
}
Ejemplo n.º 26
0
static void fm_dir_list_job_init(FmDirListJob *job)
{
    job->files = fm_file_info_list_new();
    fm_job_init_cancellable(FM_JOB(job));
}
Ejemplo n.º 27
0
/**
 * fm_dir_list_job_add_found_file
 * @job: the job that collected listing
 * @file: a FmFileInfo of the newly found file
 *
 * This API may be called by the classes derived of FmDirListJob only.
 * Application developers should not use this API.
 * When a new file is found in the dir being listed, implementations
 * of FmDirListJob should call this API with the info of the newly found
 * file. The FmFileInfo will be added to the found file list.
 * 
 * If emission of the #FmDirListJob::files-found signal is turned on by
 * fm_dir_list_job_set_incremental(), the signal will be emitted
 * for the newly found files after several new files are added.
 * See the document for the signal for more detail.
 *
 * Since: 1.0.2
 */
void fm_dir_list_job_add_found_file(FmDirListJob* job, FmFileInfo* file)
{
    fm_file_info_list_push_tail(job->files, file);
    if(G_UNLIKELY(job->emit_files_found))
        fm_job_call_main_thread(FM_JOB(job), queue_add_file, file);
}
Ejemplo n.º 28
0
static gboolean fm_dir_list_job_run_gio(FmDirListJob* job)
{
    GFileEnumerator *enu;
    GFileInfo *inf;
    FmFileInfo* fi;
    GError *err = NULL;
    FmJob* fmjob = FM_JOB(job);
    GFile* gf;
    const char* query;

    gf = fm_path_to_gfile(job->dir_path);
_retry:
    inf = g_file_query_info(gf, gfile_info_query_attribs, 0, fm_job_get_cancellable(fmjob), &err);
    if(!inf )
    {
        FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MODERATE);
        g_error_free(err);
        if( act == FM_JOB_RETRY )
        {
            err = NULL;
            goto _retry;
        }
        else
        {
            g_object_unref(gf);
            return FALSE;
        }
    }

    if( g_file_info_get_file_type(inf) != G_FILE_TYPE_DIRECTORY)
    {
        char *path_str = fm_path_to_str(job->dir_path);
        err = g_error_new(G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
                          _("The specified directory '%s' is not valid"),
                          path_str);
        fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
        g_free(path_str);
        g_error_free(err);
        g_object_unref(gf);
        g_object_unref(inf);
        return FALSE;
    }

    /* check if FS is R/O and set attr. into inf */
    _fm_file_info_job_update_fs_readonly(gf, inf, NULL, NULL);

    job->dir_fi = fm_file_info_new_from_g_file_data(gf, inf, job->dir_path);
    g_object_unref(inf);

    if(G_UNLIKELY(job->flags & FM_DIR_LIST_JOB_DIR_ONLY))
    {
        query = G_FILE_ATTRIBUTE_STANDARD_TYPE","G_FILE_ATTRIBUTE_STANDARD_NAME","
                G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN","G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP","
                G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL","
                G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME","
                G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","G_FILE_ATTRIBUTE_STANDARD_ICON","
                G_FILE_ATTRIBUTE_STANDARD_SIZE","G_FILE_ATTRIBUTE_STANDARD_TARGET_URI","
                "unix::*,time::*,access::*,id::filesystem";
    }
    else
        query = gfile_info_query_attribs;

    enu = g_file_enumerate_children (gf, query, 0, fm_job_get_cancellable(fmjob), &err);
    g_object_unref(gf);
    if(enu)
    {
        while( ! fm_job_is_cancelled(fmjob) )
        {
            inf = g_file_enumerator_next_file(enu, fm_job_get_cancellable(fmjob), &err);
            if(inf)
            {
                FmPath *dir, *sub;
                GFile *child;
                if(G_UNLIKELY(job->flags & FM_DIR_LIST_JOB_DIR_ONLY))
                {
                    /* FIXME: handle symlinks */
                    if(g_file_info_get_file_type(inf) != G_FILE_TYPE_DIRECTORY)
                    {
                        g_object_unref(inf);
                        continue;
                    }
                }

                /* virtual folders may return children not within them */
                dir = fm_path_new_for_gfile(g_file_enumerator_get_container(enu));
                if (fm_path_equal(job->dir_path, dir))
                    sub = fm_path_new_child(job->dir_path, g_file_info_get_name(inf));
                else
                    sub = fm_path_new_child(dir, g_file_info_get_name(inf));
                child = g_file_get_child(g_file_enumerator_get_container(enu),
                                         g_file_info_get_name(inf));
                if (g_file_info_get_file_type(inf) == G_FILE_TYPE_DIRECTORY)
                    /* for dir: check if its FS is R/O and set attr. into inf */
                    _fm_file_info_job_update_fs_readonly(child, inf, NULL, NULL);
                fi = fm_file_info_new_from_g_file_data(child, inf, sub);
                fm_path_unref(sub);
                fm_path_unref(dir);
                g_object_unref(child);
                fm_dir_list_job_add_found_file(job, fi);
                fm_file_info_unref(fi);
            }
            else
            {
                if(err)
                {
                    FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                    g_error_free(err);
                    /* FM_JOB_RETRY is not supported. */
                    if(act == FM_JOB_ABORT)
                        fm_job_cancel(fmjob);
                }
                /* otherwise it's EOL */
                break;
            }
            g_object_unref(inf);
        }
        g_file_enumerator_close(enu, NULL, &err);
        g_object_unref(enu);
    }
    else
    {
        fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
        g_error_free(err);
        return FALSE;
    }
    return TRUE;
}
Ejemplo n.º 29
0
static gboolean fm_dir_list_job_run_posix(FmDirListJob* job)
{
    FmJob* fmjob = FM_JOB(job);
    FmFileInfo* fi;
    GError *err = NULL;
    char* path_str;
    GDir* dir;

    path_str = fm_path_to_str(job->dir_path);

    fi = _new_info_for_native_file(job, job->dir_path, path_str, NULL);
    if(fi)
    {
        if(! fm_file_info_is_dir(fi))
        {
            err = g_error_new(G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
                              _("The specified directory '%s' is not valid"),
                              path_str);
            fm_file_info_unref(fi);
            fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
            g_error_free(err);
            g_free(path_str);
            return FALSE;
        }
        job->dir_fi = fi;
    }
    else
    {
        err = g_error_new(G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
                          _("The specified directory '%s' is not valid"),
                          path_str);
        fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
        g_error_free(err);
        g_free(path_str);
        return FALSE;
    }

    dir = g_dir_open(path_str, 0, &err);
    if( dir )
    {
        const char* name;
        GString* fpath = g_string_sized_new(4096);
        int dir_len = strlen(path_str);
        g_string_append_len(fpath, path_str, dir_len);
        if(fpath->str[dir_len-1] != '/')
        {
            g_string_append_c(fpath, '/');
            ++dir_len;
        }
        while( ! fm_job_is_cancelled(fmjob) && (name = g_dir_read_name(dir)) )
        {
            FmPath* new_path;
            g_string_truncate(fpath, dir_len);
            g_string_append(fpath, name);

            if(job->flags & FM_DIR_LIST_JOB_DIR_ONLY) /* if we only want directories */
            {
                struct stat st;
                /* FIXME: this results in an additional stat() call, which is inefficient */
                if(stat(fpath->str, &st) == -1 || !S_ISDIR(st.st_mode))
                    continue;
            }

            new_path = fm_path_new_child(job->dir_path, name);

        _retry:
            fi = _new_info_for_native_file(job, new_path, fpath->str, &err);
            if (fi == NULL) /* we got a damaged file */
            {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                GFile *gf;
                GFileInfo *inf;
                gchar *disp_basename;

                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                    goto _retry;
                /* bug #3615271: Damaged mountpoint isn't shown
                   let make a simple file info then */
                inf = g_file_info_new();
                gf = fm_path_to_gfile(new_path);
                g_file_info_set_file_type(inf, G_FILE_TYPE_UNKNOWN);
                g_file_info_set_name(inf, name);
                disp_basename = g_filename_display_basename(fpath->str);
                g_file_info_set_display_name(inf, disp_basename);
                g_free(disp_basename);
                g_file_info_set_content_type(inf, "inode/x-corrupted");
                fi = fm_file_info_new_from_g_file_data(gf, inf, new_path);
                g_object_unref(inf);
                g_object_unref(gf);
            }
            fm_dir_list_job_add_found_file(job, fi);
            fm_file_info_unref(fi);
            fm_path_unref(new_path);
        }
        g_string_free(fpath, TRUE);
        g_dir_close(dir);
    }
    else
    {
        fm_job_emit_error(fmjob, err, FM_JOB_ERROR_CRITICAL);
        g_error_free(err);
    }
    g_free(path_str);
    return TRUE;
}
Ejemplo n.º 30
0
static void fm_folder_finalize(GObject *object)
{
    FmFolder *self;
    g_return_if_fail(object != NULL);
    g_return_if_fail(FM_IS_FOLDER(object));

    self = FM_FOLDER(object);

    if(self->job)
    {
        g_signal_handlers_disconnect_by_func(self->job, on_job_finished, self);
        g_signal_handlers_disconnect_by_func(self->job, on_job_err, self);
        fm_job_cancel(FM_JOB(self->job)); /* FIXME: is this ok? */
        /* the job will be freed automatically in idle handler. */
    }

    if(self->pending_jobs)
    {
        GSList* l;
        for(l = self->pending_jobs;l;l=l->next)
        {
            FmJob* job = FM_JOB(l->data);
            g_signal_handlers_disconnect_by_func(job, on_job_finished, self);
            fm_job_cancel(job);
            /* the job will be freed automatically in idle handler. */
        }
    }

    /* remove from hash table */
    g_hash_table_remove(hash, self->dir_path);
    if(self->dir_path)
        fm_path_unref(self->dir_path);

    if(self->dir_fi)
        fm_file_info_unref(self->dir_fi);

    if(self->gf)
        g_object_unref(self->gf);

    if(self->mon)
    {
        g_signal_handlers_disconnect_by_func(self->mon, on_folder_changed, self);
        g_object_unref(self->mon);
    }

    if(self->idle_handler)
    {
        g_source_remove(self->idle_handler);
        if(self->files_to_add)
        {
            g_slist_foreach(self->files_to_add, (GFunc)g_free, NULL);
            g_slist_free(self->files_to_add);
        }
        if(self->files_to_update)
        {
            g_slist_foreach(self->files_to_update, (GFunc)g_free, NULL);
            g_slist_free(self->files_to_update);
        }
        if(self->files_to_del)
            g_slist_free(self->files_to_del);
    }

    fm_list_unref(self->files);

    if (G_OBJECT_CLASS(fm_folder_parent_class)->finalize)
        (* G_OBJECT_CLASS(fm_folder_parent_class)->finalize)(object);
}