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