kio Library API Documentation

kuserprofile.cpp

00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999 Torben Weis <weis@kde.org> 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License version 2 as published by the Free Software Foundation; 00007 * 00008 * This library is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Library General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Library General Public License 00014 * along with this library; see the file COPYING.LIB. If not, write to 00015 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00016 * Boston, MA 02111-1307, USA. 00017 **/ 00018 00019 #include "kuserprofile.h" 00020 #include "kservice.h" 00021 #include "kservicetype.h" 00022 #include "kservicetypefactory.h" 00023 00024 #include <kconfig.h> 00025 #include <kapplication.h> 00026 #include <kglobal.h> 00027 #include <kdebug.h> 00028 00029 #include <qtl.h> 00030 00031 template class QPtrList<KServiceTypeProfile>; 00032 00033 /********************************************* 00034 * 00035 * KServiceTypeProfile 00036 * 00037 *********************************************/ 00038 00039 QPtrList<KServiceTypeProfile>* KServiceTypeProfile::s_lstProfiles = 0L; 00040 bool KServiceTypeProfile::s_configurationMode = false; 00041 00042 void KServiceTypeProfile::initStatic() 00043 { 00044 if ( s_lstProfiles ) 00045 return; 00046 00047 // Make sure that a KServiceTypeFactory gets created. 00048 (void) KServiceTypeFactory::self(); 00049 00050 // NOTE: This can't use a static deleter because it somehow is interfered 00051 // with by kdeinit. It causes weird, unpredictable crashes. I think they 00052 // only happen when kdeinit is run, but I'm not entirely sure. Needs more 00053 // investigation I think. 00054 s_lstProfiles = new QPtrList<KServiceTypeProfile>; 00055 00056 KConfig config( "profilerc", true, false); 00057 00058 static const QString & defaultGroup = KGlobal::staticQString("<default>"); 00059 00060 QStringList tmpList = config.groupList(); 00061 for (QStringList::Iterator aIt = tmpList.begin(); 00062 aIt != tmpList.end(); ++aIt) { 00063 if ( *aIt == defaultGroup ) 00064 continue; 00065 00066 config.setGroup( *aIt ); 00067 00068 QString appId = config.readEntry( "Application" ); 00069 00070 KService::Ptr pService = KService::serviceByStorageId(appId); 00071 00072 if ( pService ) { 00073 QString application = pService->name(); 00074 QString type = config.readEntry( "ServiceType" ); 00075 QString type2 = config.readEntry( "GenericServiceType" ); 00076 if (type2.isEmpty()) // compat code 00077 type2 = (pService->type() == "Application") ? "Application" : "KParts/ReadOnlyPart"; 00078 int pref = config.readNumEntry( "Preference" ); 00079 00080 if ( !type.isEmpty() /* && pref >= 0*/ ) // Don't test for pref here. We want those in the list, to mark them as forbidden 00081 { 00082 KServiceTypeProfile* p = 00083 KServiceTypeProfile::serviceTypeProfile( type, type2 ); 00084 00085 if ( !p ) 00086 p = new KServiceTypeProfile( type, type2 ); 00087 00088 bool allow = config.readBoolEntry( "AllowAsDefault" ); 00089 //kdDebug(7014) << "KServiceTypeProfile::initStatic adding service " << application << " to profile for " << type << "," << type2 << " with preference " << pref << endl; 00090 p->addService( application, pref, allow ); 00091 } 00092 } 00093 } 00094 } 00095 00096 //static 00097 KServiceTypeProfile::OfferList KServiceTypeProfile::offers( const QString& _servicetype, const QString& _genericServiceType ) 00098 { 00099 OfferList offers; 00100 QStringList serviceList; 00101 kdDebug(7014) << "KServiceTypeProfile::offers( " << _servicetype << "," << _genericServiceType << " )" << endl; 00102 00103 // Note that KServiceTypeProfile::offers() calls KServiceType::offers(), 00104 // so we _do_ get the new services, that are available but not in the profile. 00105 if ( _genericServiceType.isEmpty() ) 00106 { 00107 initStatic(); 00108 // We want all profiles for servicetype, if we have profiles. 00109 // ## Slow loop, if profilerc is big. We should use a map instead? 00110 QPtrListIterator<KServiceTypeProfile> it( *s_lstProfiles ); 00111 for( ; it.current(); ++it ) 00112 if ( it.current()->m_strServiceType == _servicetype ) 00113 { 00114 offers += it.current()->offers(); 00115 } 00116 //kdDebug(7014) << "Found profile: " << offers.count() << " offers" << endl; 00117 } 00118 else 00119 { 00120 KServiceTypeProfile* profile = serviceTypeProfile( _servicetype, _genericServiceType ); 00121 if ( profile ) 00122 { 00123 //kdDebug(7014) << "Found profile: " << profile->offers().count() << " offers" << endl; 00124 offers += profile->offers(); 00125 } 00126 else 00127 { 00128 // Try the other way round, order is not like size, it doesn't matter. 00129 profile = serviceTypeProfile( _genericServiceType, _servicetype ); 00130 if ( profile ) 00131 { 00132 //kdDebug(7014) << "Found profile after switching: " << profile->offers().count() << " offers" << endl; 00133 offers += profile->offers(); 00134 } 00135 } 00136 } 00137 00138 // Collect services, to make the next loop faster 00139 OfferList::Iterator itOffers = offers.begin(); 00140 for( ; itOffers != offers.end(); ++itOffers ) 00141 serviceList += (*itOffers).service()->desktopEntryPath(); // this should identify each service uniquely 00142 //kdDebug(7014) << "serviceList: " << serviceList.join(",") << endl; 00143 00144 // Now complete with any other offers that aren't in the profile 00145 // This can be because the services have been installed after the profile was written, 00146 // but it's also the case for any service that's neither App nor ReadOnlyPart, e.g. RenameDlg/Plugin 00147 KService::List list = KServiceType::offers( _servicetype ); 00148 //kdDebug(7014) << "Using KServiceType::offers, result: " << list.count() << " offers" << endl; 00149 QValueListIterator<KService::Ptr> it = list.begin(); 00150 for( ; it != list.end(); ++it ) 00151 { 00152 if (_genericServiceType.isEmpty() /*no constraint*/ || (*it)->hasServiceType( _genericServiceType )) 00153 { 00154 // Check that we don't already have it ;) 00155 if ( serviceList.find( (*it)->desktopEntryPath() ) == serviceList.end() ) 00156 { 00157 bool allow = (*it)->allowAsDefault(); 00158 KServiceOffer o( (*it), (*it)->initialPreferenceForMimeType(_servicetype), allow ); 00159 offers.append( o ); 00160 //kdDebug(7014) << "Appending offer " << (*it)->name() << " initial preference=" << (*it)->initialPreference() << " allow-as-default=" << allow << endl; 00161 } 00162 //else 00163 // kdDebug(7014) << "Already having offer " << (*it)->name() << endl; 00164 } 00165 } 00166 00167 qBubbleSort( offers ); 00168 00169 #if 0 00170 // debug code, comment if you wish but don't remove. 00171 kdDebug(7014) << "Sorted list:" << endl; 00172 OfferList::Iterator itOff = offers.begin(); 00173 for( ; itOff != offers.end(); ++itOff ) 00174 kdDebug(7014) << (*itOff).service()->name() << " allow-as-default=" << (*itOff).allowAsDefault() << endl; 00175 #endif 00176 00177 kdDebug(7014) << "Returning " << offers.count() << " offers" << endl; 00178 return offers; 00179 } 00180 00181 KServiceTypeProfile::KServiceTypeProfile( const QString& _servicetype, const QString& _genericServiceType ) 00182 { 00183 initStatic(); 00184 00185 m_strServiceType = _servicetype; 00186 m_strGenericServiceType = _genericServiceType; 00187 00188 s_lstProfiles->append( this ); 00189 } 00190 00191 KServiceTypeProfile::~KServiceTypeProfile() 00192 { 00193 Q_ASSERT( s_lstProfiles ); 00194 00195 s_lstProfiles->removeRef( this ); 00196 } 00197 00198 void KServiceTypeProfile::addService( const QString& _service, 00199 int _preference, bool _allow_as_default ) 00200 { 00201 m_mapServices[ _service ].m_iPreference = _preference; 00202 m_mapServices[ _service ].m_bAllowAsDefault = _allow_as_default; 00203 } 00204 00205 int KServiceTypeProfile::preference( const QString& _service ) const 00206 { 00207 QMap<QString,Service>::ConstIterator it = m_mapServices.find( _service ); 00208 if ( it == m_mapServices.end() ) 00209 return 0; 00210 00211 return it.data().m_iPreference; 00212 } 00213 00214 bool KServiceTypeProfile::allowAsDefault( const QString& _service ) const 00215 { 00216 // Does the service itself not allow that ? 00217 KService::Ptr s = KService::serviceByName( _service ); 00218 if ( s && !s->allowAsDefault() ) 00219 return false; 00220 00221 // Look what the user says ... 00222 QMap<QString,Service>::ConstIterator it = m_mapServices.find( _service ); 00223 if ( it == m_mapServices.end() ) 00224 return 0; 00225 00226 return it.data().m_bAllowAsDefault; 00227 } 00228 00229 KServiceTypeProfile* KServiceTypeProfile::serviceTypeProfile( const QString& _servicetype, const QString& _genericServiceType ) 00230 { 00231 initStatic(); 00232 static const QString& app_str = KGlobal::staticQString("Application"); 00233 00234 const QString &_genservicetype = ((!_genericServiceType.isEmpty()) ? _genericServiceType : app_str); 00235 00236 QPtrListIterator<KServiceTypeProfile> it( *s_lstProfiles ); 00237 for( ; it.current(); ++it ) 00238 if (( it.current()->m_strServiceType == _servicetype ) && 00239 ( it.current()->m_strGenericServiceType == _genservicetype)) 00240 return it.current(); 00241 00242 return 0; 00243 } 00244 00245 00246 KServiceTypeProfile::OfferList KServiceTypeProfile::offers() const 00247 { 00248 OfferList offers; 00249 00250 kdDebug(7014) << "KServiceTypeProfile::offers serviceType=" << m_strServiceType << " genericServiceType=" << m_strGenericServiceType << endl; 00251 KService::List list = KServiceType::offers( m_strServiceType ); 00252 QValueListIterator<KService::Ptr> it = list.begin(); 00253 for( ; it != list.end(); ++it ) 00254 { 00255 //kdDebug(7014) << "KServiceTypeProfile::offers considering " << (*it)->name() << endl; 00256 if ( m_strGenericServiceType.isEmpty() || (*it)->hasServiceType( m_strGenericServiceType ) ) 00257 { 00258 // Now look into the profile, to find this service's preference. 00259 QMap<QString,Service>::ConstIterator it2 = m_mapServices.find( (*it)->name() ); 00260 00261 if( it2 != m_mapServices.end() ) 00262 { 00263 //kdDebug(7014) << "found in mapServices pref=" << it2.data().m_iPreference << endl; 00264 if ( it2.data().m_iPreference > 0 ) { 00265 bool allow = (*it)->allowAsDefault(); 00266 if ( allow ) 00267 allow = it2.data().m_bAllowAsDefault; 00268 KServiceOffer o( (*it), it2.data().m_iPreference, allow ); 00269 offers.append( o ); 00270 } 00271 } 00272 else 00273 { 00274 //kdDebug(7014) << "not found in mapServices. Appending." << endl; 00275 // We use 0 as the preference to ensure new apps don't take over existing apps (which default to 1) 00276 KServiceOffer o( (*it), 0, (*it)->allowAsDefault() ); 00277 offers.append( o ); 00278 } 00279 }/* else 00280 kdDebug(7014) << "Doesn't have " << m_strGenericServiceType << endl;*/ 00281 } 00282 00283 qBubbleSort( offers ); 00284 00285 //kdDebug(7014) << "KServiceTypeProfile::offers returning " << offers.count() << " offers" << endl; 00286 return offers; 00287 } 00288 00289 KService::Ptr KServiceTypeProfile::preferredService( const QString & _serviceType, const QString & _genericServiceType ) 00290 { 00291 OfferList lst = offers( _serviceType, _genericServiceType ); 00292 00293 OfferList::Iterator itOff = lst.begin(); 00294 // Look for the first one that is allowed as default. 00295 // Since the allowed-as-default are first anyway, we only have 00296 // to look at the first one to know. 00297 if( itOff != lst.end() && (*itOff).allowAsDefault() ) 00298 return (*itOff).service(); 00299 00300 kdDebug(7014) << "No offers, or none allowed as default" << endl; 00301 return 0L; 00302 } 00303 00304 /********************************************* 00305 * 00306 * KServiceOffer 00307 * 00308 *********************************************/ 00309 00310 KServiceOffer::KServiceOffer() 00311 { 00312 m_iPreference = -1; 00313 } 00314 00315 KServiceOffer::KServiceOffer( const KServiceOffer& _o ) 00316 { 00317 m_pService = _o.m_pService; 00318 m_iPreference = _o.m_iPreference; 00319 m_bAllowAsDefault = _o.m_bAllowAsDefault; 00320 } 00321 00322 KServiceOffer::KServiceOffer( KService::Ptr _service, int _pref, bool _default ) 00323 { 00324 m_pService = _service; 00325 m_iPreference = _pref; 00326 m_bAllowAsDefault = _default; 00327 } 00328 00329 00330 bool KServiceOffer::operator< ( const KServiceOffer& _o ) const 00331 { 00332 // Put offers allowed as default FIRST. 00333 if ( _o.m_bAllowAsDefault && !m_bAllowAsDefault ) 00334 return false; // _o is default and not 'this'. 00335 if ( !_o.m_bAllowAsDefault && m_bAllowAsDefault ) 00336 return true; // 'this' is default but not _o. 00337 // Both offers are allowed or not allowed as default 00338 // -> use preferences to sort them 00339 // The bigger the better, but we want the better FIRST 00340 return _o.m_iPreference < m_iPreference; 00341 }
KDE Logo
This file is part of the documentation for kio Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Aug 30 22:54:43 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003