22 #include "kcompletion_p.h"
29 #include <QtCore/QMutableVectorIterator>
31 class KCompletionPrivate
36 , myTreeNodeAllocator( KCompTreeNode::allocator() )
37 , myTreeRoot( new KCompTreeNode )
39 , myIgnoreCase( false )
40 , myHasMultipleMatches( false )
41 , myRotationIndex( 0 )
49 KCompletionMatchesWrapper matches;
53 QSharedPointer<KZoneAllocator> myTreeNodeAllocator;
59 KCompTreeNode * myTreeRoot;
62 bool myIgnoreCase : 1;
63 bool myHasMultipleMatches;
68 :d(new KCompletionPrivate)
81 d->matches.setSorting( order );
96 return d->myIgnoreCase;
108 bool weighted = (d->myOrder ==
Weighted);
109 QStringList::ConstIterator it;
111 for ( it = items.begin(); it != items.end(); ++it )
112 addWeightedItem( *it );
115 for ( it = items.begin(); it != items.end(); ++it )
122 KCompletionMatchesWrapper list;
123 bool addWeight = (d->myOrder ==
Weighted);
124 extractStringsFromNode( d->myTreeRoot,
QString(), &list, addWeight );
131 return (d->myTreeRoot->childrenCount() == 0);
149 d->myRotationIndex = 0;
150 d->myLastString.clear();
157 if ( item.isEmpty() )
160 KCompTreeNode *node = d->myTreeRoot;
161 uint len = item.length();
163 bool sorted = (d->myOrder ==
Sorted);
164 bool weighted = ((d->myOrder ==
Weighted) && weight > 1);
169 for ( uint i = 0; i < len; i++ ) {
170 node = node->insert( item.at(i), sorted );
172 node->confirm( weight -1 );
176 node = node->insert( 0x0,
true );
178 node->confirm( weight -1 );
182 void KCompletion::addWeightedItem(
const QString& item )
189 uint len = item.length();
193 int index = item.lastIndexOf(
':');
196 weight = item.mid( index + 1 ).toUInt( &ok );
203 addItem( item.left( len ), weight );
211 d->myRotationIndex = 0;
212 d->myLastString.clear();
214 d->myTreeRoot->remove( item );
221 d->myRotationIndex = 0;
222 d->myLastString.clear();
224 delete d->myTreeRoot;
225 d->myTreeRoot =
new KCompTreeNode;
237 d->myRotationIndex = 0;
238 d->myHasMultipleMatches =
false;
239 d->myLastMatch = d->myCurrentMatch;
244 string == d->myLastString ) {
249 findAllCompletions(
string, &d->matches, d->myHasMultipleMatches );
264 findAllCompletions(
string, &d->matches, d->myHasMultipleMatches );
265 if ( !d->matches.isEmpty() )
266 completion = d->matches.first();
269 completion = findCompletion(
string );
271 if ( d->myHasMultipleMatches )
274 d->myLastString = string;
281 emit
match( completion );
284 if ( completion.isNull() )
295 KCompletionMatchesWrapper allItems( d->myOrder );
296 extractStringsFromNode( d->myTreeRoot,
QString(), &allItems,
false );
302 if ( list.isEmpty() ) {
313 QStringList::ConstIterator it = list.constBegin();
315 for( ; it != list.constEnd(); ++it ) {
317 if ( item.indexOf(
string, 0, Qt::CaseInsensitive ) != -1 ) {
319 matches.append( item );
323 if ( matches.isEmpty() )
332 d->myCompletionMode = mode;
336 return d->myCompletionMode;
344 KCompletionMatchesWrapper
matches( d->myOrder );
346 findAllCompletions( d->myLastString, &matches, dummy );
357 KCompletionMatchesWrapper
matches( d->myOrder );
359 findAllCompletions( d->myLastString, &matches, dummy );
367 KCompletionMatchesWrapper
matches( d->myOrder );
369 findAllCompletions(
string, &matches, dummy );
377 KCompletionMatchesWrapper
matches( d->myOrder );
379 findAllCompletions(
string, &matches, dummy );
397 return d->myHasMultipleMatches;
407 d->myLastMatch = d->myCurrentMatch;
409 if ( d->matches.isEmpty() ) {
410 findAllCompletions( d->myLastString, &d->matches, d->myHasMultipleMatches );
411 if ( !d->matches.isEmpty() )
412 completion = d->matches.first();
414 d->myRotationIndex = 0;
416 emit
match( completion );
421 d->myLastMatch = matches[ d->myRotationIndex++ ];
423 if ( d->myRotationIndex == matches.count() -1 )
426 else if ( d->myRotationIndex == matches.count() )
427 d->myRotationIndex = 0;
429 completion = matches[ d->myRotationIndex ];
430 d->myCurrentMatch = completion;
432 emit
match( completion );
438 return d->myLastMatch;
445 d->myLastMatch = d->myCurrentMatch;
447 if ( d->matches.isEmpty() ) {
448 findAllCompletions( d->myLastString, &d->matches, d->myHasMultipleMatches );
449 if ( !d->matches.isEmpty() )
450 completion = d->matches.last();
452 d->myRotationIndex = 0;
454 emit
match( completion );
459 d->myLastMatch = matches[ d->myRotationIndex ];
460 if ( d->myRotationIndex == 1 )
463 else if ( d->myRotationIndex == 0 )
464 d->myRotationIndex = matches.count();
466 d->myRotationIndex--;
468 completion = matches[ d->myRotationIndex ];
471 emit
match( completion );
482 const KCompTreeNode *node = d->myTreeRoot;
485 for(
int i = 0; i <
string.length(); i++ ) {
487 node = node->find( ch );
499 while ( node->childrenCount() == 1 ) {
500 node = node->firstChild();
501 if ( !node->isNull() )
506 if ( node && node->childrenCount() > 1 ) {
507 d->myHasMultipleMatches =
true;
510 d->myRotationIndex = 1;
512 while ( (node = node->firstChild()) ) {
513 if ( !node->isNull() )
523 const KCompTreeNode* temp_node = 0L;
525 int count = node->childrenCount();
526 temp_node = node->firstChild();
527 uint weight = temp_node->weight();
528 const KCompTreeNode* hit = temp_node;
529 for(
int i = 1; i < count; i++ ) {
530 temp_node = node->childAt(i);
531 if( temp_node->weight() > weight ) {
533 weight = hit->weight();
547 doBeep( PartialMatch );
554 void KCompletion::findAllCompletions(
const QString&
string,
555 KCompletionMatchesWrapper *matches,
556 bool& hasMultipleMatches)
const
563 if ( d->myIgnoreCase ) {
564 extractStringsFromNodeCI( d->myTreeRoot,
QString(),
string, matches );
565 hasMultipleMatches = (matches->count() > 1);
571 const KCompTreeNode *node = d->myTreeRoot;
574 for(
int i = 0; i <
string.length(); i++ ) {
576 node = node->find( ch );
588 while ( node->childrenCount() == 1 ) {
589 node = node->firstChild();
590 if ( !node->isNull() )
597 if ( node->childrenCount() == 0 )
598 matches->append( node->weight(),
completion );
603 hasMultipleMatches =
true;
604 extractStringsFromNode( node, completion, matches );
609 void KCompletion::extractStringsFromNode(
const KCompTreeNode *node,
611 KCompletionMatchesWrapper *matches,
612 bool addWeight )
const
614 if ( !node || !matches )
618 const KCompTreeChildren *list = node->children();
623 for ( KCompTreeNode *cur = list->begin(); cur ; cur = cur->next) {
626 if ( !node->isNull() )
629 while ( node && node->childrenCount() == 1 ) {
630 node = node->firstChild();
631 if ( node->isNull() )
636 if ( node && node->isNull() ) {
640 w.setNum( node->weight() );
643 matches->append( node->weight(), string );
647 if ( node && node->childrenCount() > 1 )
648 extractStringsFromNode( node,
string, matches, addWeight );
652 void KCompletion::extractStringsFromNodeCI(
const KCompTreeNode *node,
655 KCompletionMatchesWrapper *matches )
const
657 if ( restString.isEmpty() ) {
658 extractStringsFromNode( node, beginning, matches,
false );
662 QChar ch1 = restString.at(0);
663 QString newRest = restString.mid(1);
664 KCompTreeNode *child1, *child2;
666 child1 = node->find( ch1 );
668 extractStringsFromNodeCI( child1, beginning + QChar(*child1), newRest,
672 if ( ch1.isLetter() ) {
674 QChar ch2 = ch1.toLower();
678 child2 = node->find( ch2 );
680 extractStringsFromNodeCI( child2, beginning + QChar(*child2), newRest,
686 void KCompletion::doBeep( BeepMode mode )
const
695 event = QLatin1String(
"Textcompletion: rotation");
696 text =
i18n(
"You reached the end of the list\nof matching items.\n");
701 event = QLatin1String(
"Textcompletion: partial match");
702 text =
i18n(
"The completion is ambiguous, more than one\nmatch is available.\n");
707 event = QLatin1String(
"Textcompletion: no match");
708 text =
i18n(
"There is no matching item available.\n");
713 if ( !text.isEmpty() )
729 KCompTreeNode::~KCompTreeNode()
732 KCompTreeNode *cur = myChildren.begin();
734 KCompTreeNode *
next = cur->next;
735 delete myChildren.remove(cur);
745 KCompTreeNode *child =
find( ch );
747 child =
new KCompTreeNode( ch );
751 KCompTreeNode * prev = 0;
752 KCompTreeNode * cur = myChildren.begin();
761 myChildren.insert( prev, child );
763 myChildren.prepend(child);
767 myChildren.append( child );
783 string += QChar(0x0);
785 QVector<KCompTreeNode *> deletables(
string.length() + 1 );
787 KCompTreeNode *child = 0L;
788 KCompTreeNode *parent =
this;
789 deletables.replace( 0, parent );
792 for ( ; i <
string.length(); i++ )
794 child = parent->find(
string.at( i ) );
796 deletables.replace( i + 1, child );
803 for ( ; i >= 1; i-- )
805 parent = deletables.at( i - 1 );
806 child = deletables.at( i );
807 if ( child->myChildren.count() == 0 )
808 delete parent->myChildren.remove( child );
817 QStringList KCompletionMatchesWrapper::list()
const
819 if ( sortedList && dirty ) {
827 for ( it = sortedList->constBegin(); it != sortedList->constEnd(); ++it )
828 stringList.prepend( (*it).value() );
830 qStableSort(stringList.begin(), stringList.end(),
lessThan);
836 class KCompletionMatchesPrivate
839 KCompletionMatchesPrivate(
bool sort )
847 d( new KCompletionMatchesPrivate( o.d->sorting ) )
856 KCompletionMatchesList::operator=( o );
857 d->sorting = o.d->sorting;
863 : d( new KCompletionMatchesPrivate( sort_P ) )
868 : d( new KCompletionMatchesPrivate( matches.sorting() ) )
870 if( matches.sortedList != 0L )
871 KCompletionMatchesList::operator=( *matches.sortedList );
874 for( QStringList::ConstIterator it = l.begin();
888 if( d->sorting && sort_P )
892 for ( ConstIterator it =
begin(); it !=
end(); ++it )
893 stringList.prepend( (*it).value() );
905 for ( it1 =
begin(); it1 !=
end(); ++it1 ) {
906 for ( (it2 = it1), ++it2; it2 !=
end();) {
907 if( (*it1).value() == (*it2).value()) {
909 (*it1).first = qMax( (*it1).key(), (*it2).key());
918 void KCompTreeNodeList::append(KCompTreeNode *item)
932 void KCompTreeNodeList::prepend(KCompTreeNode *item)
954 item->next = after->next;
965 KCompTreeNode *cur = 0;
971 while (cur && cur->next != item) cur = cur->next;
974 cur->next = item->next;
982 KCompTreeNode *KCompTreeNodeList::at(uint index)
const
984 KCompTreeNode *cur = first;
985 while (index-- && cur) cur = cur->next;
989 QSharedPointer<KZoneAllocator> KCompTreeNode::alloc(
new KZoneAllocator(8*1024));
991 #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 :)