diff options
-rw-r--r-- | src/widgets/widgets/qlineedit.cpp | 39 | ||||
-rw-r--r-- | src/widgets/widgets/qlineedit.h | 4 | ||||
-rw-r--r-- | src/widgets/widgets/qlineedit_p.cpp | 10 | ||||
-rw-r--r-- | src/widgets/widgets/qlineedit_p.h | 4 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp | 42 |
5 files changed, 98 insertions, 1 deletions
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index c704eb5c35..a8b6b1a10c 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -475,6 +475,42 @@ QAction *QLineEdit::addAction(const QIcon &icon, ActionPosition position) return result; } +/*! + \property QLineEdit::clearButtonEnabled + \brief Whether the line edit displays a clear button when it is not empty. + + If enabled, the line edit displays a trailing \e clear button when it contains + some text, otherwise the line edit does not show a clear button (the + default). + + \sa addAction(), removeAction() + \since 5.2 +*/ + +static const char clearButtonActionNameC[] = "_q_qlineeditclearaction"; + +void QLineEdit::setClearButtonEnabled(bool enable) +{ + Q_D(QLineEdit); + if (enable == isClearButtonEnabled()) + return; + if (enable) { + QAction *clearAction = new QAction(d->clearButtonIcon(), QString(), this); + clearAction->setObjectName(QLatin1String(clearButtonActionNameC)); + d->addAction(clearAction, 0, QLineEdit::TrailingPosition, QLineEditPrivate::SideWidgetClearButton | QLineEditPrivate::SideWidgetFadeInWithText); + } else { + QAction *clearAction = findChild<QAction *>(QLatin1String(clearButtonActionNameC)); + Q_ASSERT(clearAction); + removeAction(clearAction); + delete clearAction; + } +} + +bool QLineEdit::isClearButtonEnabled() const +{ + return findChild<QAction *>(QLatin1String(clearButtonActionNameC)); +} + void QLineEdit::setFrame(bool enable) { Q_D(QLineEdit); @@ -2143,6 +2179,9 @@ void QLineEdit::changeEvent(QEvent *ev) update(); break; case QEvent::LayoutDirectionChange: + foreach (const QLineEditPrivate::SideWidgetEntry &e, d->trailingSideWidgets) // Refresh icon to show arrow in right direction. + if (e.flags & QLineEditPrivate::SideWidgetClearButton) + static_cast<QLineEditIconButton *>(e.widget)->setIcon(d->clearButtonIcon()); d->positionSideWidgets(); break; default: diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h index 3d16e527b6..3d52863db2 100644 --- a/src/widgets/widgets/qlineedit.h +++ b/src/widgets/widgets/qlineedit.h @@ -85,6 +85,7 @@ class Q_WIDGETS_EXPORT QLineEdit : public QWidget Q_PROPERTY(bool acceptableInput READ hasAcceptableInput) Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText) Q_PROPERTY(Qt::CursorMoveStyle cursorMoveStyle READ cursorMoveStyle WRITE setCursorMoveStyle) + Q_PROPERTY(bool clearButtonEnabled READ isClearButtonEnabled WRITE setClearButtonEnabled) public: enum ActionPosition { LeadingPosition, @@ -108,6 +109,9 @@ public: void setFrame(bool); bool hasFrame() const; + void setClearButtonEnabled(bool enable); + bool isClearButtonEnabled() const; + enum EchoMode { Normal, NoEcho, Password, PasswordEchoOnEdit }; EchoMode echoMode() const; void setEchoMode(EchoMode); diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 028675f845..99d6d0b8d9 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -368,6 +368,14 @@ QSize QLineEditPrivate::iconSize() const return m_iconSize; } +QIcon QLineEditPrivate::clearButtonIcon() const +{ + Q_Q(const QLineEdit); + QStyleOptionFrameV2 styleOption; + q->initStyleOption(&styleOption); + return QIcon(q->style()->standardPixmap(QStyle::SP_LineEditClearButton, &styleOption, q)); +} + void QLineEditPrivate::positionSideWidgets() { Q_Q(QLineEdit); @@ -417,6 +425,8 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE QLineEditIconButton *toolButton = new QLineEditIconButton(q); toolButton->setIcon(newAction->icon()); toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0); + if (flags & SideWidgetClearButton) + QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(clear())); toolButton->setDefaultAction(newAction); w = toolButton; } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 19dbde6558..8fe45972ff 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -101,7 +101,8 @@ class Q_AUTOTEST_EXPORT QLineEditPrivate : public QWidgetPrivate public: enum SideWidgetFlag { SideWidgetFadeInWithText = 0x1, - SideWidgetCreatedByWidgetAction = 0x2 + SideWidgetCreatedByWidgetAction = 0x2, + SideWidgetClearButton = 0x4 }; struct SideWidgetEntry { @@ -197,6 +198,7 @@ public: QWidget *addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition, int flags = 0); void removeAction(const QActionEvent *e); QSize iconSize() const; + QIcon clearButtonIcon() const; void positionSideWidgets(); inline bool hasSideWidgets() const { return !leadingSideWidgets.isEmpty() || !trailingSideWidgets.isEmpty(); } inline const SideWidgetEntryList &leftSideWidgetList() const diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index cd715b7b06..3000aad9ce 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -297,6 +297,7 @@ private slots: void undoRedoAndEchoModes_data(); void undoRedoAndEchoModes(); + void clearButton(); void sideWidgets(); protected slots: @@ -4057,6 +4058,47 @@ void tst_QLineEdit::undoRedoAndEchoModes() QCOMPARE(testWidget->text(), expected.at(2)); } +void tst_QLineEdit::clearButton() +{ + // Construct a listview with a stringlist model and filter model. + QWidget testWidget; + QVBoxLayout *l = new QVBoxLayout(&testWidget); + QLineEdit *filterLineEdit = new QLineEdit(&testWidget); + l->addWidget(filterLineEdit); + QListView *listView = new QListView(&testWidget); + QStringListModel *model = new QStringListModel(QStringList() << QStringLiteral("aa") << QStringLiteral("ab") << QStringLiteral("cc"), listView); + QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(listView); + filterModel->setSourceModel(model); + connect(filterLineEdit, SIGNAL(textChanged(QString)), filterModel, SLOT(setFilterFixedString(QString))); + listView->setModel(filterModel); + l->addWidget(listView); + testWidget.move(300, 300); + testWidget.show(); + qApp->setActiveWindow(&testWidget); + QVERIFY(QTest::qWaitForWindowActive(&testWidget)); + // Flip the clear button on,off, trying to detect crashes. + filterLineEdit->setClearButtonEnabled(true); + QVERIFY(filterLineEdit->isClearButtonEnabled()); + filterLineEdit->setClearButtonEnabled(true); + QVERIFY(filterLineEdit->isClearButtonEnabled()); + filterLineEdit->setClearButtonEnabled(false); + QVERIFY(!filterLineEdit->isClearButtonEnabled()); + filterLineEdit->setClearButtonEnabled(false); + QVERIFY(!filterLineEdit->isClearButtonEnabled()); + filterLineEdit->setClearButtonEnabled(true); + QVERIFY(filterLineEdit->isClearButtonEnabled()); + // Emulate filtering + QToolButton *clearButton = filterLineEdit->findChild<QToolButton *>(); + QVERIFY(clearButton); + QCOMPARE(filterModel->rowCount(), 3); + QTest::keyClick(filterLineEdit, 'a'); + QTRY_COMPARE(filterModel->rowCount(), 2); // matches 'aa', 'ab' + QTest::keyClick(filterLineEdit, 'b'); + QTRY_COMPARE(filterModel->rowCount(), 1); // matches 'ab' + QTest::mouseClick(clearButton, Qt::LeftButton, 0, QRect(QPoint(0, 0), clearButton->size()).center()); + QTRY_COMPARE(filterModel->rowCount(), 3); +} + void tst_QLineEdit::sideWidgets() { QWidget testWidget; |