diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-04-28 07:59:43 (GMT) |
---|---|---|
committer | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-04-28 07:59:43 (GMT) |
commit | 0d70b0a9faecf042fdb20e0056bdaaec289b851c (patch) | |
tree | 5ad6397fbab4dac6b37f740256aa585183e147c1 /src | |
parent | d45ec470519d1075ebf299b74cbb846a0c7d99af (diff) | |
parent | ce4996b624678f37b13fbb7db810cccd8970a889 (diff) | |
download | Qt-0d70b0a9faecf042fdb20e0056bdaaec289b851c.zip Qt-0d70b0a9faecf042fdb20e0056bdaaec289b851c.tar.gz Qt-0d70b0a9faecf042fdb20e0056bdaaec289b851c.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt into 4.7
Conflicts:
src/s60installs/eabi/QtGuiu.def
Diffstat (limited to 'src')
97 files changed, 1755 insertions, 500 deletions
diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp index 2c01773..959172d 100644 --- a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp +++ b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp @@ -1,3 +1,28 @@ +/* This file is part of the KDE project + The following license applies to the edits made to the generated + source code: + + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + Copyright (C) 2009 Matthias Kretz. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ /* * This file was generated by dbusidl2cpp version 0.4 * when processing input file org.kde.Phonon.AudioOutput.xml diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h index 7178e9b..140a74f 100644 --- a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h +++ b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h @@ -1,3 +1,28 @@ +/* This file is part of the KDE project + The following license applies to the edits made to the generated + source code: + + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + Copyright (C) 2009 Matthias Kretz. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ /* * This file was generated by dbusidl2cpp version 0.4 * when processing input file org.kde.Phonon.AudioOutput.xml diff --git a/src/corelib/concurrent/qfutureinterface.cpp b/src/corelib/concurrent/qfutureinterface.cpp index 627d0c7..c5bd802 100644 --- a/src/corelib/concurrent/qfutureinterface.cpp +++ b/src/corelib/concurrent/qfutureinterface.cpp @@ -219,7 +219,7 @@ QString QFutureInterfaceBase::progressText() const bool QFutureInterfaceBase::isProgressUpdateNeeded() const { QMutexLocker locker(&d->m_mutex); - return (d->progressTime.elapsed() > (1000 / MaxProgressEmitsPerSecond)); + return !d->progressTime.isValid() || (d->progressTime.elapsed() > (1000 / MaxProgressEmitsPerSecond)); } void QFutureInterfaceBase::reportStarted() diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 3b4adc3..4d3f50b 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -278,6 +278,7 @@ void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo) current entry will be returned as part of the directory iteration); otherwise, false is returned. */ + bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const { Q_ASSERT(!fileName.isEmpty()); @@ -312,6 +313,14 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf return false; } #endif + // skip symlinks + const bool skipSymlinks = (filters & QDir::NoSymLinks); + const bool includeSystem = (filters & QDir::System); + if(skipSymlinks && fi.isSymLink()) { + // The only reason to save this file is if it is a broken link and we are requesting system files. + if(!includeSystem || fi.exists()) + return false; + } // filter hidden const bool includeHidden = (filters & QDir::Hidden); @@ -319,27 +328,20 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf return false; // filter system files - const bool includeSystem = (filters & QDir::System); - if (!includeSystem && ((!fi.isFile() && !fi.isDir() && !fi.isSymLink()) + if (!includeSystem && (!(fi.isFile() || fi.isDir() || fi.isSymLink()) || (!fi.exists() && fi.isSymLink()))) return false; // skip directories const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs)); - if (skipDirs && fi.isDir()) { - if (!((includeHidden && !dotOrDotDot && fi.isHidden()) - || (includeSystem && !fi.exists() && fi.isSymLink()))) - return false; - } + if (skipDirs && fi.isDir()) + return false; // skip files const bool skipFiles = !(filters & QDir::Files); - const bool skipSymlinks = (filters & QDir::NoSymLinks); - if ((skipFiles && (fi.isFile() || !fi.exists())) || (skipSymlinks && fi.isSymLink())) { - if (!((includeHidden && !dotOrDotDot && fi.isHidden()) - || (includeSystem && !fi.exists() && fi.isSymLink()))) - return false; - } + if (skipFiles && fi.isFile()) + // Basically we need a reason not to exclude this file otherwise we just eliminate it. + return false; // filter permissions const bool filterPermissions = ((filters & QDir::PermissionMask) diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp index c2bb094..34bc406 100644 --- a/src/corelib/tools/qtextboundaryfinder.cpp +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -457,33 +457,23 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons return NotAtBoundary; return StartWord; } - if (pos >= length - 1) { + if (pos == length) { if (d->attributes[length-1].whiteSpace) return NotAtBoundary; return EndWord; } - BoundaryReasons answer; - const bool nextIsSpace = d->attributes[pos + 1].whiteSpace; + const bool nextIsSpace = d->attributes[pos].whiteSpace; const bool prevIsSpace = d->attributes[pos - 1].whiteSpace; - if (d->attributes[pos].whiteSpace) - answer = EndWord; - else if (!prevIsSpace) { - answer = StartWord; - answer |= EndWord; - } - - if (prevIsSpace) - answer |= StartWord; - if (nextIsSpace) - answer |= EndWord; - if (answer == 0) { - answer = StartWord; - answer |= EndWord; - } - - return answer; + if (prevIsSpace && !nextIsSpace) + return StartWord; + else if (!prevIsSpace && nextIsSpace) + return EndWord; + else if (!prevIsSpace && !nextIsSpace) + return BoundaryReasons(StartWord | EndWord); + else + return NotAtBoundary; } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp index 0478209..93f7423 100644 --- a/src/declarative/debugger/qdeclarativedebughelper.cpp +++ b/src/declarative/debugger/qdeclarativedebughelper.cpp @@ -65,10 +65,12 @@ void QDeclarativeDebugHelper::setAnimationSlowDownFactor(qreal factor) } void QDeclarativeDebugHelper::enableDebugging() { +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { qWarning("Qml debugging is enabled. Only use this in a safe environment!"); } QDeclarativeEnginePrivate::qml_debugging_enabled = true; +#endif } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp index ea3d9a3..7fa5a62 100644 --- a/src/declarative/debugger/qdeclarativedebugserver.cpp +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -91,7 +91,7 @@ public: QStringList clientPlugins; bool gotHello; - static QDeclarativeDebugServerConnection *loadConnectionPlugin(); + static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName); }; QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() : @@ -113,7 +113,8 @@ void QDeclarativeDebugServerPrivate::advertisePlugins() connection->send(message); } -QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin() +QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin( + const QString &pluginName) { QStringList pluginCandidates; const QStringList paths = QCoreApplication::libraryPaths(); @@ -122,7 +123,8 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio if (dir.exists()) { QStringList plugins(dir.entryList(QDir::Files)); foreach (const QString &pluginPath, plugins) { - pluginCandidates << dir.absoluteFilePath(pluginPath); + if (QFileInfo(pluginPath).fileName().contains(pluginName)) + pluginCandidates << dir.absoluteFilePath(pluginPath); } } } @@ -159,14 +161,14 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() if (!commandLineTested) { commandLineTested = true; -#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp)); +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL // ### remove port definition when protocol is changed int port = 0; bool block = false; bool ok = false; - // format: qmljsdebugger=port:3768[,block] + // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block] if (!appD->qmljsDebugArgumentsString().isEmpty()) { if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { const QString message = @@ -177,24 +179,30 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() return 0; } + QString pluginName; if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); + pluginName = QLatin1String("qmldbg_tcp"); + } else if (appD->qmljsDebugArgumentsString().contains("ost")) { + pluginName = QLatin1String("qmldbg_ost"); + ok = true; } + block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); if (ok) { server = new QDeclarativeDebugServer(); QDeclarativeDebugServerConnection *connection - = QDeclarativeDebugServerPrivate::loadConnectionPlugin(); + = QDeclarativeDebugServerPrivate::loadConnectionPlugin(pluginName); if (connection) { server->d_func()->connection = connection; connection->setServer(server); connection->setPort(port, block); } else { - qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring\"-qmljsdebugger=%1\". " + qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString()); } @@ -204,6 +212,12 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() appD->qmljsDebugArgumentsString()).toAscii().constData()); } } +#else + if (!appD->qmljsDebugArgumentsString().isEmpty()) { + qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "QtDeclarative is not configured for debugging.").arg( + appD->qmljsDebugArgumentsString()).toAscii().constData()); + } #endif } diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 8f37e90..45a03a0 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -300,7 +300,7 @@ void QDeclarativeBorderImage::load() } if (d->url.isEmpty()) { - d->pix.clear(); + d->pix.clear(this); d->status = Null; setImplicitWidth(0); setImplicitHeight(0); @@ -340,6 +340,7 @@ void QDeclarativeBorderImage::load() options |= QDeclarativePixmap::Asynchronous; if (d->cache) options |= QDeclarativePixmap::Cache; + d->pix.clear(this); d->pix.load(qmlEngine(this), d->url, options); if (d->pix.isLoading()) { @@ -472,6 +473,7 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma options |= QDeclarativePixmap::Asynchronous; if (d->cache) options |= QDeclarativePixmap::Cache; + d->pix.clear(this); d->pix.load(qmlEngine(this), d->sciurl, options); if (d->pix.isLoading()) { diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 511f789..82ed18c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -45,9 +45,40 @@ #include <QGraphicsSceneMouseEvent> #include <QPointer> #include <QTimer> +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +// The maximum number of pixels a flick can overshoot +#ifndef QML_FLICK_OVERSHOOT +#define QML_FLICK_OVERSHOOT 200 +#endif + +// The number of samples to use in calculating the velocity of a flick +#ifndef QML_FLICK_SAMPLEBUFFER +#define QML_FLICK_SAMPLEBUFFER 3 +#endif + +// The number of samples to discard when calculating the flick velocity. +// Touch panels often produce inaccurate results as the finger is lifted. +#ifndef QML_FLICK_DISCARDSAMPLES +#define QML_FLICK_DISCARDSAMPLES 1 +#endif + +// The default maximum velocity of a flick. +#ifndef QML_FLICK_DEFAULTMAXVELOCITY +#define QML_FLICK_DEFAULTMAXVELOCITY 2500 +#endif + +// The default deceleration of a flick. +#ifndef QML_FLICK_DEFAULTDECELERATION +#define QML_FLICK_DEFAULTDECELERATION 1750 +#endif + +// How much faster to decelerate when overshooting +#ifndef QML_FLICK_OVERSHOOTFRICTION +#define QML_FLICK_OVERSHOOTFRICTION 8 +#endif // FlickThreshold determines how far the "mouse" must have moved // before we perform a flick. @@ -141,8 +172,9 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() , hMoved(false), vMoved(false) , movingHorizontally(false), movingVertically(false) , stealMouse(false), pressed(false), interactive(true), calcVelocity(false) - , deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) - , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600) + , deceleration(QML_FLICK_DEFAULTDECELERATION) + , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100) + , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400) , fixupMode(Normal), vTime(0), visibleArea(0) , flickableDirection(QDeclarativeFlickable::AutoFlickDirection) , boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds) @@ -176,19 +208,39 @@ void QDeclarativeFlickablePrivate::init() } /* - Returns the amount to overshoot by given a velocity. - Will be roughly in range 0 - size/4 + Returns the amount to overshoot by given a view size. + Will be up to the lesser of 1/3 of the view size or QML_FLICK_OVERSHOOT */ -qreal QDeclarativeFlickablePrivate::overShootDistance(qreal velocity, qreal size) +qreal QDeclarativeFlickablePrivate::overShootDistance(qreal size) { if (maxVelocity <= 0) return 0.0; - velocity = qAbs(velocity); - if (velocity > maxVelocity) - velocity = maxVelocity; - qreal dist = size / 4 * velocity / maxVelocity; - return dist; + return qMin(qreal(QML_FLICK_OVERSHOOT), size/3); +} + +void QDeclarativeFlickablePrivate::AxisData::addVelocitySample(qreal v, qreal maxVelocity) +{ + if (v > maxVelocity) + v = maxVelocity; + else if (v < -maxVelocity) + v = -maxVelocity; + velocityBuffer.append(v); + if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER) + velocityBuffer.remove(0); +} + +void QDeclarativeFlickablePrivate::AxisData::updateVelocity() +{ + if (velocityBuffer.count() > QML_FLICK_DISCARDSAMPLES) { + velocity = 0; + int count = velocityBuffer.count()-QML_FLICK_DISCARDSAMPLES; + for (int i = 0; i < count; ++i) { + qreal v = velocityBuffer.at(i); + velocity += v; + } + velocity /= count; + } } void QDeclarativeFlickablePrivate::itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeom, const QRectF &oldGeom) @@ -220,15 +272,12 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal Q_Q(QDeclarativeFlickable); qreal maxDistance = -1; data.fixingUp = false; - bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; // -ve velocity means list is moving up if (velocity > 0) { - if (data.move.value() < minExtent) - maxDistance = qAbs(minExtent - data.move.value() + (overShoot?overShootDistance(velocity,vSize):0)); + maxDistance = qAbs(minExtent - data.move.value()); data.flickTarget = minExtent; } else { - if (data.move.value() > maxExtent) - maxDistance = qAbs(maxExtent - data.move.value()) + (overShoot?overShootDistance(velocity,vSize):0); + maxDistance = qAbs(maxExtent - data.move.value()); data.flickTarget = maxExtent; } if (maxDistance > 0) { @@ -240,7 +289,10 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal v = maxVelocity; } timeline.reset(data.move); - timeline.accel(data.move, v, deceleration, maxDistance); + if (boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds) + timeline.accel(data.move, v, deceleration); + else + timeline.accel(data.move, v, deceleration, maxDistance); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); if (!flickingHorizontally && q->xflick()) { flickingHorizontally = true; @@ -327,6 +379,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal } } } + data.inOvershoot = false; fixupMode = Normal; vTime = timeline.time(); } @@ -706,16 +759,13 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven q->setKeepMouseGrab(stealMouse); pressed = true; timeline.clear(); - hData.velocity = 0; - vData.velocity = 0; - hData.dragStartOffset = 0; - vData.dragStartOffset = 0; + hData.reset(); + vData.reset(); hData.dragMinBound = q->minXExtent(); vData.dragMinBound = q->minYExtent(); hData.dragMaxBound = q->maxXExtent(); vData.dragMaxBound = q->maxYExtent(); - hData.fixingUp = false; - vData.fixingUp = false; + fixupMode = Normal; lastPos = QPoint(); QDeclarativeItemPrivate::start(lastPosTime); pressPos = event->pos(); @@ -807,33 +857,33 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (stealMouse) q->setKeepMouseGrab(true); - if (!lastPos.isNull()) { - qreal elapsed = qreal(QDeclarativeItemPrivate::restart(lastPosTime)) / 1000.; - if (elapsed <= 0) - elapsed = 1; - if (q->yflick()) { - qreal diff = event->pos().y() - lastPos.y(); - // average to reduce the effect of spurious moves - vData.velocity += diff / elapsed; - vData.velocity /= 2; - } - - if (q->xflick()) { - qreal diff = event->pos().x() - lastPos.x(); - // average to reduce the effect of spurious moves - hData.velocity += diff / elapsed; - hData.velocity /= 2; - } + if (rejectY) { + vData.velocityBuffer.clear(); + vData.velocity = 0; + } + if (rejectX) { + hData.velocityBuffer.clear(); + hData.velocity = 0; } - - if (rejectY) vData.velocity = 0; - if (rejectX) hData.velocity = 0; if (hMoved || vMoved) { q->movementStarting(); q->viewportMoved(); } + if (!lastPos.isNull()) { + qreal elapsed = qreal(QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.; + if (elapsed <= 0) + return; + QDeclarativeItemPrivate::restart(lastPosTime); + qreal dy = event->pos().y()-lastPos.y(); + if (q->yflick() && !rejectY) + vData.addVelocitySample(dy/elapsed, maxVelocity); + qreal dx = event->pos().x()-lastPos.x(); + if (q->xflick() && !rejectX) + hData.addVelocitySample(dx/elapsed, maxVelocity); + } + lastPos = event->pos(); } @@ -846,25 +896,33 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv if (!lastPosTime.isValid()) return; - if (QDeclarativeItemPrivate::elapsed(lastPosTime) > 100) { - // if we drag then pause before release we should not cause a flick. + // if we drag then pause before release we should not cause a flick. + if (QDeclarativeItemPrivate::elapsed(lastPosTime) < 100) { + vData.updateVelocity(); + hData.updateVelocity(); + } else { hData.velocity = 0.0; vData.velocity = 0.0; } vTime = timeline.time(); - if (qAbs(vData.velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) - flickY(vData.velocity); + + qreal velocity = vData.velocity; + if (vData.atBeginning || vData.atEnd) + velocity /= 2; + if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) + flickY(velocity); else fixupY(); - if (qAbs(hData.velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) - flickX(hData.velocity); + velocity = hData.velocity; + if (hData.atBeginning || hData.atEnd) + velocity /= 2; + if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) + flickX(velocity); else fixupX(); - lastPosTime.invalidate(); - if (!timeline.isActive()) q->movementEnding(); } @@ -911,29 +969,41 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) if (!d->interactive) { QDeclarativeItem::wheelEvent(event); } else if (yflick() && event->orientation() == Qt::Vertical) { - if (event->delta() > 0) - d->vData.velocity = qMax(event->delta() - d->vData.smoothVelocity.value(), qreal(250.0)); - else - d->vData.velocity = qMin(event->delta() - d->vData.smoothVelocity.value(), qreal(-250.0)); - d->flickingVertically = false; - d->flickY(d->vData.velocity); - if (d->flickingVertically) { - d->vMoved = true; - movementStarting(); + bool valid = false; + if (event->delta() > 0 && contentY() > -minYExtent()) { + d->vData.velocity = qMax(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(d->maxVelocity/4)); + valid = true; + } else if (event->delta() < 0 && contentY() < -maxYExtent()) { + d->vData.velocity = qMin(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(-d->maxVelocity/4)); + valid = true; + } + if (valid) { + d->flickingVertically = false; + d->flickY(d->vData.velocity); + if (d->flickingVertically) { + d->vMoved = true; + movementStarting(); + } + event->accept(); } - event->accept(); } else if (xflick() && event->orientation() == Qt::Horizontal) { - if (event->delta() > 0) - d->hData.velocity = qMax(event->delta() - d->hData.smoothVelocity.value(), qreal(250.0)); - else - d->hData.velocity = qMin(event->delta() - d->hData.smoothVelocity.value(), qreal(-250.0)); - d->flickingHorizontally = false; - d->flickX(d->hData.velocity); - if (d->flickingHorizontally) { - d->hMoved = true; - movementStarting(); + bool valid = false; + if (event->delta() > 0 && contentX() > -minXExtent()) { + d->hData.velocity = qMax(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(d->maxVelocity/4)); + valid = true; + } else if (event->delta() < 0 && contentX() < -maxXExtent()) { + d->hData.velocity = qMin(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(-d->maxVelocity/4)); + valid = true; + } + if (valid) { + d->flickingHorizontally = false; + d->flickX(d->hData.velocity); + if (d->flickingHorizontally) { + d->hMoved = true; + movementStarting(); + } + event->accept(); } - event->accept(); } else { QDeclarativeItem::wheelEvent(event); } @@ -1071,6 +1141,27 @@ void QDeclarativeFlickable::viewportMoved() } } + if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically + && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent()) + && qAbs(d->vData.smoothVelocity.value()) > 100) { + // Increase deceleration if we've passed a bound + d->vData.inOvershoot = true; + qreal maxDistance = d->overShootDistance(height()); + d->timeline.reset(d->vData.move); + d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance); + d->timeline.callback(QDeclarativeTimeLineCallback(&d->vData.move, d->fixupY_callback, d)); + } + if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally + && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent()) + && qAbs(d->hData.smoothVelocity.value()) > 100) { + // Increase deceleration if we've passed a bound + d->hData.inOvershoot = true; + qreal maxDistance = d->overShootDistance(width()); + d->timeline.reset(d->hData.move); + d->timeline.accel(d->hData.move, -d->hData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance); + d->timeline.callback(QDeclarativeTimeLineCallback(&d->hData.move, d->fixupX_callback, d)); + } + d->lastFlickablePosition = QPointF(d->hData.move.value(), d->vData.move.value()); d->vTime = d->timeline.time(); @@ -1339,7 +1430,9 @@ void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center) Q_D(QDeclarativeFlickable); if (w != d->hData.viewSize) { qreal oldSize = d->hData.viewSize; - setContentWidth(w); + d->hData.viewSize = w; + d->contentItem->setWidth(w); + emit contentWidthChanged(); if (center.x() != 0) { qreal pos = center.x() * w / oldSize; setContentX(contentX() + pos - center.x()); @@ -1347,12 +1440,15 @@ void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center) } if (h != d->vData.viewSize) { qreal oldSize = d->vData.viewSize; - setContentHeight(h); + d->vData.viewSize = h; + d->contentItem->setHeight(h); + emit contentHeightChanged(); if (center.y() != 0) { qreal pos = center.y() * h / oldSize; setContentY(contentY() + pos - center.y()); } } + d->updateBeginningEnd(); } /*! @@ -1519,7 +1615,7 @@ bool QDeclarativeFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e) \qmlproperty real Flickable::maximumFlickVelocity This property holds the maximum velocity that the user can flick the view in pixels/second. - The default is 2000 pixels/s + The default value is platform dependent. */ qreal QDeclarativeFlickable::maximumFlickVelocity() const { @@ -1540,7 +1636,7 @@ void QDeclarativeFlickable::setMaximumFlickVelocity(qreal v) \qmlproperty real Flickable::flickDeceleration This property holds the rate at which a flick will decelerate. - The default is 500. + The default value is platform dependent. */ qreal QDeclarativeFlickable::flickDeceleration() const { diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 38a5eb3..1117abb 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -94,9 +94,19 @@ public: struct AxisData { AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal)) : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true) - , fixingUp(false) + , fixingUp(false), inOvershoot(false) {} + void reset() { + velocityBuffer.clear(); + dragStartOffset = 0; + fixingUp = false; + inOvershoot = false; + } + + void addVelocitySample(qreal v, qreal maxVelocity); + void updateVelocity(); + QDeclarativeTimeLineValueProxy<QDeclarativeFlickablePrivate> move; qreal viewSize; qreal pressPos; @@ -106,9 +116,11 @@ public: qreal velocity; qreal flickTarget; QDeclarativeFlickablePrivate::Velocity smoothVelocity; + QPODVector<qreal,10> velocityBuffer; bool atEnd : 1; bool atBeginning : 1; bool fixingUp : 1; + bool inOvershoot : 1; }; void flickX(qreal velocity); @@ -129,7 +141,7 @@ public: void setRoundedViewportX(qreal x); void setRoundedViewportY(qreal y); - qreal overShootDistance(qreal velocity, qreal size); + qreal overShootDistance(qreal size); void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &); diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 546f75e..05e64b9 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -197,6 +197,7 @@ public: if (q->isComponentComplete()) { clear(); updateGrid(); + setPosition(0); q->refill(); updateCurrent(currentIndex); } @@ -583,6 +584,26 @@ void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer) --i; modelIndex = visibleItems.at(i)->index + 1; } + + if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2 + || fillTo < rowPosAt(visibleIndex) - rowSize())) { + // We've jumped more than a page. Estimate which items are now + // visible and fill from there. + int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns; + for (int i = 0; i < visibleItems.count(); ++i) + releaseItem(visibleItems.at(i)); + visibleItems.clear(); + modelIndex += count; + if (modelIndex >= model->count()) + modelIndex = model->count() - 1; + else if (modelIndex < 0) + modelIndex = 0; + modelIndex = modelIndex / columns * columns; + visibleIndex = modelIndex; + colPos = colPosAt(visibleIndex); + rowPos = rowPosAt(visibleIndex); + } + int colNum = colPos / colSize(); FxGridItem *item = 0; @@ -689,7 +710,6 @@ void QDeclarativeGridViewPrivate::updateGrid() q->setContentHeight(endPosition() - startPosition()); else q->setContentWidth(lastPosition() - originPosition()); - setPosition(0); } } @@ -1115,6 +1135,7 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } + data.inOvershoot = false; fixupMode = Normal; } @@ -1196,7 +1217,7 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m accel = v2 / (2.0f * qAbs(dist)); } else { data.flickTarget = velocity > 0 ? minExtent : maxExtent; - overshootDist = overShoot ? overShootDistance(v, vSize) : 0; + overshootDist = overShoot ? overShootDistance(vSize) : 0; } timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); @@ -2229,7 +2250,7 @@ qreal QDeclarativeGridView::maxXExtent() const qreal extent; qreal highlightStart; qreal highlightEnd; - qreal lastItemPosition; + qreal lastItemPosition = 0; if (d->isRightToLeftTopToBottom()){ highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size(); highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size(); diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index ed5d5fc..b776532 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -136,12 +136,10 @@ void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap) Q_Q(QDeclarativeImage); pix.setPixmap(pixmap); - q->setImplicitWidth(pix.width()); - q->setImplicitHeight(pix.height()); + q->pixmapChange(); status = pix.isNull() ? QDeclarativeImageBase::Null : QDeclarativeImageBase::Ready; q->update(); - q->pixmapChange(); } /*! @@ -377,6 +375,9 @@ qreal QDeclarativeImage::paintedHeight() const If the source is a non-scalable image (eg. JPEG), the loaded image will be no greater than this property specifies. For some formats (currently only JPEG), the whole image will never actually be loaded into memory. + + Since QtQuick 1.1 the sourceSize can be cleared to the natural size of the image + by setting sourceSize to \c undefined. \note \e {Changing this property dynamically causes the image source to be reloaded, potentially even from the network, if it is not in the disk cache.} @@ -387,8 +388,11 @@ void QDeclarativeImage::updatePaintedGeometry() Q_D(QDeclarativeImage); if (d->fillMode == PreserveAspectFit) { - if (!d->pix.width() || !d->pix.height()) + if (!d->pix.width() || !d->pix.height()) { + setImplicitWidth(0); + setImplicitHeight(0); return; + } qreal w = widthValid() ? width() : d->pix.width(); qreal widthScale = w / qreal(d->pix.width()); qreal h = heightValid() ? height() : d->pix.height(); @@ -402,9 +406,13 @@ void QDeclarativeImage::updatePaintedGeometry() } if (widthValid() && !heightValid()) { setImplicitHeight(d->paintedHeight); + } else { + setImplicitHeight(d->pix.height()); } if (heightValid() && !widthValid()) { setImplicitWidth(d->paintedWidth); + } else { + setImplicitWidth(d->pix.width()); } } else if (d->fillMode == PreserveAspectCrop) { if (!d->pix.width() || !d->pix.height()) @@ -563,6 +571,13 @@ void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWi void QDeclarativeImage::pixmapChange() { + Q_D(QDeclarativeImage); + // PreserveAspectFit calculates the implicit size differently so we + // don't call our superclass pixmapChange(), since that would + // result in the implicit size being set incorrectly, then updated + // in updatePaintedGeometry() + if (d->fillMode != PreserveAspectFit) + QDeclarativeImageBase::pixmapChange(); updatePaintedGeometry(); } diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 2de3ba0..81eac78 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -133,6 +133,18 @@ QSize QDeclarativeImageBase::sourceSize() const return QSize(width != -1 ? width : d->pix.width(), height != -1 ? height : d->pix.height()); } +void QDeclarativeImageBase::resetSourceSize() +{ + Q_D(QDeclarativeImageBase); + if (!d->explicitSourceSize) + return; + d->explicitSourceSize = false; + d->sourcesize = QSize(); + emit sourceSizeChanged(); + if (isComponentComplete()) + load(); +} + bool QDeclarativeImageBase::cache() const { Q_D(const QDeclarativeImageBase); @@ -176,14 +188,12 @@ void QDeclarativeImageBase::load() Q_D(QDeclarativeImageBase); if (d->url.isEmpty()) { - d->pix.clear(); + d->pix.clear(this); d->status = Null; d->progress = 0.0; - setImplicitWidth(0); - setImplicitHeight(0); + pixmapChange(); emit progressChanged(d->progress); emit statusChanged(d->status); - pixmapChange(); update(); } else { QDeclarativePixmap::Options options; @@ -191,6 +201,7 @@ void QDeclarativeImageBase::load() options |= QDeclarativePixmap::Asynchronous; if (d->cache) options |= QDeclarativePixmap::Cache; + d->pix.clear(this); d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), options); if (d->pix.isLoading()) { @@ -233,8 +244,7 @@ void QDeclarativeImageBase::requestFinished() d->progress = 1.0; - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); + pixmapChange(); if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) emit sourceSizeChanged(); @@ -243,7 +253,7 @@ void QDeclarativeImageBase::requestFinished() emit statusChanged(d->status); if (d->progress != oldProgress) emit progressChanged(d->progress); - pixmapChange(); + update(); } @@ -266,6 +276,9 @@ void QDeclarativeImageBase::componentComplete() void QDeclarativeImageBase::pixmapChange() { + Q_D(QDeclarativeImageBase); + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); } QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index abee25d..1763bba 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -59,7 +59,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeImplicitSizeI Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged REVISION 1) - Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) + Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize RESET resetSourceSize NOTIFY sourceSizeChanged) Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged REVISION 1) public: @@ -80,6 +80,7 @@ public: virtual void setSourceSize(const QSize&); QSize sourceSize() const; + void resetSourceSize(); virtual void setMirror(bool mirror); bool mirror() const; diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 6ae1ddc..2e9822e 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -744,6 +744,28 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer) if (visibleItems.at(i)->index != -1) modelIndex = visibleItems.at(i)->index + 1; } + + if (visibleItems.count() && (fillFrom > itemEnd+averageSize+spacing + || fillTo < visiblePos - averageSize - spacing)) { + // We've jumped more than a page. Estimate which items are now + // visible and fill from there. + int count = (fillFrom - itemEnd) / (averageSize + spacing); + for (int i = 0; i < visibleItems.count(); ++i) + releaseItem(visibleItems.at(i)); + visibleItems.clear(); + modelIndex += count; + if (modelIndex >= model->count()) { + count -= modelIndex - model->count() + 1; + modelIndex = model->count() - 1; + } else if (modelIndex < 0) { + count -= modelIndex; + modelIndex = 0; + } + visibleIndex = modelIndex; + visiblePos = itemEnd + count * (averageSize + spacing) + 1; + itemEnd = visiblePos-1; + } + bool changed = false; FxListItem *item = 0; qreal pos = itemEnd + 1; @@ -1354,6 +1376,7 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } + data.inOvershoot = false; fixupMode = Normal; } @@ -1428,10 +1451,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget; if (overShoot) { if (data.flickTarget >= minExtent) { - overshootDist = overShootDistance(v, vSize); + overshootDist = overShootDistance(vSize); data.flickTarget += overshootDist; } else if (data.flickTarget <= maxExtent) { - overshootDist = overShootDistance(v, vSize); + overshootDist = overShootDistance(vSize); data.flickTarget -= overshootDist; } } @@ -1451,10 +1474,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } else if (overShoot) { data.flickTarget = data.move.value() - dist; if (data.flickTarget >= minExtent) { - overshootDist = overShootDistance(v, vSize); + overshootDist = overShootDistance(vSize); data.flickTarget += overshootDist; } else if (data.flickTarget <= maxExtent) { - overshootDist = overShootDistance(v, vSize); + overshootDist = overShootDistance(vSize); data.flickTarget -= overshootDist; } } @@ -2118,9 +2141,11 @@ void QDeclarativeListView::setOrientation(QDeclarativeListView::Orientation orie if (d->orient == QDeclarativeListView::Vertical) { setContentWidth(-1); setFlickableDirection(VerticalFlick); + setContentX(0); } else { setContentHeight(-1); setFlickableDirection(HorizontalFlick); + setContentY(0); } d->regenerate(); emit orientationChanged(); @@ -2277,11 +2302,19 @@ void QDeclarativeListView::setCacheBuffer(int b) depending on the "size" property of the model item. The \c sectionHeading delegate component provides the light blue bar that marks the beginning of each section. + \snippet examples/declarative/modelviews/listview/sections.qml 0 \image qml-listview-sections-example.png + \note Adding sections to a ListView does not automatically re-order the + list items by the section criteria. + If the model is not ordered by section, then it is possible that + the sections created will not be unique; each boundary between + differing sections will result in a section header being created + even if that section exists elsewhere. + \sa {declarative/modelviews/listview}{ListView examples} */ QDeclarativeViewSection *QDeclarativeListView::sectionCriteria() @@ -2581,7 +2614,7 @@ void QDeclarativeListView::viewportMoved() d->inFlickCorrection = true; // Near an end and it seems that the extent has changed? // Recalculate the flick so that we don't end up in an odd position. - if (yflick()) { + if (yflick() && !d->vData.inOvershoot) { if (d->vData.velocity > 0) { const qreal minY = minYExtent(); if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2) @@ -2597,7 +2630,7 @@ void QDeclarativeListView::viewportMoved() } } - if (xflick()) { + if (xflick() && !d->hData.inOvershoot) { if (d->hData.velocity > 0) { const qreal minX = minXExtent(); if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2) @@ -2767,7 +2800,7 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event) return; if (d->model && d->model->count() && d->interactive) { - if ((!d->isRightToLeft() && event->key() == Qt::Key_Left) + if ((d->orient == QDeclarativeListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left) || (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right) || (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Up)) { if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) { @@ -2778,7 +2811,7 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event) event->accept(); return; } - } else if ((!d->isRightToLeft() && event->key() == Qt::Key_Right) + } else if ((d->orient == QDeclarativeListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right) || (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left) || (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Down)) { if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) { diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index f5145d0..d4e7f7b 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -496,6 +496,9 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) d->pressAndHoldTimer.start(PressAndHoldDelay, this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(true)); + + if(!event->isAccepted() && d->forwardToList.count()) + d->forwardEvent(event); } } @@ -573,6 +576,9 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); emit positionChanged(&me); + + if(!event->isAccepted() && d->forwardToList.count()) + d->forwardEvent(event); } @@ -594,6 +600,9 @@ void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) if (s && s->mouseGrabberItem() == this) ungrabMouse(); setKeepMouseGrab(false); + + if(!event->isAccepted() && d->forwardToList.count()) + d->forwardEvent(event); } d->doubleClick = false; } @@ -959,4 +968,11 @@ QDeclarativeDrag *QDeclarativeMouseArea::drag() */ +QDeclarativeListProperty<QGraphicsObject> QDeclarativeMouseArea::forwardTo() +{ + Q_D(QDeclarativeMouseArea); + return d->forwardTo; +} + + QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index 985f27e..351d4de 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -130,6 +130,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeMouseArea : public QDeclarativeItem Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged) Q_PROPERTY(QDeclarativeDrag *drag READ drag CONSTANT) //### add flicking to QDeclarativeDrag or add a QDeclarativeFlick ??? Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) + Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> forwardTo READ forwardTo); public: QDeclarativeMouseArea(QDeclarativeItem *parent=0); @@ -157,6 +158,8 @@ public: bool preventStealing() const; void setPreventStealing(bool prevent); + QDeclarativeListProperty<QGraphicsObject> forwardTo(); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h index 67694fb..7248c92 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h @@ -70,6 +70,8 @@ public: : absorb(true), hovered(false), pressed(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), drag(0) { + Q_Q(QDeclarativeMouseArea); + forwardTo = QDeclarativeListProperty<QGraphicsObject>(q, forwardToList); } ~QDeclarativeMouseAreaPrivate(); @@ -89,6 +91,18 @@ public: lastModifiers = event->modifiers(); } + void forwardEvent(QGraphicsSceneMouseEvent* event) + { + Q_Q(QDeclarativeMouseArea); + for(int i=0; i < forwardToList.count(); i++){ + event->setPos(forwardToList[i]->mapFromScene(event->scenePos())); + forwardToList[i]->scene()->sendEvent(forwardToList[i], event); + if(event->isAccepted()) + break; + } + event->setPos(q->mapFromScene(event->scenePos())); + } + bool isPressAndHoldConnected() { Q_Q(QDeclarativeMouseArea); static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QDeclarativeMouseEvent*)"); @@ -121,6 +135,9 @@ public: Qt::MouseButtons lastButtons; Qt::KeyboardModifiers lastModifiers; QBasicTimer pressAndHoldTimer; + + QDeclarativeListProperty<QGraphicsObject> forwardTo; + QList<QGraphicsObject*> forwardToList; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 778b8b9..aed849b 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1525,6 +1525,8 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count) } else { d->regenerate(); d->updateCurrent(); + if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) + d->snapToCurrent(); } if (changedOffset) emit offsetChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativepincharea.cpp b/src/declarative/graphicsitems/qdeclarativepincharea.cpp index 9bc3d8d..c30ff8c 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea.cpp +++ b/src/declarative/graphicsitems/qdeclarativepincharea.cpp @@ -138,6 +138,14 @@ QT_BEGIN_NAMESPACE ignored. */ +/*! + \qmlproperty int PinchEvent::pointCount + + Holds the number of points currently touched. The PinchArea will not react + until two touch points have initited a gesture, but will remain active until + all touch points have been released. +*/ + QDeclarativePinch::QDeclarativePinch() : m_target(0), m_minScale(1.0), m_maxScale(1.0) , m_minRotation(0.0), m_maxRotation(0.0) @@ -295,7 +303,7 @@ bool QDeclarativePinchArea::event(QEvent *event) void QDeclarativePinchArea::updatePinch() { Q_D(QDeclarativePinchArea); - if (d->touchPoints.count() != 2) { + if (d->touchPoints.count() == 0) { if (d->inPinch) { d->stealMouse = false; setKeepMouseGrab(false); @@ -308,127 +316,141 @@ void QDeclarativePinchArea::updatePinch() pe.setPreviousScale(d->pinchLastScale); pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); - pe.setPoint1(d->lastPoint1); - pe.setPoint2(d->lastPoint2); + pe.setPoint1(mapFromScene(d->lastPoint1)); + pe.setPoint2(mapFromScene(d->lastPoint2)); emit pinchFinished(&pe); d->pinchStartDist = 0; + d->pinchActivated = false; if (d->pinch && d->pinch->target()) d->pinch->setActive(false); } return; } - if (d->touchPoints.at(0).state() & Qt::TouchPointPressed - || d->touchPoints.at(1).state() & Qt::TouchPointPressed) { - d->sceneStartPoint1 = d->touchPoints.at(0).scenePos(); - d->sceneStartPoint2 = d->touchPoints.at(1).scenePos(); + QTouchEvent::TouchPoint touchPoint1 = d->touchPoints.at(0); + QTouchEvent::TouchPoint touchPoint2 = d->touchPoints.at(d->touchPoints. count() >= 2 ? 1 : 0); + if (d->touchPoints.count() == 2 + && (touchPoint1.state() & Qt::TouchPointPressed || touchPoint2.state() & Qt::TouchPointPressed)) { + d->id1 = touchPoint1.id(); + d->sceneStartPoint1 = touchPoint1.scenePos(); + d->sceneStartPoint2 = touchPoint2.scenePos(); d->inPinch = false; d->pinchRejected = false; - } else if (!d->pinchRejected){ - QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0; - if (grabber == this || !grabber || !grabber->keepMouseGrab()) { - const int dragThreshold = QApplication::startDragDistance(); - QPointF p1 = d->touchPoints.at(0).scenePos(); - QPointF p2 = d->touchPoints.at(1).scenePos(); - qreal dx = p1.x() - p2.x(); - qreal dy = p1.y() - p2.y(); - qreal dist = sqrt(dx*dx + dy*dy); - QPointF sceneCenter = (p1 + p2)/2; - qreal angle = QLineF(p1, p2).angle(); - if (angle > 180) - angle -= 360; - if (!d->inPinch) { - if (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold - || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold - || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold - || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold) { - d->sceneStartCenter = sceneCenter; - d->sceneLastCenter = sceneCenter; - d->pinchStartCenter = mapFromScene(sceneCenter); - d->pinchStartDist = dist; - d->pinchStartAngle = angle; - d->pinchLastScale = 1.0; - d->pinchLastAngle = angle; - d->pinchRotation = 0.0; - d->lastPoint1 = d->touchPoints.at(0).pos(); - d->lastPoint2 = d->touchPoints.at(1).pos(); - QDeclarativePinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0); - pe.setStartCenter(d->pinchStartCenter); - pe.setPreviousCenter(d->pinchStartCenter); - pe.setPreviousAngle(d->pinchLastAngle); - pe.setPreviousScale(d->pinchLastScale); - pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); - pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); - pe.setPoint1(d->lastPoint1); - pe.setPoint2(d->lastPoint2); - emit pinchStarted(&pe); - if (pe.accepted()) { - d->inPinch = true; - d->stealMouse = true; - QGraphicsScene *s = scene(); - if (s && s->mouseGrabberItem() != this) - grabMouse(); - setKeepMouseGrab(true); - if (d->pinch && d->pinch->target()) { - d->pinchStartPos = pinch()->target()->pos(); - d->pinchStartScale = d->pinch->target()->scale(); - d->pinchStartRotation = d->pinch->target()->rotation(); - d->pinch->setActive(true); - } - } else { - d->pinchRejected = true; - } - } - } else if (d->pinchStartDist > 0) { - qreal scale = dist / d->pinchStartDist; - qreal da = d->pinchLastAngle - angle; - if (da > 180) - da -= 360; - else if (da < -180) - da += 360; - d->pinchRotation += da; - QPointF pinchCenter = mapFromScene(sceneCenter); - QDeclarativePinchEvent pe(pinchCenter, scale, angle, d->pinchRotation); + d->pinchActivated = true; + } else if (d->pinchActivated && !d->pinchRejected) { + const int dragThreshold = QApplication::startDragDistance(); + QPointF p1 = touchPoint1.scenePos(); + QPointF p2 = touchPoint2.scenePos(); + qreal dx = p1.x() - p2.x(); + qreal dy = p1.y() - p2.y(); + qreal dist = sqrt(dx*dx + dy*dy); + QPointF sceneCenter = (p1 + p2)/2; + qreal angle = QLineF(p1, p2).angle(); + if (d->touchPoints.count() == 1) { + // If we only have one point then just move the center + if (d->id1 == touchPoint1.id()) + sceneCenter = d->sceneLastCenter + touchPoint1.scenePos() - d->lastPoint1; + else + sceneCenter = d->sceneLastCenter + touchPoint2.scenePos() - d->lastPoint2; + angle = d->pinchLastAngle; + } + d->id1 = touchPoint1.id(); + if (angle > 180) + angle -= 360; + if (!d->inPinch) { + if (d->touchPoints.count() >= 2 + && (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold + || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold + || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold + || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold)) { + d->sceneStartCenter = sceneCenter; + d->sceneLastCenter = sceneCenter; + d->pinchStartCenter = mapFromScene(sceneCenter); + d->pinchStartDist = dist; + d->pinchStartAngle = angle; + d->pinchLastScale = 1.0; + d->pinchLastAngle = angle; + d->pinchRotation = 0.0; + d->lastPoint1 = p1; + d->lastPoint2 = p2; + QDeclarativePinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0); pe.setStartCenter(d->pinchStartCenter); - pe.setPreviousCenter(mapFromScene(d->sceneLastCenter)); + pe.setPreviousCenter(d->pinchStartCenter); pe.setPreviousAngle(d->pinchLastAngle); pe.setPreviousScale(d->pinchLastScale); pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); - pe.setPoint1(d->touchPoints.at(0).pos()); - pe.setPoint2(d->touchPoints.at(1).pos()); - d->pinchLastScale = scale; - d->sceneLastCenter = sceneCenter; - d->pinchLastAngle = angle; - d->lastPoint1 = d->touchPoints.at(0).pos(); - d->lastPoint2 = d->touchPoints.at(1).pos(); - emit pinchUpdated(&pe); - if (d->pinch && d->pinch->target()) { - qreal s = d->pinchStartScale * scale; - s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale()); - pinch()->target()->setScale(s); - QPointF pos = sceneCenter - d->sceneStartCenter + d->pinchStartPos; - if (pinch()->axis() & QDeclarativePinch::XAxis) { - qreal x = pos.x(); - if (x < pinch()->xmin()) - x = pinch()->xmin(); - else if (x > pinch()->xmax()) - x = pinch()->xmax(); - pinch()->target()->setX(x); - } - if (pinch()->axis() & QDeclarativePinch::YAxis) { - qreal y = pos.y(); - if (y < pinch()->ymin()) - y = pinch()->ymin(); - else if (y > pinch()->ymax()) - y = pinch()->ymax(); - pinch()->target()->setY(y); - } - if (d->pinchStartRotation >= pinch()->minimumRotation() - && d->pinchStartRotation <= pinch()->maximumRotation()) { - qreal r = d->pinchRotation + d->pinchStartRotation; - r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation()); - pinch()->target()->setRotation(r); + pe.setPoint1(mapFromScene(d->lastPoint1)); + pe.setPoint2(mapFromScene(d->lastPoint2)); + pe.setPointCount(d->touchPoints.count()); + emit pinchStarted(&pe); + if (pe.accepted()) { + d->inPinch = true; + d->stealMouse = true; + QGraphicsScene *s = scene(); + if (s && s->mouseGrabberItem() != this) + grabMouse(); + setKeepMouseGrab(true); + if (d->pinch && d->pinch->target()) { + d->pinchStartPos = pinch()->target()->pos(); + d->pinchStartScale = d->pinch->target()->scale(); + d->pinchStartRotation = d->pinch->target()->rotation(); + d->pinch->setActive(true); } + } else { + d->pinchRejected = true; + } + } + } else if (d->pinchStartDist > 0) { + qreal scale = dist ? dist / d->pinchStartDist : d->pinchLastScale; + qreal da = d->pinchLastAngle - angle; + if (da > 180) + da -= 360; + else if (da < -180) + da += 360; + d->pinchRotation += da; + QPointF pinchCenter = mapFromScene(sceneCenter); + QDeclarativePinchEvent pe(pinchCenter, scale, angle, d->pinchRotation); + pe.setStartCenter(d->pinchStartCenter); + pe.setPreviousCenter(mapFromScene(d->sceneLastCenter)); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(touchPoint1.pos()); + pe.setPoint2(touchPoint2.pos()); + pe.setPointCount(d->touchPoints.count()); + d->pinchLastScale = scale; + d->sceneLastCenter = sceneCenter; + d->pinchLastAngle = angle; + d->lastPoint1 = touchPoint1.scenePos(); + d->lastPoint2 = touchPoint2.scenePos(); + emit pinchUpdated(&pe); + if (d->pinch && d->pinch->target()) { + qreal s = d->pinchStartScale * scale; + s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale()); + pinch()->target()->setScale(s); + QPointF pos = sceneCenter - d->sceneStartCenter + d->pinchStartPos; + if (pinch()->axis() & QDeclarativePinch::XAxis) { + qreal x = pos.x(); + if (x < pinch()->xmin()) + x = pinch()->xmin(); + else if (x > pinch()->xmax()) + x = pinch()->xmax(); + pinch()->target()->setX(x); + } + if (pinch()->axis() & QDeclarativePinch::YAxis) { + qreal y = pos.y(); + if (y < pinch()->ymin()) + y = pinch()->ymin(); + else if (y > pinch()->ymax()) + y = pinch()->ymax(); + pinch()->target()->setY(y); + } + if (d->pinchStartRotation >= pinch()->minimumRotation() + && d->pinchStartRotation <= pinch()->maximumRotation()) { + qreal r = d->pinchRotation + d->pinchStartRotation; + r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation()); + pinch()->target()->setRotation(r); } } } diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p.h index 6d04708..b5afea9 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea_p.h +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p.h @@ -203,11 +203,13 @@ class Q_AUTOTEST_EXPORT QDeclarativePinchEvent : public QObject Q_PROPERTY(QPointF startPoint1 READ startPoint1) Q_PROPERTY(QPointF point2 READ point2) Q_PROPERTY(QPointF startPoint2 READ startPoint2) + Q_PROPERTY(int pointCount READ pointCount) Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) public: QDeclarativePinchEvent(QPointF c, qreal s, qreal a, qreal r) - : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r), m_accepted(true) {} + : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r) + , m_pointCount(0), m_accepted(true) {} QPointF center() const { return m_center; } QPointF startCenter() const { return m_startCenter; } @@ -229,6 +231,8 @@ public: void setPoint2(QPointF p) { m_point2 = p; } QPointF startPoint2() const { return m_startPoint2; } void setStartPoint2(QPointF p) { m_startPoint2 = p; } + int pointCount() const { return m_pointCount; } + void setPointCount(int count) { m_pointCount = count; } bool accepted() const { return m_accepted; } void setAccepted(bool a) { m_accepted = a; } @@ -246,6 +250,7 @@ private: QPointF m_point2; QPointF m_startPoint1; QPointF m_startPoint2; + int m_pointCount; bool m_accepted; }; diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h index cd5cf2a..3264948 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h @@ -68,7 +68,8 @@ class QDeclarativePinchAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativePinchAreaPrivate() : absorb(true), stealMouse(false), inPinch(false) - , pinchRejected(false), pinch(0), pinchStartDist(0), pinchStartScale(1.0) + , pinchRejected(false), pinchActivated(false) + , pinch(0), pinchStartDist(0), pinchStartScale(1.0) , pinchLastScale(1.0), pinchStartRotation(0.0), pinchStartAngle(0.0) , pinchLastAngle(0.0), pinchRotation(0.0) { @@ -88,6 +89,7 @@ public: bool stealMouse : 1; bool inPinch : 1; bool pinchRejected : 1; + bool pinchActivated : 1; QDeclarativePinch *pinch; QPointF sceneStartPoint1; QPointF sceneStartPoint2; @@ -105,6 +107,7 @@ public: QPointF sceneLastCenter; QPointF pinchStartPos; QList<QTouchEvent::TouchPoint> touchPoints; + int id1; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 8a9bdb3..e76fc03 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -609,6 +609,11 @@ void QDeclarativeRow::setLayoutDirection(Qt::LayoutDirection layoutDirection) QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate* >(QDeclarativeBasePositionerPrivate::get(this)); if (d->layoutDirection != layoutDirection) { d->layoutDirection = layoutDirection; + // For RTL layout the positioning changes when the width changes. + if (d->layoutDirection == Qt::RightToLeft) + d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry); + else + d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry); prePositioning(); emit layoutDirectionChanged(); emit effectiveLayoutDirectionChanged(); @@ -907,6 +912,11 @@ void QDeclarativeGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection) QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this)); if (d->layoutDirection != layoutDirection) { d->layoutDirection = layoutDirection; + // For RTL layout the positioning changes when the width changes. + if (d->layoutDirection == Qt::RightToLeft) + d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry); + else + d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry); prePositioning(); emit layoutDirectionChanged(); emit effectiveLayoutDirectionChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 720692c..1d51840 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -101,7 +101,8 @@ QDeclarativeTextPrivate::QDeclarativeTextPrivate() format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1), lineHeightMode(QDeclarativeText::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX), maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), - cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true), rightToLeftText(false), naturalWidth(0), doc(0) + cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true), + rightToLeftText(false), layoutTextElided(false), naturalWidth(0), doc(0) { cacheAllTextAsImage = enableImageCache(); QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton; @@ -217,6 +218,7 @@ void QDeclarativeTextPrivate::updateLayout() return; } + layoutTextElided = false; // Setup instance of QTextLayout for all cases other than richtext if (!richText) { layout.clearLayout(); @@ -227,10 +229,13 @@ void QDeclarativeTextPrivate::updateLayout() singleline = !tmp.contains(QChar::LineSeparator); if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { QFontMetrics fm(font); - tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...? - if (tmp != text && !truncated) { - truncated = true; - emit q->truncatedChanged(); + tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); + if (tmp != text) { + layoutTextElided = true; + if (!truncated) { + truncated = true; + emit q->truncatedChanged(); + } } } layout.setText(tmp); @@ -377,6 +382,12 @@ QRect QDeclarativeTextPrivate::setupTextLayout() if (requireImplicitWidth && q->widthValid()) { // requires an extra layout + QString elidedText; + if (layoutTextElided) { + // We have provided elided text to the layout, but we must calculate unelided width. + elidedText = layout.text(); + layout.setText(text); + } layout.beginLayout(); forever { QTextLine line = layout.createLine(); @@ -390,6 +401,8 @@ QRect QDeclarativeTextPrivate::setupTextLayout() br = br.united(line.naturalTextRect()); } naturalWidth = br.width(); + if (layoutTextElided) + layout.setText(elidedText); } if (maximumLineCountValid) { diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index e3ab62a..6a3d581 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -116,6 +116,7 @@ public: bool requireImplicitWidth:1; bool hAlignImplicit:1; bool rightToLeftText:1; + bool layoutTextElided:1; QRect layedOutTextRect; QSize paintedSize; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 2cb1c94..af2c8f3 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -582,6 +582,7 @@ void QDeclarativeTextEdit::setVAlign(QDeclarativeTextEdit::VAlignment alignment) d->vAlign = alignment; d->updateDefaultTextOption(); updateSize(); + moveCursorDelegate(); emit verticalAlignmentChanged(d->vAlign); } @@ -870,8 +871,6 @@ void QDeclarativeTextEdit::setCursorDelegate(QDeclarativeComponent* c) Q_D(QDeclarativeTextEdit); if(d->cursorComponent){ if(d->cursor){ - disconnect(d->control, SIGNAL(cursorPositionChanged()), - this, SLOT(moveCursorDelegate())); d->control->setCursorWidth(-1); dirtyCache(cursorRectangle()); delete d->cursor; @@ -897,8 +896,6 @@ void QDeclarativeTextEdit::loadCursorDelegate() return; d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this))); if(d->cursor){ - connect(d->control, SIGNAL(cursorPositionChanged()), - this, SLOT(moveCursorDelegate())); d->control->setCursorWidth(0); dirtyCache(cursorRectangle()); QDeclarative_setParent_noEvent(d->cursor, this); @@ -1173,7 +1170,7 @@ Qt::TextInteractionFlags QDeclarativeTextEdit::textInteractionFlags() const QRect QDeclarativeTextEdit::cursorRectangle() const { Q_D(const QDeclarativeTextEdit); - return d->control->cursorRect().toRect().translated(0,-d->yoff); + return d->control->cursorRect().toRect().translated(0,d->yoff); } @@ -1558,7 +1555,7 @@ void QDeclarativeTextEditPrivate::init() QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); - QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged())); + QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate())); QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); #ifndef QT_NO_CLIPBOARD QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged())); @@ -1583,16 +1580,17 @@ void QDeclarativeTextEdit::q_textChanged() d->updateDefaultTextOption(); updateSize(); updateTotalLines(); - updateMicroFocus(); emit textChanged(d->text); } void QDeclarativeTextEdit::moveCursorDelegate() { Q_D(QDeclarativeTextEdit); + updateMicroFocus(); + emit cursorRectangleChanged(); if(!d->cursor) return; - QRectF cursorRect = d->control->cursorRect(); + QRectF cursorRect = cursorRectangle(); d->cursor->setX(cursorRect.x()); d->cursor->setY(cursorRect.y()); } @@ -1625,7 +1623,6 @@ void QDeclarativeTextEdit::updateSelectionMarkers() d->lastSelectionEnd = d->control->textCursor().selectionEnd(); emit selectionEndChanged(); } - updateMicroFocus(); } QRectF QDeclarativeTextEdit::boundingRect() const diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index af18c90..9a91769 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -555,8 +555,10 @@ QRect QDeclarativeTextInput::cursorRectangle() const { Q_D(const QDeclarativeTextInput); QRect r = d->control->cursorRect(); - r.setHeight(r.height()-1); // Make consistent with TextEdit (QLineControl inexplicably adds 1) - r.moveLeft(r.x() - d->hscroll); + // Scroll and make consistent with TextEdit + // QLineControl inexplicably adds 1 to the height and horizontal padding + // for unicode direction markers. + r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1); return r; } @@ -860,6 +862,20 @@ bool QDeclarativeTextInput::hasAcceptableInput() const state. */ +void QDeclarativeTextInputPrivate::updateInputMethodHints() +{ + Q_Q(QDeclarativeTextInput); + Qt::InputMethodHints hints = inputMethodHints; + uint echo = control->echoMode(); + if (echo == QDeclarativeTextInput::Password || echo == QDeclarativeTextInput::NoEcho) + hints |= Qt::ImhHiddenText; + else if (echo == QDeclarativeTextInput::PasswordEchoOnEdit) + hints &= ~Qt::ImhHiddenText; + if (echo != QDeclarativeTextInput::Normal) + hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + q->setInputMethodHints(hints); +} + /*! \qmlproperty enumeration TextInput::echoMode @@ -882,21 +898,27 @@ void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo) Q_D(QDeclarativeTextInput); if (echoMode() == echo) return; - Qt::InputMethodHints imHints = inputMethodHints(); - if (echo == Password || echo == NoEcho) - imHints |= Qt::ImhHiddenText; - else - imHints &= ~Qt::ImhHiddenText; - if (echo != Normal) - imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); - else - imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); - setInputMethodHints(imHints); d->control->setEchoMode((uint)echo); + d->updateInputMethodHints(); q_textChanged(); emit echoModeChanged(echoMode()); } +Qt::InputMethodHints QDeclarativeTextInput::imHints() const +{ + Q_D(const QDeclarativeTextInput); + return d->inputMethodHints; +} + +void QDeclarativeTextInput::setIMHints(Qt::InputMethodHints hints) +{ + Q_D(QDeclarativeTextInput); + if (d->inputMethodHints == hints) + return; + d->inputMethodHints = hints; + d->updateInputMethodHints(); +} + /*! \qmlproperty Component TextInput::cursorDelegate The delegate for the cursor in the TextInput. @@ -927,6 +949,8 @@ void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c) //note that the components are owned by something else disconnect(d->control, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(moveCursor())); + disconnect(d->control, SIGNAL(updateMicroFocus()), + this, SLOT(moveCursor())); delete d->cursorItem; }else{ d->startCreatingCursor(); @@ -939,7 +963,9 @@ void QDeclarativeTextInputPrivate::startCreatingCursor() { Q_Q(QDeclarativeTextInput); q->connect(control, SIGNAL(cursorPositionChanged(int,int)), - q, SLOT(moveCursor())); + q, SLOT(moveCursor()), Qt::UniqueConnection); + q->connect(control, SIGNAL(updateMicroFocus()), + q, SLOT(moveCursor()), Qt::UniqueConnection); if(cursorComponent->isReady()){ q->createCursor(); }else if(cursorComponent->isLoading()){ @@ -1142,9 +1168,10 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) } if (d->selectByMouse) { setKeepMouseGrab(false); + d->selectPressed = true; d->pressPos = event->pos(); } - bool mark = event->modifiers() & Qt::ShiftModifier; + bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse; int cursor = d->xToPos(event->pos().x()); d->control->moveCursor(cursor, mark); event->setAccepted(true); @@ -1155,7 +1182,7 @@ void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_D(QDeclarativeTextInput); if (d->sendMouseEventToInputContext(event, QEvent::MouseMove)) return; - if (d->selectByMouse) { + if (d->selectPressed) { if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance()) setKeepMouseGrab(true); moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode); @@ -1174,8 +1201,10 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_D(QDeclarativeTextInput); if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease)) return; - if (d->selectByMouse) + if (d->selectPressed) { + d->selectPressed = false; setKeepMouseGrab(false); + } if (!d->showInputPanelOnFocus) { // input panel on click if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) { if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { @@ -1231,8 +1260,10 @@ bool QDeclarativeTextInputPrivate::sendMouseEventToInputContext( bool QDeclarativeTextInput::sceneEvent(QEvent *event) { + Q_D(QDeclarativeTextInput); bool rv = QDeclarativeItem::sceneEvent(event); if (event->type() == QEvent::UngrabMouse) { + d->selectPressed = false; setKeepMouseGrab(false); } return rv; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 8c873b3..ec70e43 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -86,7 +86,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizeP Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged) #endif Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged) - Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) + Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ imHints WRITE setIMHints) Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged) Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged) @@ -215,6 +215,9 @@ public: bool isInputMethodComposing() const; + Qt::InputMethodHints imHints() const; + void setIMHints(Qt::InputMethodHints hints); + Q_SIGNALS: void textChanged(); void cursorPositionChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index fd4da2e..f6f6bd8 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -73,10 +73,11 @@ public: QDeclarativeTextInputPrivate() : control(new QLineControl(QString())), color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), - mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), + mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), inputMethodHints(Qt::ImhNone), hscroll(0), oldScroll(0), oldValidity(false), focused(false), focusOnPress(true), showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false), - autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true) + autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true), + selectPressed(false) { #ifdef Q_OS_SYMBIAN if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) { @@ -108,6 +109,7 @@ public: void mirrorChange(); int calculateTextWidth(); bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType); + void updateInputMethodHints(); QLineControl* control; @@ -120,6 +122,7 @@ public: QColor styleColor; QDeclarativeTextInput::HAlignment hAlign; QDeclarativeTextInput::SelectionMode mouseSelectionMode; + Qt::InputMethodHints inputMethodHints; QPointer<QDeclarativeComponent> cursorComponent; QPointer<QDeclarativeItem> cursorItem; QPointF pressPos; @@ -140,6 +143,7 @@ public: bool selectByMouse:1; bool canPaste:1; bool hAlignImplicit:1; + bool selectPressed:1; static inline QDeclarativeTextInputPrivate *get(QDeclarativeTextInput *t) { return t->d_func(); diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp index 31819f5..75d9f67 100644 --- a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp @@ -299,7 +299,7 @@ void QDeclarativeTextLayout::clearLayout() QTextLayout::clearLayout(); } -void QDeclarativeTextLayout::prepare() +void QDeclarativeTextLayout::prepare(QPainter *painter) { if (!d || !d->cached) { @@ -308,6 +308,7 @@ void QDeclarativeTextLayout::prepare() InertTextPainter *itp = inertTextPainter(); itp->device.begin(d); + itp->painter.setPen(painter->pen()); QTextLayout::draw(&itp->painter, QPointF(0, 0)); glyph_t *glyphPool = d->glyphs.data(); @@ -326,6 +327,12 @@ void QDeclarativeTextLayout::prepare() } } +// Defined in qpainter.cpp +extern Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat); + void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p) { QPainterPrivate *priv = QPainterPrivate::get(painter); @@ -340,7 +347,7 @@ void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p) return; } - prepare(); + prepare(painter); int itemCount = d->items.count(); @@ -371,6 +378,10 @@ void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p) currentColor = item.color; } priv->extended->drawStaticTextItem(&item); + + qt_draw_decoration_for_glyphs(painter, item.glyphs, item.glyphPositions, + item.numGlyphs, item.fontEngine(), painter->font(), + QTextCharFormat()); } if (currentColor != oldPen.color()) painter->setPen(oldPen); diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout_p.h b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h index 2c9264e..23b22a6 100644 --- a/src/declarative/graphicsitems/qdeclarativetextlayout_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h @@ -61,7 +61,7 @@ public: void beginLayout(); void clearLayout(); - void prepare(); + void prepare(QPainter *); void draw(QPainter *, const QPointF & = QPointF()); private: diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 97ce059..4c839a1 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -1398,7 +1398,12 @@ void QDeclarativeVisualDataModel::_q_layoutChanged() void QDeclarativeVisualDataModel::_q_modelReset() { + Q_D(QDeclarativeVisualDataModel); + d->m_root = QModelIndex(); emit modelReset(); + emit rootIndexChanged(); + if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root)) + d->m_abstractItemModel->fetchMore(d->m_root); } void QDeclarativeVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package) diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 28dfea9..47a15cb 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -225,9 +225,35 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*"); prop.setWritable(false); } else { + QByteArray propType = type; + if (t >= QVariant::UserType || t == QVariant::Invalid) { + //copy of QDeclarativeObjectScriptClass::enumType() + QByteArray scope; + QByteArray name; + int scopeIdx = propType.lastIndexOf("::"); + if (scopeIdx != -1) { + scope = propType.left(scopeIdx); + name = propType.mid(scopeIdx + 2); + } else { + name = propType; + } + const QMetaObject *meta; + if (scope == "Qt") + meta = &QObject::staticQtMetaObject; + else + meta = parent->parent()->metaObject(); //### assumes parent->parent() + for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = meta->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) { + t = QVariant::Int; + propType = "int"; + break; + } + } + } if (QDeclarativeMetaType::canCopy(t)) { types[ii] = t; - QMetaPropertyBuilder prop = mob.addProperty(name, type); + QMetaPropertyBuilder prop = mob.addProperty(name, propType); prop.setWritable(false); } else { types[ii] = 0x80000000 | t; diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index c284307..8238252 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -643,11 +643,11 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q The \a properties argument is specified as a map of property-value items. For example, the code below creates an object with initial \c x and \c y values of 100 and 200, respectively: - \qml + \js var component = Qt.createComponent("Button.qml"); if (component.status == Component.Ready) component.createObject(parent, {"x": 100, "y": 100}); - \endqml + \endjs Dynamically created instances can be deleted with the \c destroy() method. See \l {Dynamic Object Management in QML} for more information. @@ -880,6 +880,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; + state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -887,6 +888,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); + enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -917,6 +919,7 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; + state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -924,6 +927,7 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); + enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -961,6 +965,18 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri QDeclarativeEnginePrivate::clear(ps); } + for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) { + QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii); + QObject *obj = status.first; + if (obj) { + void *args[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, + status.second, args); + } + } + + //componentComplete() can register additional finalization objects + //that are then never handled. Handle them manually here. if (1 == enginePriv->inProgressCreations) { for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) { QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii); @@ -986,6 +1002,7 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri state->bindValues.clear(); state->parserStatus.clear(); + state->finalizedParserStatus.clear(); state->completePending = false; enginePriv->inProgressCreations--; diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 020c5e0..f8bec2b 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -101,6 +101,7 @@ public: ConstructionState() : componentAttached(0), completePending(false) {} QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> > bindValues; QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> > parserStatus; + QList<QPair<QDeclarativeGuard<QObject>, int> > finalizedParserStatus; QDeclarativeComponentAttached *componentAttached; QList<QDeclarativeError> errors; bool completePending; diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index bb4ece4..3abd787 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -227,6 +227,7 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindConte if (data) { lastData = data; lastContext = bindContext; + lastScopeObject = scopeObject; return QScriptClass::HandlesReadAccess; } } @@ -268,17 +269,12 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name) QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); - if (lastScopeObject) { - - return ep->objectClass->property(lastScopeObject, name); - - } else if (lastData) { + if (lastData) { if (lastData->type) { - return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->type)); + return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->type)); } else if (lastData->typeNamespace) { - return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, - lastData->typeNamespace)); + return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->typeNamespace)); } else { int index = lastData->importedScriptIndex; if (index < bindContext->importedScripts.count()) { @@ -288,6 +284,10 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name) } } + } else if (lastScopeObject) { + + return ep->objectClass->property(lastScopeObject, name); + } else if (lastPropertyIndex != -1) { QScriptValue rv; diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 31fd516..b2a05c3 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -249,10 +249,16 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, return; } - message << (object->metaObject()->propertyCount() + fakeProperties.count()); + QList<int> propertyIndexes; + for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) { + if (object->metaObject()->property(ii).isScriptable()) + propertyIndexes << ii; + } + + message << propertyIndexes.size() + fakeProperties.count(); - for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) - message << propertyData(object, ii); + for (int ii = 0; ii < propertyIndexes.size(); ++ii) + message << propertyData(object, propertyIndexes.at(ii)); for (int ii = 0; ii < fakeProperties.count(); ++ii) message << fakeProperties[ii]; diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index 6938892..7f487a0 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -79,7 +79,7 @@ public: Loading, // Prior to data being received and dataReceived() being called WaitingForDependencies, // While there are outstanding addDependency()s Complete, // Finished - Error, // Error + Error // Error }; enum Type { diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp index 41f8fe5..a1321e2 100644 --- a/src/declarative/util/qdeclarativebehavior.cpp +++ b/src/declarative/util/qdeclarativebehavior.cpp @@ -72,7 +72,7 @@ public: /*! \qmlclass Behavior QDeclarativeBehavior - \ingroup qml-animation-transition + \ingroup qml-animation-transition \since 4.7 \brief The Behavior element allows you to specify a default animation for a property change. @@ -91,7 +91,8 @@ public: If a \l{QML States}{state change} has a \l Transition that matches the same property as a Behavior, the \l Transition animation overrides the Behavior for that - state change. + state change. For general advice on using Behaviors to animate state changes, see + \l{Using QML Behaviors with States}. \sa {QML Animation and Transitions}, {declarative/animation/behaviors}{Behavior example}, QtDeclarative */ diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index b2739f0..258bc81 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -1301,9 +1301,6 @@ int NestedListModel::count() const void NestedListModel::clear() { - _rolesOk = false; - roleStrings.clear(); - if (_root) _root->clear(); } diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index 099eae9..a29854f 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -424,7 +424,8 @@ void QDeclarativePixmapReader::processJobs() replies.remove(reply); reply->close(); } - delete job; + // deleteLater, since not owned by this thread + job->deleteLater(); } cancelled.clear(); } diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 5af53e6..a61ac06 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -144,6 +144,7 @@ struct XmlQueryJob QList<void*> roleQueryErrorId; // the ptr to send back if there is an error QStringList keyRoleQueries; QStringList keyRoleResultsCache; + QString prefix; }; class QDeclarativeXmlQuery : public QObject @@ -172,6 +173,12 @@ public: } int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) { + { + QMutexLocker m1(&m_mutex); + m_queryIds.ref(); + if (m_queryIds <= 0) + m_queryIds = 1; + } XmlQueryJob job; job.queryId = m_queryIds; @@ -194,9 +201,6 @@ public: { QMutexLocker ml(&m_mutex); m_jobs.insert(m_queryIds, job); - m_queryIds++; - if (m_queryIds <= 0) - m_queryIds = 1; } QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId)); @@ -214,20 +218,15 @@ private slots: job = m_jobs.value(queryId); } - QDeclarativeXmlQueryResult r; - doQueryJob(&job); - doSubQueryJob(&job); - r.queryId = job.queryId; - r.size = m_size; - r.data = m_modelData; - r.inserted = m_insertedItemRanges; - r.removed = m_removedItemRanges; - r.keyRoleResultsCache = job.keyRoleResultsCache; + QDeclarativeXmlQueryResult result; + result.queryId = job.queryId; + doQueryJob(&job, &result); + doSubQueryJob(&job, &result); { QMutexLocker ml(&m_mutex); if (m_jobs.contains(queryId)) { - emit queryCompleted(r); + emit queryCompleted(result); m_jobs.remove(queryId); } } @@ -241,8 +240,8 @@ protected: private: - void doQueryJob(XmlQueryJob* job); - void doSubQueryJob(XmlQueryJob* job); + void doQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); + void doSubQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const; void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const; @@ -250,17 +249,12 @@ private: QMutex m_mutex; QThread m_thread; QMap<int, XmlQueryJob> m_jobs; - int m_queryIds; - QString m_prefix; - int m_size; - QList<QList<QVariant> > m_modelData; - QList<QDeclarativeXmlListRange> m_insertedItemRanges; - QList<QDeclarativeXmlListRange> m_removedItemRanges; + QAtomicInt m_queryIds; }; Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery) -void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob) +void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) { Q_ASSERT(currentJob->queryId != -1); @@ -295,10 +289,8 @@ void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob) } currentJob->data = xml; - m_prefix = namespaces + prefix + QLatin1Char('/'); - m_size = 0; - if (count > 0) - m_size = count; + currentJob->prefix = namespaces + prefix + QLatin1Char('/'); + currentResult->size = (count > 0 ? count : 0); } void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const @@ -306,9 +298,9 @@ void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QS const QStringList &keysQueries = currentJob.keyRoleQueries; QString keysQuery; if (keysQueries.count() == 1) - keysQuery = m_prefix + keysQueries[0]; + keysQuery = currentJob.prefix + keysQueries[0]; else if (keysQueries.count() > 1) - keysQuery = m_prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")"); + keysQuery = currentJob.prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")"); if (!keysQuery.isEmpty()) { query->setQuery(keysQuery); @@ -331,10 +323,9 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> * ranges->append(qMakePair(index, 1)); } -void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) +void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) { Q_ASSERT(currentJob->queryId != -1); - m_modelData.clear(); QBuffer b(¤tJob->data); b.open(QIODevice::ReadOnly); @@ -347,16 +338,14 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) // See if any values of key roles have been inserted or removed. - m_insertedItemRanges.clear(); - m_removedItemRanges.clear(); if (currentJob->keyRoleResultsCache.isEmpty()) { - m_insertedItemRanges << qMakePair(0, m_size); + currentResult->inserted << qMakePair(0, currentResult->size); } else { if (keyRoleResults != currentJob->keyRoleResultsCache) { QStringList temp; for (int i=0; i<currentJob->keyRoleResultsCache.count(); i++) { if (!keyRoleResults.contains(currentJob->keyRoleResultsCache[i])) - addIndexToRangeList(&m_removedItemRanges, i); + addIndexToRangeList(¤tResult->removed, i); else temp << currentJob->keyRoleResultsCache[i]; } @@ -364,12 +353,12 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) for (int i=0; i<keyRoleResults.count(); i++) { if (temp.count() == i || keyRoleResults[i] != temp[i]) { temp.insert(i, keyRoleResults[i]); - addIndexToRangeList(&m_insertedItemRanges, i); + addIndexToRangeList(¤tResult->inserted, i); } } } } - currentJob->keyRoleResultsCache = keyRoleResults; + currentResult->keyRoleResultsCache = keyRoleResults; // Get the new values for each role. //### we might be able to condense even further (query for everything in one go) @@ -377,7 +366,7 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) for (int i = 0; i < queries.size(); ++i) { QList<QVariant> resultList; if (!queries[i].isEmpty()) { - subquery.setQuery(m_prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); + subquery.setQuery(currentJob->prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); if (subquery.isValid()) { QXmlResultItems resultItems; subquery.evaluateTo(&resultItems); @@ -391,9 +380,9 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) } } //### should warn here if things have gone wrong. - while (resultList.count() < m_size) + while (resultList.count() < currentResult->size) resultList << QVariant(); - m_modelData << resultList; + currentResult->data << resultList; b.seek(0); } @@ -919,7 +908,7 @@ void QDeclarativeXmlListModel::reload() } else { d->notifyQueryStarted(true); QNetworkRequest req(d->src); - req.setRawHeader("Accept", "application/xml"); + req.setRawHeader("Accept", "application/xml,*/*"); d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req); QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), diff --git a/src/gui/embedded/qvfbhdr.h b/src/gui/embedded/qvfbhdr.h index 31704b3..84f82ac 100644 --- a/src/gui/embedded/qvfbhdr.h +++ b/src/gui/embedded/qvfbhdr.h @@ -53,36 +53,37 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) #ifndef QT_QWS_TEMP_DIR -#define QT_QWS_TEMP_DIR "/tmp" +# define QT_QWS_TEMP_DIR QLatin1String("/tmp") #endif #ifdef QT_PRIVATE_QWS -#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2-%3") \ - .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY) - +#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2-%3") \ + .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY) #define QT_VFB_MOUSE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_mouse") + .append(QLatin1String("/qtvfb_mouse")) #define QT_VFB_KEYBOARD_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_keyboard") + .append(QLatin1String("/qtvfb_keyboard")) #define QT_VFB_MAP(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qtvfb_map") + .append(QLatin1String("/qtvfb_map")) #define QT_VFB_SOUND_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/qt_soundserver") + .append(QLatin1String("/qt_soundserver")) #define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/QtEmbedded") + .append(QLatin1String("/QtEmbedded")) #define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY) #else -#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2") \ - .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) -#define QT_VFB_MOUSE_PIPE(DISPLAY) QString("/tmp/.qtvfb_mouse-%1").arg(DISPLAY) -#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString("/tmp/.qtvfb_keyboard-%1").arg(DISPLAY) -#define QT_VFB_MAP(DISPLAY) QString("/tmp/.qtvfb_map-%1").arg(DISPLAY) -#define QT_VFB_SOUND_PIPE(DISPLAY) QString("/tmp/.qt_soundserver-%1").arg(DISPLAY) -#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ - .append("/QtEmbedded-%1") \ - .arg(DISPLAY) -#define QTE_PIPE_QVFB(DISPLAY) QString("/tmp/qtembedded-%1/QtEmbedded-%1") \ - .arg(DISPLAY) +#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_MOUSE_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_mouse-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_keyboard-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_MAP(DISPLAY) QString::fromLatin1("%1/.qtvfb_map-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QT_VFB_SOUND_PIPE(DISPLAY) QString::fromLatin1("%1/.qt_soundserver-%2") \ + .arg(QT_QWS_TEMP_DIR).arg(DISPLAY) +#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append(QLatin1String("/QtEmbedded-%1")).arg(DISPLAY) +#define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY) #endif struct QVFbHeader diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a36a276..d51fdfe 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -421,7 +421,7 @@ \omitvalue ItemStopsFocusHandling \omit Same as ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag allows you to completely take over focus handling. - This flag was introduced in Qt 4.7. + This flag was introduced in Qt 4.7. \endomit */ /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 85a4e16..c0a4bf9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5983,9 +5983,6 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; - if (item && (item->d_ptr->flags - & (QGraphicsItem::ItemStopsClickFocusPropagation | QGraphicsItem::ItemStopsFocusHandling))) - break; } touchEvent->setAccepted(eventAccepted); diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index 06df788..513c41f 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -92,6 +92,7 @@ #include "qgraphicstransform_p.h" #include <QDebug> #include <QtCore/qmath.h> +#include <QtCore/qnumeric.h> #ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE @@ -467,6 +468,7 @@ void QGraphicsRotation::setOrigin(const QVector3D &point) item will be rotated counter-clockwise. Normally the rotation angle will be in the range (-360, 360), but you can also provide numbers outside of this range (e.g., a angle of 370 degrees gives the same result as 10 degrees). + Setting the angle to NaN results in no rotation. \sa origin */ @@ -570,7 +572,7 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const { Q_D(const QGraphicsRotation); - if (d->angle == 0. || d->axis.isNull()) + if (d->angle == 0. || d->axis.isNull() || qIsNaN(d->angle)) return; matrix->translate(d->origin); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2b129d7..16268a8 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2498,7 +2498,7 @@ QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query) const else if (value.type() == QVariant::PointF) value = mapFromScene(value.toPointF()); else if (value.type() == QVariant::Rect) - value = mapFromScene(value.toRect()).boundingRect(); + value = d->mapRectFromScene(value.toRect()).toRect(); else if (value.type() == QVariant::Point) value = mapFromScene(value.toPoint()); return value; diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 1fa1058..e7b1000 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1482,6 +1482,9 @@ QByteArray QImageReader::imageFormat(QIODevice *device) configure script or check the appropriate option in the graphical installer. + Note that the QApplication instance must be created before this function is + called. + \sa setFormat(), QImageWriter::supportedImageFormats(), QImageIOPlugin */ QList<QByteArray> QImageReader::supportedImageFormats() diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index 8a65ac0..504260a 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -679,6 +679,9 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const Reading and writing SVG files is supported through Qt's \l{QtSvg Module}{SVG Module}. + Note that the QApplication instance must be created before this function is + called. + \sa setFormat(), QImageReader::supportedImageFormats(), QImageIOPlugin */ QList<QByteArray> QImageWriter::supportedImageFormats() diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 0d1473d..eb54bac 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -263,6 +263,11 @@ QStyledItemDelegate::~QStyledItemDelegate() The default implementation uses the QLocale::toString to convert \a value into a QString. + + This function is not called for empty model indices, i.e., indices for which + the model returns an invalid QVariant. + + \sa QAbstractItemModel::data() */ QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const { diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6e89ceb..913bc7e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3779,16 +3779,32 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::sendSpontaneousEvent(this, &e); hideChildren(true); } - } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) { + } else if (msg.wParam != SIZE_MINIMIZED) { + bool window_state_changed = false; + Qt::WindowStates oldstate = Qt::WindowStates(dataPtr()->window_state); + if (isMinimized()) { #ifndef Q_WS_WINCE - const QString title = windowTitle(); - if (!title.isEmpty()) - d_func()->setWindowTitle_helper(title); + const QString title = windowTitle(); + if (!title.isEmpty()) + d_func()->setWindowTitle_helper(title); #endif - data->window_state &= ~Qt::WindowMinimized; - showChildren(true); - QShowEvent e; - QApplication::sendSpontaneousEvent(this, &e); + data->window_state &= ~Qt::WindowMinimized; + showChildren(true); + QShowEvent e; + QApplication::sendSpontaneousEvent(this, &e); + // Capture SIZE_MAXIMIZED and SIZE_RESTORED without preceding WM_SYSCOMMAND + // (Aero Snap on Win7) + } else if (msg.wParam == SIZE_MAXIMIZED && !isMaximized()) { + data->window_state |= Qt::WindowMaximized; + window_state_changed = true; + } else if (msg.wParam == SIZE_RESTORED && isMaximized()) { + data->window_state &= ~(Qt::WindowMaximized); + window_state_changed = true; + } + if (window_state_changed) { + QWindowStateChangeEvent e(oldstate); + QApplication::sendSpontaneousEvent(this, &e); + } } } if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) { @@ -3820,7 +3836,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::postEvent(this, e); } } -} else if (msg.message == WM_MOVE) { // move event + } else if (msg.message == WM_MOVE) { // move event int a = (int) (short) LOWORD(msg.lParam); int b = (int) (short) HIWORD(msg.lParam); QPoint oldPos = geometry().topLeft(); diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 6254061..406e6d4 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -157,6 +157,20 @@ QT_END_NAMESPACE [NSApp terminate:sender]; } +- (void)setLevel:(NSInteger)windowLevel +{ + // Cocoa will upon activating/deactivating applications level modal + // windows up and down, regardsless of any explicit set window level. + // To ensure that modal stays-on-top dialogs actually stays on top after + // the application is activated (and therefore stacks in front of + // other stays-on-top windows), we need to add this little special-case override: + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + if (widget && widget->isModal() && (widget->windowFlags() & Qt::WindowStaysOnTopHint)) + [super setLevel:NSPopUpMenuWindowLevel]; + else + [super setLevel:windowLevel]; +} + - (void)sendEvent:(NSEvent *)event { if ([event type] == NSApplicationDefined) { diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 0a73481..ac35d42 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -598,8 +598,7 @@ void QWidget::setAutoFillBackground(bool enabled) \brief The QWidget class is the base class of all user interface objects. \ingroup basicwidgets - - + The widget is the atom of the user interface: it receives mouse, keyboard and other events from the window system, and paints a representation of itself on the screen. Every widget is rectangular, and they are sorted in a diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 7e5173f..8784ffd 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2794,6 +2794,11 @@ void QWidgetPrivate::transferChildren() #ifdef QT_MAC_USE_COCOA void QWidgetPrivate::setSubWindowStacking(bool set) { + // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child + // window API, we have decided to revert this behaviour as much as we can. We + // therefore now only allow child windows to exist for children of modal dialogs. + static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty(); + // This will set/remove a visual relationship between parent and child on screen. // The reason for doing this is to ensure that a child always stacks infront of // its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has @@ -2822,7 +2827,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) { if (set) { Qt::WindowType ptype = parent->window()->windowType(); - if ([pwin isVisible] && (ptype == Qt::Window || ptype == Qt::Dialog) && ![qwin parentWindow]) { + if ([pwin isVisible] + && (ptype == Qt::Window || ptype == Qt::Dialog) + && ![qwin parentWindow] + && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) { NSInteger level = [qwin level]; [pwin addChildWindow:qwin ordered:NSWindowAbove]; if ([qwin level] < level) @@ -2834,6 +2842,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) } } + // Only set-up child windows for q if q is modal: + if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal) + return; + QObjectList widgets = q->children(); for (int i=0; i<widgets.size(); ++i) { QWidget *child = qobject_cast<QWidget *>(widgets.at(i)); diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 00b103d..debca37 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -327,10 +327,8 @@ void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl, blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha); - for (int j = 0; j < tail; ++j) { + for (int j = 0; j < tail; ++j) dst[i + j] = dstBuffer[j]; - src[i + j] = srcBuffer[j]; - } } dst = (quint16 *)(((uchar *) dst) + dbpl); diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index c3aac1b..b07053e 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -969,7 +969,7 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co return; bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false; - CGRect rect = CGRectMake(qRound(r.x()), qRound(r.y()), qRound(r.width()), qRound(r.height())); + CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); QCFType<CGImageRef> image; bool isBitmap = (pm.depth() == 1); if (isBitmap) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 76ac7db..3735e7c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -95,10 +95,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const const QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing -static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat); +Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat); static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) { @@ -5937,9 +5937,9 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText } d->extended->drawStaticTextItem(item); - drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions, - item->numGlyphs, item->fontEngine(), staticText_d->font, - QTextCharFormat()); + qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions, + item->numGlyphs, item->fontEngine(), staticText_d->font, + QTextCharFormat()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6383,10 +6383,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setBrush(oldBrush); } -static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat) +Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat) { if (!(font.underline() || font.strikeOut() || font.overline())) return; @@ -8097,12 +8097,16 @@ start_lengthVariant: QTextLine line = textLayout.lineAt(i); qreal advance = line.horizontalAdvance(); - if (tf & Qt::AlignRight) - xoff = r.width() - advance; + xoff = 0; + if (tf & Qt::AlignRight) { + QTextEngine *eng = textLayout.engine(); + xoff = r.width() - advance - + eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal(); + } else if (tf & Qt::AlignHCenter) - xoff = (r.width() - advance)/2; + xoff = (r.width() - advance) / 2; - line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); + line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff)); } if (restore) { diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 0948a64..0bb2901 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1863,39 +1863,39 @@ static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y return false; } -static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2) +static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2, int depth = 0) { QRectF bounds = bezier.bounds(); if (y >= bounds.top() && y < bounds.bottom() && bounds.right() >= x1 && bounds.left() < x2) { const qreal lower_bound = qreal(.01); - if (bounds.width() < lower_bound && bounds.height() < lower_bound) + if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound) return true; QBezier first_half, second_half; bezier.split(&first_half, &second_half); - if (qt_isect_curve_horizontal(first_half, y, x1, x2) - || qt_isect_curve_horizontal(second_half, y, x1, x2)) + if (qt_isect_curve_horizontal(first_half, y, x1, x2, depth + 1) + || qt_isect_curve_horizontal(second_half, y, x1, x2, depth + 1)) return true; } return false; } -static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2) +static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2, int depth = 0) { QRectF bounds = bezier.bounds(); if (x >= bounds.left() && x < bounds.right() && bounds.bottom() >= y1 && bounds.top() < y2) { const qreal lower_bound = qreal(.01); - if (bounds.width() < lower_bound && bounds.height() < lower_bound) + if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound) return true; QBezier first_half, second_half; bezier.split(&first_half, &second_half); - if (qt_isect_curve_vertical(first_half, x, y1, y2) - || qt_isect_curve_vertical(second_half, x, y1, y2)) + if (qt_isect_curve_vertical(first_half, x, y1, y2, depth + 1) + || qt_isect_curve_vertical(second_half, x, y1, y2, depth + 1)) return true; } return false; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 42b9402..05e3d3c 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -144,7 +144,7 @@ void qmacfontengine_gamma_correct(QImage *image) #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) +QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &atsFamilyRef, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) : QFontEngineMulti(0) { this->fontDef = fontDef; @@ -162,6 +162,8 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con QCFString name; ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name); + if (QString(name).isEmpty()) + ATSFontFamilyGetName(atsFamilyRef, kATSOptionFlagsDefault, &name); transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 501bfff..4057142 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -195,6 +195,10 @@ public: head->root = new_root; } + inline bool isValid(uint n) const { + return n > 0 && n != head->freelist; + } + union { Header *head; Fragment *fragments; @@ -854,6 +858,7 @@ public: return data.fragment(index); } inline uint position(uint node, uint field = 0) const { return data.position(node, field); } + inline bool isValid(uint n) const { return data.isValid(n); } inline uint next(uint n) const { return data.next(n); } inline uint previous(uint n) const { return data.previous(n); } inline uint size(uint node, uint field = 0) const { return data.size(node, field); } diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 6babca1..3fd3ab5 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1518,7 +1518,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); - mousePressed = true; + mousePressed = (interactionFlags & Qt::TextSelectableByMouse); #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; #endif @@ -1551,7 +1551,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con extendBlockwiseSelection(cursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(cursorPos, pos.x()); - else if (wordSelectionEnabled) + else if (!wordSelectionEnabled) setCursorPosition(cursorPos, QTextCursor::KeepAnchor); } else { @@ -1607,13 +1607,11 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons if (!(buttons & Qt::LeftButton)) return; - const bool selectable = interactionFlags & Qt::TextSelectableByMouse; const bool editable = interactionFlags & Qt::TextEditable; - if (!selectable && !editable) - return; - if (!(mousePressed + || editable + || mightStartDrag || selectedWordOnDoubleClick.hasSelection() || selectedBlockOnTrippleClick.hasSelection())) return; @@ -1627,7 +1625,7 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons return; } - if (!selectable) + if (!mousePressed) return; const qreal mouseX = qreal(mousePos.x()); @@ -1695,10 +1693,8 @@ void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, c if (mousePressed) { mousePressed = false; #ifndef QT_NO_CLIPBOARD - if (interactionFlags & Qt::TextSelectableByMouse) { - setClipboardSelection(); - selectionChanged(true); - } + setClipboardSelection(); + selectionChanged(true); } else if (button == Qt::MidButton && (interactionFlags & Qt::TextEditable) && QApplication::clipboard()->supportsSelection()) { @@ -1950,6 +1946,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) if (isGettingInput) layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); QList<QTextLayout::FormatRange> overrides; + const int oldPreeditCursor = preeditCursor; preeditCursor = e->preeditString().length(); hideCursor = false; for (int i = 0; i < e->attributes().size(); ++i) { @@ -1970,6 +1967,8 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } layout->setAdditionalFormats(overrides); cursor.endEditBlock(); + if (oldPreeditCursor != preeditCursor) + emit q->microFocusChanged(); } QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 4378c62..4f86cff 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2681,6 +2681,22 @@ void QTextEngine::resolveAdditionalFormats() const specialData->resolvedFormatIndices = indices; } +QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line) +{ + if (!line.hasTrailingSpaces + || (option.flags() & QTextOption::IncludeTrailingSpaces) + || !isRightToLeft()) + return QFixed(); + + int pos = line.length; + const HB_CharAttributes *attributes = this->attributes(); + if (!attributes) + return QFixed(); + while (pos > 0 && attributes[line.from + pos - 1].whiteSpace) + --pos; + return width(line.from + pos, line.length - pos); +} + QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) : QTextEngine(string, f), _layoutData(string, _memory, MemSize) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 34723ab..67d7453 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -592,6 +592,7 @@ public: QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0) const; void shapeLine(const QScriptLine &line); + QFixed leadingSpaceWidth(const QScriptLine &line); private: void setBoundary(int strPos) const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 905f81b..692620f 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -64,23 +64,6 @@ QT_BEGIN_NAMESPACE #define SuppressText 0x5012 #define SuppressBackground 0x513 -static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line) -{ - if (!line.hasTrailingSpaces - || (eng->option.flags() & QTextOption::IncludeTrailingSpaces) - || !(eng->option.alignment() & Qt::AlignRight) - || !eng->isRightToLeft()) - return QFixed(); - - int pos = line.length; - const HB_CharAttributes *attributes = eng->attributes(); - if (!attributes) - return QFixed(); - while (pos > 0 && attributes[line.from + pos - 1].whiteSpace) - --pos; - return eng->width(line.from + pos, line.length - pos); -} - static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) { QFixed x = 0; @@ -91,7 +74,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) if (align & Qt::AlignJustify && eng->isRightToLeft()) align = Qt::AlignRight; if (align & Qt::AlignRight) - x = line.width - (line.textAdvance + leadingSpaceWidth(eng, line)); + x = line.width - (line.textAdvance + eng->leadingSpaceWidth(line)); else if (align & Qt::AlignHCenter) x = (line.width - line.textAdvance)/2; } diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 94f2fc7..a403cc5 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -891,6 +891,11 @@ QTextBlockUserData::~QTextBlockUserData() Returns true if this text block is valid; otherwise returns false. */ +bool QTextBlock::isValid() const +{ + return p != 0 && p->blockMap().isValid(n); +} + /*! \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other) diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index d5c1e8d..73aed79 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -204,7 +204,7 @@ public: inline QTextBlock(const QTextBlock &o) : p(o.p), n(o.n) {} inline QTextBlock &operator=(const QTextBlock &o) { p = o.p; n = o.n; return *this; } - inline bool isValid() const { return p != 0 && n != 0; } + bool isValid() const; inline bool operator==(const QTextBlock &o) const { return p == o.p && n == o.n; } inline bool operator!=(const QTextBlock &o) const { return p != o.p || n != o.n; } diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp index 96860df..8caeb74 100644 --- a/src/gui/util/qdesktopservices_s60.cpp +++ b/src/gui/util/qdesktopservices_s60.cpp @@ -314,7 +314,7 @@ static bool handleUrl(const QUrl &url) if (!url.isValid()) return false; - QString urlString(url.toString()); + QString urlString(url.toEncoded()); TPtrC urlPtr(qt_QString2TPtrC(urlString)); TRAPD( err, handleUrlL(urlPtr)); return err ? false : true; diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index c1ae3f9..04ab801 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -398,7 +398,7 @@ void QComboBoxPrivateContainer::leaveEvent(QEvent *) #ifdef Q_WS_MAC QStyleOptionComboBox opt = comboStyleOption(); if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)) - view->setCurrentIndex(QModelIndex()); + view->clearSelection(); #endif } @@ -671,8 +671,8 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive()) blockMouseReleaseTimer.stop(); QModelIndex indexUnderMouse = view->indexAt(m->pos()); - if (indexUnderMouse.isValid() && indexUnderMouse != view->currentIndex() - && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { + if (indexUnderMouse.isValid() + && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { view->setCurrentIndex(indexUnderMouse); } } @@ -704,11 +704,13 @@ void QComboBoxPrivateContainer::hideEvent(QHideEvent *) { emit resetButton(); combo->update(); +#ifndef QT_NO_GRAPHICSVIEW // QGraphicsScenePrivate::removePopup closes the combo box popup, it hides it non-explicitly. // Hiding/showing the QComboBox after this will unexpectedly show the popup as well. // Re-hiding the popup container makes sure it is explicitly hidden. if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) proxy->hide(); +#endif } void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 5a281ad..202ea7a 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -254,12 +254,20 @@ void QLineControl::setSelection(int start, int length) m_selstart = start; m_selend = qMin(start + length, (int)m_text.length()); m_cursor = m_selend; - } else { + } else if (length < 0){ if (start == m_selend && start + length == m_selstart) return; m_selstart = qMax(start + length, 0); m_selend = start; m_cursor = m_selstart; + } else if (m_selstart != m_selend) { + m_selstart = 0; + m_selend = 0; + m_cursor = start; + } else { + m_cursor = start; + emitCursorPositionChanged(); + return; } emit selectionChanged(); emitCursorPositionChanged(); @@ -435,7 +443,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) removeSelectedText(); } if (!event->commitString().isEmpty()) { - insert(event->commitString()); + internalInsert(event->commitString()); cursorPositionChanged = true; } diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index 3767b95..77ecf70 100644 --- a/src/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/audio/qaudioinput.cpp @@ -202,7 +202,13 @@ QAudioInput::~QAudioInput() /*! Uses the \a device as the QIODevice to transfer data. Passing a QIODevice allows the data to be transferred without any extra code. - All that is required is to open the QIODevice. + All that is required is to open the QIODevice. QAudioInput does not take + ownership of \a device. + + The QAudioInput will write to the device when new data is available. You can + subclass QIODevice and reimplement \l{QIODevice::}{writeData()} if you wish to + access the data. If you simply want to save data to a file, you can pass a + QFile to this function. If able to successfully get audio data from the systems audio device the state() is set to either QAudio::ActiveState or QAudio::IdleState, @@ -222,9 +228,12 @@ void QAudioInput::start(QIODevice* device) } /*! - Returns a pointer to the QIODevice being used to handle the data - transfer. This QIODevice can be used to read() audio data - directly. + + Returns a pointer to a new QIODevice that will be used to handle the data transfer. + This QIODevice can be used to \l{QIODevice::}{read()} audio data directly. + You will typically connect to the \l{QIODevice::}{readyRead()} signal, and + read from the device in the slot you connect to. QAudioInput keeps ownership + of the device. If able to access the systems audio device the state() is set to QAudio::IdleState, error() is set to QAudio::NoError diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index ccc20e6..69e59d1 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -363,9 +363,9 @@ qint64 QFtpDTP::read(char *data, qint64 maxlen) if (socket && socket->state() == QTcpSocket::ConnectedState) { read = socket->read(data, maxlen); } else { - read = bytesFromSocket.size(); + read = qMin(maxlen, qint64(bytesFromSocket.size())); memcpy(data, bytesFromSocket.data(), read); - bytesFromSocket.clear(); + bytesFromSocket.remove(0, read); } bytesDone += read; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 108ac68..7c90f68 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -1001,14 +1001,11 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo if (hop_by_hop) continue; - // for 4.6.0, we were planning to not store the date header in the - // cached resource; through that we planned to reduce the number - // of writes to disk when using a QNetworkDiskCache (i.e. don't - // write to disk when only the date changes). - // However, without the date we cannot calculate the age of the page - // anymore. - //if (header == "date") - //continue; + // we are currently not using the date header to determine the expiration time of a page, + // but only the "Expires", "max-age" and "s-maxage" headers, see + // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()"). + if (header == "date") + continue; // Don't store Warning 1xx headers if (header == "warning") { diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index dc4e4f7..8634b6b 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -196,6 +196,9 @@ QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() /*! Constructs a QNetworkConfigurationManager with the given \a parent. + + Note that to ensure a valid list of current configurations immediately available, updating + is done during construction which causes some delay. */ QNetworkConfigurationManager::QNetworkConfigurationManager( QObject* parent ) : QObject(parent) diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index 28ca173..fcb0128 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -59,6 +59,11 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager() return rv; } +static void doDeleteLater(QObject* obj) +{ + obj->deleteLater(); +} + QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(QNetworkConfiguration config) { QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); @@ -69,7 +74,7 @@ QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(QNetwor return p; } //otherwise make one - QSharedPointer<QNetworkSession> session(new QNetworkSession(config)); + QSharedPointer<QNetworkSession> session(new QNetworkSession(config), doDeleteLater); m->sessions[config] = session; return session; } diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 618ac79..a5cdf01 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -219,17 +219,19 @@ bool QSslCertificate::isNull() const Returns true if this certificate is valid; otherwise returns false. - Note: Currently, this function only checks that the current + Note: Currently, this function checks that the current data-time is within the date-time range during which the - certificate is considered valid. No other checks are - currently performed. + certificate is considered valid, and checks that the + certificate is not in a blacklist of fraudulent certificates. \sa isNull() */ bool QSslCertificate::isValid() const { const QDateTime currentTime = QDateTime::currentDateTime(); - return currentTime >= d->notValidBefore && currentTime <= d->notValidAfter; + return currentTime >= d->notValidBefore && + currentTime <= d->notValidAfter && + ! QSslCertificatePrivate::isBlacklisted(*this); } /*! @@ -798,6 +800,30 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr return certificates; } +// These certificates are known to be fraudulent and were created during the comodo +// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html +static const char *certificate_blacklist[] = { + "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", + "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", + "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", + "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", + "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", + "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", + "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", + "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", + "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", + 0 +}; + +bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) +{ + for (int a = 0; certificate_blacklist[a] != 0; a++) { + if (certificate.serialNumber() == certificate_blacklist[a]) + return true; + } + return false; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QSslCertificate &certificate) { diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index cdceb0f..1ce33d3 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -96,6 +96,7 @@ public: static QSslCertificate QSslCertificate_from_X509(X509 *x509); static QList<QSslCertificate> certificatesFromPem(const QByteArray &pem, int count = -1); static QList<QSslCertificate> certificatesFromDer(const QByteArray &der, int count = -1); + static bool isBlacklisted(const QSslCertificate &certificate); friend class QSslSocketBackendPrivate; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 0866534..2427193 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1193,6 +1193,13 @@ bool QSslSocketBackendPrivate::startHandshake() X509 *x509 = q_SSL_get_peer_certificate(ssl); configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509); q_X509_free(x509); + if (QSslCertificatePrivate::isBlacklisted(configuration.peerCertificate)) { + q->setErrorString(QSslSocket::tr("The peer certificate is blacklisted")); + q->setSocketError(QAbstractSocket::SslHandshakeFailedError); + emit q->error(QAbstractSocket::SslHandshakeFailedError); + plainSocket->disconnectFromHost(); + return false; + } // Start translating errors. QList<QSslError> errors; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index ded7aa8..b755153 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -69,6 +69,7 @@ #if !defined(QT_OPENGL_ES_1) #include "gl2paintengineex/qpaintengineex_opengl2_p.h" +#include <private/qwindowsurface_gl_p.h> #endif #ifndef QT_OPENGL_ES_2 @@ -86,7 +87,6 @@ #include <private/qpixmapdata_p.h> #include <private/qpixmapdata_gl_p.h> #include <private/qglpixelbuffer_p.h> -#include <private/qwindowsurface_gl_p.h> #include <private/qimagepixmapcleanuphooks_p.h> #include "qcolormap.h" #include "qfile.h" diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index ae61ca1..0e879df 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -43,13 +43,13 @@ #include <private/qgl_p.h> #include <private/qglpixelbuffer_p.h> #include <private/qglframebufferobject_p.h> -#include <private/qwindowsurface_gl_p.h> #ifdef Q_WS_X11 #include <private/qpixmapdata_x11gl_p.h> #endif #if !defined(QT_OPENGL_ES_1) #include <private/qpixmapdata_gl_p.h> +#include <private/qwindowsurface_gl_p.h> #endif QT_BEGIN_NAMESPACE diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_poolgl.cpp index 44d9c84..95152dd 100644 --- a/src/opengl/qpixmapdata_poolgl.cpp +++ b/src/opengl/qpixmapdata_poolgl.cpp @@ -64,19 +64,6 @@ QT_BEGIN_NAMESPACE Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); -/*! - \class QGLFramebufferObjectPool - \since 4.6 - - \brief The QGLFramebufferObject class provides a pool of framebuffer - objects for offscreen rendering purposes. - - When requesting an FBO of a given size and format, an FBO of the same - format and a size at least as big as the requested size will be returned. - - \internal -*/ - static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) { return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index dc74c4e..6d6fb02 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -1025,11 +1025,10 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m case QPainter::CompositionMode_DestinationOut: surface->SetPorterDuff(surface, DSPD_DST_OUT); break; -#if (Q_DIRECTFB_VERSION >= 0x010209) case QPainter::CompositionMode_Destination: - surface->SetPorterDuff(surface, DSPD_DST); + surface->SetSrcBlendFunction(surface, DSBF_ZERO); + surface->SetDstBlendFunction(surface, DSBF_ONE); break; -#endif #if (Q_DIRECTFB_VERSION >= 0x010000) case QPainter::CompositionMode_SourceAtop: surface->SetPorterDuff(surface, DSPD_SRC_ATOP); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 3d8cf50..9a94c30 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -365,10 +365,12 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, if (!win) return; -#ifndef QT_NO_QWS_PROXYSCREEN +#if !defined(QT_NO_QWS_PROXYSCREEN) && !defined(QT_NO_GRAPHICSVIEW) QWExtra *extra = qt_widget_private(widget)->extraData(); if (extra && extra->proxyWidget) return; +#else + Q_UNUSED(widget); #endif const quint8 windowOpacity = quint8(win->windowOpacity() * 0xff); diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index c904c3c..69a6922 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -170,7 +170,7 @@ bool QMeeGoGraphicsSystemSwitchHandler::eventFilter(QObject *object, QEvent *eve if (visibleWidgets() == 0) QMeeGoGraphicsSystem::switchToRaster(); } else { - if (visibleWidgets() == 1) + if (visibleWidgets() > 0) QMeeGoGraphicsSystem::switchToMeeGo(); } } diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp index 0970b89..b6ba7ec 100644 --- a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp @@ -194,6 +194,8 @@ QImage* QMeeGoLivePixmapData::lock(EGLSyncKHR fenceSync) void *data = 0; int pitch = 0; + int surfaceWidth = 0; + int surfaceHeight = 0; EGLSurface surface = 0; QImage::Format format; lockedImage = QImage(); @@ -206,9 +208,11 @@ QImage* QMeeGoLivePixmapData::lock(EGLSyncKHR fenceSync) eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) &data); eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) &pitch); + eglQuerySurface(QEgl::display(), surface, EGL_WIDTH, (EGLint*) &surfaceWidth); + eglQuerySurface(QEgl::display(), surface, EGL_HEIGHT, (EGLint*) &surfaceHeight); // Ok, here we know we just support those two formats. Real solution would be: - // uqery also the format. + // query also the format. if (backingX11Pixmap->depth() > 16) format = QImage::Format_ARGB32_Premultiplied; else @@ -219,6 +223,12 @@ QImage* QMeeGoLivePixmapData::lock(EGLSyncKHR fenceSync) return &lockedImage; } + if (width() != surfaceWidth || height() != surfaceHeight) { + qWarning("Live texture dimensions don't match!"); + QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface); + return &lockedImage; + } + lockedImage = QImage((uchar *) data, width(), height(), pitch, format); return &lockedImage; } diff --git a/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro b/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro new file mode 100644 index 0000000..2748889 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro @@ -0,0 +1,21 @@ +TARGET = qmldbg_ost +QT += declarative network + +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmltooling +QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)" + +SOURCES += \ + qmlostplugin.cpp \ + qostdevice.cpp + +HEADERS += \ + qmlostplugin.h \ + qostdevice.h \ + usbostcomm.h + +target.path += $$[QT_INSTALL_PLUGINS]/qmltooling +INSTALLS += target + +symbian:TARGET.UID3=0x20031E92 diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp new file mode 100644 index 0000000..1c91c34 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlostplugin.h" +#include "qostdevice.h" + +#include <private/qdeclarativedebugserver_p.h> +#include <private/qpacketprotocol_p.h> + +QT_BEGIN_NAMESPACE + +static const TInt KQmlOstProtocolId = 0x94; + +class QmlOstPluginPrivate { +public: + QmlOstPluginPrivate(); + + QOstDevice *ost; + QPacketProtocol *protocol; + QDeclarativeDebugServer *debugServer; +}; + +QmlOstPluginPrivate::QmlOstPluginPrivate() : + ost(0), + protocol(0), + debugServer(0) +{ +} + +QmlOstPlugin::QmlOstPlugin() : + d_ptr(new QmlOstPluginPrivate) +{ +} + +QmlOstPlugin::~QmlOstPlugin() +{ + delete d_ptr; +} + +void QmlOstPlugin::setServer(QDeclarativeDebugServer *server) +{ + Q_D(QmlOstPlugin); + d->debugServer = server; +} + +bool QmlOstPlugin::isConnected() const +{ + Q_D(const QmlOstPlugin); + return d->ost && d->ost->isOpen(); +} + +void QmlOstPlugin::send(const QByteArray &message) +{ + Q_D(QmlOstPlugin); + + if (!isConnected()) + return; + + QPacket pack; + pack.writeRawData(message.data(), message.length()); + + d->protocol->send(pack); + //d->socket->flush(); +} + +void QmlOstPlugin::disconnect() +{ + Q_D(QmlOstPlugin); + + delete d->protocol; + d->protocol = 0; +} + +void QmlOstPlugin::setPort(int port, bool block) +{ + Q_UNUSED(port); + Q_UNUSED(block); + + Q_D(QmlOstPlugin); + + d->ost = new QOstDevice(this); + bool ok = d->ost->open(KQmlOstProtocolId); + if (!ok) { + if (d->ost->errorString().length()) + qDebug("Error from QOstDevice: %s", qPrintable(d->ost->errorString())); + qWarning("QDeclarativeDebugServer: Unable to listen on OST"); // This message is part of the signalling - do not change the format! + return; + } + d->protocol = new QPacketProtocol(d->ost, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + qWarning("QDeclarativeDebugServer: Waiting for connection via OST"); // This message is part of the signalling - do not change the format! +} + +void QmlOstPlugin::readyRead() +{ + Q_D(QmlOstPlugin); + QPacket packet = d->protocol->read(); + + QByteArray content = packet.data(); + d->debugServer->receiveMessage(content); +} + +Q_EXPORT_PLUGIN2(qmlostplugin, QmlOstPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h new file mode 100644 index 0000000..eee6ee1 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLOSTPLUGIN_H +#define QMLOSTPLUGIN_H + +#include <QtGui/QStylePlugin> +#include <QtDeclarative/private/qdeclarativedebugserverconnection_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeDebugServer; +class QmlOstPluginPrivate; + +class QmlOstPlugin : public QObject, public QDeclarativeDebugServerConnection +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlOstPlugin) + Q_DISABLE_COPY(QmlOstPlugin) + Q_INTERFACES(QDeclarativeDebugServerConnection) + + +public: + QmlOstPlugin(); + ~QmlOstPlugin(); + + void setServer(QDeclarativeDebugServer *server); + void setPort(int port, bool bock); + + bool isConnected() const; + void send(const QByteArray &message); + void disconnect(); + +private Q_SLOTS: + void readyRead(); + +private: + QmlOstPluginPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QMLOSTPLUGIN_H diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp new file mode 100644 index 0000000..21b0169 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qostdevice.h" +#include <e32base.h> + +#include "usbostcomm.h" + +class QOstDevicePrivate : public CActive +{ + QOstDevice* q_ptr; + Q_DECLARE_PUBLIC(QOstDevice) + +public: + QOstDevicePrivate() : CActive(CActive::EPriorityStandard) { + CActiveScheduler::Add(this); + } + ~QOstDevicePrivate() { + Cancel(); + } + +private: + void RunL(); + void DoCancel(); + +private: + RUsbOstComm ost; + TBuf8<4096> readBuf; + QByteArray dataBuf; +}; + +QOstDevice::QOstDevice(QObject *parent) : + QIODevice(parent), d_ptr(new QOstDevicePrivate) +{ + d_ptr->q_ptr = this; +} + +QOstDevice::~QOstDevice() +{ + close(); + delete d_ptr; +} + +bool QOstDevice::open(int ostProtocolId) +{ + if (isOpen()) + return false; + + Q_D(QOstDevice); + TInt err = d->ost.Connect(); + if (!err) err = d->ost.Open(); + const TVersion KRequiredVersion(1,1,0); + TVersion version = d->ost.Version(); + if (version.iMajor < KRequiredVersion.iMajor || + (version.iMajor == KRequiredVersion.iMajor && version.iMinor < KRequiredVersion.iMinor)) { + setErrorString("CODA version too old. At least version 4.0.18 (without TRK) is required."); + return false; + } + + if (!err) err = d->ost.RegisterProtocolID((TOstProtIds)ostProtocolId, EFalse); + if (!err) { + d->ost.ReadMessage(d->iStatus, d->readBuf); + d->SetActive(); + return QIODevice::open(ReadWrite | Unbuffered); + } + return false; +} + +void QOstDevicePrivate::RunL() +{ + Q_Q(QOstDevice); + //qDebug("QOstDevice received %d bytes q=%x", readBuf.Size(), q); + if (iStatus == KErrNone) { + QByteArray data = QByteArray::fromRawData((const char*)readBuf.Ptr(), readBuf.Size()); + dataBuf.append(data); + + readBuf.Zero(); + ost.ReadMessage(iStatus, readBuf); + SetActive(); + + emit q->readyRead(); + } else { + q->setErrorString(QString("Error %1 from RUsbOstComm::ReadMessage()").arg(iStatus.Int())); + } + //qDebug("-QOstDevicePrivate RunL"); +} + +void QOstDevicePrivate::DoCancel() +{ + ost.ReadCancel(); +} + +void QOstDevice::close() +{ + Q_D(QOstDevice); + QIODevice::close(); + d->Cancel(); + // RDbgTrcComm::Close isn't safe to call when not open, sigh + if (d->ost.Handle()) { + d->ost.Close(); + } +} + +qint64 QOstDevice::readData(char *data, qint64 maxSize) +{ + Q_D(QOstDevice); + if (d->dataBuf.length() == 0 && !d->IsActive()) + return -1; + qint64 available = qMin(maxSize, (qint64)d->dataBuf.length()); + memcpy(data, d->dataBuf.constData(), available); + d->dataBuf.remove(0, available); + return available; +} + +static const TInt KMaxOstPacketLen = 4096; + +qint64 QOstDevice::writeData(const char *data, qint64 maxSize) +{ + Q_D(QOstDevice); + TPtrC8 ptr((const TUint8*)data, (TInt)maxSize); + while (ptr.Length()) { + TPtrC8 fragment = ptr.Left(qMin(ptr.Length(), KMaxOstPacketLen)); + //qDebug("QOstDevice writing %d bytes", fragment.Length()); + TRequestStatus stat; + d->ost.WriteMessage(stat, fragment); + User::WaitForRequest(stat); + if (stat.Int() != KErrNone) { + setErrorString(QString("Error %1 from RUsbOstComm::WriteMessage()").arg(stat.Int())); + return -1; + } + ptr.Set(ptr.Mid(fragment.Length())); + } + emit bytesWritten(maxSize); //TODO does it matter this is emitted synchronously? + //qDebug("QOstDevice wrote %d bytes", ptr.Size()); + return maxSize; +} + +qint64 QOstDevice::bytesAvailable() const +{ + Q_D(const QOstDevice); + return d->dataBuf.length(); +} diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h new file mode 100644 index 0000000..2c26ff7 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOSTDEVICE_H +#define QOSTDEVICE_H + +#include <QtCore/QIODevice> + +QT_BEGIN_NAMESPACE + +class QOstDevicePrivate; + +class QOstDevice : public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QOstDevice) + Q_DISABLE_COPY(QOstDevice) + +public: + explicit QOstDevice(QObject *parent=0); + ~QOstDevice(); + + bool open(int ostProtocolId); + void close(); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + qint64 bytesAvailable() const; + +private: + QOstDevicePrivate* d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QOSTDEVICE_H diff --git a/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h b/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h new file mode 100644 index 0000000..48ff7bf --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef USBHOSTCOMM_H +#define USBHOSTCOMM_H + +// Based on the official usbostrouter header, modified to remove dependancy on +// the client DLL + +#include <e32base.h> + +typedef int TOstProtIds; + +class RUsbOstComm : public RSessionBase +{ +public: + RUsbOstComm(); + TInt Connect(); + TInt Disconnect(); + TInt Open(); + TInt Close(); + TInt RegisterProtocolID(TOstProtIds aId, TBool aNeedHeader); + void ReadMessage(TRequestStatus& aStatus, TDes8& aDes); + TInt ReadCancel(); + void WriteMessage(TRequestStatus& aStatus, const TDesC8& aDes, TBool aHasHeader=EFalse); + TVersion Version() const; + +private: + enum TUsbOstCmdCode + { + EUsbOstCmdCodeFirst, + EUsbOstCmdConnect, + EUsbOstCmdDisconnect, + EUsbOstCmdCodeGetAcmConfig, + EUsbOstCmdCodeSetAcmConfig, + EUsbOstCmdCodeOpen, + EUsbOstCmdCodeClose, + EUsbOstCmdCodeRegisterId, + EUsbOstCmdCodeRegisterIds, + EUsbOstCmdCodeUnRegisterId, + EUsbOstCmdCodeUnRegisterIds, + EUsbOstCmdCodeReadMsg, + EUsbOstCmdCodeReadCancel, + EUsbOstCmdCodeWriteMsg, + EUsbOstCmdCodeWriteCancel, + EUsbOstCmdCodeLast + }; +}; + +RUsbOstComm::RUsbOstComm() +{ +} + +TInt RUsbOstComm::Connect() +{ + _LIT(KUsbOstServerName, "!UsbOstRouter"); + _LIT(KUsbOstServerImageName, "usbostrouter"); + const TUid KUsbOstServerUid = { 0x200170BE }; + TInt startupAttempts = 2; + for(;;) { + TInt ret = CreateSession(KUsbOstServerName, TVersion(1,0,0)); + if (ret != KErrNotFound && ret != KErrServerTerminated) { + return ret; + } + + if (startupAttempts-- == 0) { + return ret; + } + + RProcess server; + ret = server.Create(KUsbOstServerImageName, KNullDesC, KUsbOstServerUid); + if (ret != KErrNone) + return ret; + + TRequestStatus serverDiedRequestStatus; + server.Rendezvous(serverDiedRequestStatus); + + if (serverDiedRequestStatus != KRequestPending) { + // Abort startup + server.Kill(KErrNone); + } else { + // Logon OK - start the server + server.Resume(); + } + User::WaitForRequest(serverDiedRequestStatus); + ret = (server.ExitType() == EExitPanic) ? KErrGeneral : serverDiedRequestStatus.Int(); + server.Close(); + + if (ret != KErrNone && ret != KErrAlreadyExists) { + return ret; + } + } +} + +TInt RUsbOstComm::Disconnect() +{ + return SendReceive(EUsbOstCmdDisconnect); +} + +TInt RUsbOstComm::Open() +{ + return SendReceive(EUsbOstCmdCodeOpen); +} + +TInt RUsbOstComm::Close() +{ + TInt err = SendReceive(EUsbOstCmdCodeClose); + RHandleBase::Close(); + return err; +} + +TInt RUsbOstComm::RegisterProtocolID(const TOstProtIds aId, TBool aNeedHeader) +{ + TIpcArgs args(aId, aNeedHeader); + return SendReceive(EUsbOstCmdCodeRegisterId, args); +} + +void RUsbOstComm::ReadMessage(TRequestStatus& aStatus, TDes8& aDes) +{ + TIpcArgs args(aDes.MaxLength(), &aDes); + SendReceive(EUsbOstCmdCodeReadMsg, args, aStatus); +} + +TInt RUsbOstComm::ReadCancel() +{ + return SendReceive(EUsbOstCmdCodeReadCancel); +} + +void RUsbOstComm::WriteMessage(TRequestStatus& aStatus, const TDesC8& aDes, TBool aHasHeader) +{ + TIpcArgs args(aHasHeader, aDes.Length(), &aDes); + SendReceive(EUsbOstCmdCodeWriteMsg, args, aStatus); +} + +typedef TVersion (*TVersionFunction)(const RUsbOstComm*); +const TInt KVersionOrdinal = 17; + +TVersion RUsbOstComm::Version() const +{ + // This function has to go to the DLL, unfortunately + TVersion result; // Return 0.0.0 on any error + RLibrary lib; + TInt err = lib.Load(_L("usbostcomm")); + if (err) return result; + + TLibraryFunction fn = lib.Lookup(KVersionOrdinal); + if (fn) + result = ((TVersionFunction)fn)(this); + lib.Close(); + return result; +} + +#endif //USBHOSTCOMM_H diff --git a/src/plugins/qmltooling/tcpserver/tcpserver.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro index f4f2666..e8ab962 100644 --- a/src/plugins/qmltooling/tcpserver/tcpserver.pro +++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro @@ -1,4 +1,4 @@ -TARGET = tcpserver +TARGET = qmldbg_tcp QT += declarative network include(../../qpluginbase.pri) @@ -15,4 +15,4 @@ HEADERS += \ target.path += $$[QT_INSTALL_PLUGINS]/qmltooling INSTALLS += target -symbian:TARGET.UID3=0x20031E90
\ No newline at end of file +symbian:TARGET.UID3=0x20031E90 diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp index 69c1ef5..7db0db3 100644 --- a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp @@ -97,7 +97,8 @@ void QTcpServerConnection::send(const QByteArray &message) { Q_D(QTcpServerConnection); - if (!isConnected()) + if (!isConnected() + || !d->protocol || !d->socket) return; QPacket pack; @@ -111,9 +112,10 @@ void QTcpServerConnection::disconnect() { Q_D(QTcpServerConnection); - delete d->protocol; + // protocol might still be processing packages at this point + d->protocol->deleteLater(); d->protocol = 0; - delete d->socket; + d->socket->deleteLater(); d->socket = 0; } @@ -143,6 +145,9 @@ void QTcpServerConnection::listen() void QTcpServerConnection::readyRead() { Q_D(QTcpServerConnection); + if (!d->protocol) + return; + QPacket packet = d->protocol->read(); QByteArray content = packet.data(); diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h index a6e17e6..a6e17e6 100644 --- a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro index 01cf1a9..9b3346f 100644 --- a/src/plugins/qmltooling/qmltooling.pro +++ b/src/plugins/qmltooling/qmltooling.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = tcpserver - +SUBDIRS = qmldbg_tcp +symbian:SUBDIRS += qmldbg_ost diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 82ded24..11ff7bc 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12182,5 +12182,7 @@ EXPORTS _ZNK14QVolatileImage9constBitsEv @ 12181 NONAME _ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12182 NONAME _Z32qt_s60_setPartialScreenInputModeb @ 12183 NONAME - _ZNK14QVolatileImage14paintingActiveEv @ 12184 NONAME + _Z29qt_draw_decoration_for_glyphsP8QPainterPKjPK11QFixedPointiP11QFontEngineRK5QFontRK15QTextCharFormat @ 12184 NONAME + _ZNK10QTextBlock7isValidEv @ 12185 NONAME + _ZNK14QVolatileImage14paintingActiveEv @ 12186 NONAME diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 495b1a6..441e355 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -1374,12 +1374,16 @@ QStringList QMYSQLDriver::tables(QSql::TableType type) const } else { QSqlQuery q(createResult()); if(type & QSql::Tables) { - q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'BASE TABLE'")); + QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'BASE TABLE'"); + q.exec(sql); + while(q.next()) tl.append(q.value(0).toString()); } if(type & QSql::Views) { - q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'VIEW'")); + QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'VIEW'"); + q.exec(sql); + while(q.next()) tl.append(q.value(0).toString()); } diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 9698860..3fbc08c 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -584,7 +584,7 @@ static qreal toDouble(const QChar *&str) ++str; } bool exponent = false; - if (*str == QLatin1Char('e') && pos < maxLen) { + if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) { exponent = true; temp[pos++] = 'e'; ++str; |