• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kcompletion.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
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., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 
00021 #include <kapplication.h>
00022 #include <kdebug.h>
00023 #include <klocale.h>
00024 #include <knotifyclient.h>
00025 #include <kglobal.h>
00026 
00027 #include <qptrvector.h>
00028 
00029 #include "kcompletion.h"
00030 #include "kcompletion_private.h"
00031 
00032 
00033 class KCompletionPrivate
00034 {
00035 public:
00036     // not a member to avoid #including kcompletion_private.h from kcompletion.h
00037     // list used for nextMatch() and previousMatch()
00038     KCompletionMatchesWrapper matches;
00039 };
00040 
00041 KCompletion::KCompletion()
00042 {
00043     d = new KCompletionPrivate;
00044 
00045     myCompletionMode = KGlobalSettings::completionMode();
00046     myTreeRoot = new KCompTreeNode;
00047     myBeep       = true;
00048     myIgnoreCase = false;
00049     myHasMultipleMatches = false;
00050     myRotationIndex = 0;
00051     setOrder( Insertion );
00052 }
00053 
00054 KCompletion::~KCompletion()
00055 {
00056     delete d;
00057     delete myTreeRoot;
00058 }
00059 
00060 void KCompletion::setOrder( CompOrder order )
00061 {
00062     myOrder = order;
00063     d->matches.setSorting( order == Weighted );
00064 }
00065 
00066 void KCompletion::setIgnoreCase( bool ignoreCase )
00067 {
00068     myIgnoreCase = ignoreCase;
00069 }
00070 
00071 void KCompletion::setItems( const QStringList& items )
00072 {
00073     clear();
00074     insertItems( items );
00075 }
00076 
00077 
00078 void KCompletion::insertItems( const QStringList& items )
00079 {
00080     bool weighted = (myOrder == Weighted);
00081     QStringList::ConstIterator it;
00082     if ( weighted ) { // determine weight
00083         for ( it = items.begin(); it != items.end(); ++it )
00084             addWeightedItem( *it );
00085     }
00086     else {
00087         for ( it = items.begin(); it != items.end(); ++it )
00088             addItem( *it, 0 );
00089     }
00090 }
00091 
00092 QStringList KCompletion::items() const
00093 {
00094     KCompletionMatchesWrapper list; // unsorted
00095     bool addWeight = (myOrder == Weighted);
00096     extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight );
00097 
00098     return list.list();
00099 }
00100 
00101 bool KCompletion::isEmpty() const
00102 {
00103   return (myTreeRoot->childrenCount() == 0);
00104 }
00105 
00106 void KCompletion::addItem( const QString& item )
00107 {
00108     d->matches.clear();
00109     myRotationIndex = 0;
00110     myLastString = QString::null;
00111 
00112     addItem( item, 0 );
00113 }
00114 
00115 void KCompletion::addItem( const QString& item, uint weight )
00116 {
00117     if ( item.isEmpty() )
00118         return;
00119 
00120     KCompTreeNode *node = myTreeRoot;
00121     uint len = item.length();
00122 
00123     bool sorted = (myOrder == Sorted);
00124     bool weighted = ((myOrder == Weighted) && weight > 1);
00125 
00126     // knowing the weight of an item, we simply add this weight to all of its
00127     // nodes.
00128 
00129     for ( uint i = 0; i < len; i++ ) {
00130         node = node->insert( item.at(i), sorted );
00131         if ( weighted )
00132             node->confirm( weight -1 ); // node->insert() sets weighting to 1
00133     }
00134 
00135     // add 0x0-item as delimiter with evtl. weight
00136     node = node->insert( 0x0, true );
00137     if ( weighted )
00138         node->confirm( weight -1 );
00139 //     qDebug("*** added: %s (%i)", item.latin1(), node->weight());
00140 }
00141 
00142 void KCompletion::addWeightedItem( const QString& item )
00143 {
00144     if ( myOrder != Weighted ) {
00145         addItem( item, 0 );
00146         return;
00147     }
00148 
00149     uint len = item.length();
00150     uint weight = 0;
00151 
00152     // find out the weighting of this item (appended to the string as ":num")
00153     int index = item.findRev(':');
00154     if ( index > 0 ) {
00155         bool ok;
00156         weight = item.mid( index + 1 ).toUInt( &ok );
00157         if ( !ok )
00158             weight = 0;
00159 
00160         len = index; // only insert until the ':'
00161     }
00162 
00163     addItem( item.left( len ), weight );
00164     return;
00165 }
00166 
00167 
00168 void KCompletion::removeItem( const QString& item )
00169 {
00170     d->matches.clear();
00171     myRotationIndex = 0;
00172     myLastString = QString::null;
00173 
00174     myTreeRoot->remove( item );
00175 }
00176 
00177 
00178 void KCompletion::clear()
00179 {
00180     d->matches.clear();
00181     myRotationIndex = 0;
00182     myLastString = QString::null;
00183 
00184     delete myTreeRoot;
00185     myTreeRoot = new KCompTreeNode;
00186 }
00187 
00188 
00189 QString KCompletion::makeCompletion( const QString& string )
00190 {
00191     if ( myCompletionMode == KGlobalSettings::CompletionNone )
00192         return QString::null;
00193 
00194     //kdDebug(0) << "KCompletion: completing: " << string << endl;
00195 
00196     d->matches.clear();
00197     myRotationIndex = 0;
00198     myHasMultipleMatches = false;
00199     myLastMatch = myCurrentMatch;
00200 
00201     // in Shell-completion-mode, emit all matches when we get the same
00202     // complete-string twice
00203     if ( myCompletionMode == KGlobalSettings::CompletionShell &&
00204          string == myLastString ) {
00205         // Don't use d->matches since calling postProcessMatches()
00206         // on d->matches here would interfere with call to
00207         // postProcessMatch() during rotation
00208     
00209         findAllCompletions( string, &d->matches, myHasMultipleMatches );
00210         QStringList l = d->matches.list();
00211         postProcessMatches( &l );
00212         emit matches( l );
00213 
00214         if ( l.isEmpty() )
00215             doBeep( NoMatch );
00216     
00217         return QString::null;
00218     }
00219 
00220     QString completion;
00221     // in case-insensitive popup mode, we search all completions at once
00222     if ( myCompletionMode == KGlobalSettings::CompletionPopup ||
00223          myCompletionMode == KGlobalSettings::CompletionPopupAuto ) {
00224         findAllCompletions( string, &d->matches, myHasMultipleMatches );
00225         if ( !d->matches.isEmpty() )
00226             completion = d->matches.first();
00227     }
00228     else
00229         completion = findCompletion( string );
00230 
00231     if ( myHasMultipleMatches )
00232         emit multipleMatches();
00233 
00234     myLastString = string;
00235     myCurrentMatch = completion;
00236 
00237     postProcessMatch( &completion );
00238 
00239     if ( !string.isEmpty() ) { // only emit match when string is not empty
00240         //kdDebug(0) << "KCompletion: Match: " << completion << endl;
00241         emit match( completion );
00242     }
00243 
00244     if ( completion.isNull() )
00245         doBeep( NoMatch );
00246 
00247     return completion;
00248 }
00249 
00250 
00251 QStringList KCompletion::substringCompletion( const QString& string ) const
00252 {
00253     // get all items in the tree, possibly in sorted order
00254     bool sorted = (myOrder == Weighted);
00255     KCompletionMatchesWrapper allItems( sorted );
00256     extractStringsFromNode( myTreeRoot, QString::null, &allItems, false );
00257 
00258     QStringList list = allItems.list();
00259 
00260     // subStringMatches is invoked manually, via a shortcut, so we should
00261     // beep here, if necessary.
00262     if ( list.isEmpty() ) {
00263         doBeep( NoMatch );
00264         return list;
00265     }
00266 
00267     if ( string.isEmpty() ) { // shortcut
00268         postProcessMatches( &list );
00269         return list;
00270     }
00271 
00272     QStringList matches;
00273     QStringList::ConstIterator it = list.begin();
00274 
00275     for( ; it != list.end(); ++it ) {
00276         QString item = *it;
00277         if ( item.find( string, 0, false ) != -1 ) { // always case insensitive
00278             matches.append( item );
00279         }
00280     }
00281 
00282     postProcessMatches( &matches );
00283 
00284     if ( matches.isEmpty() )
00285         doBeep( NoMatch );
00286 
00287     return matches;
00288 }
00289 
00290 
00291 void KCompletion::setCompletionMode( KGlobalSettings::Completion mode )
00292 {
00293     myCompletionMode = mode;
00294 }
00295 
00296 QStringList KCompletion::allMatches()
00297 {
00298     // Don't use d->matches since calling postProcessMatches()
00299     // on d->matches here would interfere with call to
00300     // postProcessMatch() during rotation
00301     KCompletionMatchesWrapper matches( myOrder == Weighted );
00302     bool dummy;
00303     findAllCompletions( myLastString, &matches, dummy );
00304     QStringList l = matches.list();
00305     postProcessMatches( &l );
00306     return l;
00307 }
00308 
00309 KCompletionMatches KCompletion::allWeightedMatches()
00310 {
00311     // Don't use d->matches since calling postProcessMatches()
00312     // on d->matches here would interfere with call to
00313     // postProcessMatch() during rotation
00314     KCompletionMatchesWrapper matches( myOrder == Weighted );
00315     bool dummy;
00316     findAllCompletions( myLastString, &matches, dummy );
00317     KCompletionMatches ret( matches );
00318     postProcessMatches( &ret );
00319     return ret;
00320 }
00321 
00322 QStringList KCompletion::allMatches( const QString &string )
00323 {
00324     KCompletionMatchesWrapper matches( myOrder == Weighted );
00325     bool dummy;
00326     findAllCompletions( string, &matches, dummy );
00327     QStringList l = matches.list();
00328     postProcessMatches( &l );
00329     return l;
00330 }
00331 
00332 KCompletionMatches KCompletion::allWeightedMatches( const QString &string )
00333 {
00334     KCompletionMatchesWrapper matches( myOrder == Weighted );
00335     bool dummy;
00336     findAllCompletions( string, &matches, dummy );
00337     KCompletionMatches ret( matches );
00338     postProcessMatches( &ret );
00339     return ret;
00340 }
00341 
00344 
00345 
00346 QString KCompletion::nextMatch()
00347 {
00348     QString completion;
00349     myLastMatch = myCurrentMatch;
00350 
00351     if ( d->matches.isEmpty() ) {
00352         findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
00353         completion = d->matches.first();
00354         myCurrentMatch = completion;
00355         myRotationIndex = 0;
00356         postProcessMatch( &completion );
00357         emit match( completion );
00358         return completion;
00359     }
00360 
00361     QStringList matches = d->matches.list();
00362     myLastMatch = matches[ myRotationIndex++ ];
00363 
00364     if ( myRotationIndex == matches.count() -1 )
00365         doBeep( Rotation ); // indicate last matching item -> rotating
00366 
00367     else if ( myRotationIndex == matches.count() )
00368         myRotationIndex = 0;
00369 
00370     completion = matches[ myRotationIndex ];
00371     myCurrentMatch = completion;
00372     postProcessMatch( &completion );
00373     emit match( completion );
00374     return completion;
00375 }
00376 
00377 
00378 
00379 QString KCompletion::previousMatch()
00380 {
00381     QString completion;
00382     myLastMatch = myCurrentMatch;
00383 
00384     if ( d->matches.isEmpty() ) {
00385         findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
00386         completion = d->matches.last();
00387         myCurrentMatch = completion;
00388         myRotationIndex = 0;
00389         postProcessMatch( &completion );
00390         emit match( completion );
00391         return completion;
00392     }
00393 
00394     QStringList matches = d->matches.list();
00395     myLastMatch = matches[ myRotationIndex ];
00396     if ( myRotationIndex == 1 )
00397         doBeep( Rotation ); // indicate first item -> rotating
00398 
00399     else if ( myRotationIndex == 0 )
00400         myRotationIndex = matches.count();
00401 
00402     myRotationIndex--;
00403 
00404     completion = matches[ myRotationIndex ];
00405     myCurrentMatch = completion;
00406     postProcessMatch( &completion );
00407     emit match( completion );
00408     return completion;
00409 }
00410 
00411 
00412 
00413 // tries to complete "string" from the tree-root
00414 QString KCompletion::findCompletion( const QString& string )
00415 {
00416     QChar ch;
00417     QString completion;
00418     const KCompTreeNode *node = myTreeRoot;
00419 
00420     // start at the tree-root and try to find the search-string
00421     for( uint i = 0; i < string.length(); i++ ) {
00422         ch = string.at( i );
00423         node = node->find( ch );
00424 
00425         if ( node )
00426             completion += ch;
00427         else
00428             return QString::null; // no completion
00429     }
00430 
00431     // Now we have the last node of the to be completed string.
00432     // Follow it as long as it has exactly one child (= longest possible
00433     // completion)
00434 
00435     while ( node->childrenCount() == 1 ) {
00436         node = node->firstChild();
00437         if ( !node->isNull() )
00438             completion += *node;
00439     }
00440     // if multiple matches and auto-completion mode
00441     // -> find the first complete match
00442     if ( node && node->childrenCount() > 1 ) {
00443         myHasMultipleMatches = true;
00444     
00445         if ( myCompletionMode == KGlobalSettings::CompletionAuto ) {
00446             myRotationIndex = 1;
00447             if (myOrder != Weighted) {
00448                 while ( (node = node->firstChild()) ) {
00449                     if ( !node->isNull() )
00450                         completion += *node;
00451                     else
00452                         break;
00453                 }
00454             }
00455             else {
00456                 // don't just find the "first" match, but the one with the
00457                 // highest priority
00458         
00459                 const KCompTreeNode* temp_node = 0L;
00460                 while(1) {
00461                     int count = node->childrenCount();
00462                     temp_node = node->firstChild();
00463                     uint weight = temp_node->weight();
00464                     const KCompTreeNode* hit = temp_node;
00465                     for( int i = 1; i < count; i++ ) {
00466                         temp_node = node->childAt(i);
00467                         if( temp_node->weight() > weight ) {
00468                             hit = temp_node;
00469                             weight = hit->weight();
00470                         }
00471                     }
00472                     // 0x0 has the highest priority -> we have the best match
00473                     if ( hit->isNull() )
00474                         break;
00475 
00476                     node = hit;
00477                     completion += *node;
00478                 }
00479             }
00480         }
00481 
00482         else
00483             doBeep( PartialMatch ); // partial match -> beep
00484     }
00485 
00486     return completion;
00487 }
00488 
00489 
00490 void KCompletion::findAllCompletions(const QString& string,
00491                                      KCompletionMatchesWrapper *matches,
00492                                      bool& hasMultipleMatches) const
00493 {
00494     //kdDebug(0) << "*** finding all completions for " << string << endl;
00495 
00496     if ( string.isEmpty() )
00497         return;
00498 
00499     if ( myIgnoreCase ) { // case insensitive completion
00500         extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches );
00501         hasMultipleMatches = (matches->count() > 1);
00502         return;
00503     }
00504 
00505     QChar ch;
00506     QString completion;
00507     const KCompTreeNode *node = myTreeRoot;
00508 
00509     // start at the tree-root and try to find the search-string
00510     for( uint i = 0; i < string.length(); i++ ) {
00511         ch = string.at( i );
00512         node = node->find( ch );
00513 
00514         if ( node )
00515             completion += ch;
00516         else
00517             return; // no completion -> return empty list
00518     }
00519     
00520     // Now we have the last node of the to be completed string.
00521     // Follow it as long as it has exactly one child (= longest possible
00522     // completion)
00523 
00524     while ( node->childrenCount() == 1 ) {
00525         node = node->firstChild();
00526         if ( !node->isNull() )
00527             completion += *node;
00528         // kdDebug() << completion << node->latin1();
00529     }
00530 
00531 
00532     // there is just one single match)
00533     if ( node->childrenCount() == 0 )
00534         matches->append( node->weight(), completion );
00535 
00536     else {
00537         // node has more than one child
00538         // -> recursively find all remaining completions
00539         hasMultipleMatches = true;
00540         extractStringsFromNode( node, completion, matches );
00541     }
00542 }
00543 
00544 
00545 void KCompletion::extractStringsFromNode( const KCompTreeNode *node,
00546                                           const QString& beginning,
00547                                           KCompletionMatchesWrapper *matches,
00548                                           bool addWeight ) const
00549 {
00550     if ( !node || !matches )
00551         return;
00552 
00553     // kDebug() << "Beginning: " << beginning << endl;
00554     const KCompTreeChildren *list = node->children();
00555     QString string;
00556     QString w;
00557 
00558     // loop thru all children
00559     for ( KCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
00560         string = beginning;
00561         node = cur;
00562         if ( !node->isNull() )
00563             string += *node;
00564 
00565         while ( node && node->childrenCount() == 1 ) {
00566             node = node->firstChild();
00567             if ( node->isNull() )
00568                 break;
00569             string += *node;
00570         }
00571 
00572         if ( node && node->isNull() ) { // we found a leaf
00573             if ( addWeight ) {
00574                 // add ":num" to the string to store the weighting
00575                 string += ':';
00576                 w.setNum( node->weight() );
00577                 string.append( w );
00578             }
00579             matches->append( node->weight(), string );
00580         }
00581 
00582         // recursively find all other strings.
00583         if ( node && node->childrenCount() > 1 )
00584             extractStringsFromNode( node, string, matches, addWeight );
00585     }
00586 }
00587 
00588 void KCompletion::extractStringsFromNodeCI( const KCompTreeNode *node,
00589                                             const QString& beginning,
00590                                             const QString& restString,
00591                                             KCompletionMatchesWrapper *matches ) const
00592 {
00593     if ( restString.isEmpty() ) {
00594         extractStringsFromNode( node, beginning, matches, false /*noweight*/ );
00595         return;
00596     }
00597 
00598     QChar ch1 = restString.at(0);
00599     QString newRest = restString.mid(1);
00600     KCompTreeNode *child1, *child2;
00601 
00602     child1 = node->find( ch1 ); // the correct match
00603     if ( child1 )
00604         extractStringsFromNodeCI( child1, beginning + *child1, newRest,
00605                                   matches );
00606 
00607     // append the case insensitive matches, if available
00608     if ( ch1.isLetter() ) {
00609         // find out if we have to lower or upper it. Is there a better way?
00610         QChar ch2 = ch1.lower();
00611         if ( ch1 == ch2 )
00612             ch2 = ch1.upper();
00613         if ( ch1 != ch2 ) {
00614             child2 = node->find( ch2 );
00615             if ( child2 )
00616                 extractStringsFromNodeCI( child2, beginning + *child2, newRest,
00617                                           matches );
00618         }
00619     }
00620 }
00621 
00622 void KCompletion::doBeep( BeepMode mode ) const
00623 {
00624     if ( !myBeep )
00625         return;
00626 
00627     QString text, event;
00628 
00629     switch ( mode ) {
00630         case Rotation:
00631             event = QString::fromLatin1("Textcompletion: rotation");
00632             text = i18n("You reached the end of the list\nof matching items.\n");
00633             break;
00634         case PartialMatch:
00635             if ( myCompletionMode == KGlobalSettings::CompletionShell ||
00636                  myCompletionMode == KGlobalSettings::CompletionMan ) {
00637                 event = QString::fromLatin1("Textcompletion: partial match");
00638                 text = i18n("The completion is ambiguous, more than one\nmatch is available.\n");
00639             }
00640             break;
00641         case NoMatch:
00642             if ( myCompletionMode == KGlobalSettings::CompletionShell ) {
00643                 event = QString::fromLatin1("Textcompletion: no match");
00644                 text = i18n("There is no matching item available.\n");
00645             }
00646             break;
00647     }
00648 
00649     if ( !text.isEmpty() )
00650         KNotifyClient::event( event, text );
00651 }
00652 
00653 
00656 
00657 
00658 // Implements the tree. Every node is a QChar and has a list of children, which
00659 // are Nodes as well.
00660 // QChar( 0x0 ) is used as the delimiter of a string; the last child of each
00661 // inserted string is 0x0.
00662 
00663 KCompTreeNode::~KCompTreeNode()
00664 {
00665     // delete all children
00666     KCompTreeNode *cur = myChildren.begin();
00667     while (cur) {
00668         KCompTreeNode * next = cur->next;
00669         delete myChildren.remove(cur);
00670         cur = next;
00671     }
00672 }
00673 
00674 
00675 // Adds a child-node "ch" to this node. If such a node is already existant,
00676 // it will not be created. Returns the new/existing node.
00677 KCompTreeNode * KCompTreeNode::insert( const QChar& ch, bool sorted )
00678 {
00679     KCompTreeNode *child = find( ch );
00680     if ( !child ) {
00681         child = new KCompTreeNode( ch );
00682 
00683         // FIXME, first (slow) sorted insertion implementation
00684         if ( sorted ) {
00685             KCompTreeNode * prev = 0;
00686             KCompTreeNode * cur = myChildren.begin();
00687             while ( cur ) {
00688                 if ( ch > *cur ) {
00689                     prev = cur;
00690                     cur = cur->next;
00691                 } else
00692                     break;
00693             }
00694             if (prev)
00695                 myChildren.insert( prev, child );
00696             else
00697                 myChildren.prepend(child);
00698         }
00699 
00700         else
00701             myChildren.append( child );
00702     }
00703 
00704     // implicit weighting: the more often an item is inserted, the higher
00705     // priority it gets.
00706     child->confirm();
00707 
00708     return child;
00709 }
00710 
00711 
00712 // Iteratively removes a string from the tree. The nicer recursive
00713 // version apparently was a little memory hungry (see #56757)
00714 void KCompTreeNode::remove( const QString& str )
00715 {
00716     QString string = str;
00717     string += QChar(0x0);
00718 
00719     QPtrVector<KCompTreeNode> deletables( string.length() + 1 );
00720 
00721     KCompTreeNode *child = 0L;
00722     KCompTreeNode *parent = this;
00723     deletables.insert( 0, parent );
00724     
00725     uint i = 0;
00726     for ( ; i < string.length(); i++ )
00727     {
00728         child = parent->find( string.at( i ) );
00729         if ( child )
00730             deletables.insert( i + 1, child );
00731         else
00732             break;
00733 
00734         parent = child;
00735     }
00736 
00737     for ( ; i >= 1; i-- )
00738     {
00739         parent = deletables.at( i - 1 );
00740         child = deletables.at( i );
00741         if ( child->myChildren.count() == 0 )
00742             delete parent->myChildren.remove( child );
00743     }
00744 }
00745 
00746 QStringList KCompletionMatchesWrapper::list() const 
00747 {
00748     if ( sortedList && dirty ) {
00749         sortedList->sort();
00750         dirty = false;
00751 
00752         stringList.clear();
00753 
00754         // high weight == sorted last -> reverse the sorting here
00755         QValueListConstIterator<KSortableItem<QString> > it;
00756         for ( it = sortedList->begin(); it != sortedList->end(); ++it )
00757             stringList.prepend( (*it).value() );
00758     }
00759 
00760     return stringList;
00761 }
00762 
00763 KCompletionMatches::KCompletionMatches( bool sort_P )
00764     : _sorting( sort_P )
00765 {
00766 }
00767 
00768 KCompletionMatches::KCompletionMatches( const KCompletionMatchesWrapper& matches )
00769     : _sorting( matches.sorting())
00770 {
00771     if( matches.sortedList != 0L )
00772         KCompletionMatchesList::operator=( *matches.sortedList );
00773     else {
00774         QStringList l = matches.list();
00775         for( QStringList::ConstIterator it = l.begin();
00776              it != l.end();
00777              ++it )
00778             prepend( KSortableItem<QString, int>( 1, *it ) );
00779     }
00780 }
00781 
00782 KCompletionMatches::~KCompletionMatches()
00783 {
00784 }
00785 
00786 QStringList KCompletionMatches::list( bool sort_P ) const
00787 {
00788     if( _sorting && sort_P )
00789         const_cast< KCompletionMatches* >( this )->sort();
00790     QStringList stringList;
00791     // high weight == sorted last -> reverse the sorting here
00792     for ( ConstIterator it = begin(); it != end(); ++it )
00793         stringList.prepend( (*it).value() );
00794     return stringList;
00795 }
00796 
00797 void KCompletionMatches::removeDuplicates()
00798 {
00799     Iterator it1, it2;
00800     for ( it1 = begin(); it1 != end(); ++it1 ) {
00801         for ( (it2 = it1), ++it2; it2 != end();) {
00802             if( (*it1).value() == (*it2).value()) {
00803                 // use the max height
00804                 (*it1).first = kMax( (*it1).index(), (*it2).index());
00805                 it2 = remove( it2 );
00806                 continue;
00807             }
00808             ++it2;
00809         }
00810     }
00811 }
00812 
00813 void KCompTreeNodeList::append(KCompTreeNode *item)
00814 {
00815     m_count++;
00816     if (!last) {
00817         last = item;
00818         last->next = 0;
00819         first = item;
00820         return;
00821     }
00822     last->next = item;
00823     item->next = 0;
00824     last = item;
00825 }
00826 
00827 void KCompTreeNodeList::prepend(KCompTreeNode *item)
00828 {
00829     m_count++;
00830     if (!last) {
00831         last = item;
00832         last->next = 0;
00833         first = item;
00834         return;
00835     }
00836     item->next = first;
00837     first = item;
00838 }
00839 
00840 void KCompTreeNodeList::insert(KCompTreeNode *after, KCompTreeNode *item)
00841 {
00842     if (!after) {
00843         append(item);
00844         return;
00845     }
00846 
00847     m_count++;
00848 
00849     item->next = after->next;
00850     after->next = item;
00851 
00852     if (after == last)
00853         last = item;
00854 }
00855 
00856 KCompTreeNode *KCompTreeNodeList::remove(KCompTreeNode *item)
00857 {
00858     if (!first || !item)
00859         return 0;
00860     KCompTreeNode *cur = 0;
00861 
00862     if (item == first)
00863         first = first->next;
00864     else {
00865         cur = first;
00866         while (cur && cur->next != item) cur = cur->next;
00867         if (!cur)
00868             return 0;
00869         cur->next = item->next;
00870     }
00871     if (item == last)
00872         last = cur;
00873     m_count--;
00874     return item;
00875 }
00876 
00877 KCompTreeNode *KCompTreeNodeList::at(uint index) const
00878 {
00879     KCompTreeNode *cur = first;
00880     while (index-- && cur) cur = cur->next;
00881     return cur;
00882 }
00883 
00884 KZoneAllocator KCompTreeNode::alloc(8192);
00885 
00886 void KCompletion::virtual_hook( int, void* )
00887 { /*BASE::virtual_hook( id, data );*/ }
00888 
00889 void KCompletionBase::virtual_hook( int, void* )
00890 { /*BASE::virtual_hook( id, data );*/ }
00891 
00892 #include "kcompletion.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal