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 65 QT_REQUIRE_CONFIG(completer); 66 67 QT_BEGIN_NAMESPACE 68 69 class QCompletionModel; 70 71 class QCompleterPrivate : public QObjectPrivate 72 { 73 Q_DECLARE_PUBLIC(QCompleter) 74 75 public: 76 QCompleterPrivate(); ~QCompleterPrivate()77 ~QCompleterPrivate() { delete popup; } 78 void init(QAbstractItemModel *model = nullptr); 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 get(QCompleter * o)105 static QCompleterPrivate *get(QCompleter *o) { return o->d_func(); } get(const QCompleter * o)106 static const QCompleterPrivate *get(const QCompleter *o) { return o->d_func(); } 107 }; 108 109 class QIndexMapper 110 { 111 public: QIndexMapper()112 QIndexMapper() : v(false), f(0), t(-1) { } QIndexMapper(int f,int t)113 QIndexMapper(int f, int t) : v(false), f(f), t(t) { } QIndexMapper(const QVector<int> & vec)114 QIndexMapper(const QVector<int> &vec) : v(true), vector(vec), f(-1), t(-1) { } 115 count()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; } indexOf(int x)118 inline int indexOf(int x) const { return v ? vector.indexOf(x) : ((t < f) ? -1 : x - f); } isValid()119 inline bool isValid() const { return !isEmpty(); } isEmpty()120 inline bool isEmpty() const { return v ? vector.isEmpty() : (t < f); } append(int x)121 inline void append(int x) { Q_ASSERT(v); vector.append(x); } first()122 inline int first() const { return v ? vector.first() : f; } last()123 inline int last() const { return v ? vector.last() : t; } from()124 inline int from() const { Q_ASSERT(!v); return f; } to()125 inline int to() const { Q_ASSERT(!v); return t; } cost()126 inline int cost() const { return vector.count()+2; } 127 128 private: 129 bool v; 130 QVector<int> vector; 131 int f, t; 132 }; 133 134 struct QMatchData { QMatchDataQMatchData135 QMatchData() : exactMatchIndex(-1), partial(false) { } QMatchDataQMatchData136 QMatchData(const QIndexMapper& indices, int em, bool p) : 137 indices(indices), exactMatchIndex(em), partial(p) { } 138 QIndexMapper indices; isValidQMatchData139 inline bool isValid() const { return indices.isValid(); } 140 int exactMatchIndex; 141 bool partial; 142 }; 143 144 class QCompletionEngine 145 { 146 public: 147 typedef QMap<QString, QMatchData> CacheItem; 148 typedef QMap<QModelIndex, CacheItem> Cache; 149 QCompletionEngine(QCompleterPrivate * c)150 QCompletionEngine(QCompleterPrivate *c) : c(c), curRow(-1), cost(0) { } ~QCompletionEngine()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 filterOnDemand(int)161 virtual void filterOnDemand(int) { } 162 virtual QMatchData filter(const QString&, const QModelIndex&, int) = 0; 163 matchCount()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 176 class QSortedModelEngine : public QCompletionEngine 177 { 178 public: QSortedModelEngine(QCompleterPrivate * c)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 185 class QUnsortedModelEngine : public QCompletionEngine 186 { 187 public: QUnsortedModelEngine(QCompleterPrivate * c)188 QUnsortedModelEngine(QCompleterPrivate *c) : QCompletionEngine(c) { } 189 190 void filterOnDemand(int) override; 191 QMatchData filter(const QString&, const QModelIndex&, int) override; 192 private: 193 int buildIndices(const QString& str, const QModelIndex& parent, int n, 194 const QIndexMapper& iv, QMatchData* m); 195 }; 196 197 // ### Qt6: QStyledItemDelegate 198 class QCompleterItemDelegate : public QItemDelegate 199 { 200 public: QCompleterItemDelegate(QAbstractItemView * view)201 QCompleterItemDelegate(QAbstractItemView *view) 202 : QItemDelegate(view), view(view) { } paint(QPainter * p,const QStyleOptionViewItem & opt,const QModelIndex & idx)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 211 private: 212 QAbstractItemView *view; 213 }; 214 215 class QCompletionModelPrivate; 216 217 class QCompletionModel : public QAbstractProxyModel 218 { 219 Q_OBJECT 220 221 public: 222 QCompletionModel(QCompleterPrivate *c, QObject *parent); 223 224 void createEngine(); 225 void setFiltered(bool); 226 void filter(const QStringList& parts); 227 int completionCount() const; currentRow()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 249 signals: 250 void rowsAdded(); 251 252 public Q_SLOTS: 253 void invalidate(); 254 void rowsInserted(); 255 void modelDestroyed(); 256 }; 257 258 class QCompletionModelPrivate : public QAbstractProxyModelPrivate 259 { 260 Q_DECLARE_PUBLIC(QCompletionModel) 261 }; 262 263 QT_END_NAMESPACE 264 265 #endif // QCOMPLETER_P_H 266