kio Library API Documentation

kservice.cpp

00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 1999 - 2001 Waldo Bastian <bastian@kde.org> 00003 * Copyright (C) 1999 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., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 **/ 00019 00020 // $Id: kservice.cpp,v 1.157 2004/09/21 14:39:29 waba Exp $ 00021 00022 #include <config.h> 00023 00024 #include "kservice.h" 00025 #include "kservice_p.h" 00026 00027 #include <sys/types.h> 00028 #include <sys/stat.h> 00029 00030 #include <stddef.h> 00031 #include <unistd.h> 00032 #include <stdlib.h> 00033 00034 #include <qstring.h> 00035 #include <qfile.h> 00036 #include <qdir.h> 00037 #include <qtl.h> 00038 00039 #include <ksimpleconfig.h> 00040 #include <kapplication.h> 00041 #include <kdebug.h> 00042 #include <kdesktopfile.h> 00043 #include <kglobal.h> 00044 #include <kiconloader.h> 00045 #include <klocale.h> 00046 #include <kconfigbase.h> 00047 #include <kstandarddirs.h> 00048 #include <dcopclient.h> 00049 00050 #include "kservicefactory.h" 00051 #include "kservicetypefactory.h" 00052 #include "kservicetype.h" 00053 #include "kuserprofile.h" 00054 #include "ksycoca.h" 00055 00056 class KService::KServicePrivate 00057 { 00058 public: 00059 QStringList categories; 00060 QString menuId; 00061 }; 00062 00063 KService::KService( const QString & _name, const QString &_exec, const QString &_icon) 00064 : KSycocaEntry( QString::null) 00065 { 00066 d = new KServicePrivate; 00067 m_bValid = true; 00068 m_bDeleted = false; 00069 m_strType = "Application"; 00070 m_strName = _name; 00071 m_strExec = _exec; 00072 m_strIcon = _icon; 00073 m_bTerminal = false; 00074 m_bAllowAsDefault = true; 00075 m_initialPreference = 10; 00076 } 00077 00078 00079 KService::KService( const QString & _fullpath ) 00080 : KSycocaEntry( _fullpath) 00081 { 00082 KDesktopFile config( _fullpath ); 00083 00084 init(&config); 00085 } 00086 00087 KService::KService( KDesktopFile *config ) 00088 : KSycocaEntry( config->fileName()) 00089 { 00090 init(config); 00091 } 00092 00093 void 00094 KService::init( KDesktopFile *config ) 00095 { 00096 d = new KServicePrivate; 00097 m_bValid = true; 00098 00099 bool absPath = !QDir::isRelativePath(entryPath()); 00100 00101 config->setDesktopGroup(); 00102 00103 QMap<QString, QString> entryMap = config->entryMap(config->group()); 00104 00105 entryMap.remove("Encoding"); // reserved as part of Desktop Entry Standard 00106 entryMap.remove("Version"); // reserved as part of Desktop Entry Standard 00107 00108 m_bDeleted = config->readBoolEntry( "Hidden", false ); 00109 entryMap.remove("Hidden"); 00110 if (m_bDeleted) 00111 { 00112 m_bValid = false; 00113 return; 00114 } 00115 00116 m_strName = config->readEntry( "Name" ); 00117 entryMap.remove("Name"); 00118 if ( m_strName.isEmpty() ) 00119 { 00120 if (config->readEntry( "Exec" ).isEmpty()) 00121 { 00122 m_bValid = false; 00123 return; 00124 } 00125 // Try to make up a name. 00126 m_strName = entryPath(); 00127 int i = m_strName.findRev('/'); 00128 m_strName = m_strName.mid(i+1); 00129 i = m_strName.findRev('.'); 00130 if (i != -1) 00131 m_strName = m_strName.left(i); 00132 } 00133 00134 m_strType = config->readEntry( "Type" ); 00135 entryMap.remove("Type"); 00136 if ( m_strType.isEmpty() ) 00137 { 00138 /*kdWarning(7012) << "The desktop entry file " << entryPath() 00139 << " has no Type=... entry." 00140 << " It should be \"Application\" or \"Service\"" << endl; 00141 m_bValid = false; 00142 return;*/ 00143 m_strType = "Application"; 00144 } else if ( m_strType != "Application" && m_strType != "Service" ) 00145 { 00146 kdWarning(7012) << "The desktop entry file " << entryPath() 00147 << " has Type=" << m_strType 00148 << " instead of \"Application\" or \"Service\"" << endl; 00149 m_bValid = false; 00150 return; 00151 } 00152 00153 // In case Try Exec is set, check if the application is available 00154 if (!config->tryExec()) { 00155 m_bDeleted = true; 00156 m_bValid = false; 00157 return; 00158 } 00159 00160 QString resource = config->resource(); 00161 00162 if ( (m_strType == "Application") && 00163 (!resource.isEmpty()) && 00164 (resource != "apps") && 00165 !absPath) 00166 { 00167 kdWarning(7012) << "The desktop entry file " << entryPath() 00168 << " has Type=" << m_strType << " but is located under \"" << resource 00169 << "\" instead of \"apps\"" << endl; 00170 m_bValid = false; 00171 return; 00172 } 00173 00174 if ( (m_strType == "Service") && 00175 (!resource.isEmpty()) && 00176 (resource != "services") && 00177 !absPath) 00178 { 00179 kdWarning(7012) << "The desktop entry file " << entryPath() 00180 << " has Type=" << m_strType << " but is located under \"" << resource 00181 << "\" instead of \"services\"" << endl; 00182 m_bValid = false; 00183 return; 00184 } 00185 00186 QString name = entryPath(); 00187 int pos = name.findRev('/'); 00188 if (pos != -1) 00189 name = name.mid(pos+1); 00190 pos = name.find('.'); 00191 if (pos != -1) 00192 name = name.left(pos); 00193 00194 m_strExec = config->readPathEntry( "Exec" ); 00195 entryMap.remove("Exec"); 00196 00197 m_strIcon = config->readEntry( "Icon", "unknown" ); 00198 entryMap.remove("Icon"); 00199 m_bTerminal = (config->readBoolEntry( "Terminal" )); // should be a property IMHO 00200 entryMap.remove("Terminal"); 00201 m_strTerminalOptions = config->readEntry( "TerminalOptions" ); // should be a property IMHO 00202 entryMap.remove("TerminalOptions"); 00203 m_strPath = config->readPathEntry( "Path" ); 00204 entryMap.remove("Path"); 00205 m_strComment = config->readEntry( "Comment" ); 00206 entryMap.remove("Comment"); 00207 m_strGenName = config->readEntry( "GenericName" ); 00208 entryMap.remove("GenericName"); 00209 QString untranslatedGenericName = config->readEntryUntranslated( "GenericName" ); 00210 entryMap.insert("UntranslatedGenericName", untranslatedGenericName); 00211 00212 m_lstKeywords = config->readListEntry("Keywords"); 00213 entryMap.remove("Keywords"); 00214 d->categories = config->readListEntry("Categories", ';'); 00215 entryMap.remove("Categories"); 00216 m_strLibrary = config->readEntry( "X-KDE-Library" ); 00217 entryMap.remove("X-KDE-Library"); 00218 m_strInit = config->readEntry("X-KDE-Init" ); 00219 entryMap.remove("X-KDE-Init"); 00220 00221 m_lstServiceTypes = config->readListEntry( "ServiceTypes" ); 00222 entryMap.remove("ServiceTypes"); 00223 // For compatibility with KDE 1.x 00224 m_lstServiceTypes += config->readListEntry( "MimeType", ';' ); 00225 entryMap.remove("MimeType"); 00226 00227 if ( m_strType == "Application" && !m_lstServiceTypes.contains("Application") ) 00228 // Applications implement the service type "Application" ;-) 00229 m_lstServiceTypes += "Application"; 00230 00231 QString dcopServiceType = config->readEntry("X-DCOP-ServiceType").lower(); 00232 entryMap.remove("X-DCOP-ServiceType"); 00233 if (dcopServiceType == "unique") 00234 m_DCOPServiceType = DCOP_Unique; 00235 else if (dcopServiceType == "multi") 00236 m_DCOPServiceType = DCOP_Multi; 00237 else if (dcopServiceType == "wait") 00238 m_DCOPServiceType = DCOP_Wait; 00239 else 00240 m_DCOPServiceType = DCOP_None; 00241 00242 m_strDesktopEntryName = name.lower(); 00243 00244 m_bAllowAsDefault = config->readBoolEntry( "AllowDefault", true ); 00245 entryMap.remove("AllowDefault"); 00246 00247 m_initialPreference = config->readNumEntry( "InitialPreference", 1 ); 00248 entryMap.remove("InitialPreference"); 00249 00250 // Store all additional entries in the property map. 00251 // A QMap<QString,QString> would be easier for this but we can't 00252 // brake BC, so we have to store it in m_mapProps. 00253 // qWarning("Path = %s", entryPath().latin1()); 00254 QMap<QString,QString>::ConstIterator it = entryMap.begin(); 00255 for( ; it != entryMap.end();++it) 00256 { 00257 // qWarning(" Key = %s Data = %s", it.key().latin1(), it.data().latin1()); 00258 m_mapProps.insert( it.key(), QVariant( it.data())); 00259 } 00260 } 00261 00262 KService::KService( QDataStream& _str, int offset ) : KSycocaEntry( _str, offset ) 00263 { 00264 d = new KServicePrivate; 00265 load( _str ); 00266 } 00267 00268 KService::~KService() 00269 { 00270 //debug("KService::~KService()"); 00271 delete d; 00272 } 00273 00274 QPixmap KService::pixmap( KIcon::Group _group, int _force_size, int _state, QString * _path ) const 00275 { 00276 KIconLoader *iconLoader=KGlobal::iconLoader(); 00277 if (!iconLoader->extraDesktopThemesAdded()) 00278 { 00279 QPixmap pixmap=iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path, true ); 00280 if (!pixmap.isNull() ) return pixmap; 00281 00282 iconLoader->addExtraDesktopThemes(); 00283 } 00284 00285 return iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path ); 00286 } 00287 00288 void KService::load( QDataStream& s ) 00289 { 00290 // dummies are here because of fields that were removed, to keep bin compat. 00291 // Feel free to re-use, but fields for Applications only (not generic services) 00292 // should rather be added to application.desktop 00293 Q_INT8 def, term, dummy1, dummy2; 00294 Q_INT8 dst, initpref; 00295 QString dummyStr1, dummyStr2; 00296 int dummyI1, dummyI2; 00297 Q_UINT32 dummyUI32; 00298 00299 // WARNING: IN KDE 3.x THIS NEEDS TO REMAIN COMPATIBLE WITH KDE 2.x! 00300 // !! This data structure should remain binary compatible at all times !! 00301 // You may add new fields at the end. Make sure to update the version 00302 // number in ksycoca.h 00303 s >> m_strType >> m_strName >> m_strExec >> m_strIcon 00304 >> term >> m_strTerminalOptions 00305 >> m_strPath >> m_strComment >> m_lstServiceTypes >> def >> m_mapProps 00306 >> m_strLibrary >> dummyI1 >> dummyI2 00307 >> dst 00308 >> m_strDesktopEntryName 00309 >> dummy1 >> dummyStr1 >> initpref >> dummyStr2 >> dummy2 00310 >> m_lstKeywords >> m_strInit >> dummyUI32 >> m_strGenName 00311 >> d->categories >> d->menuId; 00312 00313 m_bAllowAsDefault = def; 00314 m_bTerminal = term; 00315 m_DCOPServiceType = (DCOPServiceType_t) dst; 00316 m_initialPreference = initpref; 00317 00318 m_bValid = true; 00319 } 00320 00321 void KService::save( QDataStream& s ) 00322 { 00323 KSycocaEntry::save( s ); 00324 Q_INT8 def = m_bAllowAsDefault, initpref = m_initialPreference; 00325 Q_INT8 term = m_bTerminal; 00326 Q_INT8 dst = (Q_INT8) m_DCOPServiceType; 00327 Q_INT8 dummy1 = 0, dummy2 = 0; // see ::load 00328 QString dummyStr1, dummyStr2; 00329 int dummyI1 = 0, dummyI2 = 0; 00330 Q_UINT32 dummyUI32 = 0; 00331 00332 // WARNING: IN KDE 3.x THIS NEEDS TO REMAIN COMPATIBLE WITH KDE 2.x! 00333 // !! This data structure should remain binary compatible at all times !! 00334 // You may add new fields at the end. Make sure to update the version 00335 // number in ksycoca.h 00336 s << m_strType << m_strName << m_strExec << m_strIcon 00337 << term << m_strTerminalOptions 00338 << m_strPath << m_strComment << m_lstServiceTypes << def << m_mapProps 00339 << m_strLibrary << dummyI1 << dummyI2 00340 << dst 00341 << m_strDesktopEntryName 00342 << dummy1 << dummyStr1 << initpref << dummyStr2 << dummy2 00343 << m_lstKeywords << m_strInit << dummyUI32 << m_strGenName 00344 << d->categories << d->menuId; 00345 } 00346 00347 bool KService::hasServiceType( const QString& _servicetype ) const 00348 { 00349 if (!m_bValid) return false; // safety test 00350 00351 //kdDebug(7012) << "Testing " << m_strDesktopEntryName << " for " << _servicetype << endl; 00352 00353 KMimeType::Ptr mimePtr = KMimeType::mimeType( _servicetype ); 00354 if ( mimePtr && mimePtr == KMimeType::defaultMimeTypePtr() ) 00355 mimePtr = 0; 00356 00357 bool isNumber; 00358 // For each service type we are associated with, if it doesn't 00359 // match then we try its parent service types. 00360 QStringList::ConstIterator it = m_lstServiceTypes.begin(); 00361 for( ; it != m_lstServiceTypes.end(); ++it ) 00362 { 00363 (*it).toInt(&isNumber); 00364 if (isNumber) 00365 continue; 00366 //kdDebug(7012) << " has " << (*it) << endl; 00367 KServiceType::Ptr ptr = KServiceType::serviceType( *it ); 00368 if ( ptr && ptr->inherits( _servicetype ) ) 00369 return true; 00370 00371 // The mimetype inheritance ("is also") works the other way. 00372 // e.g. if we're looking for a handler for mimePtr==smb-workgroup 00373 // then a handler for inode/directory is ok. 00374 if ( mimePtr && mimePtr->is( *it ) ) 00375 return true; 00376 } 00377 return false; 00378 } 00379 00380 int KService::initialPreferenceForMimeType( const QString& mimeType ) const 00381 { 00382 if (!m_bValid) return 0; // safety test 00383 00384 bool isNumber; 00385 00386 // For each service type we are associated with 00387 QStringList::ConstIterator it = m_lstServiceTypes.begin(); 00388 for( ; it != m_lstServiceTypes.end(); ++it ) 00389 { 00390 (*it).toInt(&isNumber); 00391 if (isNumber) 00392 continue; 00393 //kdDebug(7012) << " has " << (*it) << endl; 00394 KServiceType::Ptr ptr = KServiceType::serviceType( *it ); 00395 if ( !ptr || !ptr->inherits( mimeType ) ) 00396 continue; 00397 00398 int initalPreference = m_initialPreference; 00399 ++it; 00400 if (it != m_lstServiceTypes.end()) 00401 { 00402 int i = (*it).toInt(&isNumber); 00403 if (isNumber) 00404 initalPreference = i; 00405 } 00406 return initalPreference; 00407 } 00408 00409 KMimeType::Ptr mimePtr = KMimeType::mimeType( mimeType ); 00410 if ( mimePtr && mimePtr == KMimeType::defaultMimeTypePtr() ) 00411 mimePtr = 0; 00412 00413 // Try its parent service types. 00414 it = m_lstServiceTypes.begin(); 00415 for( ; it != m_lstServiceTypes.end(); ++it ) 00416 { 00417 (*it).toInt(&isNumber); 00418 if (isNumber) 00419 continue; 00420 00421 // The mimetype inheritance ("is also") works the other way. 00422 // e.g. if we're looking for a handler for mimePtr==smb-workgroup 00423 // then a handler for inode/directory is ok. 00424 if ( !mimePtr || !mimePtr->is( *it ) ) 00425 continue; 00426 00427 int initalPreference = m_initialPreference; 00428 ++it; 00429 if (it != m_lstServiceTypes.end()) 00430 { 00431 int i = (*it).toInt(&isNumber); 00432 if (isNumber) 00433 initalPreference = i; 00434 } 00435 return initalPreference; 00436 } 00437 return 0; 00438 } 00439 00440 class KServiceReadProperty : public KConfigBase 00441 { 00442 public: 00443 KServiceReadProperty(const QString &_key, const QCString &_value) 00444 : key(_key), value(_value) { } 00445 00446 bool internalHasGroup(const QCString &) const { /*qDebug("hasGroup(const QCString &)");*/ return false; } 00447 00448 QStringList groupList() const { return QStringList(); } 00449 00450 QMap<QString,QString> entryMap(const QString &) const 00451 { return QMap<QString,QString>(); } 00452 00453 void reparseConfiguration() { } 00454 00455 KEntryMap internalEntryMap( const QString &) const { return KEntryMap(); } 00456 00457 KEntryMap internalEntryMap() const { return KEntryMap(); } 00458 00459 void putData(const KEntryKey &, const KEntry&, bool) { } 00460 00461 KEntry lookupData(const KEntryKey &) const 00462 { KEntry entry; entry.mValue = value; return entry; } 00463 protected: 00464 QString key; 00465 QCString value; 00466 }; 00467 00468 QVariant KService::property( const QString& _name) const 00469 { 00470 return property( _name, QVariant::Invalid); 00471 } 00472 00473 // Return a string QVariant if string isn't null, and invalid variant otherwise 00474 // (the variant must be invalid if the field isn't in the .desktop file) 00475 // This allows trader queries like "exist Library" to work. 00476 static QVariant makeStringVariant( const QString& string ) 00477 { 00478 // Using isEmpty here would be wrong. 00479 // Empty is "specified but empty", null is "not specified" (in the .desktop file) 00480 return string.isNull() ? QVariant() : QVariant( string ); 00481 } 00482 00483 QVariant KService::property( const QString& _name, QVariant::Type t ) const 00484 { 00485 if ( _name == "Type" ) 00486 return QVariant( m_strType ); // can't be null 00487 else if ( _name == "Name" ) 00488 return QVariant( m_strName ); // can't be null 00489 else if ( _name == "Exec" ) 00490 return makeStringVariant( m_strExec ); 00491 else if ( _name == "Icon" ) 00492 return makeStringVariant( m_strIcon ); 00493 else if ( _name == "Terminal" ) 00494 return QVariant( static_cast<int>(m_bTerminal) ); 00495 else if ( _name == "TerminalOptions" ) 00496 return makeStringVariant( m_strTerminalOptions ); 00497 else if ( _name == "Path" ) 00498 return makeStringVariant( m_strPath ); 00499 else if ( _name == "Comment" ) 00500 return makeStringVariant( m_strComment ); 00501 else if ( _name == "GenericName" ) 00502 return makeStringVariant( m_strGenName ); 00503 else if ( _name == "ServiceTypes" ) 00504 return QVariant( m_lstServiceTypes ); 00505 else if ( _name == "AllowAsDefault" ) 00506 return QVariant( static_cast<int>(m_bAllowAsDefault) ); 00507 else if ( _name == "InitialPreference" ) 00508 return QVariant( m_initialPreference ); 00509 else if ( _name == "Library" ) 00510 return makeStringVariant( m_strLibrary ); 00511 else if ( _name == "DesktopEntryPath" ) // can't be null 00512 return QVariant( entryPath() ); 00513 else if ( _name == "DesktopEntryName") 00514 return QVariant( m_strDesktopEntryName ); // can't be null 00515 else if ( _name == "Categories") 00516 return QVariant( d->categories ); 00517 else if ( _name == "Keywords") 00518 return QVariant( m_lstKeywords ); 00519 00520 // Ok we need to convert the property from a QString to its real type. 00521 // Maybe the caller helped us. 00522 if (t == QVariant::Invalid) 00523 { 00524 // No luck, let's ask KServiceTypeFactory what the type of this property 00525 // is supposed to be. 00526 t = KServiceTypeFactory::self()->findPropertyTypeByName(_name); 00527 if (t == QVariant::Invalid) 00528 { 00529 kdDebug(7012) << "Request for unknown property '" << _name << "'\n"; 00530 return QVariant(); // Unknown property: Invalid variant. 00531 } 00532 } 00533 00534 // Then we use a homebuild class based on KConfigBase to convert the QString. 00535 // For some often used property types we do the conversion ourselves. 00536 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( _name ); 00537 if ( (it == m_mapProps.end()) || (!it.data().isValid())) 00538 { 00539 //kdDebug(7012) << "Property not found " << _name << endl; 00540 return QVariant(); // No property set. 00541 } 00542 00543 switch(t) 00544 { 00545 case QVariant::String: 00546 return it.data(); 00547 case QVariant::Bool: 00548 case QVariant::Int: 00549 { 00550 QString aValue = it.data().toString(); 00551 int val = 0; 00552 if (aValue == "true" || aValue == "on" || aValue == "yes") 00553 val = 1; 00554 else 00555 { 00556 bool bOK; 00557 val = aValue.toInt( &bOK ); 00558 if( !bOK ) 00559 val = 0; 00560 } 00561 if (t == QVariant::Bool) 00562 { 00563 return QVariant((bool)val, 1); 00564 } 00565 return QVariant(val); 00566 } 00567 default: 00568 // All others 00569 KServiceReadProperty ksrp(_name, it.data().toString().utf8()); 00570 return ksrp.readPropertyEntry(_name, t); 00571 } 00572 } 00573 00574 QStringList KService::propertyNames() const 00575 { 00576 QStringList res; 00577 00578 QMap<QString,QVariant>::ConstIterator it = m_mapProps.begin(); 00579 for( ; it != m_mapProps.end(); ++it ) 00580 res.append( it.key() ); 00581 00582 res.append( "Type" ); 00583 res.append( "Name" ); 00584 res.append( "Comment" ); 00585 res.append( "GenericName" ); 00586 res.append( "Icon" ); 00587 res.append( "Exec" ); 00588 res.append( "Terminal" ); 00589 res.append( "TerminalOptions" ); 00590 res.append( "Path" ); 00591 res.append( "ServiceTypes" ); 00592 res.append( "AllowAsDefault" ); 00593 res.append( "InitialPreference" ); 00594 res.append( "Library" ); 00595 res.append( "DesktopEntryPath" ); 00596 res.append( "DesktopEntryName" ); 00597 res.append( "Keywords" ); 00598 res.append( "Categories" ); 00599 00600 return res; 00601 } 00602 00603 KService::List KService::allServices() 00604 { 00605 return KServiceFactory::self()->allServices(); 00606 } 00607 00608 KService::Ptr KService::serviceByName( const QString& _name ) 00609 { 00610 KService * s = KServiceFactory::self()->findServiceByName( _name ); 00611 return KService::Ptr( s ); 00612 } 00613 00614 KService::Ptr KService::serviceByDesktopPath( const QString& _name ) 00615 { 00616 KService * s = KServiceFactory::self()->findServiceByDesktopPath( _name ); 00617 return KService::Ptr( s ); 00618 } 00619 00620 KService::Ptr KService::serviceByDesktopName( const QString& _name ) 00621 { 00622 KService * s = KServiceFactory::self()->findServiceByDesktopName( _name.lower() ); 00623 if (!s && !_name.startsWith("kde-")) 00624 s = KServiceFactory::self()->findServiceByDesktopName( "kde-"+_name.lower() ); 00625 return KService::Ptr( s ); 00626 } 00627 00628 KService::Ptr KService::serviceByMenuId( const QString& _name ) 00629 { 00630 KService * s = KServiceFactory::self()->findServiceByMenuId( _name ); 00631 return KService::Ptr( s ); 00632 } 00633 00634 KService::Ptr KService::serviceByStorageId( const QString& _storageId ) 00635 { 00636 KService::Ptr service = KService::serviceByMenuId( _storageId ); 00637 if (service) 00638 return service; 00639 00640 service = KService::serviceByDesktopPath(_storageId); 00641 if (service) 00642 return service; 00643 00644 if (!QDir::isRelativePath(_storageId) && QFile::exists(_storageId)) 00645 return new KService(_storageId); 00646 00647 QString tmp = _storageId; 00648 tmp = tmp.mid(tmp.findRev('/')+1); // Strip dir 00649 00650 if (tmp.endsWith(".desktop")) 00651 tmp.truncate(tmp.length()-8); 00652 00653 if (tmp.endsWith(".kdelnk")) 00654 tmp.truncate(tmp.length()-7); 00655 00656 service = KService::serviceByDesktopName(tmp); 00657 00658 return service; 00659 } 00660 00661 KService::List KService::allInitServices() 00662 { 00663 return KServiceFactory::self()->allInitServices(); 00664 } 00665 00666 bool KService::substituteUid() const { 00667 QVariant v = property("X-KDE-SubstituteUID", QVariant::Bool); 00668 return v.isValid() && v.toBool(); 00669 } 00670 00671 QString KService::username() const { 00672 // See also KDesktopFile::tryExec() 00673 QString user; 00674 QVariant v = property("X-KDE-Username", QVariant::String); 00675 user = v.isValid() ? v.toString() : QString::null; 00676 if (user.isEmpty()) 00677 user = ::getenv("ADMIN_ACCOUNT"); 00678 if (user.isEmpty()) 00679 user = "root"; 00680 return user; 00681 } 00682 00683 bool KService::noDisplay() const { 00684 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "NoDisplay" ); 00685 if ( (it != m_mapProps.end()) && (it.data().isValid())) 00686 { 00687 QString aValue = it.data().toString().lower(); 00688 if (aValue == "true" || aValue == "on" || aValue == "yes") 00689 return true; 00690 } 00691 00692 it = m_mapProps.find( "OnlyShowIn" ); 00693 if ( (it != m_mapProps.end()) && (it.data().isValid())) 00694 { 00695 QString aValue = it.data().toString(); 00696 QStringList aList = QStringList::split(';', aValue); 00697 if (!aList.contains("KDE")) 00698 return true; 00699 } 00700 00701 it = m_mapProps.find( "NotShowIn" ); 00702 if ( (it != m_mapProps.end()) && (it.data().isValid())) 00703 { 00704 QString aValue = it.data().toString(); 00705 QStringList aList = QStringList::split(';', aValue); 00706 if (aList.contains("KDE")) 00707 return true; 00708 } 00709 00710 if (!kapp->authorizeControlModule(d->menuId)) 00711 return true; 00712 00713 return false; 00714 } 00715 00716 QString KService::untranslatedGenericName() const { 00717 QVariant v = property("UntranslatedGenericName", QVariant::String); 00718 return v.isValid() ? v.toString() : QString::null; 00719 } 00720 00721 QString KService::parentApp() const { 00722 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "X-KDE-ParentApp" ); 00723 if ( (it == m_mapProps.end()) || (!it.data().isValid())) 00724 { 00725 return QString::null; 00726 } 00727 00728 return it.data().toString(); 00729 } 00730 00731 bool KService::allowMultipleFiles() const { 00732 // Can we pass multiple files on the command line or do we have to start the application for every single file ? 00733 if ( m_strExec.find( "%F" ) != -1 || m_strExec.find( "%U" ) != -1 || 00734 m_strExec.find( "%N" ) != -1 || m_strExec.find( "%D" ) != -1 ) 00735 return true; 00736 else 00737 return false; 00738 } 00739 00740 QStringList KService::categories() const 00741 { 00742 return d->categories; 00743 } 00744 00745 QString KService::menuId() const 00746 { 00747 return d->menuId; 00748 } 00749 00750 void KService::setMenuId(const QString &menuId) 00751 { 00752 d->menuId = menuId; 00753 } 00754 00755 QString KService::storageId() const 00756 { 00757 if (!d->menuId.isEmpty()) 00758 return d->menuId; 00759 return entryPath(); 00760 } 00761 00762 QString KService::locateLocal() 00763 { 00764 if (d->menuId.isEmpty() || desktopEntryPath().startsWith(".hidden") || 00765 (QDir::isRelativePath(desktopEntryPath()) && d->categories.isEmpty())) 00766 return KDesktopFile::locateLocal(desktopEntryPath()); 00767 00768 return ::locateLocal("xdgdata-apps", d->menuId); 00769 } 00770 00771 QString KService::newServicePath(bool showInMenu, const QString &suggestedName, 00772 QString *menuId, const QStringList *reservedMenuIds) 00773 { 00774 QString base = suggestedName; 00775 QString typeMenu = KStandardDirs::menu_type_by_version(); 00776 if (!showInMenu) 00777 { 00778 if( typeMenu!="kde") 00779 base.prepend("blackPantherOS-.hidden-"); 00780 else 00781 base.prepend("kde-"); 00782 } 00783 00784 QString result; 00785 for(int i = 1; true; i++) 00786 { 00787 if (i == 1) 00788 result = base + ".desktop"; 00789 else 00790 result = base + QString("-%1.desktop").arg(i); 00791 00792 if (reservedMenuIds && reservedMenuIds->contains(result)) 00793 continue; 00794 00795 // Lookup service by menu-id 00796 KService::Ptr s = serviceByMenuId(result); 00797 if (s) 00798 continue; 00799 00800 if (showInMenu) 00801 { 00802 if (!locate("xdgdata-apps", result).isEmpty()) 00803 continue; 00804 } 00805 else 00806 { 00807 if( typeMenu=="kde") 00808 { 00809 QString file = result.mid(4); // Strip "kde- 00810 if (!locate("apps", ".hidden/"+file).isEmpty()) 00811 continue; 00812 } 00813 else 00814 { 00815 QString file = result.mid(22); // Strip "blackPantherOS... 00816 if (!locate("xdgdata-apps", "blackPantherOS/.hidden/"+file).isEmpty()) 00817 continue; 00818 } 00819 } 00820 00821 break; 00822 } 00823 if (menuId) 00824 *menuId = result; 00825 00826 if (showInMenu) 00827 { 00828 return ::locateLocal("xdgdata-apps", result); 00829 } 00830 else 00831 { 00832 QString file = result.mid(4); // Strip "kde-" 00833 if( typeMenu=="kde") 00834 { 00835 QString file = result.mid(4); // Strip "kde-" 00836 return ::locateLocal("apps", ".hidden/"+file); 00837 } 00838 else 00839 { 00840 QString file = result.mid(22); // Strip "kde-" 00841 return ::locateLocal("xdgdata-apps", "blackPantherOS/.hidden/"+file); 00842 } 00843 } 00844 } 00845 00846 00847 void KService::virtual_hook( int id, void* data ) 00848 { KSycocaEntry::virtual_hook( id, data ); } 00849 00850 00851 void KService::rebuildKSycoca(QWidget *parent) 00852 { 00853 KServiceProgressDialog dlg(parent, "ksycoca_progress", 00854 i18n("Updating System Configuration"), 00855 i18n("Updating system configuration.")); 00856 00857 QByteArray data; 00858 DCOPClient *client = kapp->dcopClient(); 00859 00860 int result = client->callAsync("kded", "kbuildsycoca", "recreate()", 00861 data, &dlg, SLOT(slotFinished())); 00862 00863 if (result) 00864 { 00865 dlg.exec(); 00866 } 00867 } 00868 00869 KServiceProgressDialog::KServiceProgressDialog(QWidget *parent, const char *name, 00870 const QString &caption, const QString &text) 00871 : KProgressDialog(parent, name, caption, text, true) 00872 { 00873 connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotProgress())); 00874 progressBar()->setTotalSteps(20); 00875 m_timeStep = 700; 00876 m_timer.start(m_timeStep); 00877 setAutoClose(false); 00878 } 00879 00880 void 00881 KServiceProgressDialog::slotProgress() 00882 { 00883 int p = progressBar()->progress(); 00884 if (p == 18) 00885 { 00886 progressBar()->reset(); 00887 progressBar()->setProgress(1); 00888 m_timeStep = m_timeStep * 2; 00889 m_timer.start(m_timeStep); 00890 } 00891 else 00892 { 00893 progressBar()->setProgress(p+1); 00894 } 00895 } 00896 00897 void 00898 KServiceProgressDialog::slotFinished() 00899 { 00900 progressBar()->setProgress(20); 00901 m_timer.stop(); 00902 QTimer::singleShot(1000, this, SLOT(close())); 00903 } 00904 00905 #include "kservice_p.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:20:29 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003