kservicefactory.cpp
00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999 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.h" 00023 #include "kservice.h" 00024 00025 #include <qstring.h> 00026 00027 #include <klocale.h> 00028 #include <kdebug.h> 00029 #include <kglobal.h> 00030 #include <kstandarddirs.h> 00031 #include <kstaticdeleter.h> 00032 00033 KServiceFactory::KServiceFactory() 00034 : KSycocaFactory( KST_KServiceFactory ) 00035 { 00036 m_offerListOffset = 0; 00037 m_nameDictOffset = 0; 00038 m_relNameDictOffset = 0; 00039 m_menuIdDictOffset = 0; 00040 if (m_str) 00041 { 00042 // Read Header 00043 Q_INT32 i; 00044 (*m_str) >> i; 00045 m_nameDictOffset = i; 00046 (*m_str) >> i; 00047 m_relNameDictOffset = i; 00048 (*m_str) >> i; 00049 m_offerListOffset = i; 00050 (*m_str) >> i; 00051 m_initListOffset = i; 00052 (*m_str) >> i; 00053 m_menuIdDictOffset = i; 00054 00055 int saveOffset = m_str->device()->at(); 00056 // Init index tables 00057 m_nameDict = new KSycocaDict(m_str, m_nameDictOffset); 00058 // Init index tables 00059 m_relNameDict = new KSycocaDict(m_str, m_relNameDictOffset); 00060 // Init index tables 00061 m_menuIdDict = new KSycocaDict(m_str, m_menuIdDictOffset); 00062 saveOffset = m_str->device()->at(saveOffset); 00063 } 00064 else 00065 { 00066 // Build new database 00067 m_nameDict = new KSycocaDict(); 00068 m_relNameDict = new KSycocaDict(); 00069 m_menuIdDict = new KSycocaDict(); 00070 } 00071 _self = this; 00072 } 00073 00074 KServiceFactory::~KServiceFactory() 00075 { 00076 _self = 0L; 00077 delete m_nameDict; 00078 delete m_relNameDict; 00079 delete m_menuIdDict; 00080 } 00081 00082 KServiceFactory * KServiceFactory::self() 00083 { 00084 if (!_self) { 00085 _self = new KServiceFactory(); 00086 } 00087 return _self; 00088 } 00089 00090 KService * KServiceFactory::findServiceByName(const QString &_name) 00091 { 00092 if (!m_sycocaDict) return 0; // Error! 00093 00094 // Warning : this assumes we're NOT building a database 00095 // But since findServiceByName isn't called in that case... 00096 // [ see KServiceTypeFactory for how to do it if needed ] 00097 00098 int offset = m_sycocaDict->find_string( _name ); 00099 if (!offset) return 0; // Not found 00100 00101 KService * newService = createEntry(offset); 00102 00103 // Check whether the dictionary was right. 00104 if (newService && (newService->name() != _name)) 00105 { 00106 // No it wasn't... 00107 delete newService; 00108 newService = 0; // Not found 00109 } 00110 return newService; 00111 } 00112 00113 KService * KServiceFactory::findServiceByDesktopName(const QString &_name) 00114 { 00115 KService *newService = _findServiceByDesktopName(_name); 00116 if (newService) return newService; 00117 00118 newService = _findServiceByDesktopName("kde-" + _name); 00119 if (newService) return newService; 00120 00121 delete newService; 00122 newService = 0; 00123 return newService; 00124 } 00125 00126 KService * KServiceFactory::findServiceByDesktopPath(const QString &_name) 00127 { 00128 KService *newService = _findServiceByDesktopPath(_name); 00129 if (newService) return newService; 00130 00131 int pos = _name.findRev('/') + 1; 00132 QString newName = _name; 00133 newService = _findServiceByDesktopPath(newName.insert(pos, "kde-")); 00134 if (newService) return newService; 00135 00136 delete newService; 00137 newService = 0; 00138 return newService; 00139 } 00140 00141 KService * KServiceFactory::_findServiceByDesktopName(const QString &_name) 00142 { 00143 if (!m_nameDict) return 0; // Error! 00144 00145 // Warning : this assumes we're NOT building a database 00146 // But since findServiceByName isn't called in that case... 00147 // [ see KServiceTypeFactory for how to do it if needed ] 00148 00149 int offset = m_nameDict->find_string( _name ); 00150 if (!offset) return 0; // Not found 00151 00152 KService * newService = createEntry(offset); 00153 00154 // Check whether the dictionary was right. 00155 if (newService && (newService->desktopEntryName() != _name)) 00156 { 00157 // No it wasn't... 00158 delete newService; 00159 newService = 0; // Not found 00160 } 00161 return newService; 00162 } 00163 00164 KService * KServiceFactory::_findServiceByDesktopPath(const QString &_name) 00165 { 00166 if (!m_relNameDict) return 0; // Error! 00167 00168 // Warning : this assumes we're NOT building a database 00169 // But since findServiceByName isn't called in that case... 00170 // [ see KServiceTypeFactory for how to do it if needed ] 00171 00172 int offset = m_relNameDict->find_string( _name ); 00173 if (!offset) return 0; // Not found 00174 00175 KService * newService = createEntry(offset); 00176 00177 // Check whether the dictionary was right. 00178 if (newService && (newService->desktopEntryPath() != _name)) 00179 { 00180 // No it wasn't... 00181 delete newService; 00182 newService = 0; // Not found 00183 } 00184 return newService; 00185 } 00186 00187 KService * KServiceFactory::findServiceByMenuId(const QString &_menuId) 00188 { 00189 if (!m_menuIdDict) return 0; // Error! 00190 00191 // Warning : this assumes we're NOT building a database 00192 // But since findServiceByMenuId isn't called in that case... 00193 // [ see KServiceTypeFactory for how to do it if needed ] 00194 00195 int offset = m_menuIdDict->find_string( _menuId ); 00196 if (!offset) return 0; // Not found 00197 00198 KService * newService = createEntry(offset); 00199 00200 // Check whether the dictionary was right. 00201 if (newService && (newService->menuId() != _menuId)) 00202 { 00203 // No it wasn't... 00204 delete newService; 00205 newService = 0; // Not found 00206 } 00207 return newService; 00208 } 00209 00210 KService* KServiceFactory::createEntry(int offset) 00211 { 00212 KService * newEntry = 0L; 00213 KSycocaType type; 00214 QDataStream *str = KSycoca::self()->findEntry(offset, type); 00215 switch(type) 00216 { 00217 case KST_KService: 00218 newEntry = new KService(*str, offset); 00219 break; 00220 00221 default: 00222 kdError(7011) << QString("KServiceFactory: unexpected object entry in KSycoca database (type = %1)").arg((int)type) << endl; 00223 return 0; 00224 } 00225 if (!newEntry->isValid()) 00226 { 00227 kdError(7011) << "KServiceFactory: corrupt object in KSycoca database!\n" << endl; 00228 delete newEntry; 00229 newEntry = 0; 00230 } 00231 return newEntry; 00232 } 00233 00234 KService::List KServiceFactory::allServices() 00235 { 00236 KService::List result; 00237 KSycocaEntry::List list = allEntries(); 00238 for( KSycocaEntry::List::Iterator it = list.begin(); 00239 it != list.end(); 00240 ++it) 00241 { 00242 KService *newService = dynamic_cast<KService *>((*it).data()); 00243 if (newService) 00244 result.append( KService::Ptr( newService ) ); 00245 } 00246 return result; 00247 } 00248 00249 KService::List KServiceFactory::allInitServices() 00250 { 00251 KService::List list; 00252 if (!m_str) return list; 00253 00254 // Assume we're NOT building a database 00255 00256 m_str->device()->at(m_initListOffset); 00257 Q_INT32 entryCount; 00258 (*m_str) >> entryCount; 00259 00260 Q_INT32 *offsetList = new Q_INT32[entryCount]; 00261 for(int i = 0; i < entryCount; i++) 00262 { 00263 (*m_str) >> offsetList[i]; 00264 } 00265 00266 for(int i = 0; i < entryCount; i++) 00267 { 00268 KService *newEntry = createEntry(offsetList[i]); 00269 if (newEntry) 00270 { 00271 list.append( KService::Ptr( newEntry ) ); 00272 } 00273 } 00274 delete [] offsetList; 00275 return list; 00276 } 00277 00278 KService::List KServiceFactory::offers( int serviceTypeOffset ) 00279 { 00280 KService::List list; 00281 00282 QDataStream *str = m_str; 00283 // Jump to the offer list 00284 str->device()->at( m_offerListOffset ); 00285 00286 Q_INT32 aServiceTypeOffset; 00287 Q_INT32 aServiceOffset; 00288 // We might want to do a binary search instead of a linear search 00289 // since servicetype offsets are sorted. Bah. 00290 while (true) 00291 { 00292 (*str) >> aServiceTypeOffset; 00293 if ( aServiceTypeOffset ) 00294 { 00295 (*str) >> aServiceOffset; 00296 if ( aServiceTypeOffset == serviceTypeOffset ) 00297 { 00298 // Save stream position ! 00299 int savedPos = str->device()->at(); 00300 // Create Service 00301 KService * serv = createEntry( aServiceOffset ); 00302 if (serv) 00303 list.append( KService::Ptr( serv ) ); 00304 // Restore position 00305 str->device()->at( savedPos ); 00306 } else if ( aServiceTypeOffset > (Q_INT32)serviceTypeOffset ) 00307 break; // too far 00308 } 00309 else 00310 break; // 0 => end of list 00311 } 00312 return list; 00313 } 00314 00315 KServiceFactory *KServiceFactory::_self = 0; 00316 00317 void KServiceFactory::virtual_hook( int id, void* data ) 00318 { KSycocaFactory::virtual_hook( id, data ); } 00319