From b62dc3277c4d41cc99d37c457e3a55842879e0b1 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 9 Sep 2011 14:49:15 +0200 Subject: Release font engine refcount when done using it in QTextEngine 5f2b6dd2a50275bc05ae5d7e9dd8902d6d49d9df increased refcounts for font engines in QTextEngine cache, we need to decrease them when the QTextEngine is deallocated. Task-number: QTBUG-21222 Reviewed-by: Eskil --- src/gui/text/qtextengine.cpp | 12 +++++++++--- src/gui/text/qtextengine_p.h | 1 + src/gui/text/qtextlayout.cpp | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index cff3641708..ee2eef62a7 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1334,6 +1334,7 @@ QTextEngine::~QTextEngine() if (!stackEngine) delete layoutData; delete specialData; + resetFontEngineCache(); } const HB_CharAttributes *QTextEngine::attributes() const @@ -1394,6 +1395,13 @@ static inline void releaseCachedFontEngine(QFontEngine *fontEngine) } } +void QTextEngine::resetFontEngineCache() +{ + releaseCachedFontEngine(feCache.prevFontEngine); + releaseCachedFontEngine(feCache.prevScaledFontEngine); + feCache.reset(); +} + void QTextEngine::invalidate() { freeMemory(); @@ -1402,9 +1410,7 @@ void QTextEngine::invalidate() if (specialData) specialData->resolvedFormatIndices.clear(); - releaseCachedFontEngine(feCache.prevFontEngine); - releaseCachedFontEngine(feCache.prevScaledFontEngine); - feCache.reset(); + resetFontEngineCache(); } void QTextEngine::clearLineData() diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index c920c7ba6e..2b6db674a4 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -614,6 +614,7 @@ public: QFixed leadingSpaceWidth(const QScriptLine &line); int positionInLigature(const QScriptItem *si, int end, QFixed x, QFixed edge, int glyph_pos, bool cursorOnCharacter); + void resetFontEngineCache(); private: void setBoundary(int strPos) const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index d180f0edc5..f2d3de1519 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -386,7 +386,7 @@ QTextLayout::~QTextLayout() void QTextLayout::setFont(const QFont &font) { d->fnt = font; - d->feCache.reset(); + d->resetFontEngineCache(); } /*! @@ -519,7 +519,7 @@ void QTextLayout::setAdditionalFormats(const QList &formatList) } if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); - d->feCache.reset(); + d->resetFontEngineCache(); } /*! -- cgit v1.2.3 From f85819fe083ae7c6804c884de68e906d153a6d11 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 12 Sep 2011 09:42:51 +1000 Subject: StrictlyEnforceRange with snapOneItem/Row and header behavior change Change cf23188de237009136fa1480ab8fd9e3ca364769 changed the positioning of a view with StrictlyEnforceRange, snapOneItem/Row, and a header, such that the view was positioned at the beginning of the header, rather than on the first item. This change reverts back to the old behavior (position on the first item). Change-Id: I62ad183919bb2ed83d787d1d76421caf9e708599 Task-number: QTTH-1501 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativegridview.cpp | 6 ++++-- src/declarative/graphicsitems/qdeclarativelistview.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 59e4cbb80e..5a5b60e9f2 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -1064,6 +1064,8 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m highlightEnd = highlightRangeEnd; } + bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange; + if (snapMode != QDeclarativeGridView::NoSnap) { qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position(); if (snapMode == QDeclarativeGridView::SnapOneRow && moveReason == Mouse) { @@ -1081,7 +1083,7 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m FxGridItem *topItem = snapItemAt(tempPosition+highlightStart); FxGridItem *bottomItem = snapItemAt(tempPosition+highlightEnd); qreal pos; - if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) { + if (topItem && bottomItem && strictHighlightRange) { qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent); qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent); pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos; @@ -1089,7 +1091,7 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m qreal headerPos = 0; if (header) headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos(); - if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) { + if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2 && !strictHighlightRange) { pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart; } else { if (isRightToLeftTopToBottom()) diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 57b7dea699..70be7a7099 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -1293,6 +1293,7 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m correctFlick = false; fixupMode = moveReason == Mouse ? fixupMode : Immediate; + bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange; qreal highlightStart; qreal highlightEnd; @@ -1325,9 +1326,9 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m FxListItem *topItem = snapItemAt(tempPosition+highlightStart); FxListItem *bottomItem = snapItemAt(tempPosition+highlightEnd); qreal pos; - bool isInBounds = -position() > maxExtent && -position() < minExtent; + bool isInBounds = -position() > maxExtent && -position() <= minExtent; if (topItem && isInBounds) { - if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) { + if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2 && !strictHighlightRange) { pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart; } else { if (isRightToLeft()) @@ -1356,7 +1357,7 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } vTime = timeline.time(); } - } else if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange + } else if (currentItem && strictHighlightRange && moveReason != QDeclarativeListViewPrivate::SetIndex) { updateHighlight(); qreal pos = currentItem->itemPosition(); -- cgit v1.2.3 From 7d0e1bb75dcb8d6d4fa843f95610fd1adec803f0 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 13 Sep 2011 09:57:15 +1000 Subject: Backport imports directory caching performance optimization Backported from Qt5 change a6da3b26 Change-Id: Ib1715f3d5c144775e475426ce4471000b5ae0645 Task-number: QTBUG-15899 --- src/declarative/qml/qdeclarativedirparser.cpp | 29 +++++++ src/declarative/qml/qdeclarativedirparser_p.h | 4 + src/declarative/qml/qdeclarativeimport.cpp | 103 ++++++++++++------------- src/declarative/qml/qdeclarativeimport_p.h | 2 + src/declarative/qml/qdeclarativetypeloader.cpp | 99 +++++++++++++++++++++++- src/declarative/qml/qdeclarativetypeloader_p.h | 9 +++ 6 files changed, 190 insertions(+), 56 deletions(-) diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index 0a7a749c43..401eea9558 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -41,8 +41,10 @@ #include "private/qdeclarativedirparser_p.h" #include "qdeclarativeerror.h" +#include #include +#include #include QT_BEGIN_NAMESPACE @@ -66,6 +68,16 @@ void QDeclarativeDirParser::setUrl(const QUrl &url) _url = url; } +QString QDeclarativeDirParser::fileSource() const +{ + return _filePathSouce; +} + +void QDeclarativeDirParser::setFileSource(const QString &filePath) +{ + _filePathSouce = filePath; +} + QString QDeclarativeDirParser::source() const { return _source; @@ -92,6 +104,23 @@ bool QDeclarativeDirParser::parse() _plugins.clear(); _components.clear(); + if (_source.isEmpty() && !_filePathSouce.isEmpty()) { + QFile file(_filePathSouce); + if (!QDeclarative_isFileCaseCorrect(_filePathSouce)) { + QDeclarativeError error; + error.setDescription(QString::fromUtf8("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(_url.toString()).arg(_filePathSouce)); + _errors.prepend(error); + return false; + } else if (file.open(QFile::ReadOnly)) { + _source = QString::fromUtf8(file.readAll()); + } else { + QDeclarativeError error; + error.setDescription(QString::fromUtf8("module \"%1\" definition \"%2\" not readable").arg(_url.toString()).arg(_filePathSouce)); + _errors.prepend(error); + return false; + } + } + QTextStream stream(&_source); int lineNumber = 0; diff --git a/src/declarative/qml/qdeclarativedirparser_p.h b/src/declarative/qml/qdeclarativedirparser_p.h index 7db7d8cd46..347b2290fb 100644 --- a/src/declarative/qml/qdeclarativedirparser_p.h +++ b/src/declarative/qml/qdeclarativedirparser_p.h @@ -73,6 +73,9 @@ public: QString source() const; void setSource(const QString &source); + QString fileSource() const; + void setFileSource(const QString &filePath); + bool isParsed() const; bool parse(); @@ -116,6 +119,7 @@ private: QList _errors; QUrl _url; QString _source; + QString _filePathSouce; QList _components; QList _plugins; unsigned _isParsed: 1; diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 6e0b348aa8..44fc84997e 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -79,16 +79,16 @@ public: QList qmlDirComponents; - bool find_helper(int i, const QByteArray& type, int *vmajor, int *vminor, + bool find_helper(QDeclarativeTypeLoader *typeLoader, int i, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return, QUrl *base = 0, bool *typeRecursionDetected = 0); - bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, + bool find(QDeclarativeTypeLoader *typeLoader, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return, QUrl *base = 0, QString *errorString = 0); }; class QDeclarativeImportsPrivate { public: - QDeclarativeImportsPrivate(); + QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader); ~QDeclarativeImportsPrivate(); bool importExtension(const QString &absoluteFilePath, const QString &uri, @@ -111,6 +111,7 @@ public: QSet qmlDirFilesForWhichPluginsHaveBeenLoaded; QDeclarativeImportedNamespace unqualifiedset; QHash set; + QDeclarativeTypeLoader *typeLoader; }; /*! @@ -134,9 +135,12 @@ QDeclarativeImports::operator =(const QDeclarativeImports ©) return *this; } -QDeclarativeImports::QDeclarativeImports() -: d(new QDeclarativeImportsPrivate) -{ +QDeclarativeImports::QDeclarativeImports() + : d(new QDeclarativeImportsPrivate(0)){ +} + +QDeclarativeImports::QDeclarativeImports(QDeclarativeTypeLoader *typeLoader) + : d(new QDeclarativeImportsPrivate(typeLoader)){ } QDeclarativeImports::~QDeclarativeImports() @@ -268,10 +272,11 @@ bool QDeclarativeImports::resolveType(QDeclarativeImportedNamespace* ns, const Q QDeclarativeType** type_return, QUrl* url_return, int *vmaj, int *vmin) const { - return ns->find(type,vmaj,vmin,type_return,url_return); + Q_ASSERT(d->typeLoader); + return ns->find(d->typeLoader,type,vmaj,vmin,type_return,url_return); } -bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, int *vmajor, int *vminor, +bool QDeclarativeImportedNamespace::find_helper(QDeclarativeTypeLoader *typeLoader, int i, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return, QUrl *base, bool *typeRecursionDetected) { @@ -291,7 +296,6 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i return true; } - QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); QDeclarativeDirComponents qmldircomponents = qmlDirComponents.at(i); bool typeWasDeclaredInQmldir = false; @@ -303,6 +307,7 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i // importing version -1 means import ALL versions if ((vmaj == -1) || (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion))) { + QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); QUrl candidate = url.resolved(QUrl(c.fileName)); if (c.internal && base) { if (base->resolved(QUrl(c.fileName)) != candidate) @@ -323,8 +328,9 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i if (!typeWasDeclaredInQmldir && !isLibrary.at(i)) { // XXX search non-files too! (eg. zip files, see QT-524) - QFileInfo f(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)); - if (f.exists()) { + QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); + QString file = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + if (!typeLoader->absoluteFilePath(file).isEmpty()) { if (base && *base == url) { // no recursion if (typeRecursionDetected) *typeRecursionDetected = true; @@ -338,9 +344,8 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i return false; } -QDeclarativeImportsPrivate::QDeclarativeImportsPrivate() -: ref(1) -{ +QDeclarativeImportsPrivate::QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader) + : ref(1), typeLoader(loader){ } QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate() @@ -353,33 +358,19 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components, QString *errorString) { - QFile file(absoluteFilePath); - QString filecontent; - if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath); - return false; - } else if (file.open(QFile::ReadOnly)) { - filecontent = QString::fromUtf8(file.readAll()); - if (qmlImportTrace()) - qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: " - << "loaded " << absoluteFilePath; - } else { + Q_ASSERT(typeLoader); + const QDeclarativeDirParser *qmldirParser = typeLoader->qmlDirParser(absoluteFilePath); + if (qmldirParser->hasError()) { if (errorString) *errorString = QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath); return false; } - QDir dir = QFileInfo(file).dir(); - - QDeclarativeDirParser qmldirParser; - qmldirParser.setSource(filecontent); - qmldirParser.parse(); if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); - - foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { + QDir dir = QFileInfo(absoluteFilePath).dir(); + foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser->plugins()) { QString resolvedFilePath = database->resolvePlugin(dir, plugin.path, plugin.name); #if defined(QT_LIBINFIX) && defined(Q_OS_SYMBIAN) @@ -404,7 +395,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath } if (components) - *components = qmldirParser.components(); + *components = qmldirParser->components(); return true; } @@ -445,6 +436,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp QDeclarativeScriptParser::Import::Type importType, QDeclarativeImportDatabase *database, QString *errorString) { + Q_ASSERT(typeLoader); QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork; QString uri = uri_arg; QDeclarativeImportedNamespace *s; @@ -462,20 +454,20 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; QString dir; - + QString qmldir; // step 1: search for extension with fully encoded version number if (vmaj >= 0 && vmin >= 0) { foreach (const QString &p, database->fileImportPath) { dir = p+QLatin1Char('/')+url; + qmldir = dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir"); - QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); - - if (fi.isFile()) { + QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir); + if (!absoluteFilePath.isEmpty()) { found = true; - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(QLatin1Char('/'))); + url = QUrl::fromLocalFile(absolutePath).toString(); uri = resolvedUri(dir, database); if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) return false; @@ -487,14 +479,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp if (vmaj >= 0 && vmin >= 0) { foreach (const QString &p, database->fileImportPath) { dir = p+QLatin1Char('/')+url; + qmldir = dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"); - QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); - - if (fi.isFile()) { + QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir); + if (!absoluteFilePath.isEmpty()) { found = true; - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(QLatin1Char('/'))); + url = QUrl::fromLocalFile(absolutePath).toString(); uri = resolvedUri(dir, database); if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) return false; @@ -507,14 +499,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp foreach (const QString &p, database->fileImportPath) { dir = p+QLatin1Char('/')+url; + qmldir = dir+QLatin1String("/qmldir"); - QFileInfo fi(dir+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); - - if (fi.isFile()) { + QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir); + if (!absoluteFilePath.isEmpty()) { found = true; - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(QLatin1Char('/'))); + url = QUrl::fromLocalFile(absolutePath).toString(); uri = resolvedUri(dir, database); if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) return false; @@ -552,7 +544,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database); if (uri.endsWith(QLatin1Char('/'))) uri.chop(1); - if (QFile::exists(localFileOrQrc)) { + if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) { if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errorString)) return false; } @@ -615,6 +607,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return, QString *errorString) { + Q_ASSERT(typeLoader); QDeclarativeImportedNamespace *s = 0; int slash = type.indexOf('/'); if (slash >= 0) { @@ -636,7 +629,7 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int * } QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower) if (s) { - if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errorString)) + if (s->find(typeLoader, unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errorString)) return true; if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) { // qualified, and only 1 url @@ -653,16 +646,16 @@ QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const Q return set.value(type); } -bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, +bool QDeclarativeImportedNamespace::find(QDeclarativeTypeLoader *typeLoader, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return, QUrl *base, QString *errorString) { bool typeRecursionDetected = false; for (int i=0; i #include #include +#include #include QT_BEGIN_NAMESPACE +/* +Returns the set of QML files in path (qmldir, *.qml, *.js). The caller +is responsible for deleting the returned data. +*/ +static QSet *qmlFilesInDirectory(const QString &path) +{ + QDirIterator dir(path, QDir::Files); + if (!dir.hasNext()) + return 0; + QSet *files = new QSet; + while (dir.hasNext()) { + dir.next(); + QString fileName = dir.fileName(); + if (fileName == QLatin1String("qmldir") + || fileName.endsWith(QLatin1String(".qml")) + || fileName.endsWith(QLatin1String(".js"))) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) || defined(Q_OS_SYMBIAN) + fileName = fileName.toLower(); +#endif + files->insert(fileName); + } + } + return files; +} + + /*! \class QDeclarativeDataBlob \brief The QDeclarativeDataBlob encapsulates a data request that can be issued to a QDeclarativeDataLoader. @@ -715,6 +742,72 @@ QDeclarativeQmldirData *QDeclarativeTypeLoader::getQmldir(const QUrl &url) return qmldirData; } +/*! +Returns the absolute filename of path via a directory cache for files named +"qmldir", "*.qml", "*.js" +Returns a empty string if the path does not exist. +*/ +QString QDeclarativeTypeLoader::absoluteFilePath(const QString &path) +{ + if (path.isEmpty()) + return QString(); + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path); + return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); + } +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) || defined(Q_OS_SYMBIAN) + QString lowPath(path.toLower()); +#else + QString lowPath(path); +#endif + int lastSlash = lowPath.lastIndexOf(QLatin1Char('/')); + QString dirPath = lowPath.left(lastSlash); + + StringSet *fileSet = 0; + QHash::const_iterator it = m_importDirCache.find(dirPath); + if (it == m_importDirCache.end()) { + StringSet *files = qmlFilesInDirectory(path.left(lastSlash)); + m_importDirCache.insert(dirPath, files); + fileSet = files; + } else { + fileSet = *it; + } + if (!fileSet) + return QString(); + + QString absoluteFilePath = fileSet->contains(QString(lowPath.constData()+lastSlash+1, lowPath.length()-lastSlash-1)) ? path : QString(); + if (absoluteFilePath.length() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':')) + absoluteFilePath = QFileInfo(absoluteFilePath).absoluteFilePath(); + + return absoluteFilePath; +} + +/*! +Return a QDeclarativeDirParser for absoluteFilePath. The QDeclarativeDirParser may be cached. +*/ +const QDeclarativeDirParser *QDeclarativeTypeLoader::qmlDirParser(const QString &absoluteFilePath) +{ + QDeclarativeDirParser *qmldirParser; +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) || defined(Q_OS_SYMBIAN) + QString lowPath(absoluteFilePath.toLower()); +#else + QString lowPath(absoluteFilePath); +#endif + QHash::const_iterator it = m_importQmlDirCache.find(lowPath); + if (it == m_importQmlDirCache.end()) { + qmldirParser = new QDeclarativeDirParser; + qmldirParser->setFileSource(absoluteFilePath); + qmldirParser->setUrl(QUrl::fromLocalFile(absoluteFilePath)); + qmldirParser->parse(); + m_importQmlDirCache.insert(lowPath, qmldirParser); + } else { + qmldirParser = *it; + } + + return qmldirParser; +} + void QDeclarativeTypeLoader::clearCache() { for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) @@ -723,16 +816,20 @@ void QDeclarativeTypeLoader::clearCache() (*iter)->release(); for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) (*iter)->release(); + qDeleteAll(m_importDirCache); + qDeleteAll(m_importQmlDirCache); m_typeCache.clear(); m_scriptCache.clear(); m_qmldirCache.clear(); + m_importDirCache.clear(); + m_importQmlDirCache.clear(); } QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options, QDeclarativeTypeLoader *manager) -: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false), +: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_imports(manager), m_typesResolved(false), m_compiledData(0), m_typeLoader(manager) { } diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index 56b663689e..c0dce3e909 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -198,14 +198,23 @@ public: QDeclarativeScriptData *getScript(const QUrl &); QDeclarativeQmldirData *getQmldir(const QUrl &); + + QString absoluteFilePath(const QString &path); + const QDeclarativeDirParser *qmlDirParser(const QString &absoluteFilePath); + private: typedef QHash TypeCache; typedef QHash ScriptCache; typedef QHash QmldirCache; + typedef QSet StringSet; + typedef QHash ImportDirCache; + typedef QHash ImportQmlDirCache; TypeCache m_typeCache; ScriptCache m_scriptCache; QmldirCache m_qmldirCache; + ImportDirCache m_importDirCache; + ImportQmlDirCache m_importQmlDirCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options) -- cgit v1.2.3 From 71bcd941d577097ca99900554386c9f12d4353e3 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 13 Sep 2011 15:33:31 +0200 Subject: Add missing checks for httpReply in QNetworkHttpBackend. httpReply is not guaranteed to be non-null. Adding missing checks for methods that can be called from outside the class. Reviewed-By: Peter Hartmann --- src/network/access/qnetworkaccesshttpbackend.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index abef8ab56a..aa477fbd4d 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -737,7 +737,7 @@ void QNetworkAccessHttpBackend::readFromHttp() void QNetworkAccessHttpBackend::replyFinished() { - if (httpReply->bytesAvailable()) + if (!httpReply || httpReply->bytesAvailable()) // we haven't read everything yet. Wait some more. return; @@ -788,6 +788,9 @@ void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode) void QNetworkAccessHttpBackend::replyHeaderChanged() { + if (!httpReply) + return; + setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, httpReply->isPipeliningUsed()); // reconstruct the HTTP header @@ -1128,7 +1131,7 @@ bool QNetworkAccessHttpBackend::canResume() const return false; // Can only resume if server/resource supports Range header. - if (httpReply->headerField("Accept-Ranges", "none") == "none") + if (!httpReply || httpReply->headerField("Accept-Ranges", "none") == "none") return false; // We only support resuming for byte ranges. -- cgit v1.2.3 From 09cd2f818208a83489fae034b80e6497b7cc83af Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 14 Sep 2011 16:24:30 +1000 Subject: Fix StrictlyEnforceRange with snapOneItem/Row and header behavior, pt 2 Change cf23188de237009136fa1480ab8fd9e3ca364769 changed the positioning of a view with StrictlyEnforceRange, snapOneItem/Row, and a header, such that the view was positioned at the beginning of the header, rather than on the first item. Change f85819fe083ae7c6804c884de68e906d153a6d11 partially fixed the problem. This change handles the case of the header/footer being large enough to cause a snap item not to be found when the view is dragged beyond the first/last item. In this case snap to the currentItem. Change-Id: I08b7e61496a79f71c3b40fafaca985ae90f88503 Task-number: QTTH-1501 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativegridview.cpp | 10 ++++++++++ src/declarative/graphicsitems/qdeclarativelistview.cpp | 12 +++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 5a5b60e9f2..ff88e31a11 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -1081,7 +1081,17 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m tempPosition -= bias; } FxGridItem *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxGridItem *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; if (topItem && bottomItem && strictHighlightRange) { qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent); diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 70be7a7099..6c8e99bc59 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -1324,10 +1324,20 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m tempPosition -= bias; } FxListItem *topItem = snapItemAt(tempPosition+highlightStart); + if (!topItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + topItem = currentItem; + } FxListItem *bottomItem = snapItemAt(tempPosition+highlightEnd); + if (!bottomItem && strictHighlightRange && currentItem) { + // StrictlyEnforceRange always keeps an item in range + updateHighlight(); + bottomItem = currentItem; + } qreal pos; bool isInBounds = -position() > maxExtent && -position() <= minExtent; - if (topItem && isInBounds) { + if (topItem && (isInBounds || strictHighlightRange)) { if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2 && !strictHighlightRange) { pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart; } else { -- cgit v1.2.3 From c4cab7199590cc6b1901334e8ff604cd876fccee Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 14 Sep 2011 14:07:06 +0100 Subject: Prevent crash when cache is changed on the fly Calling QNetworkAccessManager::setCache while there were requests being processed using the existing cache caused crashes due to deleting the old cache invalidating pointers to the cache data streams (QTemporaryFile in case of QNetworkDiskCache). Using pointer to deleted data caused a crash in some cases. It has undefined behaviour because the memory may have been overwritten or decommitted. To fix this, use the deleted signal to notify QNetworkReplyImpl that the cache has been destroyed. It then clears the pointer to the data stream and disables caching. This avoids the crash that previously happened when trying to write to the cache file. Task-number: QT-5252 Reviewed-by: Peter Hartmann --- src/network/access/qnetworkreplyimpl.cpp | 23 +++++++++++++++++++---- src/network/access/qnetworkreplyimpl_p.h | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 8a0a944a54..81cd548bdd 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -446,6 +446,7 @@ bool QNetworkReplyImplPrivate::isCachingEnabled() const void QNetworkReplyImplPrivate::setCachingEnabled(bool enable) { + Q_Q(QNetworkReplyImpl); if (!enable && !cacheEnabled) return; // nothing to do if (enable && cacheEnabled) @@ -468,15 +469,27 @@ void QNetworkReplyImplPrivate::setCachingEnabled(bool enable) networkCache()->remove(url); cacheSaveDevice = 0; cacheEnabled = false; + QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed())); } } +void QNetworkReplyImplPrivate::_q_cacheDestroyed() +{ + //destruction of cache invalidates cacheSaveDevice + cacheSaveDevice = 0; + cacheEnabled = false; +} + void QNetworkReplyImplPrivate::completeCacheSave() { - if (cacheEnabled && errorCode != QNetworkReplyImpl::NoError) { - networkCache()->remove(url); - } else if (cacheEnabled && cacheSaveDevice) { - networkCache()->insert(cacheSaveDevice); + Q_Q(QNetworkReplyImpl); + if (cacheEnabled) { + if (errorCode != QNetworkReplyImpl::NoError) { + networkCache()->remove(url); + } else if (cacheSaveDevice) { + networkCache()->insert(cacheSaveDevice); + } + QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed())); } cacheSaveDevice = 0; cacheEnabled = false; @@ -536,6 +549,8 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice() networkCache()->remove(url); cacheSaveDevice = 0; cacheEnabled = false; + } else { + q->connect(networkCache(), SIGNAL(destroyed()), SLOT(_q_cacheDestroyed())); } } diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 31da297b79..0e4ff8f5ce 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -103,6 +103,7 @@ public: Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) #endif + Q_PRIVATE_SLOT(d_func(), void _q_cacheDestroyed()) }; class QNetworkReplyImplPrivate: public QNetworkReplyPrivate @@ -139,6 +140,7 @@ public: void _q_networkSessionConnected(); void _q_networkSessionFailed(); #endif + void _q_cacheDestroyed(); void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); -- cgit v1.2.3 From 5571dbea919d1f122e7331cb0214e584c89efcb9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 16:47:39 +0000 Subject: Fix RConnection handle leak in symbian bearer plugin The implementation was opening RConnection handles on top of previous instances, and not closing RConnection handles. Both of these cause a resource leak in the socket server which cannot clean up the connection until the Qt process has exited. After a lot of this (which could be triggered by the QNetworkReply auto test), the socket server may run out of memory resulting in all socket operations failing. Reviewed-by: Markus Goetz (cherry picked from commit f5e7b6c64caa67bf11fa9754114d686da73b22d6) --- .../bearer/symbian/qnetworksession_impl.cpp | 97 +++++++++------------- src/plugins/bearer/symbian/qnetworksession_impl.h | 1 + 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 5639c4f43e..fc6e1413f3 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -89,33 +89,43 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) TRAP_IGNORE(iConnectionMonitor.ConnectL()); } -QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +void QNetworkSessionPrivateImpl::closeHandles() { - isOpen = false; - isOpening = false; - // Cancel Connection Progress Notifications first. - // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start() + // Note: ConnectionNotifier must be destroyed before RConnection::Close() // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification() delete ipConnectionNotifier; ipConnectionNotifier = NULL; #ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } + // mobility monitor must be deleted before RConnection is closed + delete iMobility; + iMobility = NULL; #endif - // Cancel possible RConnection::Start() + // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress Cancel(); - iSocketServ.Close(); + //close any open connection (note Close twice is safe in case Cancel did it above) + iConnection.Close(); // Close global 'Open C' RConnection // Clears also possible unsetdefaultif() flags. setdefaultif(0); iConnectionMonitor.Close(); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) + << " - handles closed"; +#endif + iSocketServ.Close(); +} + +QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +{ + isOpen = false; + isOpening = false; + + closeHandles(); iOpenCLibrary.Close(); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) @@ -166,7 +176,7 @@ void QNetworkSessionPrivateImpl::configurationAdded(QNetworkConfigurationPrivate #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "configurationAdded IAP: " - << toSymbianConfig(privateConfiguration(config))->numericIdentifier(); + << toSymbianConfig(config)->numericIdentifier(); #endif syncStateWithInterface(); @@ -372,7 +382,8 @@ void QNetworkSessionPrivateImpl::open() syncStateWithInterface(); return; } - + + Q_ASSERT(!iConnection.SubSessionHandle()); error = iConnection.Open(iSocketServ); if (error != KErrNone) { // Could not open RConnection @@ -414,8 +425,8 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - iConnection.Start(pref, iStatus); if (!IsActive()) { + iConnection.Start(pref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -442,8 +453,8 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - iConnection.Start(snapPref, iStatus); if (!IsActive()) { + iConnection.Start(snapPref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -453,8 +464,8 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - iConnection.Start(iStatus); if (!IsActive()) { + iConnection.Start(iStatus); SetActive(); } newState(QNetworkSession::Connecting); @@ -465,9 +476,7 @@ void QNetworkSessionPrivateImpl::open() isOpening = false; iError = QNetworkSession::UnknownSessionError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); syncStateWithInterface(); } } @@ -521,21 +530,10 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) serviceConfig = QNetworkConfiguration(); -#ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } -#endif + closeHandles(); - if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) { - ipConnectionNotifier->StopNotifications(); - // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate - iHandleStateNotificationsFromManager = true; - } - - Cancel(); // closes iConnection - iSocketServ.Close(); + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; // Close global 'Open C' RConnection. If OpenC supports, // close the defaultif for good to avoid difficult timing @@ -759,12 +757,14 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo* } } -void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) +void QNetworkSessionPrivateImpl::Error(TInt aError) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "roaming Error() occurred, isOpen is: " << isOpen; + << "roaming Error() occurred" << aError << ", isOpen is: " << isOpen; #endif + if (aError == KErrCancel) + return; //avoid recursive deletion if (isOpen) { isOpen = false; isOpening = false; @@ -772,10 +772,7 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::RoamingError; emit QNetworkSessionPrivate::error(iError); - Cancel(); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); QT_TRY { syncStateWithInterface(); // In some cases IAP is still in Connected state when @@ -1102,18 +1099,13 @@ void QNetworkSessionPrivateImpl::RunL() isOpening = false; iError = QNetworkSession::UnknownSessionError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); if (!newActiveConfig.isValid()) { // No valid configuration, bail out. // Status updates from QNCM won't be received correctly // because there is no configuration to associate them with so transit here. - iConnection.Close(); newState(QNetworkSession::Closing); newState(QNetworkSession::Disconnected); - } else { - Cancel(); } QT_TRYCATCH_LEAVING(syncStateWithInterface()); return; @@ -1156,10 +1148,7 @@ void QNetworkSessionPrivateImpl::RunL() serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::InvalidConfigurationError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; case KErrCancel: // Connection attempt cancelled @@ -1178,10 +1167,7 @@ void QNetworkSessionPrivateImpl::RunL() iError = QNetworkSession::UnknownSessionError; } QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; } @@ -1273,10 +1259,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::SessionAbortedError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate iHandleStateNotificationsFromManager = true; emitSessionClosed = true; // Emit SessionClosed after state change has been reported diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 774b988f59..a597812796 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -149,6 +149,7 @@ private: bool easyWlanTrueIapId(TUint32 &trueIapId) const; #endif + void closeHandles(); private: // data SymbianEngine *engine; -- cgit v1.2.3 From ada33b11092f278ae4f1280a6da07ffd151a31b6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 17:22:32 +0000 Subject: Refactor dangerous multiple inheritance QObject and CBase both expect to be the root class of the object hierarchy so it can cause problems if they are used in multiple inheritance. Refactored the CActive used for starting RConnection into a helper class. Reviewed-by: Markus Goetz (cherry picked from commit 5a6365f14006ab50854e41a5927645c7e9966756) --- .../bearer/symbian/qnetworksession_impl.cpp | 82 ++++++++++++++++------ src/plugins/bearer/symbian/qnetworksession_impl.h | 29 ++++++-- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index fc6e1413f3..5514511a77 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -61,13 +61,12 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) -: CActive(CActive::EPriorityUserInput), engine(engine), - iDynamicUnSetdefaultif(0), ipConnectionNotifier(0), +: engine(engine), + ipConnectionNotifier(0), ipConnectionStarter(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false), isOpening(false) { - CActiveScheduler::Add(this); #ifdef SNAP_FUNCTIONALITY_AVAILABLE iMobility = NULL; @@ -104,7 +103,8 @@ void QNetworkSessionPrivateImpl::closeHandles() #endif // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress - Cancel(); + delete ipConnectionStarter; + ipConnectionStarter = 0; //close any open connection (note Close twice is safe in case Cancel did it above) iConnection.Close(); @@ -425,9 +425,9 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(pref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(pref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -453,9 +453,9 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(snapPref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(snapPref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -464,9 +464,9 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - if (!IsActive()) { - iConnection.Start(iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(); } newState(QNetworkSession::Connecting); } @@ -1066,13 +1066,14 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia return publicConfig; } -void QNetworkSessionPrivateImpl::RunL() +void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "RConnection::RunL with status code: " << iStatus.Int(); + << "RConnection::Start completed with status code: " << statusCode; #endif - TInt statusCode = iStatus.Int(); + delete ipConnectionStarter; + ipConnectionStarter = 0; switch (statusCode) { case KErrNone: // Connection created successfully @@ -1173,11 +1174,6 @@ void QNetworkSessionPrivateImpl::RunL() } } -void QNetworkSessionPrivateImpl::DoCancel() -{ - iConnection.Close(); -} - // Enters newState if feasible according to current state. // AccessPointId may be given as parameter. If it is zero, state-change is assumed to // concern this session's configuration. If non-zero, the configuration is looked up @@ -1566,6 +1562,50 @@ void ConnectionProgressNotifier::RunL() } } +ConnectionStarter::ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection) + : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) +{ + CActiveScheduler::Add(this); +} + +ConnectionStarter::~ConnectionStarter() +{ + Cancel(); +} + +void ConnectionStarter::Start() +{ + if (!IsActive()) { + iConnection.Start(iStatus); + SetActive(); + } +} + +void ConnectionStarter::Start(TConnPref &pref) +{ + if (!IsActive()) { + iConnection.Start(pref, iStatus); + SetActive(); + } +} + +void ConnectionStarter::RunL() +{ + iOwner.ConnectionStartComplete(iStatus.Int()); + //note owner deletes on callback +} + +TInt ConnectionStarter::RunError(TInt err) +{ + qWarning() << "ConnectionStarter::RunError" << err; + return KErrNone; +} + +void ConnectionStarter::DoCancel() +{ + iConnection.Close(); +} + QT_END_NAMESPACE #endif //QT_NO_BEARERMANAGEMENT diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index a597812796..a5a4f8791e 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -68,11 +68,12 @@ QT_BEGIN_NAMESPACE class ConnectionProgressNotifier; +class ConnectionStarter; class SymbianEngine; typedef void (*TOpenCUnSetdefaultifFunction)(); -class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive +class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate #ifdef SNAP_FUNCTIONALITY_AVAILABLE , public MMobilityProtocolResp #endif @@ -125,7 +126,7 @@ public: // From MMobilityProtocolResp #endif protected: // From CActive - void RunL(); + void ConnectionStartComplete(TInt statusCode); void DoCancel(); private Q_SLOTS: @@ -167,12 +168,13 @@ private: // data mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; ConnectionProgressNotifier* ipConnectionNotifier; - + ConnectionStarter* ipConnectionStarter; + bool iHandleStateNotificationsFromManager; bool iFirstSync; bool iStoppedByUser; bool iClosedByUser; - + #ifdef SNAP_FUNCTIONALITY_AVAILABLE CActiveCommsMobilityApiExt* iMobility; #endif @@ -190,6 +192,7 @@ private: // data bool isOpening; friend class ConnectionProgressNotifier; + friend class ConnectionStarter; }; class ConnectionProgressNotifier : public CActive @@ -212,6 +215,24 @@ private: // Data }; +class ConnectionStarter : public CActive +{ +public: + ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection); + ~ConnectionStarter(); + + void Start(); + void Start(TConnPref &pref); +protected: + void RunL(); + TInt RunError(TInt err); + void DoCancel(); + +private: // Data + QNetworkSessionPrivateImpl &iOwner; + RConnection& iConnection; +}; + QT_END_NAMESPACE #endif //QNETWORKSESSION_IMPL_H -- cgit v1.2.3 From d04f37fa73d2fbb78dd85a02e9d3180ed4ddbdab Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 19 Sep 2011 14:34:04 +0100 Subject: symbian bearer: fix tst_qnetworksession test failures Symbian is not reporting the expected KLinkLayerClosed event on the last RConnection handle. Instead, it reports the event KConfigDaemonFinishedDeregistrationStop, which indicates the nif plugin is being destroyed (this is followed by unload events) To fix, this event is treated the same as a link down event, and results in the state change to disconnected. Either there has been a behaviour change in the platform, or the test was previously run with another user of the API running in the background (e.g. WLAN wizard, connection monitor) which prevented the unload. Task-Number: QTBUG-21382 Reviewed-By: mread (cherry picked from commit a0ad54acd33873316908080f432768fdf3e3bfc2) --- src/plugins/bearer/symbian/qnetworksession_impl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 5514511a77..29f06374a3 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1438,6 +1438,9 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne newState(QNetworkSession::Closing,accessPointId); break; + // Connection stopped + case KConfigDaemonFinishedDeregistrationStop: //this comes if this is the last session, instead of KLinkLayerClosed + case KConfigDaemonFinishedDeregistrationPreserve: // Connection closed case KConnectionClosed: case KLinkLayerClosed: -- cgit v1.2.3 From fa717293080c9d00b02028bebece1935aef6e093 Mon Sep 17 00:00:00 2001 From: aavit Date: Fri, 25 Mar 2011 13:50:41 +0100 Subject: Avoid runtime warning about interlace handling from libpng 1.5 Task-number: QTBUG-13298, QTBUG-21408 (cherry picked from commit c8851ce8e109fb6b403ae80036d9f319f1b69d7a) --- src/gui/image/qpnghandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 7f5cbe8e1b..c0cebf908b 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -217,6 +217,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre png_colorp palette = 0; int num_palette; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); + png_set_interlace_handling(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale -- cgit v1.2.3 From 849694e4cb9d010517b54b2b30035485487b0e12 Mon Sep 17 00:00:00 2001 From: mread Date: Wed, 21 Sep 2011 11:35:14 +0100 Subject: QML import path puts Qt dirs in correct Symbian order The QML import path contains an entry for the standard import location on each drive on Symbian. These were being ordered so that Z:, the ROM drive, was listed first. In fact the drive order was the reverse of the normal Symbian drive search order. This had the effect that upgraded versions of QML imports installed on the device were generally ignored for older ROM based versions. The import path has now been changed to match the normal Symbian drive search order. This will make it more likely for upgraded QML imports to be picked up and used. Task-number: QTBUG-21409 Reviewed-by: Shane Kearns Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeimport.cpp | 10 ++++++++- .../tst_qdeclarativemoduleplugin.cpp | 25 ++++++++++++++++++++++ .../tst_qdeclarativemoduleplugin.pro | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 6e0b348aa8..c25207a1fc 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -733,8 +734,12 @@ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) } RFs& fs = qt_s60GetRFs(); TPtrC tempPathPtr(reinterpret_cast (tempPath.constData())); + // Symbian searches should start from Y:. Fix start drive otherwise TFindFile starts from the session drive + _LIT(KStartDir, "Y:"); + TFileName dirPath(KStartDir); + dirPath.Append(tempPathPtr); TFindFile finder(fs); - TInt err = finder.FindByDir(tempPathPtr, tempPathPtr); + TInt err = finder.FindByDir(tempPathPtr, dirPath); while (err == KErrNone) { QString foundDir(reinterpret_cast(finder.File().Ptr()), finder.File().Length()); @@ -742,6 +747,9 @@ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) addImportPath(foundDir); err = finder.Find(); } + // TFindFile found the directories in the order we want, but addImportPath reverses it. + // Reverse the order again to get it right. + QAlgorithmsPrivate::qReverse(fileImportPath.begin(), fileImportPath.end()); } else { addImportPath(installImportsPath); } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 2cc297171c..96bea68fca 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "../shared/testhttpserver.h" #include "../../../shared/util.h" @@ -70,6 +71,7 @@ private slots: void remoteImportWithUnquotedUri(); void versionNotInstalled(); void versionNotInstalled_data(); + void importPath(); }; #ifdef Q_OS_SYMBIAN @@ -308,6 +310,29 @@ void tst_qdeclarativemoduleplugin::versionNotInstalled() VERIFY_ERRORS(errorFile.toLatin1().constData()); } +void tst_qdeclarativemoduleplugin::importPath() +{ +#ifndef Q_OS_SYMBIAN + QSKIP("Import path order testing for Symbian only", SkipAll); +#else + QDeclarativeEngine engine; + QStringList imports = engine.importPathList(); + QString installImportsPath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::ImportsPath)); + QString driveOrder(QLatin1String("ZABCDEFGHIJKLMNOPQRSTUVWXY")); + int lastOrder = 30; + foreach(QString import, imports) + { + if (import.endsWith(installImportsPath)) + { + int order = driveOrder.indexOf(import[0]); + QVERIFY(order < lastOrder); + lastOrder = order; + } + } + QVERIFY(lastOrder != 30); +#endif +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro index a92d3a256f..2716a8bdf5 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro @@ -9,7 +9,7 @@ CONFIG -= app_bundle symbian: { importFiles.sources = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } -- cgit v1.2.3 From c3669d24b498aa0661ade5ed7465260788f629b5 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Thu, 22 Sep 2011 11:23:23 +0300 Subject: QLineControl: selectedTextChanged() signal is omitted in some cases QLineControl does not emit selectionChanged() signal when selection is changed due to handling of input method query. As a fix, the signal is emitted when internal values for selection end and beginning are changed in processInputMethodEvent(). Additionally, added deselect() test case for both QDeclarativeTextEdit and QDeclarativeTextInput to help out autotesting of text selections. Note that there are some differences in the QLineControl and QTextControl implementations. This causes the different signal counts even if the test steps are similar. Task-number: QTBUG-21429 Reviewed-by: Miikka Heikkinen --- src/gui/widgets/qlinecontrol.cpp | 4 + .../tst_qdeclarativetextedit.cpp | 115 ++++++++++++++++++++ .../tst_qdeclarativetextinput.cpp | 117 ++++++++++++++++++++- 3 files changed, 235 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 198bc045aa..c5232ad749 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -447,6 +447,8 @@ void QLineControl::moveCursor(int pos, bool mark) void QLineControl::processInputMethodEvent(QInputMethodEvent *event) { int priorState = 0; + int originalSelectionStart = m_selstart; + int originalSelectionEnd = m_selend; bool isGettingInput = !event->commitString().isEmpty() || event->preeditString() != preeditAreaText() || event->replacementLength() > 0; @@ -525,6 +527,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) } m_textLayout.setAdditionalFormats(formats); updateDisplayText(/*force*/ true); + if (originalSelectionStart != m_selstart || originalSelectionEnd != m_selend) + emit selectionChanged(); if (cursorPositionChanged) emitCursorPositionChanged(); else if (m_preeditCursor != oldPreeditCursor) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index fde0588338..b6df30847b 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -154,6 +154,7 @@ private slots: void inputContextMouseHandler(); void inputMethodComposing(); void cursorRectangleSize(); + void deselect(); private: void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0); @@ -2655,6 +2656,120 @@ void tst_qdeclarativetextedit::cursorRectangleSize() QCOMPARE(microFocusFromScene.size(), cursorRect.size()); QCOMPARE(microFocusFromApp.size(), cursorRect.size()); } + +void tst_qdeclarativetextedit::deselect() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/CursorRect.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextEdit *textEdit = qobject_cast(canvas->rootObject()); + QVERIFY(textEdit != 0); + + textEdit->setText("Select"); + + QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); + QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); + QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged())); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 1); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 1); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + textEdit->deselect(); + + QCOMPARE(selectionStartSpy.count(), 2); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 2); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 6); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 3); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + QKeyEvent leftArrowPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QKeyEvent leftArrowRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier); + QApplication::sendEvent(canvas, &leftArrowPress); + QApplication::sendEvent(canvas, &leftArrowRelese); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 2); + QCOMPARE(selectionSpy.count(), 4); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 5); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 3); + QCOMPARE(selectionSpy.count(), 5); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + QList attributes; + attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); + QInputMethodEvent event(QLatin1String(""), attributes); + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 4); + QCOMPARE(selectionSpy.count(), 6); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 0); + + textEdit->setCursorPosition(1); + + QCOMPARE(selectionStartSpy.count(), 5); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectionSpy.count(), 6); + + QKeyEvent leftArrowShiftPress(QEvent::KeyPress, Qt::Key_Left, Qt::ShiftModifier); + QKeyEvent leftArrowShiftRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::ShiftModifier); + QApplication::sendEvent(canvas, &leftArrowShiftPress); + QApplication::sendEvent(canvas, &leftArrowShiftRelese); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectionSpy.count(), 7); + QCOMPARE(textEdit->selectionStart(), 0); + QCOMPARE(textEdit->selectionEnd(), 1); + QCOMPARE(textEdit->selectedText(), QLatin1String("S")); + QCOMPARE(textEdit->cursorPosition(), 0); + + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 6); + QCOMPARE(selectionSpy.count(), 8); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 0); +} QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index bb895bfbbf..b077670fcd 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -147,6 +147,7 @@ private slots: void inputContextMouseHandler(); void inputMethodComposing(); void cursorRectangleSize(); + void deselect(); private: void simulateKey(QDeclarativeView *, int key); @@ -2367,7 +2368,7 @@ void tst_qdeclarativetextinput::openInputPanelOnFocus() QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); // input method should not be enabled - // if TextEdit is read only. + // if TextInput is read only. input.setReadOnly(true); ic.openInputPanelReceived = false; input.setFocus(true); @@ -2815,6 +2816,120 @@ void tst_qdeclarativetextinput::cursorRectangleSize() QCOMPARE(microFocusFromApp.size(), cursorRect.size()); } +void tst_qdeclarativetextinput::deselect() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextInput *textInput = qobject_cast(canvas->rootObject()); + QVERIFY(textInput != 0); + + textInput->setText("Select"); + + QSignalSpy selectionStartSpy(textInput, SIGNAL(selectionStartChanged())); + QSignalSpy selectionEndSpy(textInput, SIGNAL(selectionEndChanged())); + QSignalSpy selectedTextSpy(textInput, SIGNAL(selectedTextChanged())); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 1); + QCOMPARE(selectionEndSpy.count(), 0); + QCOMPARE(selectedTextSpy.count(), 1); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + textInput->deselect(); + + QCOMPARE(selectionStartSpy.count(), 2); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectedTextSpy.count(), 2); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 6); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectedTextSpy.count(), 3); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + QKeyEvent leftArrowPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QKeyEvent leftArrowRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier); + QApplication::sendEvent(canvas, &leftArrowPress); + QApplication::sendEvent(canvas, &leftArrowRelese); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 2); + QCOMPARE(selectedTextSpy.count(), 4); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 5); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 3); + QCOMPARE(selectedTextSpy.count(), 5); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + QList attributes; + attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); + QInputMethodEvent event(QLatin1String(""), attributes); + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 5); + QCOMPARE(selectionEndSpy.count(), 4); + QCOMPARE(selectedTextSpy.count(), 6); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 0); + + textInput->setCursorPosition(1); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectedTextSpy.count(), 6); + + QKeyEvent leftArrowShiftPress(QEvent::KeyPress, Qt::Key_Left, Qt::ShiftModifier); + QKeyEvent leftArrowShiftRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::ShiftModifier); + QApplication::sendEvent(canvas, &leftArrowShiftPress); + QApplication::sendEvent(canvas, &leftArrowShiftRelese); + + QCOMPARE(selectionStartSpy.count(), 7); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectedTextSpy.count(), 7); + QCOMPARE(textInput->selectionStart(), 0); + QCOMPARE(textInput->selectionEnd(), 1); + QCOMPARE(textInput->selectedText(), QLatin1String("S")); + QCOMPARE(textInput->cursorPosition(), 0); + + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 8); + QCOMPARE(selectionEndSpy.count(), 6); + QCOMPARE(selectedTextSpy.count(), 8); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 0); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v1.2.3 From 6f6493747121db428a71d494c8cb3f04a0292279 Mon Sep 17 00:00:00 2001 From: Viktor Kolesnyk Date: Mon, 5 Sep 2011 15:08:23 +0300 Subject: Incorrect 'break' in switch-case was replaced by 'return' --- src/gui/kernel/qcursor_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index cef83f5a1b..a68472c584 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -477,7 +477,7 @@ void QCursorData::update() QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape); hcurs = create32BitCursor(pixmap, hx, hy); } - break; + return; default: qWarning("QCursor::update: Invalid cursor shape %d", cshape); return; -- cgit v1.2.3 From 872872f3d3f0d89010d3a196b70e8445a08d0784 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Fri, 23 Sep 2011 07:47:24 +0300 Subject: Fix to QtOpenGL crash Exiting the native video recorder on Symbian and going back to Qt app which runs on opengl graphics system crashed on some devices because there was not enough GPU memory and also because low GPU mem device environment detection was flawed. This patch fixes 32MB GPU memory detection and adds wait/retrial to EGL surface creation if it fails. Task-number: QTBUG-21499 Reviewed-by: Laszlo Agocs --- src/gui/egl/qegl.cpp | 32 ++++++++ src/gui/painting/qgraphicssystemex_symbian.cpp | 105 +++++++++++++++++++++---- 2 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 4db4a6aa1f..02adef8142 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -684,6 +684,37 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr else props = 0; EGLSurface surf; +#ifdef Q_OS_SYMBIAN + // On Symbian there might be situations (especially on 32MB GPU devices) + // where Qt is trying to create EGL surface while some other application + // is still holding all available GPU memory but is about to release it + // soon. For an example when exiting native video recorder and going back to + // Qt application behind it. Video stack tear down takes some time and Qt + // app might be too quick in reserving its EGL surface and thus running out + // of GPU memory right away. So if EGL surface creation fails due to bad + // alloc, let's try recreating it four times within ~1 second if needed. + // This strategy gives some time for video recorder to tear down its stack + // and a chance to Qt for creating a valid surface. + int tries = 4; + while(tries--) { + if (devType == QInternal::Widget) + surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); + else + surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props); + if (surf == EGL_NO_SURFACE) { + EGLint error = eglGetError(); + if (error == EGL_BAD_ALLOC) { + if (tries) { + User::After(1000 * 250); // 250ms + continue; + } + } + qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", error); + } else { + break; + } + } +#else if (devType == QInternal::Widget) surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); else @@ -691,6 +722,7 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr if (surf == EGL_NO_SURFACE) { qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); } +#endif return surf; } #endif diff --git a/src/gui/painting/qgraphicssystemex_symbian.cpp b/src/gui/painting/qgraphicssystemex_symbian.cpp index 4469704668..46731d8474 100644 --- a/src/gui/painting/qgraphicssystemex_symbian.cpp +++ b/src/gui/painting/qgraphicssystemex_symbian.cpp @@ -46,31 +46,106 @@ #include +#ifdef Q_SYMBIAN_SUPPORTS_SURFACES +#include "private/qegl_p.h" +#endif + QT_BEGIN_NAMESPACE static bool bcm2727Initialized = false; static bool bcm2727 = false; +typedef EGLBoolean (*NOK_resource_profiling)(EGLDisplay, EGLint, EGLint*, EGLint, EGLint*); +#define EGL_PROF_TOTAL_MEMORY_NOK 0x3070 + +// Detect if Qt is running on BCM2727 chip. +// BCM2727 is a special case on Symbian because +// it has only 32MB GPU memory which exposes +// significant limitations to hw accelerated UI. bool QSymbianGraphicsSystemEx::hasBCM2727() { if (bcm2727Initialized) return bcm2727; - const TUid KIvePropertyCat = {0x2726beef}; - enum TIvePropertyChipType { - EVCBCM2727B1 = 0x00000000, - EVCBCM2763A0 = 0x04000100, - EVCBCM2763B0 = 0x04000102, - EVCBCM2763C0 = 0x04000103, - EVCBCM2763C1 = 0x04000104, - EVCBCMUnknown = 0x7fffffff - }; - - TInt chipType = EVCBCMUnknown; - if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) { - if (chipType == EVCBCM2727B1) +#ifdef Q_SYMBIAN_SUPPORTS_SURFACES + EGLDisplay display = QEgl::display(); +#if 1 + // Hacky but fast ~0ms. + const char* vendor = eglQueryString(display, EGL_VENDOR); + if (strstr(vendor, "Broadcom")) { + const TUid KIvePropertyCat = {0x2726beef}; + enum TIvePropertyChipType { + EVCBCM2727B1 = 0x00000000, + EVCBCM2763A0 = 0x04000100, + EVCBCM2763B0 = 0x04000102, + EVCBCM2763C0 = 0x04000103, + EVCBCM2763C1 = 0x04000104, + EVCBCMUnknown = 0x7fffffff + }; + + // Broadcom driver publishes KIvePropertyCat PS key on + // devices which are running on BCM2727 chip and post Anna Symbian. + TInt chipType = EVCBCMUnknown; + if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) { + if (chipType == EVCBCM2727B1) + bcm2727 = true; + } else if (QSysInfo::symbianVersion() <= QSysInfo::SV_SF_3) { + // Device is running on Symbian Anna or older Symbian^3 in which + // KIvePropertyCat is not published. These ones are always 32MB devices. + bcm2727 = true; + } else { + // We have some other Broadcom chip on post Anna Symbian. + // Should have > 32MB GPU memory. + } + } +#else + // Fool proof but takes 15-20ms and we don't want this delay on app startup... + + // All devices with <= 32MB GPU memory should be + // dealed in similar manner to BCM2727 + // So let's query max GPU memory amount. + NOK_resource_profiling eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK"); + if (eglQueryProfilingData) { + EGLint dataCount; + eglQueryProfilingData(display, + EGL_PROF_QUERY_GLOBAL_BIT_NOK | + EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, + NULL, + 0, + (EGLint*)&dataCount); + + // Allocate room for the profiling data + EGLint* profData = (EGLint*)malloc(dataCount * sizeof(EGLint)); + memset(profData,0,dataCount * sizeof(EGLint)); + + // Retrieve the profiling data + eglQueryProfilingData(display, + EGL_PROF_QUERY_GLOBAL_BIT_NOK | + EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, + profData, + dataCount, + (EGLint*)&dataCount); + + int totalMemory; + EGLint i = 0; + while (profData && i < dataCount) { + switch (profData[i++]) { + case EGL_PROF_TOTAL_MEMORY_NOK: + totalMemory = profData[i++]; + break; + default: + i++; + } + } + + // ok, hasBCM2727() naming is a bit misleading but Qt must + // behave the same on all chips like BCM2727 (<= 32MB GPU memory) + // and our code (and others) are already using this function. + if (totalMemory <= 33554432) bcm2727 = true; } +#endif +#endif // Q_SYMBIAN_SUPPORTS_SURFACES bcm2727Initialized = true; @@ -80,7 +155,9 @@ bool QSymbianGraphicsSystemEx::hasBCM2727() void QSymbianGraphicsSystemEx::releaseCachedGpuResources() { // Do nothing here - // This is implemented in graphics system specific plugin + + // This virtual function should be implemented in graphics system specific + // plugin } void QSymbianGraphicsSystemEx::releaseAllGpuResources() -- cgit v1.2.3 From e90cffc2c5f313cc813d0a21a1d9d0afe8d0ea7a Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Tue, 27 Sep 2011 08:17:25 +0300 Subject: Crash in QDeclarativeCompiler::indexOfProperty In QDeclarativePropertyCache, plain integer bitfield overrideIndex is initialized with -1 in class constructor. Unfortunately, ARM compiler treats bitfields as unsigned, unless explicitly defined as signed [1]. Therefore, overrideIndex actually gets initial value of 2147483647, which causes array operations done with the index to fail. As a fix, define overrideIndex as signed int bitfield. [1] http://www.keil.com/support/man/docs/armccref/armccref_Babjddhe.htm Under bitfields/Note: "A plain bitfield, declared without either signed or unsigned qualifiers, is treated as unsigned" Task-number: QT-5285 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativepropertycache_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 581f5197f4..c648d25cb7 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -111,7 +111,7 @@ public: int relatedIndex; // When IsFunction }; uint overrideIndexIsProperty : 1; - int overrideIndex : 31; + signed int overrideIndex : 31; int revision; int metaObjectOffset; -- cgit v1.2.3 From 24855ef3983fa5d87b3e3a06fe891a769e670ae5 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 31 Aug 2011 15:52:25 +0100 Subject: Always recreate backing store when TLW transparency changes When using either the opengl or openvg graphics system on Symbian, if a TLW is made transparent, the widget switches to using raster rendering, because EGL surface transparency is currently not supported by the platform. This patch enables the reverse to occur: when the widget is subsequently made opaque, rendering switches back to using GL/VG. Task-number: QTBUG-21211 Reviewed-by: Jani Hautakangas Reviewed-by: Laszlo Agocs Reviewed-by: Sami Merila --- src/gui/kernel/qwidget.cpp | 24 ++++++++++++---- src/gui/kernel/qwidget_p.h | 1 + src/gui/kernel/qwidget_s60.cpp | 58 ++++++++++++++++++++++++-------------- tests/auto/qwidget/tst_qwidget.cpp | 45 ++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 27 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 8e8266cd4a..bda088550c 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -2238,10 +2238,16 @@ void QWidgetPrivate::updateIsOpaque() #endif #ifdef Q_WS_S60 - if (q->windowType() == Qt::Dialog && q->testAttribute(Qt::WA_TranslucentBackground) - && S60->avkonComponentsSupportTransparency) { - setOpaque(false); - return; + if (q->testAttribute(Qt::WA_TranslucentBackground)) { + if (q->windowType() & Qt::Dialog || q->windowType() & Qt::Popup) { + if (S60->avkonComponentsSupportTransparency) { + setOpaque(false); + return; + } + } else { + setOpaque(false); + return; + } } #endif @@ -2261,11 +2267,16 @@ void QWidgetPrivate::updateIsOpaque() } if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) { +#ifdef Q_WS_S60 + setOpaque(true); + return; +#else const QBrush &windowBrush = q->palette().brush(QPalette::Window); if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) { setOpaque(true); return; } +#endif } setOpaque(false); } @@ -10845,11 +10856,14 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } break; case Qt::WA_TranslucentBackground: +#if defined(Q_OS_SYMBIAN) + setAttribute(Qt::WA_NoSystemBackground, on); +#else if (on) { setAttribute(Qt::WA_NoSystemBackground); d->updateIsTranslucent(); } - +#endif break; case Qt::WA_AcceptTouchEvents: #if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index e30497c59b..caa64549cd 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -228,6 +228,7 @@ struct QTLWExtra { uint inExpose : 1; // Prevents drawing recursion uint nativeWindowTransparencyEnabled : 1; // Tracks native window transparency uint forcedToRaster : 1; + uint noSystemRotationDisabled : 1; #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index e80ecedc16..e12dfa73e5 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -820,19 +820,12 @@ void QWidgetPrivate::setConstraints_sys() void QWidgetPrivate::s60UpdateIsOpaque() { Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) return; - const bool writeAlpha = extraData()->nativePaintMode == QWExtra::BlitWriteAlpha; - if (!q->testAttribute(Qt::WA_TranslucentBackground) && !writeAlpha) - return; const bool requireAlphaChannel = !isOpaque || writeAlpha; - createTLExtra(); - RWindow *const window = static_cast(q->effectiveWinId()->DrawableWindow()); - #ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces && !extra->topextra->forcedToRaster) { @@ -841,25 +834,47 @@ void QWidgetPrivate::s60UpdateIsOpaque() return; } #endif + const bool recreateBackingStore = extra->topextra->backingStore.data() && ( + QApplicationPrivate::graphics_system_name == QLatin1String("openvg") || + QApplicationPrivate::graphics_system_name == QLatin1String("opengl") + ); if (requireAlphaChannel) { - const TDisplayMode displayMode = static_cast(window->SetRequiredDisplayMode(EColor16MA)); - if (window->SetTransparencyAlphaChannel() == KErrNone) { + window->SetRequiredDisplayMode(EColor16MA); + if (window->SetTransparencyAlphaChannel() == KErrNone) window->SetBackgroundColor(TRgb(255, 255, 255, 0)); - extra->topextra->nativeWindowTransparencyEnabled = 1; - if (extra->topextra->backingStore.data() && ( - QApplicationPrivate::graphics_system_name == QLatin1String("openvg") - || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"))) { - // Semi-transparent EGL surfaces aren't supported. We need to - // recreate backing store to get translucent surface (raster surface). - extra->topextra->backingStore.create(q); - extra->topextra->backingStore.registerWidget(q); - // FixNativeOrientation() will not work without an EGL surface. + } else { + if (recreateBackingStore) { + // Clear the UI surface to ensure that the EGL surface content is visible + CWsScreenDevice *screenDevice = S60->screenDevice(q); + QScopedPointer gc(new CWindowGc(screenDevice)); + const int err = gc->Construct(); + if (!err) { + gc->Activate(*window); + window->BeginRedraw(); + gc->SetDrawMode(CWindowGc::EDrawModeWriteAlpha); + gc->SetBrushColor(TRgb(0, 0, 0, 0)); + gc->Clear(TRect(0, 0, q->width(), q->height())); + window->EndRedraw(); + } + } + if (extra->topextra->nativeWindowTransparencyEnabled) + window->SetTransparentRegion(TRegionFix<1>()); + } + extra->topextra->nativeWindowTransparencyEnabled = requireAlphaChannel; + if (recreateBackingStore) { + extra->topextra->backingStore.create(q); + extra->topextra->backingStore.registerWidget(q); + bool noSystemRotationDisabled = false; + if (requireAlphaChannel) { + if (q->testAttribute(Qt::WA_SymbianNoSystemRotation)) { + // FixNativeOrientation() will not work without an EGL surface q->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + noSystemRotationDisabled = true; } + } else { + q->setAttribute(Qt::WA_SymbianNoSystemRotation, extra->topextra->noSystemRotationDisabled); } - } else if (extra->topextra->nativeWindowTransparencyEnabled) { - window->SetTransparentRegion(TRegionFix<1>()); - extra->topextra->nativeWindowTransparencyEnabled = 0; + extra->topextra->noSystemRotationDisabled = noSystemRotationDisabled; } } @@ -1020,6 +1035,7 @@ void QWidgetPrivate::createTLSysExtra() extra->topextra->inExpose = 0; extra->topextra->nativeWindowTransparencyEnabled = 0; extra->topextra->forcedToRaster = 0; + extra->topextra->noSystemRotationDisabled = 0; } void QWidgetPrivate::deleteTLSysExtra() diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 43dd07796c..2161f99038 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -397,6 +397,9 @@ private slots: void minimizedWindowModeTransitions(); void normalWindowModeTransitions(); void focusSwitchClosesPopupMenu(); +#if !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) + void opacityChangeCausesBackingStoreRecreation(); +#endif #endif void focusProxyAndInputMethods(); @@ -10336,7 +10339,47 @@ void tst_QWidget::focusSwitchClosesPopupMenu() mainWindow.activateWindow(); QVERIFY(!CEikonEnv::Static()->AppUiFactory()->MenuBar()->IsDisplayed()); } -#endif + +#if !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) +class OpacityChangeWidget : public QWidget +{ +public: + OpacityChangeWidget() : m_paintEngineType(QPaintEngine::MaxUser) { } + void paintEvent(QPaintEvent *) + { + QPainter painter(this); + m_paintEngineType = painter.paintEngine()->type(); + } + QPaintEngine::Type paintEngineType() const { return m_paintEngineType; } +private: + QPaintEngine::Type m_paintEngineType; +}; + +void tst_QWidget::opacityChangeCausesBackingStoreRecreation() +{ + OpacityChangeWidget w; + w.show(); + QTest::qWaitForWindowShown(&w); + const QPaintEngine::Type type = w.paintEngineType(); + if (QPaintEngine::OpenGL != type && QPaintEngine::OpenVG != type) { + QSKIP("Test case is only valid when using opengl or openvg graphics system", SkipAll); + } else { + if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { + QSKIP("Test case is only valid when EGL surface transparency is not supported", SkipAll); + } else { + // Making window transparent should force switch to raster graphics system + w.setAttribute(Qt::WA_TranslucentBackground, true); + w.repaint(); + QCOMPARE(w.paintEngineType(), QPaintEngine::Raster); + // Making window opaque should cause switch back to previous graphics system + w.setAttribute(Qt::WA_TranslucentBackground, false); + w.repaint(); + QCOMPARE(w.paintEngineType(), type); + } + } +} +#endif // !Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE +#endif // Q_OS_SYMBIAN class InputContextTester : public QInputContext { -- cgit v1.2.3 From 55d25e4471074241a4edf9b9c0033cce4e211bdf Mon Sep 17 00:00:00 2001 From: Eero Hyyti Date: Tue, 27 Sep 2011 16:09:42 +0300 Subject: Document updates to Qt for Symbian installation instructions and platform notes. --- doc/src/getting-started/installation.qdoc | 570 ++++++++++++++++-------------- doc/src/platforms/platform-notes.qdoc | 95 +++-- 2 files changed, 374 insertions(+), 291 deletions(-) diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc index ef010b43b6..bec9ee42c7 100644 --- a/doc/src/getting-started/installation.qdoc +++ b/doc/src/getting-started/installation.qdoc @@ -79,6 +79,8 @@ for your platform from the following list. \snippet doc/src/snippets/code/doc_src_installation.qdoc 1 Type \c{./configure -help} to get a list of all available options. + The \l{Configuration Options for Qt} page gives a brief overview + of these. To create the library and compile all the demos, examples, tools, and tutorials, type: @@ -218,7 +220,8 @@ for your platform from the following list. \snippet doc/src/snippets/code/doc_src_installation.qdoc 8 - Type \c{configure -help} to get a list of all available options. + Type \c{configure -help} to get a list of all available options. The + \l{Configuration Options for Qt} page gives a brief overview of these. If you have multiple compilers installed, and want to build the Qt library using a specific compiler, you must specify a \c qmake specification. @@ -433,7 +436,9 @@ in the \l{Qt for Windows CE Requirements} document. If you want to configure Qt for another platform or with other options, type \c{configure -help} to get a list of all available - options. See the \c README file for the list of supported platforms. + options. The \l{Configuration Options for Qt} page gives a brief + overview of these. See the \c README file for the list of supported + platforms. \section1 Step 4: Build Qt Library @@ -505,7 +510,10 @@ in the \l{Qt for the Symbian platform Requirements} document. \section1 Step 1: Install Qt - Run \c{qt-symbian-opensource-%VERSION%.exe} and follow the instructions. + Download the \c {Qt libraries 4.x for Windows} package (for \c minGW or \c {VS 2008}) + from the \l {http://qt.nokia.com/downloads#qt-lib}{downloads} page. + + Run the downloaded package and follow the instructions. \note Qt must be installed on the same drive as the Symbian SDK you are using, and the install path must not contain any spaces. @@ -626,6 +634,10 @@ Binary Package} document. \snippet doc/src/snippets/code/doc_src_installation.qdoc 31 (to build the tools using MinGW, and the libraries using SBSv2) + Type \c{./configure -help} to get a list of all available options. + The \l{Configuration Options for Qt} page gives a brief overview + of these. + SBSv2 (also known as \l{http://developer.symbian.org/wiki/index.php/Introduction_to_RAPTOR} {Raptor}) is a next-generation Symbian build system. SBSv2 is not officially supported by any of the S60 SDKs currently available from Forum Nokia. @@ -643,23 +655,39 @@ Binary Package} document. Congratulations, Qt is now ready to use. \section1 Step 7: Installing Qt Libraries on the Device - - To run the demo on a real device, you first have to install - the Qt libraries on the device: + + To run a Qt application on a device, it must have Qt libraries installed. + + Symbian devices have a pre-installed Qt as follows: + \list + \o Symbian Anna devices have the pre-installed Qt, Qt Mobility, and Qt Webkit. + \o Symbian Belle and later devices have the pre-installed Qt on the device firmware. + \endlist + + \l {http://www.developer.nokia.com/Community/Wiki/Nokia_Smart_Installer_for_Symbian} + {Nokia Smart Installer for Symbian} deploys the required Qt libraries to supported S60 + and Symbian devices if the libraries are not pre-installed. + + Nokia Developer site's \l {http://www.developer.nokia.com/Devices/Device_specifications/?filter1=qt} + {Device specifications} provide information on which devices have a + pre-installed Qt and the used Qt version. + + To create your own Qt installation package, do as follows: \snippet doc/src/snippets/code/doc_src_installation.qdoc 29 - The Qt libraries are built with "All -Tcb" capability, so that - they can support all types of application. - If you don't have a suitable certificate, it is possible to patch - the binaries as follows: - - If you have no certificate, build a self signed Qt: -\snippet doc/src/snippets/code/doc_src_installation.qdoc 34 + The Qt libraries are built with "All -Tcb" capability, so they can support + all types of applications. If you don't have a suitable certificate, you can + patch the binaries in either of the following ways: + + \list + \o If you have no certificate, build a self-signed Qt: + \snippet doc/src/snippets/code/doc_src_installation.qdoc 34 - If you have a symbian-signed developer certificate, specify the + \o If you have a symbian-signed developer certificate, specify the capabilities you can sign for, for example: -\snippet doc/src/snippets/code/doc_src_installation.qdoc 35 + \snippet doc/src/snippets/code/doc_src_installation.qdoc 35 + \endlist \section1 Running Qt demos @@ -740,6 +768,9 @@ to build the libraries using RVCT or to build the libraries using GCCE. +Type \c{./configure -help} to get a list of all available options. +The \l{Configuration Options for Qt} page gives a brief overview +of these. \section1 Step 5: Build Qt @@ -1303,7 +1334,12 @@ We hope you will enjoy using Qt. \brief Setting up the Symbian platform environment for Qt. \previouspage General Qt Requirements - Qt for the Symbian platform requires the following software installed on your development PC: + \l {http://qt.nokia.com/downloads}{Qt SDK} provides all the necessary tools + and libraries for developing Qt applications. However, if you want to build + Qt itself for Symbian, follow the instructions below. + + Qt for the Symbian platform requires the following software installed on + your development PC: \list \o \l{http://www.forum.nokia.com/Library/Tools_and_downloads/Other/Carbide.c++/}{Carbide.c++ v2.3.0 or higher recommended}. \list @@ -1368,253 +1404,263 @@ We hope you will enjoy using Qt. /*! \page configure-options.html - \title Configure options for Qt + \title Configuration Options for Qt \ingroup installation - \brief Brief description of available options building Qt. - - This page gives a brief description of the different options - available when building Qt using configure. To build Qt using - default options, just call configure from the command line like - showed below. If you would like to customize your build, please - use the options listed in the following tables. - - \c {.\configure.exe} - - \section2 Cross platform options: - - \table - \header \o Option \o Description \o Note - \row \o \c {-buildkey } \o Build the Qt library and plugins - using the specified \o - \row \o \c {} \o When the library loads plugins, it will only - load those that have a matching . \o - \row \o \c {-release } \o Compile and link Qt with debugging turned off. \o - \row \o \c {-debug } \o Compile and link Qt with debugging turned on. - \o Default value. - \row \o \c {-debug-and-release} \o Compile and link two Qt libraries, - with and without debugging turned on. \o This option denotes a default - value and needs to be evaluated. If the evaluation succeeds, the - feature is included. - \row \o \c {-opensource} \o Compile and link the Open-Source Edition - of Qt. \o - \row \o \c {-commercial } \o Compile and link the Commercial Edition - of Qt. \o - \row \o \c {-developer-build} \o Compile and link Qt with Qt developer - options including auto-tests exporting) \o - \row \o \c {-shared} \o Create and use shared Qt libraries. \o Default - value. - \row \o \c {-static} \o Create and use static Qt libraries. \o - \row \o \c {-ltcg} \o Use Link Time Code Generation. \o Apply to release - builds only. - \row \o \c {-no-ltcg} \o Do not use Link Time Code Generation. \o Default - value. - \row \o \c {-no-fast} \o Configure Qt normally by generating Makefiles for - all project files. \o Default value. - \row \o \c {-fast} \o Configure Qt quickly by generating Makefiles only for - library and subdirectory targets. \o All other Makefiles are created as - wrappers which will in turn run qmake. - \row \o \c {-no-exceptions} \o Disable exceptions on platforms that support - it. \o - \row \o \c {-exceptions} \o Enable exceptions on platforms that support it. - \o Default value. - \row \o \c {-no-accessibility} \o Do not compile Windows Active - Accessibility support. \o - \row \o \c {-accessibility} \o Compile Windows Active Accessibility - support. \o Default value. - \row \o \c {-no-stl} \o Do not compile STL support. \o - \row \o \c {-stl} \o Compile STL support. \o Default value. - \row \o \c {-no-sql-} \o Disable SQL entirely, by default - none are turned on. \o - \row \o \c {-qt-sql-} \o Enable a SQL in the Qt Library. - \o - \row \o \c {-plugin-sql-} \o Enable SQL as a plugin to be - linked to at run time. \o Available values for : mysql, psql, - oci, odbc, tds, db2, sqlite, sqlite2, ibase. Drivers marked with a - '+' during configure have been detected as available on this system. - \row \o \c {-system-sqlite} \o Use sqlite from the operating system. \o - \row \o \c {-no-qt3support} \o Disables the Qt 3 support functionality. \o - \row \o \c {-no-opengl} \o Disables OpenGL functionality \o - \row \o \c {-opengl } \o Enable OpenGL support with specified API - version. \o Available values for : desktop - Enable support for - Desktop OpenGL (Default), es1 - Enable support for OpenGL ES Common - Profile, es2 - Enable support for OpenGL ES 2.0. - \row \o \c {-no-openvg} \o Disables OpenVG functionality \o Default value. - \row \o \c {-openvg} \o Enables OpenVG functionality \o Requires EGL - support, typically supplied by an OpenGL or other graphics - implementation. - \row \o \c {-platform } \o The operating system and compiler you - are building on. \o The default value is %QMAKESPEC%. - \row \o \c {-xplatform } \o The operating system and compiler you - are cross compiling for. \o See the README file for a list of supported - operating systems and compilers. - \row \o \c {-qtnamespace } \o Wraps all Qt library code in - 'namespace name {..} \o - \row \o \c {-qtlibinfix } \o Renames all Qt* libs to Qt* - \o - \row \o \c {-D } \o Add an explicit define to the preprocessor. - \o - \row \o \c {-I } \o Add an explicit include path. \o - \row \o \c {-L } \o Add an explicit library path. \o - \row \o \c {-l } \o Add an explicit library name, residing - in a librarypath. \o - \row \o \c {-graphicssystem } \o Specify which graphics system should - be used. \o Available values for : * raster - Software rasterizer, - opengl - Using OpenGL acceleration, experimental!, openvg - Using - OpenVG acceleration, experimental! - \row \o \c {-help, -h, -?} \o Display this information. \o - \endtable - - \section2 Third Party Libraries: - \table - \header \o Option \o Description \o Note - \row \o \c {-qt-zlib} \o Use the zlib bundled with Qt. \o - \row \o \c {-system-zlib} \o Use zlib from the operating system. - \o See http://www.gzip.org/zlib - \row \o \c {-no-gif} \o Do not compile GIF reading support. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-qt-gif} \o Compile GIF reading support. \o See also - src/gui/image/qgifhandler_p.h - \row \o \c {-no-libpng} \o Do not compile PNG support. \o - \row \o \c {-qt-libpng} \o Use the libpng bundled with Qt. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-system-libpng} \o Use libpng from the operating system. - \o See http://www.libpng.org/pub/png - \row \o \c {-no-libmng} \o Do not compile MNG support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libmng} \o Use the libmng bundled with Qt. \o - \row \o \c {-system-libmng} \o Use libmng from the operating system. - \o See http://www.libmng.com - \row \o \c {-no-libtiff} \o Do not compile TIFF support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libtiff} \o Use the libtiff bundled with Qt. \o - \row \o \c {-system-libtiff} \o Use libtiff from the operating system. - \o See http://www.libtiff.org - \row \o \c {-no-libjpeg} \o Do not compile JPEG support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libjpeg} \o Use the libjpeg bundled with Qt. \o - \row \o \c {-system-libjpeg} \o Use libjpeg from the operating system. - \o See http://www.ijg.org. This option denotes a default value and - needs to be evaluated. If the evaluation succeeds, the feature is - included. - \endtable - - \section2 Qt for Windows only: - \table - \header \o Option \o Description \o Note - \row \o \c {-no-dsp} \o Do not generate VC++ .dsp files. \o - \row \o \c {-dsp} \o Generate VC++ .dsp files, only if spec "win32-msvc". - \o Default value. - \row \o \c {-no-vcproj} \o Do not generate VC++ .vcproj files. \o - \row \o \c {-vcproj} \o Generate VC++ .vcproj files, only if platform - "win32-msvc.net". \o Default value. - \row \o \c {-no-incredibuild-xge} \o Do not add IncrediBuild XGE distribution - commands to custom build steps. \o - \row \o \c {-incredibuild-xge} \o Add IncrediBuild XGE distribution commands - to custom build steps. This will distribute MOC and UIC steps, and other - custom buildsteps which are added to the INCREDIBUILD_XGE variable. - \o The IncrediBuild distribution commands are only added to Visual Studio - projects. This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-no-plugin-manifests} \o Do not embed manifests in plugins. \o - \row \o \c {-plugin-manifests} \o Embed manifests in plugins. - \o Default value. - \row \o \c {-no-qmake} \o Do not compile qmake. \o - \row \o \c {-qmake} \o Compile qmake. \o Default value - \row \o \c {-dont-process} \o Do not generate Makefiles/Project files. This - will override -no-fast if specified. \o - \row \o \c {-process} \o Generate Makefiles/Project files. \o Default value. - \row \o \c {-no-rtti} \o Do not compile runtime type information. \o - \row \o \c {-rtti} \o Compile runtime type information. \o Default value. - \row \o \c {-no-mmx} \o Do not compile with use of MMX instructions \o - \row \o \c {-mmx} \o Compile with use of MMX instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-3dnow} \o Do not compile with use of 3DNOW instructions \o - \row \o \c {-3dnow} \o Compile with use of 3DNOW instructions \o This - option denotes a default value and needs to be evaluated. If the - evaluation succeeds, the feature is included. - \row \o \c {-no-sse} \o Do not compile with use of SSE instructions \o - \row \o \c {-sse} \o Compile with use of SSE instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-sse2} \o Do not compile with use of SSE2 instructions \o - \row \o \c {-sse2} \o Compile with use of SSE2 instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-openssl} \o Do not compile in OpenSSL support \o - \row \o \c {-openssl} \o Compile in run-time OpenSSL support \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-openssl-linked} \o Compile in linked OpenSSL support \o - \row \o \c {-no-dbus} \o Do not compile in D-Bus support \o - \row \o \c {-dbus} \o Compile in D-Bus support and load libdbus-1 dynamically. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-dbus-linked} \o Compile in D-Bus support and link to - libdbus-1 \o - \row \o \c {-no-phonon} \o Do not compile in the Phonon module \o - \row \o \c {-phonon} \o Compile the Phonon module. \o Phonon is built if a - decent C++ compiler is used. This option denotes a default value and needs - to be evaluated. If the evaluation succeeds, the feature is included. - \row \o \c {-no-phonon-backend} \o Do not compile the platform-specific - Phonon backend-plugin \o - \row \o \c {-phonon-backend} \o Compile in the platform-specific Phonon - backend-plugin \o Default value. - \row \o \c {-no-multimedia} \o Do not compile the multimedia module \o - \row \o \c {-multimedia} \o Compile in multimedia module \o Default value. - \row \o \c {-no-audio-backend} \o Do not compile in the platform audio - backend into QtMultimedia \o - \row \o \c {-audio-backend} \o Compile in the platform audio backend into - QtMultimedia \o This option denotes a default value and needs to be - evaluated. If the evaluation succeeds, the feature is included. - \row \o \c {-no-webkit} \o Do not compile in the WebKit module \o - \row \o \c {-webkit} \o Compile in the WebKit module \o WebKit is built - if a decent C++ compiler is used. This option denotes a default value - and needs to be evaluated. If the evaluation succeeds, the feature is - included. - \row \o \c {-webkit-debug} \o Compile in the WebKit module with debug - symbols. \o - \row \o \c {-no-script} \o Do not build the QtScript module. \o - \row \o \c {-script} \o Build the QtScript module. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-scripttools} \o Do not build the QtScriptTools module. \o - \row \o \c {-scripttools} \o Build the QtScriptTools module. \o This - option denotes a default value and needs to be evaluated. If the - evaluation succeeds, the feature is included. - \row \o \c {-no-declarative} \o Do not build the declarative module \o - \row \o \c {-declarative} \o Build the declarative module \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-declarative-debug} \o Do not build the declarative debugging - support \o - \row \o \c {-declarative-debug} \o Build the declarative debugging support - \o Default value. - \row \o \c {-arch } \o Specify an architecture. \o Available values for - : * windows, windowsce, symbian, boundschecker, generic. - \row \o \c {-no-style-