~ubuntu-branches/ubuntu/quantal/libfm/quantal

« back to all changes in this revision

Viewing changes to .pc/02-libfm-0.1.14-API-changes.patch/src/base/fm-folder.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2011-02-21 21:55:43 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20110221215543-m7gn2snkhpk1kk9u
Tags: 0.1.15+git-3625952cea-0ubuntu1
* New upstream snapshot (2011-02-15)
 - Use x-schemas-handler (LP: #683922)
* debian/patches/
 - 90_add_gobject_link.patch: Remove, merged upstream.
 - 02-libfm-0.1.14-API-changes.patch: Refresh.
 - 03_disable_deprecated_gio_module.patch: Refresh.
 - 04_fix_docs_linker.patch: Fix DSO linking in docs/.
* debian/libfm0.install:
 - Remove usr/lib/libfm/gnome-terminal, dropped upstream.
 - Remove gio module, dropped upstream.
* debian/rules:
 - Add --enable-gtk-doc to configure.
* debian/libfm-gtk0.symbols:
 - Update with new symbols.
* debian/apport/source_libfm.py
 - Fix location of pcmanfm config files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      fm-folder.c
3
 
 *
4
 
 *      Copyright 2009 PCMan <pcman.tw@gmail.com>
5
 
 *
6
 
 *      This program is free software; you can redistribute it and/or modify
7
 
 *      it under the terms of the GNU General Public License as published by
8
 
 *      the Free Software Foundation; either version 2 of the License, or
9
 
 *      (at your option) any later version.
10
 
 *
11
 
 *      This program is distributed in the hope that it will be useful,
12
 
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *      GNU General Public License for more details.
15
 
 *
16
 
 *      You should have received a copy of the GNU General Public License
17
 
 *      along with this program; if not, write to the Free Software
18
 
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 
 *      MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#include "fm-folder.h"
23
 
#include "fm-monitor.h"
24
 
#include "fm-marshal.h"
25
 
#include <string.h>
26
 
 
27
 
enum {
28
 
    FILES_ADDED,
29
 
    FILES_REMOVED,
30
 
    FILES_CHANGED,
31
 
    LOADED,
32
 
    UNMOUNT,
33
 
    ERROR,
34
 
    N_SIGNALS
35
 
};
36
 
 
37
 
static FmFolder* fm_folder_new_internal(FmPath* path, GFile* gf);
38
 
static FmFolder* fm_folder_get_internal(FmPath* path, GFile* gf);
39
 
static void fm_folder_finalize              (GObject *object);
40
 
 
41
 
static void on_file_info_finished(FmFileInfoJob* job, FmFolder* folder);
42
 
static gboolean on_idle(FmFolder* folder);
43
 
 
44
 
G_DEFINE_TYPE(FmFolder, fm_folder, G_TYPE_OBJECT);
45
 
 
46
 
static GList* _fm_folder_get_file_by_name(FmFolder* folder, const char* name);
47
 
 
48
 
static guint signals[N_SIGNALS];
49
 
static GHashTable* hash = NULL; /* FIXME: should this be guarded with a mutex? */
50
 
 
51
 
static void fm_folder_class_init(FmFolderClass *klass)
52
 
{
53
 
    GObjectClass *g_object_class;
54
 
    g_object_class = G_OBJECT_CLASS(klass);
55
 
    g_object_class->finalize = fm_folder_finalize;
56
 
    fm_folder_parent_class = (GObjectClass*)g_type_class_peek(G_TYPE_OBJECT);
57
 
 
58
 
    /*
59
 
    * files-added is emitted when there is a new file created in the dir.
60
 
    * The param is GList* of the newly added file.
61
 
    */
62
 
    signals[ FILES_ADDED ] =
63
 
        g_signal_new ( "files-added",
64
 
                       G_TYPE_FROM_CLASS ( klass ),
65
 
                       G_SIGNAL_RUN_FIRST,
66
 
                       G_STRUCT_OFFSET ( FmFolderClass, files_added ),
67
 
                       NULL, NULL,
68
 
                       g_cclosure_marshal_VOID__POINTER,
69
 
                       G_TYPE_NONE, 1, G_TYPE_POINTER );
70
 
 
71
 
    /*
72
 
    * files-removed is emitted when there is a file deleted in the dir.
73
 
    * The param is GList* of the removed files.
74
 
    */
75
 
    signals[ FILES_REMOVED ] =
76
 
        g_signal_new ( "files-removed",
77
 
                       G_TYPE_FROM_CLASS ( klass ),
78
 
                       G_SIGNAL_RUN_FIRST,
79
 
                       G_STRUCT_OFFSET ( FmFolderClass, files_removed ),
80
 
                       NULL, NULL,
81
 
                       g_cclosure_marshal_VOID__POINTER,
82
 
                       G_TYPE_NONE, 1, G_TYPE_POINTER );
83
 
 
84
 
    /*
85
 
    * file-changed is emitted when there is a file changed in the dir.
86
 
    * The param is VFSFileInfo of the newly created file.
87
 
    */
88
 
    signals[ FILES_CHANGED ] =
89
 
        g_signal_new ( "files-changed",
90
 
                       G_TYPE_FROM_CLASS ( klass ),
91
 
                       G_SIGNAL_RUN_FIRST,
92
 
                       G_STRUCT_OFFSET ( FmFolderClass, files_changed ),
93
 
                       NULL, NULL,
94
 
                       g_cclosure_marshal_VOID__POINTER,
95
 
                       G_TYPE_NONE, 1, G_TYPE_POINTER );
96
 
 
97
 
    signals[ LOADED ] =
98
 
        g_signal_new ( "loaded",
99
 
                       G_TYPE_FROM_CLASS ( klass ),
100
 
                       G_SIGNAL_RUN_FIRST,
101
 
                       G_STRUCT_OFFSET ( FmFolderClass, loaded ),
102
 
                       NULL, NULL,
103
 
                       g_cclosure_marshal_VOID__VOID,
104
 
                       G_TYPE_NONE, 0);
105
 
 
106
 
    signals[ UNMOUNT ] =
107
 
        g_signal_new ( "unmount",
108
 
                       G_TYPE_FROM_CLASS ( klass ),
109
 
                       G_SIGNAL_RUN_FIRST,
110
 
                       G_STRUCT_OFFSET ( FmFolderClass, unmount ),
111
 
                       NULL, NULL,
112
 
                       g_cclosure_marshal_VOID__VOID,
113
 
                       G_TYPE_NONE, 0);
114
 
 
115
 
    signals[ERROR] =
116
 
        g_signal_new( "error",
117
 
                      G_TYPE_FROM_CLASS ( klass ),
118
 
                      G_SIGNAL_RUN_LAST,
119
 
                      G_STRUCT_OFFSET ( FmFolderClass, error ),
120
 
                      NULL, NULL,
121
 
                      fm_marshal_INT__POINTER_INT,
122
 
                      G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_INT );
123
 
}
124
 
 
125
 
 
126
 
static void fm_folder_init(FmFolder *self)
127
 
{
128
 
    self->files = fm_file_info_list_new();
129
 
}
130
 
 
131
 
void on_file_info_finished(FmFileInfoJob* job, FmFolder* folder)
132
 
{
133
 
    GList* l;
134
 
    GSList* files_to_add = NULL;
135
 
    GSList* files_to_update = NULL;
136
 
 
137
 
    for(l=fm_list_peek_head_link(job->file_infos);l;l=l->next)
138
 
    {
139
 
        FmFileInfo* fi = (FmFileInfo*)l->data;
140
 
        GList* l2 = _fm_folder_get_file_by_name(folder, fi->path->name);
141
 
        if(l2) /* the file is already in the folder, update */
142
 
        {
143
 
            FmFileInfo* fi2 = (FmFileInfo*)l2->data;
144
 
            /* FIXME: will fm_file_info_copy here cause problems?
145
 
             *        the file info might be referenced by others, too.
146
 
             *        we're mofifying an object referenced by others.
147
 
             *        we should redesign the API, or document this clearly
148
 
             *        in future API doc.
149
 
             */
150
 
            fm_file_info_copy(fi2, fi);
151
 
            files_to_update = g_slist_prepend(files_to_update, fi2);
152
 
        }
153
 
        else
154
 
        {
155
 
            files_to_add = g_slist_prepend(files_to_add, fi);
156
 
            fm_file_info_ref(fi);
157
 
            fm_list_push_tail(folder->files, fi);
158
 
        }
159
 
    }
160
 
    if(files_to_add)
161
 
    {
162
 
        g_signal_emit(folder, signals[FILES_ADDED], 0, files_to_add);
163
 
        g_slist_free(files_to_add);
164
 
    }
165
 
    if(files_to_update)
166
 
    {
167
 
        g_signal_emit(folder, signals[FILES_CHANGED], 0, files_to_update);
168
 
        g_slist_free(files_to_update);
169
 
    }
170
 
 
171
 
    folder->pending_jobs = g_slist_remove(folder->pending_jobs, job);
172
 
}
173
 
 
174
 
gboolean on_idle(FmFolder* folder)
175
 
{
176
 
    GSList* l;
177
 
    FmFileInfoJob* job = NULL;
178
 
    FmPath* path;
179
 
    folder->idle_handler = 0;
180
 
    if(folder->files_to_update || folder->files_to_add)
181
 
        job = (FmFileInfoJob*)fm_file_info_job_new(NULL, 0);
182
 
 
183
 
    if(folder->files_to_update)
184
 
    {
185
 
        GSList* prev = NULL;
186
 
        for(l=folder->files_to_update;l;)
187
 
        {
188
 
            /* if a file is already in files_to_add, remove it. */
189
 
            if(g_slist_find_custom(folder->files_to_add, l->data, (GCompareFunc)strcmp))
190
 
            {
191
 
                GSList* tmp = l;
192
 
                l=l->next;
193
 
                if(G_LIKELY(prev))
194
 
                    prev->next = l;
195
 
                g_free(tmp->data);
196
 
                g_slist_free_1(tmp);
197
 
                if(G_UNLIKELY(tmp == folder->files_to_update))
198
 
                    folder->files_to_update = l;
199
 
                continue;
200
 
            }
201
 
            path = fm_path_new_child(folder->dir_path, (char*)l->data);
202
 
            fm_file_info_job_add(job, path);
203
 
            fm_path_unref(path);
204
 
            g_free(l->data);
205
 
 
206
 
            prev = l;
207
 
            l=l->next;
208
 
        }
209
 
        g_slist_free(folder->files_to_update);
210
 
        folder->files_to_update = NULL;
211
 
    }
212
 
 
213
 
    if(folder->files_to_add)
214
 
    {
215
 
        for(l=folder->files_to_add;l;l=l->next)
216
 
        {
217
 
            path = fm_path_new_child(folder->dir_path, (char*)l->data);
218
 
            fm_file_info_job_add(job, path);
219
 
            fm_path_unref(path);
220
 
            g_free(l->data);
221
 
        }
222
 
        g_slist_free(folder->files_to_add);
223
 
        folder->files_to_add = NULL;
224
 
    }
225
 
 
226
 
    if(job)
227
 
    {
228
 
        g_signal_connect(job, "finished", on_file_info_finished, folder);
229
 
        folder->pending_jobs = g_slist_prepend(folder->pending_jobs, job);
230
 
        fm_job_run_async(FM_JOB(job));
231
 
    }
232
 
 
233
 
    if(folder->files_to_del)
234
 
    {
235
 
        GSList* ll;
236
 
        for(ll=folder->files_to_del;ll;ll=ll->next)
237
 
        {
238
 
            GList* l= (GList*)ll->data;
239
 
            ll->data = l->data;
240
 
            fm_list_delete_link_nounref(folder->files , l);
241
 
        }
242
 
        g_signal_emit(folder, signals[FILES_REMOVED], 0, folder->files_to_del);
243
 
        g_slist_foreach(folder->files_to_del, (GFunc)fm_file_info_unref, NULL);
244
 
        g_slist_free(folder->files_to_del);
245
 
        folder->files_to_del = NULL;
246
 
    }
247
 
 
248
 
    return FALSE;
249
 
}
250
 
 
251
 
static void on_folder_changed(GFileMonitor* mon, GFile* gf, GFile* other, GFileMonitorEvent evt, FmFolder* folder)
252
 
{
253
 
    GList* l;
254
 
    char* name;
255
 
/*
256
 
    const char* names[]={
257
 
        "G_FILE_MONITOR_EVENT_CHANGED",
258
 
        "G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT",
259
 
        "G_FILE_MONITOR_EVENT_DELETED",
260
 
        "G_FILE_MONITOR_EVENT_CREATED",
261
 
        "G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED",
262
 
        "G_FILE_MONITOR_EVENT_PRE_UNMOUNT",
263
 
        "G_FILE_MONITOR_EVENT_UNMOUNTED"
264
 
    };
265
 
    name = g_file_get_basename(gf);
266
 
    g_debug("folder: %p, file %s event: %s", folder, name, names[evt]);
267
 
    g_free(name);
268
 
*/
269
 
 
270
 
    if(g_file_equal(gf, folder->gf))
271
 
    {
272
 
        g_debug("event of the folder itself: %d", evt);
273
 
        /* FIXME: handle unmount events */
274
 
        if(evt == G_FILE_MONITOR_EVENT_PRE_UNMOUNT)
275
 
        {
276
 
            g_debug("folder is going to be unmounted");
277
 
        }
278
 
        else if(evt == G_FILE_MONITOR_EVENT_UNMOUNTED)
279
 
        {
280
 
            g_signal_emit(folder, signals[UNMOUNT], 0);
281
 
            g_debug("folder is unmounted");
282
 
        }
283
 
        return;
284
 
    }
285
 
 
286
 
    name = g_file_get_basename(gf);
287
 
    switch(evt)
288
 
    {
289
 
    case G_FILE_MONITOR_EVENT_CREATED:
290
 
        folder->files_to_add = g_slist_append(folder->files_to_add, name);
291
 
        break;
292
 
    case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
293
 
    case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
294
 
        folder->files_to_update = g_slist_append(folder->files_to_update, name);
295
 
        break;
296
 
    case G_FILE_MONITOR_EVENT_DELETED:
297
 
        l = _fm_folder_get_file_by_name(folder, name);
298
 
        if(l && !g_slist_find(folder->files_to_del, l) )
299
 
            folder->files_to_del = g_slist_prepend(folder->files_to_del, l);
300
 
        g_free(name);
301
 
        break;
302
 
    default:
303
 
        /* g_debug("folder %p %s event: %s", folder, name, names[evt]); */
304
 
        g_free(name);
305
 
        return;
306
 
    }
307
 
    if(!folder->idle_handler)
308
 
        folder->idle_handler = g_idle_add_full(G_PRIORITY_LOW, on_idle, folder, NULL);
309
 
}
310
 
 
311
 
static void on_job_finished(FmDirListJob* job, FmFolder* folder)
312
 
{
313
 
    GList* l;
314
 
    GSList* files = NULL;
315
 
    /* actually manually disconnecting from 'finished' signal is not
316
 
     * needed since the signal is only emit once, and later the job
317
 
     * object will be distroyed very soon. */
318
 
    /* g_signal_handlers_disconnect_by_func(job, on_job_finished, folder); */
319
 
    for(l = fm_list_peek_head_link(job->files); l; l=l->next)
320
 
    {
321
 
        FmFileInfo* inf = (FmFileInfo*)l->data;
322
 
        files = g_slist_prepend(files, inf);
323
 
        fm_list_push_tail(folder->files, inf);
324
 
    }
325
 
    if(G_LIKELY(files))
326
 
        g_signal_emit(folder, signals[FILES_ADDED], 0, files);
327
 
 
328
 
    if(job->dir_fi)
329
 
        folder->dir_fi = fm_file_info_ref(job->dir_fi);
330
 
 
331
 
    folder->job = NULL; /* the job object will be freed in idle handler. */
332
 
    g_signal_emit(folder, signals[LOADED], 0);
333
 
}
334
 
 
335
 
static FmJobErrorAction on_job_err(FmDirListJob* job, GError* err, FmJobErrorSeverity severity, FmFolder* folder)
336
 
{
337
 
        FmJobErrorAction ret;
338
 
        g_signal_emit(folder, signals[ERROR], 0, err, severity, &ret);
339
 
    return ret;
340
 
}
341
 
 
342
 
FmFolder* fm_folder_new_internal(FmPath* path, GFile* gf)
343
 
{
344
 
    GError* err = NULL;
345
 
    FmFolder* folder = (FmFolder*)g_object_new(FM_TYPE_FOLDER, NULL);
346
 
    folder->dir_path = fm_path_ref(path);
347
 
 
348
 
    folder->gf = (GFile*)g_object_ref(gf);
349
 
 
350
 
    folder->mon = fm_monitor_directory(gf, &err);
351
 
    if(folder->mon)
352
 
        g_signal_connect(folder->mon, "changed", G_CALLBACK(on_folder_changed), folder );
353
 
    else
354
 
        g_error_free(err);
355
 
 
356
 
    fm_folder_reload(folder);
357
 
    return folder;
358
 
}
359
 
 
360
 
FmFolder* fm_folder_get_internal(FmPath* path, GFile* gf)
361
 
{
362
 
    FmFolder* folder;
363
 
    /* FIXME: should we provide a generic FmPath cache in fm-path.c
364
 
     * to associate all kinds of data structures with FmPaths? */
365
 
 
366
 
    /* FIXME: should creation of the hash table be moved to fm_init()? */
367
 
    if( G_LIKELY(hash) )
368
 
        folder = (FmFolder*)g_hash_table_lookup(hash, path);
369
 
    else
370
 
    {
371
 
        hash = g_hash_table_new((GHashFunc)fm_path_hash, (GEqualFunc)fm_path_equal);
372
 
        folder = NULL;
373
 
    }
374
 
 
375
 
    if( G_UNLIKELY(!folder) )
376
 
    {
377
 
        GFile* _gf = NULL;
378
 
        if(!gf)
379
 
            _gf = gf = fm_path_to_gfile(path);
380
 
        folder = fm_folder_new_internal(path, gf);
381
 
        if(_gf)
382
 
            g_object_unref(_gf);
383
 
        g_hash_table_insert(hash, folder->dir_path, folder);
384
 
    }
385
 
    else
386
 
        return (FmFolder*)g_object_ref(folder);
387
 
    return folder;
388
 
}
389
 
 
390
 
static void fm_folder_finalize(GObject *object)
391
 
{
392
 
    FmFolder *self;
393
 
    g_return_if_fail(object != NULL);
394
 
    g_return_if_fail(FM_IS_FOLDER(object));
395
 
 
396
 
    self = FM_FOLDER(object);
397
 
 
398
 
    if(self->job)
399
 
    {
400
 
        g_signal_handlers_disconnect_by_func(self->job, on_job_finished, self);
401
 
        g_signal_handlers_disconnect_by_func(self->job, on_job_err, self);
402
 
        fm_job_cancel(FM_JOB(self->job)); /* FIXME: is this ok? */
403
 
        /* the job will be freed automatically in idle handler. */
404
 
    }
405
 
 
406
 
    if(self->pending_jobs)
407
 
    {
408
 
        GSList* l;
409
 
        for(l = self->pending_jobs;l;l=l->next)
410
 
        {
411
 
            FmJob* job = FM_JOB(l->data);
412
 
            g_signal_handlers_disconnect_by_func(job, on_job_finished, self);
413
 
            fm_job_cancel(job);
414
 
            /* the job will be freed automatically in idle handler. */
415
 
        }
416
 
    }
417
 
 
418
 
    /* remove from hash table */
419
 
    g_hash_table_remove(hash, self->dir_path);
420
 
    if(self->dir_path)
421
 
        fm_path_unref(self->dir_path);
422
 
 
423
 
    if(self->dir_fi)
424
 
        fm_file_info_unref(self->dir_fi);
425
 
 
426
 
    if(self->gf)
427
 
        g_object_unref(self->gf);
428
 
 
429
 
    if(self->mon)
430
 
    {
431
 
        g_signal_handlers_disconnect_by_func(self->mon, on_folder_changed, self);
432
 
        g_object_unref(self->mon);
433
 
    }
434
 
 
435
 
    if(self->idle_handler)
436
 
    {
437
 
        g_source_remove(self->idle_handler);
438
 
        if(self->files_to_add)
439
 
        {
440
 
            g_slist_foreach(self->files_to_add, (GFunc)g_free, NULL);
441
 
            g_slist_free(self->files_to_add);
442
 
        }
443
 
        if(self->files_to_update)
444
 
        {
445
 
            g_slist_foreach(self->files_to_update, (GFunc)g_free, NULL);
446
 
            g_slist_free(self->files_to_update);
447
 
        }
448
 
        if(self->files_to_del)
449
 
            g_slist_free(self->files_to_del);
450
 
    }
451
 
 
452
 
    fm_list_unref(self->files);
453
 
 
454
 
    if (G_OBJECT_CLASS(fm_folder_parent_class)->finalize)
455
 
        (* G_OBJECT_CLASS(fm_folder_parent_class)->finalize)(object);
456
 
}
457
 
 
458
 
FmFolder*    fm_folder_get_for_gfile    (GFile* gf)
459
 
{
460
 
    FmPath* path = fm_path_new_for_gfile(gf);
461
 
    FmFolder* folder = fm_folder_new_internal(path, gf);
462
 
    fm_path_unref(path);
463
 
    return folder;
464
 
}
465
 
 
466
 
FmFolder* fm_folder_get_for_path(FmPath* path)
467
 
{
468
 
    return fm_folder_get_internal(path, NULL);
469
 
}
470
 
 
471
 
FmFolder* fm_folder_get_for_path_name(const char* path)
472
 
{
473
 
    FmPath* fm_path = fm_path_new(path);
474
 
    FmFolder* folder = fm_folder_get_internal(fm_path, NULL);
475
 
    fm_path_unref(fm_path);
476
 
    return folder;
477
 
}
478
 
 
479
 
/* FIXME: should we use GFile here? */
480
 
FmFolder*    fm_folder_get_for_uri    (const char* uri)
481
 
{
482
 
    GFile* gf = g_file_new_for_uri(uri);
483
 
    FmFolder* folder = fm_folder_get_for_gfile(gf);
484
 
    g_object_unref(gf);
485
 
    return folder;
486
 
}
487
 
 
488
 
void fm_folder_reload(FmFolder* folder)
489
 
{
490
 
    /* FIXME: remove all items and re-run a dir list job. */
491
 
    GSList* files_to_del = NULL;
492
 
    GList* l = fm_list_peek_head_link(folder->files);
493
 
    if(l)
494
 
    {
495
 
        for(;l;l=l->next)
496
 
        {
497
 
            FmFileInfo* fi = (FmFileInfo*)l->data;
498
 
            files_to_del = g_slist_prepend(files_to_del, fi);
499
 
        }
500
 
        g_signal_emit(folder, signals[FILES_REMOVED], 0, files_to_del);
501
 
        fm_list_clear(folder->files); /* fm_file_info_unref will be invoked. */
502
 
        g_slist_free(files_to_del);
503
 
    }
504
 
 
505
 
    folder->job = fm_dir_list_job_new(folder->dir_path, FALSE);
506
 
    g_signal_connect(folder->job, "finished", G_CALLBACK(on_job_finished), folder);
507
 
    g_signal_connect(folder->job, "error", G_CALLBACK(on_job_err), folder);
508
 
    fm_job_run_async(FM_JOB(folder->job));
509
 
}
510
 
 
511
 
FmFileInfoList* fm_folder_get_files (FmFolder* folder)
512
 
{
513
 
    return folder->files;
514
 
}
515
 
 
516
 
GList* _fm_folder_get_file_by_name(FmFolder* folder, const char* name)
517
 
{
518
 
    GList* l = fm_list_peek_head_link(folder->files);
519
 
    for(;l;l=l->next)
520
 
    {
521
 
        FmFileInfo* fi = (FmFileInfo*)l->data;
522
 
        if(strcmp(fi->path->name, name) == 0)
523
 
            return l;
524
 
    }
525
 
    return NULL;
526
 
}
527
 
 
528
 
FmFileInfo* fm_folder_get_file_by_name(FmFolder* folder, const char* name)
529
 
{
530
 
    GList* l = _fm_folder_get_file_by_name(folder, name);
531
 
    return l ? (FmFileInfo*)l->data : NULL;
532
 
}
533
 
 
534
 
FmFolder* fm_folder_get(FmPath* path)
535
 
{
536
 
    return fm_folder_get_internal(path, NULL);
537
 
}
538
 
 
539
 
gboolean fm_folder_get_is_loading(FmFolder* folder)
540
 
{
541
 
    return (folder->job != NULL);
542
 
}