File patch-r901205.diff of Package kdelibs4

Subject: fix File Associations settings are not saved
From: wstephenson@suse.de
Bug: kde#164584,kde#178560
Patch-upstream: 901205
--- kded/kded.cpp	(revision 901204)
+++ kded/kded.cpp	(revision 901205)
@@ -190,7 +190,7 @@ void Kded::initModules()
     if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
         kde_running = false;
      // Preload kded modules.
-     KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
+     const KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
      {
          KService::Ptr service = *it;
@@ -234,7 +234,7 @@ void Kded::loadSecondPhase()
      kDebug(7020) << "Loading second phase autoload";
      KSharedConfig::Ptr config = KGlobal::config();
      KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
-     for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
+     for(KService::List::ConstIterator it = kdedModules.constBegin(); it != kdedModules.constEnd(); ++it)
      {
          KService::Ptr service = *it;
          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
@@ -386,8 +386,8 @@ void Kded::updateDirWatch()
            this, SLOT(dirDeleted(const QString&)));
 
   // For each resource
-  for( QStringList::ConstIterator it = m_allResourceDirs.begin();
-       it != m_allResourceDirs.end();
+  for( QStringList::ConstIterator it = m_allResourceDirs.constBegin();
+       it != m_allResourceDirs.constEnd();
        ++it )
   {
      readDirectory( *it );
@@ -609,7 +609,7 @@ KUpdateD::KUpdateD()
     QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
            this, SLOT(slotNewUpdateFile()));
 
-    QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
+    const QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
     for( QStringList::ConstIterator it = dirs.begin();
          it != dirs.end();
          ++it )
--- kded/kbuildsycoca.cpp	(revision 901204)
+++ kded/kbuildsycoca.cpp	(revision 901205)
@@ -222,8 +222,8 @@ bool KBuildSycoca::build()
     const KSycocaResourceList *list = (*factory)->resourceList();
     if (!list) continue;
 
-    for( KSycocaResourceList::ConstIterator it1 = list->begin();
-         it1 != list->end();
+    for( KSycocaResourceList::ConstIterator it1 = list->constBegin();
+         it1 != list->constEnd();
          ++it1 )
     {
       KSycocaResource res = (*it1);
@@ -235,8 +235,8 @@ bool KBuildSycoca::build()
   g_ctimeInfo = new KCTimeInfo(); // This is a build factory too, don't delete!!
   bool uptodate = true;
   // For all resources
-  for( QStringList::ConstIterator it1 = allResources.begin();
-       it1 != allResources.end();
+  for( QStringList::ConstIterator it1 = allResources.constBegin();
+       it1 != allResources.constEnd();
        ++it1 )
   {
      g_changed = false;
@@ -255,8 +255,8 @@ bool KBuildSycoca::build()
      // For each factory
      KBSEntryDictList::const_iterator ed_it = entryDictList.begin();
      const KBSEntryDictList::const_iterator ed_end = entryDictList.end();
-     KSycocaFactoryList::const_iterator it = factories()->begin();
-     const KSycocaFactoryList::const_iterator end = factories()->end();
+     KSycocaFactoryList::const_iterator it = factories()->constBegin();
+     const KSycocaFactoryList::const_iterator end = factories()->constEnd();
      for ( ; it != end; ++it, ++ed_it )
      {
         g_factory = (*it);
@@ -266,16 +266,16 @@ bool KBuildSycoca::build()
         const KSycocaResourceList *list = g_factory->resourceList();
         if (!list) continue;
 
-        for( KSycocaResourceList::ConstIterator it2 = list->begin();
-             it2 != list->end();
+        for( KSycocaResourceList::ConstIterator it2 = list->constBegin();
+             it2 != list->constEnd();
              ++it2 )
         {
            KSycocaResource res = (*it2);
            if (res.resource != (*it1)) continue;
 
            // For each file in the resource
-           for( QStringList::ConstIterator it3 = relFiles.begin();
-                it3 != relFiles.end();
+           for( QStringList::ConstIterator it3 = relFiles.constBegin();
+                it3 != relFiles.constEnd();
                 ++it3 )
            {
                // Check if file matches filter
--- kded/kbuildmimetypefactory.cpp	(revision 901204)
+++ kded/kbuildmimetypefactory.cpp	(revision 901205)
@@ -60,8 +60,8 @@ KMimeType::Ptr KBuildMimeTypeFactory::fi
 
     QString name = _name;
     if (options & KMimeType::ResolveAliases) {
-        QMap<QString, QString>::const_iterator it = aliases().find(_name);
-        if (it != aliases().end())
+        QMap<QString, QString>::const_iterator it = aliases().constFind(_name);
+        if (it != aliases().constEnd())
             name = *it;
     }
 
--- kded/kbuildservicefactory.cpp	(revision 901204)
+++ kded/kbuildservicefactory.cpp	(revision 901205)
@@ -23,7 +23,6 @@
 #include "ksycoca.h"
 #include "ksycocadict.h"
 #include "kresourcelist.h"
-#include "kmimetype.h"
 #include "kdesktopfile.h"
 
 #include <kglobal.h>
@@ -139,41 +138,59 @@ void KBuildServiceFactory::save(QDataStr
 
 void KBuildServiceFactory::collectInheritedServices()
 {
-    // With multiple inheritance, the "mimeTypeInheritanceLevel" isn't exactly
-    // correct (it should only be increased when going up a level, not when iterating
-    // through the multiple parents at a given level). I don't think we care,
-    // but just in case we do, this is the reason I didn't port this to mimeType->allParentMimeTypes.
+    // For each mimetype, go up the parent-mimetype chains and collect offers.
+    // For "removed associations" to work, we can't just grab everything from all parents.
+    // We need to process parents before children, hence the recursive call in
+    // collectInheritedServices(mime) and the QSet to process a given parent only once.
+    QSet<KMimeType::Ptr> visitedMimes;
     const KMimeType::List allMimeTypes = m_mimeTypeFactory->allMimeTypes();
     KMimeType::List::const_iterator itm = allMimeTypes.begin();
     for( ; itm != allMimeTypes.end(); ++itm ) {
         const KMimeType::Ptr mimeType = *itm;
-        const QString mimeTypeName = mimeType->name();
-        QStringList parents = mimeType->parentMimeTypes();
-        int mimeTypeInheritanceLevel = 0;
-        while ( !parents.isEmpty() ) {
-            const QString& parent = parents.takeFirst();
-            const KMimeType::Ptr parentMimeType = m_mimeTypeFactory->findMimeTypeByName( parent );
-            if ( parentMimeType ) {
-                ++mimeTypeInheritanceLevel;
-                const QList<KServiceOffer>& offers = m_offerHash.offersFor(parent);
-                QList<KServiceOffer>::const_iterator itserv = offers.begin();
-                const QList<KServiceOffer>::const_iterator endserv = offers.end();
-                for ( ; itserv != endserv; ++itserv ) {
+        collectInheritedServices(mimeType, visitedMimes);
+    }
+    // TODO do the same for all/all and all/allfiles, if (!KServiceTypeProfile::configurationMode())
+}
+
+void KBuildServiceFactory::collectInheritedServices(KMimeType::Ptr mimeType, QSet<KMimeType::Ptr>& visitedMimes)
+{
+    if (visitedMimes.contains(mimeType))
+        return;
+    visitedMimes.insert(mimeType);
+
+    // With multiple inheritance, the "mimeTypeInheritanceLevel" isn't exactly
+    // correct (it should only be increased when going up a level, not when iterating
+    // through the multiple parents at a given level). I don't think we care, though.
+    int mimeTypeInheritanceLevel = 0;
+
+    const QString mimeTypeName = mimeType->name();
+    Q_FOREACH(const QString& parent, mimeType->parentMimeTypes()) {
+        const KMimeType::Ptr parentMimeType =
+            m_mimeTypeFactory->findMimeTypeByName(parent, KMimeType::ResolveAliases);
+
+        if ( parentMimeType ) {
+            collectInheritedServices(parentMimeType, visitedMimes);
+
+            ++mimeTypeInheritanceLevel;
+            const QList<KServiceOffer>& offers = m_offerHash.offersFor(parent);
+            QList<KServiceOffer>::const_iterator itserv = offers.begin();
+            const QList<KServiceOffer>::const_iterator endserv = offers.end();
+            for ( ; itserv != endserv; ++itserv ) {
+                if (!m_offerHash.hasRemovedOffer(mimeTypeName, (*itserv).service())) {
                     KServiceOffer offer(*itserv);
                     offer.setMimeTypeInheritanceLevel(mimeTypeInheritanceLevel);
                     //kDebug(7021) << "INHERITANCE: Adding service" << (*itserv).service()->entryPath() << "to" << mimeTypeName << "mimeTypeInheritanceLevel=" << mimeTypeInheritanceLevel;
                     m_offerHash.addServiceOffer( mimeTypeName, offer );
                 }
-                parents += parentMimeType->parentMimeTypes();
-            } else {
-                kWarning(7012) << "parent mimetype not found:" << parent;
-                break;
             }
+        } else {
+            kWarning(7012) << "parent mimetype not found:" << parent;
+            break;
         }
     }
-    // TODO do the same for all/all and all/allfiles, if (!KServiceTypeProfile::configurationMode())
 }
 
+
 void KBuildServiceFactory::populateServiceTypes()
 {
     // For every service...
@@ -235,8 +252,8 @@ void KBuildServiceFactory::populateServi
     int offersOffset = 0;
     const int offerEntrySize = sizeof( qint32 ) * 4; // four qint32s, see saveOfferList.
 
-    KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->begin();
-    const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->end();
+    KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->constBegin();
+    const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->constEnd();
     for( ; itstf != endstf; ++itstf ) {
         KServiceType::Ptr entry = KServiceType::Ptr::staticCast( *itstf );
         const int numOffers = m_offerHash.offersFor(entry->name()).count();
@@ -245,8 +262,8 @@ void KBuildServiceFactory::populateServi
             offersOffset += offerEntrySize * numOffers;
         }
     }
-    KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->begin();
-    const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->end();
+    KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->constBegin();
+    const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->constEnd();
     for( ; itmtf != endmtf; ++itmtf )
     {
         KMimeType::Ptr entry = KMimeType::Ptr::staticCast( *itmtf );
@@ -263,8 +280,8 @@ void KBuildServiceFactory::saveOfferList
     m_offerListOffset = str.device()->pos();
 
     // For each entry in servicetypeFactory
-    KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->begin();
-    const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->end();
+    KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->constBegin();
+    const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->constEnd();
     for( ; itstf != endstf; ++itstf ) {
         // export associated services
         const KServiceType::Ptr entry = KServiceType::Ptr::staticCast( *itstf );
@@ -273,8 +290,8 @@ void KBuildServiceFactory::saveOfferList
         QList<KServiceOffer> offers = m_offerHash.offersFor(entry->name());
         qStableSort( offers ); // by initial preference
 
-        for(QList<KServiceOffer>::const_iterator it2 = offers.begin();
-            it2 != offers.end(); ++it2) {
+        for(QList<KServiceOffer>::const_iterator it2 = offers.constBegin();
+            it2 != offers.constEnd(); ++it2) {
             //kDebug(7021) << "servicetype offers list:" << entry->name() << "->" << (*it2).service()->entryPath();
 
             str << (qint32) entry->offset();
@@ -286,8 +303,8 @@ void KBuildServiceFactory::saveOfferList
     }
 
     // For each entry in mimeTypeFactory
-    KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->begin();
-    const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->end();
+    KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->constBegin();
+    const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->constEnd();
     for( ; itmtf != endmtf; ++itmtf ) {
         // export associated services
         const KMimeType::Ptr entry = KMimeType::Ptr::staticCast( *itmtf );
@@ -295,8 +312,8 @@ void KBuildServiceFactory::saveOfferList
         QList<KServiceOffer> offers = m_offerHash.offersFor(entry->name());
         qStableSort( offers ); // by initial preference
 
-        for(QList<KServiceOffer>::const_iterator it2 = offers.begin();
-            it2 != offers.end(); ++it2) {
+        for(QList<KServiceOffer>::const_iterator it2 = offers.constBegin();
+            it2 != offers.constEnd(); ++it2) {
             //kDebug(7021) << "mimetype offers list:" << entry->name() << "->" << (*it2).service()->entryPath() << "pref" << (*it2).preference();
             Q_ASSERT((*it2).service()->offset() != 0);
             str << (qint32) entry->offset();
--- kded/kbuildservicetypefactory.cpp	(revision 901204)
+++ kded/kbuildservicetypefactory.cpp	(revision 901205)
@@ -109,7 +109,7 @@ KBuildServiceTypeFactory::saveHeader(QDa
 {
     KSycocaFactory::saveHeader(str);
     str << (qint32) m_propertyTypeDict.count();
-    for (QMap<QString, int>::ConstIterator it = m_propertyTypeDict.begin(); it != m_propertyTypeDict.end(); ++it) {
+    for (QMap<QString, int>::ConstIterator it = m_propertyTypeDict.constBegin(); it != m_propertyTypeDict.constEnd(); ++it) {
         str << it.key() << (qint32)it.value();
     }
 }
--- kded/kmimeassociations.h	(revision 901204)
+++ kded/kmimeassociations.h	(revision 901205)
@@ -30,6 +30,7 @@ class KConfigGroup;
 struct ServiceTypeOffersData {
     QList<KServiceOffer> offers; // service + initial preference + allow as default
     QSet<KService::Ptr> offerSet; // for quick contains() check
+    QSet<KService::Ptr> removedOffers; // remember removed offers explicitely
 };
 
 class KOfferHash
@@ -44,6 +45,7 @@ public:
     }
     void addServiceOffer(const QString& serviceType, const KServiceOffer& offer);
     void removeServiceOffer(const QString& serviceType, KService::Ptr service);
+    bool hasRemovedOffer(const QString& serviceType, KService::Ptr service) const;
 
 private:
     KOfferHash(const KOfferHash&); // forbidden
--- kded/test/kmimeassociationstest.cpp	(revision 901204)
+++ kded/test/kmimeassociationstest.cpp	(revision 901205)
@@ -84,14 +84,14 @@ static bool offerListHasService( const K
     return found;
 }
 
-static void writeAppDesktopFile(const QString& path, const char* mimetype)
+static void writeAppDesktopFile(const QString& path, const QStringList& mimeTypes)
 {
     KDesktopFile file(path);
     KConfigGroup group = file.desktopGroup();
     group.writeEntry("Name", "FakeApplication");
     group.writeEntry("Type", "Application");
     group.writeEntry("Exec", "ls");
-    group.writeEntry("MimeType", QString(mimetype) + ';');
+    group.writeXdgListEntry("MimeType", mimeTypes);
 }
 
 /**
@@ -125,15 +125,22 @@ private Q_SLOTS:
         fakeTextApplication = m_localApps + "faketextapplication.desktop";
         if (!QFile::exists(fakeTextApplication)) {
             mustUpdateKSycoca = true;
-            writeAppDesktopFile(fakeTextApplication, "text/plain");
+            writeAppDesktopFile(fakeTextApplication, QStringList() << "text/plain");
         }
 
         fakeJpegApplication = m_localApps + "fakejpegapplication.desktop";
         if (!QFile::exists(fakeJpegApplication)) {
             mustUpdateKSycoca = true;
-            writeAppDesktopFile(fakeJpegApplication, "image/jpeg");
+            writeAppDesktopFile(fakeJpegApplication, QStringList() << "image/jpeg");
         }
 
+        fakeArkApplication = m_localApps + "fakearkapplication.desktop";
+        if (!QFile::exists(fakeArkApplication)) {
+            mustUpdateKSycoca = true;
+            writeAppDesktopFile(fakeArkApplication, QStringList() << "application/zip");
+        }
+
+
         if ( mustUpdateKSycoca ) {
             // Update ksycoca in ~/.kde-unit-test after creating the above
             runKBuildSycoca();
@@ -299,7 +306,7 @@ private Q_SLOTS:
         QVERIFY(offerListHasService(offers, fakeTextApplication, true));
     }
 
-    void testRemovedAssociation()
+    void testRemoveAssociationFromParent()
     {
         // I removed kate from text/plain, and it would still appear in text/x-java.
 
@@ -317,6 +324,61 @@ private Q_SLOTS:
         QVERIFY(!offerListHasService(offers, fakeTextApplication, false));
     }
 
+    void testRemovedImplicitAssociation() // remove (implicit) assoc from derived mimetype
+    {
+        // #164584: Removing ark from opendocument.text didn't work
+        const QString opendocument = "application/vnd.oasis.opendocument.text";
+        KService::List offers = KMimeTypeTrader::self()->query(opendocument);
+        QVERIFY(offerListHasService(offers, fakeArkApplication, true));
+
+        writeToMimeApps(QByteArray("[Removed Associations]\n"
+                                   "application/vnd.oasis.opendocument.text=fakearkapplication.desktop;\n"));
+
+        offers = KMimeTypeTrader::self()->query(opendocument);
+        QVERIFY(!offerListHasService(offers, fakeArkApplication, false));
+
+        offers = KMimeTypeTrader::self()->query("application/zip");
+        QVERIFY(offerListHasService(offers, fakeArkApplication, true));
+    }
+
+    void testRemovedImplicitAssociation178560()
+    {
+        // #178560: Removing ark from interface/x-winamp-skin didn't work
+        const QString mime = "interface/x-winamp-skin";
+        KService::List offers = KMimeTypeTrader::self()->query(mime);
+        QVERIFY(offerListHasService(offers, fakeArkApplication, true));
+
+        writeToMimeApps(QByteArray("[Removed Associations]\n"
+                                   "interface/x-winamp-skin=fakearkapplication.desktop;\n"));
+
+        offers = KMimeTypeTrader::self()->query(mime);
+        QVERIFY(!offerListHasService(offers, fakeArkApplication, false));
+
+        offers = KMimeTypeTrader::self()->query("application/zip");
+        QVERIFY(offerListHasService(offers, fakeArkApplication, true));
+    }
+
+    // remove assoc from a mime which is both a parent and a derived mimetype
+    void testRemovedMiddleAssociation()
+    {
+        // More tricky: x-theme inherits x-desktop inherits text/plain,
+        // if we remove an association for x-desktop then x-theme shouldn't
+        // get it from text/plain...
+
+        KService::List offers;
+        writeToMimeApps(QByteArray("[Removed Associations]\n"
+                                   "application/x-desktop=faketextapplication.desktop;\n"));
+
+        offers = KMimeTypeTrader::self()->query("text/plain");
+        QVERIFY(offerListHasService(offers, fakeTextApplication, true));
+
+        offers = KMimeTypeTrader::self()->query("application/x-desktop");
+        QVERIFY(!offerListHasService(offers, fakeTextApplication, false));
+
+        offers = KMimeTypeTrader::self()->query("application/x-theme");
+        QVERIFY(!offerListHasService(offers, fakeTextApplication, false));
+    }
+
 private:
     typedef QMap<QString /*mimetype*/, QStringList> ExpectedResultsMap;
 
@@ -387,6 +449,7 @@ private:
     QByteArray m_mimeAppsFileContents;
     QString fakeTextApplication;
     QString fakeJpegApplication;
+    QString fakeArkApplication;
 
     ExpectedResultsMap preferredApps;
     ExpectedResultsMap removedApps;
--- kded/kctimefactory.cpp	(revision 901204)
+++ kded/kctimefactory.cpp	(revision 901205)
@@ -53,8 +53,8 @@ KCTimeInfo::save(QDataStream &str)
   KSycocaFactory::save(str);
 
   m_dictOffset = str.device()->pos();
-  Dict::const_iterator it = ctimeDict.begin();
-  const Dict::const_iterator end = ctimeDict.end();
+  Dict::const_iterator it = ctimeDict.constBegin();
+  const Dict::const_iterator end = ctimeDict.constEnd();
   for ( ; it != end; ++it )
   {
      str << it.key() << it.value();
--- kded/kmimeassociations.cpp	(revision 901204)
+++ kded/kmimeassociations.cpp	(revision 901205)
@@ -105,7 +105,7 @@ void KMimeAssociations::parseRemovedAsso
             if (!pService) {
                 kDebug(7021) << file << "specifies unknown service" << service << "in" << group.name();
             } else {
-                //kDebug(7021) << "removing mime" << mime << "from service" << service;
+                //kDebug(7021) << "removing mime" << mime << "from service" << pService.data() << pService->entryPath();
                 m_offerHash.removeServiceOffer(mime, pService);
             }
         }
@@ -123,7 +123,7 @@ void KOfferHash::addServiceOffer(const Q
         offers.append( offer );
         offerSet.insert( service );
     } else {
-        // kDebug(7021) << service.offers() << service->entryPath() << "already in" << serviceType;
+        //kDebug(7021) << service->entryPath() << "already in" << serviceType;
         // This happens when mimeapps.list mentions a service (to make it preferred)
         // Update initialPreference to qMax(existing offer, new offer)
         QMutableListIterator<KServiceOffer> sfit(data.offers);
@@ -136,14 +136,21 @@ void KOfferHash::addServiceOffer(const Q
 
 void KOfferHash::removeServiceOffer(const QString& serviceType, KService::Ptr service)
 {
-    QHash<QString, ServiceTypeOffersData>::iterator it = m_serviceTypeData.find(serviceType);
+    ServiceTypeOffersData& data = m_serviceTypeData[serviceType]; // find or create
+    data.removedOffers.insert(service);
+    data.offerSet.remove(service);
+    QMutableListIterator<KServiceOffer> sfit(data.offers);
+    while (sfit.hasNext()) {
+        if (sfit.next().service()->storageId() == service->storageId())
+            sfit.remove();
+    }
+}
+
+bool KOfferHash::hasRemovedOffer(const QString& serviceType, KService::Ptr service) const
+{
+    QHash<QString, ServiceTypeOffersData>::const_iterator it = m_serviceTypeData.find(serviceType);
     if (it != m_serviceTypeData.end()) {
-        ServiceTypeOffersData& data = *it;
-        data.offerSet.remove(service);
-        QMutableListIterator<KServiceOffer> sfit(data.offers);
-        while (sfit.hasNext()) {
-            if (sfit.next().service()->storageId() == service->storageId())
-                sfit.remove();
-        }
+        return (*it).removedOffers.contains(service);
     }
+    return false;
 }
--- kded/vfolder_menu.cpp	(revision 901204)
+++ kded/vfolder_menu.cpp	(revision 901205)
@@ -323,8 +323,8 @@ VFolderMenu::~VFolderMenu()
    foreach (appsInfo *info, m_appsInfoStack) \
    { \
       KService::List *list = info->dictCategories[category]; \
-      if (list) for(KService::List::ConstIterator it = list->begin(); \
-             it != list->end(); ++it) \
+      if (list) for(KService::List::ConstIterator it = list->constBegin(); \
+             it != list->constEnd(); ++it) \
       {
 #define FOR_CATEGORY_END } }
 
@@ -366,7 +366,7 @@ VFolderMenu::buildApplicationIndex(bool
             continue;
          }
 
-         QStringList cats = s->categories();
+         const QStringList cats = s->categories();
          for(QStringList::ConstIterator it2 = cats.begin();
              it2 != cats.end(); ++it2)
          {
@@ -637,7 +637,7 @@ VFolderMenu::mergeMenus(QDomElement &doc
       else if( e.tagName() == "MergeDir") {
          QString dir = absoluteDir(e.text(), e.attribute("__BaseDir"), true);
 
-         QStringList dirs = KGlobal::dirs()->findDirs("xdgconf-menu", dir);
+         const QStringList dirs = KGlobal::dirs()->findDirs("xdgconf-menu", dir);
          for(QStringList::ConstIterator it=dirs.begin();
              it != dirs.end(); ++it)
          {
@@ -657,8 +657,8 @@ VFolderMenu::mergeMenus(QDomElement &doc
                                                      KStandardDirs::NoDuplicates, fileList);
          }
 
-         for(QStringList::ConstIterator it=fileList.begin();
-             it != fileList.end(); ++it)
+         for(QStringList::ConstIterator it=fileList.constBegin();
+             it != fileList.constEnd(); ++it)
          {
             pushDocInfo(*it);
             mergeFile(docElem, n);
@@ -807,12 +807,11 @@ VFolderMenu::locateDirectoryFile(const Q
    }
 
    // First location in the list wins
-   QString tmp;
-   for(QStringList::ConstIterator it = m_directoryDirs.begin();
-       it != m_directoryDirs.end();
+   for(QStringList::ConstIterator it = m_directoryDirs.constBegin();
+       it != m_directoryDirs.constEnd();
        ++it)
    {
-      tmp = (*it)+fileName;
+      QString tmp = (*it)+fileName;
       if (KStandardDirs::exists(tmp))
          return tmp;
    }
@@ -1044,8 +1043,8 @@ kDebug(7021) << "processKDELegacyDirs()"
                                              KStandardDirs::Recursive |
                                              KStandardDirs::NoDuplicates,
                                              relFiles);
-   for(QStringList::ConstIterator it = relFiles.begin();
-       it != relFiles.end(); ++it)
+   for(QStringList::ConstIterator it = relFiles.constBegin();
+       it != relFiles.constEnd(); ++it)
    {
       if (!m_forcedLegacyLoad && (*it).endsWith(".directory"))
       {
@@ -1638,7 +1637,7 @@ VFolderMenu::parseMenu(const QString &fi
    m_legacyLoaded = false;
    m_appsInfo = 0;
 
-   QStringList dirs = KGlobal::dirs()->resourceDirs("xdgconf-menu");
+   const QStringList dirs = KGlobal::dirs()->resourceDirs("xdgconf-menu");
    for(QStringList::ConstIterator it=dirs.begin();
        it != dirs.end(); ++it)
    {
--- kded/kbuildservicefactory.h	(revision 901204)
+++ kded/kbuildservicefactory.h	(revision 901205)
@@ -24,6 +24,7 @@
 #include <QtCore/QStringList>
 
 #include "kmimeassociations.h"
+#include <kmimetype.h>
 #include <kservicefactory.h>
 // We export the services to the service group factory!
 class KBuildServiceGroupFactory;
@@ -87,6 +88,7 @@ public:
 private:
     void saveOfferList(QDataStream &str);
     void collectInheritedServices();
+    void collectInheritedServices(KMimeType::Ptr mime, QSet<KMimeType::Ptr>& visitedMimes);
 
     QHash<QString, KService::Ptr> m_nameMemoryHash; // m_nameDict is not useable while building ksycoca
     QHash<QString, KService::Ptr> m_relNameMemoryHash; // m_relNameDict is not useable while building ksycoca
Index: kded/kded.cpp
===================================================================
Index: kded/kbuildsycoca.cpp
===================================================================
Index: kded/kbuildmimetypefactory.cpp
===================================================================
Index: kded/kbuildservicefactory.cpp
===================================================================
Index: kded/kbuildservicetypefactory.cpp
===================================================================
Index: kded/kmimeassociations.h
===================================================================
Index: kded/test/kmimeassociationstest.cpp
===================================================================
Index: kded/kctimefactory.cpp
===================================================================
Index: kded/kmimeassociations.cpp
===================================================================
Index: kded/vfolder_menu.cpp
===================================================================
Index: kded/kbuildservicefactory.h
===================================================================
openSUSE Build Service is sponsored by