KDED
kbuildservicefactory.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kbuildservicefactory.h"
00021 #include "kbuildservicegroupfactory.h"
00022 #include "kbuildmimetypefactory.h"
00023 #include "ksycoca.h"
00024 #include "ksycocadict.h"
00025 #include "kresourcelist.h"
00026 #include "kdesktopfile.h"
00027
00028 #include <kglobal.h>
00029 #include <kstandarddirs.h>
00030 #include <klocale.h>
00031 #include <kdebug.h>
00032 #include <assert.h>
00033 #include <kmimetypefactory.h>
00034
00035 KBuildServiceFactory::KBuildServiceFactory( KSycocaFactory *serviceTypeFactory,
00036 KBuildMimeTypeFactory *mimeTypeFactory,
00037 KBuildServiceGroupFactory *serviceGroupFactory ) :
00038 KServiceFactory(),
00039 m_nameMemoryHash(),
00040 m_relNameMemoryHash(),
00041 m_menuIdMemoryHash(),
00042 m_dupeDict(),
00043 m_serviceTypeFactory( serviceTypeFactory ),
00044 m_mimeTypeFactory( mimeTypeFactory ),
00045 m_serviceGroupFactory( serviceGroupFactory )
00046 {
00047 m_resourceList = new KSycocaResourceList();
00048
00049
00050 m_resourceList->add( "services", "*.desktop" );
00051 }
00052
00053
00054
00055 QStringList KBuildServiceFactory::resourceTypes()
00056 {
00057 return QStringList() << "services";
00058 }
00059
00060 KBuildServiceFactory::~KBuildServiceFactory()
00061 {
00062 delete m_resourceList;
00063 }
00064
00065 KService::Ptr KBuildServiceFactory::findServiceByDesktopName(const QString &name)
00066 {
00067 return m_nameMemoryHash.value(name);
00068 }
00069
00070 KService::Ptr KBuildServiceFactory::findServiceByDesktopPath(const QString &name)
00071 {
00072 return m_relNameMemoryHash.value(name);
00073 }
00074
00075 KService::Ptr KBuildServiceFactory::findServiceByMenuId(const QString &menuId)
00076 {
00077 return m_menuIdMemoryHash.value(menuId);
00078 }
00079
00080 KSycocaEntry* KBuildServiceFactory::createEntry( const QString& file, const char *resource ) const
00081 {
00082 QString name = file;
00083 int pos = name.lastIndexOf('/');
00084 if (pos != -1) {
00085 name = name.mid(pos+1);
00086 }
00087
00088 if (!name.endsWith(".desktop"))
00089 return 0;
00090
00091 KDesktopFile desktopFile(resource, file);
00092
00093 KService * serv = new KService(&desktopFile);
00094
00095
00096
00097
00098 if ( serv->isValid() && !serv->isDeleted() ) {
00099 return serv;
00100 } else {
00101 if (!serv->isDeleted())
00102 kWarning(7012) << "Invalid Service : " << file;
00103 delete serv;
00104 return 0;
00105 }
00106 }
00107
00108 void KBuildServiceFactory::saveHeader(QDataStream &str)
00109 {
00110 KSycocaFactory::saveHeader(str);
00111
00112 str << (qint32) m_nameDictOffset;
00113 str << (qint32) m_relNameDictOffset;
00114 str << (qint32) m_offerListOffset;
00115 str << (qint32) m_menuIdDictOffset;
00116 }
00117
00118 void KBuildServiceFactory::save(QDataStream &str)
00119 {
00120 KSycocaFactory::save(str);
00121
00122 m_nameDictOffset = str.device()->pos();
00123 m_nameDict->save(str);
00124
00125 m_relNameDictOffset = str.device()->pos();
00126 m_relNameDict->save(str);
00127
00128 saveOfferList(str);
00129
00130 m_menuIdDictOffset = str.device()->pos();
00131 m_menuIdDict->save(str);
00132
00133 int endOfFactoryData = str.device()->pos();
00134
00135
00136 saveHeader(str);
00137
00138
00139 str.device()->seek(endOfFactoryData);
00140 }
00141
00142 void KBuildServiceFactory::collectInheritedServices()
00143 {
00144
00145
00146
00147
00148 QSet<KMimeType::Ptr> visitedMimes;
00149 const KMimeType::List allMimeTypes = m_mimeTypeFactory->allMimeTypes();
00150 KMimeType::List::const_iterator itm = allMimeTypes.begin();
00151 for( ; itm != allMimeTypes.end(); ++itm ) {
00152 const KMimeType::Ptr mimeType = *itm;
00153 collectInheritedServices(mimeType, visitedMimes);
00154 }
00155
00156 }
00157
00158 void KBuildServiceFactory::collectInheritedServices(KMimeType::Ptr mimeType, QSet<KMimeType::Ptr>& visitedMimes)
00159 {
00160 if (visitedMimes.contains(mimeType))
00161 return;
00162 visitedMimes.insert(mimeType);
00163
00164
00165
00166
00167 int mimeTypeInheritanceLevel = 0;
00168
00169 const QString mimeTypeName = mimeType->name();
00170 Q_FOREACH(const QString& parent, mimeType->parentMimeTypes()) {
00171 const KMimeType::Ptr parentMimeType =
00172 m_mimeTypeFactory->findMimeTypeByName(parent, KMimeType::ResolveAliases);
00173
00174 if ( parentMimeType ) {
00175 collectInheritedServices(parentMimeType, visitedMimes);
00176
00177 ++mimeTypeInheritanceLevel;
00178 const QList<KServiceOffer>& offers = m_offerHash.offersFor(parent);
00179 QList<KServiceOffer>::const_iterator itserv = offers.begin();
00180 const QList<KServiceOffer>::const_iterator endserv = offers.end();
00181 for ( ; itserv != endserv; ++itserv ) {
00182 if (!m_offerHash.hasRemovedOffer(mimeTypeName, (*itserv).service())) {
00183 KServiceOffer offer(*itserv);
00184 offer.setMimeTypeInheritanceLevel(mimeTypeInheritanceLevel);
00185
00186 m_offerHash.addServiceOffer( mimeTypeName, offer );
00187 }
00188 }
00189 } else {
00190 kWarning(7012) << "parent mimetype not found:" << parent;
00191 break;
00192 }
00193 }
00194 }
00195
00196
00197 void KBuildServiceFactory::populateServiceTypes()
00198 {
00199
00200 KSycocaEntryDict::Iterator itserv = m_entryDict->begin();
00201 const KSycocaEntryDict::Iterator endserv = m_entryDict->end();
00202 for( ; itserv != endserv ; ++itserv ) {
00203 KService::Ptr service = KService::Ptr::staticCast(*itserv);
00204 QVector<KService::ServiceTypeAndPreference> serviceTypeList = service->_k_accessServiceTypes();
00205
00206
00207
00208
00209 for (int i = 0; i < serviceTypeList.count() ; ++i) {
00210 const QString stName = serviceTypeList[i].serviceType;
00211
00212 KServiceType::Ptr serviceType = KServiceType::serviceType(stName);
00213 if (!serviceType) {
00214 serviceType = KServiceType::Ptr::staticCast(m_mimeTypeFactory->findMimeTypeByName(stName, KMimeType::ResolveAliases));
00215 }
00216
00217
00218
00219 #if 0
00220 if (!serviceType) {
00221 if ( stName == QLatin1String( "all/all" ) ) {
00222 hasAllAll = true;
00223 continue;
00224 } else if ( stName == QLatin1String( "all/allfiles" ) ) {
00225 hasAllFiles = true;
00226 continue;
00227 }
00228 }
00229 #endif
00230
00231 if (!serviceType) {
00232 kDebug(7021) << service->entryPath() << "specifies undefined mimetype/servicetype" << stName;
00233 continue;
00234 }
00235
00236 const int preference = serviceTypeList[i].preference;
00237 const QString parent = serviceType->parentServiceType();
00238 if (!parent.isEmpty())
00239 serviceTypeList.append(KService::ServiceTypeAndPreference(preference, parent));
00240
00241
00242 m_offerHash.addServiceOffer(stName, KServiceOffer(service, preference, 0, service->allowAsDefault()) );
00243 }
00244 }
00245
00246
00247 KMimeAssociations mimeAssociations(m_offerHash);
00248 mimeAssociations.parseAllMimeAppsList();
00249
00250
00251 collectInheritedServices();
00252
00253
00254
00255 int offersOffset = 0;
00256 const int offerEntrySize = sizeof( qint32 ) * 4;
00257
00258 KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->constBegin();
00259 const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->constEnd();
00260 for( ; itstf != endstf; ++itstf ) {
00261 KServiceType::Ptr entry = KServiceType::Ptr::staticCast( *itstf );
00262 const int numOffers = m_offerHash.offersFor(entry->name()).count();
00263 if ( numOffers ) {
00264 entry->setServiceOffersOffset( offersOffset );
00265 offersOffset += offerEntrySize * numOffers;
00266 }
00267 }
00268 KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->constBegin();
00269 const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->constEnd();
00270 for( ; itmtf != endmtf; ++itmtf )
00271 {
00272 KMimeType::Ptr entry = KMimeType::Ptr::staticCast( *itmtf );
00273 const int numOffers = m_offerHash.offersFor(entry->name()).count();
00274 if ( numOffers ) {
00275 entry->setServiceOffersOffset( offersOffset );
00276 offersOffset += offerEntrySize * numOffers;
00277 }
00278 }
00279 }
00280
00281 void KBuildServiceFactory::saveOfferList(QDataStream &str)
00282 {
00283 m_offerListOffset = str.device()->pos();
00284
00285
00286 KSycocaEntryDict::const_iterator itstf = m_serviceTypeFactory->entryDict()->constBegin();
00287 const KSycocaEntryDict::const_iterator endstf = m_serviceTypeFactory->entryDict()->constEnd();
00288 for( ; itstf != endstf; ++itstf ) {
00289
00290 const KServiceType::Ptr entry = KServiceType::Ptr::staticCast( *itstf );
00291 Q_ASSERT( entry );
00292
00293 QList<KServiceOffer> offers = m_offerHash.offersFor(entry->name());
00294 qStableSort( offers );
00295
00296 for(QList<KServiceOffer>::const_iterator it2 = offers.constBegin();
00297 it2 != offers.constEnd(); ++it2) {
00298
00299
00300 str << (qint32) entry->offset();
00301 str << (qint32) (*it2).service()->offset();
00302 str << (qint32) (*it2).preference();
00303 str << (qint32) 0;
00304
00305 }
00306 }
00307
00308
00309 KSycocaEntryDict::const_iterator itmtf = m_mimeTypeFactory->entryDict()->constBegin();
00310 const KSycocaEntryDict::const_iterator endmtf = m_mimeTypeFactory->entryDict()->constEnd();
00311 for( ; itmtf != endmtf; ++itmtf ) {
00312
00313 const KMimeType::Ptr entry = KMimeType::Ptr::staticCast( *itmtf );
00314 Q_ASSERT( entry );
00315 QList<KServiceOffer> offers = m_offerHash.offersFor(entry->name());
00316 qStableSort( offers );
00317
00318 for(QList<KServiceOffer>::const_iterator it2 = offers.constBegin();
00319 it2 != offers.constEnd(); ++it2) {
00320
00321 Q_ASSERT((*it2).service()->offset() != 0);
00322 str << (qint32) entry->offset();
00323 str << (qint32) (*it2).service()->offset();
00324 str << (qint32) (*it2).preference();
00325 str << (qint32) (*it2).mimeTypeInheritanceLevel();
00326
00327 }
00328 }
00329
00330 str << (qint32) 0;
00331 }
00332
00333 void KBuildServiceFactory::addEntry(const KSycocaEntry::Ptr& newEntry)
00334 {
00335 Q_ASSERT(newEntry);
00336 if (m_dupeDict.contains(newEntry))
00337 return;
00338
00339 KSycocaFactory::addEntry(newEntry);
00340
00341 const KService::Ptr service = KService::Ptr::staticCast( newEntry );
00342 m_dupeDict.insert(newEntry);
00343
00344 if (!service->isDeleted()) {
00345 const QString parent = service->parentApp();
00346 if (!parent.isEmpty())
00347 m_serviceGroupFactory->addNewChild(parent, KSycocaEntry::Ptr::staticCast(service));
00348 }
00349
00350 const QString name = service->desktopEntryName();
00351 m_nameDict->add( name, newEntry );
00352 m_nameMemoryHash.insert(name, service);
00353
00354 const QString relName = service->entryPath();
00355
00356 m_relNameDict->add( relName, newEntry );
00357 m_relNameMemoryHash.insert(relName, service);
00358
00359 const QString menuId = service->menuId();
00360 if (!menuId.isEmpty()) {
00361 m_menuIdDict->add( menuId, newEntry );
00362 m_menuIdMemoryHash.insert(menuId, service);
00363 }
00364 }
00365