1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qlineedit.h"
41#include "qlineedit_p.h"
42
43#include "qvariant.h"
44#if QT_CONFIG(itemviews)
45#include "qabstractitemview.h"
46#endif
47#if QT_CONFIG(draganddrop)
48#include "qdrag.h"
49#endif
50#include "qwidgetaction.h"
51#include "qclipboard.h"
52#ifndef QT_NO_ACCESSIBILITY
53#include "qaccessible.h"
54#endif
55#ifndef QT_NO_IM
56#include "qinputmethod.h"
57#include "qlist.h"
58#endif
59#include <qpainter.h>
60#if QT_CONFIG(animation)
61#include <qpropertyanimation.h>
62#endif
63#include <qstylehints.h>
64#include <qvalidator.h>
65
66QT_BEGIN_NAMESPACE
67
68const int QLineEditPrivate::verticalMargin(1);
69const int QLineEditPrivate::horizontalMargin(2);
70
71QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const
72{
73 QRect widgetRect = !rect.isEmpty() ? rect : q_func()->rect();
74 QRect cr = adjustedContentsRect();
75 int cix = cr.x() - hscroll + horizontalMargin;
76 return widgetRect.translated(QPoint(cix, vscroll));
77}
78
79int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
80{
81 QRect cr = adjustedContentsRect();
82 x-= cr.x() - hscroll + horizontalMargin;
83 return control->xToPos(x, betweenOrOn);
84}
85
86bool QLineEditPrivate::inSelection(int x) const
87{
88 x -= adjustedContentsRect().x() - hscroll + horizontalMargin;
89 return control->inSelection(x);
90}
91
92QRect QLineEditPrivate::cursorRect() const
93{
94 return adjustedControlRect(control->cursorRect());
95}
96
97#if QT_CONFIG(completer)
98
99void QLineEditPrivate::_q_completionHighlighted(const QString &newText)
100{
101 Q_Q(QLineEdit);
102 if (control->completer()->completionMode() != QCompleter::InlineCompletion) {
103 q->setText(newText);
104 } else {
105 int c = control->cursor();
106 QString text = control->text();
107 q->setText(text.leftRef(c) + newText.midRef(c));
108 control->moveCursor(control->end(), false);
109#ifndef Q_OS_ANDROID
110 const bool mark = true;
111#else
112 const bool mark = (imHints & Qt::ImhNoPredictiveText);
113#endif
114 control->moveCursor(c, mark);
115 }
116}
117
118#endif // QT_CONFIG(completer)
119
120void QLineEditPrivate::_q_handleWindowActivate()
121{
122 Q_Q(QLineEdit);
123 if (!q->hasFocus() && control->hasSelectedText())
124 control->deselect();
125}
126
127void QLineEditPrivate::_q_textEdited(const QString &text)
128{
129 Q_Q(QLineEdit);
130 edited = true;
131 emit q->textEdited(text);
132#if QT_CONFIG(completer)
133 if (control->completer()
134 && control->completer()->completionMode() != QCompleter::InlineCompletion)
135 control->complete(-1); // update the popup on cut/paste/del
136#endif
137}
138
139void QLineEditPrivate::_q_cursorPositionChanged(int from, int to)
140{
141 Q_Q(QLineEdit);
142 q->update();
143 emit q->cursorPositionChanged(from, to);
144}
145
146#ifdef QT_KEYPAD_NAVIGATION
147void QLineEditPrivate::_q_editFocusChange(bool e)
148{
149 Q_Q(QLineEdit);
150 q->setEditFocus(e);
151}
152#endif
153
154void QLineEditPrivate::_q_selectionChanged()
155{
156 Q_Q(QLineEdit);
157 if (control->preeditAreaText().isEmpty()) {
158 QStyleOptionFrame opt;
159 q->initStyleOption(&opt);
160 bool showCursor = control->hasSelectedText() ?
161 q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q):
162 q->hasFocus();
163 setCursorVisible(showCursor);
164 }
165
166 emit q->selectionChanged();
167#ifndef QT_NO_ACCESSIBILITY
168 QAccessibleTextSelectionEvent ev(q, control->selectionStart(), control->selectionEnd());
169 ev.setCursorPosition(control->cursorPosition());
170 QAccessible::updateAccessibility(&ev);
171#endif
172}
173
174void QLineEditPrivate::_q_updateNeeded(const QRect &rect)
175{
176 q_func()->update(adjustedControlRect(rect));
177}
178
179void QLineEditPrivate::init(const QString& txt)
180{
181 Q_Q(QLineEdit);
182 control = new QWidgetLineControl(txt);
183 control->setParent(q);
184 control->setFont(q->font());
185 QObject::connect(control, SIGNAL(textChanged(QString)),
186 q, SIGNAL(textChanged(QString)));
187 QObject::connect(control, SIGNAL(textEdited(QString)),
188 q, SLOT(_q_textEdited(QString)));
189 QObject::connect(control, SIGNAL(cursorPositionChanged(int,int)),
190 q, SLOT(_q_cursorPositionChanged(int,int)));
191 QObject::connect(control, SIGNAL(selectionChanged()),
192 q, SLOT(_q_selectionChanged()));
193 QObject::connect(control, SIGNAL(accepted()),
194 q, SIGNAL(returnPressed()));
195 QObject::connect(control, SIGNAL(editingFinished()),
196 q, SIGNAL(editingFinished()));
197#ifdef QT_KEYPAD_NAVIGATION
198 QObject::connect(control, SIGNAL(editFocusChange(bool)),
199 q, SLOT(_q_editFocusChange(bool)));
200#endif
201 QObject::connect(control, SIGNAL(cursorPositionChanged(int,int)),
202 q, SLOT(updateMicroFocus()));
203
204 QObject::connect(control, SIGNAL(textChanged(QString)),
205 q, SLOT(updateMicroFocus()));
206
207 QObject::connect(control, SIGNAL(updateMicroFocus()),
208 q, SLOT(updateMicroFocus()));
209
210 // for now, going completely overboard with updates.
211 QObject::connect(control, SIGNAL(selectionChanged()),
212 q, SLOT(update()));
213
214 QObject::connect(control, SIGNAL(selectionChanged()),
215 q, SLOT(updateMicroFocus()));
216
217 QObject::connect(control, SIGNAL(displayTextChanged(QString)),
218 q, SLOT(update()));
219
220 QObject::connect(control, SIGNAL(updateNeeded(QRect)),
221 q, SLOT(_q_updateNeeded(QRect)));
222 QObject::connect(control, SIGNAL(inputRejected()), q, SIGNAL(inputRejected()));
223
224 QStyleOptionFrame opt;
225 q->initStyleOption(&opt);
226 control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q));
227 control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
228#ifndef QT_NO_CURSOR
229 q->setCursor(Qt::IBeamCursor);
230#endif
231 q->setFocusPolicy(Qt::StrongFocus);
232 q->setAttribute(Qt::WA_InputMethodEnabled);
233 // Specifies that this widget can use more, but is able to survive on
234 // less, horizontal space; and is fixed vertically.
235 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
236 q->setBackgroundRole(QPalette::Base);
237 q->setAttribute(Qt::WA_KeyCompression);
238 q->setMouseTracking(true);
239 q->setAcceptDrops(true);
240
241 q->setAttribute(Qt::WA_MacShowFocusRect);
242
243 initMouseYThreshold();
244}
245
246void QLineEditPrivate::initMouseYThreshold()
247{
248 mouseYThreshold = QGuiApplication::styleHints()->mouseQuickSelectionThreshold();
249}
250
251QRect QLineEditPrivate::adjustedContentsRect() const
252{
253 Q_Q(const QLineEdit);
254 QStyleOptionFrame opt;
255 q->initStyleOption(&opt);
256 QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
257 r = r.marginsRemoved(effectiveTextMargins());
258 return r;
259}
260
261void QLineEditPrivate::setCursorVisible(bool visible)
262{
263 Q_Q(QLineEdit);
264 if ((bool)cursorVisible == visible)
265 return;
266 cursorVisible = visible;
267 if (control->inputMask().isEmpty())
268 q->update(cursorRect());
269 else
270 q->update();
271}
272
273void QLineEditPrivate::setText(const QString& text)
274{
275 edited = true;
276 control->setText(text);
277}
278
279void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
280{
281 Q_Q(QLineEdit);
282 control->updatePasswordEchoEditing(editing);
283 q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod());
284}
285
286void QLineEditPrivate::resetInputMethod()
287{
288 Q_Q(QLineEdit);
289 if (q->hasFocus() && qApp) {
290 QGuiApplication::inputMethod()->reset();
291 }
292}
293
294/*!
295 This function is not intended as polymorphic usage. Just a shared code
296 fragment that calls QInputMethod::invokeAction for this
297 class.
298*/
299bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
300{
301#if !defined QT_NO_IM
302 if ( control->composeMode() ) {
303 int tmp_cursor = xToPos(e->pos().x());
304 int mousePos = tmp_cursor - control->cursor();
305 if ( mousePos < 0 || mousePos > control->preeditAreaText().length() )
306 mousePos = -1;
307
308 if (mousePos >= 0) {
309 if (e->type() == QEvent::MouseButtonRelease)
310 QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, mousePos);
311
312 return true;
313 }
314 }
315#else
316 Q_UNUSED(e);
317#endif
318
319 return false;
320}
321
322#if QT_CONFIG(draganddrop)
323void QLineEditPrivate::drag()
324{
325 Q_Q(QLineEdit);
326 dndTimer.stop();
327 QMimeData *data = new QMimeData;
328 data->setText(control->selectedText());
329 QDrag *drag = new QDrag(q);
330 drag->setMimeData(data);
331 Qt::DropAction action = drag->exec(Qt::CopyAction);
332 if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q)
333 control->removeSelection();
334}
335#endif // QT_CONFIG(draganddrop)
336
337
338#if QT_CONFIG(toolbutton)
339QLineEditIconButton::QLineEditIconButton(QWidget *parent)
340 : QToolButton(parent)
341 , m_opacity(0)
342{
343 setFocusPolicy(Qt::NoFocus);
344}
345
346QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const
347{
348 QLineEdit *le = qobject_cast<QLineEdit *>(parentWidget());
349 return le ? static_cast<QLineEditPrivate *>(qt_widget_private(le)) : nullptr;
350}
351
352void QLineEditIconButton::paintEvent(QPaintEvent *)
353{
354 QPainter painter(this);
355 QWindow *window = qt_widget_private(this)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
356 QIcon::Mode state = QIcon::Disabled;
357 if (isEnabled())
358 state = isDown() ? QIcon::Active : QIcon::Normal;
359 const QLineEditPrivate *lep = lineEditPrivate();
360 const int iconWidth = lep ? lep->sideWidgetParameters().iconSize : 16;
361 const QSize iconSize(iconWidth, iconWidth);
362 const QPixmap iconPixmap = icon().pixmap(window, iconSize, state, QIcon::Off);
363 QRect pixmapRect = QRect(QPoint(0, 0), iconSize);
364 pixmapRect.moveCenter(rect().center());
365 painter.setOpacity(m_opacity);
366 painter.drawPixmap(pixmapRect, iconPixmap);
367}
368
369void QLineEditIconButton::actionEvent(QActionEvent *e)
370{
371 switch (e->type()) {
372 case QEvent::ActionChanged: {
373 const QAction *action = e->action();
374 if (isVisibleTo(parentWidget()) != action->isVisible()) {
375 setVisible(action->isVisible());
376 if (QLineEditPrivate *lep = lineEditPrivate())
377 lep->positionSideWidgets();
378 }
379 }
380 break;
381 default:
382 break;
383 }
384 QToolButton::actionEvent(e);
385}
386
387void QLineEditIconButton::setOpacity(qreal value)
388{
389 if (!qFuzzyCompare(m_opacity, value)) {
390 m_opacity = value;
391 updateCursor();
392 update();
393 }
394}
395
396#if QT_CONFIG(animation)
397bool QLineEditIconButton::shouldHideWithText() const
398{
399 return m_hideWithText;
400}
401
402void QLineEditIconButton::setHideWithText(bool hide)
403{
404 m_hideWithText = hide;
405}
406
407void QLineEditIconButton::onAnimationFinished()
408{
409 if (shouldHideWithText() && isVisible() && !m_wasHidden) {
410 hide();
411
412 // Invalidate previous geometry to take into account new size of side widgets
413 if (auto le = lineEditPrivate())
414 le->updateGeometry_helper(true);
415 }
416}
417
418void QLineEditIconButton::animateShow(bool visible)
419{
420 m_wasHidden = visible;
421
422 if (shouldHideWithText() && !isVisible()) {
423 show();
424
425 // Invalidate previous geometry to take into account new size of side widgets
426 if (auto le = lineEditPrivate())
427 le->updateGeometry_helper(true);
428 }
429
430 startOpacityAnimation(visible ? 1.0 : 0.0);
431}
432
433void QLineEditIconButton::startOpacityAnimation(qreal endValue)
434{
435 QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"));
436 connect(animation, &QPropertyAnimation::finished, this, &QLineEditIconButton::onAnimationFinished);
437
438 animation->setDuration(160);
439 animation->setEndValue(endValue);
440 animation->start(QAbstractAnimation::DeleteWhenStopped);
441}
442#endif
443
444void QLineEditIconButton::updateCursor()
445{
446#ifndef QT_NO_CURSOR
447 setCursor(qFuzzyCompare(m_opacity, qreal(1.0)) || !parentWidget() ? QCursor(Qt::ArrowCursor) : parentWidget()->cursor());
448#endif
449}
450#endif // QT_CONFIG(toolbutton)
451
452#if QT_CONFIG(animation) && QT_CONFIG(toolbutton)
453static void displayWidgets(const QLineEditPrivate::SideWidgetEntryList &widgets, bool display)
454{
455 for (const auto &e : widgets) {
456 if (e.flags & QLineEditPrivate::SideWidgetFadeInWithText)
457 static_cast<QLineEditIconButton *>(e.widget)->animateShow(display);
458 }
459}
460#endif
461
462void QLineEditPrivate::_q_textChanged(const QString &text)
463{
464 if (hasSideWidgets()) {
465 const int newTextSize = text.size();
466 if (!newTextSize || !lastTextSize) {
467 lastTextSize = newTextSize;
468#if QT_CONFIG(animation) && QT_CONFIG(toolbutton)
469 const bool display = newTextSize > 0;
470 displayWidgets(leadingSideWidgets, display);
471 displayWidgets(trailingSideWidgets, display);
472#endif
473 }
474 }
475}
476
477void QLineEditPrivate::_q_clearButtonClicked()
478{
479 Q_Q(QLineEdit);
480 if (!q->text().isEmpty()) {
481 q->clear();
482 emit q->textEdited(QString());
483 }
484}
485
486QLineEditPrivate::SideWidgetParameters QLineEditPrivate::sideWidgetParameters() const
487{
488 Q_Q(const QLineEdit);
489 SideWidgetParameters result;
490 result.iconSize = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
491 result.margin = result.iconSize / 4;
492 result.widgetWidth = result.iconSize + 6;
493 result.widgetHeight = result.iconSize + 2;
494 return result;
495}
496
497QIcon QLineEditPrivate::clearButtonIcon() const
498{
499 Q_Q(const QLineEdit);
500 QStyleOptionFrame styleOption;
501 q->initStyleOption(&styleOption);
502 return q->style()->standardIcon(QStyle::SP_LineEditClearButton, &styleOption, q);
503}
504
505void QLineEditPrivate::setClearButtonEnabled(bool enabled)
506{
507#if QT_CONFIG(action)
508 for (const SideWidgetEntry &e : trailingSideWidgets) {
509 if (e.flags & SideWidgetClearButton) {
510 e.action->setEnabled(enabled);
511 break;
512 }
513 }
514#else
515 Q_UNUSED(enabled);
516#endif
517}
518
519void QLineEditPrivate::positionSideWidgets()
520{
521 Q_Q(QLineEdit);
522 if (hasSideWidgets()) {
523 const QRect contentRect = q->rect();
524 const SideWidgetParameters p = sideWidgetParameters();
525 const int delta = p.margin + p.widgetWidth;
526 QRect widgetGeometry(QPoint(p.margin, (contentRect.height() - p.widgetHeight) / 2),
527 QSize(p.widgetWidth, p.widgetHeight));
528 for (const SideWidgetEntry &e : leftSideWidgetList()) {
529 e.widget->setGeometry(widgetGeometry);
530#if QT_CONFIG(action)
531 if (e.action->isVisible())
532 widgetGeometry.moveLeft(widgetGeometry.left() + delta);
533#else
534 Q_UNUSED(delta);
535#endif
536 }
537 widgetGeometry.moveLeft(contentRect.width() - p.widgetWidth - p.margin);
538 for (const SideWidgetEntry &e : rightSideWidgetList()) {
539 e.widget->setGeometry(widgetGeometry);
540#if QT_CONFIG(action)
541 if (e.action->isVisible())
542 widgetGeometry.moveLeft(widgetGeometry.left() - delta);
543#endif
544 }
545 }
546}
547
548QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QAction *a) const
549{
550 int i = 0;
551 for (const auto &e : leadingSideWidgets) {
552 if (a == e.action)
553 return {QLineEdit::LeadingPosition, i};
554 ++i;
555 }
556 i = 0;
557 for (const auto &e : trailingSideWidgets) {
558 if (a == e.action)
559 return {QLineEdit::TrailingPosition, i};
560 ++i;
561 }
562 return {QLineEdit::LeadingPosition, -1};
563}
564
565QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition position, int flags)
566{
567 Q_Q(QLineEdit);
568 if (!newAction)
569 return 0;
570 if (!hasSideWidgets()) { // initial setup.
571 QObject::connect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
572 lastTextSize = q->text().size();
573 }
574 QWidget *w = 0;
575 // Store flags about QWidgetAction here since removeAction() may be called from ~QAction,
576 // in which a qobject_cast<> no longer works.
577#if QT_CONFIG(action)
578 if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(newAction)) {
579 if ((w = widgetAction->requestWidget(q)))
580 flags |= SideWidgetCreatedByWidgetAction;
581 }
582#endif
583 if (!w) {
584#if QT_CONFIG(toolbutton)
585 QLineEditIconButton *toolButton = new QLineEditIconButton(q);
586 toolButton->setIcon(newAction->icon());
587 toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0);
588 if (flags & SideWidgetClearButton) {
589 QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(_q_clearButtonClicked()));
590
591#if QT_CONFIG(animation)
592 // The clear button is handled only by this widget. The button should be really
593 // shown/hidden in order to calculate size hints correctly.
594 toolButton->setHideWithText(true);
595#endif
596 }
597 toolButton->setDefaultAction(newAction);
598 w = toolButton;
599#else
600 return nullptr;
601#endif
602 }
603
604 // QTBUG-59957: clear button should be the leftmost action.
605 if (!before && !(flags & SideWidgetClearButton) && position == QLineEdit::TrailingPosition) {
606 for (const SideWidgetEntry &e : trailingSideWidgets) {
607 if (e.flags & SideWidgetClearButton) {
608 before = e.action;
609 break;
610 }
611 }
612 }
613
614 // If there is a 'before' action, it takes preference
615
616 // There's a bug in GHS compiler that causes internal error on the following code.
617 // The affected GHS compiler versions are 2016.5.4 and 2017.1. GHS internal reference
618 // to track the progress of this issue is TOOLS-26637.
619 // This temporary workaround allows to compile with GHS toolchain and should be
620 // removed when GHS provides a patch to fix the compiler issue.
621
622#if defined(Q_CC_GHS)
623 const SideWidgetLocation loc = {position, -1};
624 const auto location = before ? findSideWidget(before) : loc;
625#else
626 const auto location = before ? findSideWidget(before) : SideWidgetLocation{position, -1};
627#endif
628
629 SideWidgetEntryList &list = location.position == QLineEdit::TrailingPosition ? trailingSideWidgets : leadingSideWidgets;
630 list.insert(location.isValid() ? list.begin() + location.index : list.end(),
631 SideWidgetEntry(w, newAction, flags));
632 positionSideWidgets();
633 w->show();
634 return w;
635}
636
637void QLineEditPrivate::removeAction(QAction *action)
638{
639#if QT_CONFIG(action)
640 Q_Q(QLineEdit);
641 const auto location = findSideWidget(action);
642 if (!location.isValid())
643 return;
644 SideWidgetEntryList &list = location.position == QLineEdit::TrailingPosition ? trailingSideWidgets : leadingSideWidgets;
645 SideWidgetEntry entry = list[location.index];
646 list.erase(list.begin() + location.index);
647 if (entry.flags & SideWidgetCreatedByWidgetAction)
648 static_cast<QWidgetAction *>(entry.action)->releaseWidget(entry.widget);
649 else
650 delete entry.widget;
651 positionSideWidgets();
652 if (!hasSideWidgets()) // Last widget, remove connection
653 QObject::disconnect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
654 q->update();
655#else
656 Q_UNUSED(action);
657#endif // QT_CONFIG(action)
658}
659
660static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWidgetEntryList &widgets,
661 const QLineEditPrivate::SideWidgetParameters &parameters)
662{
663 if (widgets.empty())
664 return defaultMargin;
665
666 return defaultMargin + (parameters.margin + parameters.widgetWidth) *
667 int(std::count_if(widgets.begin(), widgets.end(),
668 [](const QLineEditPrivate::SideWidgetEntry &e) {
669 return e.widget->isVisibleTo(e.widget->parentWidget()); }));
670}
671
672QMargins QLineEditPrivate::effectiveTextMargins() const
673{
674 return {effectiveTextMargin(textMargins.left(), leftSideWidgetList(), sideWidgetParameters()),
675 textMargins.top(),
676 effectiveTextMargin(textMargins.right(), rightSideWidgetList(), sideWidgetParameters()),
677 textMargins.bottom()};
678}
679
680
681QT_END_NAMESPACE
682
683#include "moc_qlineedit_p.cpp"
684