22 #include "kcompletion_p.h"
29 #include <QtCore/QMutableVectorIterator>
31 class KCompletionPrivate
36 , myTreeRoot( new KCompTreeNode )
38 , myIgnoreCase( false )
39 , myHasMultipleMatches( false )
40 , myRotationIndex( 0 )
48 KCompletionMatchesWrapper matches;
56 KCompTreeNode * myTreeRoot;
59 bool myIgnoreCase : 1;
60 bool myHasMultipleMatches;
65 :d(new KCompletionPrivate)
78 d->matches.setSorting( order );
93 return d->myIgnoreCase;
105 bool weighted = (d->myOrder ==
Weighted);
106 QStringList::ConstIterator it;
108 for ( it = items.begin(); it != items.end(); ++it )
109 addWeightedItem( *it );
112 for ( it = items.begin(); it != items.end(); ++it )
119 KCompletionMatchesWrapper list;
120 bool addWeight = (d->myOrder ==
Weighted);
121 extractStringsFromNode( d->myTreeRoot,
QString(), &list, addWeight );
128 return (d->myTreeRoot->childrenCount() == 0);
146 d->myRotationIndex = 0;
147 d->myLastString.clear();
154 if ( item.isEmpty() )
157 KCompTreeNode *node = d->myTreeRoot;
158 uint len = item.length();
160 bool sorted = (d->myOrder ==
Sorted);
161 bool weighted = ((d->myOrder ==
Weighted) && weight > 1);
166 for ( uint i = 0; i < len; i++ ) {
167 node = node->insert( item.at(i), sorted );
169 node->confirm( weight -1 );
173 node = node->insert( 0x0,
true );
175 node->confirm( weight -1 );
179 void KCompletion::addWeightedItem(
const QString& item )
186 uint len = item.length();
190 int index = item.lastIndexOf(
':');
193 weight = item.mid( index + 1 ).toUInt( &ok );
200 addItem( item.left( len ), weight );
208 d->myRotationIndex = 0;
209 d->myLastString.clear();
211 d->myTreeRoot->remove( item );
218 d->myRotationIndex = 0;
219 d->myLastString.clear();
221 delete d->myTreeRoot;
222 d->myTreeRoot =
new KCompTreeNode;
234 d->myRotationIndex = 0;
235 d->myHasMultipleMatches =
false;
236 d->myLastMatch = d->myCurrentMatch;
241 string == d->myLastString ) {
246 findAllCompletions(
string, &d->matches, d->myHasMultipleMatches );
261 findAllCompletions(
string, &d->matches, d->myHasMultipleMatches );
262 if ( !d->matches.isEmpty() )
263 completion = d->matches.first();
266 completion = findCompletion(
string );
268 if ( d->myHasMultipleMatches )
271 d->myLastString = string;
278 emit
match( completion );
281 if ( completion.isNull() )
292 KCompletionMatchesWrapper allItems( d->myOrder );
293 extractStringsFromNode( d->myTreeRoot,
QString(), &allItems,
false );
299 if ( list.isEmpty() ) {
310 QStringList::ConstIterator it = list.constBegin();
312 for( ; it != list.constEnd(); ++it ) {
314 if ( item.indexOf(
string, 0, Qt::CaseInsensitive ) != -1 ) {
316 matches.append( item );
320 if ( matches.isEmpty() )
329 d->myCompletionMode = mode;
333 return d->myCompletionMode;
341 KCompletionMatchesWrapper
matches( d->myOrder );
343 findAllCompletions( d->myLastString, &matches, dummy );
354 KCompletionMatchesWrapper
matches( d->myOrder );
356 findAllCompletions( d->myLastString, &matches, dummy );
364 KCompletionMatchesWrapper
matches( d->myOrder );
366 findAllCompletions(
string, &matches, dummy );
374 KCompletionMatchesWrapper
matches( d->myOrder );
376 findAllCompletions(
string, &matches, dummy );
394 return d->myHasMultipleMatches;
404 d->myLastMatch = d->myCurrentMatch;
406 if ( d->matches.isEmpty() ) {
407 findAllCompletions( d->myLastString, &d->matches, d->myHasMultipleMatches );
408 if ( !d->matches.isEmpty() )
409 completion = d->matches.first();
411 d->myRotationIndex = 0;
413 emit
match( completion );
418 d->myLastMatch = matches[ d->myRotationIndex++ ];
420 if ( d->myRotationIndex == matches.count() -1 )
423 else if ( d->myRotationIndex == matches.count() )
424 d->myRotationIndex = 0;
426 completion = matches[ d->myRotationIndex ];
427 d->myCurrentMatch = completion;
429 emit
match( completion );
435 return d->myLastMatch;
442 d->myLastMatch = d->myCurrentMatch;
444 if ( d->matches.isEmpty() ) {
445 findAllCompletions( d->myLastString, &d->matches, d->myHasMultipleMatches );
446 if ( !d->matches.isEmpty() )
447 completion = d->matches.last();
449 d->myRotationIndex = 0;
451 emit
match( completion );
456 d->myLastMatch = matches[ d->myRotationIndex ];
457 if ( d->myRotationIndex == 1 )
460 else if ( d->myRotationIndex == 0 )
461 d->myRotationIndex = matches.count();
463 d->myRotationIndex--;
465 completion = matches[ d->myRotationIndex ];
468 emit
match( completion );
479 const KCompTreeNode *node = d->myTreeRoot;
482 for(
int i = 0; i <
string.length(); i++ ) {
484 node = node->find( ch );
496 while ( node->childrenCount() == 1 ) {
497 node = node->firstChild();
498 if ( !node->isNull() )
503 if ( node && node->childrenCount() > 1 ) {
504 d->myHasMultipleMatches =
true;
507 d->myRotationIndex = 1;
509 while ( (node = node->firstChild()) ) {
510 if ( !node->isNull() )
520 const KCompTreeNode* temp_node = 0L;
522 int count = node->childrenCount();
523 temp_node = node->firstChild();
524 uint weight = temp_node->weight();
525 const KCompTreeNode* hit = temp_node;
526 for(
int i = 1; i < count; i++ ) {
527 temp_node = node->childAt(i);
528 if( temp_node->weight() > weight ) {
530 weight = hit->weight();
544 doBeep( PartialMatch );
551 void KCompletion::findAllCompletions(
const QString&
string,
552 KCompletionMatchesWrapper *matches,
553 bool& hasMultipleMatches)
const
560 if ( d->myIgnoreCase ) {
561 extractStringsFromNodeCI( d->myTreeRoot,
QString(),
string, matches );
562 hasMultipleMatches = (matches->count() > 1);
568 const KCompTreeNode *node = d->myTreeRoot;
571 for(
int i = 0; i <
string.length(); i++ ) {
573 node = node->find( ch );
585 while ( node->childrenCount() == 1 ) {
586 node = node->firstChild();
587 if ( !node->isNull() )
594 if ( node->childrenCount() == 0 )
595 matches->append( node->weight(),
completion );
600 hasMultipleMatches =
true;
601 extractStringsFromNode( node, completion, matches );
606 void KCompletion::extractStringsFromNode(
const KCompTreeNode *node,
608 KCompletionMatchesWrapper *matches,
609 bool addWeight )
const
611 if ( !node || !matches )
615 const KCompTreeChildren *list = node->children();
620 for ( KCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
623 if ( !node->isNull() )
626 while ( node && node->childrenCount() == 1 ) {
627 node = node->firstChild();
628 if ( node->isNull() )
633 if ( node && node->isNull() ) {
637 w.setNum( node->weight() );
640 matches->append( node->weight(), string );
644 if ( node && node->childrenCount() > 1 )
645 extractStringsFromNode( node,
string, matches, addWeight );
649 void KCompletion::extractStringsFromNodeCI(
const KCompTreeNode *node,
652 KCompletionMatchesWrapper *matches )
const
654 if ( restString.isEmpty() ) {
655 extractStringsFromNode( node, beginning, matches,
false );
659 QChar ch1 = restString.at(0);
660 QString newRest = restString.mid(1);
661 KCompTreeNode *child1, *child2;
663 child1 = node->find( ch1 );
665 extractStringsFromNodeCI( child1, beginning + QChar(*child1), newRest,
669 if ( ch1.isLetter() ) {
671 QChar ch2 = ch1.toLower();
675 child2 = node->find( ch2 );
677 extractStringsFromNodeCI( child2, beginning + QChar(*child2), newRest,
683 void KCompletion::doBeep( BeepMode mode )
const
692 event = QLatin1String(
"Textcompletion: rotation");
693 text =
i18n(
"You reached the end of the list\nof matching items.\n");
698 event = QLatin1String(
"Textcompletion: partial match");
699 text =
i18n(
"The completion is ambiguous, more than one\nmatch is available.\n");
704 event = QLatin1String(
"Textcompletion: no match");
705 text =
i18n(
"There is no matching item available.\n");
710 if ( !text.isEmpty() )
726 KCompTreeNode::~KCompTreeNode()
729 KCompTreeNode *cur = myChildren.begin();
731 KCompTreeNode *
next = cur->next;
732 delete myChildren.remove(cur);
742 KCompTreeNode *child =
find( ch );
744 child =
new KCompTreeNode( ch );
748 KCompTreeNode * prev = 0;
749 KCompTreeNode * cur = myChildren.begin();
758 myChildren.insert( prev, child );
760 myChildren.prepend(child);
764 myChildren.append( child );
780 string += QChar(0x0);
782 QVector<KCompTreeNode *> deletables(
string.length() + 1 );
784 KCompTreeNode *child = 0L;
785 KCompTreeNode *parent =
this;
786 deletables.replace( 0, parent );
789 for ( ; i <
string.length(); i++ )
791 child = parent->find(
string.at( i ) );
793 deletables.replace( i + 1, child );
800 for ( ; i >= 1; i-- )
802 parent = deletables.at( i - 1 );
803 child = deletables.at( i );
804 if ( child->myChildren.count() == 0 )
805 delete parent->myChildren.remove( child );
814 QStringList KCompletionMatchesWrapper::list()
const
816 if ( sortedList && dirty ) {
824 for ( it = sortedList->constBegin(); it != sortedList->constEnd(); ++it )
825 stringList.prepend( (*it).value() );
827 qStableSort(stringList.begin(), stringList.end(),
lessThan);
833 class KCompletionMatchesPrivate
836 KCompletionMatchesPrivate(
bool sort )
844 d( new KCompletionMatchesPrivate( o.d->sorting ) )
853 KCompletionMatchesList::operator=( o );
854 d->sorting = o.d->sorting;
860 : d( new KCompletionMatchesPrivate( sort_P ) )
865 : d( new KCompletionMatchesPrivate( matches.sorting() ) )
867 if( matches.sortedList != 0L )
868 KCompletionMatchesList::operator=( *matches.sortedList );
871 for( QStringList::ConstIterator it = l.begin();
885 if( d->sorting && sort_P )
889 for ( ConstIterator it =
begin(); it !=
end(); ++it )
890 stringList.prepend( (*it).value() );
902 for ( it1 =
begin(); it1 !=
end(); ++it1 ) {
903 for ( (it2 = it1), ++it2; it2 !=
end();) {
904 if( (*it1).value() == (*it2).value()) {
906 (*it1).first = qMax( (*it1).key(), (*it2).key());
915 void KCompTreeNodeList::append(KCompTreeNode *item)
929 void KCompTreeNodeList::prepend(KCompTreeNode *item)
951 item->next = after->next;
962 KCompTreeNode *cur = 0;
968 while (cur && cur->next != item) cur = cur->next;
971 cur->next = item->next;
979 KCompTreeNode *KCompTreeNodeList::at(uint index)
const
981 KCompTreeNode *cur = first;
982 while (index-- && cur) cur = cur->next;
988 #include "kcompletion.moc"
virtual void postProcessMatches(QStringList *pMatches) const
This method is called before a list of all available completions is emitted via matches.
QString i18n(const char *text)
virtual void clear()
Removes all inserted items.
QStringList list(bool sort=true) const
Returns the matches as a QStringList.
int naturalCompare(const QString &a, const QString &b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
virtual void setSoundsEnabled(bool enable)
Enables/disables playing a sound when.
Use alphabetically sorted order.
bool isEmpty() const
Returns true when the completion object contains no entries.
KCompletionMatches & operator=(const KCompletionMatches &)
assignment operator.
KAction * find(const QObject *recvr, const char *slot, QObject *parent)
Initiate a 'find' request in the current document.
QStringList items() const
Returns a list of all items inserted into KCompletion.
CompOrder
Constants that represent the order in which KCompletion performs completion-lookups.
virtual const QString & lastMatch() const
Returns the last match.
void match(const QString &item)
The matching item.
KGuiItem remove()
Returns the 'Remove' gui item.
void removeDuplicates()
Removes duplicate matches.
virtual void postProcessMatch(QString *pMatch) const
This method is called after a completion is found and before the matching string is emitted...
const KShortcut & insert()
Toggle insert/overwrite (with visual feedback, e.g.
bool sorting() const
If sorting() returns false, the matches aren't sorted by their weight, even if true is passed to list...
QStringList allMatches()
Returns a list of all items matching the last completed string.
Text is automatically filled in whenever possible.
virtual void setCompletionMode(KGlobalSettings::Completion mode)
Sets the completion mode to Auto/Manual, Shell or None.
void insertItems(const QStringList &items)
Inserts items into the list of possible completions.
virtual void setIgnoreCase(bool ignoreCase)
Setting this to true makes KCompletion behave case insensitively.
This structure is returned by KCompletion::allWeightedMatches .
virtual void setItems(const QStringList &list)
Sets the list of items available for completion.
~KCompletionMatches()
default destructor.
KAction * next(const QObject *recvr, const char *slot, QObject *parent)
Scroll down one page.
void matches(const QStringList &matchlist)
All matching items.
KGlobalSettings::Completion completionMode() const
Return the current completion mode.
Access the KDE global configuration.
bool lessThan(const QString &left, const QString &right)
void multipleMatches()
This signal is emitted, when calling makeCompletion() and more than one matching item is found...
QString nextMatch()
Returns the next item from the matching-items-list.
CompOrder order() const
Returns the completion order.
KGuiItem ok()
Returns the 'Ok' gui item.
virtual ~KCompletion()
Destructor, nothing special here, either.
Lists all possible matches in a popup list-box to choose from.
static KNotification * event(const QString &eventId, const QString &title, const QString &text, const QPixmap &pixmap=QPixmap(), QWidget *widget=0L, const NotificationFlags &flags=CloseOnTimeout, const KComponentData &componentData=KComponentData())
emit an event
Same as automatic except shortest match is used for completion.
virtual QString makeCompletion(const QString &string)
Attempts to find an item in the list of available completions, that begins with string.
bool ignoreCase() const
Return whether KCompletion acts case insensitively or not.
bool soundsEnabled() const
Tells you whether KCompletion will play sounds on certain occasions.
Completion
This enum describes the completion mode used for by the KCompletion class.
QStringList substringCompletion(const QString &string) const
Returns a list of all completion items that contain the given string.
void removeItem(const QString &item)
Removes an item from the list of available completions.
void addItem(const QString &item)
Adds an item to the list of available completions.
bool hasMultipleMatches() const
Returns true when more than one match is found.
Complete text much in the same way as a typical *nix shell would.
KCompletionMatches allWeightedMatches()
Returns a list of all items matching the last completed string.
const KShortcut & end()
Goto end of the document.
const KShortcut & completion()
Complete text in input widgets.
KCompletionMatches(bool sort)
Default constructor.
virtual void setOrder(CompOrder order)
KCompletion offers three different ways in which it offers its items:
QString previousMatch()
Returns the next item from the matching-items-list.
Lists all possible matches in a popup list-box to choose from, and automatically fill the result when...
const KShortcut & begin()
Goto beginning of the document.
KCompletion()
Constructor, nothing special here :)