mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 19:02:48 +00:00
245 lines
6.6 KiB
C++
245 lines
6.6 KiB
C++
/* This file is part of the KDE libraries
|
|
* Copyright (C) 1999 David Faure <faure@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License version 2 as published by the Free Software Foundation;
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "ksycocafactory.h"
|
|
#include "ksycoca.h"
|
|
#include "ksycocatype.h"
|
|
#include "ksycocaentry.h"
|
|
#include "ksycocadict_p.h"
|
|
|
|
#include <config.h>
|
|
#include <kdebug.h>
|
|
|
|
#include <QThread>
|
|
#include <QtCore/QHash>
|
|
|
|
class KSycocaFactory::Private
|
|
{
|
|
public:
|
|
Private() : mOffset(0),
|
|
m_sycocaDictOffset(0),
|
|
m_beginEntryOffset(0),
|
|
m_endEntryOffset(0) {}
|
|
~Private()
|
|
{
|
|
delete m_sycocaDict;
|
|
}
|
|
|
|
int mOffset;
|
|
int m_sycocaDictOffset;
|
|
int m_beginEntryOffset;
|
|
int m_endEntryOffset;
|
|
KSycocaDict *m_sycocaDict;
|
|
};
|
|
|
|
KSycocaFactory::KSycocaFactory(KSycocaFactoryId factory_id)
|
|
: m_resourceList(0), m_entryDict(0), m_str(0), d(new Private)
|
|
{
|
|
if (!KSycoca::self()->isBuilding() && (m_str = KSycoca::self()->findFactory(factory_id))) {
|
|
// Read position of index tables....
|
|
qint32 i;
|
|
(*m_str) >> i;
|
|
d->m_sycocaDictOffset = i;
|
|
(*m_str) >> i;
|
|
d->m_beginEntryOffset = i;
|
|
(*m_str) >> i;
|
|
d->m_endEntryOffset = i;
|
|
|
|
QDataStream* str = stream();
|
|
int saveOffset = str->device()->pos();
|
|
// Init index tables
|
|
d->m_sycocaDict = new KSycocaDict(str, d->m_sycocaDictOffset);
|
|
saveOffset = str->device()->seek(saveOffset);
|
|
} else {
|
|
// We are in kbuildsycoca4 -- build new database!
|
|
m_entryDict = new KSycocaEntryDict;
|
|
d->m_sycocaDict = new KSycocaDict;
|
|
d->m_beginEntryOffset = 0;
|
|
d->m_endEntryOffset = 0;
|
|
|
|
// m_resourceList will be filled in by inherited constructors
|
|
}
|
|
KSycoca::self()->addFactory(this);
|
|
}
|
|
|
|
KSycocaFactory::~KSycocaFactory()
|
|
{
|
|
delete m_entryDict;
|
|
delete d;
|
|
}
|
|
|
|
void
|
|
KSycocaFactory::saveHeader(QDataStream &str)
|
|
{
|
|
// Write header
|
|
str.device()->seek(d->mOffset);
|
|
str << (qint32) d->m_sycocaDictOffset;
|
|
str << (qint32) d->m_beginEntryOffset;
|
|
str << (qint32) d->m_endEntryOffset;
|
|
}
|
|
|
|
void
|
|
KSycocaFactory::save(QDataStream &str)
|
|
{
|
|
if (!m_entryDict) return; // Error! Function should only be called when
|
|
// building database
|
|
if (!d->m_sycocaDict) return; // Error!
|
|
|
|
d->mOffset = str.device()->pos(); // store position in member variable
|
|
d->m_sycocaDictOffset = 0;
|
|
|
|
// Write header (pass #1)
|
|
saveHeader(str);
|
|
|
|
d->m_beginEntryOffset = str.device()->pos();
|
|
|
|
// Write all entries.
|
|
int entryCount = 0;
|
|
for(KSycocaEntryDict::Iterator it = m_entryDict->begin();
|
|
it != m_entryDict->end(); ++it)
|
|
{
|
|
KSycocaEntry::Ptr entry = *it;
|
|
entry->save(str);
|
|
entryCount++;
|
|
}
|
|
|
|
d->m_endEntryOffset = str.device()->pos();
|
|
|
|
// Write indices...
|
|
// Linear index
|
|
str << (qint32) entryCount;
|
|
for(KSycocaEntryDict::Iterator it = m_entryDict->begin();
|
|
it != m_entryDict->end(); ++it)
|
|
{
|
|
str << qint32(it->data()->offset());
|
|
}
|
|
|
|
// Dictionary index
|
|
d->m_sycocaDictOffset = str.device()->pos();
|
|
d->m_sycocaDict->save(str);
|
|
|
|
int endOfFactoryData = str.device()->pos();
|
|
|
|
// Update header (pass #2)
|
|
saveHeader(str);
|
|
|
|
// Seek to end.
|
|
str.device()->seek(endOfFactoryData);
|
|
}
|
|
|
|
void
|
|
KSycocaFactory::addEntry(const KSycocaEntry::Ptr& newEntry)
|
|
{
|
|
if (!m_entryDict) return; // Error! Function should only be called when
|
|
// building database
|
|
|
|
if (!d->m_sycocaDict) return; // Error!
|
|
|
|
KSycocaEntry::Ptr oldEntry = m_entryDict->value(newEntry->storageId());
|
|
if (oldEntry) {
|
|
// Already exists -> replace
|
|
// We found a more-local override, e.g. ~/.local/share/applications/kde4/foo.desktop
|
|
// So forget about the more global file.
|
|
//
|
|
// This can also happen with two .protocol files using the same protocol= entry.
|
|
// If we didn't remove one here, we would end up asserting because save()
|
|
// wasn't called on one of the entries.
|
|
//kDebug(7021) << "removing" << oldEntry.data() << oldEntry->entryPath() << "because of" << newEntry->entryPath() << "they have the same storageId" << newEntry->storageId();
|
|
removeEntry(newEntry->storageId());
|
|
}
|
|
|
|
const QString name = newEntry->storageId();
|
|
m_entryDict->insert( name, newEntry );
|
|
d->m_sycocaDict->add( name, newEntry );
|
|
}
|
|
|
|
void
|
|
KSycocaFactory::removeEntry(const QString& entryName)
|
|
{
|
|
if (!m_entryDict) return; // Error! Function should only be called when
|
|
// building database
|
|
|
|
if (!d->m_sycocaDict) return; // Error!
|
|
|
|
m_entryDict->remove( entryName );
|
|
d->m_sycocaDict->remove( entryName ); // O(N)
|
|
}
|
|
|
|
KSycocaEntry::List KSycocaFactory::allEntries() const
|
|
{
|
|
KSycocaEntry::List list;
|
|
|
|
// Assume we're NOT building a database
|
|
|
|
QDataStream* str = stream();
|
|
if (!str) return list;
|
|
str->device()->seek(d->m_endEntryOffset);
|
|
qint32 entryCount;
|
|
(*str) >> entryCount;
|
|
|
|
if (entryCount > 8192)
|
|
{
|
|
kDebug(7021) << QThread::currentThread() << "error detected in factory" << this;
|
|
KSycoca::flagError();
|
|
return list;
|
|
}
|
|
|
|
// offsetList is needed because createEntry() modifies the stream position
|
|
qint32 *offsetList = new qint32[entryCount];
|
|
for(int i = 0; i < entryCount; i++)
|
|
{
|
|
(*str) >> offsetList[i];
|
|
}
|
|
|
|
for(int i = 0; i < entryCount; i++)
|
|
{
|
|
KSycocaEntry *newEntry = createEntry(offsetList[i]);
|
|
if (newEntry)
|
|
{
|
|
list.append( KSycocaEntry::Ptr( newEntry ) );
|
|
}
|
|
}
|
|
delete [] offsetList;
|
|
return list;
|
|
}
|
|
|
|
int KSycocaFactory::offset() const
|
|
{
|
|
return d->mOffset;
|
|
}
|
|
|
|
const KSycocaResourceList * KSycocaFactory::resourceList() const
|
|
{
|
|
return m_resourceList;
|
|
}
|
|
|
|
const KSycocaDict * KSycocaFactory::sycocaDict() const
|
|
{
|
|
return d->m_sycocaDict;
|
|
}
|
|
|
|
bool KSycocaFactory::isEmpty() const
|
|
{
|
|
return d->m_beginEntryOffset == d->m_endEntryOffset;
|
|
}
|
|
|
|
QDataStream* KSycocaFactory::stream() const
|
|
{
|
|
return m_str;
|
|
}
|
|
|