aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickanimatedimage.cpp11
-rw-r--r--src/quick/items/qquickanimatedimage_p_p.h12
-rw-r--r--src/quick/items/qquickborderimage.cpp98
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickborderimage_p_p.h30
-rw-r--r--src/quick/items/qquickdrag.cpp46
-rw-r--r--src/quick/items/qquickdrag_p.h6
-rw-r--r--src/quick/items/qquickitem.cpp37
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickrectangle.cpp1
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp183
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h39
-rw-r--r--src/quick/items/qquickspriteengine.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp33
-rw-r--r--src/quick/items/qquicktextcontrol.cpp30
-rw-r--r--src/quick/items/qquicktextcontrol_p.h3
-rw-r--r--src/quick/items/qquicktextedit.cpp60
-rw-r--r--src/quick/items/qquicktextedit_p.h5
-rw-r--r--src/quick/items/qquicktextinput.cpp90
-rw-r--r--src/quick/items/qquicktextinput_p.h5
-rw-r--r--src/quick/items/qquicktextinput_p_p.h2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp4
-rw-r--r--src/quick/items/qquickview.cpp3
-rw-r--r--src/quick/items/qquickwindow.cpp55
-rw-r--r--src/quick/items/qquickwindow_p.h5
26 files changed, 691 insertions, 74 deletions
diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index ab5170cd65..6f14bf15fe 100644
--- a/src/quick/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
@@ -47,8 +47,10 @@
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlengine.h>
#include <QtGui/qmovie.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -144,8 +146,10 @@ QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent)
QQuickAnimatedImage::~QQuickAnimatedImage()
{
Q_D(QQuickAnimatedImage);
+#ifndef QT_NO_NETWORK
if (d->reply)
d->reply->deleteLater();
+#endif
delete d->_movie;
qDeleteAll(d->frameMap);
d->frameMap.clear();
@@ -264,10 +268,12 @@ void QQuickAnimatedImage::setSource(const QUrl &url)
if (url == d->url)
return;
+#ifndef QT_NO_NETWORK
if (d->reply) {
d->reply->deleteLater();
d->reply = 0;
}
+#endif
d->setImage(QImage());
qDeleteAll(d->frameMap);
@@ -319,6 +325,7 @@ void QQuickAnimatedImage::load()
d->_movie = new QMovie(lf);
movieRequestFinished();
} else {
+#ifndef QT_NO_NETWORK
if (d->status != Loading) {
d->status = Loading;
emit statusChanged(d->status);
@@ -335,6 +342,7 @@ void QQuickAnimatedImage::load()
this, SLOT(movieRequestFinished()));
QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(requestProgress(qint64,qint64)));
+#endif
}
}
}
@@ -343,8 +351,10 @@ void QQuickAnimatedImage::load()
void QQuickAnimatedImage::movieRequestFinished()
{
+
Q_D(QQuickAnimatedImage);
+#ifndef QT_NO_NETWORK
if (d->reply) {
d->redirectCount++;
if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
@@ -360,6 +370,7 @@ void QQuickAnimatedImage::movieRequestFinished()
d->redirectCount=0;
d->_movie = new QMovie(d->reply);
}
+#endif
if (!d->_movie->isValid()) {
qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h
index 6d32f1071f..ed735d1c9c 100644
--- a/src/quick/items/qquickanimatedimage_p_p.h
+++ b/src/quick/items/qquickanimatedimage_p_p.h
@@ -58,7 +58,9 @@
QT_BEGIN_NAMESPACE
class QMovie;
+#ifndef QT_NO_NETWORK
class QNetworkReply;
+#endif
class QQuickAnimatedImagePrivate : public QQuickImagePrivate
{
@@ -66,7 +68,11 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate
public:
QQuickAnimatedImagePrivate()
- : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0), oldPlaying(false), currentSourceSize(0, 0)
+ : playing(true), paused(false), preset_currentframe(0), _movie(0), oldPlaying(false)
+#ifndef QT_NO_NETWORK
+ , reply(0), redirectCount(0)
+#endif
+ , currentSourceSize(0, 0)
{
}
@@ -76,9 +82,11 @@ public:
bool paused;
int preset_currentframe;
QMovie *_movie;
+ bool oldPlaying;
+#ifndef QT_NO_NETWORK
QNetworkReply *reply;
int redirectCount;
- bool oldPlaying;
+#endif
QMap<int, QQuickPixmap *> frameMap;
QSize currentSourceSize;
};
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 66f414d816..b3a35e6219 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -43,7 +43,9 @@
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlengine.h>
+#ifndef QT_NO_NETWORK
#include <QtNetwork/qnetworkreply.h>
+#endif
#include <QtCore/qfile.h>
#include <QtCore/qmath.h>
#include <QtGui/qguiapplication.h>
@@ -169,9 +171,11 @@ QQuickBorderImage::QQuickBorderImage(QQuickItem *parent)
QQuickBorderImage::~QQuickBorderImage()
{
+#ifndef QT_NO_NETWORK
Q_D(QQuickBorderImage);
if (d->sciReply)
d->sciReply->deleteLater();
+#endif
}
/*!
@@ -270,10 +274,12 @@ void QQuickBorderImage::setSource(const QUrl &url)
if (url == d->url)
return;
+#ifndef QT_NO_NETWORK
if (d->sciReply) {
d->sciReply->deleteLater();
d->sciReply = 0;
}
+#endif
d->url = url;
d->sciurl = QUrl();
@@ -311,6 +317,7 @@ void QQuickBorderImage::load()
setGridScaledImage(QQuickGridScaledImage(&file));
return;
} else {
+#ifndef QT_NO_NETWORK
if (d->progress != 0.0) {
d->progress = 0.0;
emit progressChanged(d->progress);
@@ -320,6 +327,7 @@ void QQuickBorderImage::load()
d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
qmlobject_connect(d->sciReply, QNetworkReply, SIGNAL(finished()),
this, QQuickBorderImage, SLOT(sciRequestFinished()))
+#endif
}
} else {
QQuickPixmap::Options options;
@@ -529,6 +537,7 @@ void QQuickBorderImage::requestFinished()
pixmapChange();
}
+#ifndef QT_NO_NETWORK
#define BORDERIMAGE_MAX_REDIRECT 16
void QQuickBorderImage::sciRequestFinished()
@@ -558,12 +567,59 @@ void QQuickBorderImage::sciRequestFinished()
setGridScaledImage(sci);
}
}
+#endif // QT_NO_NETWORK
void QQuickBorderImage::doUpdate()
{
update();
}
+void QQuickBorderImagePrivate::calculateRects(const QQuickScaleGrid *border,
+ const QSize &sourceSize,
+ const QSizeF &targetSize,
+ int horizontalTileMode,
+ int verticalTileMode,
+ qreal devicePixelRatio,
+ QRectF *targetRect,
+ QRectF *innerTargetRect,
+ QRectF *innerSourceRect,
+ QRectF *subSourceRect)
+{
+ *innerSourceRect = QRectF(0, 0, 1, 1);
+ *targetRect = QRectF(0, 0, targetSize.width(), targetSize.height());
+ *innerTargetRect = *targetRect;
+
+ if (border) {
+ *innerSourceRect = QRectF(border->left() * devicePixelRatio / qreal(sourceSize.width()),
+ border->top() * devicePixelRatio / qreal(sourceSize.height()),
+ qMax<qreal>(0, sourceSize.width() - (border->right() + border->left()) * devicePixelRatio) / sourceSize.width(),
+ qMax<qreal>(0, sourceSize.height() - (border->bottom() + border->top()) * devicePixelRatio) / sourceSize.height());
+ *innerTargetRect = QRectF(border->left(),
+ border->top(),
+ qMax<qreal>(0, targetSize.width() - (border->right() + border->left())),
+ qMax<qreal>(0, targetSize.height() - (border->bottom() + border->top())));
+ }
+
+ qreal hTiles = 1;
+ qreal vTiles = 1;
+ const QSizeF innerTargetSize = innerTargetRect->size() * devicePixelRatio;
+ if (innerSourceRect->width() != 0
+ && horizontalTileMode != QQuickBorderImage::Stretch) {
+ hTiles = innerTargetSize.width() / qreal(innerSourceRect->width() * sourceSize.width());
+ if (horizontalTileMode == QQuickBorderImage::Round)
+ hTiles = qCeil(hTiles);
+ }
+ if (innerSourceRect->height() != 0
+ && verticalTileMode != QQuickBorderImage::Stretch) {
+ vTiles = innerTargetSize.height() / qreal(innerSourceRect->height() * sourceSize.height());
+ if (verticalTileMode == QQuickBorderImage::Round)
+ vTiles = qCeil(vTiles);
+ }
+
+ *subSourceRect = QRectF(0, 0, hTiles, vTiles);
+}
+
+
QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickBorderImage);
@@ -588,45 +644,25 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
node->setTexture(texture);
// Don't implicitly create the scalegrid in the rendering thread...
- QRectF innerSourceRect(0, 0, 1, 1);
- QRectF targetRect(0, 0, width(), height());
- QRectF innerTargetRect = targetRect;
- if (d->border) {
- const QQuickScaleGrid *border = d->getScaleGrid();
- innerSourceRect = QRectF(border->left() * d->devicePixelRatio / qreal(d->pix.width()),
- border->top() * d->devicePixelRatio / qreal(d->pix.height()),
- qMax<qreal>(0, d->pix.width() - (border->right() + border->left()) * d->devicePixelRatio) / d->pix.width(),
- qMax<qreal>(0, d->pix.height() - (border->bottom() + border->top()) * d->devicePixelRatio) / d->pix.height());
- innerTargetRect = QRectF(border->left(),
- border->top(),
- qMax<qreal>(0, width() - (border->right() + border->left())),
- qMax<qreal>(0, height() - (border->bottom() + border->top())));
- }
- qreal hTiles = 1;
- qreal vTiles = 1;
- const QSizeF innerTargetSize = innerTargetRect.size() * d->devicePixelRatio;
- if (innerSourceRect.width() != 0
- && d->horizontalTileMode != QQuickBorderImage::Stretch) {
- hTiles = innerTargetSize.width() / qreal(innerSourceRect.width() * d->pix.width());
- if (d->horizontalTileMode == QQuickBorderImage::Round)
- hTiles = qCeil(hTiles);
- }
- if (innerSourceRect.height() != 0
- && d->verticalTileMode != QQuickBorderImage::Stretch) {
- vTiles = innerTargetSize.height() / qreal(innerSourceRect.height() * d->pix.height());
- if (d->verticalTileMode == QQuickBorderImage::Round)
- vTiles = qCeil(vTiles);
- }
+ QRectF targetRect;
+ QRectF innerTargetRect;
+ QRectF innerSourceRect;
+ QRectF subSourceRect;
+ d->calculateRects(d->border,
+ QSize(d->pix.width(), d->pix.height()), QSizeF(width(), height()),
+ d->horizontalTileMode, d->verticalTileMode, d->devicePixelRatio,
+ &targetRect, &innerTargetRect,
+ &innerSourceRect, &subSourceRect);
node->setTargetRect(targetRect);
node->setInnerSourceRect(innerSourceRect);
node->setInnerTargetRect(innerTargetRect);
- node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
+ node->setSubSourceRect(subSourceRect);
node->setMirror(d->mirror);
node->setMipmapFiltering(QSGTexture::None);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) {
+ if (innerSourceRect == QRectF(0, 0, 1, 1) && (subSourceRect.width() > 1 || subSourceRect.height() > 1)) {
node->setHorizontalWrapMode(QSGTexture::Repeat);
node->setVerticalWrapMode(QSGTexture::Repeat);
} else {
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 7f8b172a21..f2764660f6 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -101,7 +101,9 @@ private:
private Q_SLOTS:
void doUpdate();
void requestFinished() Q_DECL_OVERRIDE;
+#ifndef QT_NO_NETWORK
void sciRequestFinished();
+#endif
private:
Q_DISABLE_COPY(QQuickBorderImage)
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 478de88a52..56fbbab049 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -58,17 +58,20 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_NETWORK
class QNetworkReply;
+#endif
class QQuickBorderImagePrivate : public QQuickImageBasePrivate
{
Q_DECLARE_PUBLIC(QQuickBorderImage)
public:
QQuickBorderImagePrivate()
- : border(0), sciReply(0),
- horizontalTileMode(QQuickBorderImage::Stretch),
- verticalTileMode(QQuickBorderImage::Stretch),
- redirectCount(0), pixmapChanged(false)
+ : border(0), horizontalTileMode(QQuickBorderImage::Stretch),
+ verticalTileMode(QQuickBorderImage::Stretch), pixmapChanged(false)
+#ifndef QT_NO_NETWORK
+ , sciReply(0), redirectCount(0)
+#endif
{
}
@@ -88,14 +91,27 @@ public:
return border;
}
+ static void calculateRects(const QQuickScaleGrid *border,
+ const QSize &sourceSize,
+ const QSizeF &targetSize,
+ int horizontalTileMode,
+ int verticalTileMode,
+ qreal devicePixelRatio,
+ QRectF *targetRect,
+ QRectF *innerTargetRect,
+ QRectF *innerSourceRect,
+ QRectF *subSourceRect);
+
QQuickScaleGrid *border;
QUrl sciurl;
- QNetworkReply *sciReply;
QQuickBorderImage::TileMode horizontalTileMode;
QQuickBorderImage::TileMode verticalTileMode;
- int redirectCount;
-
bool pixmapChanged : 1;
+
+#ifndef QT_NO_NETWORK
+ QNetworkReply *sciReply;
+ int redirectCount;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 9a24d7a8a0..cc30199253 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -45,6 +45,7 @@
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <private/qquickitemchangelistener_p.h>
+#include <private/qquickpixmapcache_p.h>
#include <private/qv8engine_p.h>
#include <private/qv4scopedvalue_p.h>
#include <QtCore/qmimedata.h>
@@ -110,6 +111,8 @@ public:
bool eventQueued : 1;
bool overrideActions : 1;
QPointF hotSpot;
+ QUrl imageSource;
+ QQuickPixmap pixmapLoader;
QStringList keys;
QVariantMap externalMimeData;
QQuickDrag::DragType dragType;
@@ -409,6 +412,43 @@ void QQuickDragAttached::setHotSpot(const QPointF &hotSpot)
}
/*!
+ \qmlattachedproperty QUrl QtQuick::Drag::imageSource
+ \since 5.8
+
+ This property holds the URL of the image which will be used to represent
+ the data during the drag and drop operation. Changing this property after
+ the drag operation has started will have no effect.
+
+ The example below uses an item's contents as a drag image:
+
+ \snippet qml/externaldrag.qml 0
+
+ \sa Item::grabToImage()
+*/
+
+QUrl QQuickDragAttached::imageSource() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->imageSource;
+}
+
+void QQuickDragAttached::setImageSource(const QUrl &url)
+{
+ Q_D(QQuickDragAttached);
+ if (d->imageSource != url) {
+ d->imageSource = url;
+
+ if (url.isEmpty()) {
+ d->pixmapLoader.clear();
+ } else {
+ d->pixmapLoader.load(qmlEngine(this), url);
+ }
+
+ Q_EMIT imageSourceChanged();
+ }
+}
+
+/*!
\qmlattachedproperty stringlist QtQuick::Drag::keys
This property holds a list of keys that can be used by a DropArea to filter drag events.
@@ -727,9 +767,9 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
mimeData->setData(it.key(), it.value().toString().toUtf8());
drag->setMimeData(mimeData);
-
- // TODO: how to handle drag image?
- // drag->setPixmap(iconPixmap);
+ if (pixmapLoader.isReady()) {
+ drag->setPixmap(QPixmap::fromImage(pixmapLoader.image()));
+ }
emit q->dragStarted();
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index c1695e49f0..17721251d9 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -58,6 +58,7 @@
#include <QtCore/qmimedata.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
#ifndef QT_NO_DRAGANDDROP
@@ -247,6 +248,7 @@ class QQuickDragAttached : public QObject
Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
+ Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged REVISION 8)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
@@ -268,6 +270,9 @@ public:
QPointF hotSpot() const;
void setHotSpot(const QPointF &hotSpot);
+ QUrl imageSource() const;
+ void setImageSource(const QUrl &url);
+
QStringList keys() const;
void setKeys(const QStringList &keys);
@@ -300,6 +305,7 @@ Q_SIGNALS:
void sourceChanged();
void targetChanged();
void hotSpotChanged();
+ void imageSourceChanged();
void keysChanged();
void mimeDataChanged();
void supportedActionsChanged();
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 95b4e09aa5..d6fdf5795e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -84,6 +84,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET)
+
#ifndef QT_NO_DEBUG
static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
@@ -2889,6 +2891,8 @@ void QQuickItemPrivate::addChild(QQuickItem *child)
if (childPrivate->hasCursorInChild && !hasCursorInChild)
setHasCursorInChild(true);
#endif
+ if (childPrivate->hasHoverInChild && !hasHoverInChild)
+ setHasHoverInChild(true);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -2914,6 +2918,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
if (childPrivate->hasCursorInChild && hasCursorInChild)
setHasCursorInChild(false);
#endif
+ if (childPrivate->hasHoverInChild && hasHoverInChild)
+ setHasHoverInChild(false);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -3136,6 +3142,7 @@ QQuickItemPrivate::QQuickItemPrivate()
, culled(false)
, hasCursor(false)
, hasCursorInChild(false)
+ , hasHoverInChild(false)
, activeFocusOnTab(false)
, implicitAntialiasing(false)
, antialiasingValid(false)
@@ -6940,7 +6947,7 @@ void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
}
/*!
- Returns whether mouse events of this item's children should be filtered
+ Returns whether mouse and touch events of this item's children should be filtered
through this item.
\sa setFiltersChildMouseEvents(), childMouseEventFilter()
@@ -6952,7 +6959,7 @@ bool QQuickItem::filtersChildMouseEvents() const
}
/*!
- Sets whether mouse events of this item's children should be filtered
+ Sets whether mouse and touch events of this item's children should be filtered
through this item.
If \a filter is true, childMouseEventFilter() will be called when
@@ -7003,6 +7010,7 @@ void QQuickItem::setAcceptHoverEvents(bool enabled)
{
Q_D(QQuickItem);
d->hoverEnabled = enabled;
+ d->setHasHoverInChild(enabled);
}
void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
@@ -7030,6 +7038,29 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
#endif
}
+void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
+{
+ Q_Q(QQuickItem);
+
+ // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node
+ // removal) then we should check our children and make sure it's really ok
+ // to turn it off.
+ if (!hasHover && hasHoverInChild) {
+ foreach (QQuickItem *otherChild, childItems) {
+ QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
+ if (otherChildPrivate->hasHoverInChild)
+ return; // nope! sorry, something else wants it kept on.
+ }
+ }
+
+ hasHoverInChild = hasHover;
+ QQuickItem *parent = q->parentItem();
+ if (parent) {
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
+ parentPrivate->setHasHoverInChild(hasHover);
+ }
+}
+
void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e)
{
Q_Q(QQuickItem);
@@ -7155,6 +7186,7 @@ void QQuickItem::ungrabMouse()
return;
}
+ qCDebug(DBG_MOUSE_TARGET) << "ungrabMouse" << windowPriv->mouseGrabberItem << "-> null";
windowPriv->mouseGrabberItem = 0;
QEvent ev(QEvent::UngrabMouse);
@@ -7224,6 +7256,7 @@ void QQuickItem::grabTouchPoints(const QVector<int> &ids)
QQuickItem *mouseGrabber = windowPriv->mouseGrabberItem;
if (windowPriv->touchMouseId == ids.at(i) && mouseGrabber && mouseGrabber != this) {
+ qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << windowPriv->mouseGrabberItem << "-> null";
windowPriv->mouseGrabberItem = 0;
QEvent ev(QEvent::UngrabMouse);
d->window->sendEvent(mouseGrabber, &ev);
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index ad649e5b5f..854cbd769b 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -429,6 +429,7 @@ public:
bool hasCursor:1;
bool hasCursorInChild:1;
// Bit 32
+ bool hasHoverInChild:1;
bool activeFocusOnTab:1;
bool implicitAntialiasing:1;
bool antialiasingValid:1;
@@ -606,6 +607,7 @@ public:
virtual void mirrorChange() {}
void setHasCursorInChild(bool hasCursor);
+ void setHasHoverInChild(bool hasHover);
// recursive helper to let a visual parent mark its visual children
void markObjects(QV4::ExecutionEngine *e);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 08d95119d7..0b413b76b6 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -211,6 +211,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
qmlRegisterUncreatableType<QQuickShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QQuickShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
qmlRegisterType<QQuickGridMesh>("QtQuick", 2, 0, "GridMesh");
+ qmlRegisterType<QQuickBorderImageMesh>("QtQuick", 2, 8, "BorderImageMesh");
qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 74ca0f482a..b8c680433e 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -44,7 +44,6 @@
#include <private/qsgadaptationlayer_p.h>
#include <QtGui/qpixmapcache.h>
-#include <QtCore/qstringbuilder.h>
#include <QtCore/qmath.h>
#include <QtCore/qmetaobject.h>
diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp
index 0811025654..842befac37 100644
--- a/src/quick/items/qquickshadereffectmesh.cpp
+++ b/src/quick/items/qquickshadereffectmesh.cpp
@@ -40,6 +40,9 @@
#include "qquickshadereffectmesh_p.h"
#include <QtQuick/qsggeometry.h>
#include "qquickshadereffect_p.h"
+#include "qquickscalegrid_p_p.h"
+#include "qquickborderimage_p_p.h"
+#include <QtQuick/private/qsgdefaultimagenode_p.h>
QT_BEGIN_NAMESPACE
@@ -217,4 +220,184 @@ QSize QQuickGridMesh::resolution() const
return m_resolution;
}
+/*!
+ \qmltype BorderImageMesh
+ \instantiates QQuickBorderImageMesh
+ \inqmlmodule QtQuick
+ \since 5.8
+ \ingroup qtquick-effects
+ \brief Defines a mesh with vertices arranged like those of a BorderImage.
+
+ BorderImageMesh provides BorderImage-like capabilities to a ShaderEffect
+ without the need for a potentially costly ShaderEffectSource.
+
+ The following are functionally equivalent:
+ \qml
+ BorderImage {
+ id: borderImage
+ border {
+ left: 10
+ right: 10
+ top: 10
+ bottom: 10
+ }
+ source: "myImage.png"
+ visible: false
+ }
+ ShaderEffectSource {
+ id: effectSource
+ sourceItem: borderImage
+ visible: false
+ }
+ ShaderEffect {
+ property var source: effectSource
+ ...
+ }
+ \endqml
+
+ \qml
+ Image {
+ id: image
+ source: "myImage.png"
+ visible: false
+ }
+ ShaderEffect {
+ property var source: image
+ mesh: BorderImageMesh {
+ border {
+ left: 10
+ right: 10
+ top: 10
+ bottom: 10
+ }
+ size: image.sourceSize
+ }
+ ...
+ }
+ \endqml
+
+ But the BorderImageMesh version can typically be better optimized.
+*/
+QQuickBorderImageMesh::QQuickBorderImageMesh(QObject *parent)
+ : QQuickShaderEffectMesh(parent), m_border(new QQuickScaleGrid(this)),
+ m_horizontalTileMode(QQuickBorderImageMesh::Stretch),
+ m_verticalTileMode(QQuickBorderImageMesh::Stretch)
+{
+}
+
+QSGGeometry *QQuickBorderImageMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &/*attributes*/, const QRectF &srcRect, const QRectF &rect)
+{
+ QRectF innerSourceRect;
+ QRectF targetRect;
+ QRectF innerTargetRect;
+ QRectF subSourceRect;
+
+ QQuickBorderImagePrivate::calculateRects(m_border, m_size, rect.size(), m_horizontalTileMode, m_verticalTileMode, 1, &targetRect, &innerTargetRect, &innerSourceRect, &subSourceRect);
+
+ QRectF sourceRect = srcRect;
+ QRectF modifiedInnerSourceRect(sourceRect.x() + innerSourceRect.x() * sourceRect.width(),
+ sourceRect.y() + innerSourceRect.y() * sourceRect.height(),
+ innerSourceRect.width() * sourceRect.width(),
+ innerSourceRect.height() * sourceRect.height());
+
+ geometry = QSGDefaultImageNode::updateGeometry(targetRect, innerTargetRect, sourceRect, modifiedInnerSourceRect, subSourceRect, geometry);
+
+ return geometry;
+}
+
+/*!
+ \qmlpropertygroup QtQuick::BorderImageMesh::border
+ \qmlproperty int QtQuick::BorderImageMesh::border.left
+ \qmlproperty int QtQuick::BorderImageMesh::border.right
+ \qmlproperty int QtQuick::BorderImageMesh::border.top
+ \qmlproperty int QtQuick::BorderImageMesh::border.bottom
+
+ The 4 border lines (2 horizontal and 2 vertical) break the image into 9 sections,
+ as shown below:
+
+ \image declarative-scalegrid.png
+
+ Each border line (left, right, top, and bottom) specifies an offset in pixels
+ from the respective edge of the mesh. By default, each border line has
+ a value of 0.
+
+ For example, the following definition sets the bottom line 10 pixels up from
+ the bottom of the mesh:
+
+ \qml
+ BorderImageMesh {
+ border.bottom: 10
+ // ...
+ }
+ \endqml
+*/
+QQuickScaleGrid *QQuickBorderImageMesh::border()
+{
+ return m_border;
+}
+
+/*!
+ \qmlproperty size QtQuick::BorderImageMesh::size
+
+ The base size of the mesh. This generally corresponds to the \l {Image::}{sourceSize}
+ of the image being used by the ShaderEffect.
+*/
+QSize QQuickBorderImageMesh::size() const
+{
+ return m_size;
+}
+
+void QQuickBorderImageMesh::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+ m_size = size;
+ Q_EMIT sizeChanged();
+ Q_EMIT geometryChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick::BorderImageMesh::horizontalTileMode
+ \qmlproperty enumeration QtQuick::BorderImageMesh::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of an image.
+
+ \list
+ \li BorderImage.Stretch - Scales the image to fit to the available area.
+ \li BorderImage.Repeat - Tile the image until there is no more space. May crop the last image.
+ \li BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+
+ The default tile mode for each property is BorderImage.Stretch.
+*/
+
+QQuickBorderImageMesh::TileMode QQuickBorderImageMesh::horizontalTileMode() const
+{
+ return m_horizontalTileMode;
+}
+
+void QQuickBorderImageMesh::setHorizontalTileMode(TileMode t)
+{
+ if (t == m_horizontalTileMode)
+ return;
+ m_horizontalTileMode = t;
+ Q_EMIT horizontalTileModeChanged();
+ Q_EMIT geometryChanged();
+}
+
+QQuickBorderImageMesh::TileMode QQuickBorderImageMesh::verticalTileMode() const
+{
+ return m_verticalTileMode;
+}
+
+void QQuickBorderImageMesh::setVerticalTileMode(TileMode t)
+{
+ if (t == m_verticalTileMode)
+ return;
+
+ m_verticalTileMode = t;
+ Q_EMIT verticalTileModeChanged();
+ Q_EMIT geometryChanged();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index 7f9c95888c..34d3908140 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -100,6 +100,45 @@ private:
QString m_log;
};
+class QQuickScaleGrid;
+class QQuickBorderImageMesh : public QQuickShaderEffectMesh
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+public:
+ QQuickBorderImageMesh(QObject *parent = 0);
+ QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &srcRect, const QRectF &rect) Q_DECL_OVERRIDE;
+
+ QQuickScaleGrid *border();
+
+ enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+ Q_ENUM(TileMode)
+
+ QSize size() const;
+ void setSize(const QSize &size);
+
+ TileMode horizontalTileMode() const;
+ void setHorizontalTileMode(TileMode);
+
+ TileMode verticalTileMode() const;
+ void setVerticalTileMode(TileMode);
+
+Q_SIGNALS:
+ void sizeChanged();
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+
+private:
+ QQuickScaleGrid *m_border;
+ QSize m_size;
+ TileMode m_horizontalTileMode;
+ TileMode m_verticalTileMode;
+};
+
inline QColor qt_premultiply_color(const QColor &c)
{
return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 60d5e3f6dd..6de613c5b0 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -111,7 +111,7 @@ QQuickSpriteEngine::QQuickSpriteEngine(QObject *parent)
}
QQuickSpriteEngine::QQuickSpriteEngine(QList<QQuickSprite*> sprites, QObject *parent)
- : QQuickStochasticEngine(parent), m_startedImageAssembly(false), m_loaded(false)
+ : QQuickSpriteEngine(parent)
{
foreach (QQuickSprite* sprite, sprites)
m_states << (QQuickStochasticState*)sprite;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index f3254cf8d7..65044d33d4 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1423,6 +1423,39 @@ QQuickText::~QQuickText()
Text { text: "Hello"; font.capitalization: Font.AllLowercase }
\endqml
*/
+
+/*!
+ \qmlproperty enumeration QtQuick::Text::font.hintingPreference
+ \since 5.8
+
+ Sets the preferred hinting on the text. This is a hint to the underlying text rendering system
+ to use a certain level of hinting, and has varying support across platforms. See the table in
+ the documentation for QFont::HintingPreference for more details.
+
+ \note This property only has an effect when used together with render type Text.NativeRendering.
+
+ \list
+ \value Font.PreferDefaultHinting - Use the default hinting level for the target platform.
+ \value Font.PreferNoHinting - If possible, render text without hinting the outlines
+ of the glyphs. The text layout will be typographically accurate, using the same metrics
+ as are used e.g. when printing.
+ \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting,
+ but align glyphs to the pixel grid in the vertical direction. The text will appear
+ crisper on displays where the density is too low to give an accurate rendering
+ of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's
+ layout will be scalable to higher density devices (such as printers) without impacting
+ details such as line breaks.
+ \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and
+ vertical directions. The text will be altered to optimize legibility on the target
+ device, but since the metrics will depend on the target size of the text, the positions
+ of glyphs, line breaks, and other typographical detail will not scale, meaning that a
+ text layout may look different on devices with different pixel densities.
+ \endlist
+
+ \qml
+ Text { text: "Hello"; renderType: Text.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting }
+ \endqml
+*/
QFont QQuickText::font() const
{
Q_D(const QQuickText);
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 0cee9c7d27..45238e2d0c 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -44,6 +44,7 @@
#include <qcoreapplication.h>
#include <qfont.h>
+#include <qfontmetrics.h>
#include <qevent.h>
#include <qdebug.h>
#include <qdrag.h>
@@ -982,6 +983,14 @@ process:
{
QString text = e->text();
if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) {
+ if (overwriteMode
+ // no need to call deleteChar() if we have a selection, insertText
+ // does it already
+ && !cursor.hasSelection()
+ && !cursor.atBlockEnd()) {
+ cursor.deleteChar();
+ }
+
cursor.insertText(text);
selectionChanged();
} else {
@@ -1024,6 +1033,12 @@ QRectF QQuickTextControlPrivate::rectForPosition(int position) const
if (line.isValid()) {
qreal x = line.cursorToX(relativePos);
qreal w = 0;
+ if (overwriteMode) {
+ if (relativePos < line.textLength() - line.textStart())
+ w = line.cursorToX(relativePos + 1) - x;
+ else
+ w = QFontMetrics(block.layout()->font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height());
} else {
r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10); // #### correct height
@@ -1506,6 +1521,21 @@ bool QQuickTextControl::hasImState() const
return d->hasImState;
}
+bool QQuickTextControl::overwriteMode() const
+{
+ Q_D(const QQuickTextControl);
+ return d->overwriteMode;
+}
+
+void QQuickTextControl::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextControl);
+ if (d->overwriteMode == overwrite)
+ return;
+ d->overwriteMode = overwrite;
+ emit overwriteModeChanged(overwrite);
+}
+
bool QQuickTextControl::cursorVisible() const
{
Q_D(const QQuickTextControl);
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index ca5a3d3191..602e457cb8 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -94,6 +94,8 @@ public:
#endif
bool hasImState() const;
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
bool cursorVisible() const;
void setCursorVisible(bool visible);
QRectF anchorRect() const;
@@ -149,6 +151,7 @@ Q_SIGNALS:
void copyAvailable(bool b);
void selectionChanged();
void cursorPositionChanged();
+ void overwriteModeChanged(bool overwriteMode);
// control signals
void updateCursorRequest();
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 5968028c26..36eb5d3cde 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -323,6 +323,39 @@ QString QQuickTextEdit::text() const
*/
/*!
+ \qmlproperty enumeration QtQuick::TextEdit::font.hintingPreference
+ \since 5.8
+
+ Sets the preferred hinting on the text. This is a hint to the underlying text rendering system
+ to use a certain level of hinting, and has varying support across platforms. See the table in
+ the documentation for QFont::HintingPreference for more details.
+
+ \note This property only has an effect when used together with render type TextEdit.NativeRendering.
+
+ \list
+ \value Font.PreferDefaultHinting - Use the default hinting level for the target platform.
+ \value Font.PreferNoHinting - If possible, render text without hinting the outlines
+ of the glyphs. The text layout will be typographically accurate, using the same metrics
+ as are used e.g. when printing.
+ \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting,
+ but align glyphs to the pixel grid in the vertical direction. The text will appear
+ crisper on displays where the density is too low to give an accurate rendering
+ of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's
+ layout will be scalable to higher density devices (such as printers) without impacting
+ details such as line breaks.
+ \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and
+ vertical directions. The text will be altered to optimize legibility on the target
+ device, but since the metrics will depend on the target size of the text, the positions
+ of glyphs, line breaks, and other typographical detail will not scale, meaning that a
+ text layout may look different on devices with different pixel densities.
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; renderType: TextEdit.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting }
+ \endqml
+*/
+
+/*!
\qmlproperty string QtQuick::TextEdit::text
The text to display. If the text format is AutoText the text edit will
@@ -1583,6 +1616,32 @@ bool QQuickTextEdit::event(QEvent *event)
}
/*!
+ \qmlproperty bool QtQuick::TextEdit::overwriteMode
+ \since 5.8
+ Whether text entered by the user will overwrite existing text.
+
+ As with many text editors, the text editor widget can be configured
+ to insert or overwrite existing text with new text entered by the user.
+
+ If this property is \c true, existing text is overwritten, character-for-character
+ by new text; otherwise, text is inserted at the cursor position, displacing
+ existing text.
+
+ By default, this property is \c false (new text does not overwrite existing text).
+*/
+bool QQuickTextEdit::overwriteMode() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->overwriteMode();
+}
+
+void QQuickTextEdit::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextEdit);
+ d->control->setOverwriteMode(overwrite);
+}
+
+/*!
\overload
Handles the given key \a event.
*/
@@ -2193,6 +2252,7 @@ void QQuickTextEditPrivate::init()
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkHovered(QString)), q, QQuickTextEdit, SIGNAL(linkHovered(QString)));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(overwriteModeChanged(bool)), q, QQuickTextEdit, SIGNAL(overwriteModeChanged(bool)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(preeditTextChanged()), q, QQuickTextEdit, SIGNAL(preeditTextChanged()));
#ifndef QT_NO_CLIPBOARD
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index f6ecb984e3..42c9064860 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -86,6 +86,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
Q_PROPERTY(QQmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged)
Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
@@ -199,6 +200,9 @@ public:
QQmlComponent* cursorDelegate() const;
void setCursorDelegate(QQmlComponent*);
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
+
int selectionStart() const;
int selectionEnd() const;
@@ -313,6 +317,7 @@ Q_SIGNALS:
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
+ void overwriteModeChanged(bool overwriteMode);
void activeFocusOnPressChanged(bool activeFocusOnPressed);
void persistentSelectionChanged(bool isPersistentSelection);
void textMarginChanged(qreal textMargin);
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 504dece0d1..9b7eb4ea4b 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -345,6 +345,38 @@ QString QQuickTextInputPrivate::realText() const
\endqml
*/
+/*!
+ \qmlproperty enumeration QtQuick::TextInput::font.hintingPreference
+ \since 5.8
+
+ Sets the preferred hinting on the text. This is a hint to the underlying text rendering system
+ to use a certain level of hinting, and has varying support across platforms. See the table in
+ the documentation for QFont::HintingPreference for more details.
+
+ \note This property only has an effect when used together with render type TextInput.NativeRendering.
+
+ \list
+ \value Font.PreferDefaultHinting - Use the default hinting level for the target platform.
+ \value Font.PreferNoHinting - If possible, render text without hinting the outlines
+ of the glyphs. The text layout will be typographically accurate, using the same metrics
+ as are used e.g. when printing.
+ \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting,
+ but align glyphs to the pixel grid in the vertical direction. The text will appear
+ crisper on displays where the density is too low to give an accurate rendering
+ of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's
+ layout will be scalable to higher density devices (such as printers) without impacting
+ details such as line breaks.
+ \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and
+ vertical directions. The text will be altered to optimize legibility on the target
+ device, but since the metrics will depend on the target size of the text, the positions
+ of glyphs, line breaks, and other typographical detail will not scale, meaning that a
+ text layout may look different on devices with different pixel densities.
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; renderType: TextInput.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting }
+ \endqml
+*/
QFont QQuickTextInput::font() const
{
Q_D(const QQuickTextInput);
@@ -808,7 +840,14 @@ QRectF QQuickTextInput::cursorRectangle() const
return QRectF();
qreal x = l.cursorToX(c) - d->hscroll + leftPadding();
qreal y = l.y() - d->vscroll + topPadding();
- return QRectF(x, y, 1, l.height());
+ qreal w = 1;
+ if (d->overwriteMode) {
+ if (c < text().length())
+ w = l.cursorToX(c + 1) - x;
+ else
+ w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
+ return QRectF(x, y, w, l.height());
}
/*!
@@ -1288,7 +1327,14 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
return QRectF();
qreal x = l.cursorToX(pos) - d->hscroll;
qreal y = l.y() - d->vscroll;
- return QRectF(x, y, 1, l.height());
+ qreal w = 1;
+ if (d->overwriteMode) {
+ if (pos < text().length())
+ w = l.cursorToX(pos + 1) - x;
+ else
+ w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ }
+ return QRectF(x, y, w, l.height());
}
/*!
@@ -1370,6 +1416,36 @@ int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPositi
return line.isValid() ? line.xToCursor(x, position) : 0;
}
+/*!
+ \qmlproperty bool QtQuick::TextInput::overwriteMode
+ \since 5.8
+
+ Whether text entered by the user will overwrite existing text.
+
+ As with many text editors, the text editor widget can be configured
+ to insert or overwrite existing text with new text entered by the user.
+
+ If this property is \c true, existing text is overwritten, character-for-character
+ by new text; otherwise, text is inserted at the cursor position, displacing
+ existing text.
+
+ By default, this property is \c false (new text does not overwrite existing text).
+*/
+bool QQuickTextInput::overwriteMode() const
+{
+ Q_D(const QQuickTextInput);
+ return d->overwriteMode;
+}
+
+void QQuickTextInput::setOverwriteMode(bool overwrite)
+{
+ Q_D(QQuickTextInput);
+ if (d->overwriteMode == overwrite)
+ return;
+ d->overwriteMode = overwrite;
+ emit overwriteModeChanged(overwrite);
+}
+
void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
{
Q_D(QQuickTextInput);
@@ -2767,7 +2843,7 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
// characters)
QChar* uc = str.data();
for (int i = 0; i < (int)str.length(); ++i) {
- if ((uc[i] < 0x20 && uc[i] != 0x09)
+ if ((uc[i].unicode() < 0x20 && uc[i] != QChar::Tabulation)
|| uc[i] == QChar::LineSeparator
|| uc[i] == QChar::ParagraphSeparator
|| uc[i] == QChar::ObjectReplacementCharacter)
@@ -4448,6 +4524,14 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
if (unknown && !m_readOnly) {
QString t = event->text();
if (!t.isEmpty() && t.at(0).isPrint()) {
+ if (overwriteMode
+ // no need to call del() if we have a selection, insert
+ // does it already
+ && !hasSelectedText()
+ && !(m_cursor == q_func()->text().length())) {
+ del();
+ }
+
insert(t);
event->accept();
return;
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 211d9146fc..d0461f551e 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -79,6 +79,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
Q_PROPERTY(QQmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged)
Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
@@ -245,6 +246,9 @@ public:
QQmlComponent* cursorDelegate() const;
void setCursorDelegate(QQmlComponent*);
+ bool overwriteMode() const;
+ void setOverwriteMode(bool overwrite);
+
bool focusOnPress() const;
void setFocusOnPress(bool);
@@ -325,6 +329,7 @@ Q_SIGNALS:
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
+ void overwriteModeChanged(bool overwriteMode);
void maximumLengthChanged(int maximumLength);
void validatorChanged();
void inputMaskChanged(const QString &inputMask);
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 57a9f6413a..93a8778c40 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -158,6 +158,7 @@ public:
, m_passwordEchoEditing(false)
, inLayout(false)
, requireImplicitWidth(false)
+ , overwriteMode(false)
{
}
@@ -299,6 +300,7 @@ public:
bool m_passwordEchoEditing : 1;
bool inLayout:1;
bool requireImplicitWidth:1;
+ bool overwriteMode:1;
static inline QQuickTextInputPrivate *get(QQuickTextInput *t) {
return t->d_func();
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 2872c3e230..7b600adf53 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -731,10 +731,13 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN
QVector<QPointF> glyphPositions = glyphRun.positions();
glyphPositions.reserve(count);
+ QRectF glyphBoundingRect = glyphRun.boundingRect();
+
for (int j = 1; j < nodes.size(); ++j) {
BinaryTreeNode *otherNode = nodes.at(j);
glyphIndexes += otherNode->glyphRun.glyphIndexes();
primaryNode->ranges += otherNode->ranges;
+ glyphBoundingRect = glyphBoundingRect.united(otherNode->glyphRun.boundingRect());
QVector<QPointF> otherPositions = otherNode->glyphRun.positions();
for (int k = 0; k < otherPositions.size(); ++k)
@@ -746,6 +749,7 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN
glyphRun.setGlyphIndexes(glyphIndexes);
glyphRun.setPositions(glyphPositions);
+ glyphRun.setBoundingRect(glyphBoundingRect);
}
}
}
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 3ce96b673d..1101b88992 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -194,9 +194,8 @@ QQuickView::QQuickView(QWindow *parent)
*/
QQuickView::QQuickView(const QUrl &source, QWindow *parent)
-: QQuickWindow(*(new QQuickViewPrivate), parent)
+ : QQuickView(parent)
{
- d_func()->init();
setSource(source);
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index b06cfe54cc..48e5b54016 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -79,11 +79,12 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch");
-Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target");
-Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse");
-Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus");
-Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty");
+Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch")
+Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target")
+Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse")
+Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target")
+Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus")
+Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty")
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
@@ -746,6 +747,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
if (mouseGrabberItem == grabber)
return;
+ qCDebug(DBG_MOUSE_TARGET) << "grabber" << mouseGrabberItem << "->" << grabber;
QQuickItem *oldGrabber = mouseGrabberItem;
mouseGrabberItem = grabber;
@@ -1174,10 +1176,8 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
Constructs a window for displaying a QML scene with parent window \a parent.
*/
QQuickWindow::QQuickWindow(QWindow *parent)
- : QWindow(*(new QQuickWindowPrivate), parent)
+ : QQuickWindow(*new QQuickWindowPrivate, parent)
{
- Q_D(QQuickWindow);
- d->init(this);
}
@@ -1654,7 +1654,7 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
return;
}
- qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
+ qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons() << "grabber:" << d->mouseGrabberItem;
if (!d->mouseGrabberItem) {
QWindow::mouseReleaseEvent(event);
@@ -1761,13 +1761,15 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
return false;
}
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
- continue;
- if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
- return true;
+ if (itemPrivate->hasHoverInChild) {
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QQuickItem *child = children.at(ii);
+ if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
+ continue;
+ if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
+ return true;
+ }
}
if (itemPrivate->hoverEnabled) {
@@ -2182,7 +2184,7 @@ bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *even
return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty());
}
-// touchEventForItemBounds has no means to generate a touch event that contains
+// touchEventForItem has no means to generate a touch event that contains
// only the points that are relevant for this item. Thus the need for
// matchingPoints to already be that set of interesting points.
// They are all pre-transformed, too.
@@ -2244,7 +2246,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
return touchEventAccepted;
}
-QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent)
+QTouchEvent *QQuickWindowPrivate::touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds)
{
const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints();
QList<QTouchEvent::TouchPoint> pointsInBounds;
@@ -2252,7 +2254,10 @@ QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, co
if (originalEvent.touchPointStates() != Qt::TouchPointStationary) {
for (int i = 0; i < touchPoints.count(); ++i) {
const QTouchEvent::TouchPoint &tp = touchPoints.at(i);
- if (tp.state() == Qt::TouchPointPressed) {
+ // Touch presses are relevant to the target item only if they occur inside its bounds.
+ // Touch updates and releases are relevant if they occur inside, or if we want to
+ // finish the sequence because the press occurred inside.
+ if (tp.state() == Qt::TouchPointPressed || alwaysCheckBounds) {
QPointF p = target->mapFromScene(tp.scenePos());
if (target->contains(p))
pointsInBounds.append(tp);
@@ -2481,7 +2486,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
hasFiltered->insert(target);
- QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
+ QScopedPointer<QTouchEvent> targetEvent(touchEventForItem(target, *event));
if (!targetEvent->touchPoints().isEmpty()) {
if (target->childMouseEventFilter(item, targetEvent.data())) {
qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
@@ -2561,6 +2566,7 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem
hasFiltered->insert(target);
if (target->childMouseEventFilter(item, event))
filtered = true;
+ qCDebug(DBG_MOUSE_TARGET) << target << "childMouseEventFilter ->" << filtered;
}
return sendFilteredMouseEvent(target->parentItem(), item, event, hasFiltered) || filtered;
@@ -2581,6 +2587,15 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
return overThreshold;
}
+bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold)
+{
+ QStyleHints *styleHints = qApp->styleHints();
+ bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
+ qreal velocity = axis == Qt::XAxis ? tp->velocity().x() : tp->velocity().y();
+ overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
+ return overThreshold;
+}
+
/*!
\qmlproperty list<Object> Window::data
\default
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 1064be7178..1486e20e1e 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -163,8 +163,8 @@ public:
void flushDelayedTouchEvent();
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
- QTouchEvent *touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent);
- QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
+ static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
+ static QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered);
bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, bool accepted);
@@ -265,6 +265,7 @@ public:
static bool defaultAlphaBuffer;
static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
+ static bool dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold = -1);
// data property
static void data_append(QQmlListProperty<QObject> *, QObject *);