void DB::FileInfo::parseKFileMetaInfo( const DB::FileName& fileName )
{
    KFileMetaInfo metainfo( fileName.absolute() );
    if ( !metainfo.isValid() )
        return;

    // Date.
    if ( metainfo.keys().contains( QString::fromLatin1( "CreationDate" ) ) ) {
        QDate date = metainfo.item( QString::fromLatin1( "CreationDate" )).value().toDate();
        if ( date.isValid() ) {
            m_date.setDate( date );

            if ( metainfo.keys().contains( QString::fromLatin1( "CreationTime" ) ) ) {
                QTime time = metainfo.item(QString::fromLatin1( "CreationTime" )).value().toTime();
                if ( time.isValid() )
                    m_date.setTime( time );
            }
        }
    }

    // Angle
    if ( metainfo.keys().contains( QString::fromLatin1( "Orientation" ) ) )
        m_angle = orientationToAngle( metainfo.item( QString::fromLatin1( "Orientation" ) ).value().toInt() );

    // Description
    if ( metainfo.keys().contains( QString::fromLatin1( "Comment" ) ) )
        m_description = metainfo.item( QString::fromLatin1( "Comment" ) ).value().toString();
}
DB::FileInfo::FileInfo( const DB::FileName& fileName, DB::ExifMode mode )
    : m_angle(0)
{
#ifdef HAVE_EXIV2
    parseEXIV2( fileName );
#else
    parseKFileMetaInfo( fileName );
#endif


    if ( updateDataFromFileTimeStamp(fileName,mode))
        m_date = QFileInfo( fileName.absolute() ).lastModified();
}
bool RAWImageDecoder::_fileExistsWithExtensions( const DB::FileName& fileName,
                                                 const QStringList& extensionList) const
{
    QString baseFileName = fileName.absolute();
    int extStart = baseFileName.lastIndexOf(QChar::fromLatin1('.'));
    // We're interested in xxx.yyy, not .yyy
    if (extStart <= 1) return false;
    baseFileName.remove(extStart, baseFileName.length() - extStart);
    for ( QStringList::ConstIterator it = extensionList.begin();
          it != extensionList.end(); ++it ) {
        if (QFile::exists(baseFileName + *it)) return true;
    }
    return false;
}
bool RAWImageDecoder::_fileIsKnownWithExtensions( const DB::FileNameSet& files,
                                                  const DB::FileName& fileName,
                                                  const QStringList& extensionList) const
{
    QString baseFileName = fileName.absolute();
    int extStart = baseFileName.lastIndexOf(QChar::fromLatin1('.'));
    if (extStart <= 1) return false;
    baseFileName.remove(extStart, baseFileName.length() - extStart);
    for ( QStringList::ConstIterator it = extensionList.begin();
          it != extensionList.end(); ++it ) {
        if (files.contains(DB::FileName::fromAbsolutePath(baseFileName + *it)) )
            return true;
    }
    return false;
}
ImageInfo::ImageInfo( const DB::FileName& fileName, MediaType type, bool readExifInfo )
    :  m_imageOnDisk( YesOnDisk ), m_null( false ), m_size( -1, -1 ), m_type( type )
      , m_rating(-1), m_stackId(0), m_stackOrder(0)
      , m_videoLength(-1)
      , m_locked(false), m_delaySaving( true )
{
    QFileInfo fi( fileName.absolute() );
    m_label = fi.completeBaseName();
    m_angle = 0;

    setFileName(fileName);

    // Read EXIF information
    if ( readExifInfo )
        readExif(fileName, EXIFMODE_INIT);

    m_dirty = false;
    m_delaySaving = false;
}
QString MainWindow::ExternalPopup::mimeType( const DB::FileName& file )
{
    return KMimeType::findByPath(file.absolute(), 0, true)->name();
}
bool RAWImageDecoder::_decode( QImage *img, const DB::FileName& imageFile, QSize* fullSize, int dim)
{
    /* width and height seem to be only hints, ignore */
    Q_UNUSED( dim );

#ifdef HAVE_KDCRAW
#if KDCRAW_VERSION >= 0x020200
    if ( !KDcrawIface::KDcraw::loadRawPreview( *img, imageFile.absolute() ) )
#else
    if ( !KDcrawIface::KDcraw::loadDcrawPreview( *img, imageFile.absolute() ) )
#endif
        return false;

    // FIXME: The preview data for Canon's image is always returned in its non-rotated form by libkdcraw, ie. KPA should do the rotation.
    // FIXME: This will happen later on.
    if ( Settings::SettingsData::instance()->useRawThumbnail() &&
         img->width() >= Settings::SettingsData::instance()->useRawThumbnailSize().width() &&
         img->height() >= Settings::SettingsData::instance()->useRawThumbnailSize().height() )
        return true;

    KDcrawIface::DcrawInfoContainer metadata;
    if (!KDcrawIface::KDcraw::rawFileIdentify(metadata, imageFile.absolute()))
        return false;

    if ((img->width() < metadata.imageSize.width() * 0.8) ||
        (img->height() < metadata.imageSize.height() * 0.8)) {

        // let's try to get a better resolution
        KDcrawIface::KDcraw decoder;
        KDcrawIface::RawDecodingSettings rawDecodingSettings;

        if ( rawDecodingSettings.sixteenBitsImage ) {
            kDebug() << "16 bits per color channel is not supported yet";
            return false;
        } else {
            QByteArray imageData; /* 3 bytes for each pixel,  */
            int width, height, rgbmax;
            if ( !decoder.decodeRAWImage( imageFile.absolute(), rawDecodingSettings, imageData, width, height, rgbmax ) )
                return false;

            // Now the funny part, how to turn this fugly QByteArray into an QImage. Yay!
            *img = QImage(width, height, QImage::Format_RGB32);
            if (img->isNull())
                return false;

            uchar* data = img->bits();

            for ( int i = 0; i < imageData.size(); i += 3, data += 4 ) {
                data[0] = imageData[i + 2]; // blue
                data[1] = imageData[i + 1]; // green
                data[2] = imageData[i];     // red
                data[3] = 0xff;             // alpha
            }
        }
    }

    if ( fullSize )
        *fullSize = img->size();

    return true;
#else /* HAVE_KDCRAW */
    Q_UNUSED( img );
    Q_UNUSED( imageFile );
    Q_UNUSED( fullSize );
    return false;
#endif /* HAVE_KDCRAW */
}