KDECore
ksycocafactory.cpp
Go to the documentation of this file.
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 "ksycocafactory.h" 00020 #include "ksycoca.h" 00021 #include "ksycocatype.h" 00022 #include "ksycocaentry.h" 00023 #include "ksycocadict_p.h" 00024 00025 #include <config.h> 00026 #include <kdebug.h> 00027 00028 #include <QThread> 00029 #include <QtCore/QHash> 00030 00031 class KSycocaFactory::Private 00032 { 00033 public: 00034 Private() : mOffset(0), 00035 m_sycocaDictOffset(0), 00036 m_beginEntryOffset(0), 00037 m_endEntryOffset(0) {} 00038 ~Private() 00039 { 00040 delete m_sycocaDict; 00041 } 00042 00043 int mOffset; 00044 int m_sycocaDictOffset; 00045 int m_beginEntryOffset; 00046 int m_endEntryOffset; 00047 KSycocaDict *m_sycocaDict; 00048 }; 00049 00050 KSycocaFactory::KSycocaFactory(KSycocaFactoryId factory_id) 00051 : m_resourceList(0), m_entryDict(0), m_str(0), d(new Private) 00052 { 00053 if (!KSycoca::self()->isBuilding() && (m_str = KSycoca::self()->findFactory(factory_id))) { 00054 // Read position of index tables.... 00055 qint32 i; 00056 (*m_str) >> i; 00057 d->m_sycocaDictOffset = i; 00058 (*m_str) >> i; 00059 d->m_beginEntryOffset = i; 00060 (*m_str) >> i; 00061 d->m_endEntryOffset = i; 00062 00063 QDataStream* str = stream(); 00064 int saveOffset = str->device()->pos(); 00065 // Init index tables 00066 d->m_sycocaDict = new KSycocaDict(str, d->m_sycocaDictOffset); 00067 saveOffset = str->device()->seek(saveOffset); 00068 } else { 00069 // We are in kbuildsycoca4 -- build new database! 00070 m_entryDict = new KSycocaEntryDict; 00071 d->m_sycocaDict = new KSycocaDict; 00072 d->m_beginEntryOffset = 0; 00073 d->m_endEntryOffset = 0; 00074 00075 // m_resourceList will be filled in by inherited constructors 00076 } 00077 KSycoca::self()->addFactory(this); 00078 } 00079 00080 KSycocaFactory::~KSycocaFactory() 00081 { 00082 delete m_entryDict; 00083 delete d; 00084 } 00085 00086 void 00087 KSycocaFactory::saveHeader(QDataStream &str) 00088 { 00089 // Write header 00090 str.device()->seek(d->mOffset); 00091 str << (qint32) d->m_sycocaDictOffset; 00092 str << (qint32) d->m_beginEntryOffset; 00093 str << (qint32) d->m_endEntryOffset; 00094 } 00095 00096 void 00097 KSycocaFactory::save(QDataStream &str) 00098 { 00099 if (!m_entryDict) return; // Error! Function should only be called when 00100 // building database 00101 if (!d->m_sycocaDict) return; // Error! 00102 00103 d->mOffset = str.device()->pos(); // store position in member variable 00104 d->m_sycocaDictOffset = 0; 00105 00106 // Write header (pass #1) 00107 saveHeader(str); 00108 00109 d->m_beginEntryOffset = str.device()->pos(); 00110 00111 // Write all entries. 00112 int entryCount = 0; 00113 for(KSycocaEntryDict::Iterator it = m_entryDict->begin(); 00114 it != m_entryDict->end(); ++it) 00115 { 00116 KSycocaEntry::Ptr entry = *it; 00117 entry->save(str); 00118 entryCount++; 00119 } 00120 00121 d->m_endEntryOffset = str.device()->pos(); 00122 00123 // Write indices... 00124 // Linear index 00125 str << (qint32) entryCount; 00126 for(KSycocaEntryDict::Iterator it = m_entryDict->begin(); 00127 it != m_entryDict->end(); ++it) 00128 { 00129 str << qint32(it->data()->offset()); 00130 } 00131 00132 // Dictionary index 00133 d->m_sycocaDictOffset = str.device()->pos(); 00134 d->m_sycocaDict->save(str); 00135 00136 int endOfFactoryData = str.device()->pos(); 00137 00138 // Update header (pass #2) 00139 saveHeader(str); 00140 00141 // Seek to end. 00142 str.device()->seek(endOfFactoryData); 00143 } 00144 00145 void 00146 KSycocaFactory::addEntry(const KSycocaEntry::Ptr& newEntry) 00147 { 00148 if (!m_entryDict) return; // Error! Function should only be called when 00149 // building database 00150 00151 if (!d->m_sycocaDict) return; // Error! 00152 00153 KSycocaEntry::Ptr oldEntry = m_entryDict->value(newEntry->storageId()); 00154 if (oldEntry) { 00155 // Already exists -> replace 00156 // We found a more-local override, e.g. ~/.local/share/applications/kde4/foo.desktop 00157 // So forget about the more global file. 00158 // 00159 // This can also happen with two .protocol files using the same protocol= entry. 00160 // If we didn't remove one here, we would end up asserting because save() 00161 // wasn't called on one of the entries. 00162 //kDebug(7021) << "removing" << oldEntry.data() << oldEntry->entryPath() << "because of" << newEntry->entryPath() << "they have the same storageId" << newEntry->storageId(); 00163 removeEntry(newEntry->storageId()); 00164 } 00165 00166 const QString name = newEntry->storageId(); 00167 m_entryDict->insert( name, newEntry ); 00168 d->m_sycocaDict->add( name, newEntry ); 00169 } 00170 00171 void 00172 KSycocaFactory::removeEntry(const QString& entryName) 00173 { 00174 if (!m_entryDict) return; // Error! Function should only be called when 00175 // building database 00176 00177 if (!d->m_sycocaDict) return; // Error! 00178 00179 m_entryDict->remove( entryName ); 00180 d->m_sycocaDict->remove( entryName ); // O(N) 00181 } 00182 00183 KSycocaEntry::List KSycocaFactory::allEntries() const 00184 { 00185 KSycocaEntry::List list; 00186 00187 // Assume we're NOT building a database 00188 00189 QDataStream* str = stream(); 00190 if (!str) return list; 00191 str->device()->seek(d->m_endEntryOffset); 00192 qint32 entryCount; 00193 (*str) >> entryCount; 00194 00195 if (entryCount > 8192) 00196 { 00197 kDebug(7021) << QThread::currentThread() << "error detected in factory" << this; 00198 KSycoca::flagError(); 00199 return list; 00200 } 00201 00202 // offsetList is needed because createEntry() modifies the stream position 00203 qint32 *offsetList = new qint32[entryCount]; 00204 for(int i = 0; i < entryCount; i++) 00205 { 00206 (*str) >> offsetList[i]; 00207 } 00208 00209 for(int i = 0; i < entryCount; i++) 00210 { 00211 KSycocaEntry *newEntry = createEntry(offsetList[i]); 00212 if (newEntry) 00213 { 00214 list.append( KSycocaEntry::Ptr( newEntry ) ); 00215 } 00216 } 00217 delete [] offsetList; 00218 return list; 00219 } 00220 00221 int KSycocaFactory::offset() const 00222 { 00223 return d->mOffset; 00224 } 00225 00226 const KSycocaResourceList * KSycocaFactory::resourceList() const 00227 { 00228 return m_resourceList; 00229 } 00230 00231 const KSycocaDict * KSycocaFactory::sycocaDict() const 00232 { 00233 return d->m_sycocaDict; 00234 } 00235 00236 bool KSycocaFactory::isEmpty() const 00237 { 00238 return d->m_beginEntryOffset == d->m_endEntryOffset; 00239 } 00240 00241 QDataStream* KSycocaFactory::stream() const 00242 { 00243 return m_str; 00244 } 00245 00246 void KSycocaFactory::virtual_hook( int /*id*/, void* /*data*/) 00247 { /*BASE::virtual_hook( id, data );*/ } 00248
KDE 4.6 API Reference