25 #include "kservice_p.h"
27 #include <sys/types.h>
40 #include <ksimpleconfig.h>
41 #include <tdeapplication.h>
43 #include <kdesktopfile.h>
44 #include <tdeglobal.h>
45 #include <kiconloader.h>
46 #include <tdelocale.h>
47 #include <tdeconfigbase.h>
48 #include <kstandarddirs.h>
49 #include <dcopclient.h>
51 #include "kservicefactory.h"
52 #include "kservicetypefactory.h"
53 #include "kservicetype.h"
54 #include "kuserprofile.h"
55 #include "tdesycoca.h"
57 class KService::KServicePrivate
65 : KSycocaEntry( TQString::null)
67 d =
new KServicePrivate;
70 m_strType =
"Application";
75 m_bAllowAsDefault =
true;
76 m_initialPreference = 10;
81 : KSycocaEntry( _fullpath)
83 KDesktopFile config( _fullpath );
89 : KSycocaEntry( config->fileName())
97 d =
new KServicePrivate;
100 bool absPath = !TQDir::isRelativePath(entryPath());
101 bool kde4application = config->fileName().contains(
"/share/applications/kde4/");
102 TQString kde4applicationprefix;
103 if (kde4application) {
105 kde4applicationprefix = config->fileName();
106 int pos = kde4applicationprefix.find(
"/share/applications/kde4/");
107 kde4applicationprefix.truncate(pos);
110 config->setDesktopGroup();
112 TQMap<TQString, TQString> entryMap = config->entryMap(config->group());
114 entryMap.remove(
"Encoding");
115 entryMap.remove(
"Version");
117 m_bDeleted = config->readBoolEntry(
"Hidden",
false );
118 entryMap.remove(
"Hidden");
126 m_strName = config->readName();
127 entryMap.remove(
"Name");
128 if ( m_strName.isEmpty() )
130 if (config->readEntry(
"Exec" ).isEmpty())
138 m_strName = entryPath();
139 int i = m_strName.findRev(
'/');
140 m_strName = m_strName.mid(i+1);
141 i = m_strName.findRev(
'.');
143 m_strName = m_strName.left(i);
146 m_strType = config->readType();
147 entryMap.remove(
"Type");
148 if ( m_strType.isEmpty() )
155 m_strType =
"Application";
156 }
else if ( m_strType !=
"Application" && m_strType !=
"Service" )
158 kdWarning(7012) <<
"The desktop entry file " << entryPath()
159 <<
" has Type=" << m_strType
160 <<
" instead of \"Application\" or \"Service\"" << endl;
166 if (!config->tryExec()) {
173 TQString resource = config->resource();
175 if ( (m_strType ==
"Application") &&
176 (!resource.isEmpty()) &&
177 (resource !=
"apps") &&
180 kdWarning(7012) <<
"The desktop entry file " << entryPath()
181 <<
" has Type=" << m_strType <<
" but is located under \"" << resource
182 <<
"\" instead of \"apps\"" << endl;
187 if ( (m_strType ==
"Service") &&
188 (!resource.isEmpty()) &&
189 (resource !=
"services") &&
192 kdWarning(7012) <<
"The desktop entry file " << entryPath()
193 <<
" has Type=" << m_strType <<
" but is located under \"" << resource
194 <<
"\" instead of \"services\"" << endl;
199 TQString
name = entryPath();
200 int pos =
name.findRev(
'/');
203 pos =
name.find(
'.');
207 m_strExec = config->readPathEntry(
"Exec" );
208 if (kde4application && !m_strExec.startsWith(
"/")) {
209 m_strExec =
"XDG_DATA_DIRS=" + kde4applicationprefix +
"/share XDG_CONFIG_DIRS=/etc/xdg/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:$PATH "+m_strExec;
211 else if (config->readBoolEntry(
"X-TDE-SubstituteUID") || config->readBoolEntry(
"X-KDE-SubstituteUID")) {
212 TQString
path = TQString::fromLocal8Bit(getenv(
"PATH"));
215 int space = m_strExec.find(
" ");
220 command = m_strExec.left(space);
221 params = m_strExec.mid(space);
223 path.replace(TQRegExp(
"(^|:)(/usr/local|/usr)/bin($|:)"),
"\\1\\2/sbin:\\2/bin\\3");
224 path.replace(TQRegExp(
"(^|:)/bin($|:)"),
"\\1/sbin:/bin\\2");
225 m_strExec = TDEStandardDirs::findExe(command,
path);
226 if (!m_strExec.isEmpty() && !params.isEmpty()) {
231 entryMap.remove(
"Exec");
233 m_strIcon = config->readEntry(
"Icon",
"unknown" );
234 if (kde4application) {
235 if (TQFile::exists(kde4applicationprefix +
"/share/icons/oxygen/22x22/apps/" + m_strIcon +
".png")) {
236 m_strIcon = kde4applicationprefix +
"/share/icons/oxygen/22x22/apps/" + m_strIcon +
".png";
237 }
else if (TQFile::exists(kde4applicationprefix +
"/share/icons/hicolor/22x22/apps/" + m_strIcon +
".png")) {
238 m_strIcon = kde4applicationprefix +
"/share/icons/hicolor/22x22/apps/" + m_strIcon +
".png";
241 entryMap.remove(
"Icon");
242 m_bTerminal = (config->readBoolEntry(
"Terminal" ));
243 entryMap.remove(
"Terminal");
244 m_strTerminalOptions = config->readEntry(
"TerminalOptions" );
245 entryMap.remove(
"TerminalOptions");
246 m_strPath = config->readPath();
247 entryMap.remove(
"Path");
248 m_strComment = config->readComment();
249 entryMap.remove(
"Comment");
250 m_strGenName = config->readGenericName();
251 #ifdef KDE4_MENU_SUFFIX
252 if (kde4application) {
253 m_strGenName +=
" [KDE4]";
256 entryMap.remove(
"GenericName");
261 m_lstKeywords = config->readListEntry(
"Keywords",
';');
262 entryMap.remove(
"Keywords");
263 d->categories = config->readListEntry(
"Categories",
';');
264 entryMap.remove(
"Categories");
265 m_strLibrary = config->readEntry(
"X-TDE-Library" );
266 entryMap.remove(
"X-TDE-Library");
267 m_strInit = config->readEntry(
"X-TDE-Init" );
268 entryMap.remove(
"X-TDE-Init");
270 m_lstServiceTypes = config->readListEntry(
"X-TDE-ServiceTypes" );
271 entryMap.remove(
"X-TDE-ServiceTypes");
273 if (!kde4application)
274 m_lstServiceTypes += config->readListEntry(
"MimeType",
';' );
275 entryMap.remove(
"MimeType");
277 if ( m_strType ==
"Application" && !m_lstServiceTypes.contains(
"Application") )
279 m_lstServiceTypes +=
"Application";
281 TQString dcopServiceType = config->readEntry(
"X-DCOP-ServiceType").lower();
282 entryMap.remove(
"X-DCOP-ServiceType");
283 if (dcopServiceType ==
"unique")
284 m_DCOPServiceType = DCOP_Unique;
285 else if (dcopServiceType ==
"multi")
286 m_DCOPServiceType = DCOP_Multi;
287 else if (dcopServiceType ==
"wait")
288 m_DCOPServiceType = DCOP_Wait;
290 m_DCOPServiceType = DCOP_None;
292 m_strDesktopEntryName =
name.lower();
294 m_strDesktopEntryName =
"kde4-" + m_strDesktopEntryName;
296 m_bAllowAsDefault = config->readBoolEntry(
"AllowDefault",
true );
297 entryMap.remove(
"AllowDefault");
299 m_initialPreference = config->readNumEntry(
"X-TDE-InitialPreference", 1 );
300 entryMap.remove(
"X-TDE-InitialPreference");
301 if ( m_initialPreference == 1 )
302 m_initialPreference = config->readNumEntry(
"X-TDE-InitialPreference", 1 );
303 entryMap.remove(
"X-TDE-InitialPreference");
309 TQMap<TQString,TQString>::ConstIterator it = entryMap.begin();
310 for( ; it != entryMap.end();++it)
313 TQString key = it.key();
314 if (kde4application && key==
"OnlyShowIn" && it.data()==
"KDE;")
316 m_mapProps.insert( key, TQVariant( it.data()));
322 d =
new KServicePrivate;
326 KService::~KService()
332 TQPixmap
KService::pixmap( TDEIcon::Group _group,
int _force_size,
int _state, TQString * _path )
const
334 TDEIconLoader *iconLoader=TDEGlobal::iconLoader();
335 if (!iconLoader->extraDesktopThemesAdded())
337 TQPixmap
pixmap=iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path,
true );
340 iconLoader->addExtraDesktopThemes();
343 return iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path );
346 void KService::load( TQDataStream& s )
351 TQ_INT8 def, term, dummy1, dummy2;
352 TQ_INT8 dst, initpref;
353 TQString dummyStr1, dummyStr2;
354 int dummyI1, dummyI2;
361 s >> m_strType >> m_strName >> m_strExec >> m_strIcon
362 >> term >> m_strTerminalOptions
363 >> m_strPath >> m_strComment >> m_lstServiceTypes >> def >> m_mapProps
364 >> m_strLibrary >> dummyI1 >> dummyI2
366 >> m_strDesktopEntryName
367 >> dummy1 >> dummyStr1 >> initpref >> dummyStr2 >> dummy2
368 >> m_lstKeywords >> m_strInit >> dummyUI32 >> m_strGenName
369 >> d->categories >> d->menuId;
371 m_bAllowAsDefault = def;
374 m_initialPreference = initpref;
379 void KService::save( TQDataStream& s )
381 KSycocaEntry::save( s );
382 TQ_INT8 def = m_bAllowAsDefault, initpref = m_initialPreference;
383 TQ_INT8 term = m_bTerminal;
384 TQ_INT8 dst = (TQ_INT8) m_DCOPServiceType;
385 TQ_INT8 dummy1 = 0, dummy2 = 0;
386 TQString dummyStr1, dummyStr2;
387 int dummyI1 = 0, dummyI2 = 0;
388 TQ_UINT32 dummyUI32 = 0;
394 s << m_strType << m_strName << m_strExec << m_strIcon
395 << term << m_strTerminalOptions
396 << m_strPath << m_strComment << m_lstServiceTypes << def << m_mapProps
397 << m_strLibrary << dummyI1 << dummyI2
399 << m_strDesktopEntryName
400 << dummy1 << dummyStr1 << initpref << dummyStr2 << dummy2
401 << m_lstKeywords << m_strInit << dummyUI32 << m_strGenName
402 << d->categories << d->menuId;
407 if (!m_bValid)
return false;
418 TQStringList::ConstIterator it = m_lstServiceTypes.begin();
419 for( ; it != m_lstServiceTypes.end(); ++it )
421 (*it).toInt(&isNumber);
426 if ( ptr && ptr->inherits( _servicetype ) )
432 if ( mimePtr && mimePtr->is( *it ) )
440 if (!m_bValid)
return 0;
445 TQStringList::ConstIterator it = m_lstServiceTypes.begin();
446 for( ; it != m_lstServiceTypes.end(); ++it )
448 (*it).toInt(&isNumber);
453 if ( !ptr || !ptr->inherits( mimeType ) )
456 int initalPreference = m_initialPreference;
458 if (it != m_lstServiceTypes.end())
460 int i = (*it).toInt(&isNumber);
462 initalPreference = i;
464 return initalPreference;
472 it = m_lstServiceTypes.begin();
473 for( ; it != m_lstServiceTypes.end(); ++it )
475 (*it).toInt(&isNumber);
482 if ( !mimePtr || !mimePtr->is( *it ) )
485 int initalPreference = m_initialPreference;
487 if (it != m_lstServiceTypes.end())
489 int i = (*it).toInt(&isNumber);
491 initalPreference = i;
493 return initalPreference;
498 class KServiceReadProperty :
public TDEConfigBase
501 KServiceReadProperty(
const TQString &_key,
const TQCString &_value)
502 : key(_key), value(_value) { }
504 bool internalHasGroup(
const TQCString &)
const {
return false; }
506 TQStringList groupList()
const {
return TQStringList(); }
508 TQMap<TQString,TQString> entryMap(
const TQString &group)
const
509 { Q_UNUSED(group);
return TQMap<TQString,TQString>(); }
511 void reparseConfiguration() { }
513 KEntryMap internalEntryMap(
const TQString &pGroup)
const
514 { Q_UNUSED(pGroup);
return KEntryMap(); }
516 KEntryMap internalEntryMap()
const {
return KEntryMap(); }
518 void putData(
const KEntryKey &_key,
const KEntry& _data,
bool _checkGroup)
519 { Q_UNUSED(_key); Q_UNUSED(_data); Q_UNUSED(_checkGroup); }
521 KEntry lookupData(
const KEntryKey &_key)
const
522 { Q_UNUSED(_key); KEntry entry; entry.mValue = value;
return entry; }
530 return property( _name, TQVariant::Invalid);
536 static TQVariant makeStringVariant(
const TQString&
string )
540 return string.isNull() ? TQVariant() : TQVariant( string );
545 if ( _name ==
"Type" )
546 return TQVariant( m_strType );
547 else if ( _name ==
"Name" )
548 return TQVariant( m_strName );
549 else if ( _name ==
"Exec" )
550 return makeStringVariant( m_strExec );
551 else if ( _name ==
"Icon" )
552 return makeStringVariant( m_strIcon );
553 else if ( _name ==
"Terminal" )
554 return TQVariant(
static_cast<int>(m_bTerminal) );
555 else if ( _name ==
"TerminalOptions" )
556 return makeStringVariant( m_strTerminalOptions );
557 else if ( _name ==
"Path" )
558 return makeStringVariant( m_strPath );
559 else if ( _name ==
"Comment" )
560 return makeStringVariant( m_strComment );
561 else if ( _name ==
"GenericName" )
562 return makeStringVariant( m_strGenName );
563 else if ( _name ==
"ServiceTypes" )
564 return TQVariant( m_lstServiceTypes );
565 else if ( _name ==
"AllowAsDefault" )
566 return TQVariant(
static_cast<int>(m_bAllowAsDefault) );
567 else if ( _name ==
"InitialPreference" )
568 return TQVariant( m_initialPreference );
569 else if ( _name ==
"Library" )
570 return makeStringVariant( m_strLibrary );
571 else if ( _name ==
"DesktopEntryPath" )
572 return TQVariant( entryPath() );
573 else if ( _name ==
"DesktopEntryName")
574 return TQVariant( m_strDesktopEntryName );
575 else if ( _name ==
"Categories")
576 return TQVariant( d->categories );
577 else if ( _name ==
"Keywords")
578 return TQVariant( m_lstKeywords );
582 if (t == TQVariant::Invalid)
586 t = KServiceTypeFactory::self()->findPropertyTypeByName(_name);
587 if (t == TQVariant::Invalid)
589 kdDebug(7012) <<
"Request for unknown property '" << _name <<
"'\n";
596 TQStringVariantMap::ConstIterator it = m_mapProps.find( _name );
597 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
605 case TQVariant::String:
607 case TQVariant::Bool:
610 TQString aValue = it.data().toString();
612 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
617 val = aValue.toInt( &bOK );
621 if (t == TQVariant::Bool)
623 return TQVariant((
bool)val);
625 return TQVariant(val);
629 KServiceReadProperty ksrp(_name, it.data().toString().utf8());
630 return ksrp.readPropertyEntry(_name, t);
638 TQStringVariantMap::ConstIterator it = m_mapProps.begin();
639 for( ; it != m_mapProps.end(); ++it )
640 res.append( it.key() );
642 res.append(
"Type" );
643 res.append(
"Name" );
644 res.append(
"Comment" );
645 res.append(
"GenericName" );
646 res.append(
"Icon" );
647 res.append(
"Exec" );
648 res.append(
"Terminal" );
649 res.append(
"TerminalOptions" );
650 res.append(
"Path" );
651 res.append(
"ServiceTypes" );
652 res.append(
"AllowAsDefault" );
653 res.append(
"InitialPreference" );
654 res.append(
"Library" );
655 res.append(
"DesktopEntryPath" );
656 res.append(
"DesktopEntryName" );
657 res.append(
"Keywords" );
658 res.append(
"Categories" );
665 return KServiceFactory::self()->allServices();
670 KService * s = KServiceFactory::self()->findServiceByName( _name );
671 return KService::Ptr( s );
676 KService * s = KServiceFactory::self()->findServiceByDesktopPath( _name );
677 return KService::Ptr( s );
682 KService * s = KServiceFactory::self()->findServiceByDesktopName( _name.lower() );
683 if (!s && !_name.startsWith(
"tde-"))
684 s = KServiceFactory::self()->findServiceByDesktopName(
"tde-"+_name.lower() );
685 return KService::Ptr( s );
690 KService * s = KServiceFactory::self()->findServiceByMenuId( _name );
691 return KService::Ptr( s );
704 if (!TQDir::isRelativePath(_storageId) && TQFile::exists(_storageId))
707 TQString tmp = _storageId;
708 tmp = tmp.mid(tmp.findRev(
'/')+1);
710 if (tmp.endsWith(
".desktop"))
711 tmp.truncate(tmp.length()-8);
713 if (tmp.endsWith(
".kdelnk"))
714 tmp.truncate(tmp.length()-7);
723 return KServiceFactory::self()->allInitServices();
729 v =
property(
"X-TDE-SubstituteUID", TQVariant::Bool);
731 if (v.toBool()) suid =
true;
733 v =
property(
"X-KDE-SubstituteUID", TQVariant::Bool);
735 if (v.toBool()) suid =
true;
743 TQVariant v =
property(
"X-TDE-Username", TQVariant::String);
744 user = v.isValid() ? v.toString() : TQString::null;
746 user = ::getenv(
"ADMIN_ACCOUNT");
753 TQStringVariantMap::ConstIterator it = m_mapProps.find(
"NoDisplay" );
754 if ( (it != m_mapProps.end()) && (it.data().isValid()))
756 TQString aValue = it.data().toString().lower();
757 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
761 it = m_mapProps.find(
"OnlyShowIn" );
762 if ( (it != m_mapProps.end()) && (it.data().isValid()))
764 TQString aValue = it.data().toString();
765 TQStringList aList = TQStringList::split(
';', aValue);
766 #ifdef WITH_OLD_XDG_STD
767 if ((!aList.contains(
"TDE")) && (!aList.contains(
"KDE")))
770 if (!aList.contains(
"TDE"))
775 it = m_mapProps.find(
"NotShowIn" );
776 if ( (it != m_mapProps.end()) && (it.data().isValid()))
778 TQString aValue = it.data().toString();
779 TQStringList aList = TQStringList::split(
';', aValue);
780 #ifdef WITH_OLD_XDG_STD
781 if ((aList.contains(
"TDE")) || (aList.contains(
"KDE")))
784 if (aList.contains(
"TDE"))
789 if (!kapp->authorizeControlModule(d->menuId))
796 TQVariant v =
property(
"UntranslatedGenericName", TQVariant::String);
797 return v.isValid() ? v.toString() : TQString::null;
801 TQStringVariantMap::ConstIterator it = m_mapProps.find(
"X-SuSE-Unimportant" );
802 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
807 TQString aValue = it.data().toString();
808 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
815 TQStringVariantMap::ConstIterator it = m_mapProps.find(
"X-TDE-ParentApp" );
816 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
818 return TQString::null;
821 return it.data().toString();
826 if ( m_strExec.find(
"%F" ) != -1 || m_strExec.find(
"%U" ) != -1 ||
827 m_strExec.find(
"%N" ) != -1 || m_strExec.find(
"%D" ) != -1 )
835 return d->categories;
843 void KService::setMenuId(
const TQString &menuId)
850 if (!d->menuId.isEmpty())
861 return ::locateLocal(
"xdgdata-apps", d->menuId);
865 TQString *menuId,
const TQStringList *reservedMenuIds)
867 TQString base = suggestedName;
869 base.prepend(
"tde-");
872 for(
int i = 1;
true; i++)
875 result = base +
".desktop";
877 result = base + TQString(
"-%1.desktop").arg(i);
879 if (reservedMenuIds && reservedMenuIds->contains(result))
889 if (!locate(
"xdgdata-apps", result).isEmpty())
894 TQString file = result.mid(4);
895 if (!locate(
"apps",
".hidden/"+file).isEmpty())
906 return ::locateLocal(
"xdgdata-apps", result);
910 TQString file = result.mid(4);
911 return ::locateLocal(
"apps",
".hidden/"+file);
916 void KService::virtual_hook(
int id,
void* data )
917 { KSycocaEntry::virtual_hook(
id, data ); }
922 KServiceProgressDialog dlg(parent,
"tdesycoca_progress",
923 i18n(
"Updating System Configuration"),
924 i18n(
"Updating system configuration."));
927 DCOPClient *client = kapp->dcopClient();
929 int result = client->callAsync(
"kded",
"tdebuildsycoca",
"recreate()",
930 data, &dlg, TQ_SLOT(slotFinished()));
938 KServiceProgressDialog::KServiceProgressDialog(TQWidget *parent,
const char *name,
939 const TQString &caption,
const TQString &text)
940 : KProgressDialog(parent, name, caption, text, true)
942 connect(&m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotProgress()));
943 progressBar()->setTotalSteps(20);
945 m_timer.start(m_timeStep);
950 KServiceProgressDialog::slotProgress()
952 int p = progressBar()->progress();
955 progressBar()->reset();
956 progressBar()->setProgress(1);
957 m_timeStep = m_timeStep * 2;
958 m_timer.start(m_timeStep);
962 progressBar()->setProgress(p+1);
967 KServiceProgressDialog::slotFinished()
969 progressBar()->setProgress(20);
971 TQTimer::singleShot(1000,
this, TQ_SLOT(close()));
974 #include "kservice_p.moc"