Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
166
175
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
228 QList<QQuickAbstractButton *> buttons;
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.
339 QPointer<QQuickDialogButtonBox> guard(q);
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
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)
447 return QQuickDialogButtonBoxAttachedPrivate::get(attached)->standardButton;
448 else
450}
451
460
462{
464 // QQuickContainerPrivate does call this, but as our type information has already been
465 // destroyed by that point (since this destructor has already run), it won't call our
466 // implementation. So, we need to make sure our implementation is called. If we don't do this,
467 // the listener we installed on the contentItem won't get removed, possibly resulting in
468 // heap-use-after-frees.
469 contentItemChange(nullptr, d->contentItem);
470}
471
489{
490 Q_D(const QQuickDialogButtonBox);
491 return d->position;
492}
493
495{
497 if (d->position == position)
498 return;
499
500 d->position = position;
502}
503
526{
527 Q_D(const QQuickDialogButtonBox);
528 return d->alignment;
529}
530
532{
534 if (d->alignment == alignment)
535 return;
536
537 d->alignment = alignment;
538 if (isComponentComplete()) {
539 d->resizeContent();
540 polish();
541 }
543}
544
549
582QPlatformDialogHelper::StandardButtons QQuickDialogButtonBox::standardButtons() const
583{
584 Q_D(const QQuickDialogButtonBox);
585 return d->standardButtons;
586}
587
588void QQuickDialogButtonBox::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
589{
591 if (d->standardButtons == buttons)
592 return;
593
594 d->removeStandardButtons();
595
598 if (standardButton & buttons) {
599 QQuickAbstractButton *button = d->createStandardButton(standardButton);
600 if (button)
602 }
603 }
604
606 polish();
607
608 d->standardButtons = buttons;
610}
611
620{
621 Q_D(const QQuickDialogButtonBox);
622 if (Q_UNLIKELY(!(d->standardButtons & button)))
623 return nullptr;
624 for (int i = 0, n = count(); i < n; ++i) {
625 QQuickAbstractButton *btn = qobject_cast<QQuickAbstractButton *>(d->itemAt(i));
626 if (Q_LIKELY(btn)) {
627 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(btn, false));
629 return btn;
630 }
631 }
632 return nullptr;
633}
634
643{
644 Q_D(const QQuickDialogButtonBox);
645 return d->delegate;
646}
647
649{
651 if (d->delegate == delegate)
652 return;
653
654 delete d->delegate;
655 d->delegate = delegate;
657}
658
663
679{
680 Q_D(const QQuickDialogButtonBox);
681 return d->buttonLayout;
682}
683
685{
687 if (d->buttonLayout == layout)
688 return;
689
690 d->buttonLayout = layout;
692 d->updateLayout();
693 emit buttonLayoutChanged();
694}
695
700
707
709{
711 if (e->type() == QEvent::LanguageChange)
712 d->updateLanguage();
713 return QQuickContainer::event(e);
714}
715
722
723void QQuickDialogButtonBox::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
724{
726 QQuickContainer::geometryChange(newGeometry, oldGeometry);
727 d->updateLayout();
728}
729
731{
733 QQuickContainer::contentItemChange(newItem, oldItem);
734 if (oldItem)
736 if (newItem)
738}
739
741{
742 return qobject_cast<QQuickAbstractButton *>(item);
743}
744
746{
749 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
751 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false)))
752 QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(this);
753 d->updateImplicitContentSize();
755 polish();
756}
757
759{
762 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
764 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false)))
765 QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(nullptr);
766 d->updateImplicitContentSize();
768 polish();
769}
770
771#if QT_CONFIG(accessibility)
772QAccessible::Role QQuickDialogButtonBox::accessibleRole() const
773{
774 return QAccessible::PageTabList;
775}
776#endif
777
779{
781 if (buttonBox == box)
782 return;
783
784 buttonBox = box;
785 emit q->buttonBoxChanged();
786}
787
790{
793 while (parentItem && !d->buttonBox) {
794 d->buttonBox = qobject_cast<QQuickDialogButtonBox *>(parentItem);
795 parentItem = parentItem->parentItem();
796 }
797}
798
811
836
838{
840 if (d->buttonRole == role)
841 return;
842
843 d->buttonRole = role;
845}
846
848
849#include "moc_qquickdialogbuttonbox_p.cpp"
void setText(const QString &text)
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
Type type() const
Returns the event type.
Definition qcoreevent.h:304
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
static QPlatformTheme * platformTheme()
static constexpr Policy Preferred
static constexpr Policy Fixed
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:299
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:328
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
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:1389
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
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)
static QString removeMnemonics(const QString &original)
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
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 *)
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
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:484
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:672
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:669
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:813
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:511
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
\inmodule QtCore
Definition qsize.h:208
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
QPushButton * button
[2]
uint alignment
direction
const QStyleOptionButton * btn
[3]
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignHCenter
Definition qnamespace.h:148
@ AlignHorizontal_Mask
Definition qnamespace.h:151
@ AlignVertical_Mask
Definition qnamespace.h:161
LayoutDirection
@ LeftToRight
@ RightToLeft
@ Horizontal
Definition qnamespace.h:99
#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:75
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:492
static const struct TessellationWindingOrderTab cw[]
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QVBoxLayout * layout
QGraphicsItem * item