1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2000 Waldo Bastian <bastian@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-only |
6 | */ |
7 | |
8 | #include "kservicegroup.h" |
9 | #include "kservice.h" |
10 | #include "kservicefactory_p.h" |
11 | #include "kservicegroup_p.h" |
12 | #include "kservicegroupfactory_p.h" |
13 | #include "ksycoca_p.h" |
14 | #include "servicesdebug.h" |
15 | #include <KConfigGroup> |
16 | #include <KDesktopFile> |
17 | #include <ksycoca.h> |
18 | |
19 | KServiceGroup::KServiceGroup(const QString &name) |
20 | : KSycocaEntry(*new KServiceGroupPrivate(name)) |
21 | { |
22 | } |
23 | |
24 | KServiceGroup::KServiceGroup(const QString &configFile, const QString &_relpath) |
25 | : KSycocaEntry(*new KServiceGroupPrivate(_relpath)) |
26 | { |
27 | Q_D(KServiceGroup); |
28 | |
29 | QString cfg = configFile; |
30 | if (cfg.isEmpty()) { |
31 | cfg = _relpath + QLatin1String(".directory" ); |
32 | } |
33 | |
34 | d->load(cfg); |
35 | } |
36 | |
37 | void KServiceGroupPrivate::load(const QString &cfg) |
38 | { |
39 | directoryEntryPath = cfg; |
40 | |
41 | const KDesktopFile desktopFile(cfg); |
42 | |
43 | const KConfigGroup config = desktopFile.desktopGroup(); |
44 | |
45 | m_strCaption = config.readEntry(key: "Name" ); |
46 | m_strIcon = config.readEntry(key: "Icon" ); |
47 | m_strComment = config.readEntry(key: "Comment" ); |
48 | deleted = config.readEntry(key: "Hidden" , defaultValue: false); |
49 | m_bNoDisplay = desktopFile.noDisplay(); |
50 | m_strBaseGroupName = config.readEntry(key: "X-KDE-BaseGroup" ); |
51 | suppressGenericNames = config.readEntry(key: "X-KDE-SuppressGenericNames" , aDefault: QStringList()); |
52 | |
53 | // Fill in defaults. |
54 | if (m_strCaption.isEmpty()) { |
55 | m_strCaption = path; |
56 | if (m_strCaption.endsWith(c: QLatin1Char('/'))) { |
57 | m_strCaption.chop(n: 1); |
58 | } |
59 | int i = m_strCaption.lastIndexOf(c: QLatin1Char('/')); |
60 | if (i > 0) { |
61 | m_strCaption.remove(i: 0, len: i + 1); |
62 | } |
63 | } |
64 | if (m_strIcon.isEmpty()) { |
65 | m_strIcon = QStringLiteral("folder" ); |
66 | } |
67 | } |
68 | |
69 | KServiceGroup::KServiceGroup(QDataStream &_str, int offset, bool deep) |
70 | : KSycocaEntry(*new KServiceGroupPrivate(_str, offset)) |
71 | { |
72 | Q_D(KServiceGroup); |
73 | d->m_bDeep = deep; |
74 | d->load(s&: _str); |
75 | } |
76 | |
77 | KServiceGroup::~KServiceGroup() |
78 | { |
79 | } |
80 | |
81 | QString KServiceGroup::relPath() const |
82 | { |
83 | return entryPath(); |
84 | } |
85 | |
86 | QString KServiceGroup::caption() const |
87 | { |
88 | Q_D(const KServiceGroup); |
89 | return d->m_strCaption; |
90 | } |
91 | |
92 | QString KServiceGroup::icon() const |
93 | { |
94 | Q_D(const KServiceGroup); |
95 | return d->m_strIcon; |
96 | } |
97 | |
98 | QString KServiceGroup::() const |
99 | { |
100 | Q_D(const KServiceGroup); |
101 | return d->m_strComment; |
102 | } |
103 | |
104 | int KServiceGroup::childCount() const |
105 | { |
106 | Q_D(const KServiceGroup); |
107 | return d->childCount(); |
108 | } |
109 | |
110 | int KServiceGroupPrivate::childCount() const |
111 | { |
112 | if (m_childCount == -1) { |
113 | m_childCount = 0; |
114 | |
115 | for (const KSycocaEntry::Ptr &entryPtr : m_serviceList) { |
116 | if (entryPtr->isType(t: KST_KService)) { |
117 | KService::Ptr service(static_cast<KService *>(entryPtr.data())); |
118 | if (!service->noDisplay()) { |
119 | m_childCount++; |
120 | } |
121 | } else if (entryPtr->isType(t: KST_KServiceGroup)) { |
122 | KServiceGroup::Ptr serviceGroup(static_cast<KServiceGroup *>(entryPtr.data())); |
123 | m_childCount += serviceGroup->childCount(); |
124 | } |
125 | } |
126 | } |
127 | return m_childCount; |
128 | } |
129 | |
130 | bool KServiceGroup::() const |
131 | { |
132 | Q_D(const KServiceGroup); |
133 | return d->m_bShowInlineHeader; |
134 | } |
135 | |
136 | bool KServiceGroup::() const |
137 | { |
138 | Q_D(const KServiceGroup); |
139 | return d->m_bShowEmptyMenu; |
140 | } |
141 | |
142 | bool KServiceGroup::inlineAlias() const |
143 | { |
144 | Q_D(const KServiceGroup); |
145 | return d->m_bInlineAlias; |
146 | } |
147 | |
148 | void KServiceGroup::setInlineAlias(bool _b) |
149 | { |
150 | Q_D(KServiceGroup); |
151 | d->m_bInlineAlias = _b; |
152 | } |
153 | |
154 | void KServiceGroup::(bool _b) |
155 | { |
156 | Q_D(KServiceGroup); |
157 | d->m_bShowEmptyMenu = _b; |
158 | } |
159 | |
160 | void KServiceGroup::(bool _b) |
161 | { |
162 | Q_D(KServiceGroup); |
163 | d->m_bShowInlineHeader = _b; |
164 | } |
165 | |
166 | int KServiceGroup::inlineValue() const |
167 | { |
168 | Q_D(const KServiceGroup); |
169 | return d->m_inlineValue; |
170 | } |
171 | |
172 | void KServiceGroup::setInlineValue(int _val) |
173 | { |
174 | Q_D(KServiceGroup); |
175 | d->m_inlineValue = _val; |
176 | } |
177 | |
178 | bool KServiceGroup::allowInline() const |
179 | { |
180 | Q_D(const KServiceGroup); |
181 | return d->m_bAllowInline; |
182 | } |
183 | |
184 | void KServiceGroup::setAllowInline(bool _b) |
185 | { |
186 | Q_D(KServiceGroup); |
187 | d->m_bAllowInline = _b; |
188 | } |
189 | |
190 | bool KServiceGroup::noDisplay() const |
191 | { |
192 | Q_D(const KServiceGroup); |
193 | return d->m_bNoDisplay || d->m_strCaption.startsWith(c: QLatin1Char('.')); |
194 | } |
195 | |
196 | QStringList KServiceGroup::suppressGenericNames() const |
197 | { |
198 | Q_D(const KServiceGroup); |
199 | return d->suppressGenericNames; |
200 | } |
201 | |
202 | void KServiceGroupPrivate::load(QDataStream &s) |
203 | { |
204 | QStringList groupList; |
205 | qint8 noDisplay; |
206 | qint8 ; |
207 | qint8 ; |
208 | qint8 _inlineAlias; |
209 | qint8 _allowInline; |
210 | s >> m_strCaption >> m_strIcon >> m_strComment >> groupList >> m_strBaseGroupName >> m_childCount >> noDisplay >> suppressGenericNames >> directoryEntryPath |
211 | >> sortOrder >> _showEmptyMenu >> inlineHeader >> _inlineAlias >> _allowInline; |
212 | |
213 | m_bNoDisplay = (noDisplay != 0); |
214 | m_bShowEmptyMenu = (_showEmptyMenu != 0); |
215 | m_bShowInlineHeader = (inlineHeader != 0); |
216 | m_bInlineAlias = (_inlineAlias != 0); |
217 | m_bAllowInline = (_allowInline != 0); |
218 | |
219 | if (m_bDeep) { |
220 | for (const QString &path : std::as_const(t&: groupList)) { |
221 | if (path.endsWith(c: QLatin1Char('/'))) { |
222 | KServiceGroup::Ptr serviceGroup; |
223 | serviceGroup = KSycocaPrivate::self()->serviceGroupFactory()->findGroupByDesktopPath(name: path, deep: false); |
224 | if (serviceGroup) { |
225 | m_serviceList.append(t: KServiceGroup::SPtr(serviceGroup)); |
226 | } |
227 | } else { |
228 | KService::Ptr service; |
229 | service = KSycocaPrivate::self()->serviceFactory()->findServiceByDesktopPath(name: path); |
230 | if (service) { |
231 | m_serviceList.append(t: KServiceGroup::SPtr(service)); |
232 | } |
233 | } |
234 | } |
235 | } |
236 | } |
237 | |
238 | void KServiceGroup::addEntry(const KSycocaEntry::Ptr &entry) |
239 | { |
240 | Q_D(KServiceGroup); |
241 | d->m_serviceList.append(t: entry); |
242 | } |
243 | |
244 | void KServiceGroupPrivate::save(QDataStream &s) |
245 | { |
246 | KSycocaEntryPrivate::save(s); |
247 | |
248 | QStringList groupList; |
249 | for (const KSycocaEntry::Ptr &p : std::as_const(t&: m_serviceList)) { |
250 | if (p->isType(t: KST_KService)) { |
251 | KService::Ptr service(static_cast<KService *>(p.data())); |
252 | groupList.append(t: service->entryPath()); |
253 | } else if (p->isType(t: KST_KServiceGroup)) { |
254 | KServiceGroup::Ptr serviceGroup(static_cast<KServiceGroup *>(p.data())); |
255 | groupList.append(t: serviceGroup->relPath()); |
256 | } else { |
257 | // fprintf(stderr, "KServiceGroup: Unexpected object in list!\n"); |
258 | } |
259 | } |
260 | |
261 | (void)childCount(); |
262 | |
263 | qint8 noDisplay = m_bNoDisplay ? 1 : 0; |
264 | qint8 = m_bShowEmptyMenu ? 1 : 0; |
265 | qint8 = m_bShowInlineHeader ? 1 : 0; |
266 | qint8 _inlineAlias = m_bInlineAlias ? 1 : 0; |
267 | qint8 _allowInline = m_bAllowInline ? 1 : 0; |
268 | s << m_strCaption << m_strIcon << m_strComment << groupList << m_strBaseGroupName << m_childCount << noDisplay << suppressGenericNames << directoryEntryPath |
269 | << sortOrder << _showEmptyMenu << inlineHeader << _inlineAlias << _allowInline; |
270 | } |
271 | |
272 | QList<KServiceGroup::Ptr> KServiceGroup::groupEntries(EntriesOptions options) |
273 | { |
274 | Q_D(KServiceGroup); |
275 | bool sort = options & SortEntries || options & AllowSeparators; |
276 | QList<KServiceGroup::Ptr> list; |
277 | const List tmp = d->entries(group: this, sort, excludeNoDisplay: options & ExcludeNoDisplay, allowSeparators: options & AllowSeparators, sortByGenericName: options & SortByGenericName); |
278 | for (const SPtr &ptr : tmp) { |
279 | if (ptr->isType(t: KST_KServiceGroup)) { |
280 | KServiceGroup::Ptr serviceGroup(static_cast<KServiceGroup *>(ptr.data())); |
281 | list.append(t: serviceGroup); |
282 | } else if (ptr->isType(t: KST_KServiceSeparator)) { |
283 | list.append(t: KServiceGroup::Ptr(static_cast<KServiceGroup *>(new KSycocaEntry()))); |
284 | } else if (sort && ptr->isType(t: KST_KService)) { |
285 | break; |
286 | } |
287 | } |
288 | return list; |
289 | } |
290 | |
291 | KService::List KServiceGroup::serviceEntries(EntriesOptions options) |
292 | { |
293 | Q_D(KServiceGroup); |
294 | bool sort = options & SortEntries || options & AllowSeparators; |
295 | QList<KService::Ptr> list; |
296 | const List tmp = d->entries(group: this, sort, excludeNoDisplay: options & ExcludeNoDisplay, allowSeparators: options & AllowSeparators, sortByGenericName: options & SortByGenericName); |
297 | bool foundService = false; |
298 | for (const SPtr &ptr : tmp) { |
299 | if (ptr->isType(t: KST_KService)) { |
300 | list.append(t: KService::Ptr(static_cast<KService *>(ptr.data()))); |
301 | foundService = true; |
302 | } else if (ptr->isType(t: KST_KServiceSeparator) && foundService) { |
303 | list.append(t: KService::Ptr(static_cast<KService *>(new KSycocaEntry()))); |
304 | } |
305 | } |
306 | return list; |
307 | } |
308 | |
309 | KServiceGroup::List KServiceGroup::entries(bool sort) |
310 | { |
311 | Q_D(KServiceGroup); |
312 | return d->entries(group: this, sort, excludeNoDisplay: true, allowSeparators: false, sortByGenericName: false); |
313 | } |
314 | |
315 | KServiceGroup::List KServiceGroup::entries(bool sort, bool excludeNoDisplay) |
316 | { |
317 | Q_D(KServiceGroup); |
318 | return d->entries(group: this, sort, excludeNoDisplay, allowSeparators: false, sortByGenericName: false); |
319 | } |
320 | |
321 | KServiceGroup::List KServiceGroup::entries(bool sort, bool excludeNoDisplay, bool allowSeparators, bool sortByGenericName) |
322 | { |
323 | Q_D(KServiceGroup); |
324 | return d->entries(group: this, sort, excludeNoDisplay, allowSeparators, sortByGenericName); |
325 | } |
326 | |
327 | static void addItem(KServiceGroup::List &sorted, const KSycocaEntry::Ptr &p, bool &addSeparator) |
328 | { |
329 | if (addSeparator && !sorted.isEmpty()) { |
330 | sorted.append(t: KSycocaEntry::Ptr(new KServiceSeparator())); |
331 | } |
332 | sorted.append(t: p); |
333 | addSeparator = false; |
334 | } |
335 | |
336 | KServiceGroup::List KServiceGroupPrivate::entries(KServiceGroup *group, bool sort, bool excludeNoDisplay, bool allowSeparators, bool sortByGenericName) |
337 | { |
338 | KSycoca::self()->ensureCacheValid(); |
339 | |
340 | // If the entries haven't been loaded yet, we have to reload ourselves |
341 | // together with the entries. We can't only load the entries afterwards |
342 | // since the offsets could have been changed if the database has changed. |
343 | |
344 | KServiceGroup::Ptr grp; |
345 | if (!m_bDeep) { |
346 | grp = KSycocaPrivate::self()->serviceGroupFactory()->findGroupByDesktopPath(name: path, deep: true); |
347 | |
348 | group = grp.data(); |
349 | if (nullptr == group) { // No guarantee that we still exist! |
350 | return KServiceGroup::List(); |
351 | } |
352 | } |
353 | |
354 | if (!sort) { |
355 | return group->d_func()->m_serviceList; |
356 | } |
357 | |
358 | // Sort the list alphabetically, according to locale. |
359 | // Groups come first, then services. |
360 | |
361 | // We use a QMap, for sorting using a stored temporary key. |
362 | typedef QMap<QByteArray, KServiceGroup::SPtr> SortedContainer; |
363 | SortedContainer slist; |
364 | SortedContainer glist; |
365 | const auto listService = group->d_func()->m_serviceList; |
366 | for (const KSycocaEntry::Ptr &p : listService) { |
367 | bool noDisplay = p->isType(t: KST_KServiceGroup) ? static_cast<KServiceGroup *>(p.data())->noDisplay() : static_cast<KService *>(p.data())->noDisplay(); |
368 | if (excludeNoDisplay && noDisplay) { |
369 | continue; |
370 | } |
371 | // Choose the right list |
372 | SortedContainer &list = p->isType(t: KST_KServiceGroup) ? glist : slist; |
373 | QString name; |
374 | if (p->isType(t: KST_KServiceGroup)) { |
375 | name = static_cast<KServiceGroup *>(p.data())->caption(); |
376 | } else if (sortByGenericName) { |
377 | name = static_cast<KService *>(p.data())->genericName() + QLatin1Char(' ') + p->name(); |
378 | } else { |
379 | name = p->name() + QLatin1Char(' ') + static_cast<KService *>(p.data())->genericName(); |
380 | } |
381 | |
382 | const QByteArray nameStr = name.toLocal8Bit(); |
383 | |
384 | QByteArray key; |
385 | // strxfrm() crashes on Solaris and strxfrm is not defined under wince |
386 | #if !defined(USE_SOLARIS) && !defined(_WIN32_WCE) |
387 | // maybe it'd be better to use wcsxfrm() where available |
388 | key.resize(size: name.length() * 4 + 1); |
389 | size_t ln = strxfrm(dest: key.data(), src: nameStr.constData(), n: key.size()); |
390 | if (ln != size_t(-1)) { |
391 | key.resize(size: ln); |
392 | if (int(ln) >= key.size()) { |
393 | // didn't fit? |
394 | ln = strxfrm(dest: key.data(), src: nameStr.constData(), n: key.size()); |
395 | if (ln == size_t(-1)) { |
396 | key = nameStr; |
397 | } |
398 | } |
399 | } else |
400 | #endif |
401 | { |
402 | key = nameStr; |
403 | } |
404 | list.insert(key, value: KServiceGroup::SPtr(p)); |
405 | } |
406 | |
407 | if (sortOrder.isEmpty()) { |
408 | sortOrder << QStringLiteral(":M" ); |
409 | sortOrder << QStringLiteral(":F" ); |
410 | sortOrder << QStringLiteral(":OIH IL[4]" ); // just inline header |
411 | } |
412 | |
413 | QString rp = path; |
414 | if (rp == QLatin1String("/" )) { |
415 | rp.clear(); |
416 | } |
417 | |
418 | // Iterate through the sort spec list. |
419 | // If an entry gets mentioned explicitly, we remove it from the sorted list |
420 | for (const QString &item : std::as_const(t&: sortOrder)) { |
421 | if (item.isEmpty()) { |
422 | continue; |
423 | } |
424 | if (item[0] == QLatin1Char('/')) { |
425 | QString groupPath = rp + QStringView(item).mid(pos: 1) + QLatin1Char('/'); |
426 | // Remove entry from sorted list of services. |
427 | for (SortedContainer::iterator it2 = glist.begin(); it2 != glist.end(); ++it2) { |
428 | const KServiceGroup::Ptr group(static_cast<KServiceGroup *>(it2.value().data())); |
429 | if (group->relPath() == groupPath) { |
430 | glist.erase(it: it2); |
431 | break; |
432 | } |
433 | } |
434 | } else if (item[0] != QLatin1Char(':')) { |
435 | // Remove entry from sorted list of services. |
436 | // TODO: Remove item from sortOrder-list if not found |
437 | // TODO: This prevents duplicates |
438 | for (SortedContainer::iterator it2 = slist.begin(); it2 != slist.end(); ++it2) { |
439 | const KService::Ptr service(static_cast<KService *>(it2.value().data())); |
440 | if (service->menuId() == item) { |
441 | slist.erase(it: it2); |
442 | break; |
443 | } |
444 | } |
445 | } |
446 | } |
447 | |
448 | KServiceGroup::List sorted; |
449 | |
450 | bool needSeparator = false; |
451 | // Iterate through the sort spec list. |
452 | // Add the entries to the list according to the sort spec. |
453 | for (QStringList::ConstIterator it(sortOrder.constBegin()); it != sortOrder.constEnd(); ++it) { |
454 | const QString &item = *it; |
455 | if (item.isEmpty()) { |
456 | continue; |
457 | } |
458 | if (item[0] == QLatin1Char(':')) { |
459 | // Special condition... |
460 | if (item == QLatin1String(":S" )) { |
461 | if (allowSeparators) { |
462 | needSeparator = true; |
463 | } |
464 | } else if (item.contains(s: QLatin1String(":O" ))) { |
465 | // todo parse attribute: |
466 | QString tmp(item); |
467 | tmp.remove(QStringLiteral(":O" )); |
468 | QStringList optionAttribute = tmp.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
469 | if (optionAttribute.isEmpty()) { |
470 | optionAttribute.append(t: tmp); |
471 | } |
472 | bool = false; |
473 | bool showInline = false; |
474 | bool = false; |
475 | bool showInlineAlias = false; |
476 | int inlineValue = -1; |
477 | |
478 | for (QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3) { |
479 | parseAttribute(item: *it3, showEmptyMenu, showInline, showInlineHeader, showInlineAlias, inlineValue); |
480 | } |
481 | for (SortedContainer::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2) { |
482 | KServiceGroup::Ptr group(static_cast<KServiceGroup *>(it2.value().data())); |
483 | group->setShowEmptyMenu(showEmptyMenu); |
484 | group->setAllowInline(showInline); |
485 | group->setShowInlineHeader(showInlineHeader); |
486 | group->setInlineAlias(showInlineAlias); |
487 | group->setInlineValue(inlineValue); |
488 | } |
489 | |
490 | } else if (item == QLatin1String(":M" )) { |
491 | // Add sorted list of sub-menus |
492 | for (SortedContainer::const_iterator it2 = glist.constBegin(); it2 != glist.constEnd(); ++it2) { |
493 | addItem(sorted, p: it2.value(), addSeparator&: needSeparator); |
494 | } |
495 | } else if (item == QLatin1String(":F" )) { |
496 | // Add sorted list of services |
497 | for (SortedContainer::const_iterator it2 = slist.constBegin(); it2 != slist.constEnd(); ++it2) { |
498 | addItem(sorted, p: it2.value(), addSeparator&: needSeparator); |
499 | } |
500 | } else if (item == QLatin1String(":A" )) { |
501 | // Add sorted lists of services and submenus |
502 | SortedContainer::Iterator it_s = slist.begin(); |
503 | SortedContainer::Iterator it_g = glist.begin(); |
504 | |
505 | while (true) { |
506 | if (it_s == slist.end()) { |
507 | if (it_g == glist.end()) { |
508 | break; // Done |
509 | } |
510 | |
511 | // Insert remaining sub-menu |
512 | addItem(sorted, p: it_g.value(), addSeparator&: needSeparator); |
513 | it_g++; |
514 | } else if (it_g == glist.end()) { |
515 | // Insert remaining service |
516 | addItem(sorted, p: it_s.value(), addSeparator&: needSeparator); |
517 | it_s++; |
518 | } else if (it_g.key() < it_s.key()) { |
519 | // Insert sub-menu first |
520 | addItem(sorted, p: it_g.value(), addSeparator&: needSeparator); |
521 | it_g++; |
522 | } else { |
523 | // Insert service first |
524 | addItem(sorted, p: it_s.value(), addSeparator&: needSeparator); |
525 | it_s++; |
526 | } |
527 | } |
528 | } |
529 | } else if (item[0] == QLatin1Char('/')) { |
530 | QString groupPath = rp + QStringView(item).mid(pos: 1) + QLatin1Char('/'); |
531 | |
532 | for (KServiceGroup::List::ConstIterator it2(group->d_func()->m_serviceList.constBegin()); it2 != group->d_func()->m_serviceList.constEnd(); ++it2) { |
533 | if (!(*it2)->isType(t: KST_KServiceGroup)) { |
534 | continue; |
535 | } |
536 | KServiceGroup::Ptr group(static_cast<KServiceGroup *>((*it2).data())); |
537 | if (group->relPath() == groupPath) { |
538 | if (!excludeNoDisplay || !group->noDisplay()) { |
539 | ++it; |
540 | const QString &nextItem = (it == sortOrder.constEnd()) ? QString() : *it; |
541 | |
542 | if (nextItem.startsWith(s: QLatin1String(":O" ))) { |
543 | QString tmp(nextItem); |
544 | tmp.remove(QStringLiteral(":O" )); |
545 | QStringList optionAttribute = tmp.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
546 | if (optionAttribute.isEmpty()) { |
547 | optionAttribute.append(t: tmp); |
548 | } |
549 | bool = false; |
550 | bool bShowInline = false; |
551 | bool = false; |
552 | bool bShowInlineAlias = false; |
553 | int inlineValue = -1; |
554 | for (const QString &opt_attr : std::as_const(t&: optionAttribute)) { |
555 | parseAttribute(item: opt_attr, showEmptyMenu&: bShowEmptyMenu, showInline&: bShowInline, showInlineHeader&: bShowInlineHeader, showInlineAlias&: bShowInlineAlias, inlineValue); |
556 | group->setShowEmptyMenu(bShowEmptyMenu); |
557 | group->setAllowInline(bShowInline); |
558 | group->setShowInlineHeader(bShowInlineHeader); |
559 | group->setInlineAlias(bShowInlineAlias); |
560 | group->setInlineValue(inlineValue); |
561 | } |
562 | } else { |
563 | it--; |
564 | } |
565 | |
566 | addItem(sorted, p: KServiceGroup::SPtr(group), addSeparator&: needSeparator); |
567 | } |
568 | break; |
569 | } |
570 | } |
571 | } else { |
572 | for (KServiceGroup::List::ConstIterator it2(group->d_func()->m_serviceList.constBegin()); it2 != group->d_func()->m_serviceList.constEnd(); ++it2) { |
573 | if (!(*it2)->isType(t: KST_KService)) { |
574 | continue; |
575 | } |
576 | const KService::Ptr service(static_cast<KService *>((*it2).data())); |
577 | if (service->menuId() == item) { |
578 | if (!excludeNoDisplay || !service->noDisplay()) { |
579 | addItem(sorted, p: (*it2), addSeparator&: needSeparator); |
580 | } |
581 | break; |
582 | } |
583 | } |
584 | } |
585 | } |
586 | |
587 | return sorted; |
588 | } |
589 | |
590 | void KServiceGroupPrivate::parseAttribute(const QString &item, |
591 | bool &, |
592 | bool &showInline, |
593 | bool &, |
594 | bool &showInlineAlias, |
595 | int &inlineValue) |
596 | { |
597 | if (item == QLatin1String("ME" )) { // menu empty |
598 | showEmptyMenu = true; |
599 | } else if (item == QLatin1String("NME" )) { // not menu empty |
600 | showEmptyMenu = false; |
601 | } else if (item == QLatin1String("I" )) { // inline menu ! |
602 | showInline = true; |
603 | } else if (item == QLatin1String("NI" )) { // not inline menu! |
604 | showInline = false; |
605 | } else if (item == QLatin1String("IH" )) { // inline header! |
606 | showInlineHeader = true; |
607 | } else if (item == QLatin1String("NIH" )) { // not inline header! |
608 | showInlineHeader = false; |
609 | } else if (item == QLatin1String("IA" )) { // inline alias! |
610 | showInlineAlias = true; |
611 | } else if (item == QLatin1String("NIA" )) { // not inline alias! |
612 | showInlineAlias = false; |
613 | } else if ((item).contains(s: QLatin1String("IL" ))) { // inline limit! |
614 | QString tmp(item); |
615 | tmp.remove(QStringLiteral("IL[" )); |
616 | tmp.remove(c: QLatin1Char(']')); |
617 | bool ok; |
618 | int _inlineValue = tmp.toInt(ok: &ok); |
619 | if (!ok) { // error |
620 | _inlineValue = -1; |
621 | } |
622 | inlineValue = _inlineValue; |
623 | } else { |
624 | qCDebug(SERVICES) << "This attribute is not supported:" << item; |
625 | } |
626 | } |
627 | |
628 | void KServiceGroup::setLayoutInfo(const QStringList &layout) |
629 | { |
630 | Q_D(KServiceGroup); |
631 | d->sortOrder = layout; |
632 | } |
633 | |
634 | QStringList KServiceGroup::layoutInfo() const |
635 | { |
636 | Q_D(const KServiceGroup); |
637 | return d->sortOrder; |
638 | } |
639 | |
640 | KServiceGroup::Ptr KServiceGroup::root() |
641 | { |
642 | KSycoca::self()->ensureCacheValid(); |
643 | return KSycocaPrivate::self()->serviceGroupFactory()->findGroupByDesktopPath(QStringLiteral("/" ), deep: true); |
644 | } |
645 | |
646 | KServiceGroup::Ptr KServiceGroup::group(const QString &relPath) |
647 | { |
648 | if (relPath.isEmpty()) { |
649 | return root(); |
650 | } |
651 | KSycoca::self()->ensureCacheValid(); |
652 | return KSycocaPrivate::self()->serviceGroupFactory()->findGroupByDesktopPath(name: relPath, deep: true); |
653 | } |
654 | |
655 | KServiceGroup::Ptr KServiceGroup::childGroup(const QString &parent) |
656 | { |
657 | KSycoca::self()->ensureCacheValid(); |
658 | return KSycocaPrivate::self()->serviceGroupFactory()->findGroupByDesktopPath(name: QLatin1String("#parent#" ) + parent, deep: true); |
659 | } |
660 | |
661 | QString KServiceGroup::baseGroupName() const |
662 | { |
663 | return d_func()->m_strBaseGroupName; |
664 | } |
665 | |
666 | QString KServiceGroup::directoryEntryPath() const |
667 | { |
668 | Q_D(const KServiceGroup); |
669 | return d->directoryEntryPath; |
670 | } |
671 | |
672 | class KServiceSeparatorPrivate : public KSycocaEntryPrivate |
673 | { |
674 | public: |
675 | K_SYCOCATYPE(KST_KServiceSeparator, KSycocaEntryPrivate) |
676 | |
677 | KServiceSeparatorPrivate(const QString &name) |
678 | : KSycocaEntryPrivate(name) |
679 | { |
680 | } |
681 | |
682 | QString name() const override; |
683 | }; |
684 | |
685 | QString KServiceSeparatorPrivate::name() const |
686 | { |
687 | return QStringLiteral("separator" ); |
688 | } |
689 | |
690 | KServiceSeparator::KServiceSeparator() |
691 | : KSycocaEntry(*new KServiceSeparatorPrivate(QStringLiteral("separator" ))) |
692 | { |
693 | } |
694 | |
695 | KServiceSeparator::~KServiceSeparator() |
696 | { |
697 | } |
698 | |