diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-04-23 20:26:35 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-04-25 03:48:09 +0000 |
commit | 99fa43b3708d6615e17d0cc5561aca78a9c72d1a (patch) | |
tree | a8891fc183b5da10eb53d14184d9c789f51d49fc /src | |
parent | dd0a29bb332b8ed0acfdf72ab2072be3bbd84006 (diff) |
Promote QQuickToolTip's repositioning code to QQuickPopup
QQuickToolTip already had repositioning implemented for both horizontal
and vertical directions. Promote that code up to QQuickPopup so that
QQuickMenu gets properly repositioned when used as a context menu.
As special cases, QQuickComboBox enables vertical flipping for its
popup, and QQuickToolTip enables both. In the QQuickPopup base class,
both are disabled by default.
Task-number: QTBUG-52608
Change-Id: Ia8f835321222d4841a6f79434822b33f057d13fc
Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 77 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquicktooltip.cpp | 87 |
4 files changed, 68 insertions, 104 deletions
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 1d6c0250..1c007496 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -37,7 +37,7 @@ #include "qquickcombobox_p.h" #include "qquickcontrol_p_p.h" #include "qquickabstractbutton_p.h" -#include "qquickpopup_p.h" +#include "qquickpopup_p_p.h" #include <QtCore/qregexp.h> #include <QtGui/qpa/qplatformtheme.h> @@ -620,8 +620,10 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) return; delete d->popup; - if (popup) + if (popup) { + QQuickPopupPrivate::get(popup)->allowVerticalFlip = true; popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent); + } d->popup = popup; emit popupChanged(); } diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 2ca16b29..13e562d0 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -127,6 +127,8 @@ QQuickPopupPrivate::QQuickPopupPrivate() , hasLeftMargin(false) , hasRightMargin(false) , hasBottomMargin(false) + , allowVerticalFlip(false) + , allowHorizontalFlip(false) , x(0) , y(0) , margins(0) @@ -532,7 +534,9 @@ void QQuickPopupPrivate::reposition() const qreal iw = popupItem->implicitWidth(); const qreal ih = popupItem->implicitHeight(); - bool adjusted = false; + bool widthAdjusted = false; + bool heightAdjusted = false; + QRectF rect(x, y, iw > 0 ? iw : w, ih > 0 ? ih : h); if (parentItem) { rect = parentItem->mapRectToScene(rect); @@ -552,33 +556,70 @@ void QQuickPopupPrivate::reposition() if (margins.right() > 0 && rect.right() > bounds.right()) rect.moveRight(bounds.right()); + if (rect.left() < bounds.left() || rect.right() > bounds.right()) { + if (allowHorizontalFlip) { + // if the tooltip doesn't fit inside the window, try flipping it around (left <-> 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 (iw > 0) { + // neither the flipped around geometry fits inside the window, choose + // whichever side (left vs. right) fits larger part of the popup + 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 width to fit the window + if (rect.left() < bounds.left()) { + rect.setLeft(bounds.left()); + widthAdjusted = true; + } + if (rect.right() > bounds.right()) { + rect.setRight(bounds.right()); + widthAdjusted = true; + } + } + } + if (rect.top() < bounds.top() || rect.bottom() > bounds.bottom()) { - // if the popup doesn't fit inside the window, try flipping it around (below <-> above) - const QRectF flipped = parentItem->mapRectToScene(QRectF(x, parentItem->height() - y - rect.height(), rect.width(), rect.height())); - if (flipped.top() >= bounds.top() && flipped.bottom() < bounds.bottom()) { - adjusted = true; - rect = flipped; - } else if (ih > 0) { + if (allowVerticalFlip) { + // if the tooltip doesn't fit inside the window, try flipping it around (above <-> below) + 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()); + } + + if (ih > 0) { // neither the flipped around geometry fits inside the window, choose // whichever side (above vs. below) fits larger part of the popup - const QRectF primary = rect.intersected(bounds); - const QRectF secondary = flipped.intersected(bounds); - - if (primary.height() > secondary.height()) { - rect.setY(primary.y()); - rect.setHeight(primary.height()); - } else { - rect.setY(secondary.y()); - rect.setHeight(secondary.height()); + 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 height to fit the window + if (rect.top() < bounds.top()) { + rect.setTop(bounds.top()); + heightAdjusted = true; + } + if (rect.bottom() > bounds.bottom()) { + rect.setBottom(bounds.bottom()); + heightAdjusted = true; } - adjusted = true; } } } } popupItem->setPosition(rect.topLeft()); - if (adjusted && ih > 0) + if (widthAdjusted && rect.width() > 0) + popupItem->setWidth(rect.width()); + if (heightAdjusted && rect.height() > 0) popupItem->setHeight(rect.height()); } diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 4e123170..a765998a 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -182,6 +182,8 @@ public: bool hasLeftMargin; bool hasRightMargin; bool hasBottomMargin; + bool allowVerticalFlip; + bool allowHorizontalFlip; qreal x; qreal y; qreal margins; diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index f7d011c1..0992c2e4 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -127,8 +127,6 @@ public: void startTimeout(); void stopTimeout(); - void reposition() override; - int delay; int timeout; QString text; @@ -160,91 +158,12 @@ void QQuickToolTipPrivate::stopTimeout() timeoutTimer.stop(); } -void QQuickToolTipPrivate::reposition() -{ - Q_Q(QQuickToolTip); - 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(x, y, iw > 0 ? iw : w, ih > 0 ? ih : h); - if (parentItem) { - rect = parentItem->mapRectToScene(rect); - - QQuickWindow *window = q->window(); - if (window) { - const QRectF bounds = QRectF(0, 0, window->width(), window->height()).marginsRemoved(getMargins()); - - if (rect.left() < bounds.left() || rect.right() > bounds.right()) { - // if the tooltip doesn't fit inside the window, try flipping it around (left <-> 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 (iw > 0) { - // neither the flipped around geometry fits inside the window, choose - // whichever side (left vs. right) fits larger part of the popup - 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 width to fit the window - if (rect.left() < bounds.left()) { - rect.setLeft(bounds.left()); - widthAdjusted = true; - } - if (rect.right() > bounds.right()) { - rect.setRight(bounds.right()); - widthAdjusted = true; - } - } - } - - if (rect.top() < bounds.top() || rect.bottom() > bounds.bottom()) { - // if the tooltip doesn't fit inside the window, try flipping it around (above <-> below) - 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()); - - if (ih > 0) { - // neither the flipped around geometry fits inside the window, choose - // whichever side (above vs. below) fits larger part of the popup - 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 height to fit the window - if (rect.top() < bounds.top()) { - rect.setTop(bounds.top()); - heightAdjusted = true; - } - if (rect.bottom() > bounds.bottom()) { - rect.setBottom(bounds.bottom()); - heightAdjusted = true; - } - } - } - } - } - - popupItem->setPosition(rect.topLeft()); - if (widthAdjusted && rect.width() > 0) - popupItem->setWidth(rect.width()); - if (heightAdjusted && rect.height() > 0) - popupItem->setHeight(rect.height()); -} - QQuickToolTip::QQuickToolTip(QQuickItem *parent) : QQuickPopup(*(new QQuickToolTipPrivate), parent) { + Q_D(QQuickToolTip); + d->allowVerticalFlip = true; + d->allowHorizontalFlip = true; } /*! |