diff options
Diffstat (limited to 'src/declarative/graphicsitems')
21 files changed, 501 insertions, 141 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors.cpp b/src/declarative/graphicsitems/qdeclarativeanchors.cpp index ef07cbb..aa53aba 100644 --- a/src/declarative/graphicsitems/qdeclarativeanchors.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanchors.cpp @@ -92,17 +92,17 @@ static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine //position when origin is 0,0 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) { - int ret = 0; + qreal ret = 0.0; QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); switch(anchorLine) { case QDeclarativeAnchorLine::Left: - ret = 0; + ret = 0.0; break; case QDeclarativeAnchorLine::Right: ret = d->width(); break; case QDeclarativeAnchorLine::Top: - ret = 0; + ret = 0.0; break; case QDeclarativeAnchorLine::Bottom: ret = d->height(); @@ -459,10 +459,10 @@ void QDeclarativeAnchors::resetCenterIn() bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1, const QDeclarativeAnchorLine &edge2, - int offset1, - int offset2, + qreal offset1, + qreal offset2, QDeclarativeAnchorLine::AnchorLine line, - int &stretch) + qreal &stretch) { bool edge1IsParent = (edge1.item == item->parentItem()); bool edge2IsParent = (edge2.item == item->parentItem()); @@ -471,15 +471,15 @@ bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1 bool invalid = false; if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) { - stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2) - - ((int)position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(edge2.item, edge2.anchorLine) + offset2) + - (position(edge1.item, edge1.anchorLine) + offset1); } else if (edge2IsParent && edge1IsSibling) { - stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2) - - ((int)position(item->parentObject(), line) - + (int)position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(edge2.item, edge2.anchorLine) + offset2) + - (position(item->parentObject(), line) + + position(edge1.item, edge1.anchorLine) + offset1); } else if (edge2IsSibling && edge1IsParent) { - stretch = ((int)position(item->parentObject(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2) - - ((int)position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2) + - (position(edge1.item, edge1.anchorLine) + offset1); } else invalid = true; @@ -497,7 +497,7 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() if (usedAnchors & QDeclarativeAnchors::TopAnchor) { //Handle stretching bool invalid = true; - int height = 0; + qreal height = 0.0; if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height); } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { @@ -516,7 +516,7 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { //Handle stretching (top + bottom case is handled above) if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { - int height = 0; + qreal height = 0.0; bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, QDeclarativeAnchorLine::Top, height); if (!invalid) @@ -569,7 +569,7 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() if (usedAnchors & QDeclarativeAnchors::LeftAnchor) { //Handle stretching bool invalid = true; - int width = 0; + qreal width = 0.0; if (usedAnchors & QDeclarativeAnchors::RightAnchor) { invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width); } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { @@ -588,7 +588,7 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { - int width = 0; + qreal width = 0.0; bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, QDeclarativeAnchorLine::Left, width); if (!invalid) diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h index 05be6c5..1bbea36 100644 --- a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h @@ -131,7 +131,7 @@ public: bool checkVValid() const; bool checkHAnchorValid(QDeclarativeAnchorLine anchor) const; bool checkVAnchorValid(QDeclarativeAnchorLine anchor) const; - bool calcStretch(const QDeclarativeAnchorLine &edge1, const QDeclarativeAnchorLine &edge2, int offset1, int offset2, QDeclarativeAnchorLine::AnchorLine line, int &stretch); + bool calcStretch(const QDeclarativeAnchorLine &edge1, const QDeclarativeAnchorLine &edge2, qreal offset1, qreal offset2, QDeclarativeAnchorLine::AnchorLine line, qreal &stretch); void updateHorizontalAnchors(); void updateVerticalAnchors(); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 560d586..10dc0f8 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -160,6 +160,7 @@ void QDeclarativeFlickablePrivate::init() q->setFiltersChildEvents(true); QDeclarativeItemPrivate *viewportPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(viewport)); viewportPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); + lastPosTime.invalidate(); } /* @@ -656,7 +657,7 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); - if (!interactive || lastPosTime.isNull()) + if (!interactive || !lastPosTime.isValid()) return; bool rejectY = false; bool rejectX = false; @@ -752,7 +753,7 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv stealMouse = false; q->setKeepMouseGrab(false); pressed = false; - if (lastPosTime.isNull()) + if (!lastPosTime.isValid()) return; if (QDeclarativeItemPrivate::elapsed(lastPosTime) > 100) { @@ -780,7 +781,7 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv fixupX(); } - lastPosTime = QTime(); + lastPosTime.invalidate(); if (!timeline.isActive()) q->movementEnding(); @@ -1026,24 +1027,6 @@ QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildr return QGraphicsItemPrivate::get(d->viewport)->childrenList(); } -bool QDeclarativeFlickable::overShoot() const -{ - Q_D(const QDeclarativeFlickable); - return d->boundsBehavior == DragAndOvershootBounds; -} - -void QDeclarativeFlickable::setOverShoot(bool o) -{ - Q_D(QDeclarativeFlickable); - if ((o && d->boundsBehavior == DragAndOvershootBounds) - || (!o && d->boundsBehavior == StopAtBounds)) - return; - qmlInfo(this) << "overshoot is deprecated and will be removed imminently - use boundsBehavior."; - d->boundsBehavior = o ? DragAndOvershootBounds : StopAtBounds; - emit boundsBehaviorChanged(); - emit overShootChanged(); -} - /*! \qmlproperty enumeration Flickable::boundsBehavior This property holds whether the surface may be dragged @@ -1078,7 +1061,6 @@ void QDeclarativeFlickable::setBoundsBehavior(BoundsBehavior b) return; d->boundsBehavior = b; emit boundsBehaviorChanged(); - emit overShootChanged(); } /*! @@ -1237,8 +1219,8 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) } return stealThisEvent || d->delayedPressEvent; - } else if (!d->lastPosTime.isNull()) { - d->lastPosTime = QTime(); + } else if (d->lastPosTime.isValid()) { + d->lastPosTime.invalidate(); } if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) { d->clearDelayedPress(); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 05887b8..d40a0dc 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -64,7 +64,6 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged) Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged) - Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot NOTIFY overShootChanged) // deprecated Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged) Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) @@ -101,9 +100,6 @@ public: QDeclarativeListProperty<QObject> flickableData(); QDeclarativeListProperty<QGraphicsObject> flickableChildren(); - bool overShoot() const; - void setOverShoot(bool); - enum BoundsBehavior { StopAtBounds, DragOverBounds, DragAndOvershootBounds }; BoundsBehavior boundsBehavior() const; void setBoundsBehavior(BoundsBehavior); @@ -172,7 +168,6 @@ Q_SIGNALS: void pageChanged(); void flickableDirectionChanged(); void interactiveChanged(); - void overShootChanged(); void boundsBehaviorChanged(); void maximumFlickVelocityChanged(); void flickDecelerationChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index b467ed2..66d2678 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -140,13 +140,13 @@ public: bool stealMouse : 1; bool pressed : 1; bool interactive : 1; - QTime lastPosTime; + QElapsedTimer lastPosTime; QPointF lastPos; QPointF pressPos; - QTime pressTime; + QElapsedTimer pressTime; qreal deceleration; qreal maxVelocity; - QTime velocityTime; + QElapsedTimer velocityTime; QPointF lastFlickablePosition; qreal reportedVelocitySmoothing; QGraphicsSceneMouseEvent *delayedPressEvent; diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 2841ac3..7bd08ce 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -3145,41 +3145,56 @@ QDebug operator<<(QDebug debug, QDeclarativeItem *item) return debug; } -int QDeclarativeItemPrivate::consistentTime = -1; -void QDeclarativeItemPrivate::setConsistentTime(int t) +qint64 QDeclarativeItemPrivate::consistentTime = -1; +void QDeclarativeItemPrivate::setConsistentTime(qint64 t) { consistentTime = t; } -QTime QDeclarativeItemPrivate::currentTime() +class QElapsedTimerConsistentTimeHack { - if (consistentTime == -1) - return QTime::currentTime(); - else - return QTime(0, 0).addMSecs(consistentTime); -} +public: + void start() { + t1 = QDeclarativeItemPrivate::consistentTime; + t2 = 0; + } + qint64 elapsed() { + return QDeclarativeItemPrivate::consistentTime - t1; + } + qint64 restart() { + qint64 val = QDeclarativeItemPrivate::consistentTime - t1; + t1 = QDeclarativeItemPrivate::consistentTime; + t2 = 0; + return val; + } -void QDeclarativeItemPrivate::start(QTime &t) +private: + qint64 t1; + qint64 t2; +}; + +void QDeclarativeItemPrivate::start(QElapsedTimer &t) { - t = currentTime(); + if (QDeclarativeItemPrivate::consistentTime == -1) + t.start(); + else + ((QElapsedTimerConsistentTimeHack*)&t)->start(); } -int QDeclarativeItemPrivate::elapsed(QTime &t) +qint64 QDeclarativeItemPrivate::elapsed(QElapsedTimer &t) { - int n = t.msecsTo(currentTime()); - if (n < 0) // passed midnight - n += 86400 * 1000; - return n; + if (QDeclarativeItemPrivate::consistentTime == -1) + return t.elapsed(); + else + return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed(); } -int QDeclarativeItemPrivate::restart(QTime &t) +qint64 QDeclarativeItemPrivate::restart(QElapsedTimer &t) { - QTime time = currentTime(); - int n = t.msecsTo(time); - if (n < 0) // passed midnight - n += 86400*1000; - t = time; - return n; + if (QDeclarativeItemPrivate::consistentTime == -1) + return t.restart(); + else + return ((QElapsedTimerConsistentTimeHack*)&t)->restart(); } QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 15b34f0..184d6f1 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -305,12 +305,11 @@ public: virtual void focusChanged(bool); - static int consistentTime; - static QTime currentTime(); - static void setConsistentTime(int t); - static void start(QTime &); - static int elapsed(QTime &); - static int restart(QTime &); + static qint64 consistentTime; + static void setConsistentTime(qint64 t); + static void start(QElapsedTimer &); + static qint64 elapsed(QElapsedTimer &); + static qint64 restart(QElapsedTimer &); }; /* diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp index c4f0b86..13d1b61 100644 --- a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp +++ b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp @@ -152,8 +152,6 @@ void QDeclarativePaintedItem::setContentsSize(const QSize &size) Q_D(QDeclarativePaintedItem); if (d->contentsSize == size) return; d->contentsSize = size; - setImplicitWidth(size.width()*d->contentsScale); - setImplicitHeight(size.height()*d->contentsScale); clearCache(); update(); emit contentsSizeChanged(); @@ -170,8 +168,6 @@ void QDeclarativePaintedItem::setContentsScale(qreal scale) Q_D(QDeclarativePaintedItem); if (d->contentsScale == scale) return; d->contentsScale = scale; - setImplicitWidth(d->contentsSize.width()*scale); - setImplicitHeight(d->contentsSize.height()*scale); clearCache(); update(); emit contentsScaleChanged(); @@ -232,6 +228,19 @@ void QDeclarativePaintedItem::setCacheFrozen(bool frozen) // XXX clear cache? } +QRectF QDeclarativePaintedItem::boundingRect() const +{ + Q_D(const QDeclarativePaintedItem); + qreal w = d->mWidth; + QSizeF sz = d->contentsSize * d->contentsScale; + if (w < sz.width()) + w = sz.width(); + qreal h = d->mHeight; + if (h < sz.height()) + h = sz.height(); + return QRectF(0.0,0.0,w,h); +} + /*! \internal */ diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem_p.h b/src/declarative/graphicsitems/qdeclarativepainteditem_p.h index 8d08ba2..86f065a 100644 --- a/src/declarative/graphicsitems/qdeclarativepainteditem_p.h +++ b/src/declarative/graphicsitems/qdeclarativepainteditem_p.h @@ -93,6 +93,7 @@ protected: const QVariant &value); void setCacheFrozen(bool); + QRectF boundingRect() const; Q_SIGNALS: void fillColorChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 207cc25..448ec06 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -110,6 +110,8 @@ QDeclarativeItem *QDeclarativePathViewPrivate::getItem(int modelIndex) att->setOnPath(true); } item->setParentItem(q); + QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item)); + itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); } requestedIndex = -1; return item; @@ -121,6 +123,8 @@ void QDeclarativePathViewPrivate::releaseItem(QDeclarativeItem *item) return; if (QDeclarativePathViewAttached *att = attached(item)) att->setOnPath(false); + QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item)); + itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry); model->release(item); } @@ -944,7 +948,7 @@ void QDeclarativePathView::mousePressEvent(QGraphicsSceneMouseEvent *event) void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativePathView); - if (!d->interactive || d->lastPosTime.isNull()) + if (!d->interactive || !d->lastPosTime.isValid()) return; if (!d->stealMouse) { @@ -978,7 +982,7 @@ void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) Q_D(QDeclarativePathView); d->stealMouse = false; setKeepMouseGrab(false); - if (!d->interactive || d->lastPosTime.isNull()) + if (!d->interactive || !d->lastPosTime.isValid()) return; qreal elapsed = qreal(d->lastElapsed + QDeclarativeItemPrivate::elapsed(d->lastPosTime)) / 1000.; @@ -1013,7 +1017,7 @@ void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) d->fixOffset(); } - d->lastPosTime = QTime(); + d->lastPosTime.invalidate(); ungrabMouse(); } @@ -1055,8 +1059,8 @@ bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) grabMouse(); return d->stealMouse; - } else if (!d->lastPosTime.isNull()) { - d->lastPosTime = QTime(); + } else if (d->lastPosTime.isValid()) { + d->lastPosTime.invalidate(); } return false; } @@ -1084,6 +1088,16 @@ bool QDeclarativePathView::sceneEventFilter(QGraphicsItem *i, QEvent *e) return QDeclarativeItem::sceneEventFilter(i, e); } +bool QDeclarativePathView::event(QEvent *event) +{ + if (event->type() == QEvent::User) { + refill(); + return true; + } + + return QDeclarativeItem::event(event); +} + void QDeclarativePathView::componentComplete() { Q_D(QDeclarativePathView); @@ -1103,6 +1117,7 @@ void QDeclarativePathView::refill() if (!d->isValid() || !isComponentComplete()) return; + d->layoutScheduled = false; bool currentVisible = false; // first move existing items and remove items off path diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p.h index 349a01c..8a6f53f 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p.h @@ -161,6 +161,7 @@ protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *); bool sendMouseEvent(QGraphicsSceneMouseEvent *event); bool sceneEventFilter(QGraphicsItem *, QEvent *); + bool event(QEvent *event); void componentComplete(); private Q_SLOTS: diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index 303486f..a0d2610 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeOpenMetaObjectType; class QDeclarativePathViewAttached; -class QDeclarativePathViewPrivate : public QDeclarativeItemPrivate +class QDeclarativePathViewPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener { Q_DECLARE_PUBLIC(QDeclarativePathView) @@ -77,7 +77,8 @@ public: : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0) , lastElapsed(0), mappedRange(1.0) , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true) - , autoHighlight(true), highlightUp(false), dragMargin(0), deceleration(100) + , autoHighlight(true), highlightUp(false), layoutScheduled(false) + , dragMargin(0), deceleration(100) , moveOffset(this, &QDeclarativePathViewPrivate::setOffset) , firstIndex(-1), pathItems(-1), requestedIndex(-1) , moveReason(Other), attType(0), highlightComponent(0), highlightItem(0) @@ -89,14 +90,29 @@ public: { } - void init() - { + void init() { Q_Q(QDeclarativePathView); offset = 0; q->setAcceptedMouseButtons(Qt::LeftButton); q->setFlag(QGraphicsItem::ItemIsFocusScope); q->setFiltersChildEvents(true); q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked())); + lastPosTime.invalidate(); + } + + void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) { + if ((newGeometry.size() != oldGeometry.size()) + && (!highlightItem || item != highlightItem)) { + scheduleLayout(); + } + } + + void scheduleLayout() { + Q_Q(QDeclarativePathView); + if (!layoutScheduled) { + layoutScheduled = true; + QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority); + } } QDeclarativeItem *getItem(int modelIndex); @@ -138,7 +154,8 @@ public: bool haveHighlightRange : 1; bool autoHighlight : 1; bool highlightUp : 1; - QTime lastPosTime; + bool layoutScheduled : 1; + QElapsedTimer lastPosTime; QPointF lastPos; qreal dragMargin; qreal deceleration; diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp index d098aa0..301ca00 100644 --- a/src/declarative/graphicsitems/qdeclarativerectangle.cpp +++ b/src/declarative/graphicsitems/qdeclarativerectangle.cpp @@ -114,11 +114,11 @@ void QDeclarativeGradientStop::updateGradient() rectangle with a gradient starting with red, blending to yellow at 1/3 of the size of the rectangle, and ending with Green: - \table - \row - \o \image gradient.png - \o \quotefile doc/src/snippets/declarative/gradient.qml - \endtable + \snippet doc/src/snippets/declarative/gradient.qml code + + Note that this item is not a visual representation of a gradient. To display a + gradient use a visual item (like rectangle) which supports having a gradient set + on it for display. \sa GradientStop */ diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 4e7e0fd..2c1eb67 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -499,13 +499,10 @@ void QDeclarativeText::setVAlign(VAlignment align) wrap if an explicit width has been set. wrapMode can be one of: \list - \o Text.NoWrap - no wrapping will be performed. - \o Text.WordWrap - wrapping is done on word boundaries. If the text cannot be - word-wrapped to the specified width it will be partially drawn outside of the item's bounds. - If this is undesirable then enable clipping on the item (Item::clip). - \o Text.WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. - \o Text.WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it - will occur at the appropriate point on the line, even in the middle of a word. + \o Text.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist The default is Text.NoWrap. @@ -715,6 +712,7 @@ void QDeclarativeTextPrivate::updateSize() QFontMetrics fm(font); if (text.isEmpty()) { q->setImplicitHeight(fm.height()); + emit q->paintedSizeChanged(); return; } @@ -753,11 +751,36 @@ void QDeclarativeTextPrivate::updateSize() //### need to comfirm cost of always setting these for richText q->setImplicitWidth(richText ? (int)doc->idealWidth() : size.width()); q->setImplicitHeight(richText ? (int)doc->size().height() : size.height()); + emit q->paintedSizeChanged(); } else { dirty = true; } } +/*! + \qmlproperty real Text::paintedWidth + + Returns the width of the text, including width past the width + which is covered due to insufficient wrapping if WrapMode is set. +*/ +qreal QDeclarativeText::paintedWidth() const +{ + return implicitWidth(); +} + +/*! + \qmlproperty real Text::paintedHeight + + Returns the height of the text, including height past the height + which is covered due to there being more text than fits in the set height. +*/ +qreal QDeclarativeText::paintedHeight() const +{ + return implicitHeight(); +} + + + // ### text layout handling should be profiled and optimized as needed // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 00ce126..db21140 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -71,6 +71,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? + Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) public: QDeclarativeText(QDeclarativeItem *parent=0); @@ -98,7 +100,8 @@ public: enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, WrapAnywhere = QTextOption::WrapAnywhere, - WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT + Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; QString text() const; @@ -137,6 +140,9 @@ public: int resourcesLoading() const; // mainly for testing + qreal paintedWidth() const; + qreal paintedHeight() const; + Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); @@ -149,6 +155,7 @@ Q_SIGNALS: void wrapModeChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); + void paintedSizeChanged(); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index e34bb3d..9ccb8d2 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -61,8 +61,9 @@ QT_BEGIN_NAMESPACE /*! \qmlclass TextEdit QDeclarativeTextEdit - \since 4.7 + \since 4.7 \brief The TextEdit item allows you to add editable formatted text to a scene. + \inherits Item It can display both plain and rich text. For example: @@ -483,14 +484,13 @@ void QDeclarativeTextEdit::setVAlign(QDeclarativeTextEdit::VAlignment alignment) The text will only wrap if an explicit width has been set. \list - \o TextEdit.NoWrap - no wrapping will be performed. - \o TextEdit.WordWrap - wrapping is done on word boundaries. - \o TextEdit.WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. - \o TextEdit.WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it - will occur at the appropriate point on the line, even in the middle of a word. + \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist - The default is TextEdit.NoWrap. + The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap. */ QDeclarativeTextEdit::WrapMode QDeclarativeTextEdit::wrapMode() const { @@ -510,6 +510,29 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) } /*! + \qmlproperty real TextEdit::paintedWidth + + Returns the width of the text, including width past the width + which is covered due to insufficient wrapping if WrapMode is set. +*/ +qreal QDeclarativeTextEdit::paintedWidth() const +{ + return implicitWidth(); +} + +/*! + \qmlproperty real TextEdit::paintedHeight + + Returns the height of the text, including height past the height + which is covered due to there being more text than fits in the set height. +*/ +qreal QDeclarativeTextEdit::paintedHeight() const +{ + return implicitHeight(); +} + + +/*! \qmlproperty bool TextEdit::cursorVisible If true the text edit shows a cursor. @@ -781,7 +804,7 @@ void QDeclarativeTextEdit::componentComplete() } /*! - \qmlproperty string TextEdit::selectByMouse + \qmlproperty bool TextEdit::selectByMouse Defaults to false. @@ -939,8 +962,8 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - bool hadFocus = hasFocus(); if (d->focusOnPress){ + bool hadFocus = hasFocus(); QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope? while(p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) @@ -948,9 +971,11 @@ void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) p = p->parentItem(); } setFocus(true); + if (hasFocus() == hadFocus && d->showInputPanelOnFocus && !isReadOnly()) { + // re-open input panel on press if already focused + openSoftwareInputPanel(); + } } - if (!hadFocus && hasFocus()) - d->clickCausedFocus = true; if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse) d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) @@ -964,11 +989,6 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - QWidget *widget = event->widget(); - if (widget && (d->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) - qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); - d->clickCausedFocus = false; - d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mouseReleaseEvent(event); @@ -1155,7 +1175,7 @@ void QDeclarativeTextEdit::updateSize() int dy = height(); // ### assumes that if the width is set, the text will fill to edges // ### (unless wrap is false, then clipping will occur) - if (widthValid()) + if (widthValid() && d->document->textWidth() != width()) d->document->setTextWidth(width()); dy -= (int)d->document->size().height(); @@ -1171,7 +1191,7 @@ void QDeclarativeTextEdit::updateSize() //### need to comfirm cost of always setting these int newWidth = qCeil(d->document->idealWidth()); - if (!widthValid()) + if (!widthValid() && d->document->textWidth() != newWidth) d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug) int cursorWidth = 1; if(d->cursor) @@ -1181,9 +1201,12 @@ void QDeclarativeTextEdit::updateSize() newWidth += 3;// ### Need a better way of accounting for space between char and cursor // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. setImplicitWidth(newWidth); - setImplicitHeight(d->document->isEmpty() ? fm.height() : (int)d->document->size().height()); + qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height(); + setImplicitHeight(newHeight); - setContentsSize(QSize(width(), height())); + setContentsSize(QSize(newWidth, newHeight)); + + emit paintedSizeChanged(); } else { d->dirty = true; } @@ -1204,4 +1227,127 @@ void QDeclarativeTextEditPrivate::updateDefaultTextOption() document->setDefaultTextOption(opt); } + +/*! + \qmlmethod void TextEdit::openSoftwareInputPanel() + + Opens software input panels like virtual keyboards for typing, useful for + customizing when you want the input keyboard to be shown and hidden in + your application. + + By default input panels are shown when TextEdit element gains focus and hidden + when the focus is lost. You can disable the automatic behavior by setting the + property showInputPanelOnFocus to false and use functions openSoftwareInputPanel() + and closeSoftwareInputPanel() to implement the behavior you want. + + Only relevant on platforms, which provide virtual keyboards. + + \code + import Qt 4.7 + TextEdit { + id: textEdit + text: "Hello world!" + showInputPanelOnFocus: false + MouseArea { + anchors.fill: parent + onClicked: textEdit.openSoftwareInputPanel() + } + onFocusChanged: if (!focus) closeSoftwareInputpanel() + } + \endcode +*/ +void QDeclarativeTextEdit::openSoftwareInputPanel() +{ + QEvent event(QEvent::RequestSoftwareInputPanel); + if (qApp) { + if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { + if (view->scene() && view->scene() == scene()) { + QApplication::sendEvent(view, &event); + } + } + } +} + +/*! + \qmlmethod void TextEdit::closeSoftwareInputPanel() + + Closes a software input panel like a virtual keyboard shown on the screen, useful + for customizing when you want the input keyboard to be shown and hidden in + your application. + + By default input panels are shown when TextEdit element gains focus and hidden + when the focus is lost. You can disable the automatic behavior by setting the + property showInputPanelOnFocus to false and use functions openSoftwareInputPanel() + and closeSoftwareInputPanel() to implement the behavior you want. + + Only relevant on platforms, which provide virtual keyboards. + + \code + import Qt 4.7 + TextEdit { + id: textEdit + text: "Hello world!" + showInputPanelOnFocus: false + MouseArea { + anchors.fill: parent + onClicked: textEdit.openSoftwareInputPanel() + } + onFocusChanged: if (!focus) closeSoftwareInputpanel() + } + \endcode +*/ +void QDeclarativeTextEdit::closeSoftwareInputPanel() +{ + QEvent event(QEvent::CloseSoftwareInputPanel); + if (qApp) { + if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { + if (view->scene() && view->scene() == scene()) { + QApplication::sendEvent(view, &event); + } + } + } +} + +/*! + \qmlproperty bool TextEdit::showInputPanelOnFocus + Whether input panels are automatically shown when TextEdit element gains + focus and hidden when focus is lost. By default this is set to true. + + Only relevant on platforms, which provide virtual keyboards. +*/ +bool QDeclarativeTextEdit::showInputPanelOnFocus() const +{ + Q_D(const QDeclarativeTextEdit); + return d->showInputPanelOnFocus; +} + +void QDeclarativeTextEdit::setShowInputPanelOnFocus(bool showOnFocus) +{ + Q_D(QDeclarativeTextEdit); + if (d->showInputPanelOnFocus == showOnFocus) + return; + + d->showInputPanelOnFocus = showOnFocus; + + emit showInputPanelOnFocusChanged(d->showInputPanelOnFocus); +} + +void QDeclarativeTextEdit::focusInEvent(QFocusEvent *event) +{ + Q_D(const QDeclarativeTextEdit); + if (d->showInputPanelOnFocus && !isReadOnly() && event->reason() != Qt::ActiveWindowFocusReason) { + openSoftwareInputPanel(); + } + QDeclarativePaintedItem::focusInEvent(event); +} + +void QDeclarativeTextEdit::focusOutEvent(QFocusEvent *event) +{ + Q_D(const QDeclarativeTextEdit); + if (d->showInputPanelOnFocus && !isReadOnly()) { + closeSoftwareInputPanel(); + } + QDeclarativePaintedItem::focusOutEvent(event); +} + QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 891b868..47174f4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -74,6 +74,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged) @@ -84,6 +86,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged) Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged) + Q_PROPERTY(bool showInputPanelOnFocus READ showInputPanelOnFocus WRITE setShowInputPanelOnFocus NOTIFY showInputPanelOnFocusChanged) Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged) Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) @@ -113,9 +116,13 @@ public: enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, WrapAnywhere = QTextOption::WrapAnywhere, - WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT + Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + Q_INVOKABLE void openSoftwareInputPanel(); + Q_INVOKABLE void closeSoftwareInputPanel(); + QString text() const; void setText(const QString &); @@ -163,6 +170,9 @@ public: bool focusOnPress() const; void setFocusOnPress(bool on); + bool showInputPanelOnFocus() const; + void setShowInputPanelOnFocus(bool showOnFocus); + bool persistentSelection() const; void setPersistentSelection(bool on); @@ -185,8 +195,12 @@ public: QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + qreal paintedWidth() const; + qreal paintedHeight() const; + Q_SIGNALS: void textChanged(const QString &); + void paintedSizeChanged(); void cursorPositionChanged(); void cursorRectangleChanged(); void selectionStartChanged(); @@ -207,6 +221,7 @@ Q_SIGNALS: void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); void selectByMouseChanged(bool selectByMouse); + void showInputPanelOnFocusChanged(bool showOnFocus); public Q_SLOTS: void selectAll(); @@ -228,6 +243,8 @@ protected: bool event(QEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); // mouse filter? void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index d96796c..8e1d630 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -70,9 +70,9 @@ public: QDeclarativeTextEditPrivate() : color("black"), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), - persistentSelection(true), clickCausedFocus(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), - cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), - wrapMode(QDeclarativeTextEdit::NoWrap), + showInputPanelOnFocus(true), persistentSelection(true), textMargin(0.0), lastSelectionStart(0), + lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), + document(0), wrapMode(QDeclarativeTextEdit::NoWrap), selectByMouse(false), yoff(0) { @@ -101,8 +101,8 @@ public: bool richText : 1; bool cursorVisible : 1; bool focusOnPress : 1; + bool showInputPanelOnFocus : 1; bool persistentSelection : 1; - bool clickCausedFocus : 1; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 2e7715f..9c70ea9 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -54,8 +54,9 @@ QT_BEGIN_NAMESPACE /*! \qmlclass TextInput QDeclarativeTextInput - \since 4.7 + \since 4.7 \brief The TextInput item allows you to add an editable line of text to a scene. + \inherits Item TextInput can only display a single line of text, and can only display plain text. However it can provide addition input constraints on the text. @@ -885,8 +886,8 @@ void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev) void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); - bool hadFocus = hasFocus(); if(d->focusOnPress){ + bool hadFocus = hasFocus(); QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope? while(p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) @@ -894,9 +895,11 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) p = p->parentItem(); } setFocus(true); + if (hasFocus() == hadFocus && d->showInputPanelOnFocus && !isReadOnly()) { + // re-open input panel on press w already focused + openSoftwareInputPanel(); + } } - if (!hadFocus && hasFocus()) - d->clickCausedFocus = true; bool mark = event->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(event->pos().x()); @@ -922,10 +925,7 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); - QWidget *widget = event->widget(); - if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos())) - qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); - d->clickCausedFocus = false; + d->control->processEvent(event); if (!event->isAccepted()) QDeclarativePaintedItem::mouseReleaseEvent(event); } @@ -1120,7 +1120,7 @@ QString QDeclarativeTextInput::displayText() const } /*! - \qmlproperty string TextInput::selectByMouse + \qmlproperty bool TextInput::selectByMouse Defaults to false. @@ -1174,6 +1174,129 @@ void QDeclarativeTextInput::moveCursorSelection(int position) d->control->moveCursor(position, true); } +/*! + \qmlmethod void TextInput::openSoftwareInputPanel() + + Opens software input panels like virtual keyboards for typing, useful for + customizing when you want the input keyboard to be shown and hidden in + your application. + + By default input panels are shown when TextInput element gains focus and hidden + when the focus is lost. You can disable the automatic behavior by setting the + property showInputPanelOnFocus to false and use functions openSoftwareInputPanel() + and closeSoftwareInputPanel() to implement the behavior you want. + + Only relevant on platforms, which provide virtual keyboards. + + \code + import Qt 4.7 + TextInput { + id: textInput + text: "Hello world!" + showInputPanelOnFocus: false + MouseArea { + anchors.fill: parent + onClicked: textInput.openSoftwareInputPanel() + } + onFocusChanged: if (!focus) closeSoftwareInputPanel() + } + \endcode +*/ +void QDeclarativeTextInput::openSoftwareInputPanel() +{ + QEvent event(QEvent::RequestSoftwareInputPanel); + if (qApp) { + if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { + if (view->scene() && view->scene() == scene()) { + QApplication::sendEvent(view, &event); + } + } + } +} + +/*! + \qmlmethod void TextInput::closeSoftwareInputPanel() + + Closes a software input panel like a virtual keyboard shown on the screen, useful + for customizing when you want the input keyboard to be shown and hidden in + your application. + + By default input panels are shown when TextInput element gains focus and hidden + when the focus is lost. You can disable the automatic behavior by setting the + property showInputPanelOnFocus to false and use functions openSoftwareInputPanel() + and closeSoftwareInputPanel() to implement the behavior you want. + + Only relevant on platforms, which provide virtual keyboards. + + \code + import Qt 4.7 + TextInput { + id: textInput + text: "Hello world!" + showInputPanelOnFocus: false + MouseArea { + anchors.fill: parent + onClicked: textInput.openSoftwareInputPanel() + } + onFocusChanged: if (!focus) closeSoftwareInputPanel() + } + \endcode +*/ +void QDeclarativeTextInput::closeSoftwareInputPanel() +{ + QEvent event(QEvent::CloseSoftwareInputPanel); + if (qApp) { + QEvent event(QEvent::CloseSoftwareInputPanel); + if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { + if (view->scene() && view->scene() == scene()) { + QApplication::sendEvent(view, &event); + } + } + } +} + +/*! + \qmlproperty bool TextInput::showInputPanelOnFocus + Whether input panels are automatically shown when TextInput element gains + focus and hidden when focus is lost. By default this is set to true. + + Only relevant on platforms, which provide virtual keyboards. +*/ +bool QDeclarativeTextInput::showInputPanelOnFocus() const +{ + Q_D(const QDeclarativeTextInput); + return d->showInputPanelOnFocus; +} + +void QDeclarativeTextInput::setShowInputPanelOnFocus(bool showOnFocus) +{ + Q_D(QDeclarativeTextInput); + if (d->showInputPanelOnFocus == showOnFocus) + return; + + d->showInputPanelOnFocus = showOnFocus; + + emit showInputPanelOnFocusChanged(d->showInputPanelOnFocus); +} + +void QDeclarativeTextInput::focusInEvent(QFocusEvent *event) +{ + Q_D(const QDeclarativeTextInput); + if (d->showInputPanelOnFocus && !isReadOnly() && event->reason() != Qt::ActiveWindowFocusReason) { + openSoftwareInputPanel(); + } + QDeclarativePaintedItem::focusInEvent(event); +} + +void QDeclarativeTextInput::focusOutEvent(QFocusEvent *event) +{ + Q_D(const QDeclarativeTextInput); + if (d->showInputPanelOnFocus && !isReadOnly()) { + closeSoftwareInputPanel(); + } + QDeclarativePaintedItem::focusOutEvent(event); +} + void QDeclarativeTextInputPrivate::init() { Q_Q(QDeclarativeTextInput); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index b2fd057..438293a 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -86,6 +86,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextInput : public QDeclarativePaintedIte Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged) Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged) Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged) + Q_PROPERTY(bool showInputPanelOnFocus READ showInputPanelOnFocus WRITE setShowInputPanelOnFocus NOTIFY showInputPanelOnFocusChanged) Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged) Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) @@ -112,6 +113,9 @@ public: Q_INVOKABLE int xToPosition(int x); Q_INVOKABLE void moveCursorSelection(int pos); + Q_INVOKABLE void openSoftwareInputPanel(); + Q_INVOKABLE void closeSoftwareInputPanel(); + QString text() const; void setText(const QString &); @@ -172,6 +176,9 @@ public: bool focusOnPress() const; void setFocusOnPress(bool); + bool showInputPanelOnFocus() const; + void setShowInputPanelOnFocus(bool showOnFocus); + bool autoScroll() const; void setAutoScroll(bool); @@ -208,6 +215,7 @@ Q_SIGNALS: void focusOnPressChanged(bool focusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); + void showInputPanelOnFocusChanged(bool showOnFocus); protected: virtual void geometryChanged(const QRectF &newGeometry, @@ -218,6 +226,8 @@ protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void keyPressEvent(QKeyEvent* ev); bool event(QEvent *e); + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); public Q_SLOTS: void selectAll(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 1d8e0f7..f44d014 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -72,7 +72,7 @@ public: color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), - cursorVisible(false), autoScroll(true), clickCausedFocus(false), + showInputPanelOnFocus(true), cursorVisible(false), autoScroll(true), selectByMouse(false) { } @@ -115,9 +115,9 @@ public: int oldScroll; bool focused; bool focusOnPress; + bool showInputPanelOnFocus; bool cursorVisible; bool autoScroll; - bool clickCausedFocus; bool selectByMouse; }; |