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 Qt Virtual Keyboard module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <QtVirtualKeyboard/qvirtualkeyboardselectionlistmodel.h>
31#include <QtVirtualKeyboard/qvirtualkeyboardabstractinputmethod.h>
32#include <QtVirtualKeyboard/private/settings_p.h>
33#include <QtCore/private/qabstractitemmodel_p.h>
34#include <QtCore/qpointer.h>
35
36QT_BEGIN_NAMESPACE
37
38using namespace QtVirtualKeyboard;
39
40class QVirtualKeyboardSelectionListModelPrivate : public QAbstractItemModelPrivate
41{
42public:
43 QVirtualKeyboardSelectionListModelPrivate() :
44 QAbstractItemModelPrivate(),
45 dataSource(nullptr),
46 type(QVirtualKeyboardSelectionListModel::Type::WordCandidateList),
47 rowCount(0),
48 wclAutoCommitWord(false)
49 {
50 }
51
52 QHash<int, QByteArray> roles;
53 QPointer<QVirtualKeyboardAbstractInputMethod> dataSource;
54 QVirtualKeyboardSelectionListModel::Type type;
55 int rowCount;
56 bool wclAutoCommitWord;
57};
58
59/*!
60 \qmltype SelectionListModel
61 \instantiates QVirtualKeyboardSelectionListModel
62 \inqmlmodule QtQuick.VirtualKeyboard
63 \ingroup qtvirtualkeyboard-qml
64 \brief Provides a data model for the selection lists.
65
66 The SelectionListModel is a data model for word candidates
67 provided by the input method.
68
69 An instance of a SelectionListModel cannot be created directly.
70 Instead, the InputEngine manages the instances and provides
71 access to the model by InputEngine::wordCandidateListModel
72 property.
73
74 The model exposes the following data roles for the list delegate:
75 \list
76 \li \c display Display text for item.
77 \li \c wordCompletionLength Word completion length for item.
78 \li \c dictionaryType Dictionary type of the word, see QVirtualKeyboardSelectionListModel::DictionaryType.
79 \li \c canRemoveSuggestion A boolean indicating if the word can be removed from the dictionary.
80 \endlist
81
82 The activeItemChanged signal indicates which item is currently
83 highlighted by the input method. The view should respond to this
84 signal by highlighting the corresponding item in the list.
85
86 The user selection is handled by the selectItem() method. The view
87 should be invoke this method when the user selects an item from the
88 list.
89*/
90
91/*!
92 \class QVirtualKeyboardSelectionListModel
93
94 \inmodule QtVirtualKeyboard
95
96 \brief List model for selection lists.
97
98 This class acts as a bridge between the UI and the
99 input method that provides the data for selection
100 lists.
101*/
102
103/*!
104 \enum QVirtualKeyboardSelectionListModel::Type
105
106 This enum specifies the type of selection list.
107
108 \value WordCandidateList
109 Shows list of word candidates.
110*/
111
112/*!
113 \enum QVirtualKeyboardSelectionListModel::Role
114
115 This enum specifies a role of the data requested.
116
117 \value Display
118 The data to be rendered in form of text.
119 \value DisplayRole
120 \c obsolete Use Role::Display.
121 \value WordCompletionLength
122 An integer specifying the length of the word
123 the completion part expressed as the
124 number of characters counted from the
125 end of the string.
126 \value WordCompletionLengthRole
127 \c obsolete Use Role::WordCompletionLength.
128 \value Dictionary
129 An integer specifying \ l {QVirtualKeyboardSelectionListModel::DictionaryType}{dictionary type}.
130 \value CanRemoveSuggestion
131 A boolean value indicating if the word candidate
132 can be removed from the dictionary.
133*/
134
135/*!
136 \enum QVirtualKeyboardSelectionListModel::DictionaryType
137
138 This enum specifies the dictionary type of a word.
139
140 \value Default
141 The word candidate is from the default dictionary.
142 \value User
143 The word candidate is from the user dictionary.
144*/
145
146QVirtualKeyboardSelectionListModel::QVirtualKeyboardSelectionListModel(QObject *parent) :
147 QAbstractListModel(*new QVirtualKeyboardSelectionListModelPrivate(), parent)
148{
149 Q_D(QVirtualKeyboardSelectionListModel);
150 d->roles =
151 {{static_cast<int>(Role::Display), "display"},
152 {static_cast<int>(Role::WordCompletionLength), "wordCompletionLength"},
153 {static_cast<int>(Role::Dictionary), "dictionary"},
154 {static_cast<int>(Role::CanRemoveSuggestion), "canRemoveSuggestion"}};
155}
156
157/*!
158 \internal
159*/
160QVirtualKeyboardSelectionListModel::~QVirtualKeyboardSelectionListModel()
161{
162}
163
164/*!
165 \internal
166*/
167void QVirtualKeyboardSelectionListModel::setDataSource(QVirtualKeyboardAbstractInputMethod *dataSource, Type type)
168{
169 Q_D(QVirtualKeyboardSelectionListModel);
170 if (d->dataSource) {
171 disconnect(receiver: this, SLOT(selectionListChanged(Type)));
172 disconnect(receiver: this, SLOT(selectionListActiveItemChanged(Type, int)));
173 }
174 d->type = type;
175 if (d->dataSource) {
176 d->dataSource = nullptr;
177 selectionListChanged(type);
178 selectionListActiveItemChanged(type, index: -1);
179 }
180 d->dataSource = dataSource;
181 if (d->dataSource) {
182 QObject::connect(sender: d->dataSource.data(), signal: &QVirtualKeyboardAbstractInputMethod::selectionListChanged, receiver: this, slot: &QVirtualKeyboardSelectionListModel::selectionListChanged);
183 QObject::connect(sender: d->dataSource.data(), signal: &QVirtualKeyboardAbstractInputMethod::selectionListActiveItemChanged, receiver: this, slot: &QVirtualKeyboardSelectionListModel::selectionListActiveItemChanged);
184 }
185}
186
187/*!
188 \internal
189*/
190QVirtualKeyboardAbstractInputMethod *QVirtualKeyboardSelectionListModel::dataSource() const
191{
192 Q_D(const QVirtualKeyboardSelectionListModel);
193 return d->dataSource;
194}
195
196/*!
197 \internal
198*/
199int QVirtualKeyboardSelectionListModel::rowCount(const QModelIndex &parent) const
200{
201 Q_D(const QVirtualKeyboardSelectionListModel);
202 Q_UNUSED(parent)
203 return d->rowCount;
204}
205
206/*!
207 \internal
208*/
209QVariant QVirtualKeyboardSelectionListModel::data(const QModelIndex &index, int role) const
210{
211 Q_D(const QVirtualKeyboardSelectionListModel);
212 return d->dataSource ? d->dataSource->selectionListData(type: d->type, index: index.row(), role: static_cast<Role>(role)) : QVariant();
213}
214
215/*!
216 \internal
217*/
218QHash<int,QByteArray> QVirtualKeyboardSelectionListModel::roleNames() const
219{
220 Q_D(const QVirtualKeyboardSelectionListModel);
221 return d->roles;
222}
223
224/*!
225 \property QVirtualKeyboardSelectionListModel::count
226 \internal
227*/
228/*
229 \internal
230*/
231int QVirtualKeyboardSelectionListModel::count() const
232{
233 Q_D(const QVirtualKeyboardSelectionListModel);
234 return d->rowCount;
235}
236
237/*! \qmlmethod void SelectionListModel::selectItem(int index)
238
239 This method should be called when the user selects an item at position
240 \a index from the list.
241 The selection is forwarded to the input method for further processing.
242*/
243/*!
244 This method should be called when the user selects an item at position
245 \a index from the list.
246 The selection is forwarded to the input method for further processing.
247*/
248void QVirtualKeyboardSelectionListModel::selectItem(int index)
249{
250 Q_D(QVirtualKeyboardSelectionListModel);
251 if (index >= 0 && index < d->rowCount && d->dataSource) {
252 emit itemSelected(index);
253 d->dataSource->selectionListItemSelected(type: d->type, index);
254 }
255}
256
257/*!
258 \qmlmethod void SelectionListModel::removeItem(int index)
259
260 This method should be called when the user removes an item at position
261 \a index from the list.
262 The removal is forwarded to the input method for further processing.
263*/
264/*!
265 This method should be called when the user removes an item at position
266 \a index from the list.
267 The removal is forwarded to the input method for further processing.
268*/
269void QVirtualKeyboardSelectionListModel::removeItem(int index)
270{
271 Q_D(QVirtualKeyboardSelectionListModel);
272 if (index >= 0 && index < d->rowCount && d->dataSource) {
273 d->dataSource->selectionListRemoveItem(type: d->type, index);
274 }
275}
276
277/*!
278 * \internal
279 */
280QVariant QVirtualKeyboardSelectionListModel::dataAt(int index, QVirtualKeyboardSelectionListModel::Role role) const
281{
282 return data(index: this->index(row: index, column: 0), role: static_cast<int>(role));
283}
284
285/*!
286 \internal
287*/
288void QVirtualKeyboardSelectionListModel::selectionListChanged(QVirtualKeyboardSelectionListModel::Type type)
289{
290 Q_D(QVirtualKeyboardSelectionListModel);
291 if (static_cast<Type>(type) == d->type) {
292 int oldCount = d->rowCount;
293 int newCount = d->dataSource ? d->dataSource->selectionListItemCount(type: d->type) : 0;
294 if (newCount) {
295 int changedCount = qMin(a: oldCount, b: newCount);
296 if (changedCount)
297 emit dataChanged(topLeft: index(row: 0), bottomRight: index(row: changedCount - 1));
298 if (oldCount > newCount) {
299 beginRemoveRows(parent: QModelIndex(), first: newCount, last: oldCount - 1);
300 d->rowCount = newCount;
301 endRemoveRows();
302 } else if (oldCount < newCount) {
303 beginInsertRows(parent: QModelIndex(), first: oldCount, last: newCount - 1);
304 d->rowCount = newCount;
305 endInsertRows();
306 }
307 } else {
308 beginResetModel();
309 d->rowCount = 0;
310 endResetModel();
311 }
312 if (static_cast<QVirtualKeyboardSelectionListModel::Type>(type) == QVirtualKeyboardSelectionListModel::Type::WordCandidateList)
313 d->wclAutoCommitWord = ((oldCount > 1 || (oldCount == 1 && d->wclAutoCommitWord)) && newCount == 1 &&
314 Settings::instance()->wclAutoCommitWord() &&
315 dataAt(index: 0).toString().length() > 1);
316 if (d->rowCount != oldCount)
317 emit countChanged();
318 }
319}
320
321/*!
322 \internal
323*/
324void QVirtualKeyboardSelectionListModel::selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type type, int index)
325{
326 Q_D(QVirtualKeyboardSelectionListModel);
327 if (static_cast<Type>(type) == d->type && index < d->rowCount) {
328 emit activeItemChanged(index);
329 if (index == 0 && d->wclAutoCommitWord)
330 selectItem(index: 0);
331 }
332}
333
334/*!
335 \qmlsignal void SelectionListModel::activeItemChanged(int index)
336
337 This signal is emitted when the active item in the list changes. The
338 UI should react to this signal by highlighting the item at \a index in
339 the list.
340*/
341/*!
342 \fn void QVirtualKeyboardSelectionListModel::activeItemChanged(int index)
343
344 This signal is emitted when the active item in the list changes. The
345 UI should react to this signal by highlighting the item at \a index in
346 the list.
347*/
348
349/*!
350 \qmlsignal void SelectionListModel::itemSelected(int index)
351
352 This signal is emitted when an item at \a index is selected by the user.
353*/
354/*!
355 \fn void QVirtualKeyboardSelectionListModel::itemSelected(int index)
356
357 This signal is emitted when an item at \a index is selected by the user.
358*/
359
360QT_END_NAMESPACE
361

source code of qtvirtualkeyboard/src/virtualkeyboard/qvirtualkeyboardselectionlistmodel.cpp