diff options
Diffstat (limited to 'src/quicktemplates2/qquickcombobox.cpp')
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 1970 |
1 files changed, 0 insertions, 1970 deletions
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp deleted file mode 100644 index 85f135c7..00000000 --- a/src/quicktemplates2/qquickcombobox.cpp +++ /dev/null @@ -1,1970 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Templates 2 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 "qquickabstractbutton_p_p.h" -#include "qquickpopup_p_p.h" -#include "qquickdeferredexecute_p_p.h" - -#include <QtCore/qregularexpression.h> -#include <QtCore/qabstractitemmodel.h> -#include <QtCore/qglobal.h> -#include <QtGui/qinputmethod.h> -#include <QtGui/qguiapplication.h> -#include <QtGui/qpa/qplatformtheme.h> -#include <QtQml/qjsvalue.h> -#include <QtQml/qqmlcontext.h> -#include <QtQml/private/qlazilyallocated_p.h> -#include <private/qqmldelegatemodel_p.h> -#include <QtQuick/private/qquickaccessibleattached_p.h> -#include <QtQuick/private/qquickevents_p_p.h> -#include <QtQuick/private/qquicktextinput_p.h> -#include <QtQuick/private/qquickitemview_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmltype ComboBox - \inherits Control -//! \instantiates QQuickComboBox - \inqmlmodule QtQuick.Controls - \since 5.7 - \ingroup qtquickcontrols2-input - \ingroup qtquickcontrols2-focusscopes - \brief Combined button and popup list for selecting options. - - \image qtquickcontrols2-combobox.gif - - 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 other types - of \l {qml-data-models}{data models} are also supported. - - \code - ComboBox { - model: ["First", "Second", "Third"] - } - \endcode - - \section1 Editable ComboBox - - ComboBox can be made \l editable. An editable combo box auto-completes - its text based on what is available in the model. - - The following example demonstrates appending content to an editable - combo box by reacting to the \l accepted signal. - - \snippet qtquickcontrols2-combobox-accepted.qml combobox - - \section1 ComboBox Model Roles - - 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. If you want to use a role of the model item - that corresponds to the text role, set \l valueRole. The \l currentValue - property and \l indexOfValue() method can then be used to get information - about those values. - - For example: - - \snippet qtquickcontrols2-combobox-valuerole.qml file - - \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}, {Focus Management in Qt Quick Controls} -*/ - -/*! - \qmlsignal void QtQuick.Controls::ComboBox::activated(int index) - - This signal is emitted when the item at \a index is activated by the user. - - An item is activated when it is selected while the popup is open, - causing the popup to close (and \l currentIndex to change), - or while the popup is closed and the combo box is navigated via - keyboard, causing the \l currentIndex to change. - The \l currentIndex property is set to \a index. - - \sa currentIndex -*/ - -/*! - \qmlsignal void QtQuick.Controls::ComboBox::highlighted(int index) - - This signal is emitted when the item at \a index in the popup list is highlighted by the user. - - The highlighted signal is only emitted when the popup is open and an item - is highlighted, but not necessarily \l activated. - - \sa highlightedIndex -*/ - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlsignal void QtQuick.Controls::ComboBox::accepted() - - This signal is emitted when the \uicontrol Return or \uicontrol Enter key is pressed - on an \l editable combo box. - - You can handle this signal in order to add the newly entered - item to the model, for example: - - \snippet qtquickcontrols2-combobox-accepted.qml combobox - - Before the signal is emitted, a check is done to see if the string - exists in the model. If it does, \l currentIndex will be set to its index, - and \l currentText to the string itself. - - After the signal has been emitted, and if the first check failed (that is, - the item did not exist), another check will be done to see if the item was - added by the signal handler. If it was, the \l currentIndex and - \l currentText are updated accordingly. Otherwise, they will be set to - \c -1 and \c "", respectively. - - \note If there is a \l validator set on the combo box, the signal will only be - emitted if the input is in an acceptable state. -*/ - -namespace { - enum Activation { NoActivate, Activate }; - enum Highlighting { NoHighlight, Highlight }; -} - -class QQuickComboBoxDelegateModel : public QQmlDelegateModel -{ -public: - explicit QQuickComboBoxDelegateModel(QQuickComboBox *combo); - QVariant variantValue(int index, const QString &role) override; - -private: - QQuickComboBox *combo = nullptr; -}; - -QQuickComboBoxDelegateModel::QQuickComboBoxDelegateModel(QQuickComboBox *combo) - : QQmlDelegateModel(qmlContext(combo), combo), - combo(combo) -{ -} - -QVariant QQuickComboBoxDelegateModel::variantValue(int index, const QString &role) -{ - const QVariant model = combo->model(); - if (model.userType() == QMetaType::QVariantList) { - QVariant object = model.toList().value(index); - if (object.userType() == QMetaType::QVariantMap) { - const QVariantMap data = object.toMap(); - if (data.count() == 1 && role == QLatin1String("modelData")) - return data.first(); - return data.value(role); - } else if (object.userType() == QMetaType::QObjectStar) { - const QObject *data = object.value<QObject *>(); - if (data && role != QLatin1String("modelData")) - return data->property(role.toUtf8()); - } - } - return QQmlDelegateModel::variantValue(index, role); -} - -class QQuickComboBoxPrivate : public QQuickControlPrivate -{ - Q_DECLARE_PUBLIC(QQuickComboBox) - -public: - bool isPopupVisible() const; - void showPopup(); - void hidePopup(bool accept); - void togglePopup(bool accept); - void popupVisibleChanged(); - - void itemClicked(); - void itemHovered(); - - void createdItem(int index, QObject *object); - void modelUpdated(); - void countChanged(); - - void updateEditText(); - void updateCurrentText(); - void updateCurrentValue(); - void updateCurrentTextAndValue(); - - bool isValidIndex(int index) const; - - void acceptInput(); - QString tryComplete(const QString &inputText); - - void incrementCurrentIndex(); - void decrementCurrentIndex(); - void setCurrentIndex(int index, Activation activate); - void updateHighlightedIndex(); - void setHighlightedIndex(int index, Highlighting highlight); - - void keySearch(const QString &text); - int match(int start, const QString &text, Qt::MatchFlags flags) const; - - void createDelegateModel(); - - void handlePress(const QPointF &point) override; - void handleMove(const QPointF &point) override; - void handleRelease(const QPointF &point) override; - void handleUngrab() override; - - void cancelIndicator(); - void executeIndicator(bool complete = false); - - void cancelPopup(); - void executePopup(bool complete = false); - - void itemImplicitWidthChanged(QQuickItem *item) override; - void itemImplicitHeightChanged(QQuickItem *item) override; - - static void hideOldPopup(QQuickPopup *popup); - - QPalette defaultPalette() const override { return QQuickTheme::palette(QQuickTheme::ComboBox); } - - bool flat = false; - bool down = false; - bool hasDown = false; - bool pressed = false; - bool ownModel = false; - bool keyNavigating = false; - bool hasDisplayText = false; - bool hasCurrentIndex = false; - int highlightedIndex = -1; - int currentIndex = -1; - QVariant model; - QString textRole; - QString currentText; - QString displayText; - QString valueRole; - QVariant currentValue; - QQuickItem *pressedItem = nullptr; - QQmlInstanceModel *delegateModel = nullptr; - QQmlComponent *delegate = nullptr; - QQuickDeferredPointer<QQuickItem> indicator; - QQuickDeferredPointer<QQuickPopup> popup; - - struct ExtraData { - bool editable = false; - bool accepting = false; - bool allowComplete = false; - bool selectTextByMouse = false; - Qt::InputMethodHints inputMethodHints = Qt::ImhNone; - QString editText; - QValidator *validator = nullptr; - }; - QLazilyAllocated<ExtraData> extra; -}; - -bool QQuickComboBoxPrivate::isPopupVisible() const -{ - return popup && popup->isVisible(); -} - -void QQuickComboBoxPrivate::showPopup() -{ - if (!popup) - executePopup(true); - - if (popup && !popup->isVisible()) - popup->open(); -} - -void QQuickComboBoxPrivate::hidePopup(bool accept) -{ - Q_Q(QQuickComboBox); - if (accept) { - q->setCurrentIndex(highlightedIndex); - emit q->activated(currentIndex); - } - if (popup && popup->isVisible()) - popup->close(); -} - -void QQuickComboBoxPrivate::togglePopup(bool accept) -{ - if (!popup || !popup->isVisible()) - showPopup(); - else - hidePopup(accept); -} - -void QQuickComboBoxPrivate::popupVisibleChanged() -{ - Q_Q(QQuickComboBox); - if (isPopupVisible()) - QGuiApplication::inputMethod()->reset(); - - QQuickItemView *itemView = popup->findChild<QQuickItemView *>(); - if (itemView) - itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange); - - updateHighlightedIndex(); - - if (itemView) - itemView->positionViewAtIndex(highlightedIndex, QQuickItemView::Beginning); - - if (!hasDown) { - q->setDown(pressed || isPopupVisible()); - hasDown = false; - } -} - -void QQuickComboBoxPrivate::itemClicked() -{ - Q_Q(QQuickComboBox); - int index = delegateModel->indexOf(q->sender(), nullptr); - if (index != -1) { - setHighlightedIndex(index, Highlight); - hidePopup(true); - } -} - -void QQuickComboBoxPrivate::itemHovered() -{ - Q_Q(QQuickComboBox); - if (keyNavigating) - return; - - QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender()); - if (!button || !button->isHovered() || QQuickAbstractButtonPrivate::get(button)->touchId != -1) - return; - - int index = delegateModel->indexOf(button, nullptr); - if (index != -1) { - setHighlightedIndex(index, Highlight); - - if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>()) - itemView->positionViewAtIndex(index, QQuickItemView::Contain); - } -} - -void QQuickComboBoxPrivate::createdItem(int index, QObject *object) -{ - Q_Q(QQuickComboBox); - QQuickItem *item = qobject_cast<QQuickItem *>(object); - if (item && !item->parentItem()) { - if (popup) - item->setParentItem(popup->contentItem()); - else - item->setParentItem(q); - QQuickItemPrivate::get(item)->setCulled(true); - } - - QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object); - if (button) { - button->setFocusPolicy(Qt::NoFocus); - connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked); - connect(button, &QQuickAbstractButton::hoveredChanged, this, &QQuickComboBoxPrivate::itemHovered); - } - - if (index == currentIndex && !q->isEditable()) - updateCurrentTextAndValue(); -} - -void QQuickComboBoxPrivate::modelUpdated() -{ - if (!extra.isAllocated() || !extra->accepting) - updateCurrentTextAndValue(); -} - -void QQuickComboBoxPrivate::countChanged() -{ - Q_Q(QQuickComboBox); - if (q->count() == 0) - q->setCurrentIndex(-1); - emit q->countChanged(); -} - -void QQuickComboBoxPrivate::updateEditText() -{ - Q_Q(QQuickComboBox); - QQuickTextInput *input = qobject_cast<QQuickTextInput *>(contentItem); - if (!input) - return; - - const QString text = input->text(); - - if (extra.isAllocated() && extra->allowComplete && !text.isEmpty()) { - const QString completed = tryComplete(text); - if (completed.length() > text.length()) { - input->setText(completed); - input->select(completed.length(), text.length()); - return; - } - } - q->setEditText(text); -} - -void QQuickComboBoxPrivate::updateCurrentText() -{ - Q_Q(QQuickComboBox); - const QString text = q->textAt(currentIndex); - if (currentText != text) { - currentText = text; - if (!hasDisplayText) - q->maybeSetAccessibleName(text); - emit q->currentTextChanged(); - } - if (!hasDisplayText && displayText != text) { - displayText = text; - emit q->displayTextChanged(); - } - if (!extra.isAllocated() || !extra->accepting) - q->setEditText(currentText); -} - -void QQuickComboBoxPrivate::updateCurrentValue() -{ - Q_Q(QQuickComboBox); - const QVariant value = q->valueAt(currentIndex); - if (currentValue == value) - return; - - currentValue = value; - emit q->currentValueChanged(); -} - -void QQuickComboBoxPrivate::updateCurrentTextAndValue() -{ - updateCurrentText(); - updateCurrentValue(); -} - -bool QQuickComboBoxPrivate::isValidIndex(int index) const -{ - return delegateModel && index >= 0 && index < delegateModel->count(); -} - -void QQuickComboBoxPrivate::acceptInput() -{ - Q_Q(QQuickComboBox); - int idx = q->find(extra.value().editText, Qt::MatchFixedString); - if (idx > -1) - q->setCurrentIndex(idx); - - extra.value().accepting = true; - emit q->accepted(); - - if (idx == -1) - q->setCurrentIndex(q->find(extra.value().editText, Qt::MatchFixedString)); - extra.value().accepting = false; -} - -QString QQuickComboBoxPrivate::tryComplete(const QString &input) -{ - Q_Q(QQuickComboBox); - QString match; - - const int itemCount = q->count(); - for (int idx = 0; idx < itemCount; ++idx) { - const QString text = q->textAt(idx); - if (!text.startsWith(input, Qt::CaseInsensitive)) - continue; - - // either the first or the shortest match - if (match.isEmpty() || text.length() < match.length()) - match = text; - } - - if (match.isEmpty()) - return input; - - return input + match.mid(input.length()); -} - -void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate) -{ - Q_Q(QQuickComboBox); - if (currentIndex == index) - return; - - currentIndex = index; - emit q->currentIndexChanged(); - - if (componentComplete) - updateCurrentTextAndValue(); - - if (activate) - emit q->activated(index); -} - -void QQuickComboBoxPrivate::incrementCurrentIndex() -{ - Q_Q(QQuickComboBox); - if (extra.isAllocated()) - extra->allowComplete = false; - if (isPopupVisible()) { - if (highlightedIndex < q->count() - 1) - setHighlightedIndex(highlightedIndex + 1, Highlight); - } else { - if (currentIndex < q->count() - 1) - setCurrentIndex(currentIndex + 1, Activate); - } - if (extra.isAllocated()) - extra->allowComplete = true; -} - -void QQuickComboBoxPrivate::decrementCurrentIndex() -{ - if (extra.isAllocated()) - extra->allowComplete = false; - if (isPopupVisible()) { - if (highlightedIndex > 0) - setHighlightedIndex(highlightedIndex - 1, Highlight); - } else { - if (currentIndex > 0) - setCurrentIndex(currentIndex - 1, Activate); - } - if (extra.isAllocated()) - extra->allowComplete = true; -} - -void QQuickComboBoxPrivate::updateHighlightedIndex() -{ - setHighlightedIndex(popup->isVisible() ? currentIndex : -1, NoHighlight); -} - -void QQuickComboBoxPrivate::setHighlightedIndex(int index, Highlighting highlight) -{ - Q_Q(QQuickComboBox); - if (highlightedIndex == index) - return; - - highlightedIndex = index; - emit q->highlightedIndexChanged(); - - if (highlight) - emit q->highlighted(index); -} - -void QQuickComboBoxPrivate::keySearch(const QString &text) -{ - const int startIndex = isPopupVisible() ? highlightedIndex : currentIndex; - const int index = match(startIndex + 1, text, Qt::MatchStartsWith | Qt::MatchWrap); - if (index != -1) { - if (isPopupVisible()) - setHighlightedIndex(index, Highlight); - else - setCurrentIndex(index, Activate); - } -} - -int QQuickComboBoxPrivate::match(int start, const QString &text, Qt::MatchFlags flags) const -{ - Q_Q(const QQuickComboBox); - uint matchType = flags & 0x0F; - bool wrap = flags & Qt::MatchWrap; - Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; - QRegularExpression::PatternOptions options = flags & Qt::MatchCaseSensitive ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - int from = start; - int to = q->count(); - - // iterates twice if wrapping - for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { - for (int idx = from; idx < to; ++idx) { - QString t = q->textAt(idx); - switch (matchType) { - case Qt::MatchExactly: - if (t == text) - return idx; - break; - case Qt::MatchRegularExpression: { - QRegularExpression rx(QRegularExpression::anchoredPattern(text), options); - if (rx.match(t).hasMatch()) - return idx; - break; - } - case Qt::MatchWildcard: { - QRegularExpression rx(QRegularExpression::wildcardToRegularExpression(text), - options); - if (rx.match(t).hasMatch()) - 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; - } - } - // prepare for the next iteration - from = 0; - to = start; - } - return -1; -} - -void QQuickComboBoxPrivate::createDelegateModel() -{ - Q_Q(QQuickComboBox); - bool ownedOldModel = ownModel; - QQmlInstanceModel* oldModel = delegateModel; - if (oldModel) { - disconnect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged); - disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::modelUpdated); - disconnect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem); - } - - ownModel = false; - delegateModel = model.value<QQmlInstanceModel *>(); - - if (!delegateModel && model.isValid()) { - QQmlDelegateModel *dataModel = new QQuickComboBoxDelegateModel(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::modelUpdated); - connect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem); - } - - emit q->delegateModelChanged(); - - if (ownedOldModel) - delete oldModel; -} - -void QQuickComboBoxPrivate::handlePress(const QPointF &point) -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::handlePress(point); - q->setPressed(true); -} - -void QQuickComboBoxPrivate::handleMove(const QPointF &point) -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::handleMove(point); - q->setPressed(q->contains(point)); -} - -void QQuickComboBoxPrivate::handleRelease(const QPointF &point) -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::handleRelease(point); - if (pressed) { - q->setPressed(false); - togglePopup(false); - } -} - -void QQuickComboBoxPrivate::handleUngrab() -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::handleUngrab(); - q->setPressed(false); -} - -static inline QString indicatorName() { return QStringLiteral("indicator"); } - -void QQuickComboBoxPrivate::cancelIndicator() -{ - Q_Q(QQuickComboBox); - quickCancelDeferred(q, indicatorName()); -} - -void QQuickComboBoxPrivate::executeIndicator(bool complete) -{ - Q_Q(QQuickComboBox); - if (indicator.wasExecuted()) - return; - - if (!indicator || complete) - quickBeginDeferred(q, indicatorName(), indicator); - if (complete) - quickCompleteDeferred(q, indicatorName(), indicator); -} - -static inline QString popupName() { return QStringLiteral("popup"); } - -void QQuickComboBoxPrivate::cancelPopup() -{ - Q_Q(QQuickComboBox); - quickCancelDeferred(q, popupName()); -} - -void QQuickComboBoxPrivate::executePopup(bool complete) -{ - Q_Q(QQuickComboBox); - if (popup.wasExecuted()) - return; - - if (!popup || complete) - quickBeginDeferred(q, popupName(), popup); - if (complete) - quickCompleteDeferred(q, popupName(), popup); -} - -void QQuickComboBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::itemImplicitWidthChanged(item); - if (item == indicator) - emit q->implicitIndicatorWidthChanged(); -} - -void QQuickComboBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) -{ - Q_Q(QQuickComboBox); - QQuickControlPrivate::itemImplicitHeightChanged(item); - if (item == indicator) - emit q->implicitIndicatorHeightChanged(); -} - -void QQuickComboBoxPrivate::hideOldPopup(QQuickPopup *popup) -{ - if (!popup) - return; - - qCDebug(lcItemManagement) << "hiding old popup" << popup; - - popup->setVisible(false); - popup->setParentItem(nullptr); -#if QT_CONFIG(accessibility) - // Remove the item from the accessibility tree. - QQuickAccessibleAttached *accessible = accessibleAttached(popup); - if (accessible) - accessible->setIgnored(true); -#endif -} - -QQuickComboBox::QQuickComboBox(QQuickItem *parent) - : QQuickControl(*(new QQuickComboBoxPrivate), parent) -{ - setFocusPolicy(Qt::StrongFocus); - setFlag(QQuickItem::ItemIsFocusScope); - setAcceptedMouseButtons(Qt::LeftButton); -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif - setInputMethodHints(Qt::ImhNoPredictiveText); -} - -QQuickComboBox::~QQuickComboBox() -{ - Q_D(QQuickComboBox); - d->removeImplicitSizeListener(d->indicator); - if (d->popup) { - // Disconnect visibleChanged() to avoid a spurious highlightedIndexChanged() signal - // emission during the destruction of the (visible) popup. (QTBUG-57650) - QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - QQuickComboBoxPrivate::hideOldPopup(d->popup); - d->popup = nullptr; - } -} - -/*! - \readonly - \qmlproperty int QtQuick.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 QtQuick.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) - return; - - if (QAbstractItemModel* aim = qvariant_cast<QAbstractItemModel *>(d->model)) { - QObjectPrivate::disconnect(aim, &QAbstractItemModel::dataChanged, - d, QOverload<>::of(&QQuickComboBoxPrivate::updateCurrentTextAndValue)); - } - if (QAbstractItemModel* aim = qvariant_cast<QAbstractItemModel *>(model)) { - QObjectPrivate::connect(aim, &QAbstractItemModel::dataChanged, - d, QOverload<>::of(&QQuickComboBoxPrivate::updateCurrentTextAndValue)); - } - - d->model = model; - d->createDelegateModel(); - emit countChanged(); - if (isComponentComplete()) { - setCurrentIndex(count() > 0 ? 0 : -1); - d->updateCurrentTextAndValue(); - } - emit modelChanged(); -} - -/*! - \internal - \qmlproperty model QtQuick.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; -} - - -/*! - \readonly - \qmlproperty bool QtQuick.Controls::ComboBox::pressed - - This property holds whether the combo box button is physically pressed. - A button can be pressed by either touch or key events. - - \sa down -*/ -bool QQuickComboBox::isPressed() const -{ - Q_D(const QQuickComboBox); - return d->pressed; -} - -void QQuickComboBox::setPressed(bool pressed) -{ - Q_D(QQuickComboBox); - if (d->pressed == pressed) - return; - - d->pressed = pressed; - emit pressedChanged(); - - if (!d->hasDown) { - setDown(d->pressed || d->isPopupVisible()); - d->hasDown = false; - } -} - -/*! - \readonly - \qmlproperty int QtQuick.Controls::ComboBox::highlightedIndex - - This property holds the index of the highlighted item in the combo box popup list. - - When a highlighted item is activated, the popup is closed, \l currentIndex - is set to \c highlightedIndex, and the value of this property is reset to - \c -1, as there is no longer a highlighted item. - - \sa highlighted(), currentIndex -*/ -int QQuickComboBox::highlightedIndex() const -{ - Q_D(const QQuickComboBox); - return d->highlightedIndex; -} - -/*! - \qmlproperty int QtQuick.Controls::ComboBox::currentIndex - - This property holds the index of the current item in the combo box. - - The default value is \c -1 when \l count is \c 0, and \c 0 otherwise. - - \sa activated(), currentText, highlightedIndex -*/ -int QQuickComboBox::currentIndex() const -{ - Q_D(const QQuickComboBox); - return d->currentIndex; -} - -void QQuickComboBox::setCurrentIndex(int index) -{ - Q_D(QQuickComboBox); - d->hasCurrentIndex = true; - d->setCurrentIndex(index, NoActivate); -} - -/*! - \readonly - \qmlproperty string QtQuick.Controls::ComboBox::currentText - - This property holds the text of the current item in the combo box. - - \sa currentIndex, displayText, textRole, editText -*/ -QString QQuickComboBox::currentText() const -{ - Q_D(const QQuickComboBox); - return d->currentText; -} - -/*! - \qmlproperty string QtQuick.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) - return; - - d->displayText = text; - maybeSetAccessibleName(text); - emit displayTextChanged(); -} - -void QQuickComboBox::resetDisplayText() -{ - Q_D(QQuickComboBox); - if (!d->hasDisplayText) - return; - - d->hasDisplayText = false; - d->updateCurrentText(); -} - - -/*! - \qmlproperty string QtQuick.Controls::ComboBox::textRole - - This property holds the model role used for populating the combo box. - - When the model has multiple roles, \c textRole can be set to determine - which role should be displayed. - - \sa model, currentText, displayText, {ComboBox Model Roles} -*/ -QString QQuickComboBox::textRole() const -{ - Q_D(const QQuickComboBox); - return d->textRole; -} - -void QQuickComboBox::setTextRole(const QString &role) -{ - Q_D(QQuickComboBox); - if (d->textRole == role) - return; - - d->textRole = role; - if (isComponentComplete()) - d->updateCurrentText(); - emit textRoleChanged(); -} - -/*! - \since QtQuick.Controls 2.14 (Qt 5.14) - \qmlproperty string QtQuick.Controls::ComboBox::valueRole - - This property holds the model role used for storing the value associated - with each item in the model. - - For an example of how to use this property, see \l {ComboBox Model Roles}. - - \sa model, currentValue -*/ -QString QQuickComboBox::valueRole() const -{ - Q_D(const QQuickComboBox); - return d->valueRole; -} - -void QQuickComboBox::setValueRole(const QString &role) -{ - Q_D(QQuickComboBox); - if (d->valueRole == role) - return; - - d->valueRole = role; - if (isComponentComplete()) - d->updateCurrentValue(); - emit valueRoleChanged(); -} - -/*! - \qmlproperty Component QtQuick.Controls::ComboBox::delegate - - This property holds a delegate that presents an item in the combo box popup. - - It is recommended to use \l ItemDelegate (or any other \l AbstractButton - derivatives) as the delegate. This ensures that the interaction works as - expected, and the popup will automatically close when appropriate. When - other types are used as the delegate, the popup must be closed manually. - For example, if \l MouseArea is used: - - \code - delegate: Rectangle { - // ... - MouseArea { - // ... - onClicked: comboBox.popup.close() - } - } - \endcode - - \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) - return; - - delete d->delegate; - d->delegate = delegate; - QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->delegateModel); - if (delegateModel) - delegateModel->setDelegate(d->delegate); - emit delegateChanged(); -} - -/*! - \qmlproperty Item QtQuick.Controls::ComboBox::indicator - - This property holds the drop indicator item. - - \sa {Customizing ComboBox} -*/ -QQuickItem *QQuickComboBox::indicator() const -{ - QQuickComboBoxPrivate *d = const_cast<QQuickComboBoxPrivate *>(d_func()); - if (!d->indicator) - d->executeIndicator(); - return d->indicator; -} - -void QQuickComboBox::setIndicator(QQuickItem *indicator) -{ - Q_D(QQuickComboBox); - if (d->indicator == indicator) - return; - - if (!d->indicator.isExecuting()) - d->cancelIndicator(); - - const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth(); - const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight(); - - d->removeImplicitSizeListener(d->indicator); - QQuickControlPrivate::hideOldItem(d->indicator); - d->indicator = indicator; - if (indicator) { - if (!indicator->parentItem()) - indicator->setParentItem(this); - d->addImplicitSizeListener(indicator); - } - - if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth())) - emit implicitIndicatorWidthChanged(); - if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight())) - emit implicitIndicatorHeightChanged(); - if (!d->indicator.isExecuting()) - emit indicatorChanged(); -} - -/*! - \qmlproperty Popup QtQuick.Controls::ComboBox::popup - - This property holds the popup. - - The popup can be opened or closed manually, if necessary: - - \code - onSpecialEvent: comboBox.popup.close() - \endcode - - \sa {Customizing ComboBox} -*/ -QQuickPopup *QQuickComboBox::popup() const -{ - QQuickComboBoxPrivate *d = const_cast<QQuickComboBoxPrivate *>(d_func()); - if (!d->popup) - d->executePopup(isComponentComplete()); - return d->popup; -} - -void QQuickComboBox::setPopup(QQuickPopup *popup) -{ - Q_D(QQuickComboBox); - if (d->popup == popup) - return; - - if (!d->popup.isExecuting()) - d->cancelPopup(); - - if (d->popup) { - QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - QQuickComboBoxPrivate::hideOldPopup(d->popup); - } - if (popup) { - QQuickPopupPrivate::get(popup)->allowVerticalFlip = true; - popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent); - QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - - if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>()) - itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange); - } - d->popup = popup; - if (!d->popup.isExecuting()) - emit popupChanged(); -} - -/*! - \since QtQuick.Controls 2.1 (Qt 5.8) - \qmlproperty bool QtQuick.Controls::ComboBox::flat - - This property holds whether the combo box button is flat. - - A flat combo box button does not draw a background unless it is interacted - with. In comparison to normal combo boxes, flat combo boxes provide looks - that make them stand out less from the rest of the UI. For instance, when - placing a combo box into a tool bar, it may be desirable to make the combo - box flat so it matches better with the flat looks of tool buttons. - - The default value is \c false. -*/ -bool QQuickComboBox::isFlat() const -{ - Q_D(const QQuickComboBox); - return d->flat; -} - -void QQuickComboBox::setFlat(bool flat) -{ - Q_D(QQuickComboBox); - if (d->flat == flat) - return; - - d->flat = flat; - emit flatChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty bool QtQuick.Controls::ComboBox::down - - This property holds whether the combo box button is visually down. - - Unless explicitly set, this property is \c true when either \c pressed - or \c popup.visible is \c true. To return to the default value, set this - property to \c undefined. - - \sa pressed, popup -*/ -bool QQuickComboBox::isDown() const -{ - Q_D(const QQuickComboBox); - return d->down; -} - -void QQuickComboBox::setDown(bool down) -{ - Q_D(QQuickComboBox); - d->hasDown = true; - - if (d->down == down) - return; - - d->down = down; - emit downChanged(); -} - -void QQuickComboBox::resetDown() -{ - Q_D(QQuickComboBox); - if (!d->hasDown) - return; - - setDown(d->pressed || d->isPopupVisible()); - d->hasDown = false; -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty bool QtQuick.Controls::ComboBox::editable - - This property holds whether the combo box is editable. - - The default value is \c false. - - \sa validator -*/ -bool QQuickComboBox::isEditable() const -{ - Q_D(const QQuickComboBox); - return d->extra.isAllocated() && d->extra->editable; -} - -void QQuickComboBox::setEditable(bool editable) -{ - Q_D(QQuickComboBox); - if (editable == isEditable()) - return; - - if (d->contentItem) { - if (editable) { - d->contentItem->installEventFilter(this); - if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) { - QObjectPrivate::connect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); - QObjectPrivate::connect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); - } -#if QT_CONFIG(cursor) - d->contentItem->setCursor(Qt::IBeamCursor); -#endif - } else { - d->contentItem->removeEventFilter(this); - if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) { - QObjectPrivate::disconnect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); - QObjectPrivate::disconnect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); - } -#if QT_CONFIG(cursor) - d->contentItem->unsetCursor(); -#endif - } - } - - d->extra.value().editable = editable; - setAccessibleProperty("editable", editable); - emit editableChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty string QtQuick.Controls::ComboBox::editText - - This property holds the text in the text field of an editable combo box. - - \sa editable, currentText, displayText -*/ -QString QQuickComboBox::editText() const -{ - Q_D(const QQuickComboBox); - return d->extra.isAllocated() ? d->extra->editText : QString(); -} - -void QQuickComboBox::setEditText(const QString &text) -{ - Q_D(QQuickComboBox); - if (text == editText()) - return; - - d->extra.value().editText = text; - emit editTextChanged(); -} - -void QQuickComboBox::resetEditText() -{ - setEditText(QString()); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty Validator QtQuick.Controls::ComboBox::validator - - This property holds an input text validator for an editable combo box. - - When a validator is set, the text field will only accept input which - leaves the text property in an intermediate state. The \l accepted signal - will only be emitted if the text is in an acceptable state when the - \uicontrol Return or \uicontrol Enter key is pressed. - - The currently supported validators are \l[QtQuick]{IntValidator}, - \l[QtQuick]{DoubleValidator}, and \l[QtQuick]{RegularExpressionValidator}. An - example of using validators is shown below, which allows input of - integers between \c 0 and \c 10 into the text field: - - \code - ComboBox { - model: 10 - editable: true - validator: IntValidator { - top: 9 - bottom: 0 - } - } - \endcode - - \sa acceptableInput, accepted, editable -*/ -QValidator *QQuickComboBox::validator() const -{ - Q_D(const QQuickComboBox); - return d->extra.isAllocated() ? d->extra->validator : nullptr; -} - -void QQuickComboBox::setValidator(QValidator *validator) -{ - Q_D(QQuickComboBox); - if (validator == QQuickComboBox::validator()) - return; - - d->extra.value().validator = validator; -#if QT_CONFIG(validator) - if (validator) - validator->setLocale(d->locale); -#endif - emit validatorChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty flags QtQuick.Controls::ComboBox::inputMethodHints - - Provides hints to the input method about the expected content of the combo box and how it - should operate. - - The default value is \c Qt.ImhNoPredictiveText. - - \include inputmethodhints.qdocinc -*/ -Qt::InputMethodHints QQuickComboBox::inputMethodHints() const -{ - Q_D(const QQuickComboBox); - return d->extra.isAllocated() ? d->extra->inputMethodHints : Qt::ImhNoPredictiveText; -} - -void QQuickComboBox::setInputMethodHints(Qt::InputMethodHints hints) -{ - Q_D(QQuickComboBox); - if (hints == inputMethodHints()) - return; - - d->extra.value().inputMethodHints = hints; - emit inputMethodHintsChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty bool QtQuick.Controls::ComboBox::inputMethodComposing - \readonly - - This property holds whether an editable combo box has partial text input from an input method. - - While it is composing, an input method may rely on mouse or key events from the combo box to - edit or commit the partial text. This property can be used to determine when to disable event - handlers that may interfere with the correct operation of an input method. -*/ -bool QQuickComboBox::isInputMethodComposing() const -{ - Q_D(const QQuickComboBox); - return d->contentItem && d->contentItem->property("inputMethodComposing").toBool(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty bool QtQuick.Controls::ComboBox::acceptableInput - \readonly - - This property holds whether the combo box contains acceptable text in the editable text field. - - If a validator has been set, the value is \c true only if the current text is acceptable - to the validator as a final string (not as an intermediate string). - - \sa validator, accepted -*/ -bool QQuickComboBox::hasAcceptableInput() const -{ - Q_D(const QQuickComboBox); - return d->contentItem && d->contentItem->property("acceptableInput").toBool(); -} - -/*! - \since QtQuick.Controls 2.5 (Qt 5.12) - \qmlproperty real QtQuick.Controls::ComboBox::implicitIndicatorWidth - \readonly - - This property holds the implicit indicator width. - - The value is equal to \c {indicator ? indicator.implicitWidth : 0}. - - This is typically used, together with \l {Control::}{implicitContentWidth} and - \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. - - \sa implicitIndicatorHeight -*/ -qreal QQuickComboBox::implicitIndicatorWidth() const -{ - Q_D(const QQuickComboBox); - if (!d->indicator) - return 0; - return d->indicator->implicitWidth(); -} - -/*! - \since QtQuick.Controls 2.5 (Qt 5.12) - \qmlproperty real QtQuick.Controls::ComboBox::implicitIndicatorHeight - \readonly - - This property holds the implicit indicator height. - - The value is equal to \c {indicator ? indicator.implicitHeight : 0}. - - This is typically used, together with \l {Control::}{implicitContentHeight} and - \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. - - \sa implicitIndicatorWidth -*/ -qreal QQuickComboBox::implicitIndicatorHeight() const -{ - Q_D(const QQuickComboBox); - if (!d->indicator) - return 0; - return d->indicator->implicitHeight(); -} - -/*! - \readonly - \since QtQuick.Controls 2.14 (Qt 5.14) - \qmlproperty string QtQuick.Controls::ComboBox::currentValue - - This property holds the value of the current item in the combo box. - - For an example of how to use this property, see \l {ComboBox Model Roles}. - - \sa currentIndex, currentText, valueRole -*/ -QVariant QQuickComboBox::currentValue() const -{ - Q_D(const QQuickComboBox); - return d->currentValue; -} - -QVariant QQuickComboBox::valueAt(int index) const -{ - Q_D(const QQuickComboBox); - if (!d->isValidIndex(index)) - return QVariant(); - - const QString effectiveValueRole = d->valueRole.isEmpty() ? QStringLiteral("modelData") : d->valueRole; - return d->delegateModel->variantValue(index, effectiveValueRole); -} - -/*! - \since QtQuick.Controls 2.14 (Qt 5.14) - \qmlmethod int QtQuick.Controls::ComboBox::indexOfValue(object value) - - Returns the index of the specified \a value, or \c -1 if no match is found. - - For an example of how to use this method, see \l {ComboBox Model Roles}. - - \sa find(), currentValue, currentIndex, valueRole -*/ -int QQuickComboBox::indexOfValue(const QVariant &value) const -{ - for (int i = 0; i < count(); ++i) { - const QVariant ourValue = valueAt(i); - if (value == ourValue) - return i; - } - return -1; -} - -/*! - \since QtQuick.Controls 2.15 (Qt 5.15) - \qmlproperty bool QtQuick.Controls::ComboBox::selectTextByMouse - - This property holds whether the text field for an editable ComboBox - can be selected with the mouse. - - The default value is \c false. -*/ -bool QQuickComboBox::selectTextByMouse() const -{ - Q_D(const QQuickComboBox); - return d->extra.isAllocated() ? d->extra->selectTextByMouse : false; -} - -void QQuickComboBox::setSelectTextByMouse(bool canSelect) -{ - Q_D(QQuickComboBox); - if (canSelect == selectTextByMouse()) - return; - - d->extra.value().selectTextByMouse = canSelect; - emit selectTextByMouseChanged(); -} -/*! - \qmlmethod string QtQuick.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->isValidIndex(index)) - return QString(); - - const QString effectiveTextRole = d->textRole.isEmpty() ? QStringLiteral("modelData") : d->textRole; - return d->delegateModel->stringValue(index, effectiveTextRole); -} - -/*! - \qmlmethod int QtQuick.Controls::ComboBox::find(string text, enumeration flags) - - 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.MatchRegularExpression 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 -{ - Q_D(const QQuickComboBox); - return d->match(0, text, flags); -} - -/*! - \qmlmethod void QtQuick.Controls::ComboBox::incrementCurrentIndex() - - Increments the current index of the combo box, or the highlighted - index if the popup list is visible. - - \sa currentIndex, highlightedIndex -*/ -void QQuickComboBox::incrementCurrentIndex() -{ - Q_D(QQuickComboBox); - d->incrementCurrentIndex(); -} - -/*! - \qmlmethod void QtQuick.Controls::ComboBox::decrementCurrentIndex() - - Decrements the current index of the combo box, or the highlighted - index if the popup list is visible. - - \sa currentIndex, highlightedIndex -*/ -void QQuickComboBox::decrementCurrentIndex() -{ - Q_D(QQuickComboBox); - d->decrementCurrentIndex(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlmethod void QtQuick.Controls::ComboBox::selectAll() - - Selects all the text in the editable text field of the combo box. - - \sa editText -*/ -void QQuickComboBox::selectAll() -{ - Q_D(QQuickComboBox); - QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem); - if (!input) - return; - input->selectAll(); -} - -bool QQuickComboBox::eventFilter(QObject *object, QEvent *event) -{ - Q_D(QQuickComboBox); - switch (event->type()) { - case QEvent::MouseButtonRelease: - if (d->isPopupVisible()) - d->hidePopup(false); - break; - case QEvent::KeyPress: { - QKeyEvent *ke = static_cast<QKeyEvent *>(event); - if (d->filterKeyEvent(ke, false)) - return true; - event->accept(); - if (d->extra.isAllocated()) - d->extra->allowComplete = ke->key() != Qt::Key_Backspace && ke->key() != Qt::Key_Delete; - break; - } - case QEvent::FocusOut: - if (qGuiApp->focusObject() != this && (!d->popup || !d->popup->hasActiveFocus())) { - // Only close the popup if focus was transferred somewhere else - // than to the popup or the popup button (which normally means that - // the user clicked on the popup button to open it, not close it). - d->hidePopup(false); - setPressed(false); - - // The focus left the text field, so if the edit text matches an item in the model, - // change our currentIndex to that. This matches widgets' behavior. - const int indexForEditText = find(d->extra.value().editText, Qt::MatchFixedString); - if (indexForEditText > -1) - setCurrentIndex(indexForEditText); - } - break; -#if QT_CONFIG(im) - case QEvent::InputMethod: - if (d->extra.isAllocated()) - d->extra->allowComplete = !static_cast<QInputMethodEvent*>(event)->commitString().isEmpty(); - break; -#endif - default: - break; - } - return QQuickControl::eventFilter(object, event); -} - -void QQuickComboBox::focusInEvent(QFocusEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::focusInEvent(event); - if (d->contentItem && isEditable()) - d->contentItem->forceActiveFocus(event->reason()); -} - -void QQuickComboBox::focusOutEvent(QFocusEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::focusOutEvent(event); - - if (qGuiApp->focusObject() != d->contentItem && (!d->popup || !d->popup->hasActiveFocus())) { - // Only close the popup if focus was transferred - // somewhere else than to the popup or the inner line edit (which is - // normally done from QQuickComboBox::focusInEvent). - d->hidePopup(false); - setPressed(false); - } -} - -#if QT_CONFIG(im) -void QQuickComboBox::inputMethodEvent(QInputMethodEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::inputMethodEvent(event); - if (!isEditable() && !event->commitString().isEmpty()) - d->keySearch(event->commitString()); - else - event->ignore(); -} -#endif - -void QQuickComboBox::keyPressEvent(QKeyEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::keyPressEvent(event); - - switch (event->key()) { - case Qt::Key_Escape: - case Qt::Key_Back: - if (d->isPopupVisible()) - event->accept(); - break; - case Qt::Key_Space: - if (!event->isAutoRepeat()) - setPressed(true); - event->accept(); - break; - case Qt::Key_Enter: - case Qt::Key_Return: - if (d->isPopupVisible()) - setPressed(true); - event->accept(); - break; - case Qt::Key_Up: - d->keyNavigating = true; - d->decrementCurrentIndex(); - event->accept(); - break; - case Qt::Key_Down: - d->keyNavigating = true; - d->incrementCurrentIndex(); - event->accept(); - break; - case Qt::Key_Home: - d->keyNavigating = true; - if (d->isPopupVisible()) - d->setHighlightedIndex(0, Highlight); - else - d->setCurrentIndex(0, Activate); - event->accept(); - break; - case Qt::Key_End: - d->keyNavigating = true; - if (d->isPopupVisible()) - d->setHighlightedIndex(count() - 1, Highlight); - else - d->setCurrentIndex(count() - 1, Activate); - event->accept(); - break; - default: - if (!isEditable() && !event->text().isEmpty()) - d->keySearch(event->text()); - else - event->ignore(); - break; - } -} - -void QQuickComboBox::keyReleaseEvent(QKeyEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::keyReleaseEvent(event); - d->keyNavigating = false; - if (event->isAutoRepeat()) - return; - - switch (event->key()) { - case Qt::Key_Space: - if (!isEditable()) - d->togglePopup(true); - setPressed(false); - event->accept(); - break; - case Qt::Key_Enter: - case Qt::Key_Return: - if (!isEditable() || d->isPopupVisible()) - d->hidePopup(d->isPopupVisible()); - setPressed(false); - event->accept(); - break; - case Qt::Key_Escape: - case Qt::Key_Back: - if (d->isPopupVisible()) { - d->hidePopup(false); - setPressed(false); - event->accept(); - } - break; - default: - break; - } -} - -#if QT_CONFIG(wheelevent) -void QQuickComboBox::wheelEvent(QWheelEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::wheelEvent(event); - if (d->wheelEnabled && !d->isPopupVisible()) { - if (event->angleDelta().y() > 0) - d->decrementCurrentIndex(); - else - d->incrementCurrentIndex(); - } -} -#endif - -bool QQuickComboBox::event(QEvent *e) -{ - Q_D(QQuickComboBox); - if (e->type() == QEvent::LanguageChange) - d->updateCurrentTextAndValue(); - return QQuickControl::event(e); -} - -void QQuickComboBox::componentComplete() -{ - Q_D(QQuickComboBox); - d->executeIndicator(true); - QQuickControl::componentComplete(); - if (d->popup) - d->executePopup(true); - - if (d->delegateModel && d->ownModel) - static_cast<QQmlDelegateModel *>(d->delegateModel)->componentComplete(); - - if (count() > 0) { - if (!d->hasCurrentIndex && d->currentIndex == -1) - setCurrentIndex(0); - else - d->updateCurrentTextAndValue(); - } -} - -void QQuickComboBox::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) -{ - Q_D(QQuickComboBox); - QQuickControl::itemChange(change, value); - if (change == ItemVisibleHasChanged && !value.boolValue) { - d->hidePopup(false); - setPressed(false); - } -} - -void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) -{ - Q_D(QQuickComboBox); - if (oldItem) { - oldItem->removeEventFilter(this); - if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem)) { - QObjectPrivate::disconnect(oldInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); - QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); - disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); - } - } - if (newItem && isEditable()) { - newItem->installEventFilter(this); - if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) { - QObjectPrivate::connect(newInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); - QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); - connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - connect(newInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); - } -#if QT_CONFIG(cursor) - newItem->setCursor(Qt::IBeamCursor); -#endif - } -} - -void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLocale) -{ - QQuickControl::localeChange(newLocale, oldLocale); -#if QT_CONFIG(validator) - if (QValidator *v = validator()) - v->setLocale(newLocale); -#endif -} - -QFont QQuickComboBox::defaultFont() const -{ - return QQuickTheme::font(QQuickTheme::ComboBox); -} - -#if QT_CONFIG(accessibility) -QAccessible::Role QQuickComboBox::accessibleRole() const -{ - return QAccessible::ComboBox; -} - -void QQuickComboBox::accessibilityActiveChanged(bool active) -{ - Q_D(QQuickComboBox); - QQuickControl::accessibilityActiveChanged(active); - - if (active) { - maybeSetAccessibleName(d->hasDisplayText ? d->displayText : d->currentText); - setAccessibleProperty("editable", isEditable()); - } -} -#endif // - -QT_END_NAMESPACE - -#include "moc_qquickcombobox_p.cpp" |