aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquickpopup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquickpopup.cpp')
-rw-r--r--src/quicktemplates2/qquickpopup.cpp510
1 files changed, 9 insertions, 501 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index 3b224698..5155b339 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -36,13 +36,12 @@
#include "qquickpopup_p.h"
#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopuppositioner_p_p.h"
#include "qquickapplicationwindow_p.h"
-#include "qquickshortcutcontext_p_p.h"
#include "qquickoverlay_p_p.h"
#include "qquickcontrol_p_p.h"
-#include <QtGui/private/qshortcutmap_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
@@ -187,13 +186,6 @@ QT_BEGIN_NAMESPACE
\sa opened
*/
-static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent
- | QQuickItemPrivate::Children;
-
-static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent;
-
QQuickPopupPrivate::QQuickPopupPrivate()
: QObjectPrivate()
, focus(false)
@@ -235,7 +227,7 @@ QQuickPopupPrivate::QQuickPopupPrivate()
, enter(nullptr)
, exit(nullptr)
, popupItem(nullptr)
- , positioner(this)
+ , positioner(nullptr)
, transitionManager(this)
{
}
@@ -250,6 +242,7 @@ void QQuickPopupPrivate::init()
popupItem = new QQuickPopupItem(q);
q->setParentItem(qobject_cast<QQuickItem *>(parent));
QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
+ positioner = new QQuickPopupPositioner(q);
}
bool QQuickPopupPrivate::tryClose(QQuickItem *item, QMouseEvent *event)
@@ -286,7 +279,7 @@ bool QQuickPopupPrivate::prepareEnterTransition()
visible = true;
transitionState = EnterTransition;
popupItem->setVisible(true);
- positioner.setParentItem(parentItem);
+ positioner->setParentItem(parentItem);
emit q->visibleChanged();
}
return true;
@@ -323,7 +316,7 @@ void QQuickPopupPrivate::finalizeEnterTransition()
void QQuickPopupPrivate::finalizeExitTransition()
{
Q_Q(QQuickPopup);
- positioner.setParentItem(nullptr);
+ positioner->setParentItem(nullptr);
popupItem->setParentItem(nullptr);
popupItem->setVisible(false);
@@ -424,314 +417,6 @@ void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
emit q->windowChanged(newWindow);
}
-class QQuickPopupItemPrivate : public QQuickControlPrivate
-{
- Q_DECLARE_PUBLIC(QQuickPopupItem)
-
-public:
- QQuickPopupItemPrivate(QQuickPopup *popup);
-
- void implicitWidthChanged() override;
- void implicitHeightChanged() override;
-
- void resolveFont() override;
-
- QQuickItem *getContentItem() override;
-
- int backId;
- int escapeId;
- QQuickPopup *popup;
-};
-
-QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
- : backId(0),
- escapeId(0),
- popup(popup)
-{
- isTabFence = true;
-}
-
-void QQuickPopupItemPrivate::implicitWidthChanged()
-{
- QQuickControlPrivate::implicitWidthChanged();
- emit popup->implicitWidthChanged();
-}
-
-void QQuickPopupItemPrivate::implicitHeightChanged()
-{
- QQuickControlPrivate::implicitHeightChanged();
- emit popup->implicitHeightChanged();
-}
-
-void QQuickPopupItemPrivate::resolveFont()
-{
- if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
- inheritFont(window->font());
-}
-
-QQuickItem *QQuickPopupItemPrivate::getContentItem()
-{
- Q_Q(QQuickPopupItem);
- if (!contentItem)
- contentItem = new QQuickItem(q);
- return contentItem;
-}
-
-QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
- QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
-{
- setParent(popup);
- setVisible(false);
- setFlag(ItemIsFocusScope);
- setAcceptedMouseButtons(Qt::AllButtons);
-
- // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
- setHoverEnabled(true);
- // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
- // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
-}
-
-void QQuickPopupItem::updatePolish()
-{
- Q_D(QQuickPopupItem);
- return QQuickPopupPrivate::get(d->popup)->reposition();
-}
-
-void QQuickPopupItem::grabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (!d->backId)
- d->backId = pApp->shortcutMap.addShortcut(this, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher);
- if (!d->escapeId)
- d->escapeId = pApp->shortcutMap.addShortcut(this, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher);
-#endif // QT_NO_SHORTCUT
-}
-
-void QQuickPopupItem::ungrabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (d->backId) {
- pApp->shortcutMap.removeShortcut(d->backId, this);
- d->backId = 0;
- }
- if (d->escapeId) {
- pApp->shortcutMap.removeShortcut(d->escapeId, this);
- d->escapeId = 0;
- }
-#endif // QT_NO_SHORTCUT
-}
-
-bool QQuickPopupItem::event(QEvent *event)
-{
- Q_D(QQuickPopupItem);
- if (event->type() == QEvent::Shortcut) {
- QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
- if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) {
- d->popup->close();
- return true;
- }
- }
- return QQuickItem::event(event);
-}
-
-bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
-{
- Q_D(QQuickPopupItem);
- return d->popup->childMouseEventFilter(child, event);
-}
-
-void QQuickPopupItem::focusInEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusInEvent(event);
-}
-
-void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusOutEvent(event);
-}
-
-void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyPressEvent(event);
-}
-
-void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyReleaseEvent(event);
-}
-
-void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mousePressEvent(event);
-}
-
-void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseMoveEvent(event);
-}
-
-void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseReleaseEvent(event);
-}
-
-void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseDoubleClickEvent(event);
-}
-
-void QQuickPopupItem::mouseUngrabEvent()
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseUngrabEvent();
-}
-
-void QQuickPopupItem::wheelEvent(QWheelEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->wheelEvent(event);
-}
-
-void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::contentItemChange(newItem, oldItem);
- d->popup->contentItemChange(newItem, oldItem);
-}
-
-void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::fontChange(newFont, oldFont);
- d->popup->fontChange(newFont, oldFont);
-}
-
-void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::geometryChanged(newGeometry, oldGeometry);
- d->popup->geometryChanged(newGeometry, oldGeometry);
-}
-
-void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::localeChange(newLocale, oldLocale);
- d->popup->localeChange(newLocale, oldLocale);
-}
-
-void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::itemChange(change, data);
- d->popup->itemChange(change, data);
-}
-
-void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::paddingChange(newPadding, oldPadding);
- d->popup->paddingChange(newPadding, oldPadding);
-}
-
-void QQuickPopupItem::spacingChange(qreal newSpacing, qreal oldSpacing)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::spacingChange(newSpacing, oldSpacing);
- d->popup->spacingChange(newSpacing, oldSpacing);
-}
-
-QFont QQuickPopupItem::defaultFont() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->defaultFont();
-}
-
-#ifndef QT_NO_ACCESSIBILITY
-QAccessible::Role QQuickPopupItem::accessibleRole() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->accessibleRole();
-}
-
-void QQuickPopupItem::accessibilityActiveChanged(bool active)
-{
- Q_D(const QQuickPopupItem);
- QQuickControl::accessibilityActiveChanged(active);
- d->popup->accessibilityActiveChanged(active);
-}
-#endif // QT_NO_ACCESSIBILITY
-
-QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopupPrivate *popup) :
- m_parentItem(nullptr),
- m_popup(popup)
-{
-}
-
-QQuickPopupPositioner::~QQuickPopupPositioner()
-{
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-}
-
-QQuickItem *QQuickPopupPositioner::parentItem() const
-{
- return m_parentItem;
-}
-
-void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
-{
- if (m_parentItem == parent)
- return;
-
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-
- m_parentItem = parent;
-
- if (!parent)
- return;
-
- QQuickItemPrivate::get(parent)->addItemChangeListener(this, ItemChangeTypes);
- addAncestorListeners(parent->parentItem());
-
- if (m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
-{
- if (m_parentItem && m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
-{
- addAncestorListeners(parent);
-}
-
-void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
-{
- if (isAncestor(child))
- removeAncestorListeners(item);
-}
-
void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
{
Q_Q(QQuickPopup);
@@ -741,143 +426,7 @@ void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
void QQuickPopupPrivate::reposition()
{
- Q_Q(QQuickPopup);
- if (!popupItem->isVisible())
- return;
-
- if (positioning) {
- popupItem->polish();
- return;
- }
-
- const qreal w = popupItem->width();
- const qreal h = popupItem->height();
- const qreal iw = popupItem->implicitWidth();
- const qreal ih = popupItem->implicitHeight();
-
- bool widthAdjusted = false;
- bool heightAdjusted = false;
-
- QRectF rect(allowHorizontalMove ? x : popupItem->x(),
- allowVerticalMove ? y : popupItem->y(),
- !hasWidth && iw > 0 ? iw : w,
- !hasHeight && ih > 0 ? ih : h);
- if (parentItem) {
- rect = parentItem->mapRectToScene(rect);
-
- if (window) {
- const QMarginsF margins = getMargins();
- const QRectF bounds(qMax<qreal>(0.0, margins.left()),
- qMax<qreal>(0.0, margins.top()),
- window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
- window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
-
- // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
- if (allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(parentItem->width() - x - rect.width(), y, rect.width(), rect.height()));
- if (flipped.intersected(bounds).width() > rect.intersected(bounds).width())
- rect.moveLeft(flipped.left());
- }
-
- // if the popup doesn't fit vertically inside the window, try flipping it around (above <-> below)
- if (allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(x, parentItem->height() - y - rect.height(), rect.width(), rect.height()));
- if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
- rect.moveTop(flipped.top());
- }
-
- // push inside the margins if specified
- if (allowVerticalMove) {
- if (margins.top() >= 0 && rect.top() < bounds.top())
- rect.moveTop(margins.top());
- if (margins.bottom() >= 0 && rect.bottom() > bounds.bottom())
- rect.moveBottom(bounds.bottom());
- }
- if (allowHorizontalMove) {
- if (margins.left() >= 0 && rect.left() < bounds.left())
- rect.moveLeft(margins.left());
- if (margins.right() >= 0 && rect.right() > bounds.right())
- rect.moveRight(bounds.right());
- }
-
- if (iw > 0 && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (left vs. right) fits larger part of the popup
- if (allowHorizontalMove && allowHorizontalFlip) {
- if (rect.left() < bounds.left() && bounds.left() + rect.width() <= bounds.right())
- rect.moveLeft(bounds.left());
- else if (rect.right() > bounds.right() && bounds.right() - rect.width() >= bounds.left())
- rect.moveRight(bounds.right());
- }
-
- // as a last resort, adjust the width to fit the window
- if (allowHorizontalResize) {
- if (rect.left() < bounds.left()) {
- rect.setLeft(bounds.left());
- widthAdjusted = true;
- }
- if (rect.right() > bounds.right()) {
- rect.setRight(bounds.right());
- widthAdjusted = true;
- }
- }
- } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right()
- && iw != w) {
- // restore original width
- rect.setWidth(iw);
- widthAdjusted = true;
- }
-
- if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (above vs. below) fits larger part of the popup
- if (allowVerticalMove && allowVerticalFlip) {
- if (rect.top() < bounds.top() && bounds.top() + rect.height() <= bounds.bottom())
- rect.moveTop(bounds.top());
- else if (rect.bottom() > bounds.bottom() && bounds.bottom() - rect.height() >= bounds.top())
- rect.moveBottom(bounds.bottom());
- }
-
- // as a last resort, adjust the height to fit the window
- if (allowVerticalResize) {
- if (rect.top() < bounds.top()) {
- rect.setTop(bounds.top());
- heightAdjusted = true;
- }
- if (rect.bottom() > bounds.bottom()) {
- rect.setBottom(bounds.bottom());
- heightAdjusted = true;
- }
- }
- } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom()
- && ih != h) {
- // restore original height
- rect.setHeight(ih);
- heightAdjusted = true;
- }
- }
- }
-
- positioning = true;
-
- popupItem->setPosition(rect.topLeft());
-
- const QPointF effectivePos = parentItem ? parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
- if (!qFuzzyCompare(effectiveX, effectivePos.x())) {
- effectiveX = effectivePos.x();
- emit q->xChanged();
- }
- if (!qFuzzyCompare(effectiveY, effectivePos.y())) {
- effectiveY = effectivePos.y();
- emit q->yChanged();
- }
-
- if (!hasWidth && widthAdjusted && rect.width() > 0)
- popupItem->setWidth(rect.width());
- if (!hasHeight && heightAdjusted && rect.height() > 0)
- popupItem->setHeight(rect.height());
-
- positioning = false;
+ positioner->reposition();
}
void QQuickPopupPrivate::resizeOverlay()
@@ -890,45 +439,6 @@ void QQuickPopupPrivate::resizeOverlay()
dimmer->setSize(QSizeF(w, h));
}
-void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->removeItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-// TODO: use QQuickItem::isAncestorOf() in dev/5.7
-bool QQuickPopupPositioner::isAncestor(QQuickItem *item) const
-{
- if (!m_parentItem)
- return false;
-
- QQuickItem *parent = m_parentItem;
- while (parent) {
- if (parent == item)
- return true;
- parent = parent->parentItem();
- }
- return false;
-}
-
QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
: QQuickTransitionManager(), popup(popup)
{
@@ -1710,8 +1220,8 @@ void QQuickPopup::setParentItem(QQuickItem *parent)
QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
}
d->parentItem = parent;
- if (d->positioner.parentItem())
- d->positioner.setParentItem(parent);
+ if (d->positioner->parentItem())
+ d->positioner->setParentItem(parent);
if (parent) {
QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
@@ -2443,5 +1953,3 @@ bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant
}
QT_END_NAMESPACE
-
-#include "moc_qquickpopup_p.cpp"