KDED
kmimeassociations.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 * Copyright 2008 David Faure <faure@kde.org> 00003 * 00004 * This library is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License or ( at 00007 * your option ) version 3 or, at the discretion of KDE e.V. ( which shall 00008 * act as a proxy as in section 14 of the GPLv3 ), any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kmimeassociations.h" 00022 #include <kmimetype.h> 00023 #include <kmimetyperepository_p.h> 00024 #include <kservice.h> 00025 #include <kconfiggroup.h> 00026 #include <kconfig.h> 00027 #include <kdebug.h> 00028 #include <kglobal.h> 00029 #include <kstandarddirs.h> 00030 00031 KMimeAssociations::KMimeAssociations(KOfferHash& offerHash) 00032 : m_offerHash(offerHash) 00033 { 00034 } 00035 00036 /* 00037 00038 The goal of this class is to parse mimeapps.list files, which are used to 00039 let users configure the application-mimetype associations. 00040 00041 Example file: 00042 00043 [Added Associations] 00044 text/plain=kate.desktop; 00045 00046 [Removed Associations] 00047 text/plain=gnome-gedit.desktop;gnu-emacs.desktop; 00048 00049 00050 00051 */ 00052 00053 bool KMimeAssociations::parseAllMimeAppsList() 00054 { 00055 // Using the "merged view" from KConfig is not enough since we -add- at every level, we don't replace. 00056 const QStringList mimeappsFiles = KGlobal::dirs()->findAllResources("xdgdata-apps", "mimeapps.list"); 00057 if (mimeappsFiles.isEmpty()) 00058 return false; 00059 00060 int basePreference = 1000; // start high :) 00061 QListIterator<QString> mimeappsIter( mimeappsFiles ); 00062 mimeappsIter.toBack(); 00063 while (mimeappsIter.hasPrevious()) { // global first, then local. 00064 const QString mimeappsFile = mimeappsIter.previous(); 00065 kDebug(7021) << "Parsing" << mimeappsFile; 00066 parseMimeAppsList(mimeappsFile, basePreference); 00067 basePreference += 50; 00068 } 00069 return true; 00070 } 00071 00072 void KMimeAssociations::parseMimeAppsList(const QString& file, int basePreference) 00073 { 00074 KConfig profile(file, KConfig::SimpleConfig); 00075 parseAddedAssociations(KConfigGroup(&profile, "Added Associations"), file, basePreference); 00076 parseRemovedAssociations(KConfigGroup(&profile, "Removed Associations"), file); 00077 00078 // KDE extension for parts and plugins, see settings/filetypes/mimetypedata.cpp 00079 parseAddedAssociations(KConfigGroup(&profile, "Added KDE Service Associations"), file, basePreference); 00080 parseRemovedAssociations(KConfigGroup(&profile, "Removed KDE Service Associations"), file); 00081 } 00082 00083 void KMimeAssociations::parseAddedAssociations(const KConfigGroup& group, const QString& file, int basePreference) 00084 { 00085 Q_FOREACH(const QString& mimeName, group.keyList()) { 00086 const QStringList services = group.readXdgListEntry(mimeName); 00087 const QString resolvedMimeName = KMimeTypeRepository::self()->canonicalName(mimeName); 00088 int pref = basePreference; 00089 Q_FOREACH(const QString &service, services) { 00090 KService::Ptr pService = KService::serviceByStorageId(service); 00091 if (!pService) { 00092 kDebug(7021) << file << "specifies unknown service" << service << "in" << group.name(); 00093 } else { 00094 //kDebug(7021) << "adding mime" << resolvedMimeName << "to service" << pService->entryPath() << "pref=" << pref; 00095 m_offerHash.addServiceOffer(resolvedMimeName, KServiceOffer(pService, pref, 0, pService->allowAsDefault())); 00096 --pref; 00097 } 00098 } 00099 } 00100 } 00101 00102 void KMimeAssociations::parseRemovedAssociations(const KConfigGroup& group, const QString& file) 00103 { 00104 Q_FOREACH(const QString& mime, group.keyList()) { 00105 const QStringList services = group.readXdgListEntry(mime); 00106 Q_FOREACH(const QString& service, services) { 00107 KService::Ptr pService = KService::serviceByStorageId(service); 00108 if (!pService) { 00109 kDebug(7021) << file << "specifies unknown service" << service << "in" << group.name(); 00110 } else { 00111 //kDebug(7021) << "removing mime" << mime << "from service" << pService.data() << pService->entryPath(); 00112 m_offerHash.removeServiceOffer(mime, pService); 00113 } 00114 } 00115 } 00116 } 00117 00118 void KOfferHash::addServiceOffer(const QString& serviceType, const KServiceOffer& offer) 00119 { 00120 KService::Ptr service = offer.service(); 00121 //kDebug(7021) << "Adding" << service->entryPath() << "to" << serviceType << offer.preference(); 00122 ServiceTypeOffersData& data = m_serviceTypeData[serviceType]; // find or create 00123 QList<KServiceOffer>& offers = data.offers; 00124 QSet<KService::Ptr>& offerSet = data.offerSet; 00125 if ( !offerSet.contains( service ) ) { 00126 offers.append( offer ); 00127 offerSet.insert( service ); 00128 } else { 00129 //kDebug(7021) << service->entryPath() << "already in" << serviceType; 00130 // This happens when mimeapps.list mentions a service (to make it preferred) 00131 // Update initialPreference to qMax(existing offer, new offer) 00132 QMutableListIterator<KServiceOffer> sfit(data.offers); 00133 while (sfit.hasNext()) { 00134 if (sfit.next().service() == service) // we can compare KService::Ptrs because they are from the memory hash 00135 sfit.value().setPreference( qMax(sfit.value().preference(), offer.preference()) ); 00136 } 00137 } 00138 } 00139 00140 void KOfferHash::removeServiceOffer(const QString& serviceType, KService::Ptr service) 00141 { 00142 ServiceTypeOffersData& data = m_serviceTypeData[serviceType]; // find or create 00143 data.removedOffers.insert(service); 00144 data.offerSet.remove(service); 00145 QMutableListIterator<KServiceOffer> sfit(data.offers); 00146 while (sfit.hasNext()) { 00147 if (sfit.next().service()->storageId() == service->storageId()) 00148 sfit.remove(); 00149 } 00150 } 00151 00152 bool KOfferHash::hasRemovedOffer(const QString& serviceType, KService::Ptr service) const 00153 { 00154 QHash<QString, ServiceTypeOffersData>::const_iterator it = m_serviceTypeData.find(serviceType); 00155 if (it != m_serviceTypeData.end()) { 00156 return (*it).removedOffers.contains(service); 00157 } 00158 return false; 00159 }
KDE 4.6 API Reference