00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <opie2/ocompletion.h>
00032
00033 class OCompTreeNode;
00034
00035
00036
00037
00038
00039 class OCompTreeNodeList
00040 {
00041 public:
00042 OCompTreeNodeList() : first(0), last(0), m_count(0) {}
00043 OCompTreeNode *begin() const { return first; }
00044 OCompTreeNode *end() const { return last; }
00045
00046 OCompTreeNode *at(uint index) const;
00047 void append(OCompTreeNode *item);
00048 void prepend(OCompTreeNode *item);
00049 void insert(OCompTreeNode *after, OCompTreeNode *item);
00050 OCompTreeNode *remove(OCompTreeNode *item);
00051 uint count() const { return m_count; }
00052
00053 private:
00054 OCompTreeNode *first, *last;
00055 uint m_count;
00056 };
00057
00058 typedef OCompTreeNodeList OCompTreeChildren;
00059 typedef OSortableValueList<QString> OCompletionMatchesList;
00060
00091
00092
00093
00094
00095 class OCompTreeNode : public QChar
00096 {
00097 public:
00098 OCompTreeNode():QChar(), myWeight(0) {}
00099 OCompTreeNode( const QChar& ch, uint weight = 0 ):QChar( ch ), myWeight( weight ) {}
00100 ~OCompTreeNode();
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 inline OCompTreeNode * find( const QChar& ch ) const {
00113 OCompTreeNode * cur = myChildren.begin();
00114 while (cur && (*cur != ch)) cur = cur->next;
00115 return cur;
00116 }
00117
00118 OCompTreeNode * insert( const QChar&, bool sorted );
00119 void remove( const QString& );
00120
00121 inline int childrenCount() const { return myChildren.count(); };
00122
00123
00124 inline void confirm() { myWeight++; };
00125 inline void confirm(uint w) { myWeight += w; };
00126 inline void decline() { myWeight--; };
00127 inline uint weight() const { return myWeight; };
00128
00129 inline const OCompTreeChildren * children() const { return &myChildren; };
00130 inline const OCompTreeNode * childAt(int index) const { return myChildren.at(index); };
00131 inline const OCompTreeNode * firstChild() const { return myChildren.begin(); };
00132 inline const OCompTreeNode * lastChild() const { return myChildren.end(); };
00133
00134
00135
00136
00137 OCompTreeNode *next;
00138
00139 private:
00140 uint myWeight;
00141 OCompTreeNodeList myChildren;
00142
00143 };
00144
00145
00146
00147
00148
00149 class OCompletionMatchesWrapper
00150 {
00151 public:
00152 OCompletionMatchesWrapper( bool sort = false )
00153 : sortedList( sort ? new OCompletionMatchesList : 0L ),
00154 dirty( false )
00155 {}
00156 ~OCompletionMatchesWrapper() {
00157 delete sortedList;
00158 }
00159
00160 void setSorting( bool sort ) {
00161 if ( sort && !sortedList )
00162 sortedList = new OCompletionMatchesList;
00163 else if ( !sort ) {
00164 delete sortedList;
00165 sortedList = 0L;
00166 }
00167 stringList.clear();
00168 dirty = false;
00169 }
00170
00171 bool sorting() const {
00172 return sortedList != 0L;
00173 }
00174
00175 void append( int i, const QString& string ) {
00176 if ( sortedList )
00177 sortedList->insert( i, string );
00178 else
00179 stringList.append( string );
00180 dirty = true;
00181 }
00182
00183 void clear() {
00184 if ( sortedList )
00185 sortedList->clear();
00186 stringList.clear();
00187 dirty = false;
00188 }
00189
00190 uint count() const {
00191 if ( sortedList )
00192 return sortedList->count();
00193 return stringList.count();
00194 }
00195
00196 bool isEmpty() const {
00197 return count() == 0;
00198 }
00199
00200 QString first() const {
00201 return list().first();
00202 }
00203
00204 QString last() const {
00205 return list().last();
00206 }
00207
00208 QStringList list() const;
00209
00210 mutable QStringList stringList;
00211 OCompletionMatchesList *sortedList;
00212 mutable bool dirty;
00213 };
00214
00215
00216
00217
00218
00219 class OCompletionPrivate
00220 {
00221 public:
00222
00223
00224 OCompletionMatchesWrapper matches;
00225 };
00226
00227
00228
00229
00230
00231 OCompletion::OCompletion()
00232 {
00233 d = new OCompletionPrivate;
00234
00235 myCompletionMode = OGlobalSettings::completionMode();
00236 myTreeRoot = new OCompTreeNode;
00237 myBeep = true;
00238 myIgnoreCase = false;
00239 myHasMultipleMatches = false;
00240 myRotationIndex = 0;
00241 setOrder( Insertion );
00242 }
00243
00244
00245 OCompletion::~OCompletion()
00246 {
00247 delete d;
00248 delete myTreeRoot;
00249 }
00250
00251
00252 void OCompletion::setOrder( CompOrder order )
00253 {
00254 myOrder = order;
00255 d->matches.setSorting( order == Weighted );
00256 }
00257
00258
00259 void OCompletion::setIgnoreCase( bool ignoreCase )
00260 {
00261 myIgnoreCase = ignoreCase;
00262 }
00263
00264
00265 void OCompletion::setItems( const QStringList& items )
00266 {
00267 clear();
00268 insertItems( items );
00269 }
00270
00271
00272 void OCompletion::insertItems( const QStringList& items )
00273 {
00274 bool weighted = (myOrder == Weighted);
00275 QStringList::ConstIterator it;
00276 if ( weighted ) {
00277 for ( it = items.begin(); it != items.end(); ++it ) addWeightedItem( *it );
00278 }
00279 else {
00280 for ( it = items.begin(); it != items.end(); ++it ) addItem( *it, 0 );
00281 }
00282 }
00283
00284
00285 QStringList OCompletion::items() const
00286 {
00287 OCompletionMatchesWrapper list;
00288 bool addWeight = (myOrder == Weighted);
00289 extractStringsFromNode( myTreeRoot, QString::null, &list, addWeight );
00290
00291 return list.list();
00292 }
00293
00294
00295 void OCompletion::addItem( const QString& item )
00296 {
00297 d->matches.clear();
00298 myRotationIndex = 0;
00299 myLastString = QString::null;
00300
00301 addItem( item, 0 );
00302 }
00303
00304
00305 void OCompletion::addItem( const QString& item, uint weight )
00306 {
00307 if ( item.isEmpty() ) return;
00308
00309 OCompTreeNode *node = myTreeRoot;
00310 uint len = item.length();
00311
00312 bool sorted = (myOrder == Sorted);
00313 bool weighted = ((myOrder == Weighted) && weight > 1);
00314
00315
00316
00317
00318 for ( uint i = 0; i < len; i++ ) {
00319 node = node->insert( item.at(i), sorted );
00320 if ( weighted ) node->confirm( weight -1 );
00321 }
00322
00323
00324 node = node->insert( 0x0, true );
00325 if ( weighted )
00326 node->confirm( weight -1 );
00327
00328 }
00329
00330
00331 void OCompletion::addWeightedItem( const QString& item )
00332 {
00333 if ( myOrder != Weighted ) {
00334 addItem( item, 0 );
00335 return;
00336 }
00337
00338 uint len = item.length();
00339 uint weight = 0;
00340
00341
00342 int index = item.findRev(':');
00343 if ( index > 0 ) {
00344 bool ok;
00345 weight = item.mid( index + 1 ).toUInt( &ok );
00346 if ( !ok )
00347 weight = 0;
00348
00349 len = index;
00350 }
00351
00352 addItem( item.left( len ), weight );
00353 return;
00354 }
00355
00356
00357 void OCompletion::removeItem( const QString& item )
00358 {
00359 d->matches.clear();
00360 myRotationIndex = 0;
00361 myLastString = QString::null;
00362
00363 myTreeRoot->remove( item );
00364 }
00365
00366
00367 void OCompletion::clear()
00368 {
00369 d->matches.clear();
00370 myRotationIndex = 0;
00371 myLastString = QString::null;
00372
00373 delete myTreeRoot;
00374 myTreeRoot = new OCompTreeNode;
00375 }
00376
00377
00378 QString OCompletion::makeCompletion( const QString& string )
00379 {
00380 if ( myCompletionMode == OGlobalSettings::CompletionNone )
00381 return QString::null;
00382
00383
00384
00385 d->matches.clear();
00386 myRotationIndex = 0;
00387 myHasMultipleMatches = false;
00388 myLastMatch = myCurrentMatch;
00389
00390
00391
00392 if ( myCompletionMode == OGlobalSettings::CompletionShell &&
00393 string == myLastString ) {
00394
00395
00396
00397
00398 findAllCompletions( string, &d->matches, myHasMultipleMatches );
00399 QStringList l = d->matches.list();
00400 postProcessMatches( &l );
00401 emit matches( l );
00402
00403 if ( l.isEmpty() )
00404 doBeep( NoMatch );
00405
00406 return QString::null;
00407 }
00408
00409 QString completion;
00410
00411 if ( myCompletionMode == OGlobalSettings::CompletionPopup ||
00412 myCompletionMode == OGlobalSettings::CompletionPopupAuto ) {
00413 findAllCompletions( string, &d->matches, myHasMultipleMatches );
00414 if ( !d->matches.isEmpty() )
00415 completion = d->matches.first();
00416 }
00417 else
00418 completion = findCompletion( string );
00419
00420 if ( myHasMultipleMatches )
00421 emit multipleMatches();
00422
00423 myLastString = string;
00424 myCurrentMatch = completion;
00425
00426 postProcessMatch( &completion );
00427
00428 if ( !string.isEmpty() ) {
00429
00430 emit match( completion );
00431 }
00432
00433 if ( completion.isNull() )
00434 doBeep( NoMatch );
00435
00436 return completion;
00437 }
00438
00439 QStringList OCompletion::substringCompletion( const QString& string ) const
00440 {
00441
00442 bool sorted = (myOrder == Weighted);
00443 OCompletionMatchesWrapper allItems( sorted );
00444 extractStringsFromNode( myTreeRoot, QString::null, &allItems, false );
00445
00446 QStringList list = allItems.list();
00447
00448
00449
00450 if ( list.isEmpty() ) {
00451 doBeep( NoMatch );
00452 return list;
00453 }
00454
00455 if ( string.isEmpty() ) {
00456 postProcessMatches( &list );
00457 return list;
00458 }
00459
00460 QStringList matches;
00461 QStringList::ConstIterator it = list.begin();
00462
00463 for( ; it != list.end(); ++it ) {
00464 QString item = *it;
00465 if ( item.find( string, 0, false ) != -1 ) {
00466 postProcessMatch( &item );
00467 matches.append( item );
00468 }
00469 }
00470
00471 if ( matches.isEmpty() )
00472 doBeep( NoMatch );
00473
00474 return matches;
00475 }
00476
00477
00478 void OCompletion::setCompletionMode( OGlobalSettings::Completion mode )
00479 {
00480 myCompletionMode = mode;
00481 }
00482
00483
00484 QStringList OCompletion::allMatches()
00485 {
00486
00487
00488
00489 OCompletionMatchesWrapper matches( myOrder == Weighted );
00490 bool dummy;
00491 findAllCompletions( myLastString, &matches, dummy );
00492 QStringList l = matches.list();
00493 postProcessMatches( &l );
00494 return l;
00495 }
00496
00497
00498 OCompletionMatches OCompletion::allWeightedMatches()
00499 {
00500
00501
00502
00503 OCompletionMatchesWrapper matches( myOrder == Weighted );
00504 bool dummy;
00505 findAllCompletions( myLastString, &matches, dummy );
00506 OCompletionMatches ret( matches );
00507 postProcessMatches( &ret );
00508 return ret;
00509 }
00510
00511 QStringList OCompletion::allMatches( const QString &string )
00512 {
00513 OCompletionMatchesWrapper matches( myOrder == Weighted );
00514 bool dummy;
00515 findAllCompletions( string, &matches, dummy );
00516 QStringList l = matches.list();
00517 postProcessMatches( &l );
00518 return l;
00519 }
00520
00521 OCompletionMatches OCompletion::allWeightedMatches( const QString &string )
00522 {
00523 OCompletionMatchesWrapper matches( myOrder == Weighted );
00524 bool dummy;
00525 findAllCompletions( string, &matches, dummy );
00526 OCompletionMatches ret( matches );
00527 postProcessMatches( &ret );
00528 return ret;
00529 }
00530
00533
00534
00535 QString OCompletion::nextMatch()
00536 {
00537 QString completion;
00538 myLastMatch = myCurrentMatch;
00539
00540 if ( d->matches.isEmpty() ) {
00541 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
00542 completion = d->matches.first();
00543 myCurrentMatch = completion;
00544 myRotationIndex = 0;
00545 postProcessMatch( &completion );
00546 emit match( completion );
00547 return completion;
00548 }
00549
00550 QStringList matches = d->matches.list();
00551 myLastMatch = matches[ myRotationIndex++ ];
00552
00553 if ( myRotationIndex == matches.count() -1 )
00554 doBeep( Rotation );
00555
00556 else if ( myRotationIndex == matches.count() )
00557 myRotationIndex = 0;
00558
00559 completion = matches[ myRotationIndex ];
00560 myCurrentMatch = completion;
00561 postProcessMatch( &completion );
00562 emit match( completion );
00563 return completion;
00564 }
00565
00566
00567
00568 QString OCompletion::previousMatch()
00569 {
00570 QString completion;
00571 myLastMatch = myCurrentMatch;
00572
00573 if ( d->matches.isEmpty() ) {
00574 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
00575 completion = d->matches.last();
00576 myCurrentMatch = completion;
00577 myRotationIndex = 0;
00578 postProcessMatch( &completion );
00579 emit match( completion );
00580 return completion;
00581 }
00582
00583 QStringList matches = d->matches.list();
00584 myLastMatch = matches[ myRotationIndex ];
00585 if ( myRotationIndex == 1 )
00586 doBeep( Rotation );
00587
00588 else if ( myRotationIndex == 0 )
00589 myRotationIndex = matches.count();
00590
00591 myRotationIndex--;
00592
00593 completion = matches[ myRotationIndex ];
00594 myCurrentMatch = completion;
00595 postProcessMatch( &completion );
00596 emit match( completion );
00597 return completion;
00598 }
00599
00600
00601
00602
00603 QString OCompletion::findCompletion( const QString& string )
00604 {
00605 QChar ch;
00606 QString completion;
00607 const OCompTreeNode *node = myTreeRoot;
00608
00609
00610 for( uint i = 0; i < string.length(); i++ ) {
00611 ch = string.at( i );
00612 node = node->find( ch );
00613
00614 if ( node )
00615 completion += ch;
00616 else
00617 return QString::null;
00618 }
00619
00620
00621
00622
00623
00624 while ( node->childrenCount() == 1 ) {
00625 node = node->firstChild();
00626 if ( !node->isNull() )
00627 completion += *node;
00628 }
00629
00630
00631 if ( node && node->childrenCount() > 1 ) {
00632 myHasMultipleMatches = true;
00633
00634 if ( myCompletionMode == OGlobalSettings::CompletionAuto ) {
00635 myRotationIndex = 1;
00636 if (myOrder != Weighted) {
00637 while ( (node = node->firstChild()) ) {
00638 if ( !node->isNull() )
00639 completion += *node;
00640 else
00641 break;
00642 }
00643 }
00644 else {
00645
00646
00647
00648 const OCompTreeNode* temp_node = 0L;
00649 while(1) {
00650 int count = node->childrenCount();
00651 temp_node = node->firstChild();
00652 uint weight = temp_node->weight();
00653 const OCompTreeNode* hit = temp_node;
00654 for( int i = 1; i < count; i++ ) {
00655 temp_node = node->childAt(i);
00656 if( temp_node->weight() > weight ) {
00657 hit = temp_node;
00658 weight = hit->weight();
00659 }
00660 }
00661
00662 if ( hit->isNull() )
00663 break;
00664
00665 node = hit;
00666 completion += *node;
00667 }
00668 }
00669 }
00670
00671 else
00672 doBeep( PartialMatch );
00673 }
00674
00675 return completion;
00676 }
00677
00678
00679 void OCompletion::findAllCompletions(const QString& string,
00680 OCompletionMatchesWrapper *matches,
00681 bool& hasMultipleMatches) const
00682 {
00683
00684
00685 if ( string.isEmpty() )
00686 return;
00687
00688 if ( myIgnoreCase ) {
00689 extractStringsFromNodeCI( myTreeRoot, QString::null, string, matches );
00690 hasMultipleMatches = (matches->count() > 1);
00691 return;
00692 }
00693
00694 QChar ch;
00695 QString completion;
00696 const OCompTreeNode *node = myTreeRoot;
00697
00698
00699 for( uint i = 0; i < string.length(); i++ ) {
00700 ch = string.at( i );
00701 node = node->find( ch );
00702
00703 if ( node )
00704 completion += ch;
00705 else
00706 return;
00707 }
00708
00709
00710
00711
00712
00713 while ( node->childrenCount() == 1 ) {
00714 node = node->firstChild();
00715 if ( !node->isNull() )
00716 completion += *node;
00717
00718 }
00719
00720
00721
00722 if ( node->childrenCount() == 0 )
00723 matches->append( node->weight(), completion );
00724
00725 else {
00726
00727
00728 hasMultipleMatches = true;
00729 extractStringsFromNode( node, completion, matches );
00730 }
00731 }
00732
00733
00734 void OCompletion::extractStringsFromNode( const OCompTreeNode *node,
00735 const QString& beginning,
00736 OCompletionMatchesWrapper *matches,
00737 bool addWeight ) const
00738 {
00739 if ( !node || !matches ) return;
00740
00741
00742 const OCompTreeChildren *list = node->children();
00743 QString string;
00744 QString w;
00745
00746
00747 for ( OCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
00748 string = beginning;
00749 node = cur;
00750 if ( !node->isNull() )
00751 string += *node;
00752
00753 while ( node && node->childrenCount() == 1 ) {
00754 node = node->firstChild();
00755 if ( node->isNull() ) break;
00756 string += *node;
00757 }
00758
00759 if ( node && node->isNull() ) {
00760 if ( addWeight ) {
00761
00762 string += ':';
00763 w.setNum( node->weight() );
00764 string.append( w );
00765 }
00766 matches->append( node->weight(), string );
00767 }
00768
00769
00770 if ( node && node->childrenCount() > 1 )
00771 extractStringsFromNode( node, string, matches, addWeight );
00772 }
00773 }
00774
00775 void OCompletion::extractStringsFromNodeCI( const OCompTreeNode *node,
00776 const QString& beginning,
00777 const QString& restString,
00778 OCompletionMatchesWrapper *matches ) const
00779 {
00780 if ( restString.isEmpty() ) {
00781 extractStringsFromNode( node, beginning, matches, false );
00782 return;
00783 }
00784
00785 QChar ch1 = restString.at(0);
00786 QString newRest = restString.mid(1);
00787 OCompTreeNode *child1, *child2;
00788
00789 child1 = node->find( ch1 );
00790 if ( child1 )
00791 extractStringsFromNodeCI( child1, beginning + *child1, newRest,
00792 matches );
00793
00794
00795 if ( ch1.isLetter() ) {
00796
00797 QChar ch2 = ch1.lower();
00798 if ( ch1 == ch2 )
00799 ch2 = ch1.upper();
00800 if ( ch1 != ch2 ) {
00801 child2 = node->find( ch2 );
00802 if ( child2 )
00803 extractStringsFromNodeCI( child2, beginning + *child2, newRest,
00804 matches );
00805 }
00806 }
00807 }
00808
00809
00810
00811 void OCompletion::doBeep( BeepMode mode ) const
00812 {
00813 if ( !myBeep ) return;
00814
00815 QString text, event;
00816
00817 switch ( mode ) {
00818 case Rotation:
00819 event = QString::fromLatin1("Textcompletion: rotation");
00820 text = tr("You reached the end of the list\nof matching items.\n");
00821 break;
00822 case PartialMatch:
00823 if ( myCompletionMode == OGlobalSettings::CompletionShell ||
00824 myCompletionMode == OGlobalSettings::CompletionMan ) {
00825 event = QString::fromLatin1("Textcompletion: partial match");
00826 text = tr("The completion is ambiguous, more than one\nmatch is available.\n");
00827 }
00828 break;
00829 case NoMatch:
00830 if ( myCompletionMode == OGlobalSettings::CompletionShell ) {
00831 event = QString::fromLatin1("Textcompletion: no match");
00832 text = tr("There is no matching item available.\n");
00833 }
00834 break;
00835 }
00836
00837
00838
00839 }
00840
00841
00842
00843
00844
00845
00846 OCompTreeNode::~OCompTreeNode()
00847 {
00848
00849 OCompTreeNode *cur = myChildren.begin();
00850 while (cur) {
00851 OCompTreeNode * next = cur->next;
00852 delete myChildren.remove(cur);
00853 cur = next;
00854 }
00855 }
00856
00857
00858
00859
00860 OCompTreeNode * OCompTreeNode::insert( const QChar& ch, bool sorted )
00861 {
00862 OCompTreeNode *child = find( ch );
00863 if ( !child ) {
00864 child = new OCompTreeNode( ch );
00865
00866
00867 if ( sorted ) {
00868 OCompTreeNode * prev = 0;
00869 OCompTreeNode * cur = myChildren.begin();
00870 while ( cur ) {
00871 if ( ch > *cur ) {
00872 prev = cur;
00873 cur = cur->next;
00874 } else
00875 break;
00876 }
00877 if (prev)
00878 myChildren.insert( prev, child );
00879 else
00880 myChildren.prepend(child);
00881 }
00882
00883 else
00884 myChildren.append( child );
00885 }
00886
00887
00888
00889 child->confirm();
00890
00891 return child;
00892 }
00893
00894
00895
00896 void OCompTreeNode::remove( const QString& string )
00897 {
00898 OCompTreeNode *child = 0L;
00899
00900 if ( string.isEmpty() ) {
00901 child = find( 0x0 );
00902 delete myChildren.remove( child );
00903 return;
00904 }
00905
00906 QChar ch = string.at(0);
00907 child = find( ch );
00908 if ( child ) {
00909 child->remove( string.right( string.length() -1 ) );
00910 if ( child->myChildren.count() == 0 ) {
00911 delete myChildren.remove( child );
00912 }
00913 }
00914 }
00915
00916 QStringList OCompletionMatchesWrapper::list() const {
00917 if ( sortedList && dirty ) {
00918 sortedList->sort();
00919 dirty = false;
00920
00921 stringList.clear();
00922
00923
00924 QValueListConstIterator<OSortableItem<QString> > it;
00925 for ( it = sortedList->begin(); it != sortedList->end(); ++it )
00926 stringList.prepend( (*it).value() );
00927 }
00928
00929 return stringList;
00930 }
00931
00932 OCompletionMatches::OCompletionMatches( bool sort_P )
00933 : _sorting( sort_P )
00934 {
00935 }
00936
00937 OCompletionMatches::OCompletionMatches( const OCompletionMatchesWrapper& matches )
00938 : _sorting( matches.sorting())
00939 {
00940 if( matches.sortedList != 0L )
00941 OCompletionMatchesList::operator=( *matches.sortedList );
00942 else {
00943 QStringList l = matches.list();
00944 for( QStringList::ConstIterator it = l.begin();
00945 it != l.end();
00946 ++it )
00947 prepend( OSortableItem<QString, int>( 1, *it ) );
00948 }
00949 }
00950
00951 OCompletionMatches::~OCompletionMatches()
00952 {
00953 }
00954
00955 QStringList OCompletionMatches::list( bool sort_P ) const
00956 {
00957 if( _sorting && sort_P )
00958 const_cast< OCompletionMatches* >( this )->sort();
00959 QStringList stringList;
00960
00961 for ( ConstIterator it = begin(); it != end(); ++it )
00962 stringList.prepend( (*it).value() );
00963 return stringList;
00964 }
00965
00966 void OCompletionMatches::removeDuplicates()
00967 {
00968 Iterator it1, it2;
00969 for ( it1 = begin(); it1 != end(); ++it1 ) {
00970 for ( (it2 = it1), ++it2; it2 != end();) {
00971 if( (*it1).value() == (*it2).value()) {
00972
00973
00974 (*it1).first = (*it2).index() < (*it1).index() ? (*it1).index() : (*it2).index();
00975 it2 = remove( it2 );
00976 continue;
00977 }
00978 ++it2;
00979 }
00980 }
00981 }
00982
00983 void OCompTreeNodeList::append(OCompTreeNode *item)
00984 {
00985 m_count++;
00986 if (!last) {
00987 last = item;
00988 last->next = 0;
00989 first = item;
00990 return;
00991 }
00992 last->next = item;
00993 item->next = 0;
00994 last = item;
00995 }
00996
00997 void OCompTreeNodeList::prepend(OCompTreeNode *item)
00998 {
00999 m_count++;
01000 if (!last) {
01001 last = item;
01002 last->next = 0;
01003 first = item;
01004 return;
01005 }
01006 item->next = first;
01007 first = item;
01008 }
01009
01010 void OCompTreeNodeList::insert(OCompTreeNode *after, OCompTreeNode *item)
01011 {
01012 if (!after) {
01013 append(item);
01014 return;
01015 }
01016
01017 m_count++;
01018
01019 item->next = after->next;
01020 after->next = item;
01021
01022 if (after == last)
01023 last = item;
01024 }
01025
01026 OCompTreeNode *OCompTreeNodeList::remove(OCompTreeNode *item)
01027 {
01028 if (!first || !item)
01029 return 0;
01030 OCompTreeNode *cur = 0;
01031
01032 if (item == first)
01033 first = first->next;
01034 else {
01035 cur = first;
01036 while (cur && cur->next != item) cur = cur->next;
01037 if (!cur)
01038 return 0;
01039 cur->next = item->next;
01040 }
01041 if (item == last)
01042 last = cur;
01043 m_count--;
01044 return item;
01045 }
01046
01047 OCompTreeNode *OCompTreeNodeList::at(uint index) const
01048 {
01049 OCompTreeNode *cur = first;
01050 while (index-- && cur) cur = cur->next;
01051 return cur;
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061