21 #include <kapplication.h>
24 #include <knotifyclient.h>
27 #include <tqptrvector.h>
29 #include "kcompletion.h"
30 #include "kcompletion_private.h"
33 class KCompletionPrivate
38 KCompletionMatchesWrapper matches;
43 d =
new KCompletionPrivate;
49 myHasMultipleMatches =
false;
63 d->matches.setSorting( order ==
Weighted );
80 bool weighted = (myOrder ==
Weighted);
81 TQStringList::ConstIterator it;
83 for ( it = items.begin(); it != items.end(); ++it )
84 addWeightedItem( *it );
87 for ( it = items.begin(); it != items.end(); ++it )
94 KCompletionMatchesWrapper list;
95 bool addWeight = (myOrder ==
Weighted);
96 extractStringsFromNode( myTreeRoot, TQString::null, &list, addWeight );
103 return (myTreeRoot->childrenCount() == 0);
110 myLastString = TQString::null;
117 if ( item.isEmpty() )
121 uint len = item.length();
123 bool sorted = (myOrder ==
Sorted);
124 bool weighted = ((myOrder ==
Weighted) && weight > 1);
129 for ( uint i = 0; i < len; i++ ) {
130 node = node->insert( item.at(i), sorted );
132 node->confirm( weight -1 );
136 node = node->insert( 0x0,
true );
138 node->confirm( weight -1 );
142 void KCompletion::addWeightedItem(
const TQString& item )
149 uint len = item.length();
153 int index = item.findRev(
':');
156 weight = item.mid( index + 1 ).toUInt( &ok );
163 addItem( item.left( len ), weight );
172 myLastString = TQString::null;
174 myTreeRoot->remove( item );
182 myLastString = TQString::null;
192 return TQString::null;
198 myHasMultipleMatches =
false;
199 myLastMatch = myCurrentMatch;
204 string == myLastString ) {
209 findAllCompletions(
string, &d->matches, myHasMultipleMatches );
210 TQStringList l = d->matches.list();
217 return TQString::null;
224 findAllCompletions(
string, &d->matches, myHasMultipleMatches );
225 if ( !d->matches.isEmpty() )
226 completion = d->matches.first();
229 completion = findCompletion(
string );
231 if ( myHasMultipleMatches )
234 myLastString = string;
235 myCurrentMatch = completion;
241 emit
match( completion );
244 if ( completion.isNull() )
254 bool sorted = (myOrder ==
Weighted);
255 KCompletionMatchesWrapper allItems( sorted );
256 extractStringsFromNode( myTreeRoot, TQString::null, &allItems,
false );
258 TQStringList list = allItems.list();
262 if ( list.isEmpty() ) {
273 TQStringList::ConstIterator it = list.begin();
275 for( ; it != list.end(); ++it ) {
277 if ( item.find(
string, 0,
false ) != -1 ) {
278 matches.append( item );
284 if ( matches.isEmpty() )
293 myCompletionMode = mode;
303 findAllCompletions( myLastString, &matches, dummy );
304 TQStringList l = matches.list();
316 findAllCompletions( myLastString, &matches, dummy );
326 findAllCompletions(
string, &matches, dummy );
327 TQStringList l = matches.list();
336 findAllCompletions(
string, &matches, dummy );
349 myLastMatch = myCurrentMatch;
351 if ( d->matches.isEmpty() ) {
352 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
353 completion = d->matches.first();
354 myCurrentMatch = completion;
357 emit
match( completion );
361 TQStringList
matches = d->matches.list();
362 myLastMatch = matches[ myRotationIndex++ ];
364 if ( myRotationIndex == matches.count() -1 )
367 else if ( myRotationIndex == matches.count() )
370 completion = matches[ myRotationIndex ];
371 myCurrentMatch = completion;
373 emit
match( completion );
382 myLastMatch = myCurrentMatch;
384 if ( d->matches.isEmpty() ) {
385 findAllCompletions( myLastString, &d->matches, myHasMultipleMatches );
386 completion = d->matches.last();
387 myCurrentMatch = completion;
390 emit
match( completion );
394 TQStringList
matches = d->matches.list();
395 myLastMatch = matches[ myRotationIndex ];
396 if ( myRotationIndex == 1 )
399 else if ( myRotationIndex == 0 )
400 myRotationIndex = matches.count();
404 completion = matches[ myRotationIndex ];
405 myCurrentMatch = completion;
407 emit
match( completion );
414 TQString KCompletion::findCompletion(
const TQString&
string )
421 for( uint i = 0; i <
string.length(); i++ ) {
423 node = node->find( ch );
428 return TQString::null;
435 while ( node->childrenCount() == 1 ) {
436 node = node->firstChild();
437 if ( !node->isNull() )
442 if ( node && node->childrenCount() > 1 ) {
443 myHasMultipleMatches =
true;
448 while ( (node = node->firstChild()) ) {
449 if ( !node->isNull() )
461 int count = node->childrenCount();
462 temp_node = node->firstChild();
463 uint weight = temp_node->weight();
465 for(
int i = 1; i < count; i++ ) {
466 temp_node = node->childAt(i);
467 if( temp_node->weight() > weight ) {
469 weight = hit->weight();
483 doBeep( PartialMatch );
490 void KCompletion::findAllCompletions(
const TQString&
string,
491 KCompletionMatchesWrapper *matches,
492 bool& hasMultipleMatches)
const
499 if ( myIgnoreCase ) {
500 extractStringsFromNodeCI( myTreeRoot, TQString::null,
string, matches );
501 hasMultipleMatches = (matches->count() > 1);
510 for( uint i = 0; i <
string.length(); i++ ) {
512 node = node->find( ch );
524 while ( node->childrenCount() == 1 ) {
525 node = node->firstChild();
526 if ( !node->isNull() )
533 if ( node->childrenCount() == 0 )
534 matches->append( node->weight(), completion );
539 hasMultipleMatches =
true;
540 extractStringsFromNode( node, completion, matches );
545 void KCompletion::extractStringsFromNode(
const KCompTreeNode *node,
546 const TQString& beginning,
547 KCompletionMatchesWrapper *matches,
548 bool addWeight )
const
550 if ( !node || !matches )
554 const KCompTreeChildren *list = node->children();
559 for (
KCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
562 if ( !node->isNull() )
565 while ( node && node->childrenCount() == 1 ) {
566 node = node->firstChild();
567 if ( node->isNull() )
572 if ( node && node->isNull() ) {
576 w.setNum( node->weight() );
579 matches->append( node->weight(), string );
583 if ( node && node->childrenCount() > 1 )
584 extractStringsFromNode( node,
string, matches, addWeight );
588 void KCompletion::extractStringsFromNodeCI(
const KCompTreeNode *node,
589 const TQString& beginning,
590 const TQString& restString,
591 KCompletionMatchesWrapper *matches )
const
593 if ( restString.isEmpty() ) {
594 extractStringsFromNode( node, beginning, matches,
false );
598 TQChar ch1 = restString.at(0);
599 TQString newRest = restString.mid(1);
602 child1 = node->find( ch1 );
604 extractStringsFromNodeCI( child1, beginning + *child1, newRest,
608 if ( ch1.isLetter() ) {
610 TQChar ch2 = ch1.lower();
614 child2 = node->find( ch2 );
616 extractStringsFromNodeCI( child2, beginning + *child2, newRest,
622 void KCompletion::doBeep( BeepMode mode )
const
627 TQString text,
event;
631 event = TQString::fromLatin1(
"Textcompletion: rotation");
632 text = i18n(
"You reached the end of the list\nof matching items.\n");
637 event = TQString::fromLatin1(
"Textcompletion: partial match");
638 text = i18n(
"The completion is ambiguous, more than one\nmatch is available.\n");
643 event = TQString::fromLatin1(
"Textcompletion: no match");
644 text = i18n(
"There is no matching item available.\n");
649 if ( !text.isEmpty() )
663 KCompTreeNode::~KCompTreeNode()
669 delete myChildren.remove(cur);
677 KCompTreeNode * KCompTreeNode::insert(
const TQChar& ch,
bool sorted )
695 myChildren.insert( prev, child );
697 myChildren.prepend(child);
701 myChildren.append( child );
714 void KCompTreeNode::remove(
const TQString& str )
716 TQString
string = str;
717 string += TQChar(0x0);
719 TQPtrVector<KCompTreeNode> deletables(
string.length() + 1 );
723 deletables.insert( 0, parent );
726 for ( ; i <
string.length(); i++ )
728 child = parent->find(
string.at( i ) );
730 deletables.insert( i + 1, child );
737 for ( ; i >= 1; i-- )
739 parent = deletables.at( i - 1 );
740 child = deletables.at( i );
741 if ( child->myChildren.count() == 0 )
742 delete parent->myChildren.remove( child );
746 TQStringList KCompletionMatchesWrapper::list()
const
748 if ( sortedList && dirty ) {
755 TQValueListConstIterator<KSortableItem<TQString> > it;
756 for ( it = sortedList->begin(); it != sortedList->end(); ++it )
757 stringList.prepend( (*it).value() );
763 KCompletionMatches::KCompletionMatches(
bool sort_P )
768 KCompletionMatches::KCompletionMatches(
const KCompletionMatchesWrapper& matches )
769 : _sorting( matches.sorting())
771 if( matches.sortedList != 0L )
772 KCompletionMatchesList::operator=( *matches.sortedList );
774 TQStringList l = matches.list();
775 for( TQStringList::ConstIterator it = l.begin();
782 KCompletionMatches::~KCompletionMatches()
788 if( _sorting && sort_P )
790 TQStringList stringList;
792 for ( ConstIterator it = begin(); it != end(); ++it )
793 stringList.prepend( (*it).value() );
800 for ( it1 = begin(); it1 != end(); ++it1 ) {
801 for ( (it2 = it1), ++it2; it2 != end();) {
802 if( (*it1).value() == (*it2).value()) {
804 (*it1).first = kMax( (*it1).index(), (*it2).index());
849 item->next = after->next;
866 while (cur && cur->next != item) cur = cur->next;
869 cur->next = item->next;
880 while (index-- && cur) cur = cur->next;
886 void KCompletion::virtual_hook(
int,
void* )
889 void KCompletionBase::virtual_hook(
int,
void* )
892 #include "kcompletion.moc"