diff options
Diffstat (limited to 'src/quick')
| -rw-r--r-- | src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml | 74 | ||||
| -rw-r--r-- | src/quick/doc/snippets/pointerHandlers/draggableGridView.qml | 168 | ||||
| -rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 92 | ||||
| -rw-r--r-- | src/quick/items/qquickgridview.cpp | 46 | ||||
| -rw-r--r-- | src/quick/items/qquicklistview.cpp | 17 | ||||
| -rw-r--r-- | src/quick/items/qquicktableview.cpp | 34 | ||||
| -rw-r--r-- | src/quick/items/qquicktext.cpp | 4 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgadaptationlayer.cpp | 7 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgdefaultglyphnode.cpp | 7 | ||||
| -rw-r--r-- | src/quick/util/qquickanimation.cpp | 5 |
10 files changed, 435 insertions, 19 deletions
diff --git a/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml b/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml new file mode 100644 index 0000000000..20a3a802cf --- /dev/null +++ b/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick + +//! [entire] +Item { + width: 320 + height: 240 + //![draggable] + Rectangle { + width: 24 + height: 24 + border.color: "steelblue" + Text { + text: "it's\ntiny" + font.pixelSize: 7 + rotation: -45 + anchors.centerIn: parent + } + + DragHandler { + margin: 12 + } + } + //![draggable] +} +//! [entire] diff --git a/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml b/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml new file mode 100644 index 0000000000..0b19274e0d --- /dev/null +++ b/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +pragma ComponentBehavior: Bound +import QtQml +import QtQuick +import QtQml.Models + +//! [entire] +GridView { + id: root + width: 320 + height: 480 + cellWidth: 80 + cellHeight: 80 + interactive: false + + displaced: Transition { + NumberAnimation { + properties: "x,y" + easing.type: Easing.OutQuad + } + } + + model: DelegateModel { + id: visualModel + model: 24 + property var dropTarget: undefined + property bool copy: false + delegate: DropArea { + id: delegateRoot + + width: 80 + height: 80 + + onEntered: drag => { + if (visualModel.copy) { + if (drag.source !== icon) + visualModel.dropTarget = icon + } else { + visualModel.items.move(drag.source.DelegateModel.itemsIndex, icon.DelegateModel.itemsIndex) + } + } + + Rectangle { + id: icon + objectName: DelegateModel.itemsIndex + + property string text + Component.onCompleted: { + color = Qt.rgba(0.2 + (48 - DelegateModel.itemsIndex) * Math.random() / 48, + 0.3 + DelegateModel.itemsIndex * Math.random() / 48, + 0.4 * Math.random(), + 1.0) + text = DelegateModel.itemsIndex + } + border.color: visualModel.dropTarget === this ? "black" : "transparent" + border.width: 2 + radius: 3 + width: 72 + height: 72 + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + states: [ + State { + when: dragHandler.active || controlDragHandler.active + ParentChange { + target: icon + parent: root + } + + AnchorChanges { + target: icon + anchors { + horizontalCenter: undefined + verticalCenter: undefined + } + } + } + ] + + Text { + anchors.centerIn: parent + color: "white" + font.pointSize: 14 + text: controlDragHandler.active ? "+" : icon.text + } + + //! [draghandlers] + DragHandler { + id: dragHandler + acceptedModifiers: Qt.NoModifier + onActiveChanged: if (!active) visualModel.dropTarget = undefined + } + + DragHandler { + id: controlDragHandler + acceptedModifiers: Qt.ControlModifier + onActiveChanged: { + visualModel.copy = active + if (!active) { + visualModel.dropTarget.text = icon.text + visualModel.dropTarget.color = icon.color + visualModel.dropTarget = undefined + } + } + } + //! [draghandlers] + + Drag.active: dragHandler.active || controlDragHandler.active + Drag.source: icon + Drag.hotSpot.x: 36 + Drag.hotSpot.y: 36 + } + } + } +} +//! [entire] diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 8c9464ee55..c3f57f9b02 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -86,7 +86,8 @@ Q_LOGGING_CATEGORY(lcDragHandler, "qt.quick.handler.drag") \c target is an Item, \c centroid is the point at which the drag begins and to which the \c target will be moved (subject to constraints). - At this time, drag-and-drop is not yet supported. + DragHandler can be used together with the \l Drag attached property to + implement drag-and-drop. \sa Drag, MouseArea, {Pointer Handlers Example} */ @@ -134,7 +135,7 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDe The snap mode configures snapping of the \l target item's center to the \l eventPoint. Possible values: - \value DragHandler.SnapNever Never snap + \value DragHandler.NoSnap Never snap \value DragHandler.SnapAuto The \l target snaps if the \l eventPoint was pressed outside of the \l target item \e and the \l target is a descendant of \l {PointerHandler::}{parent} item (default) \value DragHandler.SnapWhenPressedOutsideTarget The \l target snaps if the \l eventPoint was pressed outside of the \l target @@ -394,6 +395,93 @@ void QQuickDragHandler::setActiveTranslation(const QVector2D &trans) \c {0, 0} again. */ +/*! + \qmlproperty flags QtQuick::DragHandler::acceptedButtons + + The mouse buttons that can activate this DragHandler. + + By default, this property is set to + \l {QtQuick::MouseEvent::button} {Qt.LeftButton}. + It can be set to an OR combination of mouse buttons, and will ignore events + from other buttons. + + For example, if a component (such as TextEdit) already handles + left-button drags in its own way, it can be augmented with a + DragHandler that does something different when dragged via the + right button: + + \snippet pointerHandlers/dragHandlerAcceptedButtons.qml 0 +*/ + +/*! + \qmlproperty flags DragHandler::acceptedDevices + + The types of pointing devices that can activate this DragHandler. + + By default, this property is set to + \l{QInputDevice::DeviceType}{PointerDevice.AllDevices}. + If you set it to an OR combination of device types, it will ignore events + from non-matching devices. + + \note Not all platforms are yet able to distinguish mouse and touchpad; and + on those that do, you often want to make mouse and touchpad behavior the same. +*/ + +/*! + \qmlproperty flags DragHandler::acceptedModifiers + + If this property is set, it will require the given keyboard modifiers to + be pressed in order to react to pointer events, and otherwise ignore them. + + For example, two DragHandlers can perform two different drag-and-drop + operations, depending on whether the \c Control modifier is pressed: + + \snippet pointerHandlers/draggableGridView.qml entire + + If this property is set to \c Qt.KeyboardModifierMask (the default value), + then the DragHandler ignores the modifier keys. + + If you set \c acceptedModifiers to an OR combination of modifier keys, + it means \e all of those modifiers must be pressed to activate the handler. + + The available modifiers are as follows: + + \value NoModifier No modifier key is allowed. + \value ShiftModifier A Shift key on the keyboard must be pressed. + \value ControlModifier A Ctrl key on the keyboard must be pressed. + \value AltModifier An Alt key on the keyboard must be pressed. + \value MetaModifier A Meta key on the keyboard must be pressed. + \value KeypadModifier A keypad button must be pressed. + \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument). + A Mode_switch key on the keyboard must be pressed. + \value KeyboardModifierMask The handler does not care which modifiers are pressed. + + \sa Qt::KeyboardModifier +*/ + +/*! + \qmlproperty flags DragHandler::acceptedPointerTypes + + The types of pointing instruments (finger, stylus, eraser, etc.) + that can activate this DragHandler. + + By default, this property is set to + \l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}. + If you set it to an OR combination of device types, it will ignore events + from non-matching \l {PointerDevice}{devices}. +*/ + +/*! + \qmlproperty real DragHandler::margin + + The margin beyond the bounds of the \l {PointerHandler::parent}{parent} + item within which an \l eventPoint can activate this handler. For example, + you can make it easier to drag small items by allowing the user to drag + from a position nearby: + + \snippet pointerHandlers/dragHandlerMargin.qml draggable +*/ + QT_END_NAMESPACE #include "moc_qquickdraghandler_p.cpp" diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 916ae61cf5..27438bda14 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -1404,9 +1404,53 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) /*! \qmlproperty int QtQuick::GridView::count - This property holds the number of items in the view. + This property holds the number of items in the model. */ +/*! + \qmlproperty bool QtQuick::GridView::reuseItems + + This property enables you to reuse items that are instantiated + from the \l delegate. If set to \c false, any currently + pooled items are destroyed. + + This property is \c false by default. + + \since 5.15 + + \sa {Reusing items}, pooled(), reused() +*/ + +/*! + \qmlattachedsignal QtQuick::GridView::pooled() + + This signal is emitted after an item has been added to the reuse + pool. You can use it to pause ongoing timers or animations inside + the item, or free up resources that cannot be reused. + + This signal is emitted only if the \l reuseItems property is \c true. + + \sa {Reusing items}, reuseItems, reused() +*/ + +/*! + \qmlattachedsignal QtQuick::GridView::reused() + + This signal is emitted after an item has been reused. At this point, the + item has been taken out of the pool and placed inside the content view, + and the model properties such as \c index and \c row have been updated. + + Other properties that are not provided by the model does not change when an + item is reused. You should avoid storing any state inside a delegate, but if + you do, manually reset that state on receiving this signal. + + This signal is emitted when the item is reused, and not the first time the + item is created. + + This signal is emitted only if the \l reuseItems property is \c true. + + \sa {Reusing items}, reuseItems, pooled() +*/ /*! \qmlproperty Component QtQuick::GridView::highlight diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 9e7a8f4803..6c822e62c1 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -1721,7 +1721,7 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte updateHighlight(); bottomItem = currentItem; } - qreal pos; + qreal pos = 0; bool isInBounds = -position() > maxExtent && -position() <= minExtent; if (header && !topItem && isInBounds) { @@ -1802,6 +1802,19 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte QQuickItemViewPrivate::fixup(data, minExtent, maxExtent); return; } + // If we have the CurrentLabelAtStart flag set, then we need to consider + // the section size while calculating the position + if (sectionCriteria + && (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart) + && currentSectionItem) { + auto sectionSize = (orient == QQuickListView::Vertical) ? currentSectionItem->height() + : currentSectionItem->width(); + if (isContentFlowReversed()) + pos += sectionSize; + else + pos -= sectionSize; + } + pos = qBound(-minExtent, pos, -maxExtent); qreal dist = qAbs(data.move + pos); @@ -2380,7 +2393,7 @@ QQuickListView::~QQuickListView() /*! \qmlproperty int QtQuick::ListView::count - This property holds the number of items in the view. + This property holds the number of items in the model. */ /*! diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 9b0334b851..490e89acad 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -3297,11 +3297,18 @@ void QQuickTableViewPrivate::syncSyncView() q->setColumnSpacing(syncView->columnSpacing()); updateContentWidth(); - if (syncView->leftColumn() != q->leftColumn()) { - // The left column is no longer the same as the left - // column in syncView. This requires a rebuild. - scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn; - scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly); + if (scheduledRebuildOptions & RebuildOption::LayoutOnly) { + if (syncView->leftColumn() != q->leftColumn() + || syncView->d_func()->loadedTableOuterRect.left() != loadedTableOuterRect.left()) { + // The left column is no longer the same, or at the same pos, as the left column in + // syncView. This can happen if syncView did a relayout that caused its left column + // to be resized so small that it ended up outside the viewport. It can also happen + // if the syncView loaded and unloaded columns after the relayout. We therefore need + // to sync our own left column and pos to be the same, which we do by rebuilding the + // whole viewport instead of just doing a plain LayoutOnly. + scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn; + scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly); + } } } @@ -3309,11 +3316,18 @@ void QQuickTableViewPrivate::syncSyncView() q->setRowSpacing(syncView->rowSpacing()); updateContentHeight(); - if (syncView->topRow() != q->topRow()) { - // The top row is no longer the same as the top - // row in syncView. This requires a rebuild. - scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow; - scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly); + if (scheduledRebuildOptions & RebuildOption::LayoutOnly) { + if (syncView->topRow() != q->topRow() + || syncView->d_func()->loadedTableOuterRect.top() != loadedTableOuterRect.top()) { + // The top row is no longer the same, or at the same pos, as the top row in + // syncView. This can happen if syncView did a relayout that caused its top row + // to be resized so small that it ended up outside the viewport. It can also happen + // if the syncView loaded and unloaded rows after the relayout. We therefore need + // to sync our own top row and pos to be the same, which we do by rebuilding the + // whole viewport instead of just doing a plain LayoutOnly. + scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow; + scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly); + } } } diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index cef0dd2900..cdbcf46380 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2462,8 +2462,10 @@ void QQuickText::geometryChange(const QRectF &newGeometry, const QRectF &oldGeom } } } else if (!heightChanged && widthMaximum) { - if (!qFuzzyIsNull(oldGeometry.width())) { + if (oldGeometry.width() > 0) { // no change to height, width is adequate and wasn't 0 before + // (old width could also be negative if it was 0 and the margins + // were set) goto geomChangeDone; } } diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 9d18868c58..d3aa5ef7a8 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -190,7 +190,12 @@ void QSGDistanceFieldGlyphCache::update() distanceFields.reserve(pendingGlyphsSize); for (int i = 0; i < pendingGlyphsSize; ++i) { GlyphData &gd = glyphData(m_pendingGlyphs.at(i)); - distanceFields.append(QDistanceField(gd.path, + + QSize size = QSize(qCeil(gd.texCoord.width + gd.texCoord.xMargin * 2), + qCeil(gd.texCoord.height + gd.texCoord.yMargin * 2)); + + distanceFields.append(QDistanceField(size, + gd.path, m_pendingGlyphs.at(i), m_doubleGlyphResolution)); gd.path = QPainterPath(); // no longer needed, so release memory used by the painter path diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp index d3e0d5a7c5..fbc2227bae 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp @@ -83,11 +83,14 @@ void QSGDefaultGlyphNode::update() QRawFont font = m_glyphs.rawFont(); QMargins margins(0, 0, 0, 0); - if (m_style == QQuickText::Normal) { + const auto *fontEngine = QRawFontPrivate::get(font)->fontEngine; + const bool isColorFont = fontEngine->glyphFormat == QFontEngine::Format_ARGB; + + if (m_style == QQuickText::Normal || isColorFont) { QFontEngine::GlyphFormat glyphFormat; // Don't try to override glyph format of color fonts - if (QRawFontPrivate::get(font)->fontEngine->glyphFormat == QFontEngine::Format_ARGB) { + if (isColorFont) { glyphFormat = QFontEngine::Format_None; } else { switch (m_preferredAntialiasingMode) { diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index af60f5b02b..a2003fdc37 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -310,6 +310,11 @@ void QQuickAbstractAnimation::setRunning(bool r) // Therefore, the state of d->running will in that case be different than r if we are back in // the root stack frame of the recursive calls to setRunning() emit runningChanged(d->running); + } else if (d->animationInstance) { + // If there was a recursive call, make sure the d->running is set correctly + d->running = d->animationInstance->isRunning(); + } else { + d->running = r; } } |
