KDECore
kservicetypeprofile.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999 Torben Weis <weis@kde.org> 00003 * Copyright (C) 2006 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 "kservicetypeprofile.h" 00021 #include "kservicetypeprofile_p.h" 00022 #include <QMutex> 00023 #include "kservice.h" 00024 #include "kservicetype.h" 00025 #include "kservicetypefactory.h" 00026 #include "kservicefactory.h" 00027 00028 #include <kconfig.h> 00029 #include <kstandarddirs.h> 00030 #include <kdebug.h> 00031 #include <kconfiggroup.h> 00032 00033 #include <QtCore/QHash> 00034 #include <QtAlgorithms> 00035 00036 // servicetype -> profile 00037 class KServiceTypeProfiles : public QHash<QString, KServiceTypeProfileEntry *> 00038 { 00039 public: 00040 KServiceTypeProfiles() { m_parsed = false; ensureParsed(); } 00041 ~KServiceTypeProfiles() { clear(); } 00042 void clear() { 00043 QMutexLocker lock(&m_mutex); 00044 qDeleteAll( *this ); 00045 QHash<QString, KServiceTypeProfileEntry *>::clear(); 00046 m_parsed = false; 00047 } 00048 bool hasProfile(const QString& serviceType) { 00049 QMutexLocker lock(&m_mutex); 00050 ensureParsed(); 00051 return contains(serviceType); 00052 } 00053 void ensureParsed(); // mutex must be locked when calling this 00054 QMutex m_mutex; 00055 private: 00056 bool m_parsed; 00057 }; 00058 00059 00060 K_GLOBAL_STATIC(KServiceTypeProfiles, s_serviceTypeProfiles) 00061 00062 static bool s_configurationMode = false; 00063 00064 void KServiceTypeProfiles::ensureParsed() 00065 { 00066 if (m_parsed) 00067 return; 00068 m_parsed = true; 00069 00070 // Make sure that a KServiceTypeFactory gets created. 00071 (void) KServiceTypeFactory::self(); 00072 00073 // Read the service type profiles from servicetype_profilerc (new in kde4) 00074 // See writeServiceTypeProfile for a description of the file format. 00075 // ### Since this new format names groups after servicetypes maybe we can even 00076 // avoid doing any init upfront, and just look up the group when asked... 00077 KConfig configFile( QString::fromLatin1("servicetype_profilerc"), KConfig::NoGlobals ); 00078 const QStringList tmpList = configFile.groupList(); 00079 for (QStringList::const_iterator aIt = tmpList.begin(); 00080 aIt != tmpList.end(); ++aIt) { 00081 const QString type = *aIt; 00082 KConfigGroup config(&configFile, type); 00083 const int count = config.readEntry( "NumberOfEntries", 0 ); 00084 KServiceTypeProfileEntry* p = this->value( type, 0 ); 00085 if ( !p ) { 00086 p = new KServiceTypeProfileEntry(); 00087 this->insert( type, p ); 00088 } 00089 00090 for ( int i = 0; i < count; ++i ) { 00091 const QString num = QString::fromLatin1("Entry") + QString::number(i); 00092 const QString serviceId = config.readEntry( num + QLatin1String("_Service"), QString() ); 00093 Q_ASSERT(!serviceId.isEmpty()); 00094 const int pref = config.readEntry( num + QLatin1String("_Preference"), 0 ); 00095 //kDebug(7014) << "adding service " << serviceId << " to profile for " << type << " with preference " << pref; 00096 p->addService( serviceId, pref ); 00097 } 00098 } 00099 } 00100 00101 //static 00102 void KServiceTypeProfile::clearCache() 00103 { 00104 if (s_serviceTypeProfiles.exists()) 00105 s_serviceTypeProfiles->clear(); 00106 } 00107 00115 namespace KServiceTypeProfile { 00116 KServiceOfferList sortServiceTypeOffers( const KServiceOfferList& list, const QString& servicetype ); 00117 } 00118 00119 KServiceOfferList KServiceTypeProfile::sortServiceTypeOffers( const KServiceOfferList& list, const QString& serviceType ) 00120 { 00121 QMutexLocker lock(&s_serviceTypeProfiles->m_mutex); 00122 s_serviceTypeProfiles->ensureParsed(); 00123 KServiceTypeProfileEntry* profile = s_serviceTypeProfiles->value(serviceType, 0); 00124 00125 KServiceOfferList offers; 00126 00127 KServiceOfferList::const_iterator it = list.begin(); 00128 const KServiceOfferList::const_iterator end = list.end(); 00129 for( ; it != end; ++it ) 00130 { 00131 const KService::Ptr servPtr = (*it).service(); 00132 //kDebug(7014) << "KServiceTypeProfile::offers considering " << servPtr->storageId(); 00133 // Look into the profile (if there's one), to find this service's preference. 00134 bool foundInProfile = false; 00135 if ( profile ) 00136 { 00137 QMap<QString,int>::ConstIterator it2 = profile->m_mapServices.constFind( servPtr->storageId() ); 00138 if( it2 != profile->m_mapServices.constEnd() ) 00139 { 00140 const int pref = it2.value(); 00141 //kDebug(7014) << "found in mapServices pref=" << pref; 00142 if ( pref > 0 ) { // 0 disables the service 00143 offers.append( KServiceOffer( servPtr, pref, 0, servPtr->allowAsDefault() ) ); 00144 } 00145 foundInProfile = true; 00146 } 00147 } 00148 if ( !foundInProfile ) 00149 { 00150 // This offer isn't in the profile 00151 // This can be because we have no profile at all, or because the 00152 // services have been installed after the profile was written, 00153 // but it's also the case for any service that's neither App nor ReadOnlyPart, e.g. RenameDlg/Plugin 00154 //kDebug(7014) << "not found in mapServices. Appending."; 00155 00156 // If there's a profile, we use 0 as the preference to ensure new apps don't take over existing apps (which default to 1) 00157 offers.append( KServiceOffer( servPtr, 00158 profile ? 0 : (*it).preference(), 00159 0, 00160 servPtr->allowAsDefault() ) ); 00161 } 00162 } 00163 00164 qStableSort( offers ); 00165 00166 //kDebug(7014) << "KServiceTypeProfile::offers returning " << offers.count() << " offers"; 00167 return offers; 00168 } 00169 00170 bool KServiceTypeProfile::hasProfile( const QString& serviceType ) 00171 { 00172 return s_serviceTypeProfiles->hasProfile(serviceType); 00173 } 00174 00175 void KServiceTypeProfile::writeServiceTypeProfile( const QString& serviceType, 00176 const KService::List& services, 00177 const KService::List& disabledServices ) 00178 { 00179 /* 00180 * [ServiceType] 00181 * NumEntries=3 00182 * Entry0_Service=serv.desktop 00183 * Entry0_Preference=10 00184 * Entry1_Service=otherserv.desktop 00185 * Entry1_Preference=5 00186 * Entry2_Service=broken_service.desktop 00187 * Entry2_Preference=0 00188 */ 00189 00190 KConfig configFile( QString::fromLatin1("servicetype_profilerc"), KConfig::SimpleConfig); 00191 configFile.deleteGroup( serviceType ); 00192 00193 KConfigGroup config(&configFile, serviceType ); 00194 const int count = services.count(); 00195 config.writeEntry( "NumberOfEntries", count + disabledServices.count() ); 00196 KService::List::ConstIterator servit = services.begin(); 00197 int i = 0; 00198 for( ; servit != services.end(); ++servit, ++i ) { 00199 if (!servit->isNull()) { 00200 const QString num = QString::fromLatin1("Entry") + QString::number(i); 00201 config.writeEntry( num + QLatin1String("_Service"), (*servit)->storageId() ); 00202 config.writeEntry( num + QLatin1String("_Preference"), count - i ); 00203 } 00204 } 00205 servit = disabledServices.begin(); 00206 for( ; servit != disabledServices.end(); ++servit, ++i ) { 00207 if (!servit->isNull()) { 00208 const QString num = QString::fromLatin1("Entry") + QString::number(i); 00209 config.writeEntry( num + QLatin1String("_Service"), (*servit)->storageId() ); 00210 config.writeEntry( num + QLatin1String("_Preference"), 0 ); 00211 } 00212 } 00213 configFile.sync(); 00214 00215 // Drop the whole cache... 00216 clearCache(); 00217 } 00218 00219 void KServiceTypeProfile::deleteServiceTypeProfile( const QString& serviceType) 00220 { 00221 KConfig config(QString::fromLatin1("servicetype_profilerc"), KConfig::SimpleConfig); 00222 config.deleteGroup( serviceType ); 00223 config.sync(); 00224 00225 // Not threadsafe, but well the whole idea of using this method isn't 00226 // threadsafe in the first place. 00227 if (s_serviceTypeProfiles.exists()) { 00228 delete s_serviceTypeProfiles->take( serviceType ); 00229 } 00230 } 00231 00232 void KServiceTypeProfile::setConfigurationMode() 00233 { 00234 s_configurationMode = true; 00235 } 00236 00237 bool KServiceTypeProfile::configurationMode() 00238 { 00239 return s_configurationMode; 00240 }
KDE 4.6 API Reference