kservicetype.cpp
00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999 Waldo Bastian <bastian@kde.org> 00003 * David Faure <faure@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License version 2 as published by the Free Software Foundation; 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this library; see the file COPYING.LIB. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 **/ 00019 00020 #include "kservice.h" 00021 #include "tdesycoca.h" 00022 #include "kservicetype.h" 00023 #include "kservicetypefactory.h" 00024 #include "kservicefactory.h" 00025 #include "kuserprofile.h" 00026 #include <assert.h> 00027 #include <kdebug.h> 00028 #include <kdesktopfile.h> 00029 00030 class KServiceType::KServiceTypePrivate 00031 { 00032 public: 00033 KServiceTypePrivate() : parentTypeLoaded(false) { } 00034 00035 KServiceType::Ptr parentType; 00036 KService::List services; 00037 bool parentTypeLoaded; 00038 }; 00039 00040 KServiceType::KServiceType( const TQString & _fullpath) 00041 : KSycocaEntry(_fullpath), d(0) 00042 { 00043 KDesktopFile config( _fullpath ); 00044 00045 init(&config); 00046 } 00047 00048 KServiceType::KServiceType( KDesktopFile *config ) 00049 : KSycocaEntry(config->fileName()), d(0) 00050 { 00051 init(config); 00052 } 00053 00054 void 00055 KServiceType::init( KDesktopFile *config) 00056 { 00057 // Is it a mimetype ? 00058 m_strName = config->readEntry( "MimeType" ); 00059 00060 // Or is it a servicetype ? 00061 if ( m_strName.isEmpty() ) 00062 { 00063 m_strName = config->readEntry( "X-TDE-ServiceType" ); 00064 } 00065 00066 m_strComment = config->readComment(); 00067 m_bDeleted = config->readBoolEntry( "Hidden", false ); 00068 m_strIcon = config->readIcon(); 00069 00070 // We store this as property to preserve BC, we can't change that 00071 // because KSycoca needs to remain BC between KDE 2.x and KDE 3.x 00072 TQString sDerived = config->readEntry( "X-TDE-Derived" ); 00073 m_bDerived = !sDerived.isEmpty(); 00074 if ( m_bDerived ) 00075 m_mapProps.insert( "X-TDE-Derived", sDerived ); 00076 00077 TQStringList tmpList = config->groupList(); 00078 TQStringList::Iterator gIt = tmpList.begin(); 00079 00080 for( ; gIt != tmpList.end(); ++gIt ) 00081 { 00082 if ( (*gIt).find( "Property::" ) == 0 ) 00083 { 00084 config->setGroup( *gIt ); 00085 TQVariant v = config->readPropertyEntry( "Value", 00086 TQVariant::nameToType( config->readEntry( "Type" ).ascii() ) ); 00087 if ( v.isValid() ) 00088 m_mapProps.insert( (*gIt).mid( 10 ), v ); 00089 } 00090 } 00091 00092 gIt = tmpList.begin(); 00093 for( ; gIt != tmpList.end(); ++gIt ) 00094 { 00095 if( (*gIt).find( "PropertyDef::" ) == 0 ) 00096 { 00097 config->setGroup( *gIt ); 00098 m_mapPropDefs.insert( (*gIt).mid( 13 ), 00099 TQVariant::nameToType( config->readEntry( "Type" ).ascii() ) ); 00100 } 00101 } 00102 00103 m_bValid = !m_strName.isEmpty(); 00104 } 00105 00106 KServiceType::KServiceType( const TQString & _fullpath, const TQString& _type, 00107 const TQString& _icon, const TQString& _comment ) 00108 : KSycocaEntry(_fullpath), d(0) 00109 { 00110 m_strName = _type; 00111 m_strIcon = _icon; 00112 m_strComment = _comment; 00113 m_bValid = !m_strName.isEmpty(); 00114 } 00115 00116 KServiceType::KServiceType( TQDataStream& _str, int offset ) 00117 : KSycocaEntry( _str, offset ), d(0) 00118 { 00119 load( _str); 00120 } 00121 00122 void 00123 KServiceType::load( TQDataStream& _str ) 00124 { 00125 TQ_INT8 b; 00126 _str >> m_strName >> m_strIcon >> m_strComment >> m_mapProps >> m_mapPropDefs 00127 >> b; 00128 m_bValid = b; 00129 m_bDerived = m_mapProps.contains("X-TDE-Derived"); 00130 } 00131 00132 void 00133 KServiceType::save( TQDataStream& _str ) 00134 { 00135 KSycocaEntry::save( _str ); 00136 // !! This data structure should remain binary compatible at all times !! 00137 // You may add new fields at the end. Make sure to update the version 00138 // number in tdesycoca.h 00139 _str << m_strName << m_strIcon << m_strComment << m_mapProps << m_mapPropDefs 00140 << (TQ_INT8)m_bValid; 00141 } 00142 00143 KServiceType::~KServiceType() 00144 { 00145 delete d; 00146 } 00147 00148 TQString KServiceType::parentServiceType() const 00149 { 00150 TQVariant v = property("X-TDE-Derived"); 00151 return v.toString(); 00152 } 00153 00154 bool KServiceType::inherits( const TQString& servTypeName ) const 00155 { 00156 if ( name() == servTypeName ) 00157 return true; 00158 TQString st = parentServiceType(); 00159 while ( !st.isEmpty() ) 00160 { 00161 KServiceType::Ptr ptr = KServiceType::serviceType( st ); 00162 if (!ptr) return false; //error 00163 if ( ptr->name() == servTypeName ) 00164 return true; 00165 st = ptr->parentServiceType(); 00166 } 00167 return false; 00168 } 00169 00170 TQVariant 00171 KServiceType::property( const TQString& _name ) const 00172 { 00173 TQVariant v; 00174 00175 if ( _name == "Name" ) 00176 v = TQVariant( m_strName ); 00177 else if ( _name == "Icon" ) 00178 v = TQVariant( m_strIcon ); 00179 else if ( _name == "Comment" ) 00180 v = TQVariant( m_strComment ); 00181 else { 00182 TQStringVariantMap::ConstIterator it = m_mapProps.find( _name ); 00183 if ( it != m_mapProps.end() ) 00184 v = it.data(); 00185 } 00186 00187 return v; 00188 } 00189 00190 TQStringList 00191 KServiceType::propertyNames() const 00192 { 00193 TQStringList res; 00194 00195 TQStringVariantMap::ConstIterator it = m_mapProps.begin(); 00196 for( ; it != m_mapProps.end(); ++it ) 00197 res.append( it.key() ); 00198 00199 res.append( "Name" ); 00200 res.append( "Comment" ); 00201 res.append( "Icon" ); 00202 00203 return res; 00204 } 00205 00206 TQVariant::Type 00207 KServiceType::propertyDef( const TQString& _name ) const 00208 { 00209 TQMap<TQString,TQVariant::Type>::ConstIterator it = m_mapPropDefs.find( _name ); 00210 if ( it == m_mapPropDefs.end() ) 00211 return TQVariant::Invalid; 00212 return it.data(); 00213 } 00214 00215 TQStringList 00216 KServiceType::propertyDefNames() const 00217 { 00218 TQStringList l; 00219 00220 TQMap<TQString,TQVariant::Type>::ConstIterator it = m_mapPropDefs.begin(); 00221 for( ; it != m_mapPropDefs.end(); ++it ) 00222 l.append( it.key() ); 00223 00224 return l; 00225 } 00226 00227 KServiceType::Ptr KServiceType::serviceType( const TQString& _name ) 00228 { 00229 KServiceType * p = KServiceTypeFactory::self()->findServiceTypeByName( _name ); 00230 return KServiceType::Ptr( p ); 00231 } 00232 00233 static void addUnique(KService::List &lst, TQDict<KService> &dict, const KService::List &newLst, bool lowPrio) 00234 { 00235 TQValueListConstIterator<KService::Ptr> it = newLst.begin(); 00236 for( ; it != newLst.end(); ++it ) 00237 { 00238 KService *service = static_cast<KService*>(*it); 00239 if (dict.find(service->desktopEntryPath())) 00240 continue; 00241 dict.insert(service->desktopEntryPath(), service); 00242 lst.append(service); 00243 if (lowPrio) 00244 service->setInitialPreference( 0 ); 00245 } 00246 } 00247 00248 KService::List KServiceType::offers( const TQString& _servicetype ) 00249 { 00250 TQDict<KService> dict(53); 00251 KService::List lst; 00252 00253 // Services associated directly with this servicetype (the normal case) 00254 KServiceType::Ptr serv = KServiceTypeFactory::self()->findServiceTypeByName( _servicetype ); 00255 if ( serv ) 00256 addUnique(lst, dict, KServiceFactory::self()->offers( serv->offset() ), false); 00257 else 00258 kdWarning(7009) << "KServiceType::offers : servicetype " << _servicetype << " not found" << endl; 00259 00260 // Find services associated with any mimetype parents. e.g. text/x-java -> text/plain 00261 KMimeType::Ptr mime = dynamic_cast<KMimeType*>(static_cast<KServiceType *>(serv)); 00262 bool isAMimeType = (mime != 0); 00263 if (mime) 00264 { 00265 while(true) 00266 { 00267 TQString parent = mime->parentMimeType(); 00268 if (parent.isEmpty()) 00269 break; 00270 mime = dynamic_cast<KMimeType *>(KServiceTypeFactory::self()->findServiceTypeByName( parent )); 00271 if (!mime) 00272 break; 00273 00274 addUnique(lst, dict, KServiceFactory::self()->offers( mime->offset() ), false); 00275 } 00276 } 00277 serv = mime = 0; 00278 00279 //TQValueListIterator<KService::Ptr> it = lst.begin(); 00280 //for( ; it != lst.end(); ++it ) 00281 // kdDebug() << (*it).data() << " " << (*it)->name() << endl; 00282 00283 // Support for all/* is deactivated by KServiceTypeProfile::configurationMode() 00284 // (and makes no sense when querying for an "all" servicetype itself 00285 // nor for non-mimetypes service types) 00286 if ( !KServiceTypeProfile::configurationMode() 00287 && isAMimeType 00288 && _servicetype.left(4) != "all/" ) 00289 { 00290 // Support for services associated with "all" 00291 KServiceType * servAll = KServiceTypeFactory::self()->findServiceTypeByName( "all/all" ); 00292 if ( servAll ) 00293 { 00294 addUnique(lst, dict, KServiceFactory::self()->offers( servAll->offset() ), true); 00295 } 00296 else 00297 kdWarning(7009) << "KServiceType::offers : servicetype all/all not found" << endl; 00298 delete servAll; 00299 00300 // Support for services associated with "allfiles" 00301 if ( _servicetype != "inode/directory" && _servicetype != "inode/directory-locked" ) 00302 { 00303 KServiceType * servAllFiles = KServiceTypeFactory::self()->findServiceTypeByName( "all/allfiles" ); 00304 if ( servAllFiles ) 00305 { 00306 addUnique(lst, dict, KServiceFactory::self()->offers( servAllFiles->offset() ), true); 00307 } 00308 else 00309 kdWarning(7009) << "KServiceType::offers : servicetype all/allfiles not found" << endl; 00310 delete servAllFiles; 00311 } 00312 } 00313 00314 return lst; 00315 } 00316 00317 KServiceType::List KServiceType::allServiceTypes() 00318 { 00319 return KServiceTypeFactory::self()->allServiceTypes(); 00320 } 00321 00322 KServiceType::Ptr KServiceType::parentType() 00323 { 00324 if (d && d->parentTypeLoaded) 00325 return d->parentType; 00326 00327 if (!d) 00328 d = new KServiceTypePrivate; 00329 00330 TQString parentSt = parentServiceType(); 00331 if (!parentSt.isEmpty()) 00332 { 00333 d->parentType = KServiceTypeFactory::self()->findServiceTypeByName( parentSt ); 00334 if (!d->parentType) 00335 kdWarning(7009) << "'" << desktopEntryPath() << "' specifies undefined mimetype/servicetype '"<< parentSt << "'" << endl; 00336 } 00337 00338 d->parentTypeLoaded = true; 00339 00340 return d->parentType; 00341 } 00342 00343 void KServiceType::addService(KService::Ptr service) 00344 { 00345 if (!d) 00346 d = new KServiceTypePrivate; 00347 00348 if (d->services.count() && d->services.last() == service) 00349 return; 00350 00351 d->services.append(service); 00352 } 00353 00354 KService::List KServiceType::services() 00355 { 00356 if (d) 00357 return d->services; 00358 00359 return KService::List(); 00360 } 00361 00362 void KServiceType::virtual_hook( int id, void* data ) 00363 { KSycocaEntry::virtual_hook( id, data ); }
Trinity API Reference