bool KIcoPlugin::readInfo( KFileMetaInfo& info, uint what) { QFile file(info.path()); if (!file.open(IO_ReadOnly)) { kdDebug(7034) << "Couldn't open " << QFile::encodeName(info.path()) << endl; return false; } QDataStream dstream(&file); // ICO files are little-endian dstream.setByteOrder(QDataStream::LittleEndian); // read the beginning of the file and make sure it looks ok uint16_t ico_reserved; uint16_t ico_type; uint16_t ico_count; dstream >> ico_reserved; dstream >> ico_type; dstream >> ico_count; if ((ico_reserved != 0) || (ico_type != 1) || (ico_count < 1)) return false; // now loop through each of the icon entries uint8_t icoe_width; uint8_t icoe_height; uint8_t icoe_colorcount; uint8_t icoe_reserved; uint16_t icoe_planes; uint16_t icoe_bitcount; uint32_t icoe_bytesinres; uint32_t icoe_imageoffset; // read the data on the 1st icon dstream >> icoe_width; dstream >> icoe_height; dstream >> icoe_colorcount; dstream >> icoe_reserved; dstream >> icoe_planes; dstream >> icoe_bitcount; dstream >> icoe_bytesinres; dstream >> icoe_imageoffset; // output the useful bits KFileMetaInfoGroup group = appendGroup(info, "Technical"); appendItem(group, "Number", ico_count); if (ico_count == 1) { appendItem(group, "Dimensions", QSize(icoe_width, icoe_height)); if (icoe_colorcount > 0) appendItem(group, "Colors", icoe_colorcount); else if (icoe_bitcount > 0) appendItem(group, "Colors", 2 ^ icoe_bitcount); } else { appendItem(group, "DimensionsM", QSize(icoe_width, icoe_height)); if (icoe_colorcount > 0) appendItem(group, "ColorsM", icoe_colorcount); else if (icoe_bitcount > 0) appendItem(group, "ColorsM", 2 ^ icoe_bitcount); } return true; }
bool KOfficePlugin::readInfo( KFileMetaInfo& info, uint /*what*/) { if ( info.path().isEmpty() ) // remote file return false; KFileMetaInfoGroup group = appendGroup(info, DocumentInfo); QDomDocument doc = getMetaDocument(info.path()); if (doc.isNull()) return false; QDomElement base = getBaseNode(doc).toElement(); if (base.isNull()) return false; for (int i = 0; Information[i]; i+=2) appendItem(group, Information[i], stringFromNode(base, Information[i])); // Special case for keyword QDomNodeList keywordList = base.elementsByTagName( metakeyword ); QString allKeywords; for (uint i = 0; i < keywordList.length(); i++){ QDomNode node = keywordList.item(i); if (node.isElement()){ if (i>0) allKeywords += ", "; allKeywords += node.toElement().text(); } } appendItem(group, metakeyword, allKeywords); KFileMetaInfoGroup group1 = appendGroup(info, DocAdvanced); for (int i = 0; Advanced[i]; i+=2){ QString txt = stringFromNode(base, Advanced[i]); if (!txt.isEmpty()){ // A silly way to do it... switch (i){ case 2: case 4: case 6: getDateTime(group1, Advanced[i], txt); break; case 14: getEditingTime(group1, Advanced[i], txt); break; default: appendItem(group1, Advanced[i], txt);} } } QDomNode dstat = base.namedItem(metadocstat); KFileMetaInfoGroup group2 = appendGroup(info, DocStatistics); if (!dstat.isNull() && dstat.isElement()){ QDomElement dinfo = dstat.toElement(); for (int i = 0; Statistics[i]; i+=2) addAttributeInfo(dinfo, group2, Statistics[i] ); } QDomNodeList userList = base.elementsByTagName( metauserdef ); KFileMetaInfoGroup groupuser = appendGroup(info, UserDefined); for (uint i = 0; i < userList.length(); i++){ QDomNode node = userList.item(i); if (node.isElement()){ appendItem(groupuser, node.toElement().attribute(metaname, QString("User %1").arg(i)), node.toElement().text()); } } return true; }
bool KRpmPlugin::readInfo( KFileMetaInfo& info, uint what) { QFile file(info.path()); int pass; KFileMetaInfoGroup general, all; if (!file.open(QIODevice::ReadOnly)) { kDebug(7034) << "Couldn't open " << QFile::encodeName(info.path()); return false; } QDataStream dstream(&file); dstream.setByteOrder(QDataStream::BigEndian); general = appendGroup(info, "General"); if (what == KFileMetaInfo::Everything) all = appendGroup(info, "All tags"); file.seek(96); // Seek past old lead for (pass = 0; pass < 2; ++pass) { // RPMs have two headers uint32_t storepos, entries, size, reserved; unsigned char version; char magic[3]; dstream.readRawBytes(magic, 3); dstream >> version >> reserved >> entries >> size; if (memcmp(magic, RPM_HEADER_MAGIC, 3)) return false; if (version != 1) return false; // Only v1 headers supported storepos = file.pos() + entries * 16; if (pass == 0) { // Don't need the first batch of tags - pgp etc file.seek(storepos + size); file.seek(file.pos() + (8 - (file.pos() % 8)) % 8); // Skip padding continue; } if (entries < 500) while (entries--) { // Just in case something goes wrong, limit to 500 uint32_t tag, type, offset, count; QString tagname; dstream >> tag >> type >> offset >> count; offset += storepos; switch (tag) { case RPMTAG_NAME: tagname = "Name"; break; case RPMTAG_VERSION: tagname = "Version"; break; case RPMTAG_SUMMARY: tagname = "Summary"; break; case RPMTAG_GROUP: tagname = "Group"; break; case RPMTAG_SIZE: tagname = "Size"; break; case RPMTAG_RELEASE: tagname = "Release"; break; case RPMTAG_VENDOR: tagname = "Vendor"; break; case RPMTAG_PACKAGER: tagname = "Packager"; break; case RPMTAG_DESCRIPTION: tagname = "Comment"; break; } if ( !tagname.isEmpty() || all.isValid() ) { // kDebug(7034) << "Tag number: " << tag << " Type: " << type; int oldPos = file.pos(); file.seek(offset); // Set file position to correct place in store switch (type) { case RPM_INT32_TYPE: uint32_t int32tag; dstream >> int32tag; if ( !tagname.isEmpty() ) appendItem(general, tagname, int(int32tag)); if ( all.isValid() ) appendItem(all, QString("%1").arg( tag ), QString("%1").arg( int32tag )); break; case RPM_INT16_TYPE: uint16_t int16tag; dstream >> int16tag; if ( !tagname.isEmpty() ) appendItem(general, tagname, int(int16tag)); if ( all.isValid() ) appendItem(all, QString("%1").arg( tag ), QString("%1").arg( int16tag )); break; case RPM_I18NSTRING_TYPE: // Fallthru case RPM_STRING_TYPE: QString strtag; char in; while ( ( in = file.getch() ) != '\0' ) strtag += in; if ( !tagname.isEmpty() ) appendItem(general, tagname, strtag); if( all.isValid() ) appendItem(all, QString("%1").arg( tag ), strtag); break; } file.seek(oldPos); // Restore old position } } appendItem(general, "Archive Offset", (storepos + size) ); }
bool KFlacPlugin::readInfo( KFileMetaInfo& info, uint what ) { if ( info.path().isEmpty() ) // remote file return false; bool readComment = false; bool readTech = false; if (what & (KFileMetaInfo::Fastest | KFileMetaInfo::DontCare | KFileMetaInfo::ContentInfo)) readComment = true; if (what & (KFileMetaInfo::Fastest | KFileMetaInfo::DontCare | KFileMetaInfo::TechnicalInfo)) readTech = true; TagLib::File *file = 0; if (info.mimeType() == "audio/x-flac") file = new TagLib::FLAC::File(QFile::encodeName(info.path()).data(), readTech); #ifdef TAGLIB_1_2 else file = new TagLib::Ogg::FLAC::File(QFile::encodeName(info.path()).data(), readTech); #endif if (!file || !file->isValid()) { kdDebug(7034) << "Couldn't open " << file->name() << endl; delete file; return false; } if(readComment && file->tag()) { KFileMetaInfoGroup commentgroup = appendGroup(info, "Comment"); QString date = file->tag()->year() > 0 ? QString::number(file->tag()->year()) : QString::null; QString track = file->tag()->track() > 0 ? QString::number(file->tag()->track()) : QString::null; appendItem(commentgroup, "Title", TStringToQString(file->tag()->title()).stripWhiteSpace()); appendItem(commentgroup, "Artist", TStringToQString(file->tag()->artist()).stripWhiteSpace()); appendItem(commentgroup, "Album", TStringToQString(file->tag()->album()).stripWhiteSpace()); appendItem(commentgroup, "Date", date); appendItem(commentgroup, "Comment", TStringToQString(file->tag()->comment()).stripWhiteSpace()); appendItem(commentgroup, "Tracknumber", track); appendItem(commentgroup, "Genre", TStringToQString(file->tag()->genre()).stripWhiteSpace()); } if (readTech && file->audioProperties()) { KFileMetaInfoGroup techgroup = appendGroup(info, "Technical"); TagLib::FLAC::Properties *properties = (TagLib::FLAC::Properties*)(file->audioProperties()); appendItem(techgroup, "Bitrate", properties->bitrate()); appendItem(techgroup, "Sample Rate", properties->sampleRate()); appendItem(techgroup, "Sample Width", properties->sampleWidth()); appendItem(techgroup, "Channels", properties->channels()); appendItem(techgroup, "Length", properties->length()); } delete file; return true; }
QString KFileItem::getToolTipText(int maxcount) { // we can return QString::null if no tool tip should be shown QString tip; KFileMetaInfo info = metaInfo(); // the font tags are a workaround for the fact that the tool tip gets // screwed if the color scheme uses white as default text color const char* start = "<tr><td><nobr><font color=\"black\">"; const char* mid = "</font></nobr></td><td><nobr><font color=\"black\">"; const char* end = "</font></nobr></td></tr>"; tip = "<table cellspacing=0 cellpadding=0>"; tip += start + i18n("Name:") + mid + text() + end; tip += start + i18n("Type:") + mid; QString type = QStyleSheet::escape(mimeComment()); if ( m_bLink ) { tip += i18n("Link to %1 (%2)").arg(linkDest(), type) + end; } else tip += type + end; if ( !S_ISDIR ( m_fileMode ) ) { bool hasSize; KIO::filesize_t sizeValue = size(hasSize); if(hasSize) tip += start + i18n("Size:") + mid + KIO::convertSizeWithBytes(sizeValue) + end; } QString timeStr = timeString( KIO::UDS_MODIFICATION_TIME); if(!timeStr.isEmpty()) tip += start + i18n("Modified:") + mid + timeStr + end; #ifndef Q_WS_WIN //TODO: show win32-specific permissions QString userStr = user(); QString groupStr = group(); if(!userStr.isEmpty() || !groupStr.isEmpty()) tip += start + i18n("Owner:") + mid + userStr + " - " + groupStr + end + start + i18n("Permissions:") + mid + parsePermissions(m_permissions) + end; #endif if (info.isValid() && !info.isEmpty() ) { tip += "<tr><td colspan=2><center><s> </s></center></td></tr>"; QStringList keys = info.preferredKeys(); // now the rest QStringList::Iterator it = keys.begin(); for (int count = 0; count<maxcount && it!=keys.end() ; ++it) { KFileMetaInfoItem item = info.item( *it ); if ( item.isValid() ) { QString s = item.string(); if ( ( item.attributes() & KFileMimeTypeInfo::SqueezeText ) && s.length() > 50) { s.truncate(47); s.append("..."); } if ( !s.isEmpty() ) { count++; tip += start + QStyleSheet::escape( item.translatedKey() ) + ":" + mid + QStyleSheet::escape( s ) + end; } } } } tip += "</table>"; //kdDebug() << "making this the tool tip rich text:\n"; //kdDebug() << tip << endl; return tip; }
bool KAuPlugin::readInfo( KFileMetaInfo& info, uint what) { // the file signature, wants to be tidier... const char fsig[] = { 0x2e, 0x73, 0x6e, 0x64 }; // a dword buffer for input char inbuf[4]; // some vars for the file properties uint32_t datasize; uint32_t encoding; uint32_t samplerate; uint32_t channels; uint16_t bytespersample; if ( info.path().isEmpty() ) // remote file return false; QFile file(info.path()); if (!file.open(IO_ReadOnly)) { kdDebug(7034) << "Couldn't open " << QFile::encodeName(info.path()) << endl; return false; } QDataStream dstream(&file); // AU files are big-endian dstream.setByteOrder(QDataStream::BigEndian); // Read and verify the signature dstream.readRawBytes(inbuf, 4); if (memcmp(fsig, inbuf, 4)) return false; // skip unwanted bits file.at(8); // grab the bits we want dstream >> datasize; dstream >> encoding; dstream >> samplerate; dstream >> channels; // add the info KFileMetaInfoGroup group = appendGroup(info, "Technical"); appendItem(group, "Sample Rate", (uint) samplerate); appendItem(group, "Channels", (uint) channels); // work out the encoding switch (encoding) { case 1 : appendItem(group, "Encoding", i18n("8-bit ISDN u-law")); bytespersample = 1; break; case 2 : appendItem(group, "Encoding", i18n("8-bit linear PCM [REF-PCM]")); bytespersample = 1; break; case 3 : appendItem(group, "Encoding", i18n("16-bit linear PCM")); bytespersample = 2; break; case 4 : appendItem(group, "Encoding", i18n("24-bit linear PCM")); bytespersample = 3; break; case 5 : appendItem(group, "Encoding", i18n("32-bit linear PCM")); bytespersample = 4; break; case 6 : appendItem(group, "Encoding", i18n("32-bit IEEE floating point")); bytespersample = 4; break; case 7 : appendItem(group, "Encoding", i18n("64-bit IEEE floating point")); bytespersample = 8; break; case 23 : appendItem(group, "Encoding", i18n("8-bit ISDN u-law compressed")); bytespersample = 1; break; default : appendItem(group, "Encoding", i18n("Unknown")); bytespersample = 0; } // work out length from bytespersample + channels + size if ((channels > 0) && (datasize > 0) && (datasize != 0xFFFFFFFF) && (bytespersample > 0) && (samplerate > 0)) { uint32_t length = datasize / channels / bytespersample / samplerate; appendItem(group, "Length", (uint) length); } else { appendItem(group, "Length", "???"); } return true; }
bool KigPlugin::readInfo( KFileMetaInfo& metainfo, uint /*what*/ ) { KFileMetaInfoGroup metagroup = appendGroup( metainfo, "KigInfo"); QString sfile = metainfo.path(); bool iscompressed = false; QFile f( sfile ); if ( !sfile.endsWith( ".kig", false ) ) { iscompressed = true; QString tempdir = KGlobal::dirs()->saveLocation( "tmp" ); if ( tempdir.isEmpty() ) return false; QString tempname = sfile.section( '/', -1 ); if ( sfile.endsWith( ".kigz", false ) ) { tempname.remove( QRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) ); } else return false; // reading compressed file KTar* ark = new KTar( sfile, "application/x-gzip" ); ark->open( IO_ReadOnly ); const KArchiveDirectory* dir = ark->directory(); QStringList entries = dir->entries(); QStringList kigfiles = entries.grep( QRegExp( "\\.kig$" ) ); if ( kigfiles.count() != 1 ) return false; const KArchiveEntry* kigz = dir->entry( kigfiles[0] ); if ( !kigz->isFile() ) return false; dynamic_cast<const KArchiveFile*>( kigz )->copyTo( tempdir ); f.setName( tempdir + kigz->name() ); } if ( !f.open( IO_ReadOnly ) ) return false; QDomDocument doc( "KigDocument" ); if ( !doc.setContent( &f ) ) return false; f.close(); // removing temp file if ( iscompressed ) f.remove(); QDomElement main = doc.documentElement(); // reading the version... QString version = main.attribute( "Version" ); if ( version.isEmpty() ) version = main.attribute( "version" ); if ( version.isEmpty() ) version = i18n( "Translators: Not Available", "n/a" ); appendItem( metagroup, "Version", version ); // reading the compatibility version... QString compatversion = main.attribute( "CompatibilityVersion" ); if ( compatversion.isEmpty() ) compatversion = i18n( "%1 represents Kig version", "%1 (as the version)" ).arg( version ); appendItem( metagroup, "CompatVersion", compatversion ); // reading the Coordinate System... QCString coordsystem; for ( QDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() ) { QDomElement e = n.toElement(); if ( e.isNull() ) continue; if ( e.tagName() == "CoordinateSystem" ) coordsystem = e.text().latin1(); } appendItem( metagroup, "CoordSystem", coordsystem ); // has Kig document the grid? bool btmp = true; QString stmp = main.attribute( "grid" ); if ( !( stmp.isEmpty() || ( stmp != "0" ) ) ) btmp = ( stmp != "0" ); QString stmp2 = btmp ? i18n( "Yes" ) : i18n( "No" ); appendItem( metagroup, "Grid", stmp2 ); // has Kig document the axes? btmp = true; stmp = main.attribute( "axes" ); if ( !( stmp.isEmpty() || ( stmp != "0" ) ) ) btmp = ( stmp != "0" ); stmp2 = btmp ? i18n( "Yes" ) : i18n( "No" ); appendItem( metagroup, "Axes", stmp2 ); stmp2 = iscompressed ? i18n( "Yes" ) : i18n( "No" ); appendItem( metagroup, "Compressed", stmp2 ); return true; }
bool KXpsPlugin::readInfo( KFileMetaInfo& info, uint /* what */) { KFileMetaInfoGroup generalGroup = appendGroup(info, "General"); KZip *xpsArchive = new KZip( info.path() ); if ( xpsArchive->open( IO_ReadOnly ) == true ) { // kdDebug(7115) << "Successful open of " << xpsArchive->fileName() << endl; } else { kDebug(7115) << "Could not open XPS archive: " << xpsArchive->fileName(); delete xpsArchive; return false; } const KZipFileEntry* relFile = static_cast<const KZipFileEntry *>(xpsArchive->directory()->entry("_rels/.rels")); if ( !relFile ) { delete xpsArchive; // this might occur if we can't read the zip directory, or it doesn't have the relationships entry return false; } if ( relFile->name().isEmpty() ) { delete xpsArchive; // this might occur if we can't read the zip directory, or it doesn't have the relationships entry return false; } QIODevice* relDevice = relFile->createDevice(); QDomDocument relDom; QString errMsg; int errLine, errCol; if ( relDom.setContent( relDevice, true, &errMsg, &errLine, &errCol ) == false ) { // parse error kDebug(7115) << "Could not parse relationship document: " << errMsg << " : " << errLine << " : " << errCol << endl; delete relDevice; delete xpsArchive; return false; } QDomElement docElem = relDom.documentElement(); QString thumbFileName; QString fixedRepresentationFileName; QString metadataFileName; QDomNode n = docElem.firstChild(); while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if ("http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail" == e.attribute("Type") ) { thumbFileName = e.attribute("Target"); } else if ("http://schemas.microsoft.com/xps/2005/06/fixedrepresentation" == e.attribute("Type") ) { fixedRepresentationFileName = e.attribute("Target"); } else if ("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" == e.attribute("Type") ) { metadataFileName = e.attribute("Target"); } } n = n.nextSibling(); } delete relDevice; if ( fixedRepresentationFileName.isEmpty() ) { delete xpsArchive; // FixedRepresentation is a required part of the XPS document return false; } const KZipFileEntry* fixedRepFile = static_cast<const KZipFileEntry *>(xpsArchive->directory()->entry( fixedRepresentationFileName )); QIODevice* fixedRepDevice = fixedRepFile->createDevice(); QDomDocument fixedRepDom; if ( fixedRepDom.setContent( fixedRepDevice, true, &errMsg, &errLine, &errCol ) == false ) { // parse error kDebug(7115) << "Could not parse Fixed Representation document: " << errMsg << " : " << errLine << " : " << errCol << endl; delete fixedRepDevice; delete xpsArchive; return false; } docElem = fixedRepDom.documentElement(); QString firstDocumentFileName; int numDocuments = 0; // the number of Documents in this FixedDocumentSequence n = docElem.firstChild(); while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if (e.tagName() == "DocumentReference") { if (firstDocumentFileName.isEmpty()) { // we don't already have a filename, so take this one firstDocumentFileName = e.attribute("Source"); } numDocuments++; } } n = n.nextSibling(); } delete fixedRepDevice; #if 0 // This stuff is used for detailed parsing - not really required // no document? bail out here. if ( firstDocumentFileName.isEmpty() ) { return false; } KZipFileEntry* firstDocumentFile = static_cast<const KZipFileEntry *>(xpsArchive->directory()->entry( firstDocumentFileName )); QIODevice* firstDocumentDevice = firstDocumentFile->device(); QDomDocument firstDocumentDom; if ( firstDocumentDom.setContent( firstDocumentDevice, true, &errMsg, &errLine, &errCol ) == false ) { // parse error kDebug(7115) << "Could not parse first document: " << errMsg << " : " << errLine << " : " << errCol << endl; return false; } n = firstDocumentDom.documentElement().firstChild(); while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { kDebug(7155) << "DOcument: " << e.tagName() << " : " << e.text(); } n = n.nextSibling(); } #endif if ( ! metadataFileName.isEmpty() ) { const KZipFileEntry* corepropsFile = static_cast<const KZipFileEntry *>(xpsArchive->directory()->entry(metadataFileName)); kDebug(7115) << "metadata file name: " << metadataFileName; QDomDocument metadataDocumentDom; QIODevice *corepropsDevice = corepropsFile->createDevice(); if ( metadataDocumentDom.setContent( corepropsDevice, true, &errMsg, &errLine, &errCol ) == false ) { // parse error kDebug(7115) << "Could not parse core properties (metadata) document: " << errMsg << " : " << errLine << " : " << errCol << endl; delete corepropsDevice; delete xpsArchive; return false; } n = metadataDocumentDom.documentElement().firstChild(); // the <coreProperties> level while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if (e.tagName() == "title") { appendItem(generalGroup, "Title", e.text() ); } else if (e.tagName() == "subject") { appendItem(generalGroup, "Subject", e.text() ); } else if (e.tagName() == "description") { appendItem(generalGroup, "Description", e.text() ); } else if (e.tagName() == "creator") { appendItem(generalGroup, "Author", e.text() ); } else if (e.tagName() == "created") { appendItem(generalGroup, "CreationDate", QDateTime::fromString( e.text(), "yyyy-MM-ddThh:mm:ssZ" ) ); } else if (e.tagName() == "modified") { appendItem(generalGroup, "ModificationDate", QDateTime::fromString( e.text(), "yyyy-MM-ddThh:mm:ssZ" ) ); } else if (e.tagName() == "keywords") { appendItem(generalGroup, "Keywords", e.text() ); } else { kDebug(7155) << "unhandled metadata tag: " << e.tagName() << " : " << e.text(); } } n = n.nextSibling(); } delete corepropsDevice; } if ( ! thumbFileName.isEmpty() ) { const KZipFileEntry* thumbFile = static_cast<const KZipFileEntry *>(xpsArchive->directory()->entry(thumbFileName)); QImage img; img.loadFromData(thumbFile->data()); appendItem( generalGroup, "Thumbnail", img); appendItem( generalGroup, "ThumbnailDimensions", QSize( img.width(), img.height() ) ); } appendItem(generalGroup, "Documents", numDocuments); delete xpsArchive; return true; }
bool KRgbPlugin::readInfo(KFileMetaInfo& info, uint /*what*/) { QFile file(info.path()); if (!file.open(QIODevice::ReadOnly)) { kDebug(7034) << "Couldn't open " << QFile::encodeName(info.path()); return false; } QDataStream dstream(&file); quint16 magic; quint8 storage; quint8 bpc; quint16 dimension; quint16 xsize; quint16 ysize; quint16 zsize; quint32 pixmin; quint32 pixmax; quint32 dummy; char imagename[80]; quint32 colormap; dstream >> magic; dstream >> storage; dstream >> bpc; dstream >> dimension; dstream >> xsize; dstream >> ysize; dstream >> zsize; dstream >> pixmin; dstream >> pixmax; dstream >> dummy; dstream.readRawBytes(imagename, 80); imagename[79] = '\0'; dstream >> colormap; quint8 u8; for (uint i = 0; i < 404; i++) dstream >> u8; if (magic != 474) return false; KFileMetaInfoGroup group; group = appendGroup(info, "Technical"); if (dimension == 1) ysize = 1; appendItem(group, "Dimensions", QSize(xsize, ysize)); appendItem(group, "BitDepth", zsize * 8 * bpc); if (zsize == 1) appendItem(group, "ColorMode", i18n("Grayscale")); else if (zsize == 2) appendItem(group, "ColorMode", i18n("Grayscale/Alpha")); else if (zsize == 3) appendItem(group, "ColorMode", i18n("RGB")); else if (zsize == 4) appendItem(group, "ColorMode", i18n("RGB/Alpha")); if (!storage) appendItem(group, "Compression", i18nc("Compression", "Uncompressed")); else if (storage == 1) { long compressed = file.size() - 512; long verbatim = xsize * ysize * zsize; appendItem(group, "Compression", i18nc("Compression", "Runlength Encoded") + QString(", %1%").arg(compressed * 100.0 / verbatim, 0, 'f', 1)); long k; quint32 offs; QMap<quint32, uint> map; QMap<quint32, uint>::Iterator it; QMap<quint32, uint>::Iterator end = map.end(); for (k = 0; k < (ysize * zsize); k++) { dstream >> offs; if ((it = map.find(offs)) != end) map.insert(offs, *it + 1); else map[offs] = 0; } for (k = 0, it = map.begin(); it != end; ++it) k += *it; if (k) appendItem(group, "SharedRows", QString("%1%").arg(k * 100.0 / (ysize * zsize), 0, 'f', 1)); else appendItem(group, "SharedRows", i18nc("SharedRows", "None")); } else