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
143#ifdef QT_KEYPAD_NAVIGATION
144void QLineEditPrivate::editFocusChange(bool e)
145{
146 Q_Q(QLineEdit);
147 q->setEditFocus(e);
148}
149#endif
150
151void QLineEditPrivate::selectionChanged()
152{
153 Q_Q(QLineEdit);
154 if (control->preeditAreaText().isEmpty()) {
155 QStyleOptionFrame opt;
156 q->initStyleOption(&opt);
157 bool showCursor = control->hasSelectedText() ?
158 q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q):
159 q->hasFocus();
160 setCursorVisible(showCursor);
161 }
162
163 emit q->selectionChanged();
164#if QT_CONFIG(accessibility)
165 QAccessibleTextSelectionEvent ev(q, control->selectionStart(), control->selectionEnd());
166 ev.setCursorPosition(control->cursorPosition());
167 QAccessible::updateAccessibility(&ev);
168#endif
169}
170
171void QLineEditPrivate::updateNeeded(const QRect &rect)
172{
173 q_func()->update(adjustedControlRect(rect));
174}
175
176void QLineEditPrivate::init(const QString& txt)
177{
178 Q_Q(QLineEdit);
179
180 const auto qUpdateMicroFocus = [q]()
181 {
182 q->updateMicroFocus();
183 };
184 control = new QWidgetLineControl(txt);
185 control->setParent(q);
186 control->setFont(q->font());
187 QObject::connect(control, &QWidgetLineControl::textChanged,
188 q, &QLineEdit::textChanged);
189 QObjectPrivate::connect(control, &QWidgetLineControl::textEdited,
190 this, &QLineEditPrivate::textEdited);
191 QObjectPrivate::connect(control, &QWidgetLineControl::cursorPositionChanged,
192 this, &QLineEditPrivate::cursorPositionChanged);
193 QObjectPrivate::connect(control, &QWidgetLineControl::selectionChanged,
194 this, &QLineEditPrivate::selectionChanged);
195 QObjectPrivate::connect(control, &QWidgetLineControl::editingFinished,
196 this, &QLineEditPrivate::controlEditingFinished);
197#ifdef QT_KEYPAD_NAVIGATION
198 QObject::connect(control, &QWidgetLineControl::editFocusChange,
199 this, &QLineEditPrivate::editFocusChange);
200#endif
201 QObject::connect(control, &QWidgetLineControl::cursorPositionChanged,
202 q, qUpdateMicroFocus);
203
204 QObject::connect(control, &QWidgetLineControl::textChanged,
205 q, qUpdateMicroFocus);
206
207 QObject::connect(control, &QWidgetLineControl::updateMicroFocus,
208 q, qUpdateMicroFocus);
209
210 // for now, going completely overboard with updates.
211 QObject::connect(control, &QWidgetLineControl::selectionChanged,
212 q, qOverload<>(&QLineEdit::update));
213
214 QObject::connect(control, &QWidgetLineControl::selectionChanged,
215 q, qUpdateMicroFocus);
216
217 QObject::connect(control, &QWidgetLineControl::displayTextChanged,
218 q, qOverload<>(&QLineEdit::update));
219
220 QObjectPrivate::connect(control, &QWidgetLineControl::updateNeeded,
221 this, &QLineEditPrivate::updateNeeded);
222 QObject::connect(control, &QWidgetLineControl::inputRejected,
223 q, &QLineEdit::inputRejected);
224
225 QStyleOptionFrame opt;
226 q->initStyleOption(&opt);
227 control->setPasswordCharacter(char16_t(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q)));
228 control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
229#ifndef QT_NO_CURSOR
230 q->setCursor(Qt::IBeamCursor);
231#endif
232 q->setFocusPolicy(Qt::StrongFocus);
233 q->setAttribute(Qt::WA_InputMethodEnabled);
234 // Specifies that this widget can use more, but is able to survive on
235 // less, horizontal space; and is fixed vertically.
236 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
237 q->setBackgroundRole(QPalette::Base);
238 q->setAttribute(Qt::WA_KeyCompression);
239 q->setMouseTracking(true);
240 q->setAcceptDrops(true);
241
242 q->setAttribute(Qt::WA_MacShowFocusRect);
243
244 initMouseYThreshold();
245}
246
247void QLineEditPrivate::initMouseYThreshold()
248{
249 mouseYThreshold = QGuiApplication::styleHints()->mouseQuickSelectionThreshold();
250}
251
252QRect QLineEditPrivate::adjustedContentsRect() const
253{
254 Q_Q(const QLineEdit);
255 QStyleOptionFrame opt;
256 q->initStyleOption(&opt);
257 QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
258 r = r.marginsRemoved(effectiveTextMargins());
259 return r;
260}
261
262void QLineEditPrivate::setCursorVisible(bool visible)
263{
264 Q_Q(QLineEdit);
265 if ((bool)cursorVisible == visible)
266 return;
267 cursorVisible = visible;
268 if (control->inputMask().isEmpty())
269 q->update(cursorRect());
270 else
271 q->update();
272}
273
274void QLineEditPrivate::setText(const QString& text)
275{
276 edited = true;
277 control->setText(text);
278}
279
280void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
281{
282 Q_Q(QLineEdit);
283 control->updatePasswordEchoEditing(editing);
284 q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod());
285}
286
287void QLineEditPrivate::resetInputMethod()
288{
289 Q_Q(QLineEdit);
290 if (q->hasFocus() && qApp) {
291 QGuiApplication::inputMethod()->reset();
292 }
293}
294
295/*!
296 \class QLineEditPrivate
297 \inmodule QtWidgets
298 \internal
299*/
300
301/*!
302 This function is not intended as polymorphic usage. Just a shared code
303 fragment that calls QInputMethod::invokeAction for this
304 class.
305*/
306bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
307{
308#if !defined QT_NO_IM
309 if ( control->composeMode() ) {
310 int tmp_cursor = xToPos(e->position().toPoint().x());
311 int mousePos = tmp_cursor - control->cursor();
312 if ( mousePos < 0 || mousePos > control->preeditAreaText().size() )
313 mousePos = -1;
314
315 if (mousePos >= 0) {
316 if (e->type() == QEvent::MouseButtonRelease)
317 QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, mousePos);
318
319 return true;
320 }
321 }
322#else
323 Q_UNUSED(e);
324#endif
325
326 return false;
327}
328
329#if QT_CONFIG(draganddrop)
330void QLineEditPrivate::drag()
331{
332 Q_Q(QLineEdit);
333 dndTimer.stop();
334 QMimeData *data = new QMimeData;
335 data->setText(control->selectedText());
336 QDrag *drag = new QDrag(q);
337 drag->setMimeData(data);
338 Qt::DropAction action = drag->exec(Qt::CopyAction);
339 if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q)
340 control->removeSelection();
341}
342#endif // QT_CONFIG(draganddrop)
343
344
345#if QT_CONFIG(toolbutton)
346QLineEditIconButton::QLineEditIconButton(QWidget *parent)
347 : QToolButton(parent)
348 , m_opacity(0)
349{
350 setFocusPolicy(Qt::NoFocus);
351}
352
353QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const
354{
355 QLineEdit *le = qobject_cast<QLineEdit *>(parentWidget());
356 return le ? static_cast<QLineEditPrivate *>(qt_widget_private(le)) : nullptr;
357}
358
359void QLineEditIconButton::paintEvent(QPaintEvent *)
360{
361 QPainter painter(this);
362 QIcon::Mode mode = QIcon::Disabled;
363 if (isEnabled())
364 mode = isDown() ? QIcon::Active : QIcon::Normal;
365 const QLineEditPrivate *lep = lineEditPrivate();
366 const int iconWidth = lep ? lep->sideWidgetParameters().iconSize : 16;
367 const QSize iconSize(iconWidth, iconWidth);
368 QRect pixmapRect = QRect(QPoint(0, 0), iconSize);
369 pixmapRect.moveCenter(rect().center());
370 painter.setOpacity(m_opacity);
371 icon().paint(&painter, pixmapRect, Qt::AlignCenter, mode, QIcon::Off);
372}
373
374void QLineEditIconButton::actionEvent(QActionEvent *e)
375{
376 switch (e->type()) {
377 case QEvent::ActionChanged: {
378 const auto *action = e->action();
379 if (isVisibleTo(parentWidget()) != action->isVisible()) {
380 setVisible(action->isVisible());
381 if (QLineEditPrivate *lep = lineEditPrivate())
382 lep->positionSideWidgets();
383 }
384 }
385 break;
386 default:
387 break;
388 }
389 QToolButton::actionEvent(e);
390}
391
392void QLineEditIconButton::setOpacity(qreal value)
393{
394 if (!qFuzzyCompare(m_opacity, value)) {
395 m_opacity = value;
396 updateCursor();
397 update();
398 }
399}
400
401#if QT_CONFIG(animation)
402bool QLineEditIconButton::shouldHideWithText() const
403{
404 return m_hideWithText;
405}
406
407void QLineEditIconButton::setHideWithText(bool hide)
408{
409 m_hideWithText = hide;
410}
411
412void QLineEditIconButton::onAnimationFinished()
413{
414 if (shouldHideWithText() && isVisible() && m_fadingOut) {
415 hide();
416 m_fadingOut = false;
417
418 // Invalidate previous geometry to take into account new size of side widgets
419 if (auto le = lineEditPrivate())
420 le->updateGeometry_helper(true);
421 }
422}
423
424void QLineEditIconButton::animateShow(bool visible)
425{
426 m_fadingOut = !visible;
427
428 if (shouldHideWithText() && !isVisible()) {
429 show();
430
431 // Invalidate previous geometry to take into account new size of side widgets
432 if (auto le = lineEditPrivate())
433 le->updateGeometry_helper(true);
434 }
435
436 startOpacityAnimation(visible ? 1.0 : 0.0);
437}
438
439void QLineEditIconButton::startOpacityAnimation(qreal endValue)
440{
441 QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"), this);
442 connect(animation, &QPropertyAnimation::finished, this, &QLineEditIconButton::onAnimationFinished);
443
444 animation->setDuration(160);
445 animation->setEndValue(endValue);
446 animation->start(QAbstractAnimation::DeleteWhenStopped);
447}
448#endif
449
450void QLineEditIconButton::updateCursor()
451{
452#ifndef QT_NO_CURSOR
453 setCursor(qFuzzyCompare(m_opacity, qreal(1.0)) || !parentWidget() ? QCursor(Qt::ArrowCursor) : parentWidget()->cursor());
454#endif
455}
456#endif // QT_CONFIG(toolbutton)
457
458#if QT_CONFIG(animation) && QT_CONFIG(toolbutton)
459static void displayWidgets(const QLineEditPrivate::SideWidgetEntryList &widgets, bool display)
460{
461 for (const auto &e : widgets) {
462 if (e.flags & QLineEditPrivate::SideWidgetFadeInWithText)
463 static_cast<QLineEditIconButton *>(e.widget)->animateShow(display);
464 }
465}
466#endif
467
468void QLineEditPrivate::textChanged(const QString &text)
469{
470 if (hasSideWidgets()) {
471 const int newTextSize = text.size();
472 if (!newTextSize || !lastTextSize) {
473 lastTextSize = newTextSize;
474#if QT_CONFIG(animation) && QT_CONFIG(toolbutton)
475 const bool display = newTextSize > 0;
476 displayWidgets(leadingSideWidgets, display);
477 displayWidgets(trailingSideWidgets, display);
478#endif
479 }
480 }
481}
482
483void QLineEditPrivate::clearButtonClicked()
484{
485 Q_Q(QLineEdit);
486 if (!q->text().isEmpty()) {
487 q->clear();
488 textEdited(QString());
489 }
490}
491
492void QLineEditPrivate::controlEditingFinished()
493{
494 Q_Q(QLineEdit);
495 edited = false;
496 emit q->returnPressed();
497 emit q->editingFinished();
498}
499
500QLineEditPrivate::SideWidgetParameters QLineEditPrivate::sideWidgetParameters() const
501{
502 Q_Q(const QLineEdit);
503 SideWidgetParameters result;
504 result.iconSize = q->style()->pixelMetric(QStyle::PM_LineEditIconSize, nullptr, q);
505 result.margin = q->style()->pixelMetric(QStyle::PM_LineEditIconMargin, nullptr, q);
506 result.widgetWidth = result.iconSize + 6;
507 result.widgetHeight = result.iconSize + 2;
508 return result;
509}
510
511QIcon QLineEditPrivate::clearButtonIcon() const
512{
513 Q_Q(const QLineEdit);
514 QStyleOptionFrame styleOption;
515 q->initStyleOption(&styleOption);
516 return q->style()->standardIcon(QStyle::SP_LineEditClearButton, &styleOption, q);
517}
518
519void QLineEditPrivate::setClearButtonEnabled(bool enabled)
520{
521#if QT_CONFIG(action)
522 for (const SideWidgetEntry &e : trailingSideWidgets) {
523 if (e.flags & SideWidgetClearButton) {
524 e.action->setEnabled(enabled);
525 break;
526 }
527 }
528#else
529 Q_UNUSED(enabled);
530#endif
531}
532
533void QLineEditPrivate::positionSideWidgets()
534{
535 Q_Q(QLineEdit);
536 if (hasSideWidgets()) {
537 const QRect contentRect = q->rect();
538 const SideWidgetParameters p = sideWidgetParameters();
539 const int delta = p.margin + p.widgetWidth;
540 QRect widgetGeometry(QPoint(p.margin, (contentRect.height() - p.widgetHeight) / 2),
541 QSize(p.widgetWidth, p.widgetHeight));
542 for (const SideWidgetEntry &e : leftSideWidgetList()) {
543 e.widget->setGeometry(widgetGeometry);
544#if QT_CONFIG(action)
545 if (e.action->isVisible())
546 widgetGeometry.moveLeft(widgetGeometry.left() + delta);
547#else
548 Q_UNUSED(delta);
549#endif
550 }
551 widgetGeometry.moveLeft(contentRect.width() - p.widgetWidth - p.margin);
552 for (const SideWidgetEntry &e : rightSideWidgetList()) {
553 e.widget->setGeometry(widgetGeometry);
554#if QT_CONFIG(action)
555 if (e.action->isVisible())
556 widgetGeometry.moveLeft(widgetGeometry.left() - delta);
557#endif
558 }
559 }
560}
561
562#if QT_CONFIG(action)
563QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QAction *a) const
564{
565 int i = 0;
566 for (const auto &e : leadingSideWidgets) {
567 if (a == e.action)
568 return {QLineEdit::LeadingPosition, i};
569 ++i;
570 }
571 i = 0;
572 for (const auto &e : trailingSideWidgets) {
573 if (a == e.action)
574 return {QLineEdit::TrailingPosition, i};
575 ++i;
576 }
577 return {QLineEdit::LeadingPosition, -1};
578}
579
580QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition position, int flags)
581{
582 Q_Q(QLineEdit);
583 if (!newAction)
584 return nullptr;
585 if (!hasSideWidgets()) { // initial setup.
586 QObjectPrivate::connect(q, &QLineEdit::textChanged,
587 this, &QLineEditPrivate::textChanged);
588 lastTextSize = q->text().size();
589 }
590 QWidget *w = nullptr;
591 // Store flags about QWidgetAction here since removeAction() may be called from ~QAction,
592 // in which a qobject_cast<> no longer works.
593 if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(newAction)) {
594 if ((w = widgetAction->requestWidget(q)))
595 flags |= SideWidgetCreatedByWidgetAction;
596 }
597 if (!w) {
598#if QT_CONFIG(toolbutton)
599 QLineEditIconButton *toolButton = new QLineEditIconButton(q);
600 toolButton->setIcon(newAction->icon());
601 toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0);
602 if (flags & SideWidgetClearButton) {
603 QObjectPrivate::connect(toolButton, &QToolButton::clicked,
604 this, &QLineEditPrivate::clearButtonClicked);
605
606#if QT_CONFIG(animation)
607 // The clear button is handled only by this widget. The button should be really
608 // shown/hidden in order to calculate size hints correctly.
609 toolButton->setHideWithText(true);
610#endif
611 }
612 toolButton->setDefaultAction(newAction);
613 w = toolButton;
614#else
615 return nullptr;
616#endif
617 }
618
619 // QTBUG-59957: clear button should be the leftmost action.
620 if (!before && !(flags & SideWidgetClearButton) && position == QLineEdit::TrailingPosition) {
621 for (const SideWidgetEntry &e : trailingSideWidgets) {
622 if (e.flags & SideWidgetClearButton) {
623 before = e.action;
624 break;
625 }
626 }
627 }
628
629 // If there is a 'before' action, it takes preference
630
631 // There's a bug in GHS compiler that causes internal error on the following code.
632 // The affected GHS compiler versions are 2016.5.4 and 2017.1. GHS internal reference
633 // to track the progress of this issue is TOOLS-26637.
634 // This temporary workaround allows to compile with GHS toolchain and should be
635 // removed when GHS provides a patch to fix the compiler issue.
636
637#if defined(Q_CC_GHS)
638 const SideWidgetLocation loc = {position, -1};
639 const auto location = before ? findSideWidget(before) : loc;
640#else
641 const auto location = before ? findSideWidget(before) : SideWidgetLocation{position, -1};
642#endif
643
644 SideWidgetEntryList &list = location.position == QLineEdit::TrailingPosition ? trailingSideWidgets : leadingSideWidgets;
645 list.insert(location.isValid() ? list.begin() + location.index : list.end(),
646 SideWidgetEntry(w, newAction, flags));
647 positionSideWidgets();
648 w->show();
649 return w;
650}
651
652void QLineEditPrivate::removeAction(QAction *action)
653{
654 Q_Q(QLineEdit);
655 const auto location = findSideWidget(action);
656 if (!location.isValid())
657 return;
658 SideWidgetEntryList &list = location.position == QLineEdit::TrailingPosition ? trailingSideWidgets : leadingSideWidgets;
659 SideWidgetEntry entry = list[location.index];
660 list.erase(list.begin() + location.index);
661 if (entry.flags & SideWidgetCreatedByWidgetAction) {
662 // If the cast fails, the QAction is in the process of being deleted
663 // and has already ceased to be a QWidgetAction; in the process, it
664 // will release its widget itself, and calling releaseWidget() here
665 // would be UB, so don't:
666 if (const auto a = qobject_cast<QWidgetAction*>(entry.action))
667 a->releaseWidget(entry.widget);
668 } else {
669 delete entry.widget;
670 }
671 positionSideWidgets();
672 if (!hasSideWidgets()) // Last widget, remove connection
673 QObjectPrivate::connect(q, &QLineEdit::textChanged,
674 this, &QLineEditPrivate::textChanged);
675 q->update();
676}
677#endif // QT_CONFIG(action)
678
679static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWidgetEntryList &widgets,
680 const QLineEditPrivate::SideWidgetParameters &parameters)
681{
682 if (widgets.empty())
683 return defaultMargin;
684
685 const auto visibleSideWidgetCount = std::count_if(widgets.begin(), widgets.end(),
686 [](const QLineEditPrivate::SideWidgetEntry &e) {
687#if QT_CONFIG(toolbutton) && QT_CONFIG(animation)
688 // a button that's fading out doesn't get any space
689 if (auto* iconButton = qobject_cast<QLineEditIconButton*>(e.widget))
690 return iconButton->needsSpace();
691
692#endif
693 return e.widget->isVisibleTo(e.widget->parentWidget());
694 });
695
696 return defaultMargin + (parameters.margin + parameters.widgetWidth) * visibleSideWidgetCount;
697}
698
699QMargins QLineEditPrivate::effectiveTextMargins() const
700{
701 return {effectiveTextMargin(textMargins.left(), leftSideWidgetList(), sideWidgetParameters()),
702 textMargins.top(),
703 effectiveTextMargin(textMargins.right(), rightSideWidgetList(), sideWidgetParameters()),
704 textMargins.bottom()};
705}
706
707
708QT_END_NAMESPACE
709
710#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)