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