KCompletion

kcompletion.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 1999, 2000, 2001 Carsten Pfeiffer <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "kcompletion.h"
9 #include "kcompletion_p.h"
10 #include <kcompletion_debug.h>
11 
12 #include <QCollator>
13 
14 void KCompletionPrivate::init()
15 {
17  treeNodeAllocator = KCompTreeNode::allocator(); // keep strong-ref to allocator instance
18  treeRoot = new KCompTreeNode;
19  beep = true;
20  ignoreCase = false;
21  hasMultipleMatches = false;
22  shouldAutoSuggest = true;
23  rotationIndex = 0;
24 }
25 
26 void KCompletionPrivate::addWeightedItem(const QString &item)
27 {
28  Q_Q(KCompletion);
29  if (order != KCompletion::Weighted) {
30  q->addItem(item, 0);
31  return;
32  }
33 
34  int len = item.length();
35  uint weight = 0;
36 
37  // find out the weighting of this item (appended to the string as ":num")
38  int index = item.lastIndexOf(QLatin1Char(':'));
39  if (index > 0) {
40  bool ok;
41 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
42  weight = QStringView(item).mid(index + 1).toUInt(&ok);
43 #else
44  weight = item.midRef(index + 1).toUInt(&ok);
45 #endif
46  if (!ok) {
47  weight = 0;
48  }
49 
50  len = index; // only insert until the ':'
51  }
52 
53  q->addItem(item.left(len), weight);
54  return;
55 }
56 
57 // tries to complete "string" from the tree-root
58 QString KCompletionPrivate::findCompletion(const QString &string)
59 {
60  QChar ch;
62  const KCompTreeNode *node = treeRoot;
63 
64  // start at the tree-root and try to find the search-string
65  for (int i = 0; i < string.length(); i++) {
66  ch = string.at(i);
67  node = node->find(ch);
68 
69  if (node) {
70  completion += ch;
71  } else {
72  return QString(); // no completion
73  }
74  }
75 
76  // Now we have the last node of the to be completed string.
77  // Follow it as long as it has exactly one child (= longest possible
78  // completion)
79 
80  while (node->childrenCount() == 1) {
81  node = node->firstChild();
82  if (!node->isNull()) {
83  completion += *node;
84  }
85  }
86  // if multiple matches and auto-completion mode
87  // -> find the first complete match
88  if (node && node->childrenCount() > 1) {
89  hasMultipleMatches = true;
90 
92  rotationIndex = 1;
93  if (order != KCompletion::Weighted) {
94  while ((node = node->firstChild())) {
95  if (!node->isNull()) {
96  completion += *node;
97  } else {
98  break;
99  }
100  }
101  } else {
102  // don't just find the "first" match, but the one with the
103  // highest priority
104 
105  const KCompTreeNode *temp_node = nullptr;
106  while (1) {
107  int count = node->childrenCount();
108  temp_node = node->firstChild();
109  uint weight = temp_node->weight();
110  const KCompTreeNode *hit = temp_node;
111  for (int i = 1; i < count; i++) {
112  temp_node = node->childAt(i);
113  if (temp_node->weight() > weight) {
114  hit = temp_node;
115  weight = hit->weight();
116  }
117  }
118  // 0x0 has the highest priority -> we have the best match
119  if (hit->isNull()) {
120  break;
121  }
122 
123  node = hit;
124  completion += *node;
125  }
126  }
127  }
128  }
129 
130  return completion;
131 }
132 
133 void KCompletionPrivate::defaultSort(QStringList &stringList)
134 {
135  QCollator c;
137  std::stable_sort(stringList.begin(), stringList.end(), c);
138 }
139 
141  : d_ptr(new KCompletionPrivate(this))
142 {
143  Q_D(KCompletion);
144  d->init();
146 }
147 
149 {
150 }
151 
153 {
154  Q_D(KCompletion);
155  d->order = order;
156  d->matches.setSorting(order);
157 }
158 
159 KCompletion::CompOrder KCompletion::order() const
160 {
161  Q_D(const KCompletion);
162  return d->order;
163 }
164 
165 void KCompletion::setIgnoreCase(bool ignoreCase)
166 {
167  Q_D(KCompletion);
168  d->ignoreCase = ignoreCase;
169 }
170 
171 bool KCompletion::ignoreCase() const
172 {
173  Q_D(const KCompletion);
174  return d->ignoreCase;
175 }
176 
177 void KCompletion::setItems(const QStringList &itemList)
178 {
179  clear();
180  insertItems(itemList);
181 }
182 
184 {
185  Q_D(KCompletion);
186  bool weighted = (d->order == Weighted);
188  if (weighted) { // determine weight
189  for (it = items.begin(); it != items.end(); ++it) {
190  d->addWeightedItem(*it);
191  }
192  } else {
193  for (it = items.begin(); it != items.end(); ++it) {
194  addItem(*it, 0);
195  }
196  }
197 }
198 
199 QStringList KCompletion::items() const
200 {
201  Q_D(const KCompletion);
202  KCompletionMatchesWrapper list(d->sorterFunction); // unsorted
203  bool addWeight = (d->order == Weighted);
204  list.extractStringsFromNode(d->treeRoot, QString(), addWeight);
205 
206  return list.list();
207 }
208 
210 {
211  Q_D(const KCompletion);
212  return (d->treeRoot->childrenCount() == 0);
213 }
214 
216 {
217 }
218 
220 {
221 }
222 
224 {
225 }
226 
227 void KCompletion::addItem(const QString &item)
228 {
229  Q_D(KCompletion);
230  d->matches.clear();
231  d->rotationIndex = 0;
232  d->lastString.clear();
233 
234  addItem(item, 0);
235 }
236 
237 void KCompletion::addItem(const QString &item, uint weight)
238 {
239  Q_D(KCompletion);
240  if (item.isEmpty()) {
241  return;
242  }
243 
244  KCompTreeNode *node = d->treeRoot;
245  int len = item.length();
246 
247  bool sorted = (d->order == Sorted);
248  bool weighted = ((d->order == Weighted) && weight > 1);
249 
250  // knowing the weight of an item, we simply add this weight to all of its
251  // nodes.
252 
253  for (int i = 0; i < len; i++) {
254  node = node->insert(item.at(i), sorted);
255  if (weighted) {
256  node->confirm(weight - 1); // node->insert() sets weighting to 1
257  }
258  }
259 
260  // add 0x0-item as delimiter with evtl. weight
261  node = node->insert(QChar(0x0), true);
262  if (weighted) {
263  node->confirm(weight - 1);
264  }
265  // qDebug("*** added: %s (%i)", item.toLatin1().constData(), node->weight());
266 }
267 
269 {
270  Q_D(KCompletion);
271  d->matches.clear();
272  d->rotationIndex = 0;
273  d->lastString.clear();
274 
275  d->treeRoot->remove(item);
276 }
277 
279 {
280  Q_D(KCompletion);
281  d->matches.clear();
282  d->rotationIndex = 0;
283  d->lastString.clear();
284 
285  delete d->treeRoot;
286  d->treeRoot = new KCompTreeNode;
287 }
288 
290 {
291  Q_D(KCompletion);
292  if (d->completionMode == CompletionNone) {
293  return QString();
294  }
295 
296  // qDebug() << "KCompletion: completing: " << string;
297 
298  d->matches.clear();
299  d->rotationIndex = 0;
300  d->hasMultipleMatches = false;
301  d->lastMatch = d->currentMatch;
302 
303  // in Shell-completion-mode, emit all matches when we get the same
304  // complete-string twice
305  if (d->completionMode == CompletionShell && string == d->lastString) {
306  // Don't use d->matches since calling postProcessMatches()
307  // on d->matches here would interfere with call to
308  // postProcessMatch() during rotation
309 
310  d->matches.findAllCompletions(d->treeRoot, string, d->ignoreCase, d->hasMultipleMatches);
311  QStringList l = d->matches.list();
312  postProcessMatches(&l);
313  Q_EMIT matches(l);
314 
315  return QString();
316  }
317 
319  // in case-insensitive popup mode, we search all completions at once
320  if (d->completionMode == CompletionPopup || d->completionMode == CompletionPopupAuto) {
321  d->matches.findAllCompletions(d->treeRoot, string, d->ignoreCase, d->hasMultipleMatches);
322  if (!d->matches.isEmpty()) {
323  completion = d->matches.first();
324  }
325  } else {
326  completion = d->findCompletion(string);
327  }
328 
329  if (d->hasMultipleMatches) {
331  }
332 
333  d->lastString = string;
334  d->currentMatch = completion;
335 
337 
338  if (!string.isEmpty()) { // only emit match when string is not empty
339  // qDebug() << "KCompletion: Match: " << completion;
341  }
342 
343  return completion;
344 }
345 
347 {
348  Q_D(const KCompletion);
349  // get all items in the tree, eventually in sorted order
350  KCompletionMatchesWrapper allItems(d->sorterFunction, d->order);
351  allItems.extractStringsFromNode(d->treeRoot, QString(), false);
352 
353  QStringList list = allItems.list();
354 
355  // subStringMatches is invoked manually, via a shortcut
356  if (list.isEmpty()) {
357  return list;
358  }
359 
360  if (string.isEmpty()) { // shortcut
361  postProcessMatches(&list);
362  return list;
363  }
364 
366  for (QStringList::ConstIterator it = list.constBegin(), total = list.constEnd(); it != total; ++it) {
367  QString item = *it;
368  if (item.indexOf(string, 0, Qt::CaseInsensitive) != -1) { // always case insensitive
369  postProcessMatch(&item);
370  matches.append(item);
371  }
372  }
373 
374  return matches;
375 }
376 
378 {
379  Q_D(KCompletion);
380  d->completionMode = mode;
381 }
382 
384 {
385  Q_D(const KCompletion);
386  return d->completionMode;
387 }
388 
389 void KCompletion::setShouldAutoSuggest(const bool shouldAutoSuggest)
390 {
391  Q_D(KCompletion);
392  d->shouldAutoSuggest = shouldAutoSuggest;
393 }
394 
396 {
397  Q_D(const KCompletion);
398  return d->shouldAutoSuggest;
399 }
400 
402 {
403  Q_D(KCompletion);
404  d->sorterFunction = sortFunc ? sortFunc : KCompletionPrivate::defaultSort;
405 }
406 
408 {
409  Q_D(KCompletion);
410  // Don't use d->matches since calling postProcessMatches()
411  // on d->matches here would interfere with call to
412  // postProcessMatch() during rotation
413  KCompletionMatchesWrapper matches(d->sorterFunction, d->order);
414  bool dummy;
415  matches.findAllCompletions(d->treeRoot, d->lastString, d->ignoreCase, dummy);
416  QStringList l = matches.list();
417  postProcessMatches(&l);
418  return l;
419 }
420 
422 {
423  Q_D(KCompletion);
424  // Don't use d->matches since calling postProcessMatches()
425  // on d->matches here would interfere with call to
426  // postProcessMatch() during rotation
427  KCompletionMatchesWrapper matches(d->sorterFunction, d->order);
428  bool dummy;
429  matches.findAllCompletions(d->treeRoot, d->lastString, d->ignoreCase, dummy);
431  postProcessMatches(&ret);
432  return ret;
433 }
434 
436 {
437  Q_D(KCompletion);
438  KCompletionMatchesWrapper matches(d->sorterFunction, d->order);
439  bool dummy;
440  matches.findAllCompletions(d->treeRoot, string, d->ignoreCase, dummy);
441  QStringList l = matches.list();
442  postProcessMatches(&l);
443  return l;
444 }
445 
447 {
448  Q_D(KCompletion);
449  KCompletionMatchesWrapper matches(d->sorterFunction, d->order);
450  bool dummy;
451  matches.findAllCompletions(d->treeRoot, string, d->ignoreCase, dummy);
453  postProcessMatches(&ret);
454  return ret;
455 }
456 
458 {
459  Q_D(KCompletion);
460  d->beep = enable;
461 }
462 
464 {
465  Q_D(const KCompletion);
466  return d->beep;
467 }
468 
470 {
471  Q_D(const KCompletion);
472  return d->hasMultipleMatches;
473 }
474 
475 /////////////////////////////////////////////////////
476 ///////////////// tree operations ///////////////////
477 
479 {
480  Q_D(KCompletion);
482  d->lastMatch = d->currentMatch;
483 
484  if (d->matches.isEmpty()) {
485  d->matches.findAllCompletions(d->treeRoot, d->lastString, d->ignoreCase, d->hasMultipleMatches);
486  if (!d->matches.isEmpty()) {
487  completion = d->matches.first();
488  }
489  d->currentMatch = completion;
490  d->rotationIndex = 0;
493  return completion;
494  }
495 
496  QStringList matches = d->matches.list();
497  d->lastMatch = matches[d->rotationIndex++];
498 
499  if (d->rotationIndex == matches.count()) {
500  d->rotationIndex = 0;
501  }
502 
503  completion = matches[d->rotationIndex];
504  d->currentMatch = completion;
507  return completion;
508 }
509 
511 {
512  Q_D(const KCompletion);
513  return d->lastMatch;
514 }
515 
517 {
518  Q_D(KCompletion);
520  d->lastMatch = d->currentMatch;
521 
522  if (d->matches.isEmpty()) {
523  d->matches.findAllCompletions(d->treeRoot, d->lastString, d->ignoreCase, d->hasMultipleMatches);
524  if (!d->matches.isEmpty()) {
525  completion = d->matches.last();
526  }
527  d->currentMatch = completion;
528  d->rotationIndex = 0;
531  return completion;
532  }
533 
534  QStringList matches = d->matches.list();
535  d->lastMatch = matches[d->rotationIndex];
536 
537  if (d->rotationIndex == 0) {
538  d->rotationIndex = matches.count();
539  }
540 
541  d->rotationIndex--;
542 
543  completion = matches[d->rotationIndex];
544  d->currentMatch = completion;
547  return completion;
548 }
549 
550 /////////////////////////////////
551 /////////
552 
553 // Implements the tree. Every node is a QChar and has a list of children, which
554 // are Nodes as well.
555 // QChar( 0x0 ) is used as the delimiter of a string; the last child of each
556 // inserted string is 0x0.
557 
558 KCompTreeNode::~KCompTreeNode()
559 {
560  // delete all children
561  KCompTreeNode *cur = m_children.begin();
562  while (cur) {
563  KCompTreeNode *next = cur->m_next;
564  delete m_children.remove(cur);
565  cur = next;
566  }
567 }
568 
569 // Adds a child-node "ch" to this node. If such a node is already existent,
570 // it will not be created. Returns the new/existing node.
571 KCompTreeNode *KCompTreeNode::insert(const QChar &ch, bool sorted)
572 {
573  KCompTreeNode *child = find(ch);
574  if (!child) {
575  child = new KCompTreeNode(ch);
576 
577  // FIXME, first (slow) sorted insertion implementation
578  if (sorted) {
579  KCompTreeNode *prev = nullptr;
580  KCompTreeNode *cur = m_children.begin();
581  while (cur) {
582  if (ch > *cur) {
583  prev = cur;
584  cur = cur->m_next;
585  } else {
586  break;
587  }
588  }
589  if (prev) {
590  m_children.insert(prev, child);
591  } else {
592  m_children.prepend(child);
593  }
594  }
595 
596  else {
597  m_children.append(child);
598  }
599  }
600 
601  // implicit weighting: the more often an item is inserted, the higher
602  // priority it gets.
603  child->confirm();
604 
605  return child;
606 }
607 
608 // Iteratively removes a string from the tree. The nicer recursive
609 // version apparently was a little memory hungry (see #56757)
610 void KCompTreeNode::remove(const QString &str)
611 {
612  QString string = str;
613  string += QChar(0x0);
614 
615  QVector<KCompTreeNode *> deletables(string.length() + 1);
616 
617  KCompTreeNode *child = nullptr;
618  KCompTreeNode *parent = this;
619  deletables.replace(0, parent);
620 
621  int i = 0;
622  for (; i < string.length(); i++) {
623  child = parent->find(string.at(i));
624  if (child) {
625  deletables.replace(i + 1, child);
626  } else {
627  break;
628  }
629 
630  parent = child;
631  }
632 
633  for (; i >= 1; i--) {
634  parent = deletables.at(i - 1);
635  child = deletables.at(i);
636  if (child->m_children.count() == 0) {
637  delete parent->m_children.remove(child);
638  }
639  }
640 }
641 
642 QStringList KCompletionMatchesWrapper::list() const
643 {
644  if (m_sortedList && m_dirty) {
645  m_sortedList->sort();
646  m_dirty = false;
647 
648  m_stringList.clear();
649 
650  // high weight == sorted last -> reverse the sorting here
651  QList<KSortableItem<QString>>::const_iterator it;
652  for (it = m_sortedList->constBegin(); it != m_sortedList->constEnd(); ++it) {
653  m_stringList.prepend((*it).value());
654  }
655  } else if (m_compOrder == KCompletion::Sorted) {
656  m_sorterFunction(m_stringList);
657  }
658 
659  return m_stringList;
660 }
661 
662 void KCompletionMatchesWrapper::findAllCompletions(const KCompTreeNode *treeRoot, const QString &string, bool ignoreCase, bool &hasMultipleMatches)
663 {
664  // qDebug() << "*** finding all completions for " << string;
665 
666  if (string.isEmpty()) {
667  return;
668  }
669 
670  if (ignoreCase) { // case insensitive completion
671  extractStringsFromNodeCI(treeRoot, QString(), string);
672  hasMultipleMatches = (count() > 1);
673  return;
674  }
675 
676  QChar ch;
678  const KCompTreeNode *node = treeRoot;
679 
680  // start at the tree-root and try to find the search-string
681  for (int i = 0; i < string.length(); i++) {
682  ch = string.at(i);
683  node = node->find(ch);
684 
685  if (node) {
686  completion += ch;
687  } else {
688  return; // no completion -> return empty list
689  }
690  }
691 
692  // Now we have the last node of the to be completed string.
693  // Follow it as long as it has exactly one child (= longest possible
694  // completion)
695 
696  while (node->childrenCount() == 1) {
697  node = node->firstChild();
698  if (!node->isNull()) {
699  completion += *node;
700  }
701  // qDebug() << completion << node->latin1();
702  }
703 
704  // there is just one single match)
705  if (node->childrenCount() == 0) {
706  append(node->weight(), completion);
707  }
708 
709  else {
710  // node has more than one child
711  // -> recursively find all remaining completions
712  hasMultipleMatches = true;
713  extractStringsFromNode(node, completion);
714  }
715 }
716 
717 void KCompletionMatchesWrapper::extractStringsFromNode(const KCompTreeNode *node, const QString &beginning, bool addWeight)
718 {
719  if (!node) {
720  return;
721  }
722 
723  // qDebug() << "Beginning: " << beginning;
724  const KCompTreeChildren *list = node->children();
725  QString string;
726  QString w;
727 
728  // loop thru all children
729  for (KCompTreeNode *cur = list->begin(); cur; cur = cur->m_next) {
730  string = beginning;
731  node = cur;
732  if (!node->isNull()) {
733  string += *node;
734  }
735 
736  while (node && node->childrenCount() == 1) {
737  node = node->firstChild();
738  if (node->isNull()) {
739  break;
740  }
741  string += *node;
742  }
743 
744  if (node && node->isNull()) { // we found a leaf
745  if (addWeight) {
746  // add ":num" to the string to store the weighting
747  string += QLatin1Char(':');
748  w.setNum(node->weight());
749  string.append(w);
750  }
751  append(node->weight(), string);
752  }
753 
754  // recursively find all other strings.
755  if (node && node->childrenCount() > 1) {
756  extractStringsFromNode(node, string, addWeight);
757  }
758  }
759 }
760 
761 void KCompletionMatchesWrapper::extractStringsFromNodeCI(const KCompTreeNode *node, const QString &beginning, const QString &restString)
762 {
763  if (restString.isEmpty()) {
764  extractStringsFromNode(node, beginning, false /*noweight*/);
765  return;
766  }
767 
768  QChar ch1 = restString.at(0);
769  QString newRest = restString.mid(1);
770  KCompTreeNode *child1;
771  KCompTreeNode *child2;
772 
773  child1 = node->find(ch1); // the correct match
774  if (child1) {
775  extractStringsFromNodeCI(child1, beginning + QChar(*child1), newRest);
776  }
777 
778  // append the case insensitive matches, if available
779  if (ch1.isLetter()) {
780  // find out if we have to lower or upper it. Is there a better way?
781  QChar ch2 = ch1.toLower();
782  if (ch1 == ch2) {
783  ch2 = ch1.toUpper();
784  }
785  if (ch1 != ch2) {
786  child2 = node->find(ch2);
787  if (child2) {
788  extractStringsFromNodeCI(child2, beginning + QChar(*child2), newRest);
789  }
790  }
791  }
792 }
793 
794 void KCompTreeNodeList::append(KCompTreeNode *item)
795 {
796  m_count++;
797  if (!m_last) {
798  m_last = item;
799  m_last->m_next = nullptr;
800  m_first = item;
801  return;
802  }
803  m_last->m_next = item;
804  item->m_next = nullptr;
805  m_last = item;
806 }
807 
808 void KCompTreeNodeList::prepend(KCompTreeNode *item)
809 {
810  m_count++;
811  if (!m_last) {
812  m_last = item;
813  m_last->m_next = nullptr;
814  m_first = item;
815  return;
816  }
817  item->m_next = m_first;
818  m_first = item;
819 }
820 
821 void KCompTreeNodeList::insert(KCompTreeNode *after, KCompTreeNode *item)
822 {
823  if (!after) {
824  append(item);
825  return;
826  }
827 
828  m_count++;
829 
830  item->m_next = after->m_next;
831  after->m_next = item;
832 
833  if (after == m_last) {
834  m_last = item;
835  }
836 }
837 
838 KCompTreeNode *KCompTreeNodeList::remove(KCompTreeNode *item)
839 {
840  if (!m_first || !item) {
841  return nullptr;
842  }
843  KCompTreeNode *cur = nullptr;
844 
845  if (item == m_first) {
846  m_first = m_first->m_next;
847  } else {
848  cur = m_first;
849  while (cur && cur->m_next != item) {
850  cur = cur->m_next;
851  }
852  if (!cur) {
853  return nullptr;
854  }
855  cur->m_next = item->m_next;
856  }
857  if (item == m_last) {
858  m_last = cur;
859  }
860  m_count--;
861  return item;
862 }
863 
864 KCompTreeNode *KCompTreeNodeList::at(uint index) const
865 {
866  KCompTreeNode *cur = m_first;
867  while (index-- && cur) {
868  cur = cur->m_next;
869  }
870  return cur;
871 }
872 
873 QSharedPointer<KZoneAllocator> KCompTreeNode::m_alloc(new KZoneAllocator(8 * 1024));
QString previousMatch()
Returns the next item from the list of matching items.
CompletionMode completionMode() const
Returns the current completion mode.
@ CompletionAuto
Text is automatically filled in whenever possible.
Definition: kcompletion.h:139
@ CompletionPopup
Lists all possible matches in a popup list box to choose from.
Definition: kcompletion.h:151
virtual void postProcessMatch(QString *match) const
This method is called after a completion is found and before the matching string is emitted.
virtual void setItems(const QStringList &itemList)
Sets the list of items available for completion.
QChar toLower() const const
CaseSensitive
Q_EMITQ_EMIT
QStringRef midRef(int position, int n) const const
virtual void setSoundsEnabled(bool enable)
Enables/disables emitting a sound when.
QStringView mid(qsizetype start) const const
A generic class for completing QStrings.
Definition: kcompletion.h:117
QChar toUpper() const const
QList::const_iterator constBegin() const const
void setSorterFunction(SorterFunction sortFunc)
Sets a custom function to be used to sort the matches.
void setShouldAutoSuggest(bool shouldAutosuggest)
Deriving classes may set this property and control whether the auto-suggestion should be displayed fo...
bool isLetter() const const
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
@ Weighted
Use weighted order.
Definition: kcompletion.h:166
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
CompletionMode
This enum describes the completion mode used for by the KCompletion class.
Definition: kcompletion.h:131
@ CompletionNone
No completion is used.
Definition: kcompletion.h:135
virtual const QString & lastMatch() const
Returns the last match.
@ Insertion
Use order of insertion.
Definition: kcompletion.h:165
CompOrder
Constants that represent the order in which KCompletion performs completion lookups.
Definition: kcompletion.h:163
void insertItems(const QStringList &items)
Inserts items into the list of possible completions.
void prepend(const T &value)
~KCompletion() override
Destructor, nothing special here, either.
void match(const QString &item)
This signal is emitted when a match is found.
List for keeping matches returned from KCompletion.
QString & setNum(short n, int base)
QStringList substringCompletion(const QString &string) const
Returns a list of all completion items that contain the given string.
void matches(const QStringList &matchlist)
This signal is emitted by makeCompletion() in shell-completion mode when the same string is passed to...
KCompletion::CompletionMode completionMode() const
Returns the current completion mode.
QString nextMatch()
Returns the next item from the list of matching items.
bool isEmpty() const const
int length() const const
bool isEmpty() const
Returns true if the completion object contains no entries.
QWidget * find(WId id)
bool isEmpty() const const
@ CompletionShell
Completes text much in the same way as a typical *nix shell would.
Definition: kcompletion.h:147
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
virtual void setIgnoreCase(bool ignoreCase)
Setting this to true makes KCompletion behave case insensitively.
virtual void setCompletionMode(CompletionMode mode)
Sets the completion mode.
QStringList allMatches()
Returns a list of all items matching the last completed string.
@ CompletionPopupAuto
Lists all possible matches in a popup list box to choose from, and automatically fills the result whe...
Definition: kcompletion.h:156
virtual QString makeCompletion(const QString &string)
Attempts to find an item in the list of available completions that begins with string.
uint toUInt(bool *ok, int base) const const
typedef ConstIterator
bool hasMultipleMatches() const
Returns true when more than one match is found.
void multipleMatches()
This signal is emitted when calling makeCompletion() and more than one matching item is found.
QList::const_iterator constEnd() const const
QString left(int n) const const
virtual void postProcessMatches(QStringList *matchList) const
This method is called before a list of all available completions is emitted via matches().
void removeItem(const QString &item)
Removes an item from the list of available completions.
bool shouldAutoSuggest() const
Informs the caller if they should display the auto-suggestion for the last completion operation perfo...
void addItem(const QString &item)
Adds an item to the list of available completions.
const QChar at(int position) const const
QList::iterator begin()
std::function< void(QStringList &)> SorterFunction
The sorter function signature.
Definition: kcompletion.h:176
KCompletionMatches allWeightedMatches()
Returns a list of all items matching the last completed string.
virtual void clear()
Removes all inserted items.
bool soundsEnabled() const
Tells you whether KCompletion will emit sounds on certain occasions.
QList::iterator end()
QString mid(int position, int n) const const
void setCaseSensitivity(Qt::CaseSensitivity sensitivity)
KCompletion()
Constructor, nothing special here :)
QObject * parent() const const
QString & append(QChar ch)
Q_D(Todo)
@ Sorted
Use alphabetically sorted order or custom sorter logic.
Definition: kcompletion.h:164
void completion(const QString &)
Emitted when the completion key is pressed.
void sort(Qt::CaseSensitivity cs)
virtual void setOrder(CompOrder order)
KCompletion offers three different ways in which it offers its items:
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Jun 27 2022 04:07:52 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.