void OCompletion::extractStringsFromNodeCI( const OCompTreeNode *node, const QString& beginning, const QString& restString, OCompletionMatchesWrapper *matches ) const { if ( restString.isEmpty() ) { extractStringsFromNode( node, beginning, matches, false /*noweight*/ ); return; } QChar ch1 = restString.at(0); QString newRest = restString.mid(1); OCompTreeNode *child1, *child2; child1 = node->find( ch1 ); // the correct match if ( child1 ) extractStringsFromNodeCI( child1, beginning + *child1, newRest, matches ); // append the case insensitive matches, if available if ( ch1.isLetter() ) { // find out if we have to lower or upper it. Is there a better way? QChar ch2 = ch1.lower(); if ( ch1 == ch2 ) ch2 = ch1.upper(); if ( ch1 != ch2 ) { child2 = node->find( ch2 ); if ( child2 ) extractStringsFromNodeCI( child2, beginning + *child2, newRest, matches ); } } }
QStringList OCompletion::items() const { OCompletionMatchesWrapper list; // unsorted bool addWeight = (myOrder == Weighted); extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight ); return list.list(); }
void OCompletion::findAllCompletions(const QString& string, OCompletionMatchesWrapper *matches, bool& hasMultipleMatches) const { //qDebug( "OCompletion: finding all completions for %s", (const char*) string ); if ( string.isEmpty() ) return; if ( myIgnoreCase ) { // case insensitive completion extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches ); hasMultipleMatches = (matches->count() > 1); return; } QChar ch; QString completion; const OCompTreeNode *node = myTreeRoot; // start at the tree-root and try to find the search-string for( uint i = 0; i < string.length(); i++ ) { ch = string.at( i ); node = node->find( ch ); if ( node ) completion += ch; else return; // no completion -> return empty list } // Now we have the last node of the to be completed string. // Follow it as long as it has exactly one child (= longest possible // completion) while ( node->childrenCount() == 1 ) { node = node->firstChild(); if ( !node->isNull() ) completion += *node; // kdDebug() << completion << node->latin1(); } // there is just one single match) if ( node->childrenCount() == 0 ) matches->append( node->weight(), completion ); else { // node has more than one child // -> recursively find all remaining completions hasMultipleMatches = true; extractStringsFromNode( node, completion, matches ); } }
void KCompletion::extractStringsFromNode( const KCompTreeNode *node, const QString& beginning, KCompletionMatchesWrapper *matches, bool addWeight ) const { if ( !node || !matches ) return; // kDebug() << "Beginning: " << beginning << endl; const KCompTreeChildren *list = node->children(); QString string; QString w; // loop thru all children for ( KCompTreeNode *cur = list->begin(); cur ; cur = cur->next) { string = beginning; node = cur; if ( !node->isNull() ) string += *node; while ( node && node->childrenCount() == 1 ) { node = node->firstChild(); if ( node->isNull() ) break; string += *node; } if ( node && node->isNull() ) { // we found a leaf if ( addWeight ) { // add ":num" to the string to store the weighting string += ':'; w.setNum( node->weight() ); string.append( w ); } matches->append( node->weight(), string ); } // recursively find all other strings. if ( node && node->childrenCount() > 1 ) extractStringsFromNode( node, string, matches, addWeight ); } }
QStringList KCompletion::substringCompletion( const QString& string ) const { // get all items in the tree, possibly in sorted order bool sorted = (myOrder == Weighted); KCompletionMatchesWrapper allItems( sorted ); extractStringsFromNode( myTreeRoot, QString::null, &allItems, false ); QStringList list = allItems.list(); // subStringMatches is invoked manually, via a shortcut, so we should // beep here, if necessary. if ( list.isEmpty() ) { doBeep( NoMatch ); return list; } if ( string.isEmpty() ) { // shortcut postProcessMatches( &list ); return list; } QStringList matches; QStringList::ConstIterator it = list.begin(); for( ; it != list.end(); ++it ) { QString item = *it; if ( item.find( string, 0, false ) != -1 ) { // always case insensitive matches.append( item ); } } postProcessMatches( &matches ); if ( matches.isEmpty() ) doBeep( NoMatch ); return matches; }