kdelibs/kdecore/services/kservicefactory.cpp
Ivailo Monev b0c48bbe79 kdecore: replace QThreadStorage with thread_local
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
2019-05-14 22:55:09 +00:00

314 lines
9.8 KiB
C++

/* This file is part of the KDE libraries
* Copyright (C) 1999-2006 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 "kservicefactory.h"
#include "ksycoca.h"
#include "ksycocatype.h"
#include "ksycocadict_p.h"
#include "kservice.h"
#include <klocale.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kstandarddirs.h>
extern int servicesDebugArea();
thread_local KServiceFactory* kServiceFactoryInstance = 0;
KServiceFactory::KServiceFactory()
: KSycocaFactory( KST_KServiceFactory ),
m_nameDict(0),
m_relNameDict(0),
m_menuIdDict(0)
{
kServiceFactoryInstance = this;
m_offerListOffset = 0;
m_nameDictOffset = 0;
m_relNameDictOffset = 0;
m_menuIdDictOffset = 0;
if (!KSycoca::self()->isBuilding()) {
QDataStream* str = stream();
Q_ASSERT(str);
if (!str)
return;
// Read Header
qint32 i;
(*str) >> i;
m_nameDictOffset = i;
(*str) >> i;
m_relNameDictOffset = i;
(*str) >> i;
m_offerListOffset = i;
(*str) >> i;
m_menuIdDictOffset = i;
const int saveOffset = str->device()->pos();
// Init index tables
m_nameDict = new KSycocaDict(str, m_nameDictOffset);
// Init index tables
m_relNameDict = new KSycocaDict(str, m_relNameDictOffset);
// Init index tables
m_menuIdDict = new KSycocaDict(str, m_menuIdDictOffset);
str->device()->seek(saveOffset);
}
}
KServiceFactory::~KServiceFactory()
{
if (kServiceFactoryInstance) {
kServiceFactoryInstance = 0;
}
delete m_nameDict;
delete m_relNameDict;
delete m_menuIdDict;
}
KServiceFactory * KServiceFactory::self()
{
if (!kServiceFactoryInstance)
kServiceFactoryInstance = new KServiceFactory();
return kServiceFactoryInstance;
}
KService::Ptr KServiceFactory::findServiceByName(const QString &_name)
{
if (!sycocaDict()) return KService::Ptr(); // Error!
// Warning : this assumes we're NOT building a database
// But since findServiceByName isn't called in that case...
// [ see KServiceTypeFactory for how to do it if needed ]
int offset = sycocaDict()->find_string( _name );
if (!offset) return KService::Ptr(); // Not found
KService::Ptr newService(createEntry(offset));
// Check whether the dictionary was right.
if (newService && (newService->name() != _name)) {
// No it wasn't...
return KService::Ptr();
}
return newService;
}
KService::Ptr KServiceFactory::findServiceByDesktopName(const QString &_name)
{
if (!m_nameDict) return KService::Ptr(); // Error!
// Warning : this assumes we're NOT building a database
// KBuildServiceFactory reimplements it for the case where we are building one
int offset = m_nameDict->find_string( _name );
if (!offset) return KService::Ptr(); // Not found
KService::Ptr newService(createEntry(offset));
// Check whether the dictionary was right.
if (newService && (newService->desktopEntryName() != _name)) {
// No it wasn't...
return KService::Ptr();
}
return newService;
}
KService::Ptr KServiceFactory::findServiceByDesktopPath(const QString &_name)
{
if (!m_relNameDict) return KService::Ptr(); // Error!
// Warning : this assumes we're NOT building a database
// KBuildServiceFactory reimplements it for the case where we are building one
int offset = m_relNameDict->find_string( _name );
if (!offset) {
//kDebug(servicesDebugArea()) << "findServiceByDesktopPath:" << _name << "not found";
return KService::Ptr(); // Not found
}
KService::Ptr newService(createEntry(offset));
if (!newService) {
kDebug(servicesDebugArea()) << "findServiceByDesktopPath: createEntry failed!";
}
// Check whether the dictionary was right
// It's ok that it's wrong, for the case where we're looking up an unknown service,
// and the hash value gave us another one.
if (newService && (newService->entryPath() != _name)) {
// No it wasn't...
return KService::Ptr();
}
return newService;
}
KService::Ptr KServiceFactory::findServiceByMenuId(const QString &_menuId)
{
if (!m_menuIdDict) return KService::Ptr(); // Error!
// Warning : this assumes we're NOT building a database
// KBuildServiceFactory reimplements it for the case where we are building one
int offset = m_menuIdDict->find_string( _menuId );
if (!offset) return KService::Ptr(); // Not found
KService::Ptr newService(createEntry(offset));
// Check whether the dictionary was right.
if (newService && (newService->menuId() != _menuId)) {
// No it wasn't...
return KService::Ptr();
}
return newService;
}
KService* KServiceFactory::createEntry(int offset) const
{
KService * newEntry = 0L;
KSycocaType type;
QDataStream *str = KSycoca::self()->findEntry(offset, type);
switch(type) {
case KST_KService:
newEntry = new KService(*str, offset);
break;
default:
kError(7011) << "KServiceFactory: unexpected object entry in KSycoca database (type=" << int(type) << ")";
return 0;
}
if (!newEntry->isValid()) {
kError(7011) << "KServiceFactory: corrupt object in KSycoca database!";
delete newEntry;
newEntry = 0;
}
return newEntry;
}
KService::List KServiceFactory::allServices()
{
KService::List result;
const KSycocaEntry::List list = allEntries();
KSycocaEntry::List::const_iterator it = list.begin();
const KSycocaEntry::List::const_iterator end = list.end();
for( ; it != end; ++it ) {
const KSycocaEntry::Ptr entry = *it;
if ( entry->isType( KST_KService ) )
result.append( KService::Ptr::staticCast( entry ) );
}
return result;
}
QList<KServiceOffer> KServiceFactory::offers( int serviceTypeOffset, int serviceOffersOffset )
{
QList<KServiceOffer> list;
// Jump to the offer list
QDataStream* str = stream();
str->device()->seek( m_offerListOffset + serviceOffersOffset );
qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel;
while (true)
{
(*str) >> aServiceTypeOffset;
if ( aServiceTypeOffset ) {
(*str) >> aServiceOffset;
(*str) >> initialPreference;
(*str) >> mimeTypeInheritanceLevel;
if ( aServiceTypeOffset == serviceTypeOffset ) {
// Save stream position !
const int savedPos = str->device()->pos();
// Create Service
KService * serv = createEntry( aServiceOffset );
if (serv) {
KService::Ptr servPtr( serv );
list.append( KServiceOffer( servPtr, initialPreference, mimeTypeInheritanceLevel, servPtr->allowAsDefault() ) );
}
// Restore position
str->device()->seek( savedPos );
} else
break; // too far
}
else
break; // 0 => end of list
}
return list;
}
KService::List KServiceFactory::serviceOffers( int serviceTypeOffset, int serviceOffersOffset )
{
KService::List list;
// Jump to the offer list
QDataStream* str = stream();
str->device()->seek( m_offerListOffset + serviceOffersOffset );
qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel;
while (true) {
(*str) >> aServiceTypeOffset;
if ( aServiceTypeOffset )
{
(*str) >> aServiceOffset;
(*str) >> initialPreference;
(*str) >> mimeTypeInheritanceLevel;
if ( aServiceTypeOffset == serviceTypeOffset )
{
// Save stream position !
const int savedPos = str->device()->pos();
// Create service
KService * serv = createEntry( aServiceOffset );
if (serv)
list.append( KService::Ptr( serv ) );
// Restore position
str->device()->seek( savedPos );
} else
break; // too far
}
else
break; // 0 => end of list
}
return list;
}
bool KServiceFactory::hasOffer( int serviceTypeOffset, int serviceOffersOffset, int testedServiceOffset )
{
// Save stream position
QDataStream* str = stream();
const int savedPos = str->device()->pos();
// Jump to the offer list
str->device()->seek( m_offerListOffset + serviceOffersOffset );
bool found = false;
qint32 aServiceTypeOffset, aServiceOffset, initialPreference, mimeTypeInheritanceLevel;
while (!found)
{
(*str) >> aServiceTypeOffset;
if ( aServiceTypeOffset ) {
(*str) >> aServiceOffset;
(*str) >> initialPreference;
(*str) >> mimeTypeInheritanceLevel;
if ( aServiceTypeOffset == serviceTypeOffset )
{
if( aServiceOffset == testedServiceOffset )
found = true;
} else
break; // too far
}
else
break; // 0 => end of list
}
// Restore position
str->device()->seek( savedPos );
return found;
}