You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
8.3 KiB
277 lines
8.3 KiB
/* 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 "kbuildservicetypefactory.h"
|
|
#include "ksycoca.h"
|
|
#include "ksycocadict.h"
|
|
#include "kresourcelist.h"
|
|
|
|
#include <kglobal.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kmessageboxwrapper.h>
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
#include <assert.h>
|
|
#include <kdesktopfile.h>
|
|
|
|
template class TQDict<KMimeType>;
|
|
|
|
KBuildServiceTypeFactory::KBuildServiceTypeFactory() :
|
|
KServiceTypeFactory()
|
|
{
|
|
// Read servicetypes first, since they might be needed to read mimetype properties
|
|
m_resourceList = new KSycocaResourceList;
|
|
m_resourceList->add("servicetypes", "*.desktop");
|
|
m_resourceList->add("servicetypes", "*.kdelnk");
|
|
m_resourceList->add( "mime", "*.desktop" );
|
|
m_resourceList->add( "mime", "*.kdelnk" );
|
|
}
|
|
|
|
// return all service types for this factory
|
|
// i.e. first arguments to m_resourceList->add() above
|
|
TQStringList KBuildServiceTypeFactory::resourceTypes()
|
|
{
|
|
return TQStringList() << "servicetypes" << "mime";
|
|
}
|
|
|
|
KBuildServiceTypeFactory::~KBuildServiceTypeFactory()
|
|
{
|
|
delete m_resourceList;
|
|
}
|
|
|
|
KServiceType * KBuildServiceTypeFactory::findServiceTypeByName(const TQString &_name)
|
|
{
|
|
assert (KSycoca::self()->isBuilding());
|
|
// We're building a database - the service type must be in memory
|
|
KSycocaEntry::Ptr * servType = (*m_entryDict)[ _name ];
|
|
if (!servType)
|
|
return 0;
|
|
return (KServiceType *) ((KSycocaEntry*)*servType);
|
|
}
|
|
|
|
|
|
KSycocaEntry *
|
|
KBuildServiceTypeFactory::createEntry(const TQString &file, const char *resource)
|
|
{
|
|
TQString name = file;
|
|
int pos = name.findRev('/');
|
|
if (pos != -1)
|
|
{
|
|
name = name.mid(pos+1);
|
|
}
|
|
|
|
if (name.isEmpty())
|
|
return 0;
|
|
|
|
KDesktopFile desktopFile(file, true, resource);
|
|
|
|
if ( desktopFile.readBoolEntry( "Hidden", false ) == true )
|
|
return 0;
|
|
|
|
// TODO check Type field first
|
|
TQString mime = desktopFile.readEntry( "MimeType" );
|
|
TQString service = desktopFile.readEntry( "X-KDE-ServiceType" );
|
|
|
|
if ( mime.isEmpty() && service.isEmpty() )
|
|
{
|
|
TQString tmp = TQString("The service/mime type config file\n%1\n"
|
|
"does not contain a ServiceType=...\nor MimeType=... entry").arg( file );
|
|
kdWarning(7012) << tmp << endl;
|
|
return 0;
|
|
}
|
|
|
|
KServiceType* e;
|
|
if ( mime == "inode/directory" )
|
|
e = new KFolderType( &desktopFile );
|
|
else if ( (mime == "application/x-desktop")
|
|
|| (mime == "media/builtin-mydocuments")
|
|
|| (mime == "media/builtin-mycomputer")
|
|
|| (mime == "media/builtin-mynetworkplaces")
|
|
|| (mime == "media/builtin-printers")
|
|
|| (mime == "media/builtin-trash")
|
|
|| (mime == "media/builtin-webbrowser") )
|
|
e = new KDEDesktopMimeType( &desktopFile );
|
|
else if ( mime == "application/x-executable" || mime == "application/x-shellscript" )
|
|
e = new KExecMimeType( &desktopFile );
|
|
else if ( !mime.isEmpty() )
|
|
e = new KMimeType( &desktopFile );
|
|
else
|
|
e = new KServiceType( &desktopFile );
|
|
|
|
if (e->isDeleted())
|
|
{
|
|
delete e;
|
|
return 0;
|
|
}
|
|
|
|
if ( !(e->isValid()) )
|
|
{
|
|
kdWarning(7012) << "Invalid ServiceType : " << file << endl;
|
|
delete e;
|
|
return 0;
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
void
|
|
KBuildServiceTypeFactory::saveHeader(TQDataStream &str)
|
|
{
|
|
KSycocaFactory::saveHeader(str);
|
|
str << (TQ_INT32) m_fastPatternOffset;
|
|
str << (TQ_INT32) m_otherPatternOffset;
|
|
str << (TQ_INT32) m_propertyTypeDict.count();
|
|
|
|
TQMapIterator<TQString, int> it;
|
|
for (it = m_propertyTypeDict.begin(); it != m_propertyTypeDict.end(); ++it)
|
|
{
|
|
str << it.key() << (TQ_INT32)it.data();
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
KBuildServiceTypeFactory::save(TQDataStream &str)
|
|
{
|
|
KSycocaFactory::save(str);
|
|
|
|
savePatternLists(str);
|
|
|
|
int endOfFactoryData = str.tqdevice()->tqat();
|
|
|
|
// Update header (pass #3)
|
|
saveHeader(str);
|
|
|
|
// Seek to end.
|
|
str.tqdevice()->tqat(endOfFactoryData);
|
|
}
|
|
|
|
void
|
|
KBuildServiceTypeFactory::savePatternLists(TQDataStream &str)
|
|
{
|
|
// Store each patterns in one of the 2 string lists (for sorting)
|
|
TQStringList fastPatterns; // for *.a to *.abcd
|
|
TQStringList otherPatterns; // for the rest (core.*, *.tar.bz2, *~) ...
|
|
TQDict<KMimeType> dict;
|
|
|
|
// For each mimetype in servicetypeFactory
|
|
for(TQDictIterator<KSycocaEntry::Ptr> it ( *m_entryDict );
|
|
it.current();
|
|
++it)
|
|
{
|
|
KSycocaEntry *entry = (*it.current());
|
|
if ( entry->isType( KST_KMimeType ) )
|
|
{
|
|
KMimeType *mimeType = (KMimeType *) entry;
|
|
TQStringList pat = mimeType->patterns();
|
|
TQStringList::ConstIterator patit = pat.begin();
|
|
for ( ; patit != pat.end() ; ++patit )
|
|
{
|
|
const TQString &pattern = *patit;
|
|
if ( pattern.findRev('*') == 0
|
|
&& pattern.findRev('.') == 1
|
|
&& pattern.length() <= 6 )
|
|
// it starts with "*.", has no other '*' and no other '.', and is max 6 chars
|
|
// => fast patttern
|
|
fastPatterns.append( pattern );
|
|
else if (!pattern.isEmpty()) // some stupid mimetype files have "Patterns=;"
|
|
otherPatterns.append( pattern );
|
|
// Assumption : there is only one mimetype for that pattern
|
|
// It doesn't really make sense otherwise, anyway.
|
|
dict.replace( pattern, mimeType );
|
|
}
|
|
}
|
|
}
|
|
// Sort the list - the fast one, useless for the other one
|
|
fastPatterns.sort();
|
|
|
|
TQ_INT32 entrySize = 0;
|
|
TQ_INT32 nrOfEntries = 0;
|
|
|
|
m_fastPatternOffset = str.tqdevice()->tqat();
|
|
|
|
// Write out fastPatternHeader (Pass #1)
|
|
str.tqdevice()->tqat(m_fastPatternOffset);
|
|
str << nrOfEntries;
|
|
str << entrySize;
|
|
|
|
// For each fast pattern
|
|
TQStringList::ConstIterator it = fastPatterns.begin();
|
|
for ( ; it != fastPatterns.end() ; ++it )
|
|
{
|
|
int start = str.tqdevice()->tqat();
|
|
// Justify to 6 chars with spaces, so that the size remains constant
|
|
// in the database file.
|
|
TQString paddedPattern = (*it).leftJustify(6).right(4); // remove leading "*."
|
|
//kdDebug(7021) << TQString("FAST : '%1' '%2'").arg(paddedPattern).arg(dict[(*it)]->name()) << endl;
|
|
str << paddedPattern;
|
|
str << dict[(*it)]->offset();
|
|
entrySize = str.tqdevice()->tqat() - start;
|
|
nrOfEntries++;
|
|
}
|
|
|
|
// store position
|
|
m_otherPatternOffset = str.tqdevice()->tqat();
|
|
|
|
// Write out fastPatternHeader (Pass #2)
|
|
str.tqdevice()->tqat(m_fastPatternOffset);
|
|
str << nrOfEntries;
|
|
str << entrySize;
|
|
|
|
// For the other patterns
|
|
str.tqdevice()->tqat(m_otherPatternOffset);
|
|
|
|
it = otherPatterns.begin();
|
|
for ( ; it != otherPatterns.end() ; ++it )
|
|
{
|
|
//kdDebug(7021) << TQString("OTHER : '%1' '%2'").arg(*it).arg(dict[(*it)]->name()) << endl;
|
|
str << (*it);
|
|
str << dict[(*it)]->offset();
|
|
}
|
|
|
|
str << TQString(""); // end of list marker (has to be a string !)
|
|
}
|
|
|
|
void
|
|
KBuildServiceTypeFactory::addEntry(KSycocaEntry *newEntry, const char *resource)
|
|
{
|
|
KServiceType * serviceType = (KServiceType *) newEntry;
|
|
if ( (*m_entryDict)[ newEntry->name() ] )
|
|
{
|
|
// Already exists
|
|
if (serviceType->desktopEntryPath().endsWith("kdelnk"))
|
|
return; // Skip
|
|
|
|
// Replace
|
|
KSycocaFactory::removeEntry(newEntry);
|
|
}
|
|
KSycocaFactory::addEntry(newEntry, resource);
|
|
|
|
|
|
const TQMap<TQString,TQVariant::Type>& pd = serviceType->propertyDefs();
|
|
TQMap<TQString,TQVariant::Type>::ConstIterator pit = pd.begin();
|
|
for( ; pit != pd.end(); ++pit )
|
|
{
|
|
if (!m_propertyTypeDict.contains(pit.key()))
|
|
m_propertyTypeDict.insert(pit.key(), pit.data());
|
|
else if (m_propertyTypeDict[pit.key()] != pit.data())
|
|
kdWarning(7021) << "Property '"<< pit.key() << "' is defined multiple times ("<< serviceType->name() <<")" <<endl;
|
|
}
|
|
}
|
|
|