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 if (!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 00102 //static 00103 void KServiceTypeProfile::clearCache() 00104 { 00105 if (s_serviceTypeProfiles.exists()) 00106 s_serviceTypeProfiles->clear(); 00107 } 00108 00116 namespace KServiceTypeProfile { 00117 KServiceOfferList sortServiceTypeOffers( const KServiceOfferList& list, const QString& servicetype ); 00118 } 00119 00120 KServiceOfferList KServiceTypeProfile::sortServiceTypeOffers( const KServiceOfferList& list, const QString& serviceType ) 00121 { 00122 QMutexLocker lock(&s_serviceTypeProfiles->m_mutex); 00123 s_serviceTypeProfiles->ensureParsed(); 00124 KServiceTypeProfileEntry* profile = s_serviceTypeProfiles->value(serviceType, 0); 00125 00126 KServiceOfferList offers; 00127 00128 KServiceOfferList::const_iterator it = list.begin(); 00129 const KServiceOfferList::const_iterator end = list.end(); 00130 for( ; it != end; ++it ) 00131 { 00132 const KService::Ptr servPtr = (*it).service(); 00133 //kDebug(7014) << "KServiceTypeProfile::offers considering " << servPtr->storageId(); 00134 // Look into the profile (if there's one), to find this service's preference. 00135 bool foundInProfile = false; 00136 if ( profile ) 00137 { 00138 QMap<QString,int>::ConstIterator it2 = profile->m_mapServices.constFind( servPtr->storageId() ); 00139 if( it2 != profile->m_mapServices.constEnd() ) 00140 { 00141 const int pref = it2.value(); 00142 //kDebug(7014) << "found in mapServices pref=" << pref; 00143 if ( pref > 0 ) { // 0 disables the service 00144 offers.append( KServiceOffer( servPtr, pref, 0, servPtr->allowAsDefault() ) ); 00145 } 00146 foundInProfile = true; 00147 } 00148 } 00149 if ( !foundInProfile ) 00150 { 00151 // This offer isn't in the profile 00152 // This can be because we have no profile at all, or because the 00153 // services have been installed after the profile was written, 00154 // but it's also the case for any service that's neither App nor ReadOnlyPart, e.g. RenameDlg/Plugin 00155 //kDebug(7014) << "not found in mapServices. Appending."; 00156 00157 // 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) 00158 offers.append( KServiceOffer( servPtr, 00159 profile ? 0 : (*it).preference(), 00160 0, 00161 servPtr->allowAsDefault() ) ); 00162 } 00163 } 00164 00165 qStableSort( offers ); 00166 00167 //kDebug(7014) << "KServiceTypeProfile::offers returning " << offers.count() << " offers"; 00168 return offers; 00169 } 00170 00171 bool KServiceTypeProfile::hasProfile( const QString& serviceType ) 00172 { 00173 return s_serviceTypeProfiles->hasProfile(serviceType); 00174 } 00175 00176 void KServiceTypeProfile::writeServiceTypeProfile( const QString& serviceType, 00177 const KService::List& services, 00178 const KService::List& disabledServices ) 00179 { 00180 /* 00181 * [ServiceType] 00182 * NumEntries=3 00183 * Entry0_Service=serv.desktop 00184 * Entry0_Preference=10 00185 * Entry1_Service=otherserv.desktop 00186 * Entry1_Preference=5 00187 * Entry2_Service=broken_service.desktop 00188 * Entry2_Preference=0 00189 */ 00190 00191 KConfig configFile( QString::fromLatin1("servicetype_profilerc"), KConfig::SimpleConfig); 00192 configFile.deleteGroup( serviceType ); 00193 00194 KConfigGroup config(&configFile, serviceType ); 00195 const int count = services.count(); 00196 config.writeEntry( "NumberOfEntries", count + disabledServices.count() ); 00197 KService::List::ConstIterator servit = services.begin(); 00198 int i = 0; 00199 for( ; servit != services.end(); ++servit, ++i ) { 00200 if (!servit->isNull()) { 00201 const QString num = QString::fromLatin1("Entry") + QString::number(i); 00202 config.writeEntry( num + QLatin1String("_Service"), (*servit)->storageId() ); 00203 config.writeEntry( num + QLatin1String("_Preference"), count - i ); 00204 } 00205 } 00206 servit = disabledServices.begin(); 00207 for( ; servit != disabledServices.end(); ++servit, ++i ) { 00208 if (!servit->isNull()) { 00209 const QString num = QString::fromLatin1("Entry") + QString::number(i); 00210 config.writeEntry( num + QLatin1String("_Service"), (*servit)->storageId() ); 00211 config.writeEntry( num + QLatin1String("_Preference"), 0 ); 00212 } 00213 } 00214 configFile.sync(); 00215 00216 // Drop the whole cache... 00217 clearCache(); 00218 } 00219 00220 void KServiceTypeProfile::deleteServiceTypeProfile( const QString& serviceType) 00221 { 00222 KConfig config(QString::fromLatin1("servicetype_profilerc"), KConfig::SimpleConfig); 00223 config.deleteGroup( serviceType ); 00224 config.sync(); 00225 00226 // Not threadsafe, but well the whole idea of using this method isn't 00227 // threadsafe in the first place. 00228 if (s_serviceTypeProfiles.exists()) { 00229 delete s_serviceTypeProfiles->take( serviceType ); 00230 } 00231 } 00232 00233 void KServiceTypeProfile::setConfigurationMode() 00234 { 00235 s_configurationMode = true; 00236 } 00237 00238 bool KServiceTypeProfile::configurationMode() 00239 { 00240 return s_configurationMode; 00241 }
KDE 4.7 API Reference