Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include <QtVirtualKeyboard/qvirtualkeyboardselectionlistmodel.h>
++ #include <QtVirtualKeyboard/qvirtualkeyboardabstractinputmethod.h>
++ #include <QtVirtualKeyboard/private/settings_p.h>
++ #include <QtCore/private/qabstractitemmodel_p.h>
++ #include <QtCore/qpointer.h>
++
++ QT_BEGIN_NAMESPACE
++
++ using namespace QtVirtualKeyboard;
++
++ class QVirtualKeyboardSelectionListModelPrivate : public QAbstractItemModelPrivate
++ {
++ public:
++ QVirtualKeyboardSelectionListModelPrivate() :
++ QAbstractItemModelPrivate(),
++ dataSource(nullptr),
++ type(QVirtualKeyboardSelectionListModel::Type::WordCandidateList),
++ rowCount(0),
++ wclAutoCommitWord(false)
++ {
++ }
++
++ QHash<int, QByteArray> roles;
++ QPointer<QVirtualKeyboardAbstractInputMethod> dataSource;
++ QVirtualKeyboardSelectionListModel::Type type;
++ int rowCount;
++ bool wclAutoCommitWord;
++ };
++
++ /*!
++ \qmltype SelectionListModel
++ \nativetype QVirtualKeyboardSelectionListModel
++ \inqmlmodule QtQuick.VirtualKeyboard
++ \ingroup qtvirtualkeyboard-internal-qml
++ \brief Provides a data model for the selection lists.
++
++ The SelectionListModel is a data model for word candidates
++ provided by the input method.
++
++ An instance of a SelectionListModel cannot be created directly.
++ Instead, the InputEngine manages the instances and provides
++ access to the model by InputEngine::wordCandidateListModel
++ property.
++
++ The model exposes the following data roles for the list delegate:
++ \list
++ \li \c display Display text for item.
++ \li \c wordCompletionLength Word completion length for item.
++ \li \c dictionaryType Dictionary type of the word, see QVirtualKeyboardSelectionListModel::DictionaryType.
++ \li \c canRemoveSuggestion A boolean indicating if the word can be removed from the dictionary.
++ \endlist
++
++ The activeItemChanged signal indicates which item is currently
++ highlighted by the input method. The view should respond to this
++ signal by highlighting the corresponding item in the list.
++
++ The user selection is handled by the selectItem() method. The view
++ should be invoke this method when the user selects an item from the
++ list.
++ */
++
++ /*!
++ \class QVirtualKeyboardSelectionListModel
++
++ \inmodule QtVirtualKeyboard
++ \ingroup qtvirtualkeyboard-cpp-for-devs
++
++ \brief List model for selection lists.
++
++ This class acts as a bridge between the UI and the
++ input method that provides the data for selection
++ lists.
++ */
++
++ /*!
++ \enum QVirtualKeyboardSelectionListModel::Type
++
++ This enum specifies the type of selection list.
++
++ \value WordCandidateList
++ Shows list of word candidates.
++ */
++
++ /*!
++ \enum QVirtualKeyboardSelectionListModel::Role
++
++ This enum specifies a role of the data requested.
++
++ \value Display
++ The data to be rendered in form of text.
++ \value DisplayRole
++ \c obsolete Use Role::Display.
++ \value WordCompletionLength
++ An integer specifying the length of the word
++ the completion part expressed as the
++ number of characters counted from the
++ end of the string.
++ \value WordCompletionLengthRole
++ \c obsolete Use Role::WordCompletionLength.
++ \value Dictionary
++ An integer specifying \ l {QVirtualKeyboardSelectionListModel::DictionaryType}{dictionary type}.
++ \value CanRemoveSuggestion
++ A boolean value indicating if the word candidate
++ can be removed from the dictionary.
++ */
++
++ /*!
++ \enum QVirtualKeyboardSelectionListModel::DictionaryType
++
++ This enum specifies the dictionary type of a word.
++
++ \value Default
++ The word candidate is from the default dictionary.
++ \value User
++ The word candidate is from the user dictionary.
++ */
++
++ QVirtualKeyboardSelectionListModel::QVirtualKeyboardSelectionListModel(QObject *parent) :
++ QAbstractListModel(*new QVirtualKeyboardSelectionListModelPrivate(), parent)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ d->roles =
++ {{static_cast<int>(Role::Display), "display"},
++ {static_cast<int>(Role::WordCompletionLength), "wordCompletionLength"},
++ {static_cast<int>(Role::Dictionary), "dictionary"},
++ {static_cast<int>(Role::CanRemoveSuggestion), "canRemoveSuggestion"}};
++ }
++
++ /*!
++ \internal
++ */
++ QVirtualKeyboardSelectionListModel::~QVirtualKeyboardSelectionListModel()
++ {
++ }
++
++ /*!
++ \internal
++ */
++ void QVirtualKeyboardSelectionListModel::setDataSource(QVirtualKeyboardAbstractInputMethod *dataSource, Type type)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ if (d->dataSource) {
++ disconnect(this, SLOT(selectionListChanged(Type)));
++ disconnect(this, SLOT(selectionListActiveItemChanged(Type,int)));
++ disconnect(this, SLOT(dataSourceDestroyed()));
++ }
++ d->type = type;
++ if (d->dataSource) {
++ d->dataSource = nullptr;
++ selectionListChanged(type);
++ selectionListActiveItemChanged(type, -1);
++ }
++ d->dataSource = dataSource;
++ if (d->dataSource) {
++ QObject::connect(d->dataSource.data(), &QVirtualKeyboardAbstractInputMethod::selectionListChanged, this, &QVirtualKeyboardSelectionListModel::selectionListChanged);
++ QObject::connect(d->dataSource.data(), &QVirtualKeyboardAbstractInputMethod::selectionListActiveItemChanged, this, &QVirtualKeyboardSelectionListModel::selectionListActiveItemChanged);
++ QObject::connect(d->dataSource.data(), &QObject::destroyed, this, &QVirtualKeyboardSelectionListModel::dataSourceDestroyed);
++ }
++ }
++
++ /*!
++ \internal
++ */
++ QVirtualKeyboardAbstractInputMethod *QVirtualKeyboardSelectionListModel::dataSource() const
++ {
++ Q_D(const QVirtualKeyboardSelectionListModel);
++ return d->dataSource;
++ }
++
++ /*!
++ \internal
++ */
++ int QVirtualKeyboardSelectionListModel::rowCount(const QModelIndex &parent) const
++ {
++ Q_D(const QVirtualKeyboardSelectionListModel);
++ Q_UNUSED(parent);
++ return d->rowCount;
++ }
++
++ /*!
++ \internal
++ */
++ QVariant QVirtualKeyboardSelectionListModel::data(const QModelIndex &index, int role) const
++ {
++ Q_D(const QVirtualKeyboardSelectionListModel);
++
++ if (!d->dataSource)
++ return QVariant();
++
++ if (index.row() < 0 || index.row() >= d->rowCount)
++ return QVariant();
++
++ return d->dataSource->selectionListData(d->type, index.row(), static_cast<Role>(role));
++ }
++
++ /*!
++ \internal
++ */
++ QHash<int,QByteArray> QVirtualKeyboardSelectionListModel::roleNames() const
++ {
++ Q_D(const QVirtualKeyboardSelectionListModel);
++ return d->roles;
++ }
++
++ /*!
++ \property QVirtualKeyboardSelectionListModel::count
++ \internal
++ */
++ /*!
++ \internal
++ */
++ int QVirtualKeyboardSelectionListModel::count() const
++ {
++ Q_D(const QVirtualKeyboardSelectionListModel);
++ return d->rowCount;
++ }
++
++ /*! \qmlmethod void SelectionListModel::selectItem(int index)
++
++ This method should be called when the user selects an item at position
++ \a index from the list.
++ The selection is forwarded to the input method for further processing.
++ */
++ /*!
++ This method should be called when the user selects an item at position
++ \a index from the list.
++ The selection is forwarded to the input method for further processing.
++ */
++ void QVirtualKeyboardSelectionListModel::selectItem(int index)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ if (index >= 0 && index < d->rowCount && d->dataSource) {
++ emit itemSelected(index);
++ d->dataSource->selectionListItemSelected(d->type, index);
++ }
++ }
++
++ /*!
++ \qmlmethod void SelectionListModel::removeItem(int index)
++
++ This method should be called when the user removes an item at position
++ \a index from the list.
++ The removal is forwarded to the input method for further processing.
++ */
++ /*!
++ This method should be called when the user removes an item at position
++ \a index from the list.
++ The removal is forwarded to the input method for further processing.
++ */
++ void QVirtualKeyboardSelectionListModel::removeItem(int index)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ if (index >= 0 && index < d->rowCount && d->dataSource) {
++ d->dataSource->selectionListRemoveItem(d->type, index);
++ }
++ }
++
++ /*!
++ * \internal
++ */
++ QVariant QVirtualKeyboardSelectionListModel::dataAt(int index, QVirtualKeyboardSelectionListModel::Role role) const
++ {
++ return data(this->index(index, 0), static_cast<int>(role));
++ }
++
++ /*!
++ \internal
++ */
++ void QVirtualKeyboardSelectionListModel::selectionListChanged(QVirtualKeyboardSelectionListModel::Type type)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ if (static_cast<Type>(type) == d->type) {
++ int oldCount = d->rowCount;
++ int newCount = d->dataSource ? d->dataSource->selectionListItemCount(d->type) : 0;
++ if (newCount) {
++ int changedCount = qMin(oldCount, newCount);
++ if (changedCount)
++ emit dataChanged(index(0), index(changedCount - 1));
++ if (oldCount > newCount) {
++ beginRemoveRows(QModelIndex(), newCount, oldCount - 1);
++ d->rowCount = newCount;
++ endRemoveRows();
++ } else if (oldCount < newCount) {
++ beginInsertRows(QModelIndex(), oldCount, newCount - 1);
++ d->rowCount = newCount;
++ endInsertRows();
++ }
++ } else {
++ beginResetModel();
++ d->rowCount = 0;
++ endResetModel();
++ }
++ if (static_cast<QVirtualKeyboardSelectionListModel::Type>(type) == QVirtualKeyboardSelectionListModel::Type::WordCandidateList)
++ d->wclAutoCommitWord = ((oldCount > 1 || (oldCount == 1 && d->wclAutoCommitWord)) && newCount == 1 &&
++ Settings::instance()->wclAutoCommitWord() &&
++ dataAt(0).toString().size() > 1);
++ if (d->rowCount != oldCount)
++ emit countChanged();
++ }
++ }
++
++ /*!
++ \internal
++ */
++ void QVirtualKeyboardSelectionListModel::selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type type, int index)
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ if (static_cast<Type>(type) == d->type && index < d->rowCount) {
++ emit activeItemChanged(index);
++ if (index == 0 && d->wclAutoCommitWord)
++ selectItem(0);
++ }
++ }
++
++ /*!
++ \internal
++ */
++ void QVirtualKeyboardSelectionListModel::dataSourceDestroyed()
++ {
++ Q_D(QVirtualKeyboardSelectionListModel);
++ selectionListChanged(d->type);
++ selectionListActiveItemChanged(d->type, -1);
++ }
++
++ /*!
++ \qmlsignal void SelectionListModel::activeItemChanged(int index)
++
++ This signal is emitted when the active item in the list changes. The
++ UI should react to this signal by highlighting the item at \a index in
++ the list.
++ */
++ /*!
++ \fn void QVirtualKeyboardSelectionListModel::activeItemChanged(int index)
++
++ This signal is emitted when the active item in the list changes. The
++ UI should react to this signal by highlighting the item at \a index in
++ the list.
++ */
++
++ /*!
++ \qmlsignal void SelectionListModel::itemSelected(int index)
++
++ This signal is emitted when an item at \a index is selected by the user.
++ */
++ /*!
++ \fn void QVirtualKeyboardSelectionListModel::itemSelected(int index)
++
++ This signal is emitted when an item at \a index is selected by the user.
++ */
++
++ QT_END_NAMESPACE