aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquickpopuppositioner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquickpopuppositioner.cpp')
-rw-r--r--src/quicktemplates2/qquickpopuppositioner.cpp310
1 files changed, 0 insertions, 310 deletions
diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp
deleted file mode 100644
index 1bfaafbe..00000000
--- a/src/quicktemplates2/qquickpopuppositioner.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickoverlay_p.h"
-#include "qquickpopuppositioner_p_p.h"
-#include "qquickpopupanchors_p.h"
-#include "qquickpopupitem_p_p.h"
-#include "qquickpopup_p_p.h"
-
-#include <QtQml/qqmlinfo.h>
-#include <QtQuick/private/qquickitem_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent
- | QQuickItemPrivate::Children;
-
-static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent;
-
-QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopup *popup)
- : m_popup(popup)
-{
-}
-
-QQuickPopupPositioner::~QQuickPopupPositioner()
-{
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-}
-
-QQuickPopup *QQuickPopupPositioner::popup() const
-{
- return m_popup;
-}
-
-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());
- // Store the scale property so the end result of any transition that could effect the scale
- // does not influence the top left of the final popup, so it doesn't appear to flip from one
- // position to another as a result
- m_popupScale = m_popup->popupItem()->scale();
- if (m_popup->popupItem()->isVisible())
- QQuickPopupPrivate::get(m_popup)->reposition();
-}
-
-void QQuickPopupPositioner::reposition()
-{
- QQuickItem *popupItem = m_popup->popupItem();
- if (!popupItem->isVisible())
- return;
-
- if (m_positioning) {
- popupItem->polish();
- return;
- }
-
- const qreal w = popupItem->width() * m_popupScale;
- const qreal h = popupItem->height() * m_popupScale;
- const qreal iw = popupItem->implicitWidth() * m_popupScale;
- const qreal ih = popupItem->implicitHeight() * m_popupScale;
-
- bool widthAdjusted = false;
- bool heightAdjusted = false;
- QQuickPopupPrivate *p = QQuickPopupPrivate::get(m_popup);
-
- const QQuickItem *centerInParent = p->anchors ? p->getAnchors()->centerIn() : nullptr;
- const QQuickOverlay *centerInOverlay = qobject_cast<const QQuickOverlay*>(centerInParent);
- QRectF rect(!centerInParent ? p->allowHorizontalMove ? p->x : popupItem->x() : 0,
- !centerInParent ? p->allowVerticalMove ? p->y : popupItem->y() : 0,
- !p->hasWidth && iw > 0 ? iw : w,
- !p->hasHeight && ih > 0 ? ih : h);
- if (m_parentItem) {
- // m_parentItem is the parent that the popup should open in,
- // and popupItem()->parentItem() is the overlay, so the mapToItem() calls below
- // effectively map the rect to scene coordinates.
- if (centerInParent) {
- if (centerInParent != parentItem() && !centerInOverlay) {
- qmlWarning(m_popup) << "Popup can only be centered within its immediate parent or Overlay.overlay";
- return;
- }
-
- if (centerInOverlay) {
- rect.moveCenter(QPointF(qRound(centerInOverlay->width() / 2.0), qRound(centerInOverlay->height() / 2.0)));
- } else {
- const QPointF parentItemCenter = QPointF(qRound(m_parentItem->width() / 2), qRound(m_parentItem->height() / 2));
- rect.moveCenter(m_parentItem->mapToItem(popupItem->parentItem(), parentItemCenter));
- }
- } else {
- rect.moveTopLeft(m_parentItem->mapToItem(popupItem->parentItem(), rect.topLeft()));
- }
-
- if (p->window) {
- const QMarginsF margins = p->getMargins();
- QRectF bounds(qMax<qreal>(0.0, margins.left()),
- qMax<qreal>(0.0, margins.top()),
- p->window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
- p->window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
- if (p->window->contentOrientation() == Qt::LandscapeOrientation || p->window->contentOrientation() == Qt::InvertedLandscapeOrientation)
- bounds = bounds.transposed();
-
- // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
- if (p->allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- const QRectF flipped(m_parentItem->mapToScene(QPointF(m_parentItem->width() - p->x - rect.width(), p->y)), rect.size());
- 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 (p->allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- const QRectF flipped(m_parentItem->mapToScene(QPointF(p->x, m_parentItem->height() - p->y - rect.height())), rect.size());
- if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
- rect.moveTop(flipped.top());
- }
-
- // push inside the margins if specified
- if (p->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 (p->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 (p->allowHorizontalMove && p->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 (p->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 (p->allowVerticalMove && p->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 (p->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;
- }
- }
- }
-
- m_positioning = true;
-
- popupItem->setPosition(rect.topLeft());
-
- // If the popup was assigned a parent, rect will be in scene coordinates,
- // so we need to map its top left back to item coordinates.
- // However, if centering within the overlay, the coordinates will be relative
- // to the window, so we don't need to do anything.
- const QPointF effectivePos = m_parentItem && !centerInOverlay ? m_parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
- if (!qFuzzyCompare(p->effectiveX, effectivePos.x())) {
- p->effectiveX = effectivePos.x();
- emit m_popup->xChanged();
- }
- if (!qFuzzyCompare(p->effectiveY, effectivePos.y())) {
- p->effectiveY = effectivePos.y();
- emit m_popup->yChanged();
- }
-
- if (!p->hasWidth && widthAdjusted && rect.width() > 0)
- popupItem->setWidth(rect.width() / m_popupScale);
- if (!p->hasHeight && heightAdjusted && rect.height() > 0)
- popupItem->setHeight(rect.height() / m_popupScale);
- m_positioning = false;
-}
-
-void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
-{
- if (m_parentItem && m_popup->popupItem()->isVisible())
- QQuickPopupPrivate::get(m_popup)->reposition();
-}
-
-void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
-{
- addAncestorListeners(parent);
-}
-
-void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
-{
- if (child == m_parentItem || child->isAncestorOf(m_parentItem))
- removeAncestorListeners(item);
-}
-
-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)->updateOrAddItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-QT_END_NAMESPACE