int KServiceGroup::childCount() { if (m_childCount == -1) { m_childCount = 0; for( List::ConstIterator it = m_serviceList.begin(); it != m_serviceList.end(); it++) { KSycocaEntry *p = (*it); if (p->isType(KST_KService)) { KService *service = static_cast<KService *>(p); if (!service->noDisplay()) m_childCount++; } else if (p->isType(KST_KServiceGroup)) { KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p); m_childCount += serviceGroup->childCount(); } } } return m_childCount; }
KServiceGroup::List KServiceGroup::entries(bool sort, bool excludeNoDisplay, bool allowSeparators, bool sortByGenericName) { KServiceGroup *group = this; // If the entries haven't been loaded yet, we have to reload ourselves // together with the entries. We can't only load the entries afterwards // since the offsets could have been changed if the database has changed. if (!m_bDeep) { group = KServiceGroupFactory::self()->findGroupByDesktopPath(relPath(), true); if (0 == group) // No guarantee that we still exist! return List(); } if (!sort) return group->m_serviceList; // Sort the list alphabetically, according to locale. // Groups come first, then services. KSortableValueList<SPtr,QCString> slist; KSortableValueList<SPtr,QCString> glist; for (List::ConstIterator it(group->m_serviceList.begin()); it != group->m_serviceList.end(); ++it) { KSycocaEntry *p = (*it); bool noDisplay = p->isType(KST_KServiceGroup) ? static_cast<KServiceGroup *>(p)->noDisplay() : static_cast<KService *>(p)->noDisplay(); if (excludeNoDisplay && noDisplay) continue; // Choose the right list KSortableValueList<SPtr,QCString> & list = p->isType(KST_KServiceGroup) ? glist : slist; QString name; if (p->isType(KST_KServiceGroup)) name = static_cast<KServiceGroup *>(p)->caption(); else if (sortByGenericName) name = static_cast<KService *>(p)->genericName() + " " + p->name(); else name = p->name() + " " + static_cast<KService *>(p)->genericName(); QCString key( name.length() * 4 + 1 ); // strxfrm() crashes on Solaris #ifndef USE_SOLARIS // maybe it'd be better to use wcsxfrm() where available size_t ln = strxfrm( key.data(), name.local8Bit().data(), key.size()); if( ln != size_t( -1 )) { if( ln >= key.size()) { // didn't fit? key.resize( ln + 1 ); if( strxfrm( key.data(), name.local8Bit().data(), key.size()) == size_t( -1 )) key = name.local8Bit(); } } else #endif { key = name.local8Bit(); } list.insert(key,SPtr(*it)); } // Now sort slist.sort(); glist.sort(); if (d->sortOrder.isEmpty()) { d->sortOrder << ":M"; d->sortOrder << ":F"; d->sortOrder << ":OIH IL[4]"; //just inline header } QString rp = relPath(); if(rp == "/") rp = QString::null; // Iterate through the sort spec list. // If an entry gets mentioned explicitly, we remove it from the sorted list for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it) { const QString &item = *it; if (item.isEmpty()) continue; if (item[0] == '/') { QString groupPath = rp + item.mid(1) + "/"; // Remove entry from sorted list of services. for(KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2) { KServiceGroup *group = (KServiceGroup *)((KSycocaEntry *)((*it2).value())); if (group->relPath() == groupPath) { glist.remove(it2); break; } } } else if (item[0] != ':') { // Remove entry from sorted list of services. // TODO: Remove item from sortOrder-list if not found // TODO: This prevents duplicates for(KSortableValueList<SPtr,QCString>::Iterator it2 = slist.begin(); it2 != slist.end(); ++it2) { KService *service = (KService *)((KSycocaEntry *)((*it2).value())); if (service->menuId() == item) { slist.remove(it2); break; } } } } List sorted; bool needSeparator = false; // Iterate through the sort spec list. // Add the entries to the list according to the sort spec. for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it) { const QString &item = *it; if (item.isEmpty()) continue; if (item[0] == ':') { // Special condition... if (item == ":S") { if (allowSeparators) needSeparator = true; } else if ( item.contains( ":O" ) ) { //todo parse attribute: QString tmp( item ); tmp = tmp.remove(":O"); QStringList optionAttribute = QStringList::split(" ",tmp); if( optionAttribute.count()==0) optionAttribute.append(tmp); bool showEmptyMenu = false; bool showInline = false; bool showInlineHeader = false; bool showInlineAlias = false; int inlineValue = -1; for ( QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3 ) { parseAttribute( *it3, showEmptyMenu, showInline, showInlineHeader, showInlineAlias, inlineValue ); } for(KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2) { KServiceGroup *group = (KServiceGroup *)((KSycocaEntry *)(*it2).value()); group->setShowEmptyMenu( showEmptyMenu ); group->setAllowInline( showInline ); group->setShowInlineHeader( showInlineHeader ); group->setInlineAlias( showInlineAlias ); group->setInlineValue( inlineValue ); } } else if (item == ":M") { // Add sorted list of sub-menus for(KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2) { addItem(sorted, (*it2).value(), needSeparator); } } else if (item == ":F") { // Add sorted list of services for(KSortableValueList<SPtr,QCString>::Iterator it2 = slist.begin(); it2 != slist.end(); ++it2) { addItem(sorted, (*it2).value(), needSeparator); } } else if (item == ":A") { // Add sorted lists of services and submenus KSortableValueList<SPtr,QCString>::Iterator it_s = slist.begin(); KSortableValueList<SPtr,QCString>::Iterator it_g = glist.begin(); while(true) { if (it_s == slist.end()) { if (it_g == glist.end()) break; // Done // Insert remaining sub-menu addItem(sorted, (*it_g).value(), needSeparator); it_g++; } else if (it_g == glist.end()) { // Insert remaining service addItem(sorted, (*it_s).value(), needSeparator); it_s++; } else if ((*it_g).index() < (*it_s).index()) { // Insert sub-menu first addItem(sorted, (*it_g).value(), needSeparator); it_g++; } else { // Insert service first addItem(sorted, (*it_s).value(), needSeparator); it_s++; } } } } else if (item[0] == '/') { QString groupPath = rp + item.mid(1) + "/"; for (List::ConstIterator it2(group->m_serviceList.begin()); it2 != group->m_serviceList.end(); ++it2) { if (!(*it2)->isType(KST_KServiceGroup)) continue; KServiceGroup *group = (KServiceGroup *)((KSycocaEntry *)(*it2)); if (group->relPath() == groupPath) { if (!excludeNoDisplay || !group->noDisplay()) { const QString &nextItem = *( ++it ); if ( nextItem.startsWith( ":O" ) ) { QString tmp( nextItem ); tmp = tmp.remove(":O"); QStringList optionAttribute = QStringList::split(" ",tmp); if( optionAttribute.count()==0) optionAttribute.append(tmp); bool bShowEmptyMenu = false; bool bShowInline = false; bool bShowInlineHeader = false; bool bShowInlineAlias = false; int inlineValue = -1; for ( QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3 ) { parseAttribute( *it3 , bShowEmptyMenu, bShowInline, bShowInlineHeader, bShowInlineAlias , inlineValue ); group->setShowEmptyMenu( bShowEmptyMenu ); group->setAllowInline( bShowInline ); group->setShowInlineHeader( bShowInlineHeader ); group->setInlineAlias( bShowInlineAlias ); group->setInlineValue( inlineValue ); } } else it--; addItem(sorted, (group), needSeparator); } break; } } } else { for (List::ConstIterator it2(group->m_serviceList.begin()); it2 != group->m_serviceList.end(); ++it2) { if (!(*it2)->isType(KST_KService)) continue; KService *service = (KService *)((KSycocaEntry *)(*it2)); if (service->menuId() == item) { if (!excludeNoDisplay || !service->noDisplay()) addItem(sorted, (*it2), needSeparator); break; } } } } return sorted; }