Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickdialogbuttonbox.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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
7#include "qquickbutton_p.h"
8#include "qquickdialog_p_p.h"
9
10#include <QtCore/qpointer.h>
11#include <QtGui/private/qguiapplication_p.h>
12#include <QtGui/qpa/qplatformtheme.h>
13#include <QtQml/qqmlengine.h>
14#include <QtQml/qqmlcontext.h>
15#include <QtQml/qqmlcomponent.h>
16
17#include <algorithm>
18
20
25
163{
165}
166
168{
170 if (item == contentItem)
172 else
174}
175
177{
179 if (item == contentItem)
181 else
183}
184
185// adapted from QStyle::alignedRect()
186static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle)
187{
189 qreal x = rectangle.x();
190 qreal y = rectangle.y();
191 qreal w = size.width();
192 qreal h = size.height();
194 y += (rectangle.size().height() - h) / 2;
196 y += rectangle.size().height() - h;
198 x += rectangle.size().width() - w;
200 x += (rectangle.size().width() - w) / 2;
201 return QRectF(x, y, w, h);
202}
203
205{
207 if (!contentItem || !contentModel)
208 return;
209
210 QRectF geometry = q->boundingRect().adjusted(q->leftPadding(), q->topPadding(), -q->rightPadding(), -q->bottomPadding());
211 if (alignment != 0)
212 geometry = alignedRect(q->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight, alignment, QSizeF(contentWidth, contentHeight), geometry);
213
214 contentItem->setPosition(geometry.topLeft());
215 contentItem->setSize(geometry.size());
216}
217
219{
221 const int count = contentModel->count();
222 if (count <= 0)
223 return;
224
225 const int halign = alignment & Qt::AlignHorizontal_Mask;
226 const int valign = alignment & Qt::AlignVertical_Mask;
227
229 const qreal cw = (alignment & Qt::AlignHorizontal_Mask) == 0 ? q->availableWidth() : contentWidth;
230 const qreal itemWidth = (cw - qMax(0, count - 1) * spacing) / count;
231
232 for (int i = 0; i < count; ++i) {
233 QQuickItem *item = q->itemAt(i);
234 if (item) {
236 if (!p->widthValid()) {
237 if (!halign)
238 item->setWidth(itemWidth);
239 else
240 item->resetWidth();
241 if (!valign)
242 item->setHeight(contentHeight);
243 else
244 item->resetHeight();
245 p->widthValidFlag = false;
246 }
247 }
248 buttons += static_cast<QQuickAbstractButton *>(item);
249 }
250
251 struct ButtonLayout {
254 {
255 }
256
257 bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second)
258 {
261
262 if (firstRole != secondRole && firstRole != QPlatformDialogHelper::InvalidRole && secondRole != QPlatformDialogHelper::InvalidRole) {
263 const int *l = m_layout;
264 while (*l != QPlatformDialogHelper::EOL) {
265 // Unset the Reverse flag.
266 const int role = (*l & ~QPlatformDialogHelper::Reverse);
267 if (role == firstRole)
268 return true;
269 if (role == secondRole)
270 return false;
271 ++l;
272 }
273 }
274
275 if (firstRole == secondRole)
276 return false;
277
278 return firstRole != QPlatformDialogHelper::InvalidRole;
279 }
280 const int *m_layout;
281 };
282
283 std::stable_sort(buttons.begin(), buttons.end(), ButtonLayout(static_cast<QPlatformDialogHelper::ButtonLayout>(buttonLayout)));
284
285 for (int i = 0; i < buttons.size() - 1; ++i)
286 q->insertItem(i, buttons.at(i));
287}
288
290{
291 Q_Q(const QQuickDialogButtonBox);
292 if (!contentModel)
293 return 0;
294
295 const int count = contentModel->count();
296 const qreal totalSpacing = qMax(0, count - 1) * spacing;
297 qreal totalWidth = totalSpacing;
298 qreal maxWidth = 0;
299 for (int i = 0; i < count; ++i) {
300 QQuickItem *item = q->itemAt(i);
301 if (item) {
302 totalWidth += item->implicitWidth();
303 maxWidth = qMax(maxWidth, item->implicitWidth());
304 }
305 }
307 totalWidth = qMax(totalWidth, count * maxWidth + totalSpacing);
308 return totalWidth;
309}
310
312{
313 Q_Q(const QQuickDialogButtonBox);
314 if (!contentModel)
315 return 0;
316
317 const int count = contentModel->count();
318 qreal maxHeight = 0;
319 for (int i = 0; i < count; ++i) {
320 QQuickItem *item = q->itemAt(i);
321 if (item)
322 maxHeight = qMax(maxHeight, item->implicitHeight());
323 }
324 return maxHeight;
325}
326
328{
330 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
331 if (!button)
332 return;
333
334 // Can't fetch this *after* emitting clicked, as clicked may destroy the button
335 // or change its role. Now changing the role is not possible yet, but arguably
336 // both clicked and accepted/rejected/etc. should be emitted "atomically"
337 // depending on whatever role the button had at the time of the click.
340
341 emit q->clicked(button);
342
343 if (!guard)
344 return;
345
346 switch (role) {
349 emit q->accepted();
350 break;
353 emit q->rejected();
354 break;
356 emit q->applied();
357 break;
359 emit q->reset();
360 break;
362 emit q->discarded();
363 break;
365 emit q->helpRequested();
366 break;
367 default:
368 break;
369 }
370}
371
373{
375}
376
378{
380 if (!delegate)
381 return nullptr;
382
383 QQmlContext *creationContext = delegate->creationContext();
384 if (!creationContext)
385 creationContext = qmlContext(q);
386
387 QObject *object = delegate->beginCreate(creationContext);
388 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(object);
389 if (button) {
390 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, true));
396 return button;
397 }
398
399 delete object;
400 return nullptr;
401}
402
404{
406 int i = q->count() - 1;
407 while (i >= 0) {
408 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->itemAt(i));
409 if (button) {
410 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
411 qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false));
412 if (attached) {
414 if (p->standardButton != QPlatformDialogHelper::NoButton) {
415 q->removeItem(button);
417 }
418 }
419 }
420 --i;
421 }
422}
423
425{
427 int i = q->count() - 1;
428 while (i >= 0) {
429 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(itemAt(i));
430 if (button) {
431 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
432 qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, true));
433 const auto boxAttachedPrivate = QQuickDialogButtonBoxAttachedPrivate::get(attached);
434 const QPlatformDialogHelper::StandardButton standardButton = boxAttachedPrivate->standardButton;
435 // The button might be a custom one with explicitly specified text, so we shouldn't change it in that case.
438 }
439 }
440 --i;
441 }
442}
443
445 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false));
446 if (attached)
448 else
450}
451
454{
457 d->buttonLayout = platformButtonLayout();
458}
459
461{
463 // QQuickContainerPrivate does call this, but as our type information has already been
464 // destroyed by that point (since this destructor has already run), it won't call our
465 // implementation. So, we need to make sure our implementation is called. If we don't do this,
466 // the listener we installed on the contentItem won't get removed, possibly resulting in
467 // heap-use-after-frees.
468 contentItemChange(nullptr, d->contentItem);
469}
470
488{
489 Q_D(const QQuickDialogButtonBox);
490 return d->position;
491}
492
494{
496 if (d->position == position)
497 return;
498
499 d->position = position;
501}
502
525{
526 Q_D(const QQuickDialogButtonBox);
527 return d->alignment;
528}
529
531{
533 if (d->alignment == alignment)
534 return;
535
536 d->alignment = alignment;
537 if (isComponentComplete()) {
538 d->resizeContent();
539 polish();
540 }
542}
543
545{
546 setAlignment({});
547}
548
581QPlatformDialogHelper::StandardButtons QQuickDialogButtonBox::standardButtons() const
582{
583 Q_D(const QQuickDialogButtonBox);
584 return d->standardButtons;
585}
586
587void QQuickDialogButtonBox::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
588{
590 if (d->standardButtons == buttons)
591 return;
592
593 d->removeStandardButtons();
594
597 if (standardButton & buttons) {
598 QQuickAbstractButton *button = d->createStandardButton(standardButton);
599 if (button)
601 }
602 }
603
605 polish();
606
607 d->standardButtons = buttons;
609}
610
619{
620 Q_D(const QQuickDialogButtonBox);
621 if (Q_UNLIKELY(!(d->standardButtons & button)))
622 return nullptr;
623 for (int i = 0, n = count(); i < n; ++i) {
624 QQuickAbstractButton *btn = qobject_cast<QQuickAbstractButton *>(d->itemAt(i));
625 if (Q_LIKELY(btn)) {
626 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(btn, false));
628 return btn;
629 }
630 }
631 return nullptr;
632}
633
642{
643 Q_D(const QQuickDialogButtonBox);
644 return d->delegate;
645}
646
648{
650 if (d->delegate == delegate)
651 return;
652
653 delete d->delegate;
654 d->delegate = delegate;
656}
657
659{
660 return new QQuickDialogButtonBoxAttached(object);
661}
662
678{
679 Q_D(const QQuickDialogButtonBox);
680 return d->buttonLayout;
681}
682
684{
686 if (d->buttonLayout == layout)
687 return;
688
689 d->buttonLayout = layout;
691 d->updateLayout();
692 emit buttonLayoutChanged();
693}
694
696{
698}
699
701{
704 d->updateLayout();
705}
706
708{
710 if (e->type() == QEvent::LanguageChange)
711 d->updateLanguage();
713}
714
716{
719 d->updateLayout();
720}
721
722void QQuickDialogButtonBox::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
723{
725 QQuickContainer::geometryChange(newGeometry, oldGeometry);
726 d->updateLayout();
727}
728
730{
732 QQuickContainer::contentItemChange(newItem, oldItem);
733 if (oldItem)
735 if (newItem)
737}
738
740{
741 return qobject_cast<QQuickAbstractButton *>(item);
742}
743
745{
748 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
750 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false)))
752 d->updateImplicitContentSize();
754 polish();
755}
756
758{
761 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
763 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false)))
765 d->updateImplicitContentSize();
767 polish();
768}
769
770#if QT_CONFIG(accessibility)
771QAccessible::Role QQuickDialogButtonBox::accessibleRole() const
772{
773 return QAccessible::PageTabList;
774}
775#endif
776
778{
780 if (buttonBox == box)
781 return;
782
783 buttonBox = box;
784 emit q->buttonBoxChanged();
785}
786
789{
792 while (parentItem && !d->buttonBox) {
793 d->buttonBox = qobject_cast<QQuickDialogButtonBox *>(parentItem);
794 parentItem = parentItem->parentItem();
795 }
796}
797
806{
808 return d->buttonBox;
809}
810
831{
833 return d->buttonRole;
834}
835
837{
839 if (d->buttonRole == role)
840 return;
841
842 d->buttonRole = role;
844}
845
847
848#include "moc_qquickdialogbuttonbox_p.cpp"
void setText(const QString &text)
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
static QPlatformTheme * platformTheme()
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
iterator begin()
Definition qlist.h:608
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:298
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
Definition qobject_p.h:327
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1363
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QPlatformDialogHelper class allows for platform-specific customization of dialogs.
static const int * buttonLayout(Qt::Orientation orientation=Qt::Horizontal, ButtonLayout policy=UnknownLayout)
static ButtonRole buttonRole(StandardButton button)
virtual QVariant themeHint(ThemeHint hint) const
static QString removeMnemonics(const QString &original)
\inmodule QtCore
Definition qpointer.h:18
The QQmlComponent class encapsulates a QML component definition.
virtual QObject * beginCreate(QQmlContext *)
Create an object instance from this component, within the specified context.
virtual void completeCreate()
This method provides advanced control over component instance creation.
QQmlContext * creationContext() const
Returns the QQmlContext the component was created in.
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
int count() const override
\qmlproperty int QtQml.Models::ObjectModel::count
QQuickItem * itemAt(int index) const
QQmlObjectModel * contentModel
Q_INVOKABLE void addItem(QQuickItem *item)
\qmlmethod void QtQuick.Controls::Container::addItem(Item item)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override
QQuickDeferredPointer< QQuickItem > contentItem
QPlatformDialogHelper::StandardButton standardButton
void setButtonBox(QQuickDialogButtonBox *box)
static QQuickDialogButtonBoxAttachedPrivate * get(QQuickDialogButtonBoxAttached *q)
QQuickDialogButtonBoxAttached(QObject *parent=nullptr)
void setButtonRole(QPlatformDialogHelper::ButtonRole role)
QPlatformDialogHelper::ButtonRole buttonRole
qreal getContentHeight() const override
static QString buttonText(QPlatformDialogHelper::StandardButton standardButton)
void itemImplicitWidthChanged(QQuickItem *item) override
QQuickAbstractButton * createStandardButton(QPlatformDialogHelper::StandardButton button)
QPlatformDialogHelper::ButtonLayout buttonLayout
void itemImplicitHeightChanged(QQuickItem *item) override
QPlatformDialogHelper::StandardButton standardButton(QQuickAbstractButton *button) const
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
bool isContent(QQuickItem *item) const override
void setAlignment(Qt::Alignment alignment)
QPlatformDialogHelper::ButtonLayout buttonLayout
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override
void itemAdded(int index, QQuickItem *item) override
void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
Q_INVOKABLE QQuickAbstractButton * standardButton(QPlatformDialogHelper::StandardButton button) const
\qmlmethod AbstractButton QtQuick.Controls::DialogButtonBox::standardButton(StandardButton button)
void setPosition(Position position)
void setButtonLayout(QPlatformDialogHelper::ButtonLayout layout)
void setDelegate(QQmlComponent *delegate)
void itemRemoved(int index, QQuickItem *item) override
QPlatformDialogHelper::StandardButtons standardButtons
void updatePolish() override
This function should perform any layout as required for this item.
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
static QQuickDialogButtonBoxAttached * qmlAttachedProperties(QObject *object)
QQuickDialogButtonBox(QQuickItem *parent=nullptr)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button)
Popup dialog with standard buttons and a title, used for short-term interaction with the user.
virtual void itemImplicitWidthChanged(QQuickItem *)
virtual void itemImplicitHeightChanged(QQuickItem *)
void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types)
void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
void setSize(const QSizeF &size)
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
QQuickItem * parentItem() const
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
virtual void updatePolish()
This function should perform any layout as required for this item.
void setPosition(const QPointF &)
void polish()
Schedules a polish event for this item.
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:658
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:655
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:799
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:510
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
\inmodule QtCore
Definition qsize.h:207
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:324
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
T value() const &
Definition qvariant.h:511
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
QPushButton * button
[2]
double e
uint alignment
direction
const QStyleOptionButton * btn
[3]
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:145
@ AlignBottom
Definition qnamespace.h:153
@ AlignVCenter
Definition qnamespace.h:154
@ AlignHCenter
Definition qnamespace.h:147
@ AlignHorizontal_Mask
Definition qnamespace.h:150
@ AlignVertical_Mask
Definition qnamespace.h:160
LayoutDirection
@ LeftToRight
@ RightToLeft
@ Horizontal
Definition qnamespace.h:98
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLenum GLsizei count
GLuint object
[3]
GLint first
GLfloat n
GLsizei const GLint * box
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle)
static QT_BEGIN_NAMESPACE QPlatformDialogHelper::ButtonLayout platformButtonLayout()
A button box used in dialogs.
static QRectF alignedRect(bool mirrored, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:483
static const struct TessellationWindingOrderTab cw[]
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
QVBoxLayout * layout
QGraphicsItem * item
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent