1 /* This file is part of the KDE libraries
2 * Copyright 2008 David Faure <faure@kde.org>
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2 of the License or ( at
7 * your option ) version 3 or, at the discretion of KDE e.V. ( which shall
8 * act as a proxy as in section 14 of the GPLv3 ), any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
21 #include "kmimeassociations.h"
23 #include <kconfiggroup.h>
27 #include <kstandarddirs.h>
29 KMimeAssociations::KMimeAssociations(KOfferHash
& offerHash
)
30 : m_offerHash(offerHash
)
36 The goal of this class is to parse mimeapps.list files, which are used to
37 let users configure the application-mimetype associations.
42 text/plain=kate.desktop;
44 [Removed Associations]
45 text/plain=gnome-gedit.desktop;gnu-emacs.desktop;
51 bool KMimeAssociations::parseAllMimeAppsList()
53 // Using the "merged view" from KConfig is not enough since we -add- at every level, we don't replace.
54 const QStringList mimeappsFiles
= KGlobal::dirs()->findAllResources("xdgdata-apps", "mimeapps.list");
55 if (mimeappsFiles
.isEmpty())
58 int basePreference
= 1000; // start high :)
59 QListIterator
<QString
> mimeappsIter( mimeappsFiles
);
60 mimeappsIter
.toBack();
61 while (mimeappsIter
.hasPrevious()) { // global first, then local.
62 const QString mimeappsFile
= mimeappsIter
.previous();
63 kDebug(7021) << "Parsing" << mimeappsFile
;
64 parseMimeAppsList(mimeappsFile
, basePreference
);
70 void KMimeAssociations::parseMimeAppsList(const QString
& file
, int basePreference
)
72 KConfig
profile(file
, KConfig::SimpleConfig
);
73 parseAddedAssociations(KConfigGroup(&profile
, "Added Associations"), file
, basePreference
);
74 parseRemovedAssociations(KConfigGroup(&profile
, "Removed Associations"), file
);
76 // KDE extension for parts and plugins, see settings/filetypes/mimetypedata.cpp
77 parseAddedAssociations(KConfigGroup(&profile
, "Added KDE Service Associations"), file
, basePreference
);
78 parseRemovedAssociations(KConfigGroup(&profile
, "Removed KDE Service Associations"), file
);
81 void KMimeAssociations::parseAddedAssociations(const KConfigGroup
& group
, const QString
& file
, int basePreference
)
83 Q_FOREACH(const QString
& mime
, group
.keyList()) {
84 int pref
= basePreference
;
85 const QStringList services
= group
.readXdgListEntry(mime
);
86 Q_FOREACH(const QString
&service
, services
) {
87 KService::Ptr pService
= KService::serviceByStorageId(service
);
89 kDebug(7021) << file
<< "specifies unknown service" << service
<< "in" << group
.name();
91 //kDebug(7021) << "adding mime" << mime << "to service" << pService->entryPath() << "pref=" << pref;
92 m_offerHash
.addServiceOffer(mime
, KServiceOffer(pService
, pref
, 0, pService
->allowAsDefault()));
99 void KMimeAssociations::parseRemovedAssociations(const KConfigGroup
& group
, const QString
& file
)
101 Q_FOREACH(const QString
& mime
, group
.keyList()) {
102 const QStringList services
= group
.readXdgListEntry(mime
);
103 Q_FOREACH(const QString
& service
, services
) {
104 KService::Ptr pService
= KService::serviceByStorageId(service
);
106 kDebug(7021) << file
<< "specifies unknown service" << service
<< "in" << group
.name();
108 //kDebug(7021) << "removing mime" << mime << "from service" << pService.data() << pService->entryPath();
109 m_offerHash
.removeServiceOffer(mime
, pService
);
115 void KOfferHash::addServiceOffer(const QString
& serviceType
, const KServiceOffer
& offer
)
117 KService::Ptr service
= offer
.service();
118 //kDebug(7021) << "Adding" << service->entryPath() << "to" << serviceType << offer.preference();
119 ServiceTypeOffersData
& data
= m_serviceTypeData
[serviceType
]; // find or create
120 QList
<KServiceOffer
>& offers
= data
.offers
;
121 QSet
<KService::Ptr
>& offerSet
= data
.offerSet
;
122 if ( !offerSet
.contains( service
) ) {
123 offers
.append( offer
);
124 offerSet
.insert( service
);
126 //kDebug(7021) << service->entryPath() << "already in" << serviceType;
127 // This happens when mimeapps.list mentions a service (to make it preferred)
128 // Update initialPreference to qMax(existing offer, new offer)
129 QMutableListIterator
<KServiceOffer
> sfit(data
.offers
);
130 while (sfit
.hasNext()) {
131 if (sfit
.next().service() == service
) // we can compare KService::Ptrs because they are from the memory hash
132 sfit
.value().setPreference( qMax(sfit
.value().preference(), offer
.preference()) );
137 void KOfferHash::removeServiceOffer(const QString
& serviceType
, KService::Ptr service
)
139 ServiceTypeOffersData
& data
= m_serviceTypeData
[serviceType
]; // find or create
140 data
.removedOffers
.insert(service
);
141 data
.offerSet
.remove(service
);
142 QMutableListIterator
<KServiceOffer
> sfit(data
.offers
);
143 while (sfit
.hasNext()) {
144 if (sfit
.next().service()->storageId() == service
->storageId())
149 bool KOfferHash::hasRemovedOffer(const QString
& serviceType
, KService::Ptr service
) const
151 QHash
<QString
, ServiceTypeOffersData
>::const_iterator it
= m_serviceTypeData
.find(serviceType
);
152 if (it
!= m_serviceTypeData
.end()) {
153 return (*it
).removedOffers
.contains(service
);