796 lines
21 KiB
C++
796 lines
21 KiB
C++
|
/****************************************************************************
|
||
|
**
|
||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||
|
** Contact: http://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the Qt Labs Templates module of the Qt Toolkit.
|
||
|
**
|
||
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||
|
** Commercial License Usage
|
||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||
|
** accordance with the commercial license agreement provided with the
|
||
|
** Software or, alternatively, in accordance with the terms contained in
|
||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||
|
**
|
||
|
** GNU Lesser General Public License Usage
|
||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||
|
** General Public License version 3 as published by the Free Software
|
||
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||
|
** packaging of this file. Please review the following information to
|
||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||
|
**
|
||
|
** GNU General Public License Usage
|
||
|
** Alternatively, this file may be used under the terms of the GNU
|
||
|
** General Public License version 2.0 or later as published by the Free
|
||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||
|
** the packaging of this file. Please review the following information to
|
||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||
|
**
|
||
|
** $QT_END_LICENSE$
|
||
|
**
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "qquickcombobox_p.h"
|
||
|
#include "qquickcontrol_p_p.h"
|
||
|
#include "qquickabstractbutton_p.h"
|
||
|
#include "qquickpanel_p.h"
|
||
|
|
||
|
#include <QtCore/qregexp.h>
|
||
|
#include <QtQml/qjsvalue.h>
|
||
|
#include <QtQml/qqmlcontext.h>
|
||
|
#include <QtQml/private/qqmldelegatemodel_p.h>
|
||
|
#include <QtQuick/private/qquickevents_p_p.h>
|
||
|
|
||
|
QT_BEGIN_NAMESPACE
|
||
|
|
||
|
/*!
|
||
|
\qmltype ComboBox
|
||
|
\inherits Control
|
||
|
\instantiates QQuickComboBox
|
||
|
\inqmlmodule Qt.labs.controls
|
||
|
\ingroup qtlabscontrols-input
|
||
|
\brief A combo box control.
|
||
|
|
||
|
\image qtlabscontrols-combobox.png
|
||
|
|
||
|
ComboBox is a combined button and popup list. It provides a means of
|
||
|
presenting a list of options to the user in a way that takes up the
|
||
|
minimum amount of screen space.
|
||
|
|
||
|
ComboBox is populated with a data model. The data model is commonly
|
||
|
a JavaScript array, a \l ListModel or an integer, but also other types
|
||
|
of \l {qml-data-models}{data models} are supported.
|
||
|
|
||
|
\code
|
||
|
ComboBox {
|
||
|
model: ["First", "Second", "Third"]
|
||
|
}
|
||
|
\endcode
|
||
|
|
||
|
ComboBox is able to visualize standard \l {qml-data-models}{data models}
|
||
|
that provide the \c modelData role:
|
||
|
\list
|
||
|
\li models that have only one role
|
||
|
\li models that do not have named roles (JavaScript array, integer)
|
||
|
\endlist
|
||
|
|
||
|
When using models that have multiple named roles, ComboBox must be configured
|
||
|
to use a specific \l {textRole}{text role} for its \l {displayText}{display text}
|
||
|
and \l delegate instances.
|
||
|
|
||
|
\code
|
||
|
ComboBox {
|
||
|
textRole: "key"
|
||
|
model: ListModel {
|
||
|
ListElement { key: "First"; value: 123 }
|
||
|
ListElement { key: "Second"; value: 456 }
|
||
|
ListElement { key: "Third"; value: 789 }
|
||
|
}
|
||
|
}
|
||
|
\endcode
|
||
|
|
||
|
\note If ComboBox is assigned a data model that has multiple named roles, but
|
||
|
\l textRole is not defined, ComboBox is unable to visualize it and throws a
|
||
|
\c {ReferenceError: modelData is not defined}.
|
||
|
|
||
|
\sa {Customizing ComboBox}, {Input Controls}
|
||
|
*/
|
||
|
|
||
|
/*!
|
||
|
\qmlsignal void Qt.labs.controls::ComboBox::activated(int index)
|
||
|
|
||
|
This signal is emitted when the item at \a index is activated by the user.
|
||
|
|
||
|
\sa currentIndex
|
||
|
*/
|
||
|
|
||
|
/*!
|
||
|
\qmlsignal void Qt.labs.controls::ComboBox::highlighted(int index)
|
||
|
|
||
|
This signal is emitted when the item at \a index in the popup list is highlighted by the user.
|
||
|
|
||
|
\sa highlightedIndex
|
||
|
*/
|
||
|
|
||
|
class QQuickComboBoxPrivate : public QQuickControlPrivate
|
||
|
{
|
||
|
Q_DECLARE_PUBLIC(QQuickComboBox)
|
||
|
|
||
|
public:
|
||
|
QQuickComboBoxPrivate() : pressed(false), ownModel(false), hasDisplayText(false),
|
||
|
hideTimer(0), highlightedIndex(-1), currentIndex(-1), delegateModel(Q_NULLPTR),
|
||
|
delegate(Q_NULLPTR), panel(Q_NULLPTR) { }
|
||
|
|
||
|
bool isPanelVisible() const;
|
||
|
void showPanel();
|
||
|
void hidePanel(bool accept);
|
||
|
void togglePanel(bool accept);
|
||
|
|
||
|
void pressedOutside();
|
||
|
void itemClicked();
|
||
|
|
||
|
void initItem(int index, QObject *object);
|
||
|
void countChanged();
|
||
|
void updateCurrentText();
|
||
|
void increase();
|
||
|
void decrease();
|
||
|
void setHighlightedIndex(int index);
|
||
|
|
||
|
void createDelegateModel();
|
||
|
|
||
|
bool pressed;
|
||
|
bool ownModel;
|
||
|
bool hasDisplayText;
|
||
|
int hideTimer;
|
||
|
int highlightedIndex;
|
||
|
int currentIndex;
|
||
|
QVariant model;
|
||
|
QString textRole;
|
||
|
QString currentText;
|
||
|
QString displayText;
|
||
|
QQuickItem *pressedItem;
|
||
|
QQmlInstanceModel *delegateModel;
|
||
|
QQmlComponent *delegate;
|
||
|
QQuickPanel *panel;
|
||
|
};
|
||
|
|
||
|
bool QQuickComboBoxPrivate::isPanelVisible() const
|
||
|
{
|
||
|
return panel && panel->isVisible();
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::showPanel()
|
||
|
{
|
||
|
if (panel && !panel->isVisible())
|
||
|
panel->show();
|
||
|
setHighlightedIndex(currentIndex);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::hidePanel(bool accept)
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (panel && panel->isVisible())
|
||
|
panel->hide();
|
||
|
if (accept) {
|
||
|
q->setCurrentIndex(highlightedIndex);
|
||
|
emit q->activated(currentIndex);
|
||
|
}
|
||
|
setHighlightedIndex(-1);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::togglePanel(bool accept)
|
||
|
{
|
||
|
if (!panel)
|
||
|
return;
|
||
|
|
||
|
if (panel->isVisible())
|
||
|
hidePanel(accept);
|
||
|
else
|
||
|
showPanel();
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::pressedOutside()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (hideTimer <= 0)
|
||
|
hideTimer = q->startTimer(0);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::itemClicked()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
int index = delegateModel->indexOf(q->sender(), Q_NULLPTR);
|
||
|
if (index != -1) {
|
||
|
setHighlightedIndex(index);
|
||
|
emit q->highlighted(index);
|
||
|
hidePanel(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::initItem(int index, QObject *object)
|
||
|
{
|
||
|
QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object);
|
||
|
if (button)
|
||
|
connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
|
||
|
|
||
|
if (index == currentIndex)
|
||
|
updateCurrentText();
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::countChanged()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (q->count() == 0)
|
||
|
q->setCurrentIndex(-1);
|
||
|
emit q->countChanged();
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::updateCurrentText()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
QString text = q->textAt(currentIndex);
|
||
|
if (currentText != text) {
|
||
|
currentText = text;
|
||
|
emit q->currentTextChanged();
|
||
|
}
|
||
|
if (!hasDisplayText && displayText != text) {
|
||
|
displayText = text;
|
||
|
emit q->displayTextChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::increase()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (isPanelVisible()) {
|
||
|
if (highlightedIndex < q->count() - 1) {
|
||
|
setHighlightedIndex(highlightedIndex + 1);
|
||
|
emit q->highlighted(highlightedIndex);
|
||
|
}
|
||
|
} else {
|
||
|
if (currentIndex < q->count() - 1) {
|
||
|
q->setCurrentIndex(currentIndex + 1);
|
||
|
emit q->activated(currentIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::decrease()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (isPanelVisible()) {
|
||
|
if (highlightedIndex > 0) {
|
||
|
setHighlightedIndex(highlightedIndex - 1);
|
||
|
emit q->highlighted(highlightedIndex);
|
||
|
}
|
||
|
} else {
|
||
|
if (currentIndex > 0) {
|
||
|
q->setCurrentIndex(currentIndex - 1);
|
||
|
emit q->activated(currentIndex);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::setHighlightedIndex(int index)
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (highlightedIndex != index) {
|
||
|
highlightedIndex = index;
|
||
|
emit q->highlightedIndexChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBoxPrivate::createDelegateModel()
|
||
|
{
|
||
|
Q_Q(QQuickComboBox);
|
||
|
if (delegateModel) {
|
||
|
if (ownModel) {
|
||
|
delete delegateModel;
|
||
|
} else {
|
||
|
disconnect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
|
||
|
disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
|
||
|
disconnect(delegateModel, &QQmlInstanceModel::initItem, this, &QQuickComboBoxPrivate::initItem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ownModel = false;
|
||
|
delegateModel = model.value<QQmlInstanceModel *>();
|
||
|
|
||
|
if (!delegateModel && model.isValid()) {
|
||
|
QQmlDelegateModel *dataModel = new QQmlDelegateModel(qmlContext(q), q);
|
||
|
dataModel->setModel(model);
|
||
|
dataModel->setDelegate(delegate);
|
||
|
if (q->isComponentComplete())
|
||
|
dataModel->componentComplete();
|
||
|
|
||
|
ownModel = true;
|
||
|
delegateModel = dataModel;
|
||
|
}
|
||
|
|
||
|
if (delegateModel) {
|
||
|
connect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
|
||
|
connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
|
||
|
connect(delegateModel, &QQmlInstanceModel::initItem, this, &QQuickComboBoxPrivate::initItem);
|
||
|
}
|
||
|
|
||
|
emit q->delegateModelChanged();
|
||
|
}
|
||
|
|
||
|
QQuickComboBox::QQuickComboBox(QQuickItem *parent) :
|
||
|
QQuickControl(*(new QQuickComboBoxPrivate), parent)
|
||
|
{
|
||
|
setActiveFocusOnTab(true);
|
||
|
setFlag(QQuickItem::ItemIsFocusScope);
|
||
|
setAcceptedMouseButtons(Qt::LeftButton);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\readonly
|
||
|
\qmlproperty int Qt.labs.controls::ComboBox::count
|
||
|
|
||
|
This property holds the number of items in the combo box.
|
||
|
*/
|
||
|
int QQuickComboBox::count() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->delegateModel ? d->delegateModel->count() : 0;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty model Qt.labs.controls::ComboBox::model
|
||
|
|
||
|
This property holds the model providing data for the combo box.
|
||
|
|
||
|
\code
|
||
|
ComboBox {
|
||
|
textRole: "key"
|
||
|
model: ListModel {
|
||
|
ListElement { key: "First"; value: 123 }
|
||
|
ListElement { key: "Second"; value: 456 }
|
||
|
ListElement { key: "Third"; value: 789 }
|
||
|
}
|
||
|
}
|
||
|
\endcode
|
||
|
|
||
|
\sa textRole, {qml-data-models}{Data Models}
|
||
|
*/
|
||
|
QVariant QQuickComboBox::model() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->model;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setModel(const QVariant& m)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QVariant model = m;
|
||
|
if (model.userType() == qMetaTypeId<QJSValue>())
|
||
|
model = model.value<QJSValue>().toVariant();
|
||
|
|
||
|
if (d->model != model) {
|
||
|
d->model = model;
|
||
|
d->createDelegateModel();
|
||
|
if (isComponentComplete()) {
|
||
|
setCurrentIndex(count() > 0 ? 0 : -1);
|
||
|
d->updateCurrentText();
|
||
|
}
|
||
|
emit modelChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\internal
|
||
|
\qmlproperty model Qt.labs.controls::ComboBox::delegateModel
|
||
|
|
||
|
This property holds the model providing delegate instances for the combo box.
|
||
|
*/
|
||
|
QQmlInstanceModel *QQuickComboBox::delegateModel() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->delegateModel;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty bool Qt.labs.controls::ComboBox::pressed
|
||
|
|
||
|
This property holds whether the combo box button is pressed.
|
||
|
*/
|
||
|
bool QQuickComboBox::isPressed() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->pressed;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setPressed(bool pressed)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->pressed != pressed) {
|
||
|
d->pressed = pressed;
|
||
|
emit pressedChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty int Qt.labs.controls::ComboBox::highlightedIndex
|
||
|
|
||
|
This property holds the index of the highlighted item in the combo box popup list.
|
||
|
|
||
|
\sa highlighted(), currentIndex
|
||
|
*/
|
||
|
int QQuickComboBox::highlightedIndex() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->highlightedIndex;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty int Qt.labs.controls::ComboBox::currentIndex
|
||
|
|
||
|
This property holds the index of the current item in the combo box.
|
||
|
|
||
|
\sa activated(), currentText
|
||
|
*/
|
||
|
int QQuickComboBox::currentIndex() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->currentIndex;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setCurrentIndex(int index)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->currentIndex != index) {
|
||
|
d->currentIndex = index;
|
||
|
emit currentIndexChanged();
|
||
|
if (isComponentComplete())
|
||
|
d->updateCurrentText();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\readonly
|
||
|
\qmlproperty string Qt.labs.controls::ComboBox::currentText
|
||
|
|
||
|
This property holds the text of the current item in the combo box.
|
||
|
|
||
|
\sa currentIndex, displayText, textRole
|
||
|
*/
|
||
|
QString QQuickComboBox::currentText() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->currentText;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty string Qt.labs.controls::ComboBox::displayText
|
||
|
|
||
|
This property holds the text that is displayed on the combo box button.
|
||
|
|
||
|
By default, the display text presents the current selection. That is,
|
||
|
it follows the text of the current item. However, the default display
|
||
|
text can be overridden with a custom value.
|
||
|
|
||
|
\code
|
||
|
ComboBox {
|
||
|
currentIndex: 1
|
||
|
displayText: "Size: " + currentText
|
||
|
model: ["S", "M", "L"]
|
||
|
}
|
||
|
\endcode
|
||
|
|
||
|
\sa currentText, textRole
|
||
|
*/
|
||
|
QString QQuickComboBox::displayText() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->displayText;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setDisplayText(const QString &text)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
d->hasDisplayText = true;
|
||
|
if (d->displayText != text) {
|
||
|
d->displayText = text;
|
||
|
emit displayTextChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::resetDisplayText()
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->hasDisplayText) {
|
||
|
d->hasDisplayText = false;
|
||
|
d->updateCurrentText();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty string Qt.labs.controls::ComboBox::textRole
|
||
|
|
||
|
This property holds the model role used for populating the combo box.
|
||
|
|
||
|
\sa model, currentText, displayText
|
||
|
*/
|
||
|
QString QQuickComboBox::textRole() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->textRole;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setTextRole(const QString &role)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->textRole != role) {
|
||
|
d->textRole = role;
|
||
|
if (isComponentComplete())
|
||
|
d->updateCurrentText();
|
||
|
emit textRoleChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty Component Qt.labs.controls::ComboBox::delegate
|
||
|
|
||
|
This property holds a delegate that presents an item in the combo box popup.
|
||
|
|
||
|
\sa ItemDelegate, {Customizing ComboBox}
|
||
|
*/
|
||
|
QQmlComponent *QQuickComboBox::delegate() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->delegate;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setDelegate(QQmlComponent* delegate)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->delegate != delegate) {
|
||
|
delete d->delegate;
|
||
|
d->delegate = delegate;
|
||
|
QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->delegateModel);
|
||
|
if (delegateModel)
|
||
|
delegateModel->setDelegate(d->delegate);
|
||
|
emit delegateChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlproperty Panel Qt.labs.controls::ComboBox::panel
|
||
|
|
||
|
This property holds the popup panel.
|
||
|
|
||
|
\sa {Customizing ComboBox}
|
||
|
*/
|
||
|
QQuickPanel *QQuickComboBox::panel() const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
return d->panel;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::setPanel(QQuickPanel *panel)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
if (d->panel != panel) {
|
||
|
delete d->panel;
|
||
|
if (panel)
|
||
|
QObjectPrivate::connect(panel, &QQuickPanel::pressedOutside, d, &QQuickComboBoxPrivate::pressedOutside);
|
||
|
d->panel = panel;
|
||
|
emit panelChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlmethod string Qt.labs.controls::ComboBox::textAt(int index)
|
||
|
|
||
|
Returns the text for the specified \a index, or an empty string
|
||
|
if the index is out of bounds.
|
||
|
|
||
|
\sa textRole
|
||
|
*/
|
||
|
QString QQuickComboBox::textAt(int index) const
|
||
|
{
|
||
|
Q_D(const QQuickComboBox);
|
||
|
if (!d->delegateModel || index < 0 || index >= d->delegateModel->count())
|
||
|
return QString();
|
||
|
return d->delegateModel->stringValue(index, d->textRole.isEmpty() ? QStringLiteral("modelData") : d->textRole);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\qmlmethod int Qt.labs.controls::ComboBox::find(string text, flags = Qt.MatchExactly)
|
||
|
|
||
|
Returns the index of the specified \a text, or \c -1 if no match is found.
|
||
|
|
||
|
The way the search is performed is defined by the specified match \a flags. By default,
|
||
|
combo box performs case sensitive exact matching (\c Qt.MatchExactly). All other match
|
||
|
types are case-insensitive unless the \c Qt.MatchCaseSensitive flag is also specified.
|
||
|
|
||
|
\value Qt.MatchExactly The search term matches exactly (default).
|
||
|
\value Qt.MatchRegExp The search term matches as a regular expression.
|
||
|
\value Qt.MatchWildcard The search term matches using wildcards.
|
||
|
\value Qt.MatchFixedString The search term matches as a fixed string.
|
||
|
\value Qt.MatchStartsWith The search term matches the start of the item.
|
||
|
\value Qt.MatchEndsWidth The search term matches the end of the item.
|
||
|
\value Qt.MatchContains The search term is contained in the item.
|
||
|
\value Qt.MatchCaseSensitive The search is case sensitive.
|
||
|
|
||
|
\sa textRole
|
||
|
*/
|
||
|
int QQuickComboBox::find(const QString &text, Qt::MatchFlags flags) const
|
||
|
{
|
||
|
int itemCount = count();
|
||
|
uint matchType = flags & 0x0F;
|
||
|
Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||
|
|
||
|
for (int idx = 0; idx < itemCount; ++idx) {
|
||
|
QString t = textAt(idx);
|
||
|
switch (matchType) {
|
||
|
case Qt::MatchExactly:
|
||
|
if (t == text)
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchRegExp:
|
||
|
if (QRegExp(text, cs).exactMatch(t))
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchWildcard:
|
||
|
if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchStartsWith:
|
||
|
if (t.startsWith(text, cs))
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchEndsWith:
|
||
|
if (t.endsWith(text, cs))
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchFixedString:
|
||
|
if (t.compare(text, cs) == 0)
|
||
|
return idx;
|
||
|
break;
|
||
|
case Qt::MatchContains:
|
||
|
default:
|
||
|
if (t.contains(text, cs))
|
||
|
return idx;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::focusOutEvent(QFocusEvent *event)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickItem::focusOutEvent(event);
|
||
|
d->hidePanel(false);
|
||
|
setPressed(false);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::keyPressEvent(QKeyEvent *event)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickControl::keyPressEvent(event);
|
||
|
if (!d->panel)
|
||
|
return;
|
||
|
|
||
|
switch (event->key()) {
|
||
|
case Qt::Key_Space:
|
||
|
if (!event->isAutoRepeat())
|
||
|
setPressed(true);
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Enter:
|
||
|
case Qt::Key_Return:
|
||
|
if (d->isPanelVisible())
|
||
|
setPressed(true);
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Up:
|
||
|
d->decrease();
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Down:
|
||
|
d->increase();
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Escape:
|
||
|
event->accept();
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::keyReleaseEvent(QKeyEvent *event)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickControl::keyReleaseEvent(event);
|
||
|
if (!d->panel || event->isAutoRepeat())
|
||
|
return;
|
||
|
|
||
|
switch (event->key()) {
|
||
|
case Qt::Key_Space:
|
||
|
d->togglePanel(true);
|
||
|
setPressed(false);
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Enter:
|
||
|
case Qt::Key_Return:
|
||
|
d->hidePanel(true);
|
||
|
setPressed(false);
|
||
|
event->accept();
|
||
|
break;
|
||
|
case Qt::Key_Escape:
|
||
|
d->hidePanel(false);
|
||
|
setPressed(false);
|
||
|
event->accept();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::mousePressEvent(QMouseEvent *event)
|
||
|
{
|
||
|
QQuickControl::mousePressEvent(event);
|
||
|
setPressed(true);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::mouseMoveEvent(QMouseEvent* event)
|
||
|
{
|
||
|
QQuickControl::mouseMoveEvent(event);
|
||
|
setPressed(contains(event->pos()));
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::mouseReleaseEvent(QMouseEvent *event)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickControl::mouseReleaseEvent(event);
|
||
|
if (d->pressed) {
|
||
|
setPressed(false);
|
||
|
if (!d->isPanelVisible())
|
||
|
forceActiveFocus(Qt::MouseFocusReason);
|
||
|
d->togglePanel(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::mouseUngrabEvent()
|
||
|
{
|
||
|
QQuickControl::mouseUngrabEvent();
|
||
|
setPressed(false);
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::timerEvent(QTimerEvent *event)
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickControl::timerEvent(event);
|
||
|
if (event->timerId() == d->hideTimer) {
|
||
|
killTimer(d->hideTimer);
|
||
|
d->hideTimer = 0;
|
||
|
if (!d->pressed)
|
||
|
d->hidePanel(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QQuickComboBox::componentComplete()
|
||
|
{
|
||
|
Q_D(QQuickComboBox);
|
||
|
QQuickControl::componentComplete();
|
||
|
|
||
|
if (d->delegateModel && d->ownModel)
|
||
|
static_cast<QQmlDelegateModel *>(d->delegateModel)->componentComplete();
|
||
|
|
||
|
if (count() > 0) {
|
||
|
if (d->currentIndex == -1)
|
||
|
setCurrentIndex(0);
|
||
|
else
|
||
|
d->updateCurrentText();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QT_END_NAMESPACE
|