KDECore
kservicefactory.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999-2006 David Faure <faure@kde.org> 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License version 2 as published by the Free Software Foundation; 00007 * 00008 * This library is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Library General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Library General Public License 00014 * along with this library; see the file COPYING.LIB. If not, write to 00015 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 * Boston, MA 02110-1301, USA. 00017 **/ 00018 00019 #include "kservicefactory.h" 00020 #include "ksycoca.h" 00021 #include "ksycocatype.h" 00022 #include "ksycocadict_p.h" 00023 #include "kservice.h" 00024 00025 #include <klocale.h> 00026 #include <kdebug.h> 00027 #include <kglobal.h> 00028 #include <kstandarddirs.h> 00029 00030 extern int servicesDebugArea(); 00031 00032 K_GLOBAL_STATIC(KSycocaFactorySingleton<KServiceFactory>, kServiceFactoryInstance) 00033 00034 KServiceFactory::KServiceFactory() 00035 : KSycocaFactory( KST_KServiceFactory ), 00036 m_nameDict(0), 00037 m_relNameDict(0), 00038 m_menuIdDict(0) 00039 { 00040 kServiceFactoryInstance->instanceCreated(this); 00041 m_offerListOffset = 0; 00042 m_nameDictOffset = 0; 00043 m_relNameDictOffset = 0; 00044 m_menuIdDictOffset = 0; 00045 if (!KSycoca::self()->isBuilding()) { 00046 QDataStream* str = stream(); 00047 Q_ASSERT(str); 00048 if (!str) 00049 return; 00050 // Read Header 00051 qint32 i; 00052 (*str) >> i; 00053 m_nameDictOffset = i; 00054 (*str) >> i; 00055 m_relNameDictOffset = i; 00056 (*str) >> i; 00057 m_offerListOffset = i; 00058 (*str) >> i; 00059 m_menuIdDictOffset = i; 00060 00061 const int saveOffset = str->device()->pos(); 00062 // Init index tables 00063 m_nameDict = new KSycocaDict(str, m_nameDictOffset); 00064 // Init index tables 00065 m_relNameDict = new KSycocaDict(str, m_relNameDictOffset); 00066 // Init index tables 00067 m_menuIdDict = new KSycocaDict(str, m_menuIdDictOffset); 00068 str->device()->seek(saveOffset); 00069 } 00070 } 00071 00072 KServiceFactory::~KServiceFactory() 00073 { 00074 if (kServiceFactoryInstance.exists()) 00075 kServiceFactoryInstance->instanceDestroyed(this); 00076 delete m_nameDict; 00077 delete m_relNameDict; 00078 delete m_menuIdDict; 00079 } 00080 00081 KServiceFactory * KServiceFactory::self() 00082 { 00083 return kServiceFactoryInstance->self(); 00084 } 00085 00086 KService::Ptr KServiceFactory::findServiceByName(const QString &_name) 00087 { 00088 if (!sycocaDict()) return KService::Ptr(); // Error! 00089 00090 // Warning : this assumes we're NOT building a database 00091 // But since findServiceByName isn't called in that case... 00092 // [ see KServiceTypeFactory for how to do it if needed ] 00093 00094 int offset = sycocaDict()->find_string( _name ); 00095 if (!offset) return KService::Ptr(); // Not found 00096 00097 KService::Ptr newService(createEntry(offset)); 00098 00099 // Check whether the dictionary was right. 00100 if (newService && (newService->name() != _name)) { 00101 // No it wasn't... 00102 return KService::Ptr(); 00103 } 00104 return newService; 00105 } 00106 00107 KService::Ptr KServiceFactory::findServiceByDesktopName(const QString &_name) 00108 { 00109 if (!m_nameDict) return KService::Ptr(); // Error! 00110 00111 // Warning : this assumes we're NOT building a database 00112 // KBuildServiceFactory reimplements it for the case where we are building one 00113 00114 int offset = m_nameDict->find_string( _name ); 00115 if (!offset) return KService::Ptr(); // Not found 00116 00117 KService::Ptr newService(createEntry(offset)); 00118 00119 // Check whether the dictionary was right. 00120 if (newService && (newService->desktopEntryName() != _name)) { 00121 // No it wasn't... 00122 return KService::Ptr(); 00123 } 00124 return newService; 00125 } 00126 00127 KService::Ptr KServiceFactory::findServiceByDesktopPath(const QString &_name) 00128 { 00129 if (!m_relNameDict) return KService::Ptr(); // Error! 00130 00131 // Warning : this assumes we're NOT building a database 00132 // KBuildServiceFactory reimplements it for the case where we are building one 00133 00134 int offset = m_relNameDict->find_string( _name ); 00135 if (!offset) { 00136 //kDebug(servicesDebugArea()) << "findServiceByDesktopPath:" << _name << "not found"; 00137 return KService::Ptr(); // Not found 00138 } 00139 00140 KService::Ptr newService(createEntry(offset)); 00141 if (!newService) { 00142 kDebug(servicesDebugArea()) << "findServiceByDesktopPath: createEntry failed!"; 00143 } 00144 // Check whether the dictionary was right 00145 // It's ok that it's wrong, for the case where we're looking up an unknown service, 00146 // and the hash value gave us another one. 00147 if (newService && (newService->entryPath() != _name)) { 00148 // No it wasn't... 00149 return KService::Ptr(); 00150 } 00151 return newService; 00152 } 00153 00154 KService::Ptr KServiceFactory::findServiceByMenuId(const QString &_menuId) 00155 { 00156 if (!m_menuIdDict) return KService::Ptr(); // Error! 00157 00158 // Warning : this assumes we're NOT building a database 00159 // KBuildServiceFactory reimplements it for the case where we are building one 00160 00161 int offset = m_menuIdDict->find_string( _menuId ); 00162 if (!offset) return KService::Ptr(); // Not found 00163 00164 KService::Ptr newService(createEntry(offset)); 00165 00166 // Check whether the dictionary was right. 00167 if (newService && (newService->menuId() != _menuId)) { 00168 // No it wasn't... 00169 return KService::Ptr(); 00170 } 00171 return newService; 00172 } 00173 00174 KService* KServiceFactory::createEntry(int offset) const 00175 { 00176 KService * newEntry = 0L; 00177 KSycocaType type; 00178 QDataStream *str = KSycoca::self()->findEntry(offset, type); 00179 switch(type) { 00180 case KST_KService: 00181 newEntry = new KService(*str, offset); 00182 break; 00183 default: 00184 kError(7011) << "KServiceFactory: unexpected object entry in KSycoca database (type=" << int(type) << ")"; 00185 return 0; 00186 } 00187 if (!newEntry->isValid()) { 00188 kError(7011) << "KServiceFactory: corrupt object in KSycoca database!"; 00189 delete newEntry; 00190 newEntry = 0; 00191 } 00192 return newEntry; 00193 } 00194 00195 KService::List KServiceFactory::allServices() 00196 { 00197 KService::List result; 00198 const KSycocaEntry::List list = allEntries(); 00199 KSycocaEntry::List::const_iterator it = list.begin(); 00200 const KSycocaEntry::List::const_iterator end = list.end(); 00201 for( ; it != end; ++it ) { 00202 const KSycocaEntry::Ptr entry = *it; 00203 if ( entry->isType( KST_KService ) ) 00204 result.append( KService::Ptr::staticCast( entry ) ); 00205 } 00206 return result; 00207 } 00208 00209 QList<KServiceOffer> KServiceFactory::offers( int serviceTypeOffset, int serviceOffersOffset ) 00210 { 00211 QList<KServiceOffer> list; 00212 00213 // Jump to the offer list 00214 QDataStream* str = stream(); 00215 str->device()->seek( m_offerListOffset + serviceOffersOffset ); 00216 00217 qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel; 00218 while (true) 00219 { 00220 (*str) >> aServiceTypeOffset; 00221 if ( aServiceTypeOffset ) { 00222 (*str) >> aServiceOffset; 00223 (*str) >> initialPreference; 00224 (*str) >> mimeTypeInheritanceLevel; 00225 if ( aServiceTypeOffset == serviceTypeOffset ) { 00226 // Save stream position ! 00227 const int savedPos = str->device()->pos(); 00228 // Create Service 00229 KService * serv = createEntry( aServiceOffset ); 00230 if (serv) { 00231 KService::Ptr servPtr( serv ); 00232 list.append( KServiceOffer( servPtr, initialPreference, mimeTypeInheritanceLevel, servPtr->allowAsDefault() ) ); 00233 } 00234 // Restore position 00235 str->device()->seek( savedPos ); 00236 } else 00237 break; // too far 00238 } 00239 else 00240 break; // 0 => end of list 00241 } 00242 return list; 00243 } 00244 00245 KService::List KServiceFactory::serviceOffers( int serviceTypeOffset, int serviceOffersOffset ) 00246 { 00247 KService::List list; 00248 00249 // Jump to the offer list 00250 QDataStream* str = stream(); 00251 str->device()->seek( m_offerListOffset + serviceOffersOffset ); 00252 00253 qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel; 00254 while (true) { 00255 (*str) >> aServiceTypeOffset; 00256 if ( aServiceTypeOffset ) 00257 { 00258 (*str) >> aServiceOffset; 00259 (*str) >> initialPreference; 00260 (*str) >> mimeTypeInheritanceLevel; 00261 if ( aServiceTypeOffset == serviceTypeOffset ) 00262 { 00263 // Save stream position ! 00264 const int savedPos = str->device()->pos(); 00265 // Create service 00266 KService * serv = createEntry( aServiceOffset ); 00267 if (serv) 00268 list.append( KService::Ptr( serv ) ); 00269 // Restore position 00270 str->device()->seek( savedPos ); 00271 } else 00272 break; // too far 00273 } 00274 else 00275 break; // 0 => end of list 00276 } 00277 return list; 00278 } 00279 00280 bool KServiceFactory::hasOffer( int serviceTypeOffset, int serviceOffersOffset, int testedServiceOffset ) 00281 { 00282 // Save stream position 00283 QDataStream* str = stream(); 00284 const int savedPos = str->device()->pos(); 00285 00286 // Jump to the offer list 00287 str->device()->seek( m_offerListOffset + serviceOffersOffset ); 00288 bool found = false; 00289 qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel; 00290 while (!found) 00291 { 00292 (*str) >> aServiceTypeOffset; 00293 if ( aServiceTypeOffset ) { 00294 (*str) >> aServiceOffset; 00295 (*str) >> initialPreference; 00296 (*str) >> mimeTypeInheritanceLevel; 00297 if ( aServiceTypeOffset == serviceTypeOffset ) 00298 { 00299 if( aServiceOffset == testedServiceOffset ) 00300 found = true; 00301 } else 00302 break; // too far 00303 } 00304 else 00305 break; // 0 => end of list 00306 } 00307 // Restore position 00308 str->device()->seek( savedPos ); 00309 return found; 00310 } 00311 00312 void KServiceFactory::virtual_hook( int id, void* data ) 00313 { KSycocaFactory::virtual_hook( id, data ); } 00314
KDE 4.6 API Reference