• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Kate

  • kde-4.14
  • applications
  • kate
  • part
  • completion
katecompletionmodel.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries and the Kate part.
2  *
3  * Copyright (C) 2005-2006 Hamish Rodda <rodda@kde.org>
4  * Copyright (C) 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "katecompletionmodel.h"
23 
24 #include <QTextEdit>
25 #include <QMultiMap>
26 #include <QTimer>
27 #include <QVarLengthArray>
28 
29 #include <klocale.h>
30 #include <kiconloader.h>
31 #include <kapplication.h>
32 
33 #include "katecompletionwidget.h"
34 #include "katecompletiontree.h"
35 #include "katecompletiondelegate.h"
36 #include "kateargumenthintmodel.h"
37 #include "kateview.h"
38 #include "katerenderer.h"
39 #include "kateconfig.h"
40 #include "codecompletionmodelcontrollerinterfacev4.h"
41 
42 using namespace KTextEditor;
43 
45 class HierarchicalModelHandler {
46 public:
47  HierarchicalModelHandler(CodeCompletionModel* model);
48  void addValue(CodeCompletionModel::ExtraItemDataRoles role, const QVariant& value);
49  //Walks the index upwards and collects all defined completion-roles on the way
50  void collectRoles(const QModelIndex& index);
51  void takeRole(const QModelIndex& index);
52 
53  CodeCompletionModel* model() const;
54 
55  //Assumes that index is a sub-index of the indices where role-values were taken
56  QVariant getData(CodeCompletionModel::ExtraItemDataRoles role, const QModelIndex& index) const;
57 
58  bool hasHierarchicalRoles() const;
59 
60  int inheritanceDepth(const QModelIndex& i) const;
61 
62  QString customGroup() const {
63  return m_customGroup;
64  }
65 
66  int customGroupingKey() const {
67  return m_groupSortingKey;
68  }
69 private:
70  typedef QMap<CodeCompletionModel::ExtraItemDataRoles, QVariant> RoleMap;
71  RoleMap m_roleValues;
72  QString m_customGroup;
73  int m_groupSortingKey;
74  CodeCompletionModel* m_model;
75 };
76 
77 CodeCompletionModel* HierarchicalModelHandler::model() const {
78  return m_model;
79 }
80 
81 bool HierarchicalModelHandler::hasHierarchicalRoles() const {
82  return !m_roleValues.isEmpty();
83 }
84 
85 void HierarchicalModelHandler::collectRoles(const QModelIndex& index) {
86  if( index.parent().isValid() )
87  collectRoles(index.parent());
88  if(m_model->rowCount(index) != 0)
89  takeRole(index);
90 }
91 
92 int HierarchicalModelHandler::inheritanceDepth(const QModelIndex& i) const {
93  return getData(CodeCompletionModel::InheritanceDepth, i).toInt();
94 }
95 
96 void HierarchicalModelHandler::takeRole(const QModelIndex& index) {
97  QVariant v = index.data(CodeCompletionModel::GroupRole);
98  if( v.isValid() && v.canConvert(QVariant::Int) ) {
99  QVariant value = index.data(v.toInt());
100  if(v.toInt() == Qt::DisplayRole) {
101  m_customGroup = index.data(Qt::DisplayRole).toString();
102  QVariant sortingKey = index.data(CodeCompletionModel::InheritanceDepth);
103  if(sortingKey.canConvert(QVariant::Int))
104  m_groupSortingKey = sortingKey.toInt();
105  }else{
106  m_roleValues[(CodeCompletionModel::ExtraItemDataRoles)v.toInt()] = value;
107  }
108  }else{
109  kDebug( 13035 ) << "Did not return valid GroupRole in hierarchical completion-model";
110  }
111 }
112 
113 QVariant HierarchicalModelHandler::getData(CodeCompletionModel::ExtraItemDataRoles role, const QModelIndex& index) const {
114  RoleMap::const_iterator it = m_roleValues.find(role);
115  if( it != m_roleValues.end() )
116  return *it;
117  else
118  return index.data(role);
119 }
120 
121 HierarchicalModelHandler::HierarchicalModelHandler(CodeCompletionModel* model) : m_groupSortingKey(-1), m_model(model) {
122 }
123 
124 void HierarchicalModelHandler::addValue(CodeCompletionModel::ExtraItemDataRoles role, const QVariant& value) {
125  m_roleValues[role] = value;
126 }
127 
128 KateCompletionModel::KateCompletionModel(KateCompletionWidget* parent)
129  : ExpandingWidgetModel(parent)
130  , m_hasGroups(false)
131  , m_matchCaseSensitivity(Qt::CaseInsensitive)
132  , m_ungrouped(new Group(this))
133  , m_argumentHints(new Group(this))
134  , m_bestMatches(new Group(this))
135  , m_sortingEnabled(false)
136  , m_sortingAlphabetical(false)
137  , m_isSortingByInheritance(false)
138  , m_sortingCaseSensitivity(Qt::CaseInsensitive)
139  , m_filteringEnabled(false)
140  , m_filterContextMatchesOnly(false)
141  , m_filterByAttribute(false)
142  , m_filterAttributes(KTextEditor::CodeCompletionModel::NoProperty)
143  , m_maximumInheritanceDepth(0)
144  , m_groupingEnabled(false)
145  , m_accessConst(false)
146  , m_accessStatic(false)
147  , m_accesSignalSlot(false)
148  , m_columnMergingEnabled(false)
149 // , m_haveExactMatch(false)
150 {
151 
152  m_ungrouped->attribute = 0;
153  m_argumentHints->attribute = -1;
154  m_bestMatches->attribute = BestMatchesProperty;
155 
156  m_argumentHints->title = i18n("Argument-hints");
157  m_bestMatches->title = i18n("Best matches");
158 
159  m_emptyGroups.append(m_ungrouped);
160  m_emptyGroups.append(m_argumentHints);
161  m_emptyGroups.append(m_bestMatches);
162 
163  m_updateBestMatchesTimer = new QTimer(this);
164  m_updateBestMatchesTimer->setSingleShot(true);
165  connect(m_updateBestMatchesTimer, SIGNAL(timeout()), this, SLOT(updateBestMatches()));
166 
167  m_groupHash.insert(0, m_ungrouped);
168  m_groupHash.insert(-1, m_argumentHints);
169  m_groupHash.insert(BestMatchesProperty, m_argumentHints);
170 }
171 
172 KateCompletionModel::~KateCompletionModel() {
173  clearCompletionModels();
174  delete m_argumentHints;
175  delete m_ungrouped;
176  delete m_bestMatches;
177 }
178 
179 QTreeView* KateCompletionModel::treeView() const {
180  return view()->completionWidget()->treeView();
181 }
182 
183 QVariant KateCompletionModel::data( const QModelIndex & index, int role ) const
184 {
185  if (!hasCompletionModel() || !index.isValid())
186  return QVariant();
187 
188  if( role == Qt::DecorationRole && index.column() == KTextEditor::CodeCompletionModel::Prefix && isExpandable(index) )
189  {
190  cacheIcons();
191 
192  if( !isExpanded(index ) )
193  return QVariant( m_collapsedIcon );
194  else
195  return QVariant( m_expandedIcon );
196  }
197 
198  //groupOfParent returns a group when the index is a member of that group, but not the group head/label.
199  if (!hasGroups() || groupOfParent(index)) {
200  switch (role) {
201  case Qt::TextAlignmentRole:
202  if (isColumnMergingEnabled() && m_columnMerges.count()) {
203  int c = 0;
204  foreach (const QList<int>& list, m_columnMerges) {
205  foreach (int column, list) {
206  if (c++ == index.column()) {
207  if (column == CodeCompletionModel::Scope)
208  if (list.count() == 1)
209  return Qt::AlignRight;
210 
211  goto dontalign;
212  }
213  }
214  }
215 
216  } else if ((!isColumnMergingEnabled() || m_columnMerges.isEmpty()) && index.column() == CodeCompletionModel::Scope) {
217  return Qt::AlignRight;
218  }
219 
220  dontalign:
221  break;
222  }
223 
224  // Merge text for column merging
225  if (role == Qt::DisplayRole && m_columnMerges.count() && isColumnMergingEnabled()) {
226  QString text;
227  foreach (int column, m_columnMerges[index.column()]) {
228  QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer()));
229  text.append(sourceIndex.data(role).toString());
230  }
231 
232  return text;
233  }
234 
235  if(role == CodeCompletionModel::HighlightingMethod)
236  {
237  //Return that we are doing custom-highlighting of one of the sub-strings does it. Unfortunately internal highlighting does not work for the other substrings.
238  foreach (int column, m_columnMerges[index.column()]) {
239  QModelIndex sourceIndex = mapToSource(createIndex(index.row(), column, index.internalPointer()));
240  QVariant method = sourceIndex.data(CodeCompletionModel::HighlightingMethod);
241  if( method.type() == QVariant::Int && method.toInt() == CodeCompletionModel::CustomHighlighting)
242  return QVariant(CodeCompletionModel::CustomHighlighting);
243  }
244  return QVariant();
245  }
246  if(role == CodeCompletionModel::CustomHighlight)
247  {
248  //Merge custom highlighting if multiple columns were merged
249  QStringList strings;
250 
251  //Collect strings
252  foreach (int column, m_columnMerges[index.column()])
253  strings << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(Qt::DisplayRole).toString();
254 
255  QList<QVariantList> highlights;
256 
257  //Collect custom-highlightings
258  foreach (int column, m_columnMerges[index.column()])
259  highlights << mapToSource(createIndex(index.row(), column, index.internalPointer())).data(CodeCompletionModel::CustomHighlight).toList();
260 
261  return mergeCustomHighlighting( strings, highlights, 0 );
262  }
263 
264  QVariant v = mapToSource(index).data(role);
265  if( v.isValid() )
266  return v;
267  else
268  return ExpandingWidgetModel::data(index, role);
269  }
270 
271  //Returns a nonzero group if this index is the head of a group(A Label in the list)
272  Group* g = groupForIndex(index);
273 
274  if (g && (!g->isEmpty)) {
275  switch (role) {
276  case Qt::DisplayRole:
277  //We return the group-header for all columns, ExpandingDelegate will paint them properly over the whole space
278  return QString(' ' + g->title);
279  break;
280 
281  case Qt::FontRole:
282  if (!index.column()) {
283  QFont f = view()->renderer()->config()->font();
284  f.setBold(true);
285  return f;
286  }
287  break;
288 
289  case Qt::ForegroundRole:
290  return KApplication::kApplication()->palette().toolTipText().color();
291  case Qt::BackgroundRole:
292  return KApplication::kApplication()->palette().toolTipBase().color();
293  }
294  }
295 
296  return QVariant();
297 }
298 
299 int KateCompletionModel::contextMatchQuality(const QModelIndex& index) const {
300  if(!index.isValid())
301  return 0;
302  Group* g = groupOfParent(index);
303  if(!g || g->filtered.size() < index.row())
304  return 0;
305 
306  return contextMatchQuality(g->filtered[index.row()].sourceRow());
307 }
308 
309 int KateCompletionModel::contextMatchQuality(const ModelRow& source) const {
310  QModelIndex realIndex = source.second;
311 
312  int bestMatch = -1;
313  //Iterate through all argument-hints and find the best match-quality
314  foreach( const Item& item, m_argumentHints->filtered )
315  {
316  const ModelRow& row(item.sourceRow());
317  if( realIndex.model() != row.first )
318  continue; //We can only match within the same source-model
319 
320  QModelIndex hintIndex = row.second;
321 
322  QVariant depth = hintIndex.data(CodeCompletionModel::ArgumentHintDepth);
323  if( !depth.isValid() || depth.type() != QVariant::Int || depth.toInt() != 1 )
324  continue; //Only match completion-items to argument-hints of depth 1(the ones the item will be given to as argument)
325 
326  hintIndex.data(CodeCompletionModel::SetMatchContext);
327 
328  QVariant matchQuality = realIndex.data(CodeCompletionModel::MatchQuality);
329  if( matchQuality.isValid() && matchQuality.type() == QVariant::Int ) {
330  int m = matchQuality.toInt();
331  if( m > bestMatch )
332  bestMatch = m;
333  }
334  }
335 
336  if(m_argumentHints->filtered.isEmpty()) {
337  QVariant matchQuality = realIndex.data(CodeCompletionModel::MatchQuality);
338  if( matchQuality.isValid() && matchQuality.type() == QVariant::Int ) {
339  int m = matchQuality.toInt();
340  if( m > bestMatch )
341  bestMatch = m;
342  }
343  }
344 
345  return bestMatch;
346 }
347 
348 Qt::ItemFlags KateCompletionModel::flags( const QModelIndex & index ) const
349 {
350  if (!hasCompletionModel() || !index.isValid())
351  return 0;
352 
353  if (!hasGroups() || groupOfParent(index))
354  return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
355 
356  return Qt::ItemIsEnabled;
357 }
358 
359 KateCompletionWidget* KateCompletionModel::widget() const {
360  return static_cast<KateCompletionWidget*>(QObject::parent());
361 }
362 
363 KateView * KateCompletionModel::view( ) const
364 {
365  return widget()->view();
366 }
367 
368 void KateCompletionModel::setMatchCaseSensitivity( Qt::CaseSensitivity cs )
369 {
370  m_matchCaseSensitivity = cs;
371 }
372 
373 int KateCompletionModel::columnCount( const QModelIndex& ) const
374 {
375  return isColumnMergingEnabled() && !m_columnMerges.isEmpty() ? m_columnMerges.count() : KTextEditor::CodeCompletionModel::ColumnCount;
376 }
377 
378 KateCompletionModel::ModelRow KateCompletionModel::modelRowPair(const QModelIndex& index) const
379 {
380  return qMakePair(static_cast<CodeCompletionModel*>(const_cast<QAbstractItemModel*>(index.model())), index);
381 }
382 
383 bool KateCompletionModel::hasChildren( const QModelIndex & parent ) const
384 {
385  if (!hasCompletionModel())
386  return false;
387 
388  if (!parent.isValid()) {
389  if (hasGroups())
390  return true;
391 
392  return !m_ungrouped->filtered.isEmpty();
393  }
394 
395  if (parent.column() != 0)
396  return false;
397 
398  if (!hasGroups())
399  return false;
400 
401  if (Group* g = groupForIndex(parent))
402  return !g->filtered.isEmpty();
403 
404  return false;
405 }
406 
407 QModelIndex KateCompletionModel::index( int row, int column, const QModelIndex & parent ) const
408 {
409  if (row < 0 || column < 0 || column >= columnCount(QModelIndex()))
410  return QModelIndex();
411 
412  if (parent.isValid() || !hasGroups()) {
413  if (parent.isValid() && parent.column() != 0)
414  return QModelIndex();
415 
416  Group* g = groupForIndex(parent);
417 
418  if (!g)
419  return QModelIndex();
420 
421  if (row >= g->filtered.count()) {
422  //kWarning() << "Invalid index requested: row " << row << " beyond indivdual range in group " << g;
423  return QModelIndex();
424  }
425 
426  //kDebug( 13035 ) << "Returning index for child " << row << " of group " << g;
427  return createIndex(row, column, g);
428  }
429 
430  if (row >= m_rowTable.count()) {
431  //kWarning() << "Invalid index requested: row " << row << " beyond group range.";
432  return QModelIndex();
433  }
434 
435  //kDebug( 13035 ) << "Returning index for group " << m_rowTable[row];
436  return createIndex(row, column, 0);
437 }
438 
439 /*QModelIndex KateCompletionModel::sibling( int row, int column, const QModelIndex & index ) const
440 {
441  if (row < 0 || column < 0 || column >= columnCount(QModelIndex()))
442  return QModelIndex();
443 
444  if (!index.isValid()) {
445  }
446 
447  if (Group* g = groupOfParent(index)) {
448  if (row >= g->filtered.count())
449  return QModelIndex();
450 
451  return createIndex(row, column, g);
452  }
453 
454  if (hasGroups())
455  return QModelIndex();
456 
457  if (row >= m_ungrouped->filtered.count())
458  return QModelIndex();
459 
460  return createIndex(row, column, m_ungrouped);
461 }*/
462 
463 bool KateCompletionModel::hasIndex( int row, int column, const QModelIndex & parent ) const
464 {
465  if (row < 0 || column < 0 || column >= columnCount(QModelIndex()))
466  return false;
467 
468  if (parent.isValid() || !hasGroups()) {
469  if (parent.isValid() && parent.column() != 0)
470  return false;
471 
472  Group* g = groupForIndex(parent);
473 
474  if (row >= g->filtered.count())
475  return false;
476 
477  return true;
478  }
479 
480  if (row >= m_rowTable.count())
481  return false;
482 
483  return true;
484 }
485 
486 QModelIndex KateCompletionModel::indexForRow( Group * g, int row ) const
487 {
488  if (row < 0 || row >= g->filtered.count())
489  return QModelIndex();
490 
491  return createIndex(row, 0, g);
492 }
493 
494 QModelIndex KateCompletionModel::indexForGroup( Group * g ) const
495 {
496  if (!hasGroups())
497  return QModelIndex();
498 
499  int row = m_rowTable.indexOf(g);
500 
501  if (row == -1)
502  return QModelIndex();
503 
504  return createIndex(row, 0, 0);
505 }
506 
507 void KateCompletionModel::clearGroups()
508 {
509  clearExpanding();
510  m_ungrouped->clear();
511  m_argumentHints->clear();
512  m_bestMatches->clear();
513 
514  // Don't bother trying to work out where it is
515  m_rowTable.removeAll(m_ungrouped);
516  m_emptyGroups.removeAll(m_ungrouped);
517 
518  m_rowTable.removeAll(m_argumentHints);
519  m_emptyGroups.removeAll(m_argumentHints);
520 
521  m_rowTable.removeAll(m_bestMatches);
522  m_emptyGroups.removeAll(m_bestMatches);
523 
524  qDeleteAll(m_rowTable);
525  qDeleteAll(m_emptyGroups);
526  m_rowTable.clear();
527  m_emptyGroups.clear();
528  m_groupHash.clear();
529  m_customGroupHash.clear();
530 
531  m_emptyGroups.append(m_ungrouped);
532  m_groupHash.insert(0, m_ungrouped);
533 
534  m_emptyGroups.append(m_argumentHints);
535  m_groupHash.insert(-1, m_argumentHints);
536 
537  m_emptyGroups.append(m_bestMatches);
538  m_groupHash.insert(BestMatchesProperty, m_bestMatches);
539 }
540 
541 QSet<KateCompletionModel::Group*> KateCompletionModel::createItems(const HierarchicalModelHandler& _handler, const QModelIndex& i, bool notifyModel) {
542  HierarchicalModelHandler handler(_handler);
543  QSet<Group*> ret;
544 
545  if( handler.model()->rowCount(i) == 0 ) {
546  //Leaf node, create an item
547  ret.insert( createItem(handler, i, notifyModel) );
548  } else {
549  //Non-leaf node, take the role from the node, and recurse to the sub-nodes
550  handler.takeRole(i);
551  for(int a = 0; a < handler.model()->rowCount(i); a++)
552  ret += createItems(handler, i.child(a, 0), notifyModel);
553  }
554 
555  return ret;
556 }
557 
558 QSet<KateCompletionModel::Group*> KateCompletionModel::deleteItems(const QModelIndex& i) {
559  QSet<Group*> ret;
560 
561  if( i.model()->rowCount(i) == 0 ) {
562  //Leaf node, delete the item
563  Group* g = groupForIndex(mapFromSource(i));
564  ret.insert(g);
565  g->removeItem(ModelRow(const_cast<CodeCompletionModel*>(static_cast<const CodeCompletionModel*>(i.model())), i));
566  } else {
567  //Non-leaf node
568  for(int a = 0; a < i.model()->rowCount(i); a++)
569  ret += deleteItems(i.child(a, 0));
570  }
571 
572  return ret;
573 }
574 
575 void KateCompletionModel::createGroups()
576 {
577  beginResetModel();
578  //After clearing the model, it has to be reset, else we will be in an invalid state while inserting
579  //new groups.
580  clearGroups();
581 
582  bool has_groups=false;
583  foreach (CodeCompletionModel* sourceModel, m_completionModels) {
584  has_groups|=sourceModel->hasGroups();
585  for (int i = 0; i < sourceModel->rowCount(); ++i)
586  createItems(HierarchicalModelHandler(sourceModel), sourceModel->index(i, 0));
587  }
588  m_hasGroups=has_groups;
589 
590  //debugStats();
591 
592  foreach (Group* g, m_rowTable)
593  hideOrShowGroup(g);
594 
595  foreach (Group* g, m_emptyGroups)
596  hideOrShowGroup(g);
597 
598  makeGroupItemsUnique();
599 
600  updateBestMatches();
601  endResetModel();
602 }
603 
604 KateCompletionModel::Group* KateCompletionModel::createItem(const HierarchicalModelHandler& handler, const QModelIndex& sourceIndex, bool notifyModel)
605 {
606  //QModelIndex sourceIndex = sourceModel->index(row, CodeCompletionModel::Name, QModelIndex());
607 
608  int completionFlags = handler.getData(CodeCompletionModel::CompletionRole, sourceIndex).toInt();
609 
610  //Scope is expensive, should not be used with big models
611  QString scopeIfNeeded = (groupingMethod() & Scope) ? sourceIndex.sibling(sourceIndex.row(), CodeCompletionModel::Scope).data(Qt::DisplayRole).toString() : QString();
612 
613  int argumentHintDepth = handler.getData(CodeCompletionModel::ArgumentHintDepth, sourceIndex).toInt();
614 
615  Group* g;
616  if( argumentHintDepth ) {
617  g = m_argumentHints;
618  } else{
619  QString customGroup = handler.customGroup();
620  if(!customGroup.isNull() && m_hasGroups) {
621  if(m_customGroupHash.contains(customGroup)) {
622  g = m_customGroupHash[customGroup];
623  }else{
624  g = new Group(this);
625  g->title = customGroup;
626  g->customSortingKey = handler.customGroupingKey();
627  m_emptyGroups.append(g);
628  m_customGroupHash.insert(customGroup, g);
629  }
630  }else{
631  g = fetchGroup(completionFlags, scopeIfNeeded, handler.hasHierarchicalRoles());
632  }
633  }
634 
635  Item item = Item(g != m_argumentHints, this, handler, ModelRow(handler.model(), sourceIndex));
636 
637  if(g != m_argumentHints)
638  item.match();
639 
640  g->addItem(item, notifyModel);
641 
642  return g;
643 }
644 
645 void KateCompletionModel::slotRowsInserted( const QModelIndex & parent, int start, int end )
646 {
647  QSet<Group*> affectedGroups;
648 
649  HierarchicalModelHandler handler(static_cast<CodeCompletionModel*>(sender()));
650  if(parent.isValid())
651  handler.collectRoles(parent);
652 
653 
654  for (int i = start; i <= end; ++i)
655  affectedGroups += createItems(handler, parent.isValid() ? parent.child(i, 0) : handler.model()->index(i, 0), true);
656 
657  foreach (Group* g, affectedGroups)
658  hideOrShowGroup(g, true);
659 }
660 
661 void KateCompletionModel::slotRowsRemoved( const QModelIndex & parent, int start, int end )
662 {
663  CodeCompletionModel* source = static_cast<CodeCompletionModel*>(sender());
664 
665  QSet<Group*> affectedGroups;
666 
667  for (int i = start; i <= end; ++i) {
668  QModelIndex index = parent.isValid() ? parent.child(i, 0) : source->index(i, 0);
669 
670  affectedGroups += deleteItems(index);
671  }
672 
673  foreach (Group* g, affectedGroups)
674  hideOrShowGroup(g, true);
675 }
676 
677 KateCompletionModel::Group* KateCompletionModel::fetchGroup( int attribute, const QString& scope, bool forceGrouping )
678 {
679  Q_UNUSED(forceGrouping);
680 
682  if (!hasGroups())
683  return m_ungrouped;
684 
685  int groupingAttribute = groupingAttributes(attribute);
686  //kDebug( 13035 ) << attribute << " " << groupingAttribute;
687 
688  if (m_groupHash.contains(groupingAttribute)) {
689  if (groupingMethod() & Scope) {
690  for (QHash<int, Group*>::ConstIterator it = m_groupHash.constFind(groupingAttribute); it != m_groupHash.constEnd() && it.key() == groupingAttribute; ++it)
691  if (it.value()->scope == scope)
692  return it.value();
693  } else {
694  return m_groupHash.value(groupingAttribute);
695  }
696  }
697  Group* ret = new Group(this);
698 
699  ret->attribute = attribute;
700  ret->scope = scope;
701 
702  QString st, at, it;
703 
704  if (groupingMethod() & ScopeType) {
705  if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
706  st = "Global";
707  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
708  st = "Namespace";
709  else if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
710  st = "Local";
711 
712  ret->title = st;
713  }
714 
715  if (groupingMethod() & Scope) {
716  if (!ret->title.isEmpty())
717  ret->title.append(" ");
718 
719  ret->title.append(scope);
720  }
721 
722  if (groupingMethod() & AccessType) {
723  if (attribute & KTextEditor::CodeCompletionModel::Public)
724  at = "Public";
725  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
726  at = "Protected";
727  else if (attribute & KTextEditor::CodeCompletionModel::Private)
728  at = "Private";
729 
730  if (accessIncludeStatic() && attribute & KTextEditor::CodeCompletionModel::Static)
731  at.append(" Static");
732 
733  if (accessIncludeConst() && attribute & KTextEditor::CodeCompletionModel::Const)
734  at.append(" Const");
735 
736  if( !at.isEmpty() ) {
737  if (!ret->title.isEmpty())
738  ret->title.append(", ");
739 
740  ret->title.append(at);
741  }
742  }
743 
744  if (groupingMethod() & ItemType) {
745  if (attribute & CodeCompletionModel::Namespace)
746  it = i18n("Namespaces");
747  else if (attribute & CodeCompletionModel::Class)
748  it = i18n("Classes");
749  else if (attribute & CodeCompletionModel::Struct)
750  it = i18n("Structs");
751  else if (attribute & CodeCompletionModel::Union)
752  it = i18n("Unions");
753  else if (attribute & CodeCompletionModel::Function)
754  it = i18n("Functions");
755  else if (attribute & CodeCompletionModel::Variable)
756  it = i18n("Variables");
757  else if (attribute & CodeCompletionModel::Enum)
758  it = i18n("Enumerations");
759 
760  if( !it.isEmpty() ) {
761  if (!ret->title.isEmpty())
762  ret->title.append(" ");
763 
764  ret->title.append(it);
765  }
766  }
767 
768  m_emptyGroups.append(ret);
769  m_groupHash.insert(groupingAttribute, ret);
770 
771  return ret;
772 }
773 
774 bool KateCompletionModel::hasGroups( ) const
775 {
776  //kDebug( 13035 ) << "m_groupHash.size()"<<m_groupHash.size();
777  //kDebug( 13035 ) << "m_rowTable.count()"<<m_rowTable.count();
778  // We cannot decide whether there is groups easily. The problem: The code-model can
779  // be populated with a delay from within a background-thread.
780  // Proper solution: Ask all attached code-models(Through a new interface) whether they want to use grouping,
781  // and if at least one wants to, return true, else return false.
782  return m_groupingEnabled && m_hasGroups;
783 }
784 
785 KateCompletionModel::Group* KateCompletionModel::groupForIndex( const QModelIndex & index ) const
786 {
787  if (!index.isValid()) {
788  if (!hasGroups())
789  return m_ungrouped;
790  else
791  return 0L;
792  }
793 
794  if (groupOfParent(index))
795  return 0L;
796 
797  if (index.row() < 0 || index.row() >= m_rowTable.count())
798  return m_ungrouped;
799 
800  return m_rowTable[index.row()];
801 }
802 
803 /*QMap< int, QVariant > KateCompletionModel::itemData( const QModelIndex & index ) const
804 {
805  if (!hasGroups() || groupOfParent(index)) {
806  QModelIndex index = mapToSource(index);
807  if (index.isValid())
808  return index.model()->itemData(index);
809  }
810 
811  return QAbstractItemModel::itemData(index);
812 }*/
813 
814 QModelIndex KateCompletionModel::parent( const QModelIndex & index ) const
815 {
816  if (!index.isValid())
817  return QModelIndex();
818 
819  if (Group* g = groupOfParent(index)) {
820  if (!hasGroups()) {
821  Q_ASSERT(g == m_ungrouped);
822  return QModelIndex();
823  }
824 
825  int row = m_rowTable.indexOf(g);
826 
827  if (row == -1) {
828  kWarning() << "Couldn't find parent for index" << index;
829  return QModelIndex();
830  }
831 
832  return createIndex(row, 0, 0);
833  }
834 
835  return QModelIndex();
836 }
837 
838 int KateCompletionModel::rowCount( const QModelIndex & parent ) const
839 {
840  if (!parent.isValid()) {
841  if (hasGroups()) {
842  //kDebug( 13035 ) << "Returning row count for toplevel " << m_rowTable.count();
843  return m_rowTable.count();
844  } else {
845  //kDebug( 13035 ) << "Returning ungrouped row count for toplevel " << m_ungrouped->filtered.count();
846  return m_ungrouped->filtered.count();
847  }
848  }
849 
850  Group* g = groupForIndex(parent);
851 
852  // This is not an error, seems you don't have to check hasChildren()
853  if (!g)
854  return 0;
855 
856  //kDebug( 13035 ) << "Returning row count for group " << g << " as " << g->filtered.count();
857  return g->filtered.count();
858 }
859 
860 void KateCompletionModel::sort( int column, Qt::SortOrder order )
861 {
862  Q_UNUSED(column)
863  Q_UNUSED(order)
864 }
865 
866 QModelIndex KateCompletionModel::mapToSource( const QModelIndex & proxyIndex ) const
867 {
868  if (!proxyIndex.isValid())
869  return QModelIndex();
870 
871  if (Group* g = groupOfParent(proxyIndex)) {
872  if( proxyIndex.row() >= 0 && proxyIndex.row() < g->filtered.count() ) {
873  ModelRow source = g->filtered[proxyIndex.row()].sourceRow();
874  return source.second.sibling(source.second.row(), proxyIndex.column());
875  }else{
876  kDebug( 13035 ) << "Invalid proxy-index";
877  }
878  }
879 
880  return QModelIndex();
881 }
882 
883 QModelIndex KateCompletionModel::mapFromSource( const QModelIndex & sourceIndex ) const
884 {
885  if (!sourceIndex.isValid())
886  return QModelIndex();
887 
888  if (!hasGroups())
889  return index(m_ungrouped->rowOf(modelRowPair(sourceIndex)), sourceIndex.column(), QModelIndex());
890 
891  foreach (Group* g, m_rowTable) {
892  int row = g->rowOf(modelRowPair(sourceIndex));
893  if (row != -1)
894  return index(row, sourceIndex.column(), indexForGroup(g));
895  }
896 
897  // Copied from above
898  foreach (Group* g, m_emptyGroups) {
899  int row = g->rowOf(modelRowPair(sourceIndex));
900  if (row != -1)
901  return index(row, sourceIndex.column(), indexForGroup(g));
902  }
903 
904  return QModelIndex();
905 }
906 
907 void KateCompletionModel::setCurrentCompletion( KTextEditor::CodeCompletionModel* model, const QString & completion )
908 {
909  if (m_currentMatch[model] == completion)
910  return;
911 
912  if (!hasCompletionModel()) {
913  m_currentMatch[model] = completion;
914  return;
915  }
916 
917  changeTypes changeType = Change;
918 
919  if (m_currentMatch[model].length() > completion.length() && m_currentMatch[model].startsWith(completion, m_matchCaseSensitivity)) {
920  // Filter has been broadened
921  changeType = Broaden;
922 
923  } else if (m_currentMatch[model].length() < completion.length() && completion.startsWith(m_currentMatch[model], m_matchCaseSensitivity)) {
924  // Filter has been narrowed
925  changeType = Narrow;
926  }
927 
928  //kDebug( 13035 ) << model << "Old match: " << m_currentMatch[model] << ", new: " << completion << ", type: " << changeType;
929 
930  m_currentMatch[model] = completion;
931 
932  const bool resetModel = (changeType != Narrow);
933  if (resetModel) {
934  beginResetModel();
935  }
936 
937  if (!hasGroups()) {
938  changeCompletions(m_ungrouped, changeType, !resetModel);
939  } else {
940  foreach (Group* g, m_rowTable) {
941  if(g != m_argumentHints)
942  changeCompletions(g, changeType, !resetModel);
943  }
944  foreach (Group* g, m_emptyGroups) {
945  if(g != m_argumentHints)
946  changeCompletions(g, changeType, !resetModel);
947  }
948  }
949 
950  // NOTE: best matches are also updated in resort
951  resort();
952 
953  if (resetModel) {
954  endResetModel();
955  }
956 
957  clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering.
958 
959  emit layoutChanged();
960 }
961 
962 QString KateCompletionModel::commonPrefixInternal(const QString &forcePrefix) const
963 {
964  QString commonPrefix; // isNull() = true
965 
966  QList< Group* > groups = m_rowTable;
967  groups += m_ungrouped;
968 
969  foreach (Group* g, groups) {
970  foreach(const Item& item, g->filtered)
971  {
972  uint startPos = m_currentMatch[item.sourceRow().first].length();
973  const QString candidate = item.name().mid(startPos);
974 
975  if(!candidate.startsWith(forcePrefix))
976  continue;
977 
978  if(commonPrefix.isNull()) {
979  commonPrefix = candidate;
980 
981  //Replace QString::null prefix with QString(""), so we won't initialize it again
982  if(commonPrefix.isNull())
983  commonPrefix = QString(""); // isEmpty() = true, isNull() = false
984  }else{
985  commonPrefix = commonPrefix.left(candidate.length());
986 
987  for(int a = 0; a < commonPrefix.length(); ++a) {
988  if(commonPrefix[a] != candidate[a]) {
989  commonPrefix = commonPrefix.left(a);
990  break;
991  }
992  }
993  }
994  }
995  }
996 
997  return commonPrefix;
998 }
999 
1000 QString KateCompletionModel::commonPrefix(QModelIndex selectedIndex) const
1001 {
1002  QString commonPrefix = commonPrefixInternal(QString());
1003 
1004  if(commonPrefix.isEmpty() && selectedIndex.isValid()) {
1005  Group* g = m_ungrouped;
1006  if(hasGroups())
1007  g = groupOfParent(selectedIndex);
1008 
1009  if(g && selectedIndex.row() < g->filtered.size())
1010  {
1011  //Follow the path of the selected item, finding the next non-empty common prefix
1012  Item item = g->filtered[selectedIndex.row()];
1013  int matchLength = m_currentMatch[item.sourceRow().first].length();
1014  commonPrefix = commonPrefixInternal(item.name().mid(matchLength).left(1));
1015  }
1016  }
1017 
1018  return commonPrefix;
1019 }
1020 
1021 void KateCompletionModel::changeCompletions( Group * g, changeTypes changeType, bool notifyModel )
1022 {
1023  if(changeType != Narrow) {
1024  g->filtered = g->prefilter;
1025  //In the "Broaden" or "Change" case, just re-filter everything,
1026  //and don't notify the model. The model is notified afterwards through a reset().
1027  }
1028 
1029  //This code determines what of the filtered items still fit, and computes the ranges that were removed, giving
1030  //them to beginRemoveRows(..) in batches
1031 
1032  QList <KateCompletionModel::Item > newFiltered;
1033  int deleteUntil = -1; //In each state, the range [currentRow+1, deleteUntil] needs to be deleted
1034  for(int currentRow = g->filtered.count()-1; currentRow >= 0; --currentRow) {
1035  if(g->filtered[currentRow].match()) {
1036  //This row does not need to be deleted, which means that currentRow+1 to deleteUntil need to be deleted now
1037  if(deleteUntil != -1 && notifyModel) {
1038  beginRemoveRows(indexForGroup(g), currentRow+1, deleteUntil);
1039  endRemoveRows();
1040  }
1041  deleteUntil = -1;
1042 
1043  newFiltered.prepend(g->filtered[currentRow]);
1044  }else{
1045  if(deleteUntil == -1)
1046  deleteUntil = currentRow; //Mark that this row needs to be deleted
1047  }
1048  }
1049 
1050  if(deleteUntil != -1 && notifyModel) {
1051  beginRemoveRows(indexForGroup(g), 0, deleteUntil);
1052  endRemoveRows();
1053  }
1054 
1055  g->filtered = newFiltered;
1056  hideOrShowGroup(g, notifyModel);
1057 }
1058 
1059 int KateCompletionModel::Group::orderNumber() const {
1060  if( this == model->m_ungrouped )
1061  return 700;
1062 
1063  if(customSortingKey != -1)
1064  return customSortingKey;
1065 
1066  if( attribute & BestMatchesProperty )
1067  return 1;
1068 
1069  if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
1070  return 100;
1071  else if (attribute & KTextEditor::CodeCompletionModel::Public)
1072  return 200;
1073  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
1074  return 300;
1075  else if (attribute & KTextEditor::CodeCompletionModel::Private)
1076  return 400;
1077  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
1078  return 500;
1079  else if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
1080  return 600;
1081 
1082 
1083  return 700;
1084 }
1085 
1086 bool KateCompletionModel::Group::orderBefore(Group* other) const {
1087  return orderNumber() < other->orderNumber();
1088 }
1089 
1090 void KateCompletionModel::hideOrShowGroup(Group* g, bool notifyModel)
1091 {
1092  if( g == m_argumentHints ) {
1093  emit argumentHintsChanged();
1094  m_updateBestMatchesTimer->start(200); //We have new argument-hints, so we have new best matches
1095  return; //Never show argument-hints in the normal completion-list
1096  }
1097 
1098  if (!g->isEmpty) {
1099  if (g->filtered.isEmpty()) {
1100  // Move to empty group list
1101  g->isEmpty = true;
1102  int row = m_rowTable.indexOf(g);
1103  if (row != -1) {
1104  if (hasGroups() && notifyModel)
1105  beginRemoveRows(QModelIndex(), row, row);
1106  m_rowTable.removeAt(row);
1107  if (hasGroups() && notifyModel)
1108  endRemoveRows();
1109  m_emptyGroups.append(g);
1110  } else {
1111  kWarning() << "Group " << g << " not found in row table!!";
1112  }
1113  }
1114 
1115  } else {
1116 
1117  if (!g->filtered.isEmpty()) {
1118  // Move off empty group list
1119  g->isEmpty = false;
1120 
1121  int row = 0; //Find row where to insert
1122  for( int a = 0; a < m_rowTable.count(); a++ ) {
1123  if( g->orderBefore(m_rowTable[a]) ) {
1124  row = a;
1125  break;
1126  }
1127  row = a+1;
1128  }
1129 
1130  if(notifyModel) {
1131  if (hasGroups())
1132  beginInsertRows(QModelIndex(), row, row);
1133  else
1134  beginInsertRows(QModelIndex(), 0, g->filtered.count());
1135  }
1136  m_rowTable.insert(row, g);
1137  if(notifyModel)
1138  endInsertRows();
1139  m_emptyGroups.removeAll(g);
1140  }
1141  }
1142 }
1143 
1144 bool KateCompletionModel::indexIsItem( const QModelIndex & index ) const
1145 {
1146  if (!hasGroups())
1147  return true;
1148 
1149  if (groupOfParent(index))
1150  return true;
1151 
1152  return false;
1153 }
1154 
1155 void KateCompletionModel::slotModelReset()
1156 {
1157  createGroups();
1158 
1159  //debugStats();
1160 }
1161 
1162 void KateCompletionModel::debugStats()
1163 {
1164  if (!hasGroups())
1165  kDebug( 13035 ) << "Model groupless, " << m_ungrouped->filtered.count() << " items.";
1166  else {
1167  kDebug( 13035 ) << "Model grouped (" << m_rowTable.count() << " groups):";
1168  foreach (Group* g, m_rowTable)
1169  kDebug( 13035 ) << "Group" << g << "count" << g->filtered.count();
1170  }
1171 }
1172 
1173 bool KateCompletionModel::hasCompletionModel( ) const
1174 {
1175  return !m_completionModels.isEmpty();
1176 }
1177 
1178 void KateCompletionModel::setFilteringEnabled( bool enable )
1179 {
1180  if (m_filteringEnabled != enable)
1181  m_filteringEnabled = enable;
1182 }
1183 
1184 void KateCompletionModel::setSortingEnabled( bool enable )
1185 {
1186  if (m_sortingEnabled != enable) {
1187  m_sortingEnabled = enable;
1188  beginResetModel();
1189  resort();
1190  endResetModel();
1191  }
1192 }
1193 
1194 void KateCompletionModel::setGroupingEnabled(bool enable)
1195 {
1196  if (m_groupingEnabled != enable)
1197  m_groupingEnabled = enable;
1198 }
1199 
1200 void KateCompletionModel::setColumnMergingEnabled(bool enable)
1201 {
1202  if (m_columnMergingEnabled != enable)
1203  m_columnMergingEnabled = enable;
1204 }
1205 
1206 bool KateCompletionModel::isColumnMergingEnabled( ) const
1207 {
1208  return m_columnMergingEnabled;
1209 }
1210 
1211 bool KateCompletionModel::isGroupingEnabled( ) const
1212 {
1213  return m_groupingEnabled;
1214 }
1215 
1216 bool KateCompletionModel::isFilteringEnabled( ) const
1217 {
1218  return m_filteringEnabled;
1219 }
1220 
1221 bool KateCompletionModel::isSortingEnabled( ) const
1222 {
1223  return m_sortingEnabled;
1224 }
1225 
1226 QString KateCompletionModel::columnName( int column )
1227 {
1228  switch (column) {
1229  case KTextEditor::CodeCompletionModel::Prefix:
1230  return i18n("Prefix");
1231  case KTextEditor::CodeCompletionModel::Icon:
1232  return i18n("Icon");
1233  case KTextEditor::CodeCompletionModel::Scope:
1234  return i18n("Scope");
1235  case KTextEditor::CodeCompletionModel::Name:
1236  return i18n("Name");
1237  case KTextEditor::CodeCompletionModel::Arguments:
1238  return i18n("Arguments");
1239  case KTextEditor::CodeCompletionModel::Postfix:
1240  return i18n("Postfix");
1241  }
1242 
1243  return QString();
1244 }
1245 
1246 const QList< QList < int > > & KateCompletionModel::columnMerges( ) const
1247 {
1248  return m_columnMerges;
1249 }
1250 
1251 void KateCompletionModel::setColumnMerges( const QList< QList < int > > & columnMerges )
1252 {
1253  beginResetModel();
1254  m_columnMerges = columnMerges;
1255  endResetModel();
1256 }
1257 
1258 int KateCompletionModel::translateColumn( int sourceColumn ) const
1259 {
1260  if (m_columnMerges.isEmpty())
1261  return sourceColumn;
1262 
1263  /* Debugging - dump column merge list
1264 
1265  QString columnMerge;
1266  foreach (const QList<int>& list, m_columnMerges) {
1267  columnMerge += '[';
1268  foreach (int column, list) {
1269  columnMerge += QString::number(column) + " ";
1270  }
1271  columnMerge += "] ";
1272  }
1273 
1274  kDebug( 13035 ) << k_funcinfo << columnMerge;*/
1275 
1276  int c = 0;
1277  foreach (const QList<int>& list, m_columnMerges) {
1278  foreach (int column, list) {
1279  if (column == sourceColumn)
1280  return c;
1281  }
1282  c++;
1283  }
1284  return -1;
1285 }
1286 
1287 int KateCompletionModel::groupingAttributes( int attribute ) const
1288 {
1289  int ret = 0;
1290 
1291  if (m_groupingMethod & ScopeType) {
1292  if (countBits(attribute & ScopeTypeMask) > 1)
1293  kWarning() << "Invalid completion model metadata: more than one scope type modifier provided.";
1294 
1295  if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
1296  ret |= KTextEditor::CodeCompletionModel::GlobalScope;
1297  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
1298  ret |= KTextEditor::CodeCompletionModel::NamespaceScope;
1299  else if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
1300  ret |= KTextEditor::CodeCompletionModel::LocalScope;
1301  }
1302 
1303  if (m_groupingMethod & AccessType) {
1304  if (countBits(attribute & AccessTypeMask) > 1)
1305  kWarning() << "Invalid completion model metadata: more than one access type modifier provided.";
1306 
1307  if (attribute & KTextEditor::CodeCompletionModel::Public)
1308  ret |= KTextEditor::CodeCompletionModel::Public;
1309  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
1310  ret |= KTextEditor::CodeCompletionModel::Protected;
1311  else if (attribute & KTextEditor::CodeCompletionModel::Private)
1312  ret |= KTextEditor::CodeCompletionModel::Private;
1313 
1314  if (accessIncludeStatic() && attribute & KTextEditor::CodeCompletionModel::Static)
1315  ret |= KTextEditor::CodeCompletionModel::Static;
1316 
1317  if (accessIncludeConst() && attribute & KTextEditor::CodeCompletionModel::Const)
1318  ret |= KTextEditor::CodeCompletionModel::Const;
1319  }
1320 
1321  if (m_groupingMethod & ItemType) {
1322  if (countBits(attribute & ItemTypeMask) > 1)
1323  kWarning() << "Invalid completion model metadata: more than one item type modifier provided.";
1324 
1325  if (attribute & KTextEditor::CodeCompletionModel::Namespace)
1326  ret |= KTextEditor::CodeCompletionModel::Namespace;
1327  else if (attribute & KTextEditor::CodeCompletionModel::Class)
1328  ret |= KTextEditor::CodeCompletionModel::Class;
1329  else if (attribute & KTextEditor::CodeCompletionModel::Struct)
1330  ret |= KTextEditor::CodeCompletionModel::Struct;
1331  else if (attribute & KTextEditor::CodeCompletionModel::Union)
1332  ret |= KTextEditor::CodeCompletionModel::Union;
1333  else if (attribute & KTextEditor::CodeCompletionModel::Function)
1334  ret |= KTextEditor::CodeCompletionModel::Function;
1335  else if (attribute & KTextEditor::CodeCompletionModel::Variable)
1336  ret |= KTextEditor::CodeCompletionModel::Variable;
1337  else if (attribute & KTextEditor::CodeCompletionModel::Enum)
1338  ret |= KTextEditor::CodeCompletionModel::Enum;
1339 
1340  /*
1341  if (itemIncludeTemplate() && attribute & KTextEditor::CodeCompletionModel::Template)
1342  ret |= KTextEditor::CodeCompletionModel::Template;*/
1343  }
1344 
1345  return ret;
1346 }
1347 
1348 void KateCompletionModel::setGroupingMethod( GroupingMethods m )
1349 {
1350  m_groupingMethod = m;
1351 
1352  createGroups();
1353 }
1354 
1355 bool KateCompletionModel::accessIncludeConst( ) const
1356 {
1357  return m_accessConst;
1358 }
1359 
1360 void KateCompletionModel::setAccessIncludeConst( bool include )
1361 {
1362  if (m_accessConst != include) {
1363  m_accessConst = include;
1364 
1365  if (groupingMethod() & AccessType)
1366  createGroups();
1367  }
1368 }
1369 
1370 bool KateCompletionModel::accessIncludeStatic( ) const
1371 {
1372  return m_accessStatic;
1373 }
1374 
1375 void KateCompletionModel::setAccessIncludeStatic( bool include )
1376 {
1377  if (m_accessStatic != include) {
1378  m_accessStatic = include;
1379 
1380  if (groupingMethod() & AccessType)
1381  createGroups();
1382  }
1383 }
1384 
1385 bool KateCompletionModel::accessIncludeSignalSlot( ) const
1386 {
1387  return m_accesSignalSlot;
1388 }
1389 
1390 void KateCompletionModel::setAccessIncludeSignalSlot( bool include )
1391 {
1392  if (m_accesSignalSlot != include) {
1393  m_accesSignalSlot = include;
1394 
1395  if (groupingMethod() & AccessType)
1396  createGroups();
1397  }
1398 }
1399 
1400 int KateCompletionModel::countBits( int value ) const
1401 {
1402  int count = 0;
1403  for (int i = 1; i; i <<= 1)
1404  if (i & value)
1405  count++;
1406 
1407  return count;
1408 }
1409 
1410 KateCompletionModel::GroupingMethods KateCompletionModel::groupingMethod( ) const
1411 {
1412  return m_groupingMethod;
1413 }
1414 
1415 bool KateCompletionModel::isSortingByInheritanceDepth() const {
1416  return m_isSortingByInheritance;
1417 }
1418 void KateCompletionModel::setSortingByInheritanceDepth(bool byInheritance) {
1419  m_isSortingByInheritance = byInheritance;
1420 }
1421 
1422 bool KateCompletionModel::isSortingAlphabetical( ) const
1423 {
1424  return m_sortingAlphabetical;
1425 }
1426 
1427 Qt::CaseSensitivity KateCompletionModel::sortingCaseSensitivity( ) const
1428 {
1429  return m_sortingCaseSensitivity;
1430 }
1431 
1432 KateCompletionModel::Item::Item( bool doInitialMatch, KateCompletionModel* m, const HierarchicalModelHandler& handler, ModelRow sr )
1433  : model(m)
1434  , m_sourceRow(sr)
1435  , matchCompletion(StartsWithMatch)
1436  , matchFilters(true)
1437  , m_haveExactMatch(false)
1438 {
1439 
1440  inheritanceDepth = handler.getData(CodeCompletionModel::InheritanceDepth, m_sourceRow.second).toInt();
1441 
1442  QModelIndex nameSibling = sr.second.sibling(sr.second.row(), CodeCompletionModel::Name);
1443  m_nameColumn = nameSibling.data(Qt::DisplayRole).toString();
1444 
1445  if(doInitialMatch) {
1446  filter();
1447  match();
1448  }
1449 }
1450 
1451 bool KateCompletionModel::Item::operator <( const Item & rhs ) const
1452 {
1453  int ret = 0;
1454 
1455  //kDebug( 13035 ) << c1 << " c/w " << c2 << " -> " << (model->isSortingReverse() ? ret > 0 : ret < 0) << " (" << ret << ")";
1456 
1457  const bool isBad = m_sourceRow.second.data(CodeCompletionModel::UnimportantItemRole).toBool();
1458  const bool otherIsBad = rhs.m_sourceRow.second.data(CodeCompletionModel::UnimportantItemRole).toBool();
1459  if( isBad && !otherIsBad ) {
1460  return false;
1461  }
1462  if( otherIsBad && !isBad ) {
1463  return true;
1464  }
1465 
1466  if( matchCompletion < rhs.matchCompletion ) {
1467  // enums are ordered in the order items should be displayed
1468  return true;
1469  }
1470  if( matchCompletion > rhs.matchCompletion ) {
1471  return false;
1472  }
1473 
1474  if( model->isSortingByInheritanceDepth() )
1475  ret = inheritanceDepth - rhs.inheritanceDepth;
1476 
1477  if (ret == 0 && model->isSortingAlphabetical()) {
1478  // Do not use localeAwareCompare, because it is simply too slow for a list of about 1000 items
1479  ret = QString::compare(m_nameColumn, rhs.m_nameColumn, model->sortingCaseSensitivity());
1480  }
1481 
1482  if( ret == 0 ) {
1483  const QString& filter = rhs.model->currentCompletion(rhs.m_sourceRow.first);
1484  if( m_nameColumn.startsWith(filter, Qt::CaseSensitive) ) {
1485  return true;
1486  }
1487  if( rhs.m_nameColumn.startsWith(filter, Qt::CaseSensitive) ) {
1488  return false;
1489  }
1490  // FIXME need to define a better default ordering for multiple model display
1491  ret = m_sourceRow.second.row() - rhs.m_sourceRow.second.row();
1492  }
1493 
1494  return ret < 0;
1495 }
1496 
1497 void KateCompletionModel::Group::addItem( Item i, bool notifyModel )
1498 {
1499  if (isEmpty)
1500  notifyModel = false;
1501 
1502  QModelIndex groupIndex;
1503  if (notifyModel)
1504  groupIndex = model->indexForGroup(this);
1505 
1506  if (model->isSortingEnabled()) {
1507 
1508  prefilter.insert(qUpperBound(prefilter.begin(), prefilter.end(), i), i);
1509  if(i.isVisible()) {
1510  QList<Item>::iterator it = qUpperBound(filtered.begin(), filtered.end(), i);
1511  uint rowNumber = it - filtered.begin();
1512 
1513  if(notifyModel)
1514  model->beginInsertRows(groupIndex, rowNumber, rowNumber);
1515 
1516  filtered.insert(it, i);
1517  }
1518  } else {
1519  if(notifyModel)
1520  model->beginInsertRows(groupIndex, prefilter.size(), prefilter.size());
1521  if (i.isVisible())
1522  prefilter.append(i);
1523  }
1524 
1525  if(notifyModel)
1526  model->endInsertRows();
1527 }
1528 
1529 bool KateCompletionModel::Group::removeItem(const ModelRow& row)
1530 {
1531  for (int pi = 0; pi < prefilter.count(); ++pi)
1532  if (prefilter[pi].sourceRow() == row) {
1533  int index = rowOf(row);
1534  if (index != -1)
1535  model->beginRemoveRows(model->indexForGroup(this), index, index);
1536 
1537  filtered.removeAt(index);
1538  prefilter.removeAt(pi);
1539 
1540  if (index != -1)
1541  model->endRemoveRows();
1542 
1543  return index != -1;
1544  }
1545 
1546  Q_ASSERT(false);
1547  return false;
1548 }
1549 
1550 KateCompletionModel::Group::Group( KateCompletionModel * m )
1551  : model(m)
1552  , isEmpty(true)
1553  , customSortingKey(-1)
1554 {
1555  Q_ASSERT(model);
1556 }
1557 
1558 void KateCompletionModel::setSortingAlphabetical( bool alphabetical )
1559 {
1560  if (m_sortingAlphabetical != alphabetical) {
1561  m_sortingAlphabetical = alphabetical;
1562  beginResetModel();
1563  resort();
1564  endResetModel();
1565  }
1566 }
1567 
1568 void KateCompletionModel::Group::resort( )
1569 {
1570  qStableSort(filtered.begin(), filtered.end());
1571  model->hideOrShowGroup(this);
1572 }
1573 
1574 void KateCompletionModel::setSortingCaseSensitivity( Qt::CaseSensitivity cs )
1575 {
1576  if (m_sortingCaseSensitivity != cs) {
1577  m_sortingCaseSensitivity = cs;
1578  beginResetModel();
1579  resort();
1580  endResetModel();
1581  }
1582 }
1583 
1584 void KateCompletionModel::resort()
1585 {
1586  foreach (Group* g, m_rowTable)
1587  g->resort();
1588 
1589  foreach (Group* g, m_emptyGroups)
1590  g->resort();
1591 
1592  // call updateBestMatches here, so they are moved to the top again.
1593  updateBestMatches();
1594 }
1595 
1596 bool KateCompletionModel::Item::isValid( ) const
1597 {
1598  return model && m_sourceRow.first && m_sourceRow.second.row() >= 0;
1599 }
1600 
1601 void KateCompletionModel::Group::clear( )
1602 {
1603  prefilter.clear();
1604  filtered.clear();
1605  isEmpty = true;
1606 }
1607 
1608 bool KateCompletionModel::filterContextMatchesOnly( ) const
1609 {
1610  return m_filterContextMatchesOnly;
1611 }
1612 
1613 void KateCompletionModel::setFilterContextMatchesOnly( bool filter )
1614 {
1615  if (m_filterContextMatchesOnly != filter) {
1616  m_filterContextMatchesOnly = filter;
1617  refilter();
1618  }
1619 }
1620 
1621 bool KateCompletionModel::filterByAttribute( ) const
1622 {
1623  return m_filterByAttribute;
1624 }
1625 
1626 void KateCompletionModel::setFilterByAttribute( bool filter )
1627 {
1628  if (m_filterByAttribute == filter) {
1629  m_filterByAttribute = filter;
1630  refilter();
1631  }
1632 }
1633 
1634 KTextEditor::CodeCompletionModel::CompletionProperties KateCompletionModel::filterAttributes( ) const
1635 {
1636  return m_filterAttributes;
1637 }
1638 
1639 void KateCompletionModel::setFilterAttributes( KTextEditor::CodeCompletionModel::CompletionProperties attributes )
1640 {
1641  if (m_filterAttributes == attributes) {
1642  m_filterAttributes = attributes;
1643  refilter();
1644  }
1645 }
1646 
1647 int KateCompletionModel::maximumInheritanceDepth( ) const
1648 {
1649  return m_maximumInheritanceDepth;
1650 }
1651 
1652 void KateCompletionModel::setMaximumInheritanceDepth( int maxDepth )
1653 {
1654  if (m_maximumInheritanceDepth != maxDepth) {
1655  m_maximumInheritanceDepth = maxDepth;
1656  refilter();
1657  }
1658 }
1659 
1660 void KateCompletionModel::refilter( )
1661 {
1662  beginResetModel();
1663  m_ungrouped->refilter();
1664 
1665  foreach (Group* g, m_rowTable)
1666  if(g != m_argumentHints)
1667  g->refilter();
1668 
1669  foreach (Group* g, m_emptyGroups)
1670  if(g != m_argumentHints)
1671  g->refilter();
1672 
1673  updateBestMatches();
1674 
1675  clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering.
1676  endResetModel();
1677 }
1678 
1679 void KateCompletionModel::Group::refilter( )
1680 {
1681  filtered.clear();
1682  foreach (const Item& i, prefilter)
1683  if (!i.isFiltered())
1684  filtered.append(i);
1685 }
1686 
1687 bool KateCompletionModel::Item::filter( )
1688 {
1689  matchFilters = false;
1690 
1691  if (model->isFilteringEnabled()) {
1692  QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name);
1693 
1694  if (model->filterContextMatchesOnly()) {
1695  QVariant contextMatch = sourceIndex.data(CodeCompletionModel::MatchQuality);
1696  if (contextMatch.canConvert(QVariant::Int) && !contextMatch.toInt())
1697  goto filter;
1698  }
1699 
1700  if (model->filterByAttribute()) {
1701  int completionFlags = sourceIndex.data(CodeCompletionModel::CompletionRole).toInt();
1702  if (model->filterAttributes() & completionFlags)
1703  goto filter;
1704  }
1705 
1706  if (model->maximumInheritanceDepth() > 0) {
1707  int inheritanceDepth = sourceIndex.data(CodeCompletionModel::InheritanceDepth).toInt();
1708  if (inheritanceDepth > model->maximumInheritanceDepth())
1709  goto filter;
1710  }
1711  }
1712 
1713  matchFilters = true;
1714 
1715  filter:
1716  return matchFilters;
1717 }
1718 
1719 uint KateCompletionModel::filteredItemCount() const
1720 {
1721  uint ret = 0;
1722  foreach(Group* group, m_rowTable)
1723  ret += group->filtered.size();
1724 
1725  return ret;
1726 }
1727 
1728 bool KateCompletionModel::shouldMatchHideCompletionList() const {
1729 
1730  // @todo Make this faster
1731 
1732  bool doHide = false;
1733  CodeCompletionModel* hideModel = 0;
1734 
1735  foreach(Group* group, m_rowTable)
1736  foreach(const Item& item, group->filtered)
1737  if(item.haveExactMatch()) {
1738  KTextEditor::CodeCompletionModelControllerInterface3* iface3 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface3*>(item.sourceRow().first);
1739  bool hide = false;
1740  if ( !iface3 ) hide = true;
1741  if(iface3 && iface3->matchingItem(item.sourceRow().second) == KTextEditor::CodeCompletionModelControllerInterface3::HideListIfAutomaticInvocation)
1742  hide = true;
1743  if(hide)
1744  {
1745  doHide = true;
1746  hideModel = item.sourceRow().first;
1747  }
1748  }
1749 
1750  if(doHide)
1751  {
1752  // Check if all other visible items are from the same model
1753  foreach(Group* group, m_rowTable)
1754  foreach(const Item& item, group->filtered)
1755  if(item.sourceRow().first != hideModel)
1756  return false;
1757  }
1758 
1759  return doHide;
1760 }
1761 
1762 static inline bool matchesAbbreviationHelper(const QString& word, const QString& typed, const QVarLengthArray<int, 32>& offsets,
1763  int& depth, int atWord = -1, int i = 0) {
1764  int atLetter = 1;
1765  for ( ; i < typed.size(); i++ ) {
1766  const QChar c = typed.at(i).toLower();
1767  bool haveNextWord = offsets.size() > atWord + 1;
1768  bool canCompare = atWord != -1 && word.size() > offsets.at(atWord) + atLetter;
1769  if ( canCompare && c == word.at(offsets.at(atWord) + atLetter).toLower() ) {
1770  // the typed letter matches a letter after the current word beginning
1771  if ( ! haveNextWord || c != word.at(offsets.at(atWord + 1)).toLower() ) {
1772  // good, simple case, no conflict
1773  atLetter += 1;
1774  continue;
1775  }
1776  // For maliciously crafted data, the code used here theoretically can have very high
1777  // complexity. Thus ensure we don't run into this case, by limiting the amount of branches
1778  // we walk through to 128.
1779  depth++;
1780  if ( depth > 128 ) {
1781  return false;
1782  }
1783  // the letter matches both the next word beginning and the next character in the word
1784  if ( haveNextWord && matchesAbbreviationHelper(word, typed, offsets, depth, atWord + 1, i + 1) ) {
1785  // resolving the conflict by taking the next word's first character worked, fine
1786  return true;
1787  }
1788  // otherwise, continue by taking the next letter in the current word.
1789  atLetter += 1;
1790  continue;
1791  }
1792  else if ( haveNextWord && c == word.at(offsets.at(atWord + 1)).toLower() ) {
1793  // the typed letter matches the next word beginning
1794  atWord++;
1795  atLetter = 1;
1796  continue;
1797  }
1798  // no match
1799  return false;
1800  }
1801  // all characters of the typed word were matched
1802  return true;
1803 }
1804 
1805 bool KateCompletionModel::matchesAbbreviation(const QString& word, const QString& typed)
1806 {
1807  // A mismatch is very likely for random even for the first letter,
1808  // thus this optimization makes sense.
1809  if ( word.at(0).toLower() != typed.at(0).toLower() ) {
1810  return false;
1811  }
1812 
1813  // First, check if all letters are contained in the word in the right order.
1814  int atLetter = 0;
1815  foreach ( const QChar c, typed ) {
1816  while ( c.toLower() != word.at(atLetter).toLower() ) {
1817  atLetter += 1;
1818  if ( atLetter >= word.size() ) {
1819  return false;
1820  }
1821  }
1822  }
1823 
1824  bool haveUnderscore = true;
1825  QVarLengthArray<int, 32> offsets;
1826  // We want to make "KComplM" match "KateCompletionModel"; this means we need
1827  // to allow parts of the typed text to be not part of the actual abbreviation,
1828  // which consists only of the uppercased / underscored letters (so "KCM" in this case).
1829  // However it might be ambigous whether a letter is part of such a word or part of
1830  // the following abbreviation, so we need to find all possible word offsets first,
1831  // then compare.
1832  for ( int i = 0; i < word.size(); i++ ) {
1833  const QChar c = word.at(i);
1834  if ( c == QLatin1Char('_') ) {
1835  haveUnderscore = true;
1836  } else if ( haveUnderscore || c.isUpper() ) {
1837  offsets.append(i);
1838  haveUnderscore = false;
1839  }
1840  }
1841  int depth = 0;
1842  return matchesAbbreviationHelper(word, typed, offsets, depth);
1843 }
1844 
1845 static inline bool containsAtWordBeginning(const QString& word, const QString& typed, Qt::CaseSensitivity caseSensitive) {
1846  for(int i = 1; i < word.size(); i++) {
1847  // The current position is a word beginning if the previous character was an underscore
1848  // or if the current character is uppercase. Subsequent uppercase characters do not count,
1849  // to handle the special case of UPPER_CASE_VARS properly.
1850  const QChar c = word.at(i);
1851  const QChar prev = word.at(i-1);
1852  if(!(prev == QLatin1Char('_') || (c.isUpper() && !prev.isUpper()))) {
1853  continue;
1854  }
1855  if(word.midRef(i).startsWith(typed, caseSensitive)) {
1856  return true;
1857  }
1858  }
1859  return false;
1860 };
1861 
1862 KateCompletionModel::Item::MatchType KateCompletionModel::Item::match()
1863 {
1864  // Check to see if the item is matched by the current completion string
1865  QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name);
1866 
1867  QString match = model->currentCompletion(m_sourceRow.first);
1868 
1869  m_haveExactMatch = false;
1870 
1871  // Hehe, everything matches nothing! (ie. everything matches a blank string)
1872  if (match.isEmpty())
1873  return PerfectMatch;
1874  if (m_nameColumn.isEmpty())
1875  return NoMatch;
1876 
1877  matchCompletion = (m_nameColumn.startsWith(match, model->matchCaseSensitivity()) ? StartsWithMatch : NoMatch);
1878  if(matchCompletion == NoMatch) {
1879  // if no match, try for "contains"
1880  // Only match when the occurence is at a "word" beginning, marked by
1881  // an underscore or a capital. So Foo matches BarFoo and Bar_Foo, but not barfoo.
1882  // Starting at 1 saves looking at the beginning of the word, that was already checked above.
1883  if(containsAtWordBeginning(m_nameColumn, match, model->matchCaseSensitivity())) {
1884  matchCompletion = ContainsMatch;
1885  }
1886  }
1887 
1888  if(matchCompletion == NoMatch && !m_nameColumn.isEmpty() && !match.isEmpty())
1889  {
1890  // if still no match, try abbreviation matching
1891  if(matchesAbbreviation(m_nameColumn, match)) {
1892  matchCompletion = AbbreviationMatch;
1893  }
1894  }
1895 
1896  if(matchCompletion && match.length() == m_nameColumn.length()) {
1897  matchCompletion = PerfectMatch;
1898  m_haveExactMatch = true;
1899  }
1900 
1901  return matchCompletion;
1902 }
1903 
1904 QString KateCompletionModel::propertyName( KTextEditor::CodeCompletionModel::CompletionProperty property )
1905 {
1906  switch (property) {
1907  case CodeCompletionModel::Public:
1908  return i18n("Public");
1909 
1910  case CodeCompletionModel::Protected:
1911  return i18n("Protected");
1912 
1913  case CodeCompletionModel::Private:
1914  return i18n("Private");
1915 
1916  case CodeCompletionModel::Static:
1917  return i18n("Static");
1918 
1919  case CodeCompletionModel::Const:
1920  return i18n("Constant");
1921 
1922  case CodeCompletionModel::Namespace:
1923  return i18n("Namespace");
1924 
1925  case CodeCompletionModel::Class:
1926  return i18n("Class");
1927 
1928  case CodeCompletionModel::Struct:
1929  return i18n("Struct");
1930 
1931  case CodeCompletionModel::Union:
1932  return i18n("Union");
1933 
1934  case CodeCompletionModel::Function:
1935  return i18n("Function");
1936 
1937  case CodeCompletionModel::Variable:
1938  return i18n("Variable");
1939 
1940  case CodeCompletionModel::Enum:
1941  return i18n("Enumeration");
1942 
1943  case CodeCompletionModel::Template:
1944  return i18n("Template");
1945 
1946  case CodeCompletionModel::Virtual:
1947  return i18n("Virtual");
1948 
1949  case CodeCompletionModel::Override:
1950  return i18n("Override");
1951 
1952  case CodeCompletionModel::Inline:
1953  return i18n("Inline");
1954 
1955  case CodeCompletionModel::Friend:
1956  return i18n("Friend");
1957 
1958  case CodeCompletionModel::Signal:
1959  return i18n("Signal");
1960 
1961  case CodeCompletionModel::Slot:
1962  return i18n("Slot");
1963 
1964  case CodeCompletionModel::LocalScope:
1965  return i18n("Local Scope");
1966 
1967  case CodeCompletionModel::NamespaceScope:
1968  return i18n("Namespace Scope");
1969 
1970  case CodeCompletionModel::GlobalScope:
1971  return i18n("Global Scope");
1972 
1973  default:
1974  return i18n("Unknown Property");
1975  }
1976 }
1977 
1978 bool KateCompletionModel::Item::isVisible( ) const
1979 {
1980  return matchCompletion && matchFilters;
1981 }
1982 
1983 bool KateCompletionModel::Item::isFiltered( ) const
1984 {
1985  return !matchFilters;
1986 }
1987 
1988 bool KateCompletionModel::Item::isMatching( ) const
1989 {
1990  return matchFilters;
1991 }
1992 
1993 const KateCompletionModel::ModelRow& KateCompletionModel::Item::sourceRow( ) const
1994 {
1995  return m_sourceRow;
1996 }
1997 
1998 QString KateCompletionModel::currentCompletion( KTextEditor::CodeCompletionModel* model ) const
1999 {
2000  return m_currentMatch.value(model);
2001 }
2002 
2003 Qt::CaseSensitivity KateCompletionModel::matchCaseSensitivity( ) const
2004 {
2005  return m_matchCaseSensitivity;
2006 }
2007 
2008 void KateCompletionModel::addCompletionModel(KTextEditor::CodeCompletionModel * model)
2009 {
2010  if (m_completionModels.contains(model))
2011  return;
2012 
2013  m_completionModels.append(model);
2014 
2015  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int)));
2016  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int)));
2017  connect(model, SIGNAL(modelReset()), SLOT(slotModelReset()));
2018 
2019  // This performs the reset
2020  createGroups();
2021 }
2022 
2023 void KateCompletionModel::setCompletionModel(KTextEditor::CodeCompletionModel* model)
2024 {
2025  clearCompletionModels();
2026  addCompletionModel(model);
2027 }
2028 
2029 void KateCompletionModel::setCompletionModels(const QList<KTextEditor::CodeCompletionModel*>& models)
2030 {
2031  //if (m_completionModels == models)
2032  //return;
2033 
2034  clearCompletionModels();
2035 
2036  m_completionModels = models;
2037 
2038  foreach (KTextEditor::CodeCompletionModel* model, models) {
2039  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int)));
2040  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int)));
2041  connect(model, SIGNAL(modelReset()), SLOT(slotModelReset()));
2042  }
2043 
2044  // This performs the reset
2045  createGroups();
2046 }
2047 
2048 QList< KTextEditor::CodeCompletionModel * > KateCompletionModel::completionModels() const
2049 {
2050  return m_completionModels;
2051 }
2052 
2053 void KateCompletionModel::removeCompletionModel(CodeCompletionModel * model)
2054 {
2055  if (!model || !m_completionModels.contains(model))
2056  return;
2057 
2058  beginResetModel();
2059  m_currentMatch.remove(model);
2060 
2061  clearGroups();
2062 
2063  model->disconnect(this);
2064 
2065  m_completionModels.removeAll(model);
2066  endResetModel();
2067 
2068  if (!m_completionModels.isEmpty()) {
2069  // This performs the reset
2070  createGroups();
2071  }
2072 }
2073 
2074 void KateCompletionModel::makeGroupItemsUnique(bool onlyFiltered)
2075 {
2076  struct FilterItems {
2077  FilterItems(KateCompletionModel& model, const QVector<KTextEditor::CodeCompletionModel*>& needShadowing) : m_model(model), m_needShadowing(needShadowing) {
2078  }
2079 
2080  QHash<QString, CodeCompletionModel*> had;
2081  KateCompletionModel& m_model;
2082  const QVector< KTextEditor::CodeCompletionModel* > m_needShadowing;
2083 
2084  void filter(QList<Item>& items)
2085  {
2086  QList<Item> temp;
2087  foreach(const Item& item, items)
2088  {
2089  QHash<QString, CodeCompletionModel*>::const_iterator it = had.constFind(item.name());
2090  if(it != had.constEnd() && *it != item.sourceRow().first && m_needShadowing.contains(item.sourceRow().first))
2091  continue;
2092  had.insert(item.name(), item.sourceRow().first);
2093  temp.push_back(item);
2094  }
2095  items = temp;
2096  }
2097 
2098  void filter(Group* group, bool onlyFiltered)
2099  {
2100  if(group->prefilter.size() == group->filtered.size())
2101  {
2102  // Filter only once
2103  filter(group->filtered);
2104  if(!onlyFiltered)
2105  group->prefilter = group->filtered;
2106  }else{
2107  // Must filter twice
2108  filter(group->filtered);
2109  if(!onlyFiltered)
2110  filter(group->prefilter);
2111  }
2112 
2113  if(group->filtered.isEmpty())
2114  m_model.hideOrShowGroup(group);
2115 
2116  }
2117  };
2118 
2119  QVector<KTextEditor::CodeCompletionModel*> needShadowing;
2120 
2121  foreach(KTextEditor::CodeCompletionModel* model, m_completionModels)
2122  {
2123  KTextEditor::CodeCompletionModelControllerInterface4* v4 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface4*>(model);
2124  if(v4 && v4->shouldHideItemsWithEqualNames())
2125  needShadowing.push_back(model);
2126  }
2127 
2128  if(needShadowing.isEmpty())
2129  return;
2130 
2131  FilterItems filter(*this, needShadowing);
2132 
2133  filter.filter(m_ungrouped, onlyFiltered);
2134 
2135  foreach(Group* group, m_rowTable)
2136  filter.filter(group, onlyFiltered);
2137 }
2138 
2139 
2140 //Updates the best-matches group
2141 void KateCompletionModel::updateBestMatches() {
2142  int maxMatches = 300; //We cannot do too many operations here, because they are all executed whenever a character is added. Would be nice if we could split the operations up somewhat using a timer.
2143 
2144  m_updateBestMatchesTimer->stop();
2145  //Maps match-qualities to ModelRows paired together with the BestMatchesCount returned by the items.
2146  typedef QMultiMap<int, QPair<int, ModelRow> > BestMatchMap;
2147  BestMatchMap matches;
2148 
2149  if(!hasGroups()) {
2150  //If there is no grouping, just change the order of the items, moving the best matching ones to the front
2151  QMultiMap<int, int> rowsForQuality;
2152 
2153  int row = 0;
2154  foreach(const Item& item, m_ungrouped->filtered) {
2155  ModelRow source = item.sourceRow();
2156 
2157  QVariant v = source.second.data(CodeCompletionModel::BestMatchesCount);
2158 
2159  if( v.type() == QVariant::Int && v.toInt() > 0 ) {
2160  int quality = contextMatchQuality(source);
2161  if(quality > 0)
2162  rowsForQuality.insert(quality, row);
2163  }
2164 
2165  ++row;
2166  --maxMatches;
2167  if(maxMatches < 0)
2168  break;
2169  }
2170 
2171  if(!rowsForQuality.isEmpty()) {
2172  //Rewrite m_ungrouped->filtered in a new order
2173  QSet<int> movedToFront;
2174  QList<Item> newFiltered;
2175  for(QMultiMap<int, int>::const_iterator it = rowsForQuality.constBegin(); it != rowsForQuality.constEnd(); ++it) {
2176  newFiltered.prepend(m_ungrouped->filtered[it.value()]);
2177  movedToFront.insert(it.value());
2178  }
2179 
2180  {
2181  uint size = m_ungrouped->filtered.size();
2182  for(uint a = 0; a < size; ++a)
2183  if(!movedToFront.contains(a))
2184  newFiltered.append(m_ungrouped->filtered[a]);
2185  }
2186  m_ungrouped->filtered = newFiltered;
2187  }
2188  return;
2189  }
2190 
2192  foreach (Group* g, m_rowTable) {
2193  if( g == m_bestMatches )
2194  continue;
2195  for( int a = 0; a < g->filtered.size(); a++ )
2196  {
2197  ModelRow source = g->filtered[a].sourceRow();
2198 
2199  QVariant v = source.second.data(CodeCompletionModel::BestMatchesCount);
2200 
2201  if( v.type() == QVariant::Int && v.toInt() > 0 ) {
2202  //Return the best match with any of the argument-hints
2203 
2204  int quality = contextMatchQuality(source);
2205  if( quality > 0 )
2206  matches.insert(quality, qMakePair(v.toInt(), g->filtered[a].sourceRow()));
2207  --maxMatches;
2208  }
2209 
2210  if( maxMatches < 0 )
2211  break;
2212  }
2213  if( maxMatches < 0 )
2214  break;
2215  }
2216 
2217  //Now choose how many of the matches will be taken. This is done with the rule:
2218  //The count of shown best-matches should equal the average count of their BestMatchesCounts
2219  int cnt = 0;
2220  int matchesSum = 0;
2221  BestMatchMap::const_iterator it = matches.constEnd();
2222  while( it != matches.constBegin() )
2223  {
2224  --it;
2225  ++cnt;
2226  matchesSum += (*it).first;
2227  if( cnt > matchesSum / cnt )
2228  break;
2229  }
2230 
2231  m_bestMatches->filtered.clear();
2232 
2233  it = matches.constEnd();
2234 
2235  while( it != matches.constBegin() && cnt > 0 )
2236  {
2237  --it;
2238  --cnt;
2239 
2240  m_bestMatches->filtered.append( Item( true, this, HierarchicalModelHandler((*it).second.first), (*it).second) );
2241  }
2242 
2243  hideOrShowGroup(m_bestMatches);
2244 }
2245 
2246 void KateCompletionModel::rowSelected(const QModelIndex& row) {
2247  ExpandingWidgetModel::rowSelected(row);
2249  int rc = widget()->argumentHintModel()->rowCount(QModelIndex());
2250  if( rc == 0 ) return;
2251 
2252  //For now, simply update the whole column 0
2253  QModelIndex start = widget()->argumentHintModel()->index(0,0);
2254  QModelIndex end = widget()->argumentHintModel()->index(rc-1,0);
2255 
2256  widget()->argumentHintModel()->emitDataChanged(start, end);
2257 }
2258 
2259 void KateCompletionModel::clearCompletionModels()
2260 {
2261  if (m_completionModels.isEmpty())
2262  return;
2263 
2264  beginResetModel();
2265  foreach (CodeCompletionModel * model, m_completionModels)
2266  model->disconnect(this);
2267 
2268  m_completionModels.clear();
2269 
2270  m_currentMatch.clear();
2271 
2272  clearGroups();
2273  endResetModel();
2274 }
2275 
2276 #include "katecompletionmodel.moc"
2277 // kate: space-indent on; indent-width 2; replace-tabs on;
operator<
bool operator<(const KateTextLayout &r, const KTextEditor::Cursor &c)
Definition: katetextlayout.cpp:78
KateCompletionModel::clearCompletionModels
void clearCompletionModels()
Definition: katecompletionmodel.cpp:2259
KateCompletionModel::BestMatchesProperty
Definition: katecompletionmodel.h:147
QVariant::canConvert
bool canConvert(Type t) const
KateCompletionModel::Group::prefilter
QList< Item > prefilter
Definition: katecompletionmodel.h:303
KateCompletionModel::indexIsItem
virtual bool indexIsItem(const QModelIndex &index) const
Should return true if the given row should be painted like a contained item(as opposed to label-rows ...
Definition: katecompletionmodel.cpp:1144
KateCompletionModel::setMaximumInheritanceDepth
void setMaximumInheritanceDepth(int maxDepth)
Definition: katecompletionmodel.cpp:1652
KateCompletionModel::filterContextMatchesOnly
bool filterContextMatchesOnly() const
Definition: katecompletionmodel.cpp:1608
KateCompletionModel::setFilterAttributes
void setFilterAttributes(KTextEditor::CodeCompletionModel::CompletionProperties attributes)
Definition: katecompletionmodel.cpp:1639
QList::clear
void clear()
QModelIndex
KateCompletionModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Does not request data from index, this only returns local data like highlighting for expanded rows an...
Definition: katecompletionmodel.cpp:183
QVarLengthArray::at
const T & at(int i) const
KateCompletionModel::Group::model
KateCompletionModel * model
Definition: katecompletionmodel.h:299
KateCompletionModel::mapFromSource
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
Maps from an index in a source-model to the index of the item in this display-model.
Definition: katecompletionmodel.cpp:883
KateCompletionModel::Group::customSortingKey
int customSortingKey
Definition: katecompletionmodel.h:306
QAbstractItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const =0
kateview.h
KateCompletionModel::completionModels
QList< KTextEditor::CodeCompletionModel * > completionModels() const
Definition: katecompletionmodel.cpp:2048
KateCompletionModel::setFilterContextMatchesOnly
void setFilterContextMatchesOnly(bool filter)
Definition: katecompletionmodel.cpp:1613
QString::append
QString & append(QChar ch)
Kate::Script::i18n
QScriptValue i18n(QScriptContext *context, QScriptEngine *engine)
i18n("text", arguments [optional])
Definition: katescripthelpers.cpp:186
KateCompletionModel::KateCompletionModel
KateCompletionModel(KateCompletionWidget *parent=0L)
Definition: katecompletionmodel.cpp:128
KateCompletionModel::accessIncludeConst
bool accessIncludeConst() const
Definition: katecompletionmodel.cpp:1355
KateCompletionModel::setCompletionModels
void setCompletionModels(const QList< KTextEditor::CodeCompletionModel * > &models)
Definition: katecompletionmodel.cpp:2029
ExpandingWidgetModel::rowSelected
virtual void rowSelected(const QModelIndex &row)
Notifies underlying models that the item was selected, collapses any previous partially expanded line...
Definition: expandingwidgetmodel.cpp:157
KateCompletionModel::matchCaseSensitivity
Qt::CaseSensitivity matchCaseSensitivity() const
Definition: katecompletionmodel.cpp:2003
containsAtWordBeginning
static bool containsAtWordBeginning(const QString &word, const QString &typed, Qt::CaseSensitivity caseSensitive)
Definition: katecompletionmodel.cpp:1845
KateCompletionModel::commonPrefix
QString commonPrefix(QModelIndex selectedIndex) const
Returns a common prefix for all current visible completion entries If there is no common prefix...
Definition: katecompletionmodel.cpp:1000
ExpandingWidgetModel::clearExpanding
void clearExpanding()
Unexpand all rows and clear all cached information about them(this includes deleting the expanding-wi...
Definition: expandingwidgetmodel.cpp:123
KateView::renderer
KateRenderer * renderer()
Definition: kateview.cpp:1664
KateCompletionModel::contextMatchQuality
virtual int contextMatchQuality(const QModelIndex &index) const
Definition: katecompletionmodel.cpp:299
QAbstractItemModel::layoutChanged
void layoutChanged()
katerenderer.h
KateCompletionModel::accessIncludeSignalSlot
bool accessIncludeSignalSlot() const
Definition: katecompletionmodel.cpp:1385
KateCompletionModel::Group::attribute
int attribute
Definition: katecompletionmodel.h:300
QList::push_back
void push_back(const T &value)
QVarLengthArray::append
void append(const T &t)
QAbstractTableModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
KateCompletionModel::mapToSource
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
Maps from this display-model into the appropriate source code-completion model.
Definition: katecompletionmodel.cpp:866
QVariant::toList
QList< QVariant > toList() const
QObject::sender
QObject * sender() const
QChar
katecompletiontree.h
QFont
KateCompletionModel::ItemTypeMask
static const int ItemTypeMask
Definition: katecompletionmodel.h:154
mergeCustomHighlighting
QList< QVariant > mergeCustomHighlighting(int leftSize, const QList< QVariant > &left, int rightSize, const QList< QVariant > &right)
Definition: expandingwidgetmodel.cpp:449
QMap::constBegin
const_iterator constBegin() const
QMap< CodeCompletionModel::ExtraItemDataRoles, QVariant >
KateCompletionModel::setFilteringEnabled
void setFilteringEnabled(bool enable)
Definition: katecompletionmodel.cpp:1178
QString::size
int size() const
katecompletiondelegate.h
KateCompletionModel::setColumnMerges
void setColumnMerges(const QList< QList< int > > &columnMerges)
Definition: katecompletionmodel.cpp:1251
KateCompletionModel::setSortingCaseSensitivity
void setSortingCaseSensitivity(Qt::CaseSensitivity cs)
Definition: katecompletionmodel.cpp:1574
KateCompletionModel::filteredItemCount
uint filteredItemCount() const
Definition: katecompletionmodel.cpp:1719
QVarLengthArray
KateCompletionModel::setGroupingEnabled
void setGroupingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1194
ExpandingWidgetModel::m_collapsedIcon
static QIcon m_collapsedIcon
Definition: expandingwidgetmodel.h:136
kateargumenthintmodel.h
KateCompletionModel
This class has the responsibility for filtering, sorting, and manipulating code completion data provi...
Definition: katecompletionmodel.h:48
KateCompletionModel::Group::resort
void resort()
Definition: katecompletionmodel.cpp:1568
KateCompletionModel::currentCompletion
QString currentCompletion(KTextEditor::CodeCompletionModel *model) const
Definition: katecompletionmodel.cpp:1998
QAbstractItemModel::modelReset
void modelReset()
QSet::insert
const_iterator insert(const T &value)
KateCompletionModel::accessIncludeStatic
bool accessIncludeStatic() const
Definition: katecompletionmodel.cpp:1370
KateCompletionModel::groupingMethod
GroupingMethods groupingMethod() const
Definition: katecompletionmodel.cpp:1410
QMap::clear
void clear()
KateCompletionModel::AccessTypeMask
static const int AccessTypeMask
Definition: katecompletionmodel.h:153
KateCompletionModel::propertyName
static QString propertyName(KTextEditor::CodeCompletionModel::CompletionProperty property)
Definition: katecompletionmodel.cpp:1904
KateCompletionModel::setCurrentCompletion
void setCurrentCompletion(KTextEditor::CodeCompletionModel *model, const QString &completion)
Definition: katecompletionmodel.cpp:907
KateCompletionModel::columnName
static QString columnName(int column)
Definition: katecompletionmodel.cpp:1226
ExpandingWidgetModel::isExpandable
bool isExpandable(const QModelIndex &index) const
Definition: expandingwidgetmodel.cpp:290
KateCompletionModel::setAccessIncludeStatic
void setAccessIncludeStatic(bool include)
Definition: katecompletionmodel.cpp:1375
QList::size
int size() const
KateCompletionModel::isFilteringEnabled
bool isFilteringEnabled() const
Definition: katecompletionmodel.cpp:1216
QString::isNull
bool isNull() const
KateCompletionModel::removeCompletionModel
void removeCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2053
KateCompletionModel::hasIndex
virtual bool hasIndex(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:463
QFont::setBold
void setBold(bool enable)
QAbstractItemModel::beginResetModel
void beginResetModel()
KateCompletionModel::Group::addItem
void addItem(Item i, bool notifyModel=false)
Definition: katecompletionmodel.cpp:1497
QAbstractItemModel::match
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, QFlags< Qt::MatchFlag > flags) const
KateView::completionWidget
KateCompletionWidget * completionWidget() const
Definition: kateview.cpp:2346
QModelIndex::isValid
bool isValid() const
codecompletionmodelcontrollerinterfacev4.h
QList::count
int count(const T &value) const
KateCompletionModel::Group::refilter
void refilter()
Definition: katecompletionmodel.cpp:1679
QList::append
void append(const T &value)
KateCompletionWidget
This is the code completion's main widget, and also contains the core interface logic.
Definition: katecompletionwidget.h:55
QString::insert
QString & insert(int position, QChar ch)
QObject::property
QVariant property(const char *name) const
QTimer
ExpandingWidgetModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Does not request data from index, this only returns local data like highlighting for expanded rows an...
Definition: expandingwidgetmodel.cpp:88
KateCompletionModel::argumentHintsChanged
void argumentHintsChanged()
QVariant::toInt
int toInt(bool *ok) const
KateCompletionModel::columnMerges
const QList< QList< int > > & columnMerges() const
Definition: katecompletionmodel.cpp:1246
KateRenderer::config
KateRendererConfig * config() const
Configuration.
Definition: katerenderer.h:362
QHash
QAbstractItemModel::endInsertRows
void endInsertRows()
KateCompletionModel::setMatchCaseSensitivity
void setMatchCaseSensitivity(Qt::CaseSensitivity cs)
Definition: katecompletionmodel.cpp:368
KateArgumentHintModel::rowCount
virtual int rowCount(const QModelIndex &parent) const
Definition: kateargumenthintmodel.cpp:226
KateCompletionModel::rowSelected
virtual void rowSelected(const QModelIndex &row)
Notifies underlying models that the item was selected, collapses any previous partially expanded line...
Definition: katecompletionmodel.cpp:2246
KateCompletionWidget::view
KateView * view() const
Definition: katecompletionwidget.cpp:271
KateCompletionModel::isSortingEnabled
bool isSortingEnabled() const
Definition: katecompletionmodel.cpp:1221
KateCompletionModel::Group::rowOf
int rowOf(ModelRow item)
Returns the row in the this group's filtered list of the given model-row in a source-model -1 if the ...
Definition: katecompletionmodel.h:292
QList::isEmpty
bool isEmpty() const
KateCompletionModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:838
QString::isEmpty
bool isEmpty() const
QList::removeAll
int removeAll(const T &value)
KateCompletionModel::columnCount
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:373
QMap::constEnd
const_iterator constEnd() const
QChar::isUpper
bool isUpper() const
katecompletionmodel.h
QAbstractItemModel::beginRemoveRows
void beginRemoveRows(const QModelIndex &parent, int first, int last)
QModelIndex::row
int row() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
KateCompletionModel::Group::clear
void clear()
Definition: katecompletionmodel.cpp:1601
KateCompletionModel::setCompletionModel
void setCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2023
QMap::const_iterator
QModelIndex::internalPointer
void * internalPointer() const
katecompletionwidget.h
KateCompletionModel::sort
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
Definition: katecompletionmodel.cpp:860
QMultiMap::insert
QMap< Key, T >::iterator insert(const Key &key, const T &value)
KateCompletionModel::widget
KateCompletionWidget * widget() const
Definition: katecompletionmodel.cpp:359
KateCompletionModel::setSortingAlphabetical
void setSortingAlphabetical(bool alphabetical)
Definition: katecompletionmodel.cpp:1558
KateCompletionModel::maximumInheritanceDepth
int maximumInheritanceDepth() const
Definition: katecompletionmodel.cpp:1647
QSet
KateCompletionModel::isSortingByInheritanceDepth
bool isSortingByInheritanceDepth() const
Definition: katecompletionmodel.cpp:1415
QString
QList< int >
matchesAbbreviationHelper
static bool matchesAbbreviationHelper(const QString &word, const QString &typed, const QVarLengthArray< int, 32 > &offsets, int &depth, int atWord=-1, int i=0)
Definition: katecompletionmodel.cpp:1762
KateCompletionModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Definition: katecompletionmodel.cpp:348
QModelIndex::parent
QModelIndex parent() const
QAbstractItemModel::rowsRemoved
void rowsRemoved(const QModelIndex &parent, int start, int end)
KateCompletionModel::view
KateView * view() const
Definition: katecompletionmodel.cpp:363
QStringList
ExpandingWidgetModel::isExpanded
bool isExpanded(const QModelIndex &row) const
Definition: expandingwidgetmodel.cpp:305
KateCompletionModel::setColumnMergingEnabled
void setColumnMergingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1200
QPair
KateView
Definition: kateview.h:77
QAbstractItemModel::createIndex
QModelIndex createIndex(int row, int column, void *ptr) const
KTextEditor::CodeCompletionModelControllerInterface4
Extension of CodeCompletionModelControllerInterface3.
Definition: codecompletionmodelcontrollerinterfacev4.h:32
KateCompletionModel::setAccessIncludeConst
void setAccessIncludeConst(bool include)
Definition: katecompletionmodel.cpp:1360
QList::end
iterator end()
KateCompletionModel::ScopeType
Definition: katecompletionmodel.h:140
KateCompletionModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:407
QLatin1Char
QStringRef::startsWith
bool startsWith(const QString &str, Qt::CaseSensitivity cs) const
QList::contains
bool contains(const T &value) const
QString::midRef
QStringRef midRef(int position, int n) const
QTimer::stop
void stop()
QChar::toLower
QChar toLower() const
KateCompletionModel::debugStats
void debugStats()
Definition: katecompletionmodel.cpp:1162
KateCompletionModel::setAccessIncludeSignalSlot
void setAccessIncludeSignalSlot(bool include)
Definition: katecompletionmodel.cpp:1390
KateCompletionModel::translateColumn
int translateColumn(int sourceColumn) const
Definition: katecompletionmodel.cpp:1258
QSet::contains
bool contains(const T &value) const
KateArgumentHintModel::emitDataChanged
void emitDataChanged(const QModelIndex &start, const QModelIndex &end)
Definition: kateargumenthintmodel.cpp:249
KateCompletionModel::ScopeTypeMask
static const int ScopeTypeMask
Definition: katecompletionmodel.h:152
QModelIndex::child
QModelIndex child(int row, int column) const
QAbstractItemModel::beginInsertRows
void beginInsertRows(const QModelIndex &parent, int first, int last)
KateCompletionModel::addCompletionModel
void addCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2008
QHash::const_iterator
KateCompletionWidget::argumentHintModel
KateArgumentHintModel * argumentHintModel() const
Definition: katecompletionwidget.cpp:248
KateCompletionModel::isColumnMergingEnabled
bool isColumnMergingEnabled() const
Definition: katecompletionmodel.cpp:1206
KateCompletionModel::Group
Definition: katecompletionmodel.h:274
KateCompletionModel::isGroupingEnabled
bool isGroupingEnabled() const
Definition: katecompletionmodel.cpp:1211
KateCompletionModel::AccessType
Definition: katecompletionmodel.h:142
KateCompletionModel::setFilterByAttribute
void setFilterByAttribute(bool filter)
Definition: katecompletionmodel.cpp:1626
QModelIndex::model
const QAbstractItemModel * model() const
QString::mid
QString mid(int position, int n) const
KateCompletionModel::shouldMatchHideCompletionList
bool shouldMatchHideCompletionList() const
Returns whether one of the filtered items exactly matches its completion string.
Definition: katecompletionmodel.cpp:1728
QVector
QModelIndex::data
QVariant data(int role) const
KateRendererConfig::font
const QFont & font() const
Definition: kateconfig.cpp:2276
KateCompletionModel::setSortingEnabled
void setSortingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1184
KateCompletionModel::Group::removeItem
bool removeItem(const ModelRow &row)
Removes the item specified by row. Returns true if a change was made to rows.
Definition: katecompletionmodel.cpp:1529
QTreeView
QList::insert
void insert(int i, const T &value)
QVector::isEmpty
bool isEmpty() const
QModelIndex::sibling
QModelIndex sibling(int row, int column) const
KateCompletionModel::setGroupingMethod
void setGroupingMethod(GroupingMethods m)
Definition: katecompletionmodel.cpp:1348
KateCompletionModel::Group::isEmpty
bool isEmpty
Definition: katecompletionmodel.h:304
KateCompletionModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:383
QString::at
const QChar at(int position) const
KateCompletionModel::hasGroups
bool hasGroups() const
Definition: katecompletionmodel.cpp:774
KateCompletionModel::Scope
Definition: katecompletionmodel.h:141
QModelIndex::column
int column() const
QString::length
int length() const
QString::left
QString left(int n) const
KateCompletionModel::sortingCaseSensitivity
Qt::CaseSensitivity sortingCaseSensitivity() const
Definition: katecompletionmodel.cpp:1427
QVector::push_back
void push_back(const T &value)
KateCompletionModel::~KateCompletionModel
~KateCompletionModel()
Definition: katecompletionmodel.cpp:172
QTimer::start
void start(int msec)
QVariant::isValid
bool isValid() const
QList::prepend
void prepend(const T &value)
QMap::isEmpty
bool isEmpty() const
KateCompletionModel::isSortingAlphabetical
bool isSortingAlphabetical() const
Definition: katecompletionmodel.cpp:1422
QtConcurrent::filter
QFuture< void > filter(Sequence &sequence, FilterFunction filterFunction)
QAbstractItemModel::endRemoveRows
void endRemoveRows()
QMultiMap
QVariant::type
Type type() const
QAbstractItemModel::rowsInserted
void rowsInserted(const QModelIndex &parent, int start, int end)
QAbstractItemModel::endResetModel
void endResetModel()
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KateCompletionModel::Group::orderBefore
bool orderBefore(Group *other) const
Definition: katecompletionmodel.cpp:1086
QObject::parent
QObject * parent() const
KateCompletionWidget::treeView
KateCompletionTree * treeView() const
Definition: katecompletionwidget.cpp:923
KateCompletionModel::filterAttributes
KTextEditor::CodeCompletionModel::CompletionProperties filterAttributes() const
Definition: katecompletionmodel.cpp:1634
KateCompletionModel::Group::title
QString title
Definition: katecompletionmodel.h:301
QString::compare
int compare(const QString &other) const
ExpandingWidgetModel::m_expandedIcon
static QIcon m_expandedIcon
Definition: expandingwidgetmodel.h:135
KateCompletionModel::ItemType
Definition: katecompletionmodel.h:143
kateconfig.h
KateCompletionModel::Group::filtered
QList< Item > filtered
Definition: katecompletionmodel.h:302
QVariant::toString
QString toString() const
QVarLengthArray::size
int size() const
KateCompletionModel::setSortingByInheritanceDepth
void setSortingByInheritanceDepth(bool byIneritance)
Definition: katecompletionmodel.cpp:1418
KateCompletionModel::filterByAttribute
bool filterByAttribute() const
Definition: katecompletionmodel.cpp:1621
QList::begin
iterator begin()
ExpandingWidgetModel::cacheIcons
void cacheIcons() const
Definition: expandingwidgetmodel.cpp:441
KTextEditor::CodeCompletionModelControllerInterface4::shouldHideItemsWithEqualNames
virtual bool shouldHideItemsWithEqualNames() const
When multiple completion models are used at the same time, it may happen that multiple models add ite...
Definition: codecompletionmodelcontrollerinterfacev4.cpp:25
QMap::value
const T value(const Key &key) const
QMap::remove
int remove(const Key &key)
QTimer::setSingleShot
void setSingleShot(bool singleShot)
KateCompletionModel::Group::Group
Group(KateCompletionModel *model)
Definition: katecompletionmodel.cpp:1550
QVariant
KateCompletionModel::Group::orderNumber
int orderNumber() const
Definition: katecompletionmodel.cpp:1059
ExpandingWidgetModel
Cares about expanding/un-expanding items in a tree-view together with ExpandingDelegate.
Definition: expandingwidgetmodel.h:36
Qt::ItemFlags
typedef ItemFlags
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat May 9 2020 03:56:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal