• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kmimetype.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00003  *                2000-2007 David Faure <faure@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "kmimetype.h"
00021 #include "kmimetype_p.h"
00022 #include "kmimetypefactory.h"
00023 
00024 #include <kconfig.h>
00025 #include <kconfiggroup.h>
00026 #include <kdebug.h>
00027 #include <kdesktopfile.h>
00028 #include <kde_file.h>
00029 #include <klocale.h>
00030 #include <kmessage.h>
00031 #include <kprotocolinfo.h>
00032 #include <kprotocolinfofactory.h>
00033 #include <kstandarddirs.h>
00034 #include <ksycoca.h>
00035 #include <kurl.h>
00036 
00037 #include <QtCore/QMutableSetIterator>
00038 #include <QtCore/QCharRef>
00039 #include <QtCore/QFile>
00040 #include <QtDBus/QtDBus>
00041 #include <QBuffer>
00042 
00043 #include <sys/types.h>
00044 #include <sys/stat.h>
00045 
00046 #include <assert.h>
00047 #include <errno.h>
00048 #include <stddef.h>
00049 #include <unistd.h>
00050 #include <stdlib.h>
00051 
00052 template class KSharedPtr<KMimeType>;
00053 
00054 static KMimeType::Ptr s_pDefaultMimeType;
00055 
00056 static void errorMissingMimeTypes( const QStringList& _types )
00057 {
00058     KMessage::message( KMessage::Error, i18np( "Could not find mime type <resource>%2</resource>",
00059                 "Could not find mime types:\n<resource>%2</resource>", _types.count(), _types.join("</resource>\n<resource>") ) );
00060 }
00061 
00062 void KMimeTypePrivate::loadInternal( QDataStream& _str )
00063 {
00064     QString oldParentMimeTypeString;
00065     _str >> m_lstPatterns >> oldParentMimeTypeString >> m_parentMimeTypes;
00066 
00067     // kde-4.0 compatibility. Remove in kde5.
00068     if (!oldParentMimeTypeString.isEmpty() && m_parentMimeTypes.isEmpty())
00069         m_parentMimeTypes.append(oldParentMimeTypeString);
00070 }
00071 
00076 void KMimeType::buildDefaultType()
00077 {
00078     assert ( !s_pDefaultMimeType );
00079     // Try to find the default type
00080     KMimeType::Ptr mime = KMimeTypeFactory::self()->
00081                           findMimeTypeByName( KMimeType::defaultMimeType() );
00082 
00083     if (mime)
00084     {
00085         s_pDefaultMimeType = mime;
00086     }
00087     else
00088     {
00089         QString defaultMimeType = KMimeType::defaultMimeType();
00090         errorMissingMimeTypes( QStringList(defaultMimeType) );
00091         QString sDefaultMimeType = KGlobal::dirs()->resourceDirs("xdgdata-mime").first()+defaultMimeType+".xml";
00092         s_pDefaultMimeType = new KMimeType( sDefaultMimeType, defaultMimeType, "mime" );
00093     }
00094 }
00095 
00096 KMimeType::Ptr KMimeType::defaultMimeTypePtr()
00097 {
00098     if ( !s_pDefaultMimeType ) // we need a default type first
00099         buildDefaultType();
00100     return s_pDefaultMimeType;
00101 }
00102 
00103 bool KMimeType::isDefault() const
00104 {
00105     return this == defaultMimeTypePtr().data();
00106 }
00107 
00111 void KMimeType::checkEssentialMimeTypes()
00112 {
00113     static bool s_bChecked = false;
00114 
00115     if ( s_bChecked ) // already done
00116         return;
00117     if ( !s_pDefaultMimeType ) // we need a default type first
00118         KMimeType::buildDefaultType();
00119 
00120   s_bChecked = true; // must be done before building mimetypes
00121 
00122   // No Mime-Types installed ?
00123   // Lets do some rescue here.
00124   if ( !KMimeTypeFactory::self()->checkMimeTypes() )
00125   {
00126     // Note that this messagebox is queued, so it will only be shown once getting back to the event loop
00127 
00128     // No mimetypes installed? Are you setting XDG_DATA_DIRS without including /usr/share in it?
00129     KMessage::message( KMessage::Error, i18n( "No mime types installed. Check that shared-mime-info is installed, and that XDG_DATA_DIRS is not set, or includes /usr/share." ) );
00130     return; // no point in going any further
00131   }
00132 
00133   QStringList missingMimeTypes;
00134 
00135 #ifndef Q_OS_WIN
00136   if ( !KMimeType::mimeType( "inode/directory" ) )
00137     missingMimeTypes.append( "inode/directory" );
00138   //if ( !KMimeType::mimeType( "inode/directory-locked" ) )
00139   //  missingMimeTypes.append( "inode/directory-locked" );
00140   if ( !KMimeType::mimeType( "inode/blockdevice" ) )
00141     missingMimeTypes.append( "inode/blockdevice" );
00142   if ( !KMimeType::mimeType( "inode/chardevice" ) )
00143     missingMimeTypes.append( "inode/chardevice" );
00144   if ( !KMimeType::mimeType( "inode/socket" ) )
00145     missingMimeTypes.append( "inode/socket" );
00146   if ( !KMimeType::mimeType( "inode/fifo" ) )
00147     missingMimeTypes.append( "inode/fifo" );
00148 #endif
00149   if ( !KMimeType::mimeType( "application/x-shellscript" ) )
00150     missingMimeTypes.append( "application/x-shellscript" );
00151   if ( !KMimeType::mimeType( "application/x-executable" ) )
00152     missingMimeTypes.append( "application/x-executable" );
00153   if ( !KMimeType::mimeType( "application/x-desktop" ) )
00154     missingMimeTypes.append( "application/x-desktop" );
00155 
00156   if (!missingMimeTypes.isEmpty())
00157     errorMissingMimeTypes(missingMimeTypes);
00158 }
00159 
00160 KMimeType::Ptr KMimeType::mimeType( const QString& _name, FindByNameOption options )
00161 {
00162     return KMimeTypeFactory::self()->findMimeTypeByName( _name, options );
00163 }
00164 
00165 KMimeType::List KMimeType::allMimeTypes()
00166 {
00167     return KMimeTypeFactory::self()->allMimeTypes();
00168 }
00169 
00170 bool KMimeType::isBufferBinaryData(const QByteArray& data)
00171 {
00172     // Check the first 32 bytes (see shared-mime spec)
00173     const char* p = data.data();
00174     const int end = qMin(32, data.size());
00175     for (int i = 0; i < end; ++i) {
00176         if (p[i] < 32 && p[i] != 9 && p[i] != 10 && p[i] != 13) // ASCII control character
00177             return true;
00178     }
00179     return false;
00180 }
00181 
00182 static KMimeType::Ptr findFromMode( const QString& path /*only used if is_local_file*/,
00183                                     mode_t mode /*0 if unknown*/,
00184                                     bool is_local_file )
00185 {
00186     if ( is_local_file && (mode == 0 || mode == (mode_t)-1) ) {
00187         KDE_struct_stat buff;
00188         if ( KDE_stat( QFile::encodeName(path), &buff ) != -1 )
00189             mode = buff.st_mode;
00190     }
00191 
00192     if ( S_ISDIR( mode ) ) {
00193         // KDE4 TODO: use an overlay instead
00194 #if 0
00195         // Special hack for local files. We want to see whether we
00196         // are allowed to enter the directory
00197         if ( is_local_file )
00198         {
00199             if ( access( QFile::encodeName(path), R_OK ) == -1 )
00200                 return KMimeType::mimeType( "inode/directory-locked" );
00201         }
00202 #endif
00203         return KMimeType::mimeType( "inode/directory" );
00204     }
00205     if ( S_ISCHR( mode ) )
00206         return KMimeType::mimeType( "inode/chardevice" );
00207     if ( S_ISBLK( mode ) )
00208         return KMimeType::mimeType( "inode/blockdevice" );
00209     if ( S_ISFIFO( mode ) )
00210         return KMimeType::mimeType( "inode/fifo" );
00211     if ( S_ISSOCK( mode ) )
00212         return KMimeType::mimeType( "inode/socket" );
00213 #ifdef Q_OS_WIN
00214     // FIXME: distinguish between mounted & unmounted
00215     int size = path.size();
00216     if ( size == 2 || size == 3 ) {
00217         unsigned int type = GetDriveTypeW( (LPCWSTR) path.utf16() );
00218         switch( type ) {
00219             case DRIVE_REMOVABLE:
00220                 return KMimeType::mimeType( "media/floppy_mounted" );
00221             case DRIVE_FIXED:
00222                 return KMimeType::mimeType( "media/hdd_mounted" );
00223             case DRIVE_REMOTE:
00224                 return KMimeType::mimeType( "media/smb_mounted" );
00225             case DRIVE_CDROM:
00226                 return KMimeType::mimeType( "media/cdrom_mounted" );
00227             case DRIVE_RAMDISK:
00228                 return KMimeType::mimeType( "media/hdd_mounted" );
00229             default:
00230                 break;
00231         };
00232     }
00233 #endif
00234     // remote executable file? stop here (otherwise findFromContent can do that better for local files)
00235     if ( !is_local_file && S_ISREG( mode ) && ( mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
00236         return KMimeType::mimeType( "application/x-executable" );
00237 
00238     return KMimeType::Ptr();
00239 }
00240 
00241 /*
00242 
00243 As agreed on the XDG list (and unlike the current shared-mime spec):
00244 
00245 Glob-matching should prefer derived mimetype over base mimetype, and longer matches
00246 over shorter ones. However if two globs of the same length match the file, and the two
00247 matches are not related in the inheritance tree, then we have a "glob conflict", which
00248 will be resolved below.
00249 
00250 If only one glob matches, use that
00251 
00252 If no glob matches, sniff and use that
00253 
00254 If several globs matches, and sniffing gives a result we do:
00255   if sniffed prio >= 80, use sniffed type
00256   for glob_match in glob_matches:
00257      if glob_match is subclass or equal to sniffed_type, use glob_match
00258 
00259 If several globs matches, and sniffing fails, or doesn't help:
00260   fall back to the first glob match
00261 
00262 This algorithm only sniffs when there is some uncertainty with the
00263 extension matching (thus, it's usable for a file manager).
00264 
00265 Note: in KDE we want the file views to sniff in a delayed manner.
00266 So there's also a fast mode which is:
00267  if no glob matches, or if more than one glob matches, use default mimetype and mark as "can be refined".
00268 
00269 */
00270 
00271 KMimeType::Ptr KMimeType::findByUrlHelper( const KUrl& _url, mode_t mode,
00272                                            bool is_local_file,
00273                                            QIODevice* device,
00274                                            int* accuracy )
00275 {
00276     checkEssentialMimeTypes();
00277     const QString path = _url.path();
00278 
00279     if (accuracy)
00280         *accuracy = 100;
00281 
00282     // Look at mode first
00283     KMimeType::Ptr mimeFromMode = findFromMode( path, mode, is_local_file );
00284     if (mimeFromMode)
00285         return mimeFromMode;
00286 
00287     // First try to find out by looking at the filename (if there's one)
00288     const QString fileName( _url.fileName() );
00289     QList<KMimeType::Ptr> mimeList;
00290     if ( !fileName.isEmpty() && !path.endsWith( '/' ) ) {
00291         // and if we can trust it (e.g. don't trust *.pl over HTTP, could be anything)
00292         if ( is_local_file || _url.hasSubUrl() || // Explicitly trust suburls
00293              KProtocolInfo::determineMimetypeFromExtension( _url.protocol() ) ) {
00294             mimeList = KMimeTypeFactory::self()->findFromFileName( fileName );
00295             // Found one glob match exactly: OK, use that.
00296             // We disambiguate multiple glob matches by sniffing, below.
00297             if ( mimeList.count() == 1 ) {
00298                 return mimeList.first();
00299             }
00300         }
00301     }
00302 
00303     if ( device && !device->isOpen() ) {
00304         if ( !device->open(QIODevice::ReadOnly) ) {
00305             device = 0;
00306         }
00307     }
00308 
00309     // Try the magic matches (if we can read the data)
00310     QByteArray beginning;
00311     if ( device ) {
00312         int magicAccuracy;
00313         KMimeType::Ptr mime = KMimeTypeFactory::self()->findFromContent(
00314             device, KMimeTypeFactory::AllRules, &magicAccuracy, beginning );
00315         // mime can't be 0, except in case of install problems.
00316         // However we get magicAccuracy==0 for octet-stream, i.e. no magic match found.
00317         //kDebug(7009) << "findFromContent said" << (mime?mime->name():QString()) << "with accuracy" << magicAccuracy;
00318         if (mime && magicAccuracy > 0) {
00319 
00320             // Disambiguate conflicting extensions (if magic found something and the magicrule was <80)
00321             if (magicAccuracy < 80 && !mimeList.isEmpty()) {
00322                 // "for glob_match in glob_matches:"
00323                 // "if glob_match is subclass or equal to sniffed_type, use glob_match"
00324                 const QString sniffedMime = mime->name();
00325                 foreach(const KMimeType::Ptr &mimeFromPattern, mimeList) {
00326                     //kDebug(7009) << "sniffedMime=" << sniffedMime << "mimeFromPattern=" << mimeFromPattern->name();
00327                     if (mimeFromPattern->is(sniffedMime)) {
00328                         // We have magic + pattern pointing to this, so it's a pretty good match
00329                         if (accuracy)
00330                             *accuracy = 100;
00331                         return mimeFromPattern;
00332                     }
00333                 }
00334             }
00335 
00336             if (accuracy)
00337                 *accuracy = magicAccuracy;
00338             return mime;
00339         }
00340     }
00341 
00342     // Not a local file, or no magic allowed, or magic found nothing
00343 
00344     // Maybe we had multiple matches from globs?
00345     if (!mimeList.isEmpty()) {
00346         if (accuracy)
00347             *accuracy = 20;
00348         // We have to pick one...
00349         return mimeList.first();
00350     }
00351 
00352     // Find a fallback from the protocol
00353     if (accuracy)
00354         *accuracy = 10;
00355     // ## this breaks with proxying; find a way to move proxying info to kdecore's kprotocolinfo?
00356     // ## or hardcode the only case of proxying that we ever had? (ftp-over-http)
00357     KProtocolInfo::Ptr prot = KProtocolInfoFactory::self()->findProtocol( _url.protocol() );
00358     QString def;
00359     if (prot)
00360         def = prot->defaultMimeType();
00361     if ( !def.isEmpty() && def != defaultMimeType() ) {
00362         // The protocol says it always returns a given mimetype (e.g. text/html for "man:")
00363         KMimeType::Ptr mime = mimeType( def );
00364         if (mime)
00365             return mime;
00366     }
00367     if ( path.endsWith( '/' ) || path.isEmpty() ) {
00368         // We have no filename at all. Maybe the protocol has a setting for
00369         // which mimetype this means (e.g. directory).
00370         // For HTTP (def==defaultMimeType()) we don't assume anything,
00371         // because of redirections (e.g. freshmeat downloads).
00372         if ( def.isEmpty() ) {
00373             // Assume inode/directory, if the protocol supports listing.
00374             KProtocolInfo::Ptr prot = KProtocolInfoFactory::self()->findProtocol( _url.protocol() );
00375             if ( prot && prot->supportsListing() ) {
00376                 KMimeType::Ptr mime = mimeType( QLatin1String("inode/directory") );
00377                 if (mime) { // only 0 if no mimetypes installed
00378                     return mime;
00379                 }
00380             } else
00381                 return defaultMimeTypePtr(); // == 'no idea', e.g. for "data:,foo/"
00382         }
00383     }
00384 
00385     if (accuracy)
00386         *accuracy = 0;
00387     return defaultMimeTypePtr();
00388 }
00389 
00390 KMimeType::Ptr KMimeType::findByUrl( const KUrl& url, mode_t mode,
00391                                      bool is_local_file, bool fast_mode,
00392                                      int *accuracy )
00393 {
00394     if ( !is_local_file && url.isLocalFile() )
00395         is_local_file = true;
00396     if (is_local_file && !fast_mode) {
00397         QFile file(url.path());
00398         return findByUrlHelper(url, mode, is_local_file, &file, accuracy);
00399     }
00400     return findByUrlHelper(url, mode, is_local_file, 0, accuracy);
00401 }
00402 
00403 KMimeType::Ptr KMimeType::findByPath( const QString& path, mode_t mode,
00404                                       bool fast_mode, int* accuracy )
00405 {
00406     KUrl url;
00407     url.setPath(path);
00408     return findByUrl(url, mode, true, fast_mode, accuracy);
00409 }
00410 
00411 KMimeType::Ptr KMimeType::findByNameAndContent( const QString& name, const QByteArray& data,
00412                                                 mode_t mode, int* accuracy )
00413 {
00414     KUrl url;
00415     url.setPath(name);
00416     QBuffer buffer(const_cast<QByteArray *>(&data));
00417     return findByUrlHelper(url, mode, false, &buffer, accuracy);
00418 }
00419 
00420 QString KMimeType::extractKnownExtension(const QString &fileName)
00421 {
00422     QString pattern;
00423     KMimeTypeFactory::self()->findFromFileName( fileName, &pattern );
00424     return pattern;
00425 }
00426 
00427 KMimeType::Ptr KMimeType::findByContent( const QByteArray &data, int *accuracy )
00428 {
00429     QBuffer buffer(const_cast<QByteArray *>(&data));
00430     buffer.open(QIODevice::ReadOnly);
00431     QByteArray cache;
00432     return KMimeTypeFactory::self()->findFromContent(
00433         &buffer, KMimeTypeFactory::AllRules, accuracy, cache );
00434 }
00435 
00436 KMimeType::Ptr KMimeType::findByFileContent( const QString &fileName, int *accuracy )
00437 {
00438     checkEssentialMimeTypes();
00439 
00440     QFile device(fileName);
00441     // Look at mode first
00442     KMimeType::Ptr mimeFromMode = findFromMode( fileName, 0, true );
00443     if (mimeFromMode) {
00444         if (accuracy)
00445             *accuracy = 100;
00446         return mimeFromMode;
00447     }
00448     if (!device.open(QIODevice::ReadOnly)) {
00449         if (accuracy)
00450             *accuracy = 0;
00451         return KMimeType::defaultMimeTypePtr();
00452     }
00453 
00454     QByteArray cache;
00455     return KMimeTypeFactory::self()->findFromContent(
00456         &device, KMimeTypeFactory::AllRules, accuracy, cache );
00457 }
00458 
00459 bool KMimeType::isBinaryData( const QString &fileName )
00460 {
00461     QFile file(fileName);
00462     if (!file.open(QIODevice::ReadOnly))
00463         return false; // err, whatever
00464     const QByteArray data = file.read(32);
00465     return isBufferBinaryData(data);
00466 }
00467 
00468 KMimeType::KMimeType( KMimeTypePrivate &dd, const QString& name,
00469                       const QString& comment )
00470     : KServiceType( dd, name, comment )
00471 {
00472 }
00473 
00474 KMimeType::KMimeType( const QString & fullpath, const QString& name,
00475                       const QString& comment )
00476     : KServiceType( *new KMimeTypePrivate(fullpath), name, comment )
00477 {
00478 }
00479 
00480 KMimeType::KMimeType( KMimeTypePrivate &dd)
00481     : KServiceType(dd)
00482 {
00483 }
00484 
00485 KMimeType::KMimeType( QDataStream& _str, int offset )
00486     : KServiceType( *new KMimeTypePrivate(_str, offset ))
00487 {
00488 }
00489 
00490 void KMimeTypePrivate::save( QDataStream& _str )
00491 {
00492     KServiceTypePrivate::save( _str );
00493     // Warning adding/removing fields here involves a binary incompatible change - update version
00494     // number in ksycoca.h
00495     _str << m_lstPatterns << QString() << m_parentMimeTypes;
00496 }
00497 
00498 QVariant KMimeTypePrivate::property( const QString& _name ) const
00499 {
00500     if ( _name == "Patterns" )
00501         return QVariant( m_lstPatterns );
00502     if ( _name == "Icon" )
00503         return QVariant( iconName(KUrl()) );
00504 
00505     return KServiceTypePrivate::property( _name );
00506 }
00507 
00508 QStringList KMimeTypePrivate::propertyNames() const
00509 {
00510     QStringList res = KServiceTypePrivate::propertyNames();
00511     res.append( "Patterns" );
00512     res.append( "Icon" );
00513     return res;
00514 }
00515 
00516 KMimeType::~KMimeType()
00517 {
00518 }
00519 
00520 QString KMimeType::iconNameForUrl( const KUrl & _url, mode_t mode )
00521 {
00522     const KMimeType::Ptr mt = findByUrl( _url, mode, _url.isLocalFile(),
00523                                          false /*HACK*/);
00524     if (!mt) {
00525         return QString();
00526     }
00527     static const QString& unknown = KGlobal::staticQString("unknown");
00528     const QString mimeTypeIcon = mt->iconName( _url );
00529     QString i = mimeTypeIcon;
00530 
00531     // if we don't find an icon, maybe we can use the one for the protocol
00532     if ( i == unknown || i.isEmpty() || mt == defaultMimeTypePtr()
00533         // and for the root of the protocol (e.g. trash:/) the protocol icon has priority over the mimetype icon
00534         || _url.path().length() <= 1 )
00535     {
00536         i = favIconForUrl( _url ); // maybe there is a favicon?
00537 
00538         if ( i.isEmpty() )
00539             i = KProtocolInfo::icon( _url.protocol() );
00540 
00541         // root of protocol: if we found nothing, revert to mimeTypeIcon (which is usually "folder")
00542         if ( _url.path().length() <= 1 && ( i == unknown || i.isEmpty() ) )
00543             i = mimeTypeIcon;
00544     }
00545     return !i.isEmpty() ? i : unknown;
00546 }
00547 
00548 QString KMimeType::favIconForUrl( const KUrl& url )
00549 {
00550     // this method will be called quite often, so better not read the config
00551     // again and again.
00552     static bool useFavIcons = true;
00553     static bool check = true;
00554     if ( check ) {
00555         check = false;
00556         KConfigGroup cg( KGlobal::config(), "HTML Settings" );
00557         useFavIcons = cg.readEntry("EnableFavicon", true);
00558     }
00559 
00560     if ( url.isLocalFile() || !url.protocol().startsWith("http")
00561          || !useFavIcons )
00562         return QString();
00563 
00564     QDBusInterface kded( "org.kde.kded", "/modules/favicons", "org.kde.FavIcon" );
00565     QDBusReply<QString> result = kded.call( "iconForUrl", url.url() );
00566     return result;              // default is QString()
00567 }
00568 
00569 QString KMimeType::comment( const KUrl &url) const
00570 {
00571     Q_D(const KMimeType);
00572     return d->comment(url);
00573 }
00574 
00575 QString KMimeType::parentMimeType() const
00576 {
00577     Q_D(const KMimeType);
00578 
00579     if (!d->m_parentMimeTypes.isEmpty())
00580         return d->m_parentMimeTypes.first();
00581     return d->fallbackParent();
00582 }
00583 
00584 QString KMimeTypePrivate::fallbackParent() const
00585 {
00586     const QString myGroup = m_strName.left(m_strName.indexOf('/'));
00587     // All text/* types are subclasses of text/plain.
00588     if (myGroup == "text" && m_strName != "text/plain")
00589         return "text/plain";
00590     // All real-file mimetypes implicitly derive from application/octet-stream
00591     if (myGroup != "inode" &&
00592         // kde extensions
00593         myGroup != "all" && myGroup != "fonts" && myGroup != "print" && myGroup != "uri"
00594         && m_strName != "application/octet-stream") {
00595         return "application/octet-stream";
00596     }
00597     return QString();
00598 }
00599 
00600 bool KMimeTypePrivate::inherits(KMimeType::Ptr mime) const
00601 {
00602     if (mime && m_strName == mime->d_func()->m_strName) {
00603         return true;
00604     }
00605     foreach( const QString& parent, parentMimeTypes() ) {
00606         KMimeType::Ptr parentMime = KMimeTypeFactory::self()->findMimeTypeByName(parent);
00607         if (!parentMime) // error
00608             return false;
00609         if (parentMime->d_func()->inherits(mime)) // recurse
00610             return true;
00611     }
00612     return false;
00613 }
00614 
00615 bool KMimeType::is( const QString& mimeTypeName ) const
00616 {
00617     Q_D(const KMimeType);
00618     if (name() == mimeTypeName)
00619         return true;
00620     KMimeType::Ptr mime = KMimeTypeFactory::self()->findMimeTypeByName(mimeTypeName, KMimeType::ResolveAliases);
00621     return d->inherits(mime);
00622 }
00623 
00624 QStringList KMimeType::parentMimeTypes() const
00625 {
00626     Q_D(const KMimeType);
00627     return d->parentMimeTypes();
00628 }
00629 
00630 QStringList KMimeTypePrivate::parentMimeTypes() const
00631 {
00632     QStringList parents = m_parentMimeTypes;
00633     if (parents.isEmpty()) {
00634         const QString myParent = fallbackParent();
00635         if (!myParent.isEmpty())
00636             parents.append(myParent);
00637     }
00638     return parents;
00639 }
00640 
00641 void KMimeTypePrivate::collectParentMimeTypes(QStringList& allParents) const
00642 {
00643     QStringList parents = parentMimeTypes();
00644     Q_FOREACH(const QString& parent, parents) {
00645         // I would use QSet, but since order matters I better not
00646         if (!allParents.contains(parent))
00647             allParents.append(parent);
00648     }
00649     // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
00650     // This means iterating twice, unfortunately.
00651     Q_FOREACH(const QString& parent, parents) {
00652         KMimeType::Ptr parentMime = KMimeTypeFactory::self()->findMimeTypeByName(parent);
00653         if (parentMime)
00654             parentMime->d_func()->collectParentMimeTypes(allParents);
00655     }
00656 }
00657 
00658 QStringList KMimeType::allParentMimeTypes() const
00659 {
00660     QStringList allParents;
00661     const QString canonical = KMimeTypeFactory::self()->resolveAlias(name());
00662     if (!canonical.isEmpty())
00663         allParents.append(canonical);
00664     d_func()->collectParentMimeTypes(allParents);
00665     return allParents;
00666 }
00667 
00668 QString KMimeType::defaultMimeType()
00669 {
00670     static const QString & s_strDefaultMimeType =
00671         KGlobal::staticQString( "application/octet-stream" );
00672     return s_strDefaultMimeType;
00673 }
00674 
00675 QString KMimeType::iconName( const KUrl& url) const
00676 {
00677     Q_D(const KMimeType);
00678     return d->iconName(url);
00679 }
00680 
00681 QStringList KMimeType::patterns() const
00682 {
00683     Q_D(const KMimeType);
00684     return d->m_lstPatterns;
00685 }
00686 
00687 void KMimeType::setPatterns(const QStringList& patterns)
00688 {
00689     Q_D(KMimeType);
00690     d->m_lstPatterns = patterns;
00691 }
00692 
00693 void KMimeType::setParentMimeType(const QString& parent)
00694 {
00695     Q_D(KMimeType);
00696     // kbuildmimetypefactory calls this multiple times, for each parent mimetype
00697     d->m_parentMimeTypes.append(parent);
00698 }
00699 
00700 void KMimeType::internalClearData()
00701 {
00702     Q_D(KMimeType);
00703     // Clear the data that KBuildMimeTypeFactory is going to refill - and only that data.
00704     d->m_parentMimeTypes.clear();
00705     d->m_lstPatterns.clear();
00706 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal