kde-workspace/kate/part/completion/katecompletionmodel.h
Ivailo Monev f68295ea28 generic: move sub-projects from kde-baseapps [ci reset]
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2022-05-14 21:56:54 +03:00

406 lines
14 KiB
C++

/* This file is part of the KDE libraries and the Kate part.
*
* Copyright (C) 2005-2006 Hamish Rodda <rodda@kde.org>
* Copyright (C) 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KATECOMPLETIONMODEL_H
#define KATECOMPLETIONMODEL_H
#include <QtGui/QAbstractProxyModel>
#include <QtCore/QPair>
#include <QtCore/QList>
#include <ktexteditor/codecompletionmodel.h>
#include "katepartinterfaces_export.h"
#include "expandingtree/expandingwidgetmodel.h"
class KateCompletionWidget;
class KateArgumentHintModel;
class KateView;
#include <QWidget>
#include <QTextEdit>
#include <QTimer>
class HierarchicalModelHandler;
/**
* This class has the responsibility for filtering, sorting, and manipulating
* code completion data provided by a CodeCompletionModel.
*
* @author Hamish Rodda <rodda@kde.org>
*/
class KATEPARTINTERFACES_EXPORT KateCompletionModel : public ExpandingWidgetModel
{
Q_OBJECT
public:
KateCompletionModel(KateCompletionWidget* parent = 0L);
~KateCompletionModel();
QList<KTextEditor::CodeCompletionModel*> completionModels() const;
void clearCompletionModels();
void addCompletionModel(KTextEditor::CodeCompletionModel* model);
void setCompletionModel(KTextEditor::CodeCompletionModel* model);
void setCompletionModels(const QList<KTextEditor::CodeCompletionModel*>& models);
void removeCompletionModel(KTextEditor::CodeCompletionModel* model);
KateView* view() const;
KateCompletionWidget* widget() const;
QString currentCompletion(KTextEditor::CodeCompletionModel* model) const;
void setCurrentCompletion(KTextEditor::CodeCompletionModel* model, const QString& completion);
Qt::CaseSensitivity matchCaseSensitivity() const;
void setMatchCaseSensitivity( Qt::CaseSensitivity cs );
static QString columnName(int column);
int translateColumn(int sourceColumn) const;
static QString propertyName(KTextEditor::CodeCompletionModel::CompletionProperty property);
///Returns a common prefix for all current visible completion entries
///If there is no common prefix, extracts the next useful prefix for the selected index
QString commonPrefix(QModelIndex selectedIndex) const;
virtual void rowSelected(const QModelIndex& row);
virtual bool indexIsItem(const QModelIndex& index) const;
virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
virtual bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const;
virtual bool hasIndex ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
// Disabled in case of bugs, reenable once fully debugged.
//virtual QMap<int, QVariant> itemData ( const QModelIndex & index ) const;
virtual QModelIndex parent ( const QModelIndex & index ) const;
virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
// Disabled in case of bugs, reenable once fully debugged.
//virtual QModelIndex sibling ( int row, int column, const QModelIndex & index ) const;
virtual void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder );
///Maps from this display-model into the appropriate source code-completion model
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
///Maps from an index in a source-model to the index of the item in this display-model
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
// Sorting
bool isSortingEnabled() const;
bool isSortingAlphabetical() const;
bool isSortingByInheritanceDepth() const;
void setSortingByInheritanceDepth(bool byIneritance);
void setSortingAlphabetical(bool alphabetical);
Qt::CaseSensitivity sortingCaseSensitivity() const;
void setSortingCaseSensitivity(Qt::CaseSensitivity cs);
bool isSortingReverse() const;
void setSortingReverse(bool reverse);
// Filtering
bool isFilteringEnabled() const;
bool filterContextMatchesOnly() const;
void setFilterContextMatchesOnly(bool filter);
bool filterByAttribute() const;
void setFilterByAttribute(bool filter);
KTextEditor::CodeCompletionModel::CompletionProperties filterAttributes() const;
void setFilterAttributes(KTextEditor::CodeCompletionModel::CompletionProperties attributes);
// A maximum depth of <= 0 equals don't filter by inheritance depth (i.e. infinity) and is default
int maximumInheritanceDepth() const;
void setMaximumInheritanceDepth(int maxDepth);
// Grouping
bool isGroupingEnabled() const;
enum gm {
ScopeType = 0x1,
Scope = 0x2,
AccessType = 0x4,
ItemType = 0x8
};
enum { //An own property that will be used to mark the best-matches group internally
BestMatchesProperty = 2*KTextEditor::CodeCompletionModel::LastProperty
};
Q_DECLARE_FLAGS(GroupingMethods, gm)
static const int ScopeTypeMask = 0x380000;
static const int AccessTypeMask = 0x7;
static const int ItemTypeMask = 0xfe0;
GroupingMethods groupingMethod() const;
void setGroupingMethod(GroupingMethods m);
bool accessIncludeConst() const;
void setAccessIncludeConst(bool include);
bool accessIncludeStatic() const;
void setAccessIncludeStatic(bool include);
bool accessIncludeSignalSlot() const;
void setAccessIncludeSignalSlot(bool include);
// Column merging
bool isColumnMergingEnabled() const;
const QList< QList<int> >& columnMerges() const;
void setColumnMerges(const QList< QList<int> >& columnMerges);
void debugStats();
///Returns whether one of the filtered items exactly matches its completion string
bool shouldMatchHideCompletionList() const;
uint filteredItemCount() const;
protected:
virtual int contextMatchQuality(const QModelIndex & index) const;
Q_SIGNALS:
void expandIndex(const QModelIndex& index);
//Emitted whenever something has changed about the group of argument-hints
void argumentHintsChanged();
public Q_SLOTS:
void setSortingEnabled(bool enable);
void setFilteringEnabled(bool enable);
void setGroupingEnabled(bool enable);
void setColumnMergingEnabled(bool enable);
private Q_SLOTS:
void slotRowsInserted( const QModelIndex & parent, int start, int end );
void slotRowsRemoved( const QModelIndex & parent, int start, int end );
void slotModelReset();
//Updates the best-matches group
void updateBestMatches();
//Makes sure that the ungrouped group contains each item only once
//Must only be called right after the group was created
void makeGroupItemsUnique(bool onlyFiltered = false);
private:
typedef QPair<KTextEditor::CodeCompletionModel*, QModelIndex> ModelRow;
virtual int contextMatchQuality(const ModelRow& sourceRow) const;
QTreeView* treeView() const;
friend class KateArgumentHintModel;
ModelRow modelRowPair(const QModelIndex& index) const;
// Represents a source row; provides sorting method
class Item {
public:
Item(bool doInitialMatch, KateCompletionModel* model, const HierarchicalModelHandler& handler, ModelRow sourceRow);
bool isValid() const;
// Returns true if the item is not filtered and matches the current completion string
bool isVisible() const;
// Returns whether the item is filtered or not
bool isFiltered() const;
// Returns whether the item matches the current completion string
bool isMatching() const;
bool filter();
enum MatchType {
NoMatch = 0,
PerfectMatch,
StartsWithMatch,
AbbreviationMatch,
ContainsMatch
};
MatchType match();
const ModelRow& sourceRow() const;
// Sorting operator
bool operator<(const Item& rhs) const;
bool haveExactMatch() const {
return m_haveExactMatch;
}
void clearExactMatch() {
m_haveExactMatch = false;
}
QString name() const {
return m_nameColumn;
}
private:
KateCompletionModel* model;
ModelRow m_sourceRow;
mutable QString m_nameColumn;
int inheritanceDepth;
// True when currently matching completion string
MatchType matchCompletion : 6;
// True when passes all active filters
bool matchFilters : 1;
bool m_haveExactMatch : 1;
QString completionSortingName() const;
};
public:
// Grouping and sorting of rows
class Group {
public:
explicit Group(KateCompletionModel* model);
void addItem(Item i, bool notifyModel = false);
/// Removes the item specified by \a row. Returns true if a change was made to rows.
bool removeItem(const ModelRow& row);
void resort();
void refilter();
void clear();
//Returns whether this group should be ordered before other
bool orderBefore(Group* other) const;
//Returns a number that can be used for ordering
int orderNumber() const;
///Returns the row in the this group's filtered list of the given model-row in a source-model
///-1 if the item is not in the filtered list
///@todo Implement an efficient way of doing this map, that does _not_ iterate over all items!
int rowOf(ModelRow item) {
for(int a = 0; a < filtered.size(); ++a)
if(filtered[a].sourceRow() == item)
return a;
return -1;
}
KateCompletionModel* model;
int attribute;
QString title, scope;
QList<Item> filtered;
QList<Item> prefilter;
bool isEmpty;
//-1 if none was set
int customSortingKey;
};
bool hasGroups() const;
private:
QString commonPrefixInternal(const QString &forcePrefix) const;
/// @note performs model reset
void createGroups();
///Creates all sub-items of index i, or the item corresponding to index i. Returns the affected groups.
///i must be an index in the source model
QSet<Group*> createItems(const HierarchicalModelHandler&, const QModelIndex& i, bool notifyModel = false);
///Deletes all sub-items of index i, or the item corresponding to index i. Returns the affected groups.
///i must be an index in the source model
QSet<Group*> deleteItems(const QModelIndex& i);
Group* createItem(const HierarchicalModelHandler&, const QModelIndex& i, bool notifyModel = false);
/// @note Make sure you're in a {begin,end}ResetModel block when calling this!
void clearGroups();
void hideOrShowGroup(Group* g, bool notifyModel = false);
/// When forceGrouping is enabled, all given attributes will be used for grouping, regardless of the completion settings.
Group* fetchGroup(int attribute, const QString& scope = QString(), bool forceGrouping = false);
//If this returns nonzero on an index, the index is the header of the returned group
Group* groupForIndex(const QModelIndex& index) const;
inline Group* groupOfParent(const QModelIndex& child) const { return static_cast<Group*>(child.internalPointer()); }
QModelIndex indexForRow(Group* g, int row) const;
QModelIndex indexForGroup(Group* g) const;
enum changeTypes {
Broaden,
Narrow,
Change
};
//Returns whether the model needs to be reset
void changeCompletions(Group* g, changeTypes changeType, bool notifyModel);
bool hasCompletionModel() const;
/// Removes attributes not used in grouping from the input \a attribute
int groupingAttributes(int attribute) const;
int countBits(int value) const;
void resort();
void refilter();
static bool matchesAbbreviation(const QString& word, const QString& typed);
bool m_hasGroups;
// ### Runtime state
// General
QList<KTextEditor::CodeCompletionModel*> m_completionModels;
QMap<KTextEditor::CodeCompletionModel*, QString> m_currentMatch;
Qt::CaseSensitivity m_matchCaseSensitivity;
// Column merging
QList< QList<int> > m_columnMerges;
QTimer* m_updateBestMatchesTimer;
Group* m_ungrouped;
Group* m_argumentHints; //The argument-hints will be passed on to another model, to be shown in another widget
Group* m_bestMatches; //A temporary group used for holding the best matches of all visible items
// Storing the sorted order
QList<Group*> m_rowTable;
QList<Group*> m_emptyGroups;
// Quick access to each specific group (if it exists)
QMultiHash<int, Group*> m_groupHash;
// Maps custom group-names to their specific groups
QHash<QString, Group*> m_customGroupHash;
// ### Configurable state
// Sorting
bool m_sortingEnabled;
bool m_sortingAlphabetical;
bool m_isSortingByInheritance;
Qt::CaseSensitivity m_sortingCaseSensitivity;
QHash< int, QList<int> > m_sortingGroupingOrder;
// Filtering
bool m_filteringEnabled;
bool m_filterContextMatchesOnly;
bool m_filterByAttribute;
KTextEditor::CodeCompletionModel::CompletionProperties m_filterAttributes;
int m_maximumInheritanceDepth;
// Grouping
bool m_groupingEnabled;
GroupingMethods m_groupingMethod;
bool m_accessConst, m_accessStatic, m_accesSignalSlot;
// Column merging
bool m_columnMergingEnabled/*, m_haveExactMatch*/;
friend class CompletionTest;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(KateCompletionModel::GroupingMethods)
#endif