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