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

Kate

  • sources
  • kde-4.12
  • 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( bool shouldReset )
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  if(shouldReset)
541  reset();
542 }
543 
544 QSet<KateCompletionModel::Group*> KateCompletionModel::createItems(const HierarchicalModelHandler& _handler, const QModelIndex& i, bool notifyModel) {
545  HierarchicalModelHandler handler(_handler);
546  QSet<Group*> ret;
547 
548  if( handler.model()->rowCount(i) == 0 ) {
549  //Leaf node, create an item
550  ret.insert( createItem(handler, i, notifyModel) );
551  } else {
552  //Non-leaf node, take the role from the node, and recurse to the sub-nodes
553  handler.takeRole(i);
554  for(int a = 0; a < handler.model()->rowCount(i); a++)
555  ret += createItems(handler, i.child(a, 0), notifyModel);
556  }
557 
558  return ret;
559 }
560 
561 QSet<KateCompletionModel::Group*> KateCompletionModel::deleteItems(const QModelIndex& i) {
562  QSet<Group*> ret;
563 
564  if( i.model()->rowCount(i) == 0 ) {
565  //Leaf node, delete the item
566  Group* g = groupForIndex(mapFromSource(i));
567  ret.insert(g);
568  g->removeItem(ModelRow(const_cast<CodeCompletionModel*>(static_cast<const CodeCompletionModel*>(i.model())), i));
569  } else {
570  //Non-leaf node
571  for(int a = 0; a < i.model()->rowCount(i); a++)
572  ret += deleteItems(i.child(a, 0));
573  }
574 
575  return ret;
576 }
577 
578 void KateCompletionModel::createGroups()
579 {
580  //After clearing the model, it has to be reset, else we will be in an invalid state while inserting
581  //new groups.
582  clearGroups(true);
583 
584  bool has_groups=false;
585  foreach (CodeCompletionModel* sourceModel, m_completionModels) {
586  has_groups|=sourceModel->hasGroups();
587  for (int i = 0; i < sourceModel->rowCount(); ++i)
588  createItems(HierarchicalModelHandler(sourceModel), sourceModel->index(i, 0));
589  }
590  m_hasGroups=has_groups;
591 
592  //debugStats();
593 
594  foreach (Group* g, m_rowTable)
595  hideOrShowGroup(g);
596 
597  foreach (Group* g, m_emptyGroups)
598  hideOrShowGroup(g);
599 
600  makeGroupItemsUnique();
601 
602  updateBestMatches();
603 
604  reset();
605 
606  emit contentGeometryChanged();
607 }
608 
609 KateCompletionModel::Group* KateCompletionModel::createItem(const HierarchicalModelHandler& handler, const QModelIndex& sourceIndex, bool notifyModel)
610 {
611  //QModelIndex sourceIndex = sourceModel->index(row, CodeCompletionModel::Name, QModelIndex());
612 
613  int completionFlags = handler.getData(CodeCompletionModel::CompletionRole, sourceIndex).toInt();
614 
615  //Scope is expensive, should not be used with big models
616  QString scopeIfNeeded = (groupingMethod() & Scope) ? sourceIndex.sibling(sourceIndex.row(), CodeCompletionModel::Scope).data(Qt::DisplayRole).toString() : QString();
617 
618  int argumentHintDepth = handler.getData(CodeCompletionModel::ArgumentHintDepth, sourceIndex).toInt();
619 
620  Group* g;
621  if( argumentHintDepth ) {
622  g = m_argumentHints;
623  } else{
624  QString customGroup = handler.customGroup();
625  if(!customGroup.isNull() && m_hasGroups) {
626  if(m_customGroupHash.contains(customGroup)) {
627  g = m_customGroupHash[customGroup];
628  }else{
629  g = new Group(this);
630  g->title = customGroup;
631  g->customSortingKey = handler.customGroupingKey();
632  m_emptyGroups.append(g);
633  m_customGroupHash.insert(customGroup, g);
634  }
635  }else{
636  g = fetchGroup(completionFlags, scopeIfNeeded, handler.hasHierarchicalRoles());
637  }
638  }
639 
640  Item item = Item(g != m_argumentHints, this, handler, ModelRow(handler.model(), sourceIndex));
641 
642  if(g != m_argumentHints)
643  item.match();
644 
645  g->addItem(item, notifyModel);
646 
647  return g;
648 }
649 
650 void KateCompletionModel::slotRowsInserted( const QModelIndex & parent, int start, int end )
651 {
652  QSet<Group*> affectedGroups;
653 
654  HierarchicalModelHandler handler(static_cast<CodeCompletionModel*>(sender()));
655  if(parent.isValid())
656  handler.collectRoles(parent);
657 
658 
659  for (int i = start; i <= end; ++i)
660  affectedGroups += createItems(handler, parent.isValid() ? parent.child(i, 0) : handler.model()->index(i, 0), true);
661 
662  foreach (Group* g, affectedGroups)
663  hideOrShowGroup(g);
664 
665  emit contentGeometryChanged();
666 }
667 
668 void KateCompletionModel::slotRowsRemoved( const QModelIndex & parent, int start, int end )
669 {
670  CodeCompletionModel* source = static_cast<CodeCompletionModel*>(sender());
671 
672  QSet<Group*> affectedGroups;
673 
674  for (int i = start; i <= end; ++i) {
675  QModelIndex index = parent.isValid() ? parent.child(i, 0) : source->index(i, 0);
676 
677  affectedGroups += deleteItems(index);
678  }
679 
680  foreach (Group* g, affectedGroups)
681  hideOrShowGroup(g);
682 
683  emit contentGeometryChanged();
684 }
685 
686 KateCompletionModel::Group* KateCompletionModel::fetchGroup( int attribute, const QString& scope, bool forceGrouping )
687 {
688  Q_UNUSED(forceGrouping);
689 
691  if (!hasGroups())
692  return m_ungrouped;
693 
694  int groupingAttribute = groupingAttributes(attribute);
695  //kDebug( 13035 ) << attribute << " " << groupingAttribute;
696 
697  if (m_groupHash.contains(groupingAttribute)) {
698  if (groupingMethod() & Scope) {
699  for (QHash<int, Group*>::ConstIterator it = m_groupHash.constFind(groupingAttribute); it != m_groupHash.constEnd() && it.key() == groupingAttribute; ++it)
700  if (it.value()->scope == scope)
701  return it.value();
702  } else {
703  return m_groupHash.value(groupingAttribute);
704  }
705  }
706  Group* ret = new Group(this);
707 
708  ret->attribute = attribute;
709  ret->scope = scope;
710 
711  QString st, at, it;
712 
713  if (groupingMethod() & ScopeType) {
714  if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
715  st = "Global";
716  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
717  st = "Namespace";
718  else if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
719  st = "Local";
720 
721  ret->title = st;
722  }
723 
724  if (groupingMethod() & Scope) {
725  if (!ret->title.isEmpty())
726  ret->title.append(" ");
727 
728  ret->title.append(scope);
729  }
730 
731  if (groupingMethod() & AccessType) {
732  if (attribute & KTextEditor::CodeCompletionModel::Public)
733  at = "Public";
734  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
735  at = "Protected";
736  else if (attribute & KTextEditor::CodeCompletionModel::Private)
737  at = "Private";
738 
739  if (accessIncludeStatic() && attribute & KTextEditor::CodeCompletionModel::Static)
740  at.append(" Static");
741 
742  if (accessIncludeConst() && attribute & KTextEditor::CodeCompletionModel::Const)
743  at.append(" Const");
744 
745  if( !at.isEmpty() ) {
746  if (!ret->title.isEmpty())
747  ret->title.append(", ");
748 
749  ret->title.append(at);
750  }
751  }
752 
753  if (groupingMethod() & ItemType) {
754  if (attribute & CodeCompletionModel::Namespace)
755  it = i18n("Namespaces");
756  else if (attribute & CodeCompletionModel::Class)
757  it = i18n("Classes");
758  else if (attribute & CodeCompletionModel::Struct)
759  it = i18n("Structs");
760  else if (attribute & CodeCompletionModel::Union)
761  it = i18n("Unions");
762  else if (attribute & CodeCompletionModel::Function)
763  it = i18n("Functions");
764  else if (attribute & CodeCompletionModel::Variable)
765  it = i18n("Variables");
766  else if (attribute & CodeCompletionModel::Enum)
767  it = i18n("Enumerations");
768 
769  if( !it.isEmpty() ) {
770  if (!ret->title.isEmpty())
771  ret->title.append(" ");
772 
773  ret->title.append(it);
774  }
775  }
776 
777  m_emptyGroups.append(ret);
778  m_groupHash.insert(groupingAttribute, ret);
779 
780  return ret;
781 }
782 
783 bool KateCompletionModel::hasGroups( ) const
784 {
785  //kDebug( 13035 ) << "m_groupHash.size()"<<m_groupHash.size();
786  //kDebug( 13035 ) << "m_rowTable.count()"<<m_rowTable.count();
787  // We cannot decide whether there is groups easily. The problem: The code-model can
788  // be populated with a delay from within a background-thread.
789  // Proper solution: Ask all attached code-models(Through a new interface) whether they want to use grouping,
790  // and if at least one wants to, return true, else return false.
791  return m_groupingEnabled && m_hasGroups;
792 }
793 
794 KateCompletionModel::Group* KateCompletionModel::groupForIndex( const QModelIndex & index ) const
795 {
796  if (!index.isValid()) {
797  if (!hasGroups())
798  return m_ungrouped;
799  else
800  return 0L;
801  }
802 
803  if (groupOfParent(index))
804  return 0L;
805 
806  if (index.row() < 0 || index.row() >= m_rowTable.count())
807  return m_ungrouped;
808 
809  return m_rowTable[index.row()];
810 }
811 
812 /*QMap< int, QVariant > KateCompletionModel::itemData( const QModelIndex & index ) const
813 {
814  if (!hasGroups() || groupOfParent(index)) {
815  QModelIndex index = mapToSource(index);
816  if (index.isValid())
817  return index.model()->itemData(index);
818  }
819 
820  return QAbstractItemModel::itemData(index);
821 }*/
822 
823 QModelIndex KateCompletionModel::parent( const QModelIndex & index ) const
824 {
825  if (!index.isValid())
826  return QModelIndex();
827 
828  if (Group* g = groupOfParent(index)) {
829  if (!hasGroups()) {
830  Q_ASSERT(g == m_ungrouped);
831  return QModelIndex();
832  }
833 
834  int row = m_rowTable.indexOf(g);
835 
836  if (row == -1) {
837  kWarning() << "Couldn't find parent for index" << index;
838  return QModelIndex();
839  }
840 
841  return createIndex(row, 0, 0);
842  }
843 
844  return QModelIndex();
845 }
846 
847 int KateCompletionModel::rowCount( const QModelIndex & parent ) const
848 {
849  if (!parent.isValid()) {
850  if (hasGroups()) {
851  //kDebug( 13035 ) << "Returning row count for toplevel " << m_rowTable.count();
852  return m_rowTable.count();
853  } else {
854  //kDebug( 13035 ) << "Returning ungrouped row count for toplevel " << m_ungrouped->filtered.count();
855  return m_ungrouped->filtered.count();
856  }
857  }
858 
859  Group* g = groupForIndex(parent);
860 
861  // This is not an error, seems you don't have to check hasChildren()
862  if (!g)
863  return 0;
864 
865  //kDebug( 13035 ) << "Returning row count for group " << g << " as " << g->filtered.count();
866  return g->filtered.count();
867 }
868 
869 void KateCompletionModel::sort( int column, Qt::SortOrder order )
870 {
871  Q_UNUSED(column)
872  Q_UNUSED(order)
873 }
874 
875 QModelIndex KateCompletionModel::mapToSource( const QModelIndex & proxyIndex ) const
876 {
877  if (!proxyIndex.isValid())
878  return QModelIndex();
879 
880  if (Group* g = groupOfParent(proxyIndex)) {
881  if( proxyIndex.row() >= 0 && proxyIndex.row() < g->filtered.count() ) {
882  ModelRow source = g->filtered[proxyIndex.row()].sourceRow();
883  return source.second.sibling(source.second.row(), proxyIndex.column());
884  }else{
885  kDebug( 13035 ) << "Invalid proxy-index";
886  }
887  }
888 
889  return QModelIndex();
890 }
891 
892 QModelIndex KateCompletionModel::mapFromSource( const QModelIndex & sourceIndex ) const
893 {
894  if (!sourceIndex.isValid())
895  return QModelIndex();
896 
897  if (!hasGroups())
898  return index(m_ungrouped->rowOf(modelRowPair(sourceIndex)), sourceIndex.column(), QModelIndex());
899 
900  foreach (Group* g, m_rowTable) {
901  int row = g->rowOf(modelRowPair(sourceIndex));
902  if (row != -1)
903  return index(row, sourceIndex.column(), indexForGroup(g));
904  }
905 
906  // Copied from above
907  foreach (Group* g, m_emptyGroups) {
908  int row = g->rowOf(modelRowPair(sourceIndex));
909  if (row != -1)
910  return index(row, sourceIndex.column(), indexForGroup(g));
911  }
912 
913  return QModelIndex();
914 }
915 
916 void KateCompletionModel::setCurrentCompletion( KTextEditor::CodeCompletionModel* model, const QString & completion )
917 {
918  if (m_currentMatch[model] == completion)
919  return;
920 
921  if (!hasCompletionModel()) {
922  m_currentMatch[model] = completion;
923  return;
924  }
925 
926  changeTypes changeType = Change;
927 
928  if (m_currentMatch[model].length() > completion.length() && m_currentMatch[model].startsWith(completion, m_matchCaseSensitivity)) {
929  // Filter has been broadened
930  changeType = Broaden;
931 
932  } else if (m_currentMatch[model].length() < completion.length() && completion.startsWith(m_currentMatch[model], m_matchCaseSensitivity)) {
933  // Filter has been narrowed
934  changeType = Narrow;
935  }
936 
937  //kDebug( 13035 ) << model << "Old match: " << m_currentMatch[model] << ", new: " << completion << ", type: " << changeType;
938 
939  m_currentMatch[model] = completion;
940 
941  bool needsReset = false;
942 
943  if (!hasGroups()) {
944  needsReset |= changeCompletions(m_ungrouped, changeType);
945  } else {
946  foreach (Group* g, m_rowTable) {
947  if(g != m_argumentHints)
948  needsReset |= changeCompletions(g, changeType);
949  }
950  foreach (Group* g, m_emptyGroups) {
951  if(g != m_argumentHints)
952  needsReset |= changeCompletions(g, changeType);
953  }
954  }
955 
956  // NOTE: best matches are also updated in resort
957  resort();
958 
959  kDebug()<<"needsReset"<<needsReset;
960  if(needsReset)
961  reset();
962 
963  clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering.
964  emit contentGeometryChanged();
965  kDebug();
966 }
967 
968 QString KateCompletionModel::commonPrefixInternal(const QString &forcePrefix) const
969 {
970  QString commonPrefix; // isNull() = true
971 
972  QList< Group* > groups = m_rowTable;
973  groups += m_ungrouped;
974 
975  foreach (Group* g, groups) {
976  foreach(const Item& item, g->filtered)
977  {
978  uint startPos = m_currentMatch[item.sourceRow().first].length();
979  const QString candidate = item.name().mid(startPos);
980 
981  if(!candidate.startsWith(forcePrefix))
982  continue;
983 
984  if(commonPrefix.isNull()) {
985  commonPrefix = candidate;
986 
987  //Replace QString::null prefix with QString(""), so we won't initialize it again
988  if(commonPrefix.isNull())
989  commonPrefix = QString(""); // isEmpty() = true, isNull() = false
990  }else{
991  commonPrefix = commonPrefix.left(candidate.length());
992 
993  for(int a = 0; a < commonPrefix.length(); ++a) {
994  if(commonPrefix[a] != candidate[a]) {
995  commonPrefix = commonPrefix.left(a);
996  break;
997  }
998  }
999  }
1000  }
1001  }
1002 
1003  return commonPrefix;
1004 }
1005 
1006 QString KateCompletionModel::commonPrefix(QModelIndex selectedIndex) const
1007 {
1008  QString commonPrefix = commonPrefixInternal(QString());
1009 
1010  if(commonPrefix.isEmpty() && selectedIndex.isValid()) {
1011  Group* g = m_ungrouped;
1012  if(hasGroups())
1013  g = groupOfParent(selectedIndex);
1014 
1015  if(g && selectedIndex.row() < g->filtered.size())
1016  {
1017  //Follow the path of the selected item, finding the next non-empty common prefix
1018  Item item = g->filtered[selectedIndex.row()];
1019  int matchLength = m_currentMatch[item.sourceRow().first].length();
1020  commonPrefix = commonPrefixInternal(item.name().mid(matchLength).left(1));
1021  }
1022  }
1023 
1024  return commonPrefix;
1025 }
1026 
1027 bool KateCompletionModel::changeCompletions( Group * g, changeTypes changeType )
1028 {
1029  bool notifyModel = true;
1030  if(changeType != Narrow) {
1031  notifyModel = false;
1032  g->filtered = g->prefilter;
1033  //In the "Broaden" or "Change" case, just re-filter everything,
1034  //and don't notify the model. The model is notified afterwards through a reset().
1035  }
1036  //This code determines what of the filtered items still fit, and computes the ranges that were removed, giving
1037  //them to beginRemoveRows(..) in batches
1038 
1039  QList <KateCompletionModel::Item > newFiltered;
1040  int deleteUntil = -1; //In each state, the range [currentRow+1, deleteUntil] needs to be deleted
1041  for(int currentRow = g->filtered.count()-1; currentRow >= 0; --currentRow) {
1042  if(g->filtered[currentRow].match()) {
1043  //This row does not need to be deleted, which means that currentRow+1 to deleteUntil need to be deleted now
1044  if(deleteUntil != -1 && notifyModel) {
1045  beginRemoveRows(indexForGroup(g), currentRow+1, deleteUntil);
1046  endRemoveRows();
1047  }
1048  deleteUntil = -1;
1049 
1050  newFiltered.prepend(g->filtered[currentRow]);
1051  }else{
1052  if(deleteUntil == -1)
1053  deleteUntil = currentRow; //Mark that this row needs to be deleted
1054  }
1055  }
1056 
1057  if(deleteUntil != -1) {
1058  beginRemoveRows(indexForGroup(g), 0, deleteUntil);
1059  endRemoveRows();
1060  }
1061 
1062  g->filtered = newFiltered;
1063  hideOrShowGroup(g, notifyModel);
1064  return !notifyModel;
1065 }
1066 
1067 int KateCompletionModel::Group::orderNumber() const {
1068  if( this == model->m_ungrouped )
1069  return 700;
1070 
1071  if(customSortingKey != -1)
1072  return customSortingKey;
1073 
1074  if( attribute & BestMatchesProperty )
1075  return 1;
1076 
1077  if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
1078  return 100;
1079  else if (attribute & KTextEditor::CodeCompletionModel::Public)
1080  return 200;
1081  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
1082  return 300;
1083  else if (attribute & KTextEditor::CodeCompletionModel::Private)
1084  return 400;
1085  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
1086  return 500;
1087  else if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
1088  return 600;
1089 
1090 
1091  return 700;
1092 }
1093 
1094 bool KateCompletionModel::Group::orderBefore(Group* other) const {
1095  return orderNumber() < other->orderNumber();
1096 }
1097 
1098 void KateCompletionModel::hideOrShowGroup(Group* g, bool notifyModel)
1099 {
1100  if( g == m_argumentHints ) {
1101  emit argumentHintsChanged();
1102  m_updateBestMatchesTimer->start(200); //We have new argument-hints, so we have new best matches
1103  return; //Never show argument-hints in the normal completion-list
1104  }
1105 
1106  if (!g->isEmpty) {
1107  if (g->filtered.isEmpty()) {
1108  // Move to empty group list
1109  g->isEmpty = true;
1110  int row = m_rowTable.indexOf(g);
1111  if (row != -1) {
1112  if (hasGroups() && notifyModel)
1113  beginRemoveRows(QModelIndex(), row, row);
1114  m_rowTable.removeAt(row);
1115  if (hasGroups() && notifyModel)
1116  endRemoveRows();
1117  m_emptyGroups.append(g);
1118  } else {
1119  kWarning() << "Group " << g << " not found in row table!!";
1120  }
1121  }
1122 
1123  } else {
1124 
1125  if (!g->filtered.isEmpty()) {
1126  // Move off empty group list
1127  g->isEmpty = false;
1128 
1129  int row = 0; //Find row where to insert
1130  for( int a = 0; a < m_rowTable.count(); a++ ) {
1131  if( g->orderBefore(m_rowTable[a]) ) {
1132  row = a;
1133  break;
1134  }
1135  row = a+1;
1136  }
1137 
1138  if(notifyModel) {
1139  if (hasGroups())
1140  beginInsertRows(QModelIndex(), row, row);
1141  else
1142  beginInsertRows(QModelIndex(), 0, g->filtered.count());
1143  }
1144  m_rowTable.insert(row, g);
1145  if(notifyModel)
1146  endInsertRows();
1147  m_emptyGroups.removeAll(g);
1148  }
1149  }
1150 }
1151 
1152 bool KateCompletionModel::indexIsItem( const QModelIndex & index ) const
1153 {
1154  if (!hasGroups())
1155  return true;
1156 
1157  if (groupOfParent(index))
1158  return true;
1159 
1160  return false;
1161 }
1162 
1163 void KateCompletionModel::slotModelReset()
1164 {
1165  createGroups();
1166 
1167  //debugStats();
1168 }
1169 
1170 void KateCompletionModel::debugStats()
1171 {
1172  if (!hasGroups())
1173  kDebug( 13035 ) << "Model groupless, " << m_ungrouped->filtered.count() << " items.";
1174  else {
1175  kDebug( 13035 ) << "Model grouped (" << m_rowTable.count() << " groups):";
1176  foreach (Group* g, m_rowTable)
1177  kDebug( 13035 ) << "Group" << g << "count" << g->filtered.count();
1178  }
1179 }
1180 
1181 bool KateCompletionModel::hasCompletionModel( ) const
1182 {
1183  return !m_completionModels.isEmpty();
1184 }
1185 
1186 void KateCompletionModel::setFilteringEnabled( bool enable )
1187 {
1188  if (m_filteringEnabled != enable)
1189  m_filteringEnabled = enable;
1190 }
1191 
1192 void KateCompletionModel::setSortingEnabled( bool enable )
1193 {
1194  if (m_sortingEnabled != enable) {
1195  m_sortingEnabled = enable;
1196  resort();
1197  }
1198 }
1199 
1200 void KateCompletionModel::setGroupingEnabled(bool enable)
1201 {
1202  if (m_groupingEnabled != enable)
1203  m_groupingEnabled = enable;
1204 }
1205 
1206 void KateCompletionModel::setColumnMergingEnabled(bool enable)
1207 {
1208  if (m_columnMergingEnabled != enable)
1209  m_columnMergingEnabled = enable;
1210 }
1211 
1212 bool KateCompletionModel::isColumnMergingEnabled( ) const
1213 {
1214  return m_columnMergingEnabled;
1215 }
1216 
1217 bool KateCompletionModel::isGroupingEnabled( ) const
1218 {
1219  return m_groupingEnabled;
1220 }
1221 
1222 bool KateCompletionModel::isFilteringEnabled( ) const
1223 {
1224  return m_filteringEnabled;
1225 }
1226 
1227 bool KateCompletionModel::isSortingEnabled( ) const
1228 {
1229  return m_sortingEnabled;
1230 }
1231 
1232 QString KateCompletionModel::columnName( int column )
1233 {
1234  switch (column) {
1235  case KTextEditor::CodeCompletionModel::Prefix:
1236  return i18n("Prefix");
1237  case KTextEditor::CodeCompletionModel::Icon:
1238  return i18n("Icon");
1239  case KTextEditor::CodeCompletionModel::Scope:
1240  return i18n("Scope");
1241  case KTextEditor::CodeCompletionModel::Name:
1242  return i18n("Name");
1243  case KTextEditor::CodeCompletionModel::Arguments:
1244  return i18n("Arguments");
1245  case KTextEditor::CodeCompletionModel::Postfix:
1246  return i18n("Postfix");
1247  }
1248 
1249  return QString();
1250 }
1251 
1252 const QList< QList < int > > & KateCompletionModel::columnMerges( ) const
1253 {
1254  return m_columnMerges;
1255 }
1256 
1257 void KateCompletionModel::setColumnMerges( const QList< QList < int > > & columnMerges )
1258 {
1259  m_columnMerges = columnMerges;
1260  reset();
1261 }
1262 
1263 int KateCompletionModel::translateColumn( int sourceColumn ) const
1264 {
1265  if (m_columnMerges.isEmpty())
1266  return sourceColumn;
1267 
1268  /* Debugging - dump column merge list
1269 
1270  QString columnMerge;
1271  foreach (const QList<int>& list, m_columnMerges) {
1272  columnMerge += '[';
1273  foreach (int column, list) {
1274  columnMerge += QString::number(column) + " ";
1275  }
1276  columnMerge += "] ";
1277  }
1278 
1279  kDebug( 13035 ) << k_funcinfo << columnMerge;*/
1280 
1281  int c = 0;
1282  foreach (const QList<int>& list, m_columnMerges) {
1283  foreach (int column, list) {
1284  if (column == sourceColumn)
1285  return c;
1286  }
1287  c++;
1288  }
1289  return -1;
1290 }
1291 
1292 int KateCompletionModel::groupingAttributes( int attribute ) const
1293 {
1294  int ret = 0;
1295 
1296  if (m_groupingMethod & ScopeType) {
1297  if (countBits(attribute & ScopeTypeMask) > 1)
1298  kWarning() << "Invalid completion model metadata: more than one scope type modifier provided.";
1299 
1300  if (attribute & KTextEditor::CodeCompletionModel::GlobalScope)
1301  ret |= KTextEditor::CodeCompletionModel::GlobalScope;
1302  else if (attribute & KTextEditor::CodeCompletionModel::NamespaceScope)
1303  ret |= KTextEditor::CodeCompletionModel::NamespaceScope;
1304  else if (attribute & KTextEditor::CodeCompletionModel::LocalScope)
1305  ret |= KTextEditor::CodeCompletionModel::LocalScope;
1306  }
1307 
1308  if (m_groupingMethod & AccessType) {
1309  if (countBits(attribute & AccessTypeMask) > 1)
1310  kWarning() << "Invalid completion model metadata: more than one access type modifier provided.";
1311 
1312  if (attribute & KTextEditor::CodeCompletionModel::Public)
1313  ret |= KTextEditor::CodeCompletionModel::Public;
1314  else if (attribute & KTextEditor::CodeCompletionModel::Protected)
1315  ret |= KTextEditor::CodeCompletionModel::Protected;
1316  else if (attribute & KTextEditor::CodeCompletionModel::Private)
1317  ret |= KTextEditor::CodeCompletionModel::Private;
1318 
1319  if (accessIncludeStatic() && attribute & KTextEditor::CodeCompletionModel::Static)
1320  ret |= KTextEditor::CodeCompletionModel::Static;
1321 
1322  if (accessIncludeConst() && attribute & KTextEditor::CodeCompletionModel::Const)
1323  ret |= KTextEditor::CodeCompletionModel::Const;
1324  }
1325 
1326  if (m_groupingMethod & ItemType) {
1327  if (countBits(attribute & ItemTypeMask) > 1)
1328  kWarning() << "Invalid completion model metadata: more than one item type modifier provided.";
1329 
1330  if (attribute & KTextEditor::CodeCompletionModel::Namespace)
1331  ret |= KTextEditor::CodeCompletionModel::Namespace;
1332  else if (attribute & KTextEditor::CodeCompletionModel::Class)
1333  ret |= KTextEditor::CodeCompletionModel::Class;
1334  else if (attribute & KTextEditor::CodeCompletionModel::Struct)
1335  ret |= KTextEditor::CodeCompletionModel::Struct;
1336  else if (attribute & KTextEditor::CodeCompletionModel::Union)
1337  ret |= KTextEditor::CodeCompletionModel::Union;
1338  else if (attribute & KTextEditor::CodeCompletionModel::Function)
1339  ret |= KTextEditor::CodeCompletionModel::Function;
1340  else if (attribute & KTextEditor::CodeCompletionModel::Variable)
1341  ret |= KTextEditor::CodeCompletionModel::Variable;
1342  else if (attribute & KTextEditor::CodeCompletionModel::Enum)
1343  ret |= KTextEditor::CodeCompletionModel::Enum;
1344 
1345  /*
1346  if (itemIncludeTemplate() && attribute & KTextEditor::CodeCompletionModel::Template)
1347  ret |= KTextEditor::CodeCompletionModel::Template;*/
1348  }
1349 
1350  return ret;
1351 }
1352 
1353 void KateCompletionModel::setGroupingMethod( GroupingMethods m )
1354 {
1355  m_groupingMethod = m;
1356 
1357  createGroups();
1358 }
1359 
1360 bool KateCompletionModel::accessIncludeConst( ) const
1361 {
1362  return m_accessConst;
1363 }
1364 
1365 void KateCompletionModel::setAccessIncludeConst( bool include )
1366 {
1367  if (m_accessConst != include) {
1368  m_accessConst = include;
1369 
1370  if (groupingMethod() & AccessType)
1371  createGroups();
1372  }
1373 }
1374 
1375 bool KateCompletionModel::accessIncludeStatic( ) const
1376 {
1377  return m_accessStatic;
1378 }
1379 
1380 void KateCompletionModel::setAccessIncludeStatic( bool include )
1381 {
1382  if (m_accessStatic != include) {
1383  m_accessStatic = include;
1384 
1385  if (groupingMethod() & AccessType)
1386  createGroups();
1387  }
1388 }
1389 
1390 bool KateCompletionModel::accessIncludeSignalSlot( ) const
1391 {
1392  return m_accesSignalSlot;
1393 }
1394 
1395 void KateCompletionModel::setAccessIncludeSignalSlot( bool include )
1396 {
1397  if (m_accesSignalSlot != include) {
1398  m_accesSignalSlot = include;
1399 
1400  if (groupingMethod() & AccessType)
1401  createGroups();
1402  }
1403 }
1404 
1405 int KateCompletionModel::countBits( int value ) const
1406 {
1407  int count = 0;
1408  for (int i = 1; i; i <<= 1)
1409  if (i & value)
1410  count++;
1411 
1412  return count;
1413 }
1414 
1415 KateCompletionModel::GroupingMethods KateCompletionModel::groupingMethod( ) const
1416 {
1417  return m_groupingMethod;
1418 }
1419 
1420 bool KateCompletionModel::isSortingByInheritanceDepth() const {
1421  return m_isSortingByInheritance;
1422 }
1423 void KateCompletionModel::setSortingByInheritanceDepth(bool byInheritance) {
1424  m_isSortingByInheritance = byInheritance;
1425 }
1426 
1427 bool KateCompletionModel::isSortingAlphabetical( ) const
1428 {
1429  return m_sortingAlphabetical;
1430 }
1431 
1432 Qt::CaseSensitivity KateCompletionModel::sortingCaseSensitivity( ) const
1433 {
1434  return m_sortingCaseSensitivity;
1435 }
1436 
1437 KateCompletionModel::Item::Item( bool doInitialMatch, KateCompletionModel* m, const HierarchicalModelHandler& handler, ModelRow sr )
1438  : model(m)
1439  , m_sourceRow(sr)
1440  , matchCompletion(StartsWithMatch)
1441  , matchFilters(true)
1442  , m_haveExactMatch(false)
1443 {
1444 
1445  inheritanceDepth = handler.getData(CodeCompletionModel::InheritanceDepth, m_sourceRow.second).toInt();
1446 
1447  QModelIndex nameSibling = sr.second.sibling(sr.second.row(), CodeCompletionModel::Name);
1448  m_nameColumn = nameSibling.data(Qt::DisplayRole).toString();
1449 
1450  if(doInitialMatch) {
1451  filter();
1452  match();
1453  }
1454 }
1455 
1456 bool KateCompletionModel::Item::operator <( const Item & rhs ) const
1457 {
1458  int ret = 0;
1459 
1460  //kDebug( 13035 ) << c1 << " c/w " << c2 << " -> " << (model->isSortingReverse() ? ret > 0 : ret < 0) << " (" << ret << ")";
1461 
1462  const bool isBad = m_sourceRow.second.data(CodeCompletionModel::UnimportantItemRole).toBool();
1463  const bool otherIsBad = rhs.m_sourceRow.second.data(CodeCompletionModel::UnimportantItemRole).toBool();
1464  if( isBad && !otherIsBad ) {
1465  return false;
1466  }
1467  if( otherIsBad && !isBad ) {
1468  return true;
1469  }
1470 
1471  if( matchCompletion < rhs.matchCompletion ) {
1472  // enums are ordered in the order items should be displayed
1473  return true;
1474  }
1475  if( matchCompletion > rhs.matchCompletion ) {
1476  return false;
1477  }
1478 
1479  if( model->isSortingByInheritanceDepth() )
1480  ret = inheritanceDepth - rhs.inheritanceDepth;
1481 
1482  if (ret == 0 && model->isSortingAlphabetical()) {
1483  // Do not use localeAwareCompare, because it is simply too slow for a list of about 1000 items
1484  ret = QString::compare(m_nameColumn, rhs.m_nameColumn, model->sortingCaseSensitivity());
1485  }
1486 
1487  if( ret == 0 ) {
1488  // FIXME need to define a better default ordering for multiple model display
1489  ret = m_sourceRow.second.row() - rhs.m_sourceRow.second.row();
1490  }
1491 
1492  return ret < 0;
1493 }
1494 
1495 void KateCompletionModel::Group::addItem( Item i, bool notifyModel )
1496 {
1497  if (isEmpty)
1498  notifyModel = false;
1499 
1500  QModelIndex groupIndex;
1501  if (notifyModel)
1502  groupIndex = model->indexForGroup(this);
1503 
1504  if (model->isSortingEnabled()) {
1505 
1506  prefilter.insert(qUpperBound(prefilter.begin(), prefilter.end(), i), i);
1507  if(i.isVisible()) {
1508  QList<Item>::iterator it = qUpperBound(filtered.begin(), filtered.end(), i);
1509  uint rowNumber = it - filtered.begin();
1510 
1511  if(notifyModel)
1512  model->beginInsertRows(groupIndex, rowNumber, rowNumber);
1513 
1514  filtered.insert(it, i);
1515  }
1516  } else {
1517  if(notifyModel)
1518  model->beginInsertRows(groupIndex, prefilter.size(), prefilter.size());
1519  if (i.isVisible())
1520  prefilter.append(i);
1521  }
1522 
1523  if(notifyModel)
1524  model->endInsertRows();
1525 }
1526 
1527 bool KateCompletionModel::Group::removeItem(const ModelRow& row)
1528 {
1529  for (int pi = 0; pi < prefilter.count(); ++pi)
1530  if (prefilter[pi].sourceRow() == row) {
1531  int index = rowOf(row);
1532  if (index != -1)
1533  model->beginRemoveRows(model->indexForGroup(this), index, index);
1534 
1535  filtered.removeAt(index);
1536  prefilter.removeAt(pi);
1537 
1538  if (index != -1)
1539  model->endRemoveRows();
1540 
1541  return index != -1;
1542  }
1543 
1544  Q_ASSERT(false);
1545  return false;
1546 }
1547 
1548 KateCompletionModel::Group::Group( KateCompletionModel * m )
1549  : model(m)
1550  , isEmpty(true)
1551  , customSortingKey(-1)
1552 {
1553  Q_ASSERT(model);
1554 }
1555 
1556 void KateCompletionModel::setSortingAlphabetical( bool alphabetical )
1557 {
1558  if (m_sortingAlphabetical != alphabetical) {
1559  m_sortingAlphabetical = alphabetical;
1560  resort();
1561  }
1562 }
1563 
1564 void KateCompletionModel::Group::resort( )
1565 {
1566  qStableSort(filtered.begin(), filtered.end());
1567  model->hideOrShowGroup(this);
1568 }
1569 
1570 void KateCompletionModel::setSortingCaseSensitivity( Qt::CaseSensitivity cs )
1571 {
1572  if (m_sortingCaseSensitivity != cs) {
1573  m_sortingCaseSensitivity = cs;
1574  resort();
1575  }
1576 }
1577 
1578 void KateCompletionModel::resort( )
1579 {
1580  foreach (Group* g, m_rowTable)
1581  g->resort();
1582 
1583  foreach (Group* g, m_emptyGroups)
1584  g->resort();
1585 
1586  // call updateBestMatches here, so they are moved to the top again.
1587  updateBestMatches();
1588  emit contentGeometryChanged();
1589 }
1590 
1591 bool KateCompletionModel::Item::isValid( ) const
1592 {
1593  return model && m_sourceRow.first && m_sourceRow.second.row() >= 0;
1594 }
1595 
1596 void KateCompletionModel::Group::clear( )
1597 {
1598  prefilter.clear();
1599  filtered.clear();
1600  isEmpty = true;
1601 }
1602 
1603 bool KateCompletionModel::filterContextMatchesOnly( ) const
1604 {
1605  return m_filterContextMatchesOnly;
1606 }
1607 
1608 void KateCompletionModel::setFilterContextMatchesOnly( bool filter )
1609 {
1610  if (m_filterContextMatchesOnly != filter) {
1611  m_filterContextMatchesOnly = filter;
1612  refilter();
1613  }
1614 }
1615 
1616 bool KateCompletionModel::filterByAttribute( ) const
1617 {
1618  return m_filterByAttribute;
1619 }
1620 
1621 void KateCompletionModel::setFilterByAttribute( bool filter )
1622 {
1623  if (m_filterByAttribute == filter) {
1624  m_filterByAttribute = filter;
1625  refilter();
1626  }
1627 }
1628 
1629 KTextEditor::CodeCompletionModel::CompletionProperties KateCompletionModel::filterAttributes( ) const
1630 {
1631  return m_filterAttributes;
1632 }
1633 
1634 void KateCompletionModel::setFilterAttributes( KTextEditor::CodeCompletionModel::CompletionProperties attributes )
1635 {
1636  if (m_filterAttributes == attributes) {
1637  m_filterAttributes = attributes;
1638  refilter();
1639  }
1640 }
1641 
1642 int KateCompletionModel::maximumInheritanceDepth( ) const
1643 {
1644  return m_maximumInheritanceDepth;
1645 }
1646 
1647 void KateCompletionModel::setMaximumInheritanceDepth( int maxDepth )
1648 {
1649  if (m_maximumInheritanceDepth != maxDepth) {
1650  m_maximumInheritanceDepth = maxDepth;
1651  refilter();
1652  }
1653 }
1654 
1655 void KateCompletionModel::refilter( )
1656 {
1657  m_ungrouped->refilter();
1658 
1659  foreach (Group* g, m_rowTable)
1660  if(g != m_argumentHints)
1661  g->refilter();
1662 
1663  foreach (Group* g, m_emptyGroups)
1664  if(g != m_argumentHints)
1665  g->refilter();
1666 
1667  updateBestMatches();
1668 
1669  clearExpanding(); //We need to do this, or be aware of expanding-widgets while filtering.
1670 }
1671 
1672 void KateCompletionModel::Group::refilter( )
1673 {
1674  filtered.clear();
1675  foreach (const Item& i, prefilter)
1676  if (!i.isFiltered())
1677  filtered.append(i);
1678 }
1679 
1680 bool KateCompletionModel::Item::filter( )
1681 {
1682  matchFilters = false;
1683 
1684  if (model->isFilteringEnabled()) {
1685  QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name);
1686 
1687  if (model->filterContextMatchesOnly()) {
1688  QVariant contextMatch = sourceIndex.data(CodeCompletionModel::MatchQuality);
1689  if (contextMatch.canConvert(QVariant::Int) && !contextMatch.toInt())
1690  goto filter;
1691  }
1692 
1693  if (model->filterByAttribute()) {
1694  int completionFlags = sourceIndex.data(CodeCompletionModel::CompletionRole).toInt();
1695  if (model->filterAttributes() & completionFlags)
1696  goto filter;
1697  }
1698 
1699  if (model->maximumInheritanceDepth() > 0) {
1700  int inheritanceDepth = sourceIndex.data(CodeCompletionModel::InheritanceDepth).toInt();
1701  if (inheritanceDepth > model->maximumInheritanceDepth())
1702  goto filter;
1703  }
1704  }
1705 
1706  matchFilters = true;
1707 
1708  filter:
1709  return matchFilters;
1710 }
1711 
1712 uint KateCompletionModel::filteredItemCount() const
1713 {
1714  uint ret = 0;
1715  foreach(Group* group, m_rowTable)
1716  ret += group->filtered.size();
1717 
1718  return ret;
1719 }
1720 
1721 bool KateCompletionModel::shouldMatchHideCompletionList() const {
1722 
1723  // @todo Make this faster
1724 
1725  bool doHide = false;
1726  CodeCompletionModel* hideModel = 0;
1727 
1728  foreach(Group* group, m_rowTable)
1729  foreach(const Item& item, group->filtered)
1730  if(item.haveExactMatch()) {
1731  KTextEditor::CodeCompletionModelControllerInterface3* iface3 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface3*>(item.sourceRow().first);
1732  bool hide = false;
1733  if ( !iface3 ) hide = true;
1734  if(iface3 && iface3->matchingItem(item.sourceRow().second) == KTextEditor::CodeCompletionModelControllerInterface3::HideListIfAutomaticInvocation)
1735  hide = true;
1736  if(hide)
1737  {
1738  doHide = true;
1739  hideModel = item.sourceRow().first;
1740  }
1741  }
1742 
1743  if(doHide)
1744  {
1745  // Check if all other visible items are from the same model
1746  foreach(Group* group, m_rowTable)
1747  foreach(const Item& item, group->filtered)
1748  if(item.sourceRow().first != hideModel)
1749  return false;
1750  }
1751 
1752  return doHide;
1753 }
1754 
1755 static inline bool matchesAbbreviationHelper(const QString& word, const QString& typed, const QVarLengthArray<int, 32>& offsets,
1756  int& depth, int atWord = -1, int i = 0) {
1757  int atLetter = 1;
1758  for ( ; i < typed.size(); i++ ) {
1759  const QChar c = typed.at(i).toLower();
1760  bool haveNextWord = offsets.size() > atWord + 1;
1761  bool canCompare = atWord != -1 && word.size() > offsets.at(atWord) + atLetter;
1762  if ( canCompare && c == word.at(offsets.at(atWord) + atLetter).toLower() ) {
1763  // the typed letter matches a letter after the current word beginning
1764  if ( ! haveNextWord || c != word.at(offsets.at(atWord + 1)).toLower() ) {
1765  // good, simple case, no conflict
1766  atLetter += 1;
1767  continue;
1768  }
1769  // For maliciously crafted data, the code used here theoretically can have very high
1770  // complexity. Thus ensure we don't run into this case, by limiting the amount of branches
1771  // we walk through to 128.
1772  depth++;
1773  if ( depth > 128 ) {
1774  return false;
1775  }
1776  // the letter matches both the next word beginning and the next character in the word
1777  if ( haveNextWord && matchesAbbreviationHelper(word, typed, offsets, depth, atWord + 1, i + 1) ) {
1778  // resolving the conflict by taking the next word's first character worked, fine
1779  return true;
1780  }
1781  // otherwise, continue by taking the next letter in the current word.
1782  atLetter += 1;
1783  continue;
1784  }
1785  else if ( haveNextWord && c == word.at(offsets.at(atWord + 1)).toLower() ) {
1786  // the typed letter matches the next word beginning
1787  atWord++;
1788  atLetter = 1;
1789  continue;
1790  }
1791  // no match
1792  return false;
1793  }
1794  // all characters of the typed word were matched
1795  return true;
1796 }
1797 
1798 bool KateCompletionModel::matchesAbbreviation(const QString& word, const QString& typed)
1799 {
1800  // A mismatch is very likely for random even for the first letter,
1801  // thus this optimization makes sense.
1802  if ( word.at(0).toLower() != typed.at(0).toLower() ) {
1803  return false;
1804  }
1805 
1806  // First, check if all letters are contained in the word in the right order.
1807  int atLetter = 0;
1808  foreach ( const QChar c, typed ) {
1809  while ( c.toLower() != word.at(atLetter).toLower() ) {
1810  atLetter += 1;
1811  if ( atLetter >= word.size() ) {
1812  return false;
1813  }
1814  }
1815  }
1816 
1817  bool haveUnderscore = true;
1818  QVarLengthArray<int, 32> offsets;
1819  // We want to make "KComplM" match "KateCompletionModel"; this means we need
1820  // to allow parts of the typed text to be not part of the actual abbreviation,
1821  // which consists only of the uppercased / underscored letters (so "KCM" in this case).
1822  // However it might be ambigous whether a letter is part of such a word or part of
1823  // the following abbreviation, so we need to find all possible word offsets first,
1824  // then compare.
1825  for ( int i = 0; i < word.size(); i++ ) {
1826  const QChar c = word.at(i);
1827  if ( c == QLatin1Char('_') ) {
1828  haveUnderscore = true;
1829  } else if ( haveUnderscore || c.isUpper() ) {
1830  offsets.append(i);
1831  haveUnderscore = false;
1832  }
1833  }
1834  int depth = 0;
1835  return matchesAbbreviationHelper(word, typed, offsets, depth);
1836 }
1837 
1838 static inline bool containsAtWordBeginning(const QString& word, const QString& typed, Qt::CaseSensitivity caseSensitive) {
1839  for(int i = 1; i < word.size(); i++) {
1840  // The current position is a word beginning if the previous character was an underscore
1841  // or if the current character is uppercase. Subsequent uppercase characters do not count,
1842  // to handle the special case of UPPER_CASE_VARS properly.
1843  const QChar c = word.at(i);
1844  const QChar prev = word.at(i-1);
1845  if(!(prev == QLatin1Char('_') || (c.isUpper() && !prev.isUpper()))) {
1846  continue;
1847  }
1848  if(word.midRef(i).startsWith(typed, caseSensitive)) {
1849  return true;
1850  }
1851  }
1852  return false;
1853 };
1854 
1855 KateCompletionModel::Item::MatchType KateCompletionModel::Item::match()
1856 {
1857  // Check to see if the item is matched by the current completion string
1858  QModelIndex sourceIndex = m_sourceRow.second.sibling(m_sourceRow.second.row(), CodeCompletionModel::Name);
1859 
1860  QString match = model->currentCompletion(m_sourceRow.first);
1861 
1862  m_haveExactMatch = false;
1863 
1864  // Hehe, everything matches nothing! (ie. everything matches a blank string)
1865  if (match.isEmpty())
1866  return PerfectMatch;
1867  if (m_nameColumn.isEmpty())
1868  return NoMatch;
1869 
1870  matchCompletion = (m_nameColumn.startsWith(match, model->matchCaseSensitivity()) ? StartsWithMatch : NoMatch);
1871  if(matchCompletion == NoMatch) {
1872  // if no match, try for "contains"
1873  // Only match when the occurence is at a "word" beginning, marked by
1874  // an underscore or a capital. So Foo matches BarFoo and Bar_Foo, but not barfoo.
1875  // Starting at 1 saves looking at the beginning of the word, that was already checked above.
1876  if(containsAtWordBeginning(m_nameColumn, match, model->matchCaseSensitivity())) {
1877  matchCompletion = ContainsMatch;
1878  }
1879  }
1880 
1881  if(matchCompletion == NoMatch && !m_nameColumn.isEmpty() && !match.isEmpty())
1882  {
1883  // if still no match, try abbreviation matching
1884  if(matchesAbbreviation(m_nameColumn, match)) {
1885  matchCompletion = AbbreviationMatch;
1886  }
1887  }
1888 
1889  if(matchCompletion && match.length() == m_nameColumn.length()) {
1890  matchCompletion = PerfectMatch;
1891  m_haveExactMatch = true;
1892  }
1893 
1894  return matchCompletion;
1895 }
1896 
1897 QString KateCompletionModel::propertyName( KTextEditor::CodeCompletionModel::CompletionProperty property )
1898 {
1899  switch (property) {
1900  case CodeCompletionModel::Public:
1901  return i18n("Public");
1902 
1903  case CodeCompletionModel::Protected:
1904  return i18n("Protected");
1905 
1906  case CodeCompletionModel::Private:
1907  return i18n("Private");
1908 
1909  case CodeCompletionModel::Static:
1910  return i18n("Static");
1911 
1912  case CodeCompletionModel::Const:
1913  return i18n("Constant");
1914 
1915  case CodeCompletionModel::Namespace:
1916  return i18n("Namespace");
1917 
1918  case CodeCompletionModel::Class:
1919  return i18n("Class");
1920 
1921  case CodeCompletionModel::Struct:
1922  return i18n("Struct");
1923 
1924  case CodeCompletionModel::Union:
1925  return i18n("Union");
1926 
1927  case CodeCompletionModel::Function:
1928  return i18n("Function");
1929 
1930  case CodeCompletionModel::Variable:
1931  return i18n("Variable");
1932 
1933  case CodeCompletionModel::Enum:
1934  return i18n("Enumeration");
1935 
1936  case CodeCompletionModel::Template:
1937  return i18n("Template");
1938 
1939  case CodeCompletionModel::Virtual:
1940  return i18n("Virtual");
1941 
1942  case CodeCompletionModel::Override:
1943  return i18n("Override");
1944 
1945  case CodeCompletionModel::Inline:
1946  return i18n("Inline");
1947 
1948  case CodeCompletionModel::Friend:
1949  return i18n("Friend");
1950 
1951  case CodeCompletionModel::Signal:
1952  return i18n("Signal");
1953 
1954  case CodeCompletionModel::Slot:
1955  return i18n("Slot");
1956 
1957  case CodeCompletionModel::LocalScope:
1958  return i18n("Local Scope");
1959 
1960  case CodeCompletionModel::NamespaceScope:
1961  return i18n("Namespace Scope");
1962 
1963  case CodeCompletionModel::GlobalScope:
1964  return i18n("Global Scope");
1965 
1966  default:
1967  return i18n("Unknown Property");
1968  }
1969 }
1970 
1971 bool KateCompletionModel::Item::isVisible( ) const
1972 {
1973  return matchCompletion && matchFilters;
1974 }
1975 
1976 bool KateCompletionModel::Item::isFiltered( ) const
1977 {
1978  return !matchFilters;
1979 }
1980 
1981 bool KateCompletionModel::Item::isMatching( ) const
1982 {
1983  return matchFilters;
1984 }
1985 
1986 const KateCompletionModel::ModelRow& KateCompletionModel::Item::sourceRow( ) const
1987 {
1988  return m_sourceRow;
1989 }
1990 
1991 QString KateCompletionModel::currentCompletion( KTextEditor::CodeCompletionModel* model ) const
1992 {
1993  return m_currentMatch.value(model);
1994 }
1995 
1996 Qt::CaseSensitivity KateCompletionModel::matchCaseSensitivity( ) const
1997 {
1998  return m_matchCaseSensitivity;
1999 }
2000 
2001 void KateCompletionModel::addCompletionModel(KTextEditor::CodeCompletionModel * model)
2002 {
2003  if (m_completionModels.contains(model))
2004  return;
2005 
2006  m_completionModels.append(model);
2007 
2008  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int)));
2009  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int)));
2010  connect(model, SIGNAL(modelReset()), SLOT(slotModelReset()));
2011 
2012  // This performs the reset
2013  createGroups();
2014 }
2015 
2016 void KateCompletionModel::setCompletionModel(KTextEditor::CodeCompletionModel* model)
2017 {
2018  clearCompletionModels();
2019  addCompletionModel(model);
2020 }
2021 
2022 void KateCompletionModel::setCompletionModels(const QList<KTextEditor::CodeCompletionModel*>& models)
2023 {
2024  //if (m_completionModels == models)
2025  //return;
2026 
2027  clearCompletionModels();
2028 
2029  m_completionModels = models;
2030 
2031  foreach (KTextEditor::CodeCompletionModel* model, models) {
2032  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int)));
2033  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotRowsRemoved(QModelIndex,int,int)));
2034  connect(model, SIGNAL(modelReset()), SLOT(slotModelReset()));
2035  }
2036 
2037  // This performs the reset
2038  createGroups();
2039 }
2040 
2041 QList< KTextEditor::CodeCompletionModel * > KateCompletionModel::completionModels() const
2042 {
2043  return m_completionModels;
2044 }
2045 
2046 void KateCompletionModel::removeCompletionModel(CodeCompletionModel * model)
2047 {
2048  if (!model || !m_completionModels.contains(model))
2049  return;
2050 
2051  m_currentMatch.remove(model);
2052 
2053  clearGroups(false);
2054 
2055  model->disconnect(this);
2056 
2057  m_completionModels.removeAll(model);
2058 
2059  if (!m_completionModels.isEmpty()) {
2060  // This performs the reset
2061  createGroups();
2062  }else{
2063  emit contentGeometryChanged();
2064  reset();
2065  }
2066 }
2067 
2068 void KateCompletionModel::makeGroupItemsUnique(bool onlyFiltered)
2069 {
2070  struct FilterItems {
2071  FilterItems(KateCompletionModel& model, const QVector<KTextEditor::CodeCompletionModel*>& needShadowing) : m_model(model), m_needShadowing(needShadowing) {
2072  }
2073 
2074  QHash<QString, CodeCompletionModel*> had;
2075  KateCompletionModel& m_model;
2076  const QVector< KTextEditor::CodeCompletionModel* > m_needShadowing;
2077 
2078  void filter(QList<Item>& items)
2079  {
2080  QList<Item> temp;
2081  foreach(const Item& item, items)
2082  {
2083  QHash<QString, CodeCompletionModel*>::const_iterator it = had.constFind(item.name());
2084  if(it != had.constEnd() && *it != item.sourceRow().first && m_needShadowing.contains(item.sourceRow().first))
2085  continue;
2086  had.insert(item.name(), item.sourceRow().first);
2087  temp.push_back(item);
2088  }
2089  items = temp;
2090  }
2091 
2092  void filter(Group* group, bool onlyFiltered)
2093  {
2094  if(group->prefilter.size() == group->filtered.size())
2095  {
2096  // Filter only once
2097  filter(group->filtered);
2098  if(!onlyFiltered)
2099  group->prefilter = group->filtered;
2100  }else{
2101  // Must filter twice
2102  filter(group->filtered);
2103  if(!onlyFiltered)
2104  filter(group->prefilter);
2105  }
2106 
2107  if(group->filtered.isEmpty())
2108  m_model.hideOrShowGroup(group);
2109 
2110  }
2111  };
2112 
2113  QVector<KTextEditor::CodeCompletionModel*> needShadowing;
2114 
2115  foreach(KTextEditor::CodeCompletionModel* model, m_completionModels)
2116  {
2117  KTextEditor::CodeCompletionModelControllerInterface4* v4 = dynamic_cast<KTextEditor::CodeCompletionModelControllerInterface4*>(model);
2118  if(v4 && v4->shouldHideItemsWithEqualNames())
2119  needShadowing.push_back(model);
2120  }
2121 
2122  if(needShadowing.isEmpty())
2123  return;
2124 
2125  FilterItems filter(*this, needShadowing);
2126 
2127  filter.filter(m_ungrouped, onlyFiltered);
2128 
2129  foreach(Group* group, m_rowTable)
2130  filter.filter(group, onlyFiltered);
2131 }
2132 
2133 
2134 //Updates the best-matches group
2135 void KateCompletionModel::updateBestMatches() {
2136  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.
2137 
2138  m_updateBestMatchesTimer->stop();
2139  //Maps match-qualities to ModelRows paired together with the BestMatchesCount returned by the items.
2140  typedef QMultiMap<int, QPair<int, ModelRow> > BestMatchMap;
2141  BestMatchMap matches;
2142 
2143  if(!hasGroups()) {
2144  //If there is no grouping, just change the order of the items, moving the best matching ones to the front
2145  QMultiMap<int, int> rowsForQuality;
2146 
2147  int row = 0;
2148  foreach(const Item& item, m_ungrouped->filtered) {
2149  ModelRow source = item.sourceRow();
2150 
2151  QVariant v = source.second.data(CodeCompletionModel::BestMatchesCount);
2152 
2153  if( v.type() == QVariant::Int && v.toInt() > 0 ) {
2154  int quality = contextMatchQuality(source);
2155  if(quality > 0)
2156  rowsForQuality.insert(quality, row);
2157  }
2158 
2159  ++row;
2160  --maxMatches;
2161  if(maxMatches < 0)
2162  break;
2163  }
2164 
2165  if(!rowsForQuality.isEmpty()) {
2166  //Rewrite m_ungrouped->filtered in a new order
2167  QSet<int> movedToFront;
2168  QList<Item> newFiltered;
2169  for(QMultiMap<int, int>::const_iterator it = rowsForQuality.constBegin(); it != rowsForQuality.constEnd(); ++it) {
2170  newFiltered.prepend(m_ungrouped->filtered[it.value()]);
2171  movedToFront.insert(it.value());
2172  }
2173 
2174  {
2175  uint size = m_ungrouped->filtered.size();
2176  for(uint a = 0; a < size; ++a)
2177  if(!movedToFront.contains(a))
2178  newFiltered.append(m_ungrouped->filtered[a]);
2179  }
2180  m_ungrouped->filtered = newFiltered;
2181  }
2182  return;
2183  }
2184 
2186  foreach (Group* g, m_rowTable) {
2187  if( g == m_bestMatches )
2188  continue;
2189  for( int a = 0; a < g->filtered.size(); a++ )
2190  {
2191  ModelRow source = g->filtered[a].sourceRow();
2192 
2193  QVariant v = source.second.data(CodeCompletionModel::BestMatchesCount);
2194 
2195  if( v.type() == QVariant::Int && v.toInt() > 0 ) {
2196  //Return the best match with any of the argument-hints
2197 
2198  int quality = contextMatchQuality(source);
2199  if( quality > 0 )
2200  matches.insert(quality, qMakePair(v.toInt(), g->filtered[a].sourceRow()));
2201  --maxMatches;
2202  }
2203 
2204  if( maxMatches < 0 )
2205  break;
2206  }
2207  if( maxMatches < 0 )
2208  break;
2209  }
2210 
2211  //Now choose how many of the matches will be taken. This is done with the rule:
2212  //The count of shown best-matches should equal the average count of their BestMatchesCounts
2213  int cnt = 0;
2214  int matchesSum = 0;
2215  BestMatchMap::const_iterator it = matches.constEnd();
2216  while( it != matches.constBegin() )
2217  {
2218  --it;
2219  ++cnt;
2220  matchesSum += (*it).first;
2221  if( cnt > matchesSum / cnt )
2222  break;
2223  }
2224 
2225  m_bestMatches->filtered.clear();
2226 
2227  it = matches.constEnd();
2228 
2229  while( it != matches.constBegin() && cnt > 0 )
2230  {
2231  --it;
2232  --cnt;
2233 
2234  m_bestMatches->filtered.append( Item( true, this, HierarchicalModelHandler((*it).second.first), (*it).second) );
2235  }
2236 
2237  hideOrShowGroup(m_bestMatches);
2238 }
2239 
2240 void KateCompletionModel::rowSelected(const QModelIndex& row) {
2241  ExpandingWidgetModel::rowSelected(row);
2243  int rc = widget()->argumentHintModel()->rowCount(QModelIndex());
2244  if( rc == 0 ) return;
2245 
2246  //For now, simply update the whole column 0
2247  QModelIndex start = widget()->argumentHintModel()->index(0,0);
2248  QModelIndex end = widget()->argumentHintModel()->index(rc-1,0);
2249 
2250  widget()->argumentHintModel()->emitDataChanged(start, end);
2251 }
2252 
2253 void KateCompletionModel::clearCompletionModels()
2254 {
2255  foreach (CodeCompletionModel * model, m_completionModels)
2256  model->disconnect(this);
2257 
2258  m_completionModels.clear();
2259 
2260  m_currentMatch.clear();
2261 
2262  clearGroups();
2263 }
2264 
2265 #include "katecompletionmodel.moc"
2266 // kate: space-indent on; indent-width 2; replace-tabs on;
QVariant
operator<
bool operator<(const KateTextLayout &r, const KTextEditor::Cursor &c)
Definition: katetextlayout.cpp:78
KateCompletionModel::clearCompletionModels
void clearCompletionModels()
Definition: katecompletionmodel.cpp:2253
KateCompletionModel::BestMatchesProperty
Definition: katecompletionmodel.h:147
KateCompletionModel::Group::prefilter
QList< Item > prefilter
Definition: katecompletionmodel.h:304
KTextEditor::CodeCompletionModel::InheritanceDepth
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:1152
KateCompletionModel::setMaximumInheritanceDepth
void setMaximumInheritanceDepth(int maxDepth)
Definition: katecompletionmodel.cpp:1647
KateCompletionModel::filterContextMatchesOnly
bool filterContextMatchesOnly() const
Definition: katecompletionmodel.cpp:1603
Group
KateCompletionModel::setFilterAttributes
void setFilterAttributes(KTextEditor::CodeCompletionModel::CompletionProperties attributes)
Definition: katecompletionmodel.cpp:1634
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
KateCompletionModel::Group::model
KateCompletionModel * model
Definition: katecompletionmodel.h:300
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:892
KateCompletionModel::Group::customSortingKey
int customSortingKey
Definition: katecompletionmodel.h:307
KTextEditor::CodeCompletionModel::GlobalScope
KTextEditor::CodeCompletionModel::Name
kateview.h
KateCompletionModel::completionModels
QList< KTextEditor::CodeCompletionModel * > completionModels() const
Definition: katecompletionmodel.cpp:2041
KateCompletionModel::setFilterContextMatchesOnly
void setFilterContextMatchesOnly(bool filter)
Definition: katecompletionmodel.cpp:1608
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:1360
KTextEditor::CodeCompletionModel::Postfix
KateCompletionModel::setCompletionModels
void setCompletionModels(const QList< KTextEditor::CodeCompletionModel * > &models)
Definition: katecompletionmodel.cpp:2022
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:1996
containsAtWordBeginning
static bool containsAtWordBeginning(const QString &word, const QString &typed, Qt::CaseSensitivity caseSensitive)
Definition: katecompletionmodel.cpp:1838
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:1006
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:1653
KateCompletionModel::contextMatchQuality
virtual int contextMatchQuality(const QModelIndex &index) const
Definition: katecompletionmodel.cpp:299
katerenderer.h
kapplication.h
KateCompletionModel::accessIncludeSignalSlot
bool accessIncludeSignalSlot() const
Definition: katecompletionmodel.cpp:1390
KateCompletionModel::Group::attribute
int attribute
Definition: katecompletionmodel.h:301
group
KateCompletionModel::mapToSource
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
Maps from this display-model into the appropriate source code-completion model.
Definition: katecompletionmodel.cpp:875
timeout
int timeout
katecompletiontree.h
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
KateCompletionModel::setFilteringEnabled
void setFilteringEnabled(bool enable)
Definition: katecompletionmodel.cpp:1186
katecompletiondelegate.h
KateCompletionModel::setColumnMerges
void setColumnMerges(const QList< QList< int > > &columnMerges)
Definition: katecompletionmodel.cpp:1257
KateCompletionModel::setSortingCaseSensitivity
void setSortingCaseSensitivity(Qt::CaseSensitivity cs)
Definition: katecompletionmodel.cpp:1570
KateCompletionModel::filteredItemCount
uint filteredItemCount() const
Definition: katecompletionmodel.cpp:1712
KateCompletionModel::setGroupingEnabled
void setGroupingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1200
ExpandingWidgetModel::m_collapsedIcon
static QIcon m_collapsedIcon
Definition: expandingwidgetmodel.h:136
kateargumenthintmodel.h
KTextEditor::CodeCompletionModel::Protected
KateCompletionModel
This class has the responsibility for filtering, sorting, and manipulating code completion data provi...
Definition: katecompletionmodel.h:48
kiconloader.h
KateCompletionModel::Group::resort
void resort()
Definition: katecompletionmodel.cpp:1564
KateCompletionModel::currentCompletion
QString currentCompletion(KTextEditor::CodeCompletionModel *model) const
Definition: katecompletionmodel.cpp:1991
QString
QHash
KTextEditor::CodeCompletionModel::hasGroups
bool hasGroups() const
KateCompletionModel::accessIncludeStatic
bool accessIncludeStatic() const
Definition: katecompletionmodel.cpp:1375
KateCompletionModel::groupingMethod
GroupingMethods groupingMethod() const
Definition: katecompletionmodel.cpp:1415
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KateCompletionModel::AccessTypeMask
static const int AccessTypeMask
Definition: katecompletionmodel.h:153
klocale.h
KateCompletionModel::propertyName
static QString propertyName(KTextEditor::CodeCompletionModel::CompletionProperty property)
Definition: katecompletionmodel.cpp:1897
KTextEditor::CodeCompletionModel::Icon
KateCompletionModel::setCurrentCompletion
void setCurrentCompletion(KTextEditor::CodeCompletionModel *model, const QString &completion)
Definition: katecompletionmodel.cpp:916
KateCompletionModel::columnName
static QString columnName(int column)
Definition: katecompletionmodel.cpp:1232
ExpandingWidgetModel::isExpandable
bool isExpandable(const QModelIndex &index) const
Definition: expandingwidgetmodel.cpp:290
KApplication::kApplication
static KApplication * kApplication()
KateCompletionModel::setAccessIncludeStatic
void setAccessIncludeStatic(bool include)
Definition: katecompletionmodel.cpp:1380
KateCompletionModel::isFilteringEnabled
bool isFilteringEnabled() const
Definition: katecompletionmodel.cpp:1222
KTextEditor::CodeCompletionModel::Class
KTextEditor::CodeCompletionModelControllerInterface3::HideListIfAutomaticInvocation
KateCompletionModel::removeCompletionModel
void removeCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2046
KateCompletionModel::hasIndex
virtual bool hasIndex(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:463
KateCompletionModel::Group::addItem
void addItem(Item i, bool notifyModel=false)
Definition: katecompletionmodel.cpp:1495
KTextEditor::CodeCompletionModel::Public
KateView::completionWidget
KateCompletionWidget * completionWidget() const
Definition: kateview.cpp:2321
KTextEditor::CodeCompletionModel::Function
codecompletionmodelcontrollerinterfacev4.h
KTextEditor::CodeCompletionModelControllerInterface3
KTextEditor::CodeCompletionModel::Namespace
KateCompletionModel::Group::refilter
void refilter()
Definition: katecompletionmodel.cpp:1672
KateCompletionWidget
This is the code completion's main widget, and also contains the core interface logic.
Definition: katecompletionwidget.h:55
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()
KateCompletionModel::columnMerges
const QList< QList< int > > & columnMerges() const
Definition: katecompletionmodel.cpp:1252
KTextEditor::CodeCompletionModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
KateRenderer::config
KateRendererConfig * config() const
Configuration.
Definition: katerenderer.h:362
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:2240
KateCompletionWidget::view
KateView * view() const
Definition: katecompletionwidget.cpp:271
KTextEditor::CodeCompletionModel::Enum
QTreeView
KateCompletionModel::contentGeometryChanged
void contentGeometryChanged()
KTextEditor::CodeCompletionModel::Struct
KateCompletionModel::isSortingEnabled
bool isSortingEnabled() const
Definition: katecompletionmodel.cpp:1227
KTextEditor::CodeCompletionModel::Scope
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:293
QStringList
KateCompletionModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:847
KateCompletionModel::columnCount
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:373
katecompletionmodel.h
KateCompletionModel::Group::clear
void clear()
Definition: katecompletionmodel.cpp:1596
KateCompletionModel::setCompletionModel
void setCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2016
katecompletionwidget.h
KateCompletionModel::sort
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
Definition: katecompletionmodel.cpp:869
KateCompletionModel::widget
KateCompletionWidget * widget() const
Definition: katecompletionmodel.cpp:359
KateCompletionModel::setSortingAlphabetical
void setSortingAlphabetical(bool alphabetical)
Definition: katecompletionmodel.cpp:1556
KateCompletionModel::maximumInheritanceDepth
int maximumInheritanceDepth() const
Definition: katecompletionmodel.cpp:1642
KateCompletionModel::isSortingByInheritanceDepth
bool isSortingByInheritanceDepth() const
Definition: katecompletionmodel.cpp:1420
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:1755
KateCompletionModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Definition: katecompletionmodel.cpp:348
KateCompletionModel::view
KateView * view() const
Definition: katecompletionmodel.cpp:363
KTextEditor::CodeCompletionModel::NamespaceScope
ExpandingWidgetModel::isExpanded
bool isExpanded(const QModelIndex &row) const
Definition: expandingwidgetmodel.cpp:305
KateCompletionModel::setColumnMergingEnabled
void setColumnMergingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1206
KateView
Definition: kateview.h:78
KTextEditor::CodeCompletionModelControllerInterface4
Extension of CodeCompletionModelControllerInterface3.
Definition: codecompletionmodelcontrollerinterfacev4.h:32
KateCompletionModel::setAccessIncludeConst
void setAccessIncludeConst(bool include)
Definition: katecompletionmodel.cpp:1365
KTextEditor::CodeCompletionModelControllerInterface3::matchingItem
virtual MatchReaction matchingItem(const QModelIndex &matched)
KateCompletionModel::ScopeType
Definition: katecompletionmodel.h:140
KateCompletionModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:407
KTextEditor::CodeCompletionModel::ColumnCount
static const int ColumnCount
QSet
KTextEditor::CodeCompletionModel::ExtraItemDataRoles
ExtraItemDataRoles
KateCompletionModel::debugStats
void debugStats()
Definition: katecompletionmodel.cpp:1170
KateCompletionModel::setAccessIncludeSignalSlot
void setAccessIncludeSignalSlot(bool include)
Definition: katecompletionmodel.cpp:1395
KateCompletionModel::translateColumn
int translateColumn(int sourceColumn) const
Definition: katecompletionmodel.cpp:1263
KateArgumentHintModel::emitDataChanged
void emitDataChanged(const QModelIndex &start, const QModelIndex &end)
Definition: kateargumenthintmodel.cpp:249
KateCompletionModel::ScopeTypeMask
static const int ScopeTypeMask
Definition: katecompletionmodel.h:152
KateCompletionModel::addCompletionModel
void addCompletionModel(KTextEditor::CodeCompletionModel *model)
Definition: katecompletionmodel.cpp:2001
KateCompletionWidget::argumentHintModel
KateArgumentHintModel * argumentHintModel() const
Definition: katecompletionwidget.cpp:248
KTextEditor::CodeCompletionModel::GroupRole
KateCompletionModel::isColumnMergingEnabled
bool isColumnMergingEnabled() const
Definition: katecompletionmodel.cpp:1212
QFont
KateCompletionModel::Group
Definition: katecompletionmodel.h:275
KateCompletionModel::isGroupingEnabled
bool isGroupingEnabled() const
Definition: katecompletionmodel.cpp:1217
KTextEditor::CodeCompletionModel::LocalScope
KateCompletionModel::AccessType
Definition: katecompletionmodel.h:142
KateCompletionModel::setFilterByAttribute
void setFilterByAttribute(bool filter)
Definition: katecompletionmodel.cpp:1621
KateCompletionModel::shouldMatchHideCompletionList
bool shouldMatchHideCompletionList() const
Returns whether one of the filtered items exactly matches its completion string.
Definition: katecompletionmodel.cpp:1721
KateRendererConfig::font
const QFont & font() const
Definition: kateconfig.cpp:2127
KateCompletionModel::setSortingEnabled
void setSortingEnabled(bool enable)
Definition: katecompletionmodel.cpp:1192
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:1527
KTextEditor::CodeCompletionModel::Private
KateCompletionModel::setGroupingMethod
void setGroupingMethod(GroupingMethods m)
Definition: katecompletionmodel.cpp:1353
KateCompletionModel::parent
virtual QModelIndex parent(const QModelIndex &index) const
Definition: katecompletionmodel.cpp:823
KateCompletionModel::Group::isEmpty
bool isEmpty
Definition: katecompletionmodel.h:305
KateCompletionModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Definition: katecompletionmodel.cpp:383
KTextEditor::CodeCompletionModel::Const
KateCompletionModel::hasGroups
bool hasGroups() const
Definition: katecompletionmodel.cpp:783
KateCompletionModel::Scope
Definition: katecompletionmodel.h:141
KTextEditor::CodeCompletionModel::Arguments
KTextEditor::CodeCompletionModel::Variable
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KateCompletionModel::sortingCaseSensitivity
Qt::CaseSensitivity sortingCaseSensitivity() const
Definition: katecompletionmodel.cpp:1432
KateCompletionModel::~KateCompletionModel
~KateCompletionModel()
Definition: katecompletionmodel.cpp:172
QPair
Item
KTextEditor::CodeCompletionModel::CompletionProperty
CompletionProperty
KTextEditor::CodeCompletionModel::Union
KateCompletionModel::isSortingAlphabetical
bool isSortingAlphabetical() const
Definition: katecompletionmodel.cpp:1427
CaseInsensitive
KTextEditor::CodeCompletionModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
reset
KGuiItem reset()
KateCompletionModel::Group::orderBefore
bool orderBefore(Group *other) const
Definition: katecompletionmodel.cpp:1094
KateCompletionWidget::treeView
KateCompletionTree * treeView() const
Definition: katecompletionwidget.cpp:921
KateCompletionModel::filterAttributes
KTextEditor::CodeCompletionModel::CompletionProperties filterAttributes() const
Definition: katecompletionmodel.cpp:1629
KateCompletionModel::Group::title
QString title
Definition: katecompletionmodel.h:302
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:303
KateCompletionModel::setSortingByInheritanceDepth
void setSortingByInheritanceDepth(bool byIneritance)
Definition: katecompletionmodel.cpp:1423
KateCompletionModel::filterByAttribute
bool filterByAttribute() const
Definition: katecompletionmodel.cpp:1616
ExpandingWidgetModel::cacheIcons
void cacheIcons() const
Definition: expandingwidgetmodel.cpp:441
QMap< CodeCompletionModel::ExtraItemDataRoles, QVariant >
KTextEditor::CodeCompletionModel::Static
QList< int >
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
KTextEditor::CodeCompletionModel::Prefix
list
QStringList list(const QString &fileClass)
KateCompletionModel::Group::Group
Group(KateCompletionModel *model)
Definition: katecompletionmodel.cpp:1548
KateCompletionModel::Group::orderNumber
int orderNumber() const
Definition: katecompletionmodel.cpp:1067
ExpandingWidgetModel
Cares about expanding/un-expanding items in a tree-view together with ExpandingDelegate.
Definition: expandingwidgetmodel.h:36
KTextEditor::CodeCompletionModel
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:51 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
  • Applications
  •   Libraries
  •     libkonq
  • 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