~ubuntu-branches/ubuntu/trusty/pcmanfm/trusty-proposed

« back to all changes in this revision

Viewing changes to src/vfs/vfs-file-info.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Lee
  • Date: 2008-09-26 10:19:20 UTC
  • mfrom: (4.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080926101920-cfldybkmwgwrtv9u
Tags: 0.5-3
* Correct spellings,  03_correct_spelling.dpatch (Closes:498794) 
* Code in some files are taken from other projects, added these
  informations into copyright file. (Closes:499678)
* Applied 04_defaut_terminal.dpatch to support x-terminal-emulator
  alternative. (Closes:497494) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
*/
12
12
 
13
13
#include "vfs-file-info.h"
14
 
#include "xdgmime.h"
15
14
#include <glib.h>
16
15
#include "glib-mem.h"
17
16
#include <glib/gi18n.h>
20
19
#include <string.h>
21
20
 
22
21
#include "vfs-app-desktop.h"
23
 
#include "md5.h"    /* for thumbnails */
24
 
 
25
 
#define _MAX( x, y )     (x > y ? x : y)
 
22
#include "vfs-thumbnail-loader.h"
 
23
#include "vfs-utils.h"  /* for vfs_load_icon */
26
24
 
27
25
static int big_thumb_size = 48, small_thumb_size = 20;
28
26
static gboolean utf8_file_name = FALSE;
87
85
    fi->flags = VFS_FILE_INFO_NONE;
88
86
}
89
87
 
90
 
void vfs_file_info_ref( VFSFileInfo* fi )
 
88
VFSFileInfo* vfs_file_info_ref( VFSFileInfo* fi )
91
89
{
92
 
    ++fi->n_ref;
 
90
    g_atomic_int_inc( &fi->n_ref );
 
91
    return fi;
93
92
}
94
93
 
95
94
void vfs_file_info_unref( VFSFileInfo* fi )
96
95
{
97
 
    --fi->n_ref;
98
 
    if ( fi->n_ref <= 0 )
 
96
    if ( g_atomic_int_dec_and_test( &fi->n_ref) )
99
97
    {
100
98
        vfs_file_info_clear( fi );
101
99
        g_slice_free( VFSFileInfo, fi );
179
177
    if ( G_UNLIKELY( !fi->disp_size ) )
180
178
    {
181
179
        char buf[ 64 ];
182
 
        file_size_to_string( buf, fi->size );
 
180
        vfs_file_size_to_string( buf, fi->size );
183
181
        fi->disp_size = g_strdup( buf );
184
182
    }
185
183
    return fi->disp_size;
221
219
    old_mime_type = fi->mime_type;
222
220
    fi->mime_type = vfs_mime_type_get_from_file( full_path,
223
221
                                                 fi->name, &file_stat );
 
222
    vfs_file_info_load_special_info( fi, full_path );
224
223
    vfs_mime_type_unref( old_mime_type );  /* FIXME: is vfs_mime_type_unref needed ?*/
225
224
}
226
225
 
247
246
        else
248
247
            w = h = 0;
249
248
 
250
 
        if ( _MAX( w, h ) != icon_size )
 
249
        if ( ABS( MAX( w, h ) - icon_size ) > 2 )
251
250
        {
252
251
            char * icon_name = NULL;
253
252
            if ( fi->big_thumbnail )
262
261
                if ( G_UNLIKELY( icon_name[ 0 ] == '/' ) )
263
262
                    fi->big_thumbnail = gdk_pixbuf_new_from_file( icon_name, NULL );
264
263
                else
265
 
                    fi->big_thumbnail = gtk_icon_theme_load_icon(
 
264
                    fi->big_thumbnail = vfs_load_icon(
266
265
                                            gtk_icon_theme_get_default(),
267
 
                                            icon_name,
268
 
                                            icon_size, 0, NULL );
 
266
                                            icon_name, icon_size );
269
267
            }
270
268
            if ( fi->big_thumbnail )
271
269
                g_object_set_data_full( G_OBJECT(fi->big_thumbnail), "name", icon_name, g_free );
374
372
    return fi->disp_perm;
375
373
}
376
374
 
377
 
void file_size_to_string( char* buf, guint64 size )
 
375
void vfs_file_size_to_string( char* buf, guint64 size )
378
376
{
379
377
    char * unit;
380
378
    /* guint point; */
462
460
    return FALSE;
463
461
}
464
462
 
 
463
gboolean vfs_file_info_is_desktop_entry( VFSFileInfo* fi )
 
464
{
 
465
    return 0 != (fi->flags & VFS_FILE_INFO_DESKTOP_ENTRY);
 
466
}
 
467
 
465
468
gboolean vfs_file_info_is_unknown_type( VFSFileInfo* fi )
466
469
{
467
470
    if ( ! strcmp( XDG_MIME_TYPE_UNKNOWN,
473
476
/* full path of the file is required by this function */
474
477
gboolean vfs_file_info_is_executable( VFSFileInfo* fi, const char* file_path )
475
478
{
476
 
    return xdg_mime_is_executable_file( file_path, fi->mime_type->type );
 
479
    return mime_type_is_executable_file( file_path, fi->mime_type->type );
477
480
}
478
481
 
479
482
/* full path of the file is required by this function */
480
483
gboolean vfs_file_info_is_text( VFSFileInfo* fi, const char* file_path )
481
484
{
482
 
    return xdg_mime_is_text_file( file_path, fi->mime_type->type );
 
485
    return mime_type_is_text_file( file_path, fi->mime_type->type );
483
486
}
484
487
 
485
488
/*
499
502
 
500
503
    if ( vfs_file_info_is_executable( fi, file_path ) )
501
504
    {
502
 
        argv[ 0 ] = file_path;
 
505
        argv[ 0 ] = (char *) file_path;
503
506
        argv[ 1 ] = '\0';
504
507
        ret = g_spawn_async( NULL, argv, NULL, G_SPAWN_STDOUT_TO_DEV_NULL|
505
508
                             G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, err );
513
516
            app = vfs_app_desktop_new( app_name );
514
517
            if ( ! vfs_app_desktop_get_exec( app ) )
515
518
                app->exec = g_strdup( app_name );   /* FIXME: app->exec */
516
 
            files = g_list_prepend( files, file_path );
 
519
            files = g_list_prepend( files, (gpointer) file_path );
517
520
            /* FIXME: working dir is needed */
518
521
            ret = vfs_app_desktop_open_files( gdk_screen_get_default(),
519
522
                                              NULL, app, files, err );
531
534
    return fi->mode;
532
535
}
533
536
 
534
 
static void unload_thumnails_if_needed( VFSFileInfo* fi )
535
 
{
536
 
    int w, h;
537
 
    if ( fi->big_thumbnail && fi->flags == VFS_FILE_INFO_NONE )
538
 
    {
539
 
        w = gdk_pixbuf_get_width( fi->big_thumbnail );
540
 
        h = gdk_pixbuf_get_height( fi->big_thumbnail );
541
 
        if ( _MAX( w, h ) != big_thumb_size )
542
 
        {
543
 
            gdk_pixbuf_unref( fi->big_thumbnail );
544
 
            fi->big_thumbnail = NULL;
545
 
        }
546
 
    }
547
 
    if ( fi->small_thumbnail && fi->flags == VFS_FILE_INFO_NONE )
548
 
    {
549
 
        w = gdk_pixbuf_get_width( fi->small_thumbnail );
550
 
        h = gdk_pixbuf_get_height( fi->small_thumbnail );
551
 
        if ( MAX( w, h ) != small_thumb_size )
552
 
        {
553
 
            gdk_pixbuf_unref( fi->small_thumbnail );
554
 
            fi->small_thumbnail = NULL;
555
 
        }
556
 
    }
557
 
}
558
 
 
559
537
gboolean vfs_file_info_is_thumbnail_loaded( VFSFileInfo* fi, gboolean big )
560
538
{
561
 
    /* FIXME: I cannot find a better place to unload thumbnails */
562
 
    unload_thumnails_if_needed( fi );
563
539
    if ( big )
564
540
        return ( fi->big_thumbnail != NULL );
565
541
    return ( fi->small_thumbnail != NULL );
569
545
                                       const char* full_path,
570
546
                                       gboolean big )
571
547
{
572
 
    char * uri;
573
 
    md5_byte_t md5[ 16 ];
574
 
    char* thumbnail_file;
575
 
    char file_name[ 36 ];
576
 
    char mtime_str[ 32 ];
577
 
    const char* thumb_mtime;
578
 
    int i, w, h, size;
579
 
    struct stat statbuf;
580
 
    GdkPixbuf* thumbnail, *result = NULL;
581
 
 
582
 
    /* FIXME: I cannot find a better place to unload thumbnails */
583
 
    unload_thumnails_if_needed( fi );
 
548
    GdkPixbuf* thumbnail;
584
549
 
585
550
    if ( big )
586
551
    {
587
 
        if ( fi->big_thumbnail && big )
 
552
        if ( fi->big_thumbnail )
588
553
            return TRUE;
589
554
    }
590
555
    else
592
557
        if ( fi->small_thumbnail )
593
558
            return TRUE;
594
559
    }
595
 
 
596
 
    if ( !gdk_pixbuf_get_file_info( full_path, &w, &h ) )
597
 
        return FALSE;   /* image format cannot be recognized */
598
 
 
599
 
    /* If the image itself is very small, we should load it directly */
600
 
    if ( w <= 128 && h <= 128 )
 
560
    thumbnail = vfs_thumbnail_load_for_file( full_path,
 
561
                                                    big ? big_thumb_size : small_thumb_size , fi->mtime );
 
562
    if( G_LIKELY( thumbnail ) )
601
563
    {
602
 
        size = big ? big_thumb_size : small_thumb_size;
603
 
        thumbnail = gdk_pixbuf_new_from_file_at_scale( full_path, size, size,
604
 
                                                       TRUE, NULL );
605
564
        if ( big )
606
565
            fi->big_thumbnail = thumbnail;
607
566
        else
608
567
            fi->small_thumbnail = thumbnail;
609
 
        return ( thumbnail != NULL );
610
 
    }
611
 
 
612
 
    uri = g_filename_to_uri( full_path, NULL, NULL );
613
 
 
614
 
    md5_state_t md5_state;
615
 
    md5_init( &md5_state );
616
 
    md5_append( &md5_state, ( md5_byte_t * ) uri, strlen( uri ) );
617
 
    md5_finish( &md5_state, md5 );
618
 
 
619
 
    for ( i = 0; i < 16; ++i )
620
 
    {
621
 
        sprintf( ( file_name + i * 2 ), "%02x", md5[ i ] );
622
 
    }
623
 
    strcpy( ( file_name + i * 2 ), ".png" );
624
 
 
625
 
    thumbnail_file = g_build_filename( g_get_home_dir(),
626
 
                                       ".thumbnails/normal",
627
 
                                       file_name, NULL );
628
 
 
629
 
    /* load existing thumbnail */
630
 
    thumbnail = gdk_pixbuf_new_from_file( thumbnail_file, NULL );
631
 
    if ( !thumbnail ||
632
 
            !( thumb_mtime = gdk_pixbuf_get_option( thumbnail, "tEXt::Thumb::MTime" ) ) ||
633
 
            atol( thumb_mtime ) != fi->mtime )
634
 
    {
635
 
        /* create new thumbnail */
636
 
        thumbnail = gdk_pixbuf_new_from_file_at_size( full_path, 128, 128, NULL );
637
 
        if ( thumbnail )
638
 
        {
639
 
            sprintf( mtime_str, "%lu", fi->mtime );
640
 
            gdk_pixbuf_save( thumbnail, thumbnail_file, "png", NULL,
641
 
                             "tEXt::Thumb::URI", uri, "tEXt::Thumb::MTime", mtime_str, NULL );
642
 
        }
643
 
    }
644
 
 
645
 
    if ( thumbnail )
646
 
    {
647
 
        w = gdk_pixbuf_get_width( thumbnail );
648
 
        h = gdk_pixbuf_get_height( thumbnail );
649
 
        size = big ? big_thumb_size : small_thumb_size;
650
 
        if ( w > h )
651
 
        {
652
 
            h = h * size / w;
653
 
            w = size;
654
 
        }
655
 
        else if ( h > w )
656
 
        {
657
 
            w = w * size / h;
658
 
            h = size;
659
 
        }
660
 
        else
661
 
        {
662
 
            w = h = size;
663
 
        }
664
 
        result = gdk_pixbuf_scale_simple(
665
 
                     thumbnail,
666
 
                     w, h, GDK_INTERP_BILINEAR );
667
 
        gdk_pixbuf_unref( thumbnail );
 
568
    }
 
569
    else /* fallback to mime_type icon */
 
570
    {
668
571
        if ( big )
669
 
            fi->big_thumbnail = result;
 
572
            fi->big_thumbnail = vfs_file_info_get_big_icon( fi );
670
573
        else
671
 
            fi->small_thumbnail = result;
 
574
            fi->small_thumbnail = vfs_file_info_get_small_icon( fi );
672
575
    }
673
 
    g_free( uri );
674
 
    g_free( thumbnail_file );
675
 
    return ( result != NULL );
 
576
    return ( thumbnail != NULL );
676
577
}
677
578
 
678
579
void vfs_file_info_set_thumbnail_size( int big, int small )
684
585
void vfs_file_info_load_special_info( VFSFileInfo* fi,
685
586
                                      const char* file_path )
686
587
{
687
 
    if ( g_str_has_suffix( fi->name, ".desktop" ) )
 
588
    /*if ( G_LIKELY(fi->type) && G_UNLIKELY(fi->type->name, "application/x-desktop") ) */
 
589
    if ( G_UNLIKELY( g_str_has_suffix( fi->name, ".desktop") ) )
688
590
    {
689
591
        VFSAppDesktop * desktop;
690
592
        const char* icon_name;
 
593
 
691
594
        fi->flags |= VFS_FILE_INFO_DESKTOP_ENTRY;
692
595
        desktop = vfs_app_desktop_new( file_path );
693
596
        if ( vfs_app_desktop_get_disp_name( desktop ) )
695
598
            vfs_file_info_set_disp_name(
696
599
                fi, vfs_app_desktop_get_disp_name( desktop ) );
697
600
        }
698
 
        if( fi->big_thumbnail )
699
 
        {
700
 
            gdk_pixbuf_unref( fi->big_thumbnail );
701
 
            fi->big_thumbnail = NULL;
702
 
        }
 
601
 
703
602
        if ( (icon_name = vfs_app_desktop_get_icon_name( desktop )) )
704
603
        {
705
 
            char * _icon_name = strdup( icon_name );
706
604
            GdkPixbuf* icon;
707
 
            int size;
708
 
            vfs_mime_type_get_icon_size( &size, NULL );
709
 
            /* icon name is a full path */
710
 
            if ( icon_name[ 0 ] == '/' )
711
 
            {
712
 
                icon = gdk_pixbuf_new_from_file_at_size(
713
 
                           icon_name, size, size, NULL );
714
 
            }
715
 
            else
716
 
            {
717
 
                char* dot = strchr( _icon_name, '.' );
718
 
                if ( dot )
719
 
                    * dot = '\0';
720
 
                icon = gtk_icon_theme_load_icon(
721
 
                           gtk_icon_theme_get_default(),
722
 
                           _icon_name, size, 0, NULL );
723
 
            }
724
 
            /* save app icon in thumbnail */
725
 
            fi->big_thumbnail = icon;
726
 
            if ( G_LIKELY( icon ) )
727
 
                g_object_set_data_full( G_OBJECT(icon), "name", _icon_name, g_free );
728
 
            else
729
 
                g_free( _icon_name );
 
605
            int big_size, small_size;
 
606
            vfs_mime_type_get_icon_size( &big_size, &small_size );
 
607
            if( ! fi->big_thumbnail )
 
608
            {
 
609
                icon = vfs_app_desktop_get_icon( desktop, big_size, FALSE );
 
610
                if( G_LIKELY(icon) )
 
611
                    fi->big_thumbnail =icon;
 
612
            }
 
613
            if( ! fi->small_thumbnail )
 
614
            {
 
615
                icon = vfs_app_desktop_get_icon( desktop, small_size, FALSE );
 
616
                if( G_LIKELY(icon) )
 
617
                    fi->small_thumbnail =icon;
 
618
            }
730
619
        }
731
620
        vfs_app_desktop_unref( desktop );
732
621
    }
742
631
char* vfs_file_resolve_path( const char* cwd, const char* relative_path )
743
632
{
744
633
    GString* ret = g_string_sized_new( 4096 );
745
 
    const char* sep;
 
634
    int len;
 
635
    gboolean strip_tail;
 
636
 
 
637
    g_return_val_if_fail( G_LIKELY(relative_path), NULL );
 
638
 
 
639
    len = strlen( relative_path );
 
640
    strip_tail = (0 == len || relative_path[len-1] != '/');
 
641
 
746
642
    if( G_UNLIKELY(*relative_path != '/') ) /* relative path */
747
643
    {
748
644
        if( G_UNLIKELY(relative_path[0] == '~') ) /* home dir */
754
650
        {
755
651
            if( ! cwd )
756
652
            {
757
 
                cwd = g_get_current_dir();
758
 
                g_string_append( ret, cwd );
759
 
                g_free( cwd );
 
653
                char *cwd_new;
 
654
                cwd_new = g_get_current_dir();
 
655
                g_string_append( ret, cwd_new );
 
656
                g_free( cwd_new );
760
657
            }
761
658
            else
762
659
                g_string_append( ret, cwd );
763
660
        }
764
661
    }
765
662
 
766
 
    if( relative_path[0] != '/' )
 
663
    if( relative_path[0] != '/'  && (0 == ret->len || ret->str[ ret->len - 1 ] != '/' ) )
767
664
        g_string_append_c( ret, '/' );
768
665
 
769
666
    while( G_LIKELY( *relative_path ) )
793
690
        }while( G_LIKELY( *(relative_path++) != '/' && *relative_path ) );
794
691
    }
795
692
 
796
 
    /* remove tailing '/' */
797
 
    if( G_LIKELY( ret->len > 1 ) && G_UNLIKELY( ret->str[ ret->len - 1 ] == '/' ) )
 
693
    /* if original path contains tailing '/', preserve it; otherwise, remove it. */
 
694
    if( strip_tail && G_LIKELY( ret->len > 1 ) && G_UNLIKELY( ret->str[ ret->len - 1 ] == '/' ) )
798
695
        g_string_truncate( ret, ret->len - 1 );
799
696
    return g_string_free( ret, FALSE );
800
697
}