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.h" 00024 00025 #include <config.h> 00026 #include <kdebug.h> 00027 00028 #include <QtCore/QMutableStringListIterator> 00029 #include <QtCore/QHash> 00030 00031 class KSycocaFactory::Private 00032 { 00033 public: 00034 Private() {} 00035 ~Private() 00036 { 00037 delete m_sycocaDict; 00038 } 00039 00040 int mOffset; 00041 int m_sycocaDictOffset; 00042 int m_beginEntryOffset; 00043 int m_endEntryOffset; 00044 KSycocaDict *m_sycocaDict; 00045 }; 00046 00047 KSycocaFactory::KSycocaFactory(KSycocaFactoryId factory_id) 00048 : m_resourceList(0), m_entryDict(0), d(new Private) 00049 { 00050 if (!KSycoca::self()->isBuilding() && (m_str = KSycoca::self()->findFactory( factory_id ))) 00051 { 00052 // Read position of index tables.... 00053 qint32 i; 00054 (*m_str) >> i; 00055 d->m_sycocaDictOffset = i; 00056 (*m_str) >> i; 00057 d->m_beginEntryOffset = i; 00058 (*m_str) >> i; 00059 d->m_endEntryOffset = i; 00060 00061 int saveOffset = m_str->device()->pos(); 00062 // Init index tables 00063 d->m_sycocaDict = new KSycocaDict(m_str, d->m_sycocaDictOffset); 00064 saveOffset = m_str->device()->seek(saveOffset); 00065 } 00066 else 00067 { 00068 // Build new database! 00069 m_str = 0; 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 // Note that we use a QMultiHash since there can be several entries 00154 // with the same name (e.g. kfmclient.desktop and konqbrowser.desktop both 00155 // have Name=Konqueror). 00156 00157 const QString name = newEntry->name(); 00158 m_entryDict->insertMulti( name, newEntry ); 00159 d->m_sycocaDict->add( name, newEntry ); 00160 } 00161 00162 void 00163 KSycocaFactory::removeEntry(const QString& entryName) 00164 { 00165 if (!m_entryDict) return; // Error! Function should only be called when 00166 // building database 00167 00168 if (!d->m_sycocaDict) return; // Error! 00169 00170 m_entryDict->remove( entryName ); 00171 d->m_sycocaDict->remove( entryName ); // O(N) 00172 } 00173 00174 KSycocaEntry::List KSycocaFactory::allEntries() const 00175 { 00176 KSycocaEntry::List list; 00177 if (!m_str) return list; 00178 00179 // Assume we're NOT building a database 00180 00181 m_str->device()->seek(d->m_endEntryOffset); 00182 qint32 entryCount; 00183 (*m_str) >> entryCount; 00184 00185 if (entryCount > 8192) 00186 { 00187 KSycoca::flagError(); 00188 return list; 00189 } 00190 00191 // offsetList is needed because createEntry() modifies the stream position 00192 qint32 *offsetList = new qint32[entryCount]; 00193 for(int i = 0; i < entryCount; i++) 00194 { 00195 (*m_str) >> offsetList[i]; 00196 } 00197 00198 for(int i = 0; i < entryCount; i++) 00199 { 00200 KSycocaEntry *newEntry = createEntry(offsetList[i]); 00201 if (newEntry) 00202 { 00203 list.append( KSycocaEntry::Ptr( newEntry ) ); 00204 } 00205 } 00206 delete [] offsetList; 00207 return list; 00208 } 00209 00210 int KSycocaFactory::offset() const 00211 { 00212 return d->mOffset; 00213 } 00214 00215 const KSycocaResourceList * KSycocaFactory::resourceList() const 00216 { 00217 return m_resourceList; 00218 } 00219 00220 const KSycocaDict * KSycocaFactory::sycocaDict() const 00221 { 00222 return d->m_sycocaDict; 00223 } 00224 00225 bool KSycocaFactory::isEmpty() const 00226 { 00227 return d->m_beginEntryOffset == d->m_endEntryOffset; 00228 } 00229 00230 void KSycocaFactory::virtual_hook( int /*id*/, void* /*data*/) 00231 { /*BASE::virtual_hook( id, data );*/ }