TDE core libraries
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.

kbuildservicetypefactory.cpp 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* This file is part of the KDE libraries
  2. * Copyright (C) 1999 David Faure <faure@kde.org>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License version 2 as published by the Free Software Foundation;
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Library General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Library General Public License
  14. * along with this library; see the file COPYING.LIB. If not, write to
  15. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. * Boston, MA 02110-1301, USA.
  17. **/
  18. #include "kbuildservicetypefactory.h"
  19. #include "tdesycoca.h"
  20. #include "tdesycocadict.h"
  21. #include "kresourcelist.h"
  22. #include <tdeglobal.h>
  23. #include <kstandarddirs.h>
  24. #include <kmessageboxwrapper.h>
  25. #include <kdebug.h>
  26. #include <tdelocale.h>
  27. #include <assert.h>
  28. #include <kdesktopfile.h>
  29. template class TQDict<KMimeType>;
  30. KBuildServiceTypeFactory::KBuildServiceTypeFactory() :
  31. KServiceTypeFactory()
  32. {
  33. // Read servicetypes first, since they might be needed to read mimetype properties
  34. m_resourceList = new KSycocaResourceList;
  35. m_resourceList->add("servicetypes", "*.desktop");
  36. m_resourceList->add("servicetypes", "*.kdelnk");
  37. m_resourceList->add( "mime", "*.desktop" );
  38. m_resourceList->add( "mime", "*.kdelnk" );
  39. }
  40. // return all service types for this factory
  41. // i.e. first arguments to m_resourceList->add() above
  42. TQStringList KBuildServiceTypeFactory::resourceTypes()
  43. {
  44. return TQStringList() << "servicetypes" << "mime";
  45. }
  46. KBuildServiceTypeFactory::~KBuildServiceTypeFactory()
  47. {
  48. delete m_resourceList;
  49. }
  50. KServiceType * KBuildServiceTypeFactory::findServiceTypeByName(const TQString &_name)
  51. {
  52. assert (KSycoca::self()->isBuilding());
  53. // We're building a database - the service type must be in memory
  54. KSycocaEntry::Ptr * servType = (*m_entryDict)[ _name ];
  55. if (!servType)
  56. return 0;
  57. return (KServiceType *) ((KSycocaEntry*)*servType);
  58. }
  59. KSycocaEntry *
  60. KBuildServiceTypeFactory::createEntry(const TQString &file, const char *resource)
  61. {
  62. TQString name = file;
  63. int pos = name.findRev('/');
  64. if (pos != -1)
  65. {
  66. name = name.mid(pos+1);
  67. }
  68. if (name.isEmpty())
  69. return 0;
  70. KDesktopFile desktopFile(file, true, resource);
  71. if ( desktopFile.readBoolEntry( "Hidden", false ) == true )
  72. return 0;
  73. // TODO check Type field first
  74. TQString mime = desktopFile.readEntry( "MimeType" );
  75. TQString service = desktopFile.readEntry( "X-TDE-ServiceType" );
  76. if ( mime.isEmpty() && service.isEmpty() )
  77. {
  78. TQString tmp = TQString("The service/mime type config file\n%1\n"
  79. "does not contain a ServiceType=...\nor MimeType=... entry").arg( file );
  80. kdWarning(7012) << tmp << endl;
  81. return 0;
  82. }
  83. KServiceType* e;
  84. if ( mime == "inode/directory" )
  85. e = new KFolderType( &desktopFile );
  86. else if ( (mime == "application/x-desktop")
  87. || (mime == "media/builtin-mydocuments")
  88. || (mime == "media/builtin-mycomputer")
  89. || (mime == "media/builtin-mynetworkplaces")
  90. || (mime == "media/builtin-printers")
  91. || (mime == "media/builtin-trash")
  92. || (mime == "media/builtin-webbrowser") )
  93. e = new KDEDesktopMimeType( &desktopFile );
  94. else if ( mime == "application/x-executable" || mime == "application/x-shellscript" )
  95. e = new KExecMimeType( &desktopFile );
  96. else if ( !mime.isEmpty() )
  97. e = new KMimeType( &desktopFile );
  98. else
  99. e = new KServiceType( &desktopFile );
  100. if (e->isDeleted())
  101. {
  102. delete e;
  103. return 0;
  104. }
  105. if ( !(e->isValid()) )
  106. {
  107. kdWarning(7012) << "Invalid ServiceType : " << file << endl;
  108. delete e;
  109. return 0;
  110. }
  111. return e;
  112. }
  113. void
  114. KBuildServiceTypeFactory::saveHeader(TQDataStream &str)
  115. {
  116. KSycocaFactory::saveHeader(str);
  117. str << (TQ_INT32) m_fastPatternOffset;
  118. str << (TQ_INT32) m_otherPatternOffset;
  119. str << (TQ_INT32) m_propertyTypeDict.count();
  120. TQMapIterator<TQString, int> it;
  121. for (it = m_propertyTypeDict.begin(); it != m_propertyTypeDict.end(); ++it)
  122. {
  123. str << it.key() << (TQ_INT32)it.data();
  124. }
  125. }
  126. void
  127. KBuildServiceTypeFactory::save(TQDataStream &str)
  128. {
  129. KSycocaFactory::save(str);
  130. savePatternLists(str);
  131. int endOfFactoryData = str.device()->at();
  132. // Update header (pass #3)
  133. saveHeader(str);
  134. // Seek to end.
  135. str.device()->at(endOfFactoryData);
  136. }
  137. void
  138. KBuildServiceTypeFactory::savePatternLists(TQDataStream &str)
  139. {
  140. // Store each patterns in one of the 2 string lists (for sorting)
  141. TQStringList fastPatterns; // for *.a to *.abcd
  142. TQStringList otherPatterns; // for the rest (core.*, *.tar.bz2, *~) ...
  143. TQDict<KMimeType> dict;
  144. // For each mimetype in servicetypeFactory
  145. for(TQDictIterator<KSycocaEntry::Ptr> it ( *m_entryDict );
  146. it.current();
  147. ++it)
  148. {
  149. KSycocaEntry *entry = (*it.current());
  150. if ( entry->isType( KST_KMimeType ) )
  151. {
  152. KMimeType *mimeType = (KMimeType *) entry;
  153. TQStringList pat = mimeType->patterns();
  154. TQStringList::ConstIterator patit = pat.begin();
  155. for ( ; patit != pat.end() ; ++patit )
  156. {
  157. const TQString &pattern = *patit;
  158. if ( pattern.findRev('*') == 0
  159. && pattern.findRev('.') == 1
  160. && pattern.length() <= 6 )
  161. // it starts with "*.", has no other '*' and no other '.', and is max 6 chars
  162. // => fast patttern
  163. fastPatterns.append( pattern );
  164. else if (!pattern.isEmpty()) // some stupid mimetype files have "Patterns=;"
  165. otherPatterns.append( pattern );
  166. // Assumption : there is only one mimetype for that pattern
  167. // It doesn't really make sense otherwise, anyway.
  168. dict.replace( pattern, mimeType );
  169. }
  170. }
  171. }
  172. // Sort the list - the fast one, useless for the other one
  173. fastPatterns.sort();
  174. TQ_INT32 entrySize = 0;
  175. TQ_INT32 nrOfEntries = 0;
  176. m_fastPatternOffset = str.device()->at();
  177. // Write out fastPatternHeader (Pass #1)
  178. str.device()->at(m_fastPatternOffset);
  179. str << nrOfEntries;
  180. str << entrySize;
  181. // For each fast pattern
  182. TQStringList::ConstIterator it = fastPatterns.begin();
  183. for ( ; it != fastPatterns.end() ; ++it )
  184. {
  185. int start = str.device()->at();
  186. // Justify to 6 chars with spaces, so that the size remains constant
  187. // in the database file.
  188. TQString paddedPattern = (*it).leftJustify(6).right(4); // remove leading "*."
  189. //kdDebug(7021) << TQString("FAST : '%1' '%2'").arg(paddedPattern).arg(dict[(*it)]->name()) << endl;
  190. str << paddedPattern;
  191. str << dict[(*it)]->offset();
  192. entrySize = str.device()->at() - start;
  193. nrOfEntries++;
  194. }
  195. // store position
  196. m_otherPatternOffset = str.device()->at();
  197. // Write out fastPatternHeader (Pass #2)
  198. str.device()->at(m_fastPatternOffset);
  199. str << nrOfEntries;
  200. str << entrySize;
  201. // For the other patterns
  202. str.device()->at(m_otherPatternOffset);
  203. it = otherPatterns.begin();
  204. for ( ; it != otherPatterns.end() ; ++it )
  205. {
  206. //kdDebug(7021) << TQString("OTHER : '%1' '%2'").arg(*it).arg(dict[(*it)]->name()) << endl;
  207. str << (*it);
  208. str << dict[(*it)]->offset();
  209. }
  210. str << TQString(""); // end of list marker (has to be a string !)
  211. }
  212. void
  213. KBuildServiceTypeFactory::addEntry(KSycocaEntry *newEntry, const char *resource)
  214. {
  215. KServiceType * serviceType = (KServiceType *) newEntry;
  216. if ( (*m_entryDict)[ newEntry->name() ] )
  217. {
  218. // Already exists
  219. if (serviceType->desktopEntryPath().endsWith("kdelnk"))
  220. return; // Skip
  221. // Replace
  222. KSycocaFactory::removeEntry(newEntry);
  223. }
  224. KSycocaFactory::addEntry(newEntry, resource);
  225. const TQMap<TQString,TQVariant::Type>& pd = serviceType->propertyDefs();
  226. TQMap<TQString,TQVariant::Type>::ConstIterator pit = pd.begin();
  227. for( ; pit != pd.end(); ++pit )
  228. {
  229. if (!m_propertyTypeDict.contains(pit.key()))
  230. m_propertyTypeDict.insert(pit.key(), pit.data());
  231. else if (m_propertyTypeDict[pit.key()] != pit.data())
  232. kdWarning(7021) << "Property '"<< pit.key() << "' is defined multiple times ("<< serviceType->name() <<")" <<endl;
  233. }
  234. }