1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QCOMPLETER_P_H
41#define QCOMPLETER_P_H
42
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists purely as an
49// implementation detail. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include <QtWidgets/private/qtwidgetsglobal_p.h>
56#include "private/qobject_p.h"
57
58#include "QtWidgets/qabstractitemview.h"
59#include "QtCore/qabstractproxymodel.h"
60#include "qcompleter.h"
61#include "QtWidgets/qitemdelegate.h"
62#include "QtGui/qpainter.h"
63#include "private/qabstractproxymodel_p.h"
64
65QT_REQUIRE_CONFIG(completer);
66
67QT_BEGIN_NAMESPACE
68
69class QCompletionModel;
70
71class QCompleterPrivate : public QObjectPrivate
72{
73 Q_DECLARE_PUBLIC(QCompleter)
74
75public:
76 QCompleterPrivate();
77 ~QCompleterPrivate() { delete popup; }
78 void init(QAbstractItemModel *model = 0);
79
80 QPointer<QWidget> widget;
81 QCompletionModel *proxy;
82 QAbstractItemView *popup;
83 QCompleter::CompletionMode mode;
84 Qt::MatchFlags filterMode;
85
86 QString prefix;
87 Qt::CaseSensitivity cs;
88 int role;
89 int column;
90 int maxVisibleItems;
91 QCompleter::ModelSorting sorting;
92 bool wrap;
93
94 bool eatFocusOut;
95 QRect popupRect;
96 bool hiddenBecauseNoMatch;
97
98 void showPopup(const QRect&);
99 void _q_complete(QModelIndex, bool = false);
100 void _q_completionSelected(const QItemSelection&);
101 void _q_autoResizePopup();
102 void _q_fileSystemModelDirectoryLoaded(const QString &path);
103 void setCurrentIndex(QModelIndex, bool = true);
104
105 static QCompleterPrivate *get(QCompleter *o) { return o->d_func(); }
106 static const QCompleterPrivate *get(const QCompleter *o) { return o->d_func(); }
107};
108
109class QIndexMapper
110{
111public:
112 QIndexMapper() : v(false), f(0), t(-1) { }
113 QIndexMapper(int f, int t) : v(false), f(f), t(t) { }
114 QIndexMapper(const QVector<int> &vec) : v(true), vector(vec), f(-1), t(-1) { }
115
116 inline int count() const { return v ? vector.count() : t - f + 1; }
117 inline int operator[] (int index) const { return v ? vector[index] : f + index; }
118 inline int indexOf(int x) const { return v ? vector.indexOf(x) : ((t < f) ? -1 : x - f); }
119 inline bool isValid() const { return !isEmpty(); }
120 inline bool isEmpty() const { return v ? vector.isEmpty() : (t < f); }
121 inline void append(int x) { Q_ASSERT(v); vector.append(x); }
122 inline int first() const { return v ? vector.first() : f; }
123 inline int last() const { return v ? vector.last() : t; }
124 inline int from() const { Q_ASSERT(!v); return f; }
125 inline int to() const { Q_ASSERT(!v); return t; }
126 inline int cost() const { return vector.count()+2; }
127
128private:
129 bool v;
130 QVector<int> vector;
131 int f, t;
132};
133
134struct QMatchData {
135 QMatchData() : exactMatchIndex(-1), partial(false) { }
136 QMatchData(const QIndexMapper& indices, int em, bool p) :
137 indices(indices), exactMatchIndex(em), partial(p) { }
138 QIndexMapper indices;
139 inline bool isValid() const { return indices.isValid(); }
140 int exactMatchIndex;
141 bool partial;
142};
143
144class QCompletionEngine
145{
146public:
147 typedef QMap<QString, QMatchData> CacheItem;
148 typedef QMap<QModelIndex, CacheItem> Cache;
149
150 QCompletionEngine(QCompleterPrivate *c) : c(c), curRow(-1), cost(0) { }
151 virtual ~QCompletionEngine() { }
152
153 void filter(const QStringList &parts);
154
155 QMatchData filterHistory();
156 bool matchHint(const QString &part, const QModelIndex &parent, QMatchData *m) const;
157
158 void saveInCache(QString, const QModelIndex&, const QMatchData&);
159 bool lookupCache(const QString &part, const QModelIndex &parent, QMatchData *m) const;
160
161 virtual void filterOnDemand(int) { }
162 virtual QMatchData filter(const QString&, const QModelIndex&, int) = 0;
163
164 int matchCount() const { return curMatch.indices.count() + historyMatch.indices.count(); }
165
166 QMatchData curMatch, historyMatch;
167 QCompleterPrivate *c;
168 QStringList curParts;
169 QModelIndex curParent;
170 int curRow;
171
172 Cache cache;
173 int cost;
174};
175
176class QSortedModelEngine : public QCompletionEngine
177{
178public:
179 QSortedModelEngine(QCompleterPrivate *c) : QCompletionEngine(c) { }
180 QMatchData filter(const QString&, const QModelIndex&, int) override;
181 QIndexMapper indexHint(QString, const QModelIndex&, Qt::SortOrder);
182 Qt::SortOrder sortOrder(const QModelIndex&) const;
183};
184
185class QUnsortedModelEngine : public QCompletionEngine
186{
187public:
188 QUnsortedModelEngine(QCompleterPrivate *c) : QCompletionEngine(c) { }
189
190 void filterOnDemand(int) override;
191 QMatchData filter(const QString&, const QModelIndex&, int) override;
192private:
193 int buildIndices(const QString& str, const QModelIndex& parent, int n,
194 const QIndexMapper& iv, QMatchData* m);
195};
196
197// ### Qt6: QStyledItemDelegate
198class QCompleterItemDelegate : public QItemDelegate
199{
200public:
201 QCompleterItemDelegate(QAbstractItemView *view)
202 : QItemDelegate(view), view(view) { }
203 void paint(QPainter *p, const QStyleOptionViewItem& opt, const QModelIndex& idx) const override {
204 QStyleOptionViewItem optCopy = opt;
205 optCopy.showDecorationSelected = true;
206 if (view->currentIndex() == idx)
207 optCopy.state |= QStyle::State_HasFocus;
208 QItemDelegate::paint(p, optCopy, idx);
209 }
210
211private:
212 QAbstractItemView *view;
213};
214
215class QCompletionModelPrivate;
216
217class QCompletionModel : public QAbstractProxyModel
218{
219 Q_OBJECT
220
221public:
222 QCompletionModel(QCompleterPrivate *c, QObject *parent);
223
224 void createEngine();
225 void setFiltered(bool);
226 void filter(const QStringList& parts);
227 int completionCount() const;
228 int currentRow() const { return engine->curRow; }
229 bool setCurrentRow(int row);
230 QModelIndex currentIndex(bool) const;
231
232 QModelIndex index(int row, int column, const QModelIndex & = QModelIndex()) const override;
233 int rowCount(const QModelIndex &index = QModelIndex()) const override;
234 int columnCount(const QModelIndex &index = QModelIndex()) const override;
235 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
236 QModelIndex parent(const QModelIndex & = QModelIndex()) const override { return QModelIndex(); }
237 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
238
239 void setSourceModel(QAbstractItemModel *sourceModel) override;
240 QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
241 QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override;
242
243 QCompleterPrivate *c;
244 QScopedPointer<QCompletionEngine> engine;
245 bool showAll;
246
247 Q_DECLARE_PRIVATE(QCompletionModel)
248
249signals:
250 void rowsAdded();
251
252public Q_SLOTS:
253 void invalidate();
254 void rowsInserted();
255 void modelDestroyed();
256};
257
258class QCompletionModelPrivate : public QAbstractProxyModelPrivate
259{
260 Q_DECLARE_PUBLIC(QCompletionModel)
261};
262
263QT_END_NAMESPACE
264
265#endif // QCOMPLETER_P_H
266