diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-09-15 10:09:36 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-09-21 21:39:47 +0000 |
commit | 244356ba182c2807ef9b15eb71ac16a568d65642 (patch) | |
tree | 15d6590511f983e98c909763a274bead9de9ee8b /src | |
parent | 175d0ea3f80af0ca32baec489d8ea66dd4ee3418 (diff) |
QQuickDrawer: allow resizing and positioning
Make QQuickDrawer re-use QQuickPopup's reposition() implementation.
This way QQuickDrawer gains support for proper positioning and margins
"for free". Now it is possible to place Drawer below the window header,
for instance:
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
visible: true
header: ToolBar { }
Drawer {
y: header.height
width: window.width * 0.6
height: window.height - header.height
}
}
[ChangeLog][Controls][Drawer] Made it possible to control the vertical
position of a horizontal drawer, and vice versa. This allows placing
a drawer below a header/toolbar, for instance.
Task-number: QTBUG-55360
Change-Id: I63621195efeefa2ea88935d676771b392e0a4030
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quicktemplates2/qquickdrawer.cpp | 73 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdrawer_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdrawer_p_p.h | 3 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 81 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p_p.h | 4 |
5 files changed, 131 insertions, 32 deletions
diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp index 4c850473..80cd95c9 100644 --- a/src/quicktemplates2/qquickdrawer.cpp +++ b/src/quicktemplates2/qquickdrawer.cpp @@ -91,6 +91,32 @@ QT_BEGIN_NAMESPACE \l {Popup::}{parent} to something else to make the drawer operate in a specific coordinate space. + Drawer can be configured to cover only part of its window edge. The following example + illustrates how Drawer can be positioned to appear below a window header: + + \code + import QtQuick 2.7 + import QtQuick.Controls 2.0 + + ApplicationWindow { + id: window + visible: true + + header: ToolBar { } + + Drawer { + y: header.height + width: window.width * 0.6 + height: window.height - header.height + } + } + \endcode + + The \l position property determines how much of the drawer is visible, as + a value between \c 0.0 and \c 1.0. It is not possible to set the x-coordinate + (or horizontal margins) of a drawer at the left or right window edge, or the + y-coordinate (or vertical margins) of a drawer at the top or bottom window edge. + In the image above, the application's contents are \e "pushed" across the screen. This is achieved by applying a translation to the contents: @@ -139,6 +165,7 @@ QQuickDrawerPrivate::QQuickDrawerPrivate() : edge(Qt::LeftEdge), offset(0), position(0), dragMargin(QGuiApplication::styleHints()->startDragDistance()) { + setEdge(Qt::LeftEdge); } qreal QQuickDrawerPrivate::positionAt(const QPointF &point) const @@ -183,6 +210,27 @@ void QQuickDrawerPrivate::reposition() popupItem->setY(window->height() - position * popupItem->height()); break; } + + QQuickPopupPrivate::reposition(); +} + +void QQuickDrawerPrivate::resizeOverlay() +{ + if (!dimmer || !window) + return; + + QRectF geometry(0, 0, window->width(), window->height()); + + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) { + geometry.setY(popupItem->y()); + geometry.setHeight(popupItem->height()); + } else { + geometry.setX(popupItem->x()); + geometry.setWidth(popupItem->width()); + } + + dimmer->setPosition(geometry.topLeft()); + dimmer->setSize(geometry.size()); } static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int threshold = -1) @@ -402,6 +450,22 @@ bool QQuickDrawerPrivate::prepareExitTransition() return QQuickPopupPrivate::prepareExitTransition(); } +void QQuickDrawerPrivate::setEdge(Qt::Edge e) +{ + edge = e; + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) { + allowVerticalMove = true; + allowVerticalResize = true; + allowHorizontalMove = false; + allowHorizontalResize = false; + } else { + allowVerticalMove = false; + allowVerticalResize = false; + allowHorizontalMove = true; + allowHorizontalResize = true; + } +} + QQuickDrawer::QQuickDrawer(QObject *parent) : QQuickPopup(*(new QQuickDrawerPrivate), parent) { @@ -434,7 +498,7 @@ void QQuickDrawer::setEdge(Qt::Edge edge) if (d->edge == edge) return; - d->edge = edge; + d->setEdge(edge); if (isComponentComplete()) d->reposition(); emit edgeChanged(); @@ -559,4 +623,11 @@ bool QQuickDrawer::overlayEvent(QQuickItem *item, QEvent *event) } } +void QQuickDrawer::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickDrawer); + QQuickPopup::geometryChanged(newGeometry, oldGeometry); + d->resizeOverlay(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickdrawer_p.h b/src/quicktemplates2/qquickdrawer_p.h index e694e27b..bada1344 100644 --- a/src/quicktemplates2/qquickdrawer_p.h +++ b/src/quicktemplates2/qquickdrawer_p.h @@ -87,6 +87,8 @@ protected: void mouseUngrabEvent() override; bool overlayEvent(QQuickItem *item, QEvent *event) override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + private: Q_DISABLE_COPY(QQuickDrawer) Q_DECLARE_PRIVATE(QQuickDrawer) diff --git a/src/quicktemplates2/qquickdrawer_p_p.h b/src/quicktemplates2/qquickdrawer_p_p.h index f14c36dd..b7555c3e 100644 --- a/src/quicktemplates2/qquickdrawer_p_p.h +++ b/src/quicktemplates2/qquickdrawer_p_p.h @@ -68,6 +68,7 @@ public: qreal positionAt(const QPointF &point) const; void reposition() override; + void resizeOverlay() override; bool startDrag(QQuickWindow *window, QMouseEvent *event); bool grabMouse(QMouseEvent *event); @@ -80,6 +81,8 @@ public: bool prepareEnterTransition() override; bool prepareExitTransition() override; + void setEdge(Qt::Edge edge); + Qt::Edge edge; qreal offset; qreal position; diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 22b399b1..6deda711 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -133,6 +133,10 @@ QQuickPopupPrivate::QQuickPopupPrivate() , hasBottomMargin(false) , allowVerticalFlip(false) , allowHorizontalFlip(false) + , allowVerticalMove(true) + , allowHorizontalMove(true) + , allowVerticalResize(true) + , allowHorizontalResize(true) , hadActiveFocusBeforeExitTransition(false) , x(0) , y(0) @@ -589,7 +593,10 @@ void QQuickPopupPrivate::reposition() bool widthAdjusted = false; bool heightAdjusted = false; - QRectF rect(x, y, !hasWidth && iw > 0 ? iw : w, !hasHeight && ih > 0 ? ih : h); + 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); @@ -615,31 +622,39 @@ void QQuickPopupPrivate::reposition() } // push inside the margins if specified - 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 (margins.left() >= 0 && rect.left() < bounds.left()) - rect.moveLeft(margins.left()); - if (margins.right() >= 0 && rect.right() > bounds.right()) - rect.moveRight(bounds.right()); + 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 (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()); + 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 (rect.left() < bounds.left()) { - rect.setLeft(bounds.left()); - widthAdjusted = true; - } - if (rect.right() > bounds.right()) { - rect.setRight(bounds.right()); - widthAdjusted = true; + 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) { @@ -651,19 +666,23 @@ void QQuickPopupPrivate::reposition() 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 (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()); + 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 (rect.top() < bounds.top()) { - rect.setTop(bounds.top()); - heightAdjusted = true; - } - if (rect.bottom() > bounds.bottom()) { - rect.setBottom(bounds.bottom()); - heightAdjusted = true; + 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) { diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 321adaf5..c9f5e264 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -192,6 +192,10 @@ public: bool hasBottomMargin; bool allowVerticalFlip; bool allowHorizontalFlip; + bool allowVerticalMove; + bool allowHorizontalMove; + bool allowVerticalResize; + bool allowHorizontalResize; bool hadActiveFocusBeforeExitTransition; qreal x; qreal y; |