00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kuserprofile.h"
00020 #include "kservice.h"
00021 #include "kservicetype.h"
00022 #include "kservicetypefactory.h"
00023 #include "kstandarddirs.h"
00024
00025 #include <kconfig.h>
00026 #include <kapplication.h>
00027 #include <kglobal.h>
00028 #include <kdebug.h>
00029 #include <kstaticdeleter.h>
00030
00031 #include <qtl.h>
00032
00033 #include <qvaluelist.h>
00034 template class QPtrList<KServiceTypeProfile>;
00035 typedef QPtrList<KServiceTypeProfile> KServiceTypeProfileList;
00036
00037
00038
00039
00040
00041
00042
00043 KServiceTypeProfileList* KServiceTypeProfile::s_lstProfiles = 0L;
00044 static KStaticDeleter< KServiceTypeProfileList > profileDeleter;
00045 bool KServiceTypeProfile::s_configurationMode = false;
00046
00047 void KServiceTypeProfile::initStatic()
00048 {
00049 if ( s_lstProfiles )
00050 return;
00051 kdDebug(7014) << "KServiceTypeProfile::initStatic" << endl;
00052
00053
00054 (void) KServiceTypeFactory::self();
00055
00056 profileDeleter.setObject(s_lstProfiles, new KServiceTypeProfileList);
00057 s_lstProfiles->setAutoDelete( true );
00058
00059 KConfig config( "profilerc", true, false);
00060
00061 static const QString & defaultGroup = KGlobal::staticQString("<default>");
00062
00063 QStringList tmpList = config.groupList();
00064 for (QStringList::Iterator aIt = tmpList.begin();
00065 aIt != tmpList.end(); ++aIt) {
00066 if ( *aIt == defaultGroup )
00067 continue;
00068
00069 config.setGroup( *aIt );
00070
00071 QString appId = config.readEntry( "Application" );
00072
00073 KService::Ptr pService = KService::serviceByStorageId(appId);
00074
00075 if ( pService ) {
00076 QString application = pService->storageId();
00077 QString type = config.readEntry( "ServiceType" );
00078 QString type2 = config.readEntry( "GenericServiceType" );
00079 if (type2.isEmpty())
00080 type2 = (pService->type() == "Application") ? "Application" : "KParts/ReadOnlyPart";
00081 int pref = config.readNumEntry( "Preference" );
00082
00083 if ( !type.isEmpty() )
00084 {
00085 KServiceTypeProfile* p =
00086 KServiceTypeProfile::serviceTypeProfile( type, type2 );
00087
00088 if ( !p ) {
00089 p = new KServiceTypeProfile( type, type2 );
00090 s_lstProfiles->append( p );
00091 }
00092
00093 bool allow = config.readBoolEntry( "AllowAsDefault" );
00094 kdDebug(7014) << "KServiceTypeProfile::initStatic adding service " << application << " to profile for "
00095 << type << "," << type2 << " with preference " << pref << endl;
00096 p->addService( application, pref, allow );
00097 }
00098 }
00099 }
00100 initKDE4compatibility();
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 void KServiceTypeProfile::initKDE4compatibility()
00112 {
00113
00114 const QStringList mimeappsFiles = KGlobal::dirs()->findAllResources("xdgdata-apps",
00115 QString::fromLatin1("mimeapps.list"), true, false);
00116 if (mimeappsFiles.isEmpty()) {
00117 kdDebug(7014) << "mimeapps files is empty"<< endl;
00118 return;
00119 }
00120
00121 int basePreference = 1000;
00122 QStringList::const_iterator mimeappsIter = mimeappsFiles.begin();
00123 for ( ; mimeappsIter != mimeappsFiles.end(); mimeappsIter++ )
00124 {
00125 parseMimeAppsList(*(mimeappsIter), basePreference, QString::fromLatin1("Added Associations"));
00126 basePreference -= 50;
00127 }
00128 }
00129 void KServiceTypeProfile::parseMimeAppsList(const QString& file, int basePreference, const QString& group)
00130 {
00131 KConfig applist(file, true, false);
00132 kdDebug(7014) << "KServiceTypeProfile::ParseMimeAppsList" << file << endl;
00133 QMap<QString, QString> mimemapping = applist.entryMap(group);
00134
00135 for (QMap<QString, QString>::Iterator aIt = mimemapping.begin();
00136 aIt != mimemapping.end(); ++aIt) {
00137
00138
00139
00140 kdDebug(7014) << "Found mimetype " << aIt.key() << " Mapping: " << aIt.data() << endl;
00141
00142 QStringList desktopNames = QStringList::split(QString::fromLatin1(";"), aIt.data());
00143 int pref = basePreference;
00144 for (QStringList::const_iterator serviceIt = desktopNames.begin();
00145 serviceIt != desktopNames.end(); serviceIt++) {
00146 KService::Ptr pService = KService::serviceByStorageId(*(serviceIt));
00147 if (!pService) {
00148 kdDebug(7014) << file << " specifies unknown service: "
00149 << *(serviceIt) << " for " << aIt.key() << endl;
00150 } else {
00151 KServiceTypeProfile* p =
00152 KServiceTypeProfile::serviceTypeProfile( aIt.key(), "Application" );
00153
00154 if ( !p ) {
00155 kdDebug(7014) << "Created new ServiceTypeProfile" << endl;
00156 p = new KServiceTypeProfile( aIt.key(), "Application" );
00157 s_lstProfiles->append( p );
00158 }
00159
00160 kdDebug(7014) << "KServiceTypeProfile::parseMimeAppsList adding service " << *(serviceIt)
00161 << " to profile for " << aIt.key() << " with preference " << pref << endl;
00162 p->addService(*(serviceIt), pref, true);
00163 --pref;
00164 }
00165 }
00166 }
00167 }
00168
00169
00170
00171 void KServiceTypeProfile::clear()
00172 {
00173
00174
00175
00176 if( s_lstProfiles == NULL || s_lstProfiles->count() == 0 )
00177 return;
00178 profileDeleter.destructObject();
00179 }
00180
00181
00182 KServiceTypeProfile::OfferList KServiceTypeProfile::offers( const QString& _servicetype, const QString& _genericServiceType )
00183 {
00184 OfferList offers;
00185 QStringList serviceList;
00186
00187
00188
00189
00190 if ( _genericServiceType.isEmpty() )
00191 {
00192 initStatic();
00193
00194
00195 QPtrListIterator<KServiceTypeProfile> it( *s_lstProfiles );
00196 for( ; it.current(); ++it )
00197 if ( it.current()->m_strServiceType == _servicetype )
00198 {
00199 offers += it.current()->offers();
00200 }
00201
00202 }
00203 else
00204 {
00205 KServiceTypeProfile* profile = serviceTypeProfile( _servicetype, _genericServiceType );
00206 if ( profile )
00207 {
00208
00209 offers += profile->offers();
00210 }
00211 else
00212 {
00213
00214 profile = serviceTypeProfile( _genericServiceType, _servicetype );
00215 if ( profile )
00216 {
00217
00218 offers += profile->offers();
00219 }
00220 }
00221 }
00222
00223
00224 OfferList::Iterator itOffers = offers.begin();
00225 for( ; itOffers != offers.end(); ++itOffers )
00226 serviceList += (*itOffers).service()->desktopEntryPath();
00227 kdDebug(7014) << "serviceList: " << serviceList.join(",") << endl;
00228
00229
00230
00231
00232 KService::List list = KServiceType::offers( _servicetype );
00233
00234 QValueListIterator<KService::Ptr> it = list.begin();
00235 for( ; it != list.end(); ++it )
00236 {
00237 if (_genericServiceType.isEmpty() || (*it)->hasServiceType( _genericServiceType ))
00238 {
00239
00240 if ( serviceList.find( (*it)->desktopEntryPath() ) == serviceList.end() )
00241 {
00242 bool allow = (*it)->allowAsDefault();
00243 KServiceOffer o( (*it), (*it)->initialPreferenceForMimeType(_servicetype), allow );
00244 offers.append( o );
00245
00246 }
00247
00248
00249 }
00250 }
00251
00252 qBubbleSort( offers );
00253
00254 #if 1
00255
00256 kdDebug(7014) << "Sorted list:" << endl;
00257 OfferList::Iterator itOff = offers.begin();
00258 for( ; itOff != offers.end(); ++itOff )
00259 kdDebug(7014) << (*itOff).service()->name() << " allow-as-default=" << (*itOff).allowAsDefault() << endl;
00260 #endif
00261
00262 kdDebug(7014) << "Returning " << offers.count() << " offers" << endl;
00263 return offers;
00264 }
00265
00266 KServiceTypeProfile::KServiceTypeProfile( const QString& _servicetype, const QString& _genericServiceType )
00267 {
00268 initStatic();
00269
00270 m_strServiceType = _servicetype;
00271 m_strGenericServiceType = _genericServiceType;
00272 }
00273
00274 KServiceTypeProfile::~KServiceTypeProfile()
00275 {
00276 }
00277
00278 void KServiceTypeProfile::addService( const QString& _service,
00279 int _preference, bool _allow_as_default )
00280 {
00281 m_mapServices[ _service ].m_iPreference = _preference;
00282 m_mapServices[ _service ].m_bAllowAsDefault = _allow_as_default;
00283 }
00284
00285 int KServiceTypeProfile::preference( const QString& _service ) const
00286 {
00287 KService::Ptr service = KService::serviceByName( _service );
00288 if (!service)
00289 return 0;
00290 QMap<QString,Service>::ConstIterator it = m_mapServices.find( service->storageId() );
00291 if ( it == m_mapServices.end() )
00292 return 0;
00293
00294 return it.data().m_iPreference;
00295 }
00296
00297 bool KServiceTypeProfile::allowAsDefault( const QString& _service ) const
00298 {
00299 KService::Ptr service = KService::serviceByName( _service );
00300 if (!service)
00301 return false;
00302
00303
00304 if ( !service->allowAsDefault() )
00305 return false;
00306
00307
00308 QMap<QString,Service>::ConstIterator it = m_mapServices.find( service->storageId() );
00309 if ( it == m_mapServices.end() )
00310 return 0;
00311
00312 return it.data().m_bAllowAsDefault;
00313 }
00314
00315 KServiceTypeProfile* KServiceTypeProfile::serviceTypeProfile( const QString& _servicetype, const QString& _genericServiceType )
00316 {
00317 initStatic();
00318 static const QString& app_str = KGlobal::staticQString("Application");
00319
00320 const QString &_genservicetype = ((!_genericServiceType.isEmpty()) ? _genericServiceType : app_str);
00321
00322 QPtrListIterator<KServiceTypeProfile> it( *s_lstProfiles );
00323 for( ; it.current(); ++it )
00324 if (( it.current()->m_strServiceType == _servicetype ) &&
00325 ( it.current()->m_strGenericServiceType == _genservicetype))
00326 return it.current();
00327
00328 return 0;
00329 }
00330
00331
00332 KServiceTypeProfile::OfferList KServiceTypeProfile::offers() const
00333 {
00334 OfferList offers;
00335
00336
00337 KService::List list = KServiceType::offers( m_strServiceType );
00338
00339
00340
00341
00342
00343
00344
00345
00346 QMapConstIterator<QString, Service> mapIt = m_mapServices.constBegin();
00347 for ( ; mapIt != m_mapServices.end(); mapIt++ ) {
00348 KService::Ptr pService = KService::serviceByStorageId(mapIt.key());
00349 if ( pService ) {
00350
00351
00352 list.append(pService);
00353 } else {
00354 kdDebug(7014) << mapIt.key() << " specifies unknown service in service map for "
00355 << m_strServiceType << endl;
00356 }
00357 }
00358
00359 QValueListIterator<KService::Ptr> it = list.begin();
00360 for( ; it != list.end(); ++it )
00361 {
00362 kdDebug(7014) << "KServiceTypeProfile::offers() considering " << (*it)->name() << endl;
00363 if ( m_strGenericServiceType.isEmpty() || (*it)->hasServiceType( m_strGenericServiceType ) )
00364 {
00365
00366 QMap<QString,Service>::ConstIterator it2 = m_mapServices.find( (*it)->storageId() );
00367
00368 if( it2 != m_mapServices.end() )
00369 {
00370
00371 if ( it2.data().m_iPreference > 0 ) {
00372 bool allow = (*it)->allowAsDefault();
00373 if ( allow )
00374 allow = it2.data().m_bAllowAsDefault;
00375 KServiceOffer o( (*it), it2.data().m_iPreference, allow );
00376 offers.append( o );
00377 }
00378 }
00379 else
00380 {
00381
00382
00383 KServiceOffer o( (*it), 0, (*it)->allowAsDefault() );
00384 offers.append( o );
00385 }
00386 }
00387
00388 }
00389
00390 qBubbleSort( offers );
00391
00392 kdDebug(7014) << "KServiceTypeProfile::offers returning " << offers.count() << " offers" << endl;
00393 return offers;
00394 }
00395
00396 KService::Ptr KServiceTypeProfile::preferredService( const QString & _serviceType, const QString & _genericServiceType )
00397 {
00398 OfferList lst = offers( _serviceType, _genericServiceType );
00399
00400 OfferList::Iterator itOff = lst.begin();
00401
00402
00403
00404 if( itOff != lst.end() && (*itOff).allowAsDefault() )
00405 return (*itOff).service();
00406
00407 kdDebug(7014) << "No offers, or none allowed as default" << endl;
00408 return 0L;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 KServiceOffer::KServiceOffer()
00418 {
00419 m_iPreference = -1;
00420 }
00421
00422 KServiceOffer::KServiceOffer( const KServiceOffer& _o )
00423 {
00424 m_pService = _o.m_pService;
00425 m_iPreference = _o.m_iPreference;
00426 m_bAllowAsDefault = _o.m_bAllowAsDefault;
00427 }
00428
00429 KServiceOffer::KServiceOffer( KService::Ptr _service, int _pref, bool _default )
00430 {
00431 m_pService = _service;
00432 m_iPreference = _pref;
00433 m_bAllowAsDefault = _default;
00434 }
00435
00436
00437 bool KServiceOffer::operator< ( const KServiceOffer& _o ) const
00438 {
00439
00440 if ( _o.m_bAllowAsDefault && !m_bAllowAsDefault )
00441 return false;
00442 if ( !_o.m_bAllowAsDefault && m_bAllowAsDefault )
00443 return true;
00444
00445
00446
00447 return _o.m_iPreference < m_iPreference;
00448 }