diff options
Diffstat (limited to 'src')
90 files changed, 2825 insertions, 1967 deletions
diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.cpp b/src/3rdparty/phonon/gstreamer/mediaobject.cpp index 3e0addc..23a60c0 100644 --- a/src/3rdparty/phonon/gstreamer/mediaobject.cpp +++ b/src/3rdparty/phonon/gstreamer/mediaobject.cpp @@ -219,9 +219,9 @@ void MediaObject::noMorePadsAvailable () if ( status != GST_INSTALL_PLUGINS_STARTED_OK ) { if( status == GST_INSTALL_PLUGINS_HELPER_MISSING ) - setError(QString(tr("Missing codec helper script assistant.")), Phonon::FatalError ); + setError(tr("Missing codec helper script assistant."), Phonon::FatalError ); else - setError(QString(tr("Plugin codec installation failed for codec: %0")) + setError(tr("Plugin codec installation failed for codec: %0") .arg(m_missingCodecs[0].split("|")[3]), error); } m_missingCodecs.clear(); @@ -232,7 +232,7 @@ void MediaObject::noMorePadsAvailable () m_hasVideo = false; emit hasVideoChanged(false); } - setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error); + setError(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0").arg(codecs), error); m_missingCodecs.clear(); #endif } diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index ac0c47c..537cdd3 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -2857,6 +2857,25 @@ contains(DEFINES, ENABLE_SYMBIAN_DIALOG_PROVIDERS) { } } +!symbian { + modfile.files = $$moduleFile + modfile.path = $$[QMAKE_MKSPECS]/modules + + INSTALLS += modfile +} else { + # INSTALLS is not implemented in qmake's s60 generators, copy headers manually + + inst_modfile.commands = $$QMAKE_COPY ${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT} + inst_modfile.input = moduleFile + inst_modfile.output = $$[QMAKE_MKSPECS]/modules + inst_modfile.CONFIG = no_clean + + QMAKE_EXTRA_COMPILERS += inst_modfile + + install.depends += compiler_inst_modfile_make_all + QMAKE_EXTRA_TARGETS += install +} + include($$PWD/../WebKit/qt/Api/headers.pri) HEADERS += $$WEBKIT_API_HEADERS @@ -2873,10 +2892,7 @@ HEADERS += $$WEBKIT_API_HEADERS !isEmpty(INSTALL_LIBS): target.path = $$INSTALL_LIBS else: target.path = $$[QT_INSTALL_LIBS] - modfile.files = $$moduleFile - modfile.path = $$[QMAKE_MKSPECS]/modules - - INSTALLS += target headers modfile + INSTALLS += target headers } else { # INSTALLS is not implemented in qmake's s60 generators, copy headers manually inst_headers.commands = $$QMAKE_COPY ${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT} @@ -2888,15 +2904,7 @@ HEADERS += $$WEBKIT_API_HEADERS QMAKE_EXTRA_COMPILERS += inst_headers - inst_modfile.commands = $$inst_headers.commands - inst_modfile.input = moduleFile - inst_modfile.output = $$[QMAKE_MKSPECS]/modules - inst_modfile.CONFIG = no_clean - - QMAKE_EXTRA_COMPILERS += inst_modfile - - install.depends += compiler_inst_headers_make_all compiler_inst_modfile_make_all - QMAKE_EXTRA_TARGETS += install + install.depends += compiler_inst_headers_make_all } win32-*|wince* { diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 2505e72..260ed59 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -19,7 +19,7 @@ INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global # Only used on platforms with CONFIG += precompile_header PRECOMPILED_HEADER = global/qt_pch.h -linux*:!static { +linux*:!static:!linux-armcc:!linux-gcce { QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate prog=$$quote(if (/program interpreter: (.*)]/) { print $1; }) DEFINES += ELF_INTERPRETER=\\\"$$system(readelf -l /bin/ls | perl -n -e \'$$prog\')\\\" diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index a0779c9..957abbf 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -66,6 +66,8 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE +extern void qDumpCPUFeatures(); // in qsimd.cpp + #ifndef QT_NO_SETTINGS struct QLibrarySettings @@ -500,7 +502,6 @@ QT_END_NAMESPACE extern const char qt_core_interpreter[] __attribute__((section(".interp"))) = ELF_INTERPRETER; -extern void qDumpCPUFeatures(); // in qsimd.cpp extern "C" void qt_core_boilerplate(); void qt_core_boilerplate() { @@ -526,7 +527,7 @@ void qt_core_boilerplate() qt_configure_libraries_path_str + 12, qt_configure_headers_path_str + 12); -// qDumpCPUFeatures(); + QT_PREPEND_NAMESPACE(qDumpCPUFeatures)(); #ifdef QT_EVAL extern void qt_core_eval_init(uint); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 1bad8ed..5cc6ae3 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -232,8 +232,12 @@ void QTimerActiveObject::DoCancel() void QTimerActiveObject::RunL() { - int error; - QT_TRYCATCH_ERROR(error, Run()); + int error = KErrNone; + if (iStatus == KErrNone) { + QT_TRYCATCH_ERROR(error, Run()); + } else { + error = iStatus.Int(); + } // All Symbian error codes are negative. if (error < 0) { CActiveScheduler::Current()->Error(error); // stop and report here, as this timer will be deleted on scope exit diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index a9ae2ab..1874a9e 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -295,14 +295,6 @@ static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArr #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK) -#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) -# define USE_MMAP -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/types.h> -# include <sys/mman.h> -QT_END_INCLUDE_NAMESPACE -#endif // Q_OS_FREEBSD || Q_OS_LINUX - static long qt_find_pattern(const char *s, ulong s_len, const char *pattern, ulong p_len) { @@ -363,34 +355,15 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB } QByteArray data; - char *filedata = 0; - ulong fdlen = 0; - -# ifdef USE_MMAP - char *mapaddr = 0; - size_t maplen = file.size(); - mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0); - if (mapaddr != MAP_FAILED) { - // mmap succeeded - filedata = mapaddr; - fdlen = maplen; - } else { - // mmap failed - if (qt_debug_component()) { - qWarning("mmap: %s", qPrintable(qt_error_string(errno))); - } - if (lib) - lib->errorString = QLibrary::tr("Could not mmap '%1': %2") - .arg(library) - .arg(qt_error_string()); -# endif // USE_MMAP + const char *filedata = 0; + ulong fdlen = file.size(); + filedata = (char *) file.map(0, fdlen); + if (filedata == 0) { // try reading the data into memory instead data = file.readAll(); - filedata = data.data(); + filedata = data.constData(); fdlen = data.size(); -# ifdef USE_MMAP } -# endif // USE_MMAP // verify that the pattern is present in the plugin const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; @@ -403,17 +376,6 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB if (!ret && lib) lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library); -# ifdef USE_MMAP - if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) { - if (qt_debug_component()) - qWarning("munmap: %s", qPrintable(qt_error_string(errno))); - if (lib) - lib->errorString = QLibrary::tr("Could not unmap '%1': %2") - .arg(library) - .arg( qt_error_string() ); - } -# endif // USE_MMAP - file.close(); return ret; } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 2626657..664543b 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -51,8 +51,13 @@ QT_BEGIN_HEADER #if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__))) // Disable MMX and SSE on Mac/PPC builds, or if the compiler // does not support -Xarch argument passing -#undef QT_HAVE_SSE2 #undef QT_HAVE_SSE +#undef QT_HAVE_SSE2 +#undef QT_HAVE_SSE3 +#undef QT_HAVE_SSSE3 +#undef QT_HAVE_SSE4_1 +#undef QT_HAVE_SSE4_2 +#undef QT_HAVE_AVX #undef QT_HAVE_3DNOW #undef QT_HAVE_MMX #endif diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index dca2695..1bbfcf4 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -128,6 +128,8 @@ void QDeclarativeDebugServer::newConnection() if (d->connection) { qWarning("QDeclarativeDebugServer error: another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; return; } diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index a710190..b302393 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1001,12 +1001,16 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, bool changed = false; if (newGeometry.width() != oldGeometry.width()) { + if (xflick()) + changed = true; if (d->hData.viewSize < 0) { d->contentItem->setWidth(width()); emit contentWidthChanged(); } } if (newGeometry.height() != oldGeometry.height()) { + if (yflick()) + changed = true; if (d->vData.viewSize < 0) { d->contentItem->setHeight(height()); emit contentHeightChanged(); @@ -1254,6 +1258,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) { d->clearDelayedPress(); d->stealMouse = false; + d->pressed = false; } return false; } diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 1054898..aca2bb7 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1883,6 +1883,12 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, } } + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QDeclarativeItemPrivate::Geometry) + change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); + } + if (newGeometry.x() != oldGeometry.x()) emit xChanged(); if (newGeometry.width() != oldGeometry.width()) @@ -1891,12 +1897,6 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, emit yChanged(); if (newGeometry.height() != oldGeometry.height()) emit heightChanged(); - - for(int ii = 0; ii < d->changeListeners.count(); ++ii) { - const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); - if (change.types & QDeclarativeItemPrivate::Geometry) - change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); - } } void QDeclarativeItemPrivate::removeItemChangeListener(QDeclarativeItemChangeListener *listener, ChangeTypes types) diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index d3d46f7..1c634d2 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2454,6 +2454,16 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event) QDeclarativeFlickable::keyPressEvent(event); } +void QDeclarativeListView::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + Q_D(QDeclarativeListView); + d->maxExtentDirty = true; + d->minExtentDirty = true; + QDeclarativeFlickable::geometryChanged(newGeometry, oldGeometry); +} + + /*! \qmlmethod ListView::incrementCurrentIndex() @@ -2906,14 +2916,18 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) } if (removedVisible && d->visibleItems.isEmpty()) { - d->visibleIndex = 0; - d->visiblePos = d->header ? d->header->size() : 0; d->timeline.clear(); - d->setPosition(0); if (d->itemCount == 0) { + d->visibleIndex = 0; + d->visiblePos = d->header ? d->header->size() : 0; + d->setPosition(0); d->updateHeader(); d->updateFooter(); update(); + } else { + if (modelIndex < d->visibleIndex) + d->visibleIndex = modelIndex+1; + d->visibleIndex = qMax(qMin(d->visibleIndex, d->itemCount-1), 0); } } diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 8fbff49..735b248 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -246,6 +246,7 @@ protected: virtual qreal minXExtent() const; virtual qreal maxXExtent() const; virtual void keyPressEvent(QKeyEvent *); + virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry); virtual void componentComplete(); private Q_SLOTS: diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index b776b8e..77b26b9 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -247,13 +247,13 @@ void QDeclarativeBasePositioner::prePositioning() positionedItems.append(posItem); item = &positionedItems[positionedItems.count()-1]; item->isNew = true; - if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden) + if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) item->isVisible = false; } else { item = &oldItems[wIdx]; // Items are only omitted from positioning if they are explicitly hidden // i.e. their positioning is not affected if an ancestor is hidden. - if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden) { + if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) { item->isVisible = false; } else if (!item->isVisible) { item->isVisible = true; @@ -321,12 +321,6 @@ void QDeclarativeBasePositioner::finishApplyTransitions() d->moveActions.clear(); } -static inline bool isInvisible(QGraphicsObject *child) -{ - QGraphicsItemPrivate *childPrivate = static_cast<QGraphicsItemPrivate*>(QGraphicsItemPrivate::get(child)); - return child->opacity() == 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height(); -} - /*! \qmlclass Column QDeclarativeColumn \ingroup qml-positioning-elements @@ -449,7 +443,7 @@ void QDeclarativeColumn::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; if(child.item->y() != voffset) @@ -584,7 +578,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; if(child.item->x() != hoffset) @@ -793,9 +787,17 @@ void QDeclarativeGrid::setFlow(Flow flow) void QDeclarativeGrid::doPositioning(QSizeF *contentSize) { + int c = m_columns; int r = m_rows; - int numVisible = positionedItems.count(); + //Is allocating the extra QPODVector too much overhead? + QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items + visibleItems.reserve(positionedItems.count()); + for(int i=0; i<positionedItems.count(); i++) + if(positionedItems[i].item && positionedItems[i].isVisible) + visibleItems.append(positionedItems[i]); + + int numVisible = visibleItems.count(); if (m_columns <= 0 && m_rows <= 0){ c = 4; r = (numVisible+3)/4; @@ -816,11 +818,10 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) if (i==0) maxColWidth << 0; - if (childIndex == positionedItems.count()) - continue; - const PositionedItem &child = positionedItems.at(childIndex++); - if (!child.item || isInvisible(child.item)) - continue; + if (childIndex == visibleItems.count()) + break; + + const PositionedItem &child = visibleItems.at(childIndex++); QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (childPrivate->width() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); @@ -837,10 +838,9 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) maxColWidth << 0; if (childIndex == positionedItems.count()) - continue; - const PositionedItem &child = positionedItems.at(childIndex++); - if (!child.item || isInvisible(child.item)) - continue; + break; + + const PositionedItem &child = visibleItems.at(childIndex++); QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (childPrivate->width() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); @@ -854,10 +854,8 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) int yoffset=0; int curRow =0; int curCol =0; - for (int i = 0; i < positionedItems.count(); ++i) { - const PositionedItem &child = positionedItems.at(i); - if (!child.item || isInvisible(child.item)) - continue; + for (int i = 0; i < visibleItems.count(); ++i) { + const PositionedItem &child = visibleItems.at(i); if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){ positionX(xoffset, child); positionY(yoffset, child); @@ -1033,7 +1031,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index b4e8bda..a46ee73 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -1305,24 +1305,27 @@ void QDeclarativeVisualDataModel::_q_itemsMoved(int from, int to, int count) void QDeclarativeVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end) { - if (!parent.isValid()) + Q_D(QDeclarativeVisualDataModel); + if (parent == d->m_root) _q_itemsInserted(begin, end - begin + 1); } void QDeclarativeVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end) { - if (!parent.isValid()) + Q_D(QDeclarativeVisualDataModel); + if (parent == d->m_root) _q_itemsRemoved(begin, end - begin + 1); } void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { + Q_D(QDeclarativeVisualDataModel); const int count = sourceEnd - sourceStart + 1; - if (!destinationParent.isValid() && !sourceParent.isValid()) { + if (destinationParent == d->m_root && sourceParent == d->m_root) { _q_itemsMoved(sourceStart, destinationRow, count); - } else if (!sourceParent.isValid()) { + } else if (sourceParent == d->m_root) { _q_itemsRemoved(sourceStart, count); - } else if (!destinationParent.isValid()) { + } else if (destinationParent == d->m_root) { _q_itemsInserted(destinationRow, count); } } @@ -1330,7 +1333,7 @@ void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end) { Q_D(QDeclarativeVisualDataModel); - if (!begin.parent().isValid()) + if (begin.parent() == d->m_root) _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles); } diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index cd08658..1eb42e4 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -677,9 +677,9 @@ int Lexer::lex() setDone(Other); } else state = Start; - if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); } else if (current == 0) { - if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); setDone(Eof); } @@ -689,14 +689,14 @@ int Lexer::lex() setDone(Bad); err = UnclosedComment; errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed comment at end of file"); - if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); } else if (isLineTerminator()) { shiftWindowsLineBreak(); yylineno++; } else if (current == '*' && next1 == '/') { state = Start; shift(1); - if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + if (driver) driver->addComment(startpos+2, tokenLength()-3, startlineno, startcolumn+2); } break; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index f044e1a..61ea9c8 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -41,7 +41,6 @@ #include "private/qdeclarativecompiler_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativeparser_p.h" #include "private/qdeclarativescriptparser_p.h" #include "qdeclarativepropertyvaluesource.h" @@ -562,7 +561,7 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data) on a successful compiler. */ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, - QDeclarativeCompositeTypeData *unit, + QDeclarativeTypeData *unit, QDeclarativeCompiledData *out) { exceptions.clear(); @@ -573,10 +572,15 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, output = out; // Compile types - for (int ii = 0; ii < unit->types.count(); ++ii) { - QDeclarativeCompositeTypeData::TypeReference &tref = unit->types[ii]; + const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); + QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes(); + + for (int ii = 0; ii < resolvedTypes.count(); ++ii) { QDeclarativeCompiledData::TypeReference ref; - QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii); + + const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii); + QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii); + if (tref.type) { ref.type = tref.type; if (!ref.type->isCreatable()) { @@ -585,33 +589,16 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, err = tr( "Element is not creatable."); COMPILE_EXCEPTION(parserRef->refObjects.first(), err); } - } else if (tref.unit) { - ref.component = tref.unit->toComponent(engine); - - if (ref.component->isError()) { - QDeclarativeError error; - error.setUrl(output->url); - error.setDescription(QLatin1String("Unable to create type ") + - parserRef->name); - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *parserObject = parserRef->refObjects.first(); - error.setLine(parserObject->location.start.line); - error.setColumn(parserObject->location.start.column); - } - - exceptions << error; - exceptions << ref.component->errors(); - reset(out); - return false; - } - ref.ref = tref.unit; + } else if (tref.typeData) { + ref.component = tref.typeData->component(); + ref.ref = tref.typeData; ref.ref->addref(); } ref.className = parserRef->name.toUtf8(); out->types << ref; } - Object *root = unit->data.tree(); + Object *root = unit->parser().tree(); Q_ASSERT(root); this->engine = engine; @@ -664,17 +651,17 @@ void QDeclarativeCompiler::compileTree(Object *tree) QHash<QString, Object::ScriptBlock> importedScripts; QStringList importedScriptIndexes; - for (int ii = 0; ii < unit->scripts.count(); ++ii) { - QString scriptCode = QString::fromUtf8(unit->scripts.at(ii).resource->data); - Object::ScriptBlock::Pragmas pragmas = QDeclarativeScriptParser::extractPragmas(scriptCode); + foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) { + QString scriptCode = script.script->scriptSource(); + Object::ScriptBlock::Pragmas pragmas = script.script->pragmas(); - Q_ASSERT(!importedScripts.contains(unit->scripts.at(ii).qualifier)); + Q_ASSERT(!importedScripts.contains(script.qualifier)); if (!scriptCode.isEmpty()) { - Object::ScriptBlock &scriptBlock = importedScripts[unit->scripts.at(ii).qualifier]; + Object::ScriptBlock &scriptBlock = importedScripts[script.qualifier]; scriptBlock.code = scriptCode; - scriptBlock.file = unit->scripts.at(ii).resource->url; + scriptBlock.file = script.script->finalUrl().toString(); scriptBlock.pragmas = pragmas; } } @@ -704,7 +691,7 @@ void QDeclarativeCompiler::compileTree(Object *tree) for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) output->importCache->add(importedScriptIndexes.at(ii), ii); - unit->imports.populateCache(output->importCache, engine); + unit->imports().populateCache(output->importCache, engine); Q_ASSERT(tree->metatype); @@ -987,7 +974,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) } // Begin the class - if (obj->parserStatusCast != -1) { + if (tr.type && obj->parserStatusCast != -1) { QDeclarativeInstruction begin; begin.type = QDeclarativeInstruction::BeginObject; begin.begin.castValue = obj->parserStatusCast; @@ -1375,7 +1362,7 @@ bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop, return p.name() != 0; } else { int idx = mo->indexOfProperty(prop->name.constData()); - return idx != -1; + return idx != -1 && mo->property(idx).isScriptable(); } } @@ -1404,7 +1391,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, QDeclarativeType *type = 0; QDeclarativeImportedNamespace *typeNamespace = 0; - unit->imports.resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); + unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); if (typeNamespace) { // ### We might need to indicate that this property is a namespace @@ -1440,6 +1427,11 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, if (prop->index != -1) { p = metaObject->property(prop->index); Q_ASSERT(p.name()); + + if (!p.isScriptable()) { + prop->index = -1; + p = QMetaProperty(); + } } } @@ -1512,7 +1504,7 @@ bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespac // Setup attached property data QDeclarativeType *type = 0; - unit->imports.resolveType(ns, prop->name, &type, 0, 0, 0); + unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); @@ -1826,6 +1818,8 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, if (idx == -1) COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); QMetaProperty p = type->metaObject()->property(idx); + if (!p.isScriptable()) + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); prop->index = idx; prop->type = p.userType(); prop->isValueTypeSubProperty = true; @@ -2139,7 +2133,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop QString typeName = parts.at(0); QDeclarativeType *type = 0; - unit->imports.resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); + unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); if (!type || obj->typeName != type->qmlTypeName()) return true; @@ -2166,7 +2160,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const int dot = script.indexOf('.'); if (dot > 0) { QDeclarativeType *type = 0; - unit->imports.resolveType(script.left(dot), &type, 0, 0, 0, 0); + unit->imports().resolveType(script.left(dot), &type, 0, 0, 0, 0); if (!type) return -1; const QMetaObject *mo = type->metaObject(); @@ -2184,7 +2178,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const { QDeclarativeType *qmltype = 0; - if (!unit->imports.resolveType(name, &qmltype, 0, 0, 0, 0)) + if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0)) return 0; if (!qmltype) return 0; @@ -2342,16 +2336,18 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn QByteArray customTypeName; QDeclarativeType *qmltype = 0; QUrl url; - if (!unit->imports.resolveType(p.customType, &qmltype, &url, 0, 0, 0)) + if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0)) COMPILE_EXCEPTION(&p, tr("Invalid property type")); if (!qmltype) { - QDeclarativeCompositeTypeData *tdata = enginePrivate->typeManager.get(url); + QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url); Q_ASSERT(tdata); - Q_ASSERT(tdata->status == QDeclarativeCompositeTypeData::Complete); + Q_ASSERT(tdata->isComplete()); - QDeclarativeCompiledData *data = tdata->toCompiledComponent(engine); + QDeclarativeCompiledData *data = tdata->compiledData(); customTypeName = data->root->className(); + data->release(); + tdata->release(); } else { customTypeName = qmltype->typeName(); } @@ -2417,17 +2413,20 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn builder.addSignal(p.name + "Changed()"); QMetaPropertyBuilder propBuilder = builder.addProperty(p.name, type, builder.methodCount() - 1); - propBuilder.setScriptable(true); propBuilder.setWritable(!readonly); } - if (mode == ResolveAliases) { - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { + const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); - if (p.type == Object::DynamicProperty::Alias) { + if (p.type == Object::DynamicProperty::Alias) { + if (mode == ResolveAliases) { ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; compileAlias(builder, dynamicData, obj, p); + } else { + // Need a fake signal so that the metaobject remains consistent across + // the resolve and non-resolve alias runs + builder.addSignal(p.name + "Changed()"); } } } @@ -2583,6 +2582,9 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + if (!aliasProperty.isScriptable()) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + writable = aliasProperty.isWritable(); if (aliasProperty.isEnumType()) @@ -2619,7 +2621,6 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); - propBuilder.setScriptable(true); propBuilder.setWritable(writable); return true; } @@ -2746,7 +2747,7 @@ bool QDeclarativeCompiler::completeComponentBuild() expr.context = binding.bindingContext.object; expr.property = binding.property; expr.expression = binding.expression; - expr.imports = unit->imports; + expr.imports = unit->imports(); int index = bindingCompiler.compile(expr, enginePrivate); if (index != -1) { diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 49dc53f..89eef09 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -56,13 +56,13 @@ #include "qdeclarative.h" #include "qdeclarativeerror.h" #include "private/qdeclarativeinstruction_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" #include "private/qdeclarativeparser_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qbitfield_p.h" #include "private/qdeclarativepropertycache_p.h" #include "private/qdeclarativeintegercache_p.h" #include "private/qdeclarativetypenamecache_p.h" +#include "private/qdeclarativetypeloader_p.h" #include <QtCore/qbytearray.h> #include <QtCore/qset.h> @@ -152,7 +152,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeCompiler public: QDeclarativeCompiler(); - bool compile(QDeclarativeEngine *, QDeclarativeCompositeTypeData *, QDeclarativeCompiledData *); + bool compile(QDeclarativeEngine *, QDeclarativeTypeData *, QDeclarativeCompiledData *); bool isError() const; QList<QDeclarativeError> errors() const; @@ -338,7 +338,7 @@ private: QDeclarativeEngine *engine; QDeclarativeEnginePrivate *enginePrivate; QDeclarativeParser::Object *unitRoot; - QDeclarativeCompositeTypeData *unit; + QDeclarativeTypeData *unit; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index d2d1f19..74de738 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -44,7 +44,6 @@ #include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativecontext_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativevme_p.h" #include "qdeclarative.h" @@ -197,7 +196,7 @@ class QByteArray; \value Error An error has occurred. Call errors() to retrieve a list of \{QDeclarativeError}{errors}. */ -void QDeclarativeComponentPrivate::typeDataReady() +void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *) { Q_Q(QDeclarativeComponent); @@ -209,28 +208,25 @@ void QDeclarativeComponentPrivate::typeDataReady() emit q->statusChanged(q->status()); } -void QDeclarativeComponentPrivate::updateProgress(qreal p) +void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p) { Q_Q(QDeclarativeComponent); progress = p; + emit q->progressChanged(p); } -void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeCompositeTypeData *data) +void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data) { - url = data->imports.baseUrl(); - QDeclarativeCompiledData *c = data->toCompiledComponent(engine); + url = data->finalUrl(); + QDeclarativeCompiledData *c = data->compiledData(); if (!c) { - Q_ASSERT(data->status == QDeclarativeCompositeTypeData::Error); - - state.errors = data->errors; - + Q_ASSERT(data->isError()); + state.errors = data->errors(); } else { - cc = c; - } data->release(); @@ -239,7 +235,7 @@ void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeCompositeTypeData *d void QDeclarativeComponentPrivate::clear() { if (typeData) { - typeData->remWaiter(this); + typeData->unregisterCallback(this); typeData->release(); typeData = 0; } @@ -271,7 +267,7 @@ QDeclarativeComponent::~QDeclarativeComponent() } if (d->typeData) { - d->typeData->remWaiter(d); + d->typeData->unregisterCallback(d); d->typeData->release(); } if (d->cc) @@ -443,19 +439,13 @@ void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url) d->url = url; - QDeclarativeCompositeTypeData *typeData = - QDeclarativeEnginePrivate::get(d->engine)->typeManager.getImmediate(data, url); + QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url); - if (typeData->status == QDeclarativeCompositeTypeData::Waiting - || typeData->status == QDeclarativeCompositeTypeData::WaitingResources) - { - d->typeData = typeData; - d->typeData->addWaiter(d); - - } else { - + if (typeData->isCompleteOrError()) { d->fromTypeData(typeData); - + } else { + d->typeData = typeData; + d->typeData->registerCallback(d); } d->progress = 1.0; @@ -501,18 +491,15 @@ void QDeclarativeComponent::loadUrl(const QUrl &url) return; } - QDeclarativeCompositeTypeData *data = - QDeclarativeEnginePrivate::get(d->engine)->typeManager.get(d->url); + QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url); - if (data->status == QDeclarativeCompositeTypeData::Waiting - || data->status == QDeclarativeCompositeTypeData::WaitingResources) - { - d->typeData = data; - d->typeData->addWaiter(d); - d->progress = data->progress; - } else { + if (data->isCompleteOrError()) { d->fromTypeData(data); d->progress = 1.0; + } else { + d->typeData = data; + d->typeData->registerCallback(d); + d->progress = data->progress(); } emit statusChanged(status()); @@ -620,10 +607,11 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent) ctxt = d->engine->rootContext(); if (!ctxt) return QScriptValue(QScriptValue::NullValue); - QObject* ret = create(ctxt); - if (!ret) + QObject* ret = beginCreate(ctxt); + if (!ret) { + completeCreate(); return QScriptValue(QScriptValue::NullValue); - + } if (parent) { ret->setParent(parent); @@ -644,6 +632,7 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent) if (needParent) qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); } + completeCreate(); QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); QDeclarativeData::get(ret, true)->setImplicitDestructible(); diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 1d1fca7..fd9cb2b 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -117,6 +117,7 @@ private: Q_DISABLE_COPY(QDeclarativeComponent) friend class QDeclarativeVME; friend class QDeclarativeCompositeTypeData; + friend class QDeclarativeTypeData; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 2a7d633..1b1454b 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -56,7 +56,7 @@ #include "qdeclarativecomponent.h" #include "private/qdeclarativeengine_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" +#include "private/qdeclarativetypeloader_p.h" #include "private/qbitfield_p.h" #include "qdeclarativeerror.h" #include "qdeclarative.h" @@ -74,7 +74,7 @@ class QDeclarativeEngine; class QDeclarativeCompiledData; class QDeclarativeComponentAttached; -class QDeclarativeComponentPrivate : public QObjectPrivate +class QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback { Q_DECLARE_PUBLIC(QDeclarativeComponent) @@ -85,11 +85,11 @@ public: QObject *beginCreate(QDeclarativeContextData *, const QBitField &); void completeCreate(); - QDeclarativeCompositeTypeData *typeData; - void typeDataReady(); - void updateProgress(qreal); + QDeclarativeTypeData *typeData; + virtual void typeDataReady(QDeclarativeTypeData *); + virtual void typeDataProgress(QDeclarativeTypeData *, qreal); - void fromTypeData(QDeclarativeCompositeTypeData *data); + void fromTypeData(QDeclarativeTypeData *data); QUrl url; qreal progress; diff --git a/src/declarative/qml/qdeclarativecompositetypedata_p.h b/src/declarative/qml/qdeclarativecompositetypedata_p.h deleted file mode 100644 index a0e4cc2..0000000 --- a/src/declarative/qml/qdeclarativecompositetypedata_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVECOMPOSITETYPEDATA_P_H -#define QDECLARATIVECOMPOSITETYPEDATA_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qdeclarativeengine_p.h" - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QDeclarativeCompositeTypeResource; -class QDeclarativeCompositeTypeData : public QDeclarativeRefCount -{ -public: - QDeclarativeCompositeTypeData(); - virtual ~QDeclarativeCompositeTypeData(); - - enum Status { - Invalid, - Complete, - Error, - Waiting, - WaitingResources - }; - Status status; - enum ErrorType { - NoError, - AccessError, - GeneralError - }; - ErrorType errorType; - - QList<QDeclarativeError> errors; - - QDeclarativeImports imports; - - QList<QDeclarativeCompositeTypeData *> dependants; - - // Return a QDeclarativeComponent if the QDeclarativeCompositeTypeData is not in the Waiting - // state. The QDeclarativeComponent is owned by the QDeclarativeCompositeTypeData, so a - // reference should be kept to keep the QDeclarativeComponent alive. - QDeclarativeComponent *toComponent(QDeclarativeEngine *); - // Return a QDeclarativeCompiledData if possible, or 0 if an error - // occurs - QDeclarativeCompiledData *toCompiledComponent(QDeclarativeEngine *); - - struct TypeReference - { - TypeReference(); - - QDeclarativeType *type; - QDeclarativeCompositeTypeData *unit; - }; - - struct ScriptReference - { - ScriptReference(); - - QString qualifier; - QDeclarativeCompositeTypeResource *resource; - }; - - QList<TypeReference> types; - QList<ScriptReference> scripts; - QList<QDeclarativeCompositeTypeResource *> resources; - - // Add or remove p as a waiter. When the QDeclarativeCompositeTypeData becomes - // ready, the QDeclarativeComponentPrivate::typeDataReady() method will be invoked on - // p. The waiter is automatically removed when the typeDataReady() method - // is invoked, so there is no need to call remWaiter() in this case. - void addWaiter(QDeclarativeComponentPrivate *p); - void remWaiter(QDeclarativeComponentPrivate *p); - - qreal progress; - -private: - friend class QDeclarativeCompositeTypeManager; - friend class QDeclarativeCompiler; - friend class QDeclarativeDomDocument; - - QDeclarativeScriptParser data; - QList<QDeclarativeComponentPrivate *> waiters; - QDeclarativeComponent *component; - QDeclarativeCompiledData *compiledComponent; -}; - -class QDeclarativeCompositeTypeResource : public QDeclarativeRefCount -{ -public: - QDeclarativeCompositeTypeResource(); - virtual ~QDeclarativeCompositeTypeResource(); - - enum Status { - Invalid, - Complete, - Error, - Waiting - }; - Status status; - - QList<QDeclarativeCompositeTypeData *> dependants; - - QString url; - QByteArray data; -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVECOMPOSITETYPEDATA_P_H - diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp deleted file mode 100644 index cc8f887..0000000 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qdeclarativecompositetypemanager_p.h" - -#include "private/qdeclarativecompositetypedata_p.h" -#include "private/qdeclarativescriptparser_p.h" -#include "qdeclarativeengine.h" -#include "private/qdeclarativeengine_p.h" -#include "qdeclarativecomponent.h" -#include "private/qdeclarativecomponent_p.h" -#include "private/qdeclarativecompiler_p.h" - -#include <QtNetwork/qnetworkreply.h> -#include <QtCore/qdebug.h> -#include <QtCore/qfile.h> - -QT_BEGIN_NAMESPACE - -QDeclarativeCompositeTypeData::QDeclarativeCompositeTypeData() -: status(Invalid), errorType(NoError), component(0), compiledComponent(0) -{ -} - -QDeclarativeCompositeTypeData::~QDeclarativeCompositeTypeData() -{ - for (int ii = 0; ii < dependants.count(); ++ii) - dependants.at(ii)->release(); - - for (int ii = 0; ii < resources.count(); ++ii) - resources.at(ii)->release(); - - if (compiledComponent) - compiledComponent->release(); - - if (component) - delete component; -} - -QDeclarativeCompositeTypeResource::QDeclarativeCompositeTypeResource() -{ -} - -QDeclarativeCompositeTypeResource::~QDeclarativeCompositeTypeResource() -{ - for (int ii = 0; ii < dependants.count(); ++ii) - dependants.at(ii)->release(); -} - -void QDeclarativeCompositeTypeData::addWaiter(QDeclarativeComponentPrivate *p) -{ - waiters << p; -} - -void QDeclarativeCompositeTypeData::remWaiter(QDeclarativeComponentPrivate *p) -{ - waiters.removeAll(p); -} - -QDeclarativeComponent *QDeclarativeCompositeTypeData::toComponent(QDeclarativeEngine *engine) -{ - if (!component) { - - QDeclarativeCompiledData *cc = toCompiledComponent(engine); - if (cc) { - component = new QDeclarativeComponent(engine, cc, -1, -1, 0); - cc->release(); - } else { - component = new QDeclarativeComponent(engine, 0); - component->d_func()->url = imports.baseUrl(); - component->d_func()->state.errors = errors; - } - - } - - return component; -} - -QDeclarativeCompiledData * -QDeclarativeCompositeTypeData::toCompiledComponent(QDeclarativeEngine *engine) -{ - if (status == Complete && !compiledComponent) { - - // Build script imports - foreach (const QDeclarativeScriptParser::Import &import, data.imports()) { - if (import.type == QDeclarativeScriptParser::Import::Script) { - QString url = imports.baseUrl().resolved(QUrl(import.uri)).toString(); - - ScriptReference ref; - ref.qualifier = import.qualifier; - - for (int ii = 0; ii < resources.count(); ++ii) { - if (resources.at(ii)->url == url) { - ref.resource = resources.at(ii); - break; - } - } - - Q_ASSERT(ref.resource); - - scripts << ref; - } - } - - compiledComponent = new QDeclarativeCompiledData(engine); - compiledComponent->url = imports.baseUrl(); - compiledComponent->name = compiledComponent->url.toString(); - - QDeclarativeCompiler compiler; - if (!compiler.compile(engine, this, compiledComponent)) { - status = Error; - errors = compiler.errors(); - compiledComponent->release(); - compiledComponent = 0; - } - - // Data is no longer needed once we have a compiled component - data.clear(); - } - - if (compiledComponent) - compiledComponent->addref(); - - return compiledComponent; -} - -QDeclarativeCompositeTypeData::TypeReference::TypeReference() -: type(0), unit(0) -{ -} - -QDeclarativeCompositeTypeData::ScriptReference::ScriptReference() -: resource(0) -{ -} - -QDeclarativeCompositeTypeManager::QDeclarativeCompositeTypeManager(QDeclarativeEngine *e) -: engine(e), redirectCount(0) -{ -} - -QDeclarativeCompositeTypeManager::~QDeclarativeCompositeTypeManager() -{ - for (Components::Iterator iter = components.begin(); iter != components.end();) { - (*iter)->release(); - iter = components.erase(iter); - } - for (Resources::Iterator iter = resources.begin(); iter != resources.end();) { - (*iter)->release(); - iter = resources.erase(iter); - } -} - -QDeclarativeCompositeTypeData *QDeclarativeCompositeTypeManager::get(const QUrl &url) -{ - Redirects::Iterator redir = redirects.find(url); - if (redir != redirects.end()) - return get(*redir); - - QDeclarativeCompositeTypeData *unit = components.value(url); - - if (!unit) { - unit = new QDeclarativeCompositeTypeData; - unit->status = QDeclarativeCompositeTypeData::Waiting; - unit->progress = 0.0; - unit->imports.setBaseUrl(url); - components.insert(url, unit); - - loadSource(unit); - } - - unit->addref(); - return unit; -} - -QDeclarativeCompositeTypeData * -QDeclarativeCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url) -{ - QDeclarativeCompositeTypeData *unit = new QDeclarativeCompositeTypeData; - unit->status = QDeclarativeCompositeTypeData::Waiting; - unit->imports.setBaseUrl(url); - setData(unit, data, url); - return unit; -} - -void QDeclarativeCompositeTypeManager::clearCache() -{ - for (Components::Iterator iter = components.begin(); iter != components.end();) { - if ((*iter)->status != QDeclarativeCompositeTypeData::Waiting) { - (*iter)->release(); - iter = components.erase(iter); - } else { - ++iter; - } - } - - for (Resources::Iterator iter = resources.begin(); iter != resources.end();) { - if ((*iter)->status != QDeclarativeCompositeTypeResource::Waiting) { - (*iter)->release(); - iter = resources.erase(iter); - } else { - ++iter; - } - } -} - -#define TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION 16 - -void QDeclarativeCompositeTypeManager::replyFinished() -{ - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeData *unit = components.value(reply->url()); - Q_ASSERT(unit); - - redirectCount++; - if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { - QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - QUrl url = reply->url().resolved(redirect.toUrl()); - redirects.insert(reply->url(),url); - unit->imports.setBaseUrl(url); - components.remove(reply->url()); - components.insert(url, unit); - reply->deleteLater(); - reply = engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(replyFinished())); - QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - return; - } - } - redirectCount = 0; - - if (reply->error() != QNetworkReply::NoError) { - QString errorDescription; - // ### - Fill in error - errorDescription = QLatin1String("Network error for URL ") + - reply->url().toString(); - - unit->status = QDeclarativeCompositeTypeData::Error; - // ### FIXME - QDeclarativeError error; - error.setDescription(errorDescription); - unit->errorType = QDeclarativeCompositeTypeData::AccessError; - unit->errors << error; - doComplete(unit); - - } else { - QByteArray data = reply->readAll(); - - setData(unit, data, reply->url()); - } - - reply->deleteLater(); -} - -void QDeclarativeCompositeTypeManager::resourceReplyFinished() -{ - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeResource *resource = resources.value(reply->url()); - Q_ASSERT(resource); - - redirectCount++; - if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { - QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - QUrl url = reply->url().resolved(redirect.toUrl()); - redirects.insert(reply->url(),url); - resource->url = url.toString(); - resources.remove(reply->url()); - resources.insert(url, resource); - reply->deleteLater(); - reply = engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(resourceReplyFinished())); - return; - } - } - redirectCount = 0; - - if (reply->error() != QNetworkReply::NoError) { - - resource->status = QDeclarativeCompositeTypeResource::Error; - - } else { - - resource->status = QDeclarativeCompositeTypeResource::Complete; - resource->data = reply->readAll(); - - } - - doComplete(resource); - reply->deleteLater(); -} - -void QDeclarativeCompositeTypeManager::loadResource(QDeclarativeCompositeTypeResource *resource) -{ - QUrl url(resource->url); - - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - - QFile file(lf); - if (file.open(QFile::ReadOnly)) { - resource->data = file.readAll(); - resource->status = QDeclarativeCompositeTypeResource::Complete; - } else { - resource->status = QDeclarativeCompositeTypeResource::Error; - } - } else if (url.scheme().isEmpty()) { - - // We can't open this, so just declare as an error - resource->status = QDeclarativeCompositeTypeResource::Error; - } else { - - QNetworkReply *reply = - engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(resourceReplyFinished())); - - } -} - -void QDeclarativeCompositeTypeManager::loadSource(QDeclarativeCompositeTypeData *unit) -{ - QUrl url(unit->imports.baseUrl()); - - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - - QFile file(lf); - if (file.open(QFile::ReadOnly)) { - QByteArray data = file.readAll(); - setData(unit, data, url); - return; // success - } - } else if (!url.scheme().isEmpty()) { - QNetworkReply *reply = - engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(replyFinished())); - QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - return; // waiting - } - - // error happened - QString errorDescription; - // ### - Fill in error - errorDescription = QLatin1String("File error for URL ") + url.toString(); - unit->status = QDeclarativeCompositeTypeData::Error; - // ### FIXME - QDeclarativeError error; - error.setDescription(errorDescription); - unit->errorType = QDeclarativeCompositeTypeData::AccessError; - unit->errors << error; - doComplete(unit); -} - -void QDeclarativeCompositeTypeManager::requestProgress(qint64 received, qint64 total) -{ - if (total <= 0) - return; - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeData *unit = components.value(reply->url()); - Q_ASSERT(unit); - - unit->progress = qreal(received)/total; - - foreach (QDeclarativeComponentPrivate *comp, unit->waiters) - comp->updateProgress(unit->progress); -} - -void QDeclarativeCompositeTypeManager::setData(QDeclarativeCompositeTypeData *unit, - const QByteArray &data, - const QUrl &url) -{ - bool ok = true; - if (!unit->data.parse(data, url)) { - ok = false; - unit->errors << unit->data.errors(); - } - - if (ok) { - compile(unit); - } else { - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - doComplete(unit); - } -} - -void QDeclarativeCompositeTypeManager::doComplete(QDeclarativeCompositeTypeData *unit) -{ - for (int ii = 0; ii < unit->dependants.count(); ++ii) { - checkComplete(unit->dependants.at(ii)); - unit->dependants.at(ii)->release(); - } - unit->dependants.clear(); - - while(!unit->waiters.isEmpty()) { - QDeclarativeComponentPrivate *p = unit->waiters.takeFirst(); - p->typeDataReady(); - } -} - -void QDeclarativeCompositeTypeManager::doComplete(QDeclarativeCompositeTypeResource *resource) -{ - for (int ii = 0; ii < resource->dependants.count(); ++ii) { - checkComplete(resource->dependants.at(ii)); - resource->dependants.at(ii)->release(); - } - resource->dependants.clear(); -} - -void QDeclarativeCompositeTypeManager::checkComplete(QDeclarativeCompositeTypeData *unit) -{ - if (unit->status != QDeclarativeCompositeTypeData::Waiting - && unit->status != QDeclarativeCompositeTypeData::WaitingResources) - return; - - int waiting = 0; - for (int ii = 0; ii < unit->resources.count(); ++ii) { - QDeclarativeCompositeTypeResource *r = unit->resources.at(ii); - - if (!r) - continue; - - if (r->status == QDeclarativeCompositeTypeResource::Error) { - unit->status = QDeclarativeCompositeTypeData::Error; - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Resource %1 unavailable").arg(r->url)); - unit->errors << error; - doComplete(unit); - return; - } else if (r->status == QDeclarativeCompositeTypeResource::Waiting) { - waiting++; - } - } - - if (waiting == 0) { - if (unit->status == QDeclarativeCompositeTypeData::WaitingResources) { - waiting += resolveTypes(unit); - if (unit->status != QDeclarativeCompositeTypeData::Error) { - if (waiting) - unit->status = QDeclarativeCompositeTypeData::Waiting; - } else { - return; - } - } else { - for (int ii = 0; ii < unit->types.count(); ++ii) { - QDeclarativeCompositeTypeData *u = unit->types.at(ii).unit; - - if (!u) - continue; - - if (u->status == QDeclarativeCompositeTypeData::Error) { - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errors = u->errors; - doComplete(unit); - return; - } else if (u->status == QDeclarativeCompositeTypeData::Waiting - || u->status == QDeclarativeCompositeTypeData::WaitingResources) - { - waiting++; - } - } - } - } - - if (!waiting) { - unit->status = QDeclarativeCompositeTypeData::Complete; - doComplete(unit); - } -} - -int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData *unit) -{ - // not called until all resources are loaded (they include import URLs) - int waiting = 0; - - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeImportDatabase *importDatabase = &ep->importDatabase; - - // For local urls, add an implicit import "." as first (most overridden) lookup. - // This will also trigger the loading of the qmldir and the import of any native - // types from available plugins. - { - QDeclarativeDirComponents qmldircomponentsnetwork; - if (QDeclarativeCompositeTypeResource *resource - = resources.value(unit->imports.baseUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { - QDeclarativeDirParser parser; - parser.setSource(QString::fromUtf8(resource->data)); - parser.parse(); - qmldircomponentsnetwork = parser.components(); - } - - unit->imports.addImport(importDatabase, - QLatin1String("."), QString(), -1, -1, QDeclarativeScriptParser::Import::File, - qmldircomponentsnetwork, - 0); // error ignored (just means no fallback) - } - - - foreach (const QDeclarativeScriptParser::Import &imp, unit->data.imports()) { - QDeclarativeDirComponents qmldircomponentsnetwork; - if (imp.type == QDeclarativeScriptParser::Import::Script) - continue; - - if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { - QString importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))).toString(); - for (int ii = 0; ii < unit->resources.count(); ++ii) { - if (unit->resources.at(ii)->url == importUrl) { - QDeclarativeDirParser parser; - parser.setSource(QString::fromUtf8(unit->resources.at(ii)->data)); - parser.parse(); - qmldircomponentsnetwork = parser.components(); - break; - } - } - } - - - int vmaj = -1; - int vmin = -1; - if (!imp.version.isEmpty()) { - int dot = imp.version.indexOf(QLatin1Char('.')); - if (dot < 0) { - vmaj = imp.version.toInt(); - vmin = 0; - } else { - vmaj = imp.version.left(dot).toInt(); - vmin = imp.version.mid(dot+1).toInt(); - } - } - - QString errorString; - if (!unit->imports.addImport(importDatabase, - imp.uri, imp.qualifier, vmaj, vmin, imp.type, - qmldircomponentsnetwork, &errorString)) { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(errorString); - error.setLine(imp.location.start.line); - error.setColumn(imp.location.start.column); - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - unit->errors << error; - doComplete(unit); - return 0; - } - } - - - QList<QDeclarativeScriptParser::TypeReference*> types = unit->data.referencedTypes(); - - for (int ii = 0; ii < types.count(); ++ii) { - QDeclarativeScriptParser::TypeReference *parserRef = types.at(ii); - QByteArray typeName = parserRef->name.toUtf8(); - - QDeclarativeCompositeTypeData::TypeReference ref; - - QUrl url; - int majorVersion; - int minorVersion; - QDeclarativeImportedNamespace *typeNamespace = 0; - QString errorString; - if (!unit->imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, - &typeNamespace, &errorString) || typeNamespace) { - // Known to not be a type: - // - known to be a namespace (Namespace {}) - // - type with unknown namespace (UnknownNamespace.SomeType {}) - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - QString userTypeName = QString::fromUtf8(typeName); - userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); - if (typeNamespace) - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(userTypeName)); - else - error.setDescription(tr("%1 %2").arg(userTypeName).arg(errorString)); - - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *obj = parserRef->refObjects.first(); - error.setLine(obj->location.start.line); - error.setColumn(obj->location.start.column); - } - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - unit->errors << error; - doComplete(unit); - return 0; - } - - if (ref.type) { - foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { - // store namespace for DOM - obj->majorVersion = majorVersion; - obj->minorVersion = minorVersion; - } - unit->types << ref; - continue; - } - - Redirects::Iterator redir = redirects.find(url); - if (redir != redirects.end()) - url = *redir; - - QDeclarativeCompositeTypeData *urlUnit = components.value(url); - - if (!urlUnit) { - urlUnit = new QDeclarativeCompositeTypeData; - urlUnit->status = QDeclarativeCompositeTypeData::Waiting; - urlUnit->imports.setBaseUrl(url); - components.insert(url, urlUnit); - - loadSource(urlUnit); - } - - ref.unit = urlUnit; - switch(urlUnit->status) { - case QDeclarativeCompositeTypeData::Invalid: - case QDeclarativeCompositeTypeData::Error: - unit->status = QDeclarativeCompositeTypeData::Error; - { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName))); - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *obj = parserRef->refObjects.first(); - error.setLine(obj->location.start.line); - error.setColumn(obj->location.start.column); - } - unit->errors << error; - } - if (urlUnit->errorType != QDeclarativeCompositeTypeData::AccessError) - unit->errors << urlUnit->errors; - doComplete(unit); - return 0; - - case QDeclarativeCompositeTypeData::Complete: - break; - - case QDeclarativeCompositeTypeData::Waiting: - case QDeclarativeCompositeTypeData::WaitingResources: - unit->addref(); - ref.unit->dependants << unit; - waiting++; - break; - } - - unit->types << ref; - } - return waiting; -} - -// ### Check ref counting in here -void QDeclarativeCompositeTypeManager::compile(QDeclarativeCompositeTypeData *unit) -{ - int waiting = 0; - - QList<QUrl> resourceList = unit->data.referencedResources(); - - foreach (QDeclarativeScriptParser::Import imp, unit->data.imports()) { - if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { - QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))); - if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { - // Import requires remote qmldir - resourceList.prepend(importUrl); - } - } - } - - QUrl importUrl; - if (!unit->imports.baseUrl().scheme().isEmpty()) - importUrl = unit->imports.baseUrl().resolved(QUrl(QLatin1String("qmldir"))); - if (!importUrl.scheme().isEmpty() && QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) - resourceList.prepend(importUrl); - - for (int ii = 0; ii < resourceList.count(); ++ii) { - QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii)); - - QDeclarativeCompositeTypeResource *resource = resources.value(url); - - if (!resource) { - resource = new QDeclarativeCompositeTypeResource; - resource->status = QDeclarativeCompositeTypeResource::Waiting; - resource->url = url.toString(); - resources.insert(url, resource); - - loadResource(resource); - } - - switch(resource->status) { - case QDeclarativeCompositeTypeResource::Invalid: - case QDeclarativeCompositeTypeResource::Error: - unit->status = QDeclarativeCompositeTypeData::Error; - { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Resource %1 unavailable").arg(resource->url)); - unit->errors << error; - } - doComplete(unit); - return; - - case QDeclarativeCompositeTypeData::Complete: - break; - - case QDeclarativeCompositeTypeData::Waiting: - unit->addref(); - resource->dependants << unit; - waiting++; - break; - } - - resource->addref(); - unit->resources << resource; - } - - if (waiting == 0) { - waiting += resolveTypes(unit); - if (unit->status != QDeclarativeCompositeTypeData::Error) { - if (!waiting) { - unit->status = QDeclarativeCompositeTypeData::Complete; - doComplete(unit); - } else { - unit->status = QDeclarativeCompositeTypeData::Waiting; - } - } - } else { - unit->status = QDeclarativeCompositeTypeData::WaitingResources; - } -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompositetypemanager_p.h b/src/declarative/qml/qdeclarativecompositetypemanager_p.h deleted file mode 100644 index 5c82c4c..0000000 --- a/src/declarative/qml/qdeclarativecompositetypemanager_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVECOMPOSITETYPEMANAGER_P_H -#define QDECLARATIVECOMPOSITETYPEMANAGER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qdeclarativescriptparser_p.h" -#include "private/qdeclarativerefcount_p.h" -#include "qdeclarativeerror.h" -#include "qdeclarativeengine.h" - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QDeclarativeCompiledData; -class QDeclarativeComponentPrivate; -class QDeclarativeComponent; -class QDeclarativeDomDocument; - -class QDeclarativeCompositeTypeData; -class QDeclarativeCompositeTypeResource; - -class QDeclarativeCompositeTypeManager : public QObject -{ - Q_OBJECT -public: - QDeclarativeCompositeTypeManager(QDeclarativeEngine *); - ~QDeclarativeCompositeTypeManager(); - - // Return a QDeclarativeCompositeTypeData for url. The QDeclarativeCompositeTypeData may be - // cached. - QDeclarativeCompositeTypeData *get(const QUrl &url); - // Return a QDeclarativeCompositeTypeData for data, with the provided base url. The - // QDeclarativeCompositeTypeData will not be cached. - QDeclarativeCompositeTypeData *getImmediate(const QByteArray &data, const QUrl &url); - - // Clear cached types. Only types that aren't in the Waiting state will - // be cleared. - void clearCache(); - -private Q_SLOTS: - void replyFinished(); - void resourceReplyFinished(); - void requestProgress(qint64 received, qint64 total); - -private: - void loadSource(QDeclarativeCompositeTypeData *); - void loadResource(QDeclarativeCompositeTypeResource *); - void compile(QDeclarativeCompositeTypeData *); - void setData(QDeclarativeCompositeTypeData *, const QByteArray &, const QUrl &); - - void doComplete(QDeclarativeCompositeTypeData *); - void doComplete(QDeclarativeCompositeTypeResource *); - void checkComplete(QDeclarativeCompositeTypeData *); - int resolveTypes(QDeclarativeCompositeTypeData *); - - QDeclarativeEngine *engine; - typedef QHash<QUrl, QDeclarativeCompositeTypeData *> Components; - Components components; - typedef QHash<QUrl, QDeclarativeCompositeTypeResource *> Resources; - Resources resources; - typedef QHash<QUrl, QUrl> Redirects; - Redirects redirects; - int redirectCount; -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVECOMPOSITETYPEMANAGER_P_H - diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp index 5b30bde..1a9b501 100644 --- a/src/declarative/qml/qdeclarativedom.cpp +++ b/src/declarative/qml/qdeclarativedom.cpp @@ -42,7 +42,6 @@ #include "private/qdeclarativedom_p.h" #include "private/qdeclarativedom_p_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativescriptparser_p.h" @@ -145,37 +144,23 @@ bool QDeclarativeDomDocument::load(QDeclarativeEngine *engine, const QByteArray d->errors.clear(); d->imports.clear(); - QDeclarativeCompiledData *component = new QDeclarativeCompiledData(engine); - QDeclarativeCompiler compiler; + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QDeclarativeTypeData *td = ep->typeLoader.get(data, url, QDeclarativeTypeLoader::PreserveParser); - QDeclarativeCompositeTypeData *td = ((QDeclarativeEnginePrivate *)QDeclarativeEnginePrivate::get(engine))->typeManager.getImmediate(data, url); - - if(td->status == QDeclarativeCompositeTypeData::Error) { - d->errors = td->errors; + if(td->isError()) { + d->errors = td->errors(); td->release(); - component->release(); return false; - } else if(td->status == QDeclarativeCompositeTypeData::Waiting || - td->status == QDeclarativeCompositeTypeData::WaitingResources) { + } else if(!td->isCompleteOrError()) { QDeclarativeError error; error.setDescription(QLatin1String("QDeclarativeDomDocument supports local types only")); d->errors << error; td->release(); - component->release(); - return false; - } - - compiler.compile(engine, td, component); - - if (compiler.isError()) { - d->errors = compiler.errors(); - td->release(); - component->release(); return false; } - for (int i = 0; i < td->data.imports().size(); ++i) { - QDeclarativeScriptParser::Import parserImport = td->data.imports().at(i); + for (int i = 0; i < td->parser().imports().size(); ++i) { + QDeclarativeScriptParser::Import parserImport = td->parser().imports().at(i); QDeclarativeDomImport domImport; domImport.d->type = static_cast<QDeclarativeDomImportPrivate::Type>(parserImport.type); domImport.d->uri = parserImport.uri; @@ -184,12 +169,12 @@ bool QDeclarativeDomDocument::load(QDeclarativeEngine *engine, const QByteArray d->imports += domImport; } - if (td->data.tree()) { - d->root = td->data.tree(); + if (td->parser().tree()) { + d->root = td->parser().tree(); d->root->addref(); } - component->release(); + td->release(); return true; } diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index c5a5c18..e77a53e 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -259,7 +259,7 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), - typeManager(e), importDatabase(e), uniqueId(1) + typeLoader(e), importDatabase(e), uniqueId(1) { if (!qt_QmlQtModule_registered) { qt_QmlQtModule_registered = true; @@ -565,7 +565,7 @@ QDeclarativeEngine::~QDeclarativeEngine() void QDeclarativeEngine::clearComponentCache() { Q_D(QDeclarativeEngine); - d->typeManager.clearCache(); + d->typeLoader.clearCache(); } /*! @@ -1716,6 +1716,9 @@ void QDeclarativeEnginePrivate::sendQuit() { Q_Q(QDeclarativeEngine); emit q->quit(); + if (q->receivers(SIGNAL(quit())) == 0) { + qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it."); + } } static void dumpwarning(const QDeclarativeError &error) @@ -2110,7 +2113,7 @@ bool QDeclarativeEnginePrivate::isQObject(int t) QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const { int t = v.userType(); - if (m_compositeTypes.contains(t)) { + if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) { if (ok) *ok = true; return *(QObject **)(v.constData()); } else { diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index db2db35..dc7315d 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -56,7 +56,7 @@ #include "qdeclarativeengine.h" #include "private/qdeclarativeclassfactory_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" +#include "private/qdeclarativetypeloader_p.h" #include "private/qdeclarativeimport_p.h" #include "private/qpodvector_p.h" #include "qdeclarative.h" @@ -239,7 +239,7 @@ public: mutable QMutex mutex; - QDeclarativeCompositeTypeManager typeManager; + QDeclarativeTypeLoader typeLoader; QDeclarativeImportDatabase importDatabase; QString offlineStoragePath; diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 3af892d..9d74238 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -192,7 +192,7 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam if (!(hints & ImplicitObject)) { local.coreIndex = -1; lastData = &local; - return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; + return QScriptClass::HandlesWriteAccess; } return 0; @@ -625,11 +625,12 @@ private: char data[4 * sizeof(void *)]; int type; + bool isObjectType; }; } MetaCallArgument::MetaCallArgument() -: type(QVariant::Invalid) +: type(QVariant::Invalid), isObjectType(false) { } @@ -744,12 +745,23 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, new (&data) QVariant(); type = -1; - QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); + QVariant v = priv->scriptValueToVariant(value); if (v.userType() == callType) { *((QVariant *)&data) = v; } else if (v.canConvert((QVariant::Type)callType)) { *((QVariant *)&data) = v; ((QVariant *)&data)->convert((QVariant::Type)callType); + } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) { + QObject *obj = priv->toQObject(v); + + if (obj) { + const QMetaObject *objMo = obj->metaObject(); + while (objMo && objMo != mo) objMo = objMo->superClass(); + if (!objMo) obj = 0; + } + + *((QVariant *)&data) = QVariant(callType, &obj); } else { *((QVariant *)&data) = QVariant(callType, (void *)0); } diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 515c4d6..d0dd2e8 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -42,7 +42,6 @@ #include "qdeclarativeproperty.h" #include "private/qdeclarativeproperty_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "qdeclarative.h" #include "private/qdeclarativebinding_p.h" #include "qdeclarativecontext.h" diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 839d79f..08503c2 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -134,8 +134,9 @@ QDeclarativePropertyCache::~QDeclarativePropertyCache() void QDeclarativePropertyCache::clear() { - for (int ii = 0; ii < indexCache.count(); ++ii) - indexCache.at(ii)->release(); + for (int ii = 0; ii < indexCache.count(); ++ii) { + if (indexCache.at(ii)) indexCache.at(ii)->release(); + } for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) @@ -156,14 +157,27 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj Q_ASSERT(metaObject); QDeclarativePropertyCache::Data rv; - int idx = metaObject->indexOfProperty(property.toUtf8()); - if (idx != -1) { - rv.load(metaObject->property(idx)); - return rv; + { + const QMetaObject *cmo = metaObject; + while (cmo) { + int idx = metaObject->indexOfProperty(property.toUtf8()); + if (idx != -1) { + QMetaProperty p = metaObject->property(idx); + if (p.isScriptable()) { + rv.load(metaObject->property(idx)); + return rv; + } else { + while (cmo && cmo->propertyOffset() >= idx) + cmo = cmo->superClass(); + } + } else { + cmo = 0; + } + } } int methodCount = metaObject->methodCount(); - for (int ii = methodCount - 1; ii >= 2; --ii) { // >=2 to block the destroyed signal + for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; @@ -189,8 +203,9 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const cache->stringCache = stringCache; cache->identifierCache = identifierCache; - for (int ii = 0; ii < indexCache.count(); ++ii) - indexCache.at(ii)->addref(); + for (int ii = 0; ii < indexCache.count(); ++ii) { + if (indexCache.at(ii)) indexCache.at(ii)->addref(); + } for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) (*iter)->addref(); for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter) @@ -210,6 +225,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb indexCache.resize(propCount); for (int ii = propOffset; ii < propCount; ++ii) { QMetaProperty p = metaObject->property(ii); + if (!p.isScriptable()) + continue; + QString propName = QString::fromUtf8(p.name()); RData *data = new RData; @@ -275,6 +293,10 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb indexCache.resize(propCount); for (int ii = propCount - 1; ii >= 0; --ii) { QMetaProperty p = metaObject->property(ii); + if (!p.isScriptable()) { + indexCache[ii] = 0; + continue; + } QString propName = QString::fromUtf8(p.name()); RData *data = new RData; @@ -294,7 +316,7 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb } int methodCount = metaObject->methodCount(); - for (int ii = methodCount - 1; ii >= 2; --ii) { // >=2 to block the destroyed signal + for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index 0b3b35f..c956051 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -387,7 +387,6 @@ bool ProcessAST::visit(AST::UiImport *node) if (uri.endsWith(QLatin1String(".js"))) { import.type = QDeclarativeScriptParser::Import::Script; - _parser->_refUrls << QUrl(uri); } else { import.type = QDeclarativeScriptParser::Import::File; } @@ -878,11 +877,6 @@ QList<QDeclarativeScriptParser::TypeReference*> QDeclarativeScriptParser::refere return _refTypes; } -QList<QUrl> QDeclarativeScriptParser::referencedResources() const -{ - return _refUrls; -} - Object *QDeclarativeScriptParser::tree() const { return root; @@ -960,6 +954,217 @@ QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extra return rv; } +#define CHECK_LINE if(l.currentLineNo() != startLine) return rv; +#define CHECK_TOKEN(t) if (token != QDeclarativeJSGrammar:: t) return rv; + +static const int uriTokens[] = { + QDeclarativeJSGrammar::T_IDENTIFIER, + QDeclarativeJSGrammar::T_PROPERTY, + QDeclarativeJSGrammar::T_SIGNAL, + QDeclarativeJSGrammar::T_READONLY, + QDeclarativeJSGrammar::T_ON, + QDeclarativeJSGrammar::T_BREAK, + QDeclarativeJSGrammar::T_CASE, + QDeclarativeJSGrammar::T_CATCH, + QDeclarativeJSGrammar::T_CONTINUE, + QDeclarativeJSGrammar::T_DEFAULT, + QDeclarativeJSGrammar::T_DELETE, + QDeclarativeJSGrammar::T_DO, + QDeclarativeJSGrammar::T_ELSE, + QDeclarativeJSGrammar::T_FALSE, + QDeclarativeJSGrammar::T_FINALLY, + QDeclarativeJSGrammar::T_FOR, + QDeclarativeJSGrammar::T_FUNCTION, + QDeclarativeJSGrammar::T_IF, + QDeclarativeJSGrammar::T_IN, + QDeclarativeJSGrammar::T_INSTANCEOF, + QDeclarativeJSGrammar::T_NEW, + QDeclarativeJSGrammar::T_NULL, + QDeclarativeJSGrammar::T_RETURN, + QDeclarativeJSGrammar::T_SWITCH, + QDeclarativeJSGrammar::T_THIS, + QDeclarativeJSGrammar::T_THROW, + QDeclarativeJSGrammar::T_TRUE, + QDeclarativeJSGrammar::T_TRY, + QDeclarativeJSGrammar::T_TYPEOF, + QDeclarativeJSGrammar::T_VAR, + QDeclarativeJSGrammar::T_VOID, + QDeclarativeJSGrammar::T_WHILE, + QDeclarativeJSGrammar::T_CONST, + QDeclarativeJSGrammar::T_DEBUGGER, + QDeclarativeJSGrammar::T_RESERVED_WORD, + QDeclarativeJSGrammar::T_WITH, + + QDeclarativeJSGrammar::EOF_SYMBOL +}; +static inline bool isUriToken(int token) +{ + const int *current = uriTokens; + while (*current != QDeclarativeJSGrammar::EOF_SYMBOL) { + if (*current == token) + return true; + ++current; + } + return false; +} + +QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMetaData(QString &script) +{ + JavaScriptMetaData rv; + + QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; + + const QString pragma(QLatin1String("pragma")); + const QString js(QLatin1String(".js")); + const QString library(QLatin1String("library")); + + QDeclarativeJS::Lexer l(0); + l.setCode(script, 0); + + int token = l.lex(); + + while (true) { + if (token != QDeclarativeJSGrammar::T_DOT) + return rv; + + int startOffset = l.tokenOffset(); + int startLine = l.currentLineNo(); + + token = l.lex(); + + CHECK_LINE; + + if (token == QDeclarativeJSGrammar::T_IMPORT) { + + // .import <URI> <Version> as <Identifier> + // .import <file.js> as <Identifier> + + token = l.lex(); + + CHECK_LINE; + + if (token == QDeclarativeJSGrammar::T_STRING_LITERAL) { + + QString file(l.characterBuffer(), l.characterCount()); + if (!file.endsWith(js)) + return rv; + + token = l.lex(); + + CHECK_TOKEN(T_AS); + CHECK_LINE; + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + if (!importId.at(0).isUpper()) + return rv; + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + Import import; + import.type = Import::Script; + import.uri = file; + import.qualifier = importId; + + rv.imports << import; + + } else { + // URI + QString uri; + QString version; + + while (true) { + if (!isUriToken(token)) + return rv; + + uri.append(QString(l.characterBuffer(), l.characterCount())); + + token = l.lex(); + CHECK_LINE; + if (token != QDeclarativeJSGrammar::T_DOT) + break; + + uri.append(QLatin1Char('.')); + + token = l.lex(); + CHECK_LINE; + } + + CHECK_TOKEN(T_NUMERIC_LITERAL); + version = script.mid(l.tokenOffset(), l.tokenLength()); + + token = l.lex(); + + CHECK_TOKEN(T_AS); + CHECK_LINE; + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + if (!importId.at(0).isUpper()) + return rv; + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + Import import; + import.type = Import::Library; + import.uri = uri; + import.version = version; + import.qualifier = importId; + + rv.imports << import; + } + + } else if (token == QDeclarativeJSGrammar::T_IDENTIFIER && + script.mid(l.tokenOffset(), l.tokenLength()) == pragma) { + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); + int endOffset = l.tokenLength() + l.tokenOffset(); + + if (pragmaValue == QLatin1String("library")) { + pragmas |= QDeclarativeParser::Object::ScriptBlock::Shared; + replaceWithSpace(script, startOffset, endOffset - startOffset); + } else { + return rv; + } + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + } else { + return rv; + } + } + return rv; +} + void QDeclarativeScriptParser::clear() { if (root) { diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h index 28e960b..6319e11 100644 --- a/src/declarative/qml/qdeclarativescriptparser_p.h +++ b/src/declarative/qml/qdeclarativescriptparser_p.h @@ -103,7 +103,6 @@ public: bool parse(const QByteArray &data, const QUrl &url = QUrl()); QList<TypeReference*> referencedTypes() const; - QList<QUrl> referencedResources() const; QDeclarativeParser::Object *tree() const; QList<Import> imports() const; @@ -112,7 +111,18 @@ public: QList<QDeclarativeError> errors() const; + class JavaScriptMetaData { + public: + JavaScriptMetaData() + : pragmas(QDeclarativeParser::Object::ScriptBlock::None) {} + + QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas; + QList<Import> imports; + }; + static QDeclarativeParser::Object::ScriptBlock::Pragmas extractPragmas(QString &); + static JavaScriptMetaData extractMetaData(QString &); + // ### private: TypeReference *findOrCreateType(const QString &name); @@ -127,7 +137,6 @@ public: QDeclarativeParser::Object *root; QList<Import> _imports; QList<TypeReference*> _refTypes; - QList<QUrl> _refUrls; QString _scriptFile; QDeclarativeScriptParserJsASTData *data; }; diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp new file mode 100644 index 0000000..8c291f2 --- /dev/null +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -0,0 +1,1070 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativetypeloader_p.h" + +#include <private/qdeclarativeengine_p.h> +#include <private/qdeclarativecompiler_p.h> +#include <private/qdeclarativecomponent_p.h> + +#include <QtDeclarative/qdeclarativecomponent.h> +#include <QtCore/qdebug.h> +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> + +QT_BEGIN_NAMESPACE + +/*! +\class QDeclarativeDataBlob +\brief The QDeclarativeDataBlob encapsulates a data request that can be issued to a QDeclarativeDataLoader. +\internal + +QDeclarativeDataBlob's are loaded by a QDeclarativeDataLoader. The user creates the QDeclarativeDataBlob +and then calls QDeclarativeDataLoader::load() or QDeclarativeDataLoader::loadWithStaticData() to load it. +The QDeclarativeDataLoader invokes callbacks on the QDeclarativeDataBlob as data becomes available. +*/ + +/*! +\enum QDeclarativeDataBlob::Status + +\o Null The blob has not yet been loaded by a QDeclarativeDataLoader +\o Loading The blob is loading network data. The QDeclarativeDataBlob::setData() callback has not yet been +invoked or has not yet returned. +\o WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status +only occurs after the QDeclarativeDataBlob::setData() callback has been made, and when the blob has outstanding +dependencies. +\o Complete The blob's data has been loaded and all dependencies are done. +\o Error An error has been set on this blob. +*/ + +/*! +\enum QDeclarativeDataBlob::Type +\o QmlFile This is a QDeclarativeTypeData +\o JavaScriptFile This is a QDeclarativeScriptData +\o QmldirFile This is a QDeclarativeQmldirData +*/ + +/*! +Create a new QDeclarativeDataBlob for \a url and of the provided \a type. +*/ +QDeclarativeDataBlob::QDeclarativeDataBlob(const QUrl &url, Type type) +: m_type(type), m_status(Null), m_progress(0), m_url(url), m_finalUrl(url), m_manager(0), + m_redirectCount(0), m_inCallback(false), m_isDone(false) +{ +} + +/*! \internal */ +QDeclarativeDataBlob::~QDeclarativeDataBlob() +{ + Q_ASSERT(m_waitingOnMe.isEmpty()); + + cancelAllWaitingFor(); +} + +/*! +Returns the type provided to the constructor. +*/ +QDeclarativeDataBlob::Type QDeclarativeDataBlob::type() const +{ + return m_type; +} + +/*! +Returns the blob's status. +*/ +QDeclarativeDataBlob::Status QDeclarativeDataBlob::status() const +{ + return m_status; +} + +/*! +Returns true if the status is Null. +*/ +bool QDeclarativeDataBlob::isNull() const +{ + return m_status == Null; +} + +/*! +Returns true if the status is Loading. +*/ +bool QDeclarativeDataBlob::isLoading() const +{ + return m_status == Loading; +} + +/*! +Returns true if the status is WaitingForDependencies. +*/ +bool QDeclarativeDataBlob::isWaiting() const +{ + return m_status == WaitingForDependencies; +} + +/*! +Returns true if the status is Complete. +*/ +bool QDeclarativeDataBlob::isComplete() const +{ + return m_status == Complete; +} + +/*! +Returns true if the status is Error. +*/ +bool QDeclarativeDataBlob::isError() const +{ + return m_status == Error; +} + +/*! +Returns true if the status is Complete or Error. +*/ +bool QDeclarativeDataBlob::isCompleteOrError() const +{ + return isComplete() || isError(); +} + +/*! +Returns the data download progress from 0 to 1. +*/ +qreal QDeclarativeDataBlob::progress() const +{ + return m_progress; +} + +/*! +Returns the blob url passed to the constructor. If a network redirect +happens while fetching the data, this url remains the same. + +\sa finalUrl() +*/ +QUrl QDeclarativeDataBlob::url() const +{ + return m_url; +} + +/*! +Returns the final url of the data. Initially this is the same as +url(), but if a network redirect happens while fetching the data, this url +is updated to reflect the new location. +*/ +QUrl QDeclarativeDataBlob::finalUrl() const +{ + return m_finalUrl; +} + +/*! +Return the errors on this blob. +*/ +QList<QDeclarativeError> QDeclarativeDataBlob::errors() const +{ + return m_errors; +} + +/*! +Mark this blob as having \a errors. + +All outstanding dependencies will be cancelled. Requests to add new dependencies +will be ignored. Entry into the Error state is irreversable, although you can change the +specific errors by additional calls to setError. +*/ +void QDeclarativeDataBlob::setError(const QDeclarativeError &errors) +{ + QList<QDeclarativeError> l; + l << errors; + setError(l); +} + +/*! +\override +*/ +void QDeclarativeDataBlob::setError(const QList<QDeclarativeError> &errors) +{ + m_status = Error; + m_errors = errors; + + cancelAllWaitingFor(); + + if (!m_inCallback) + tryDone(); +} + +/*! +Wait for \a blob to become complete or to error. If \a blob is already +complete or in error, or this blob is already complete, this has no effect. +*/ +void QDeclarativeDataBlob::addDependency(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(status() != Null); + + if (!blob || + blob->status() == Error || blob->status() == Complete || + status() == Error || status() == Complete || + m_waitingFor.contains(blob)) + return; + + blob->addref(); + m_status = WaitingForDependencies; + m_waitingFor.append(blob); + blob->m_waitingOnMe.append(this); +} + +/*! +\fn void QDeclarativeDataBlob::dataReceived(const QByteArray &data) + +Invoked when data for the blob is received. Implementors should use this callback +to determine a blob's dependencies. Within this callback you may call setError() +or addDependency(). +*/ + +/*! +Invoked once data has either been received or a network error occurred, and all +dependencies are complete. + +You can set an error in this method, but you cannot add new dependencies. Implementors +should use this callback to finalize processing of data. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::done() +{ +} + +/*! +Invoked if there is a network error while fetching this blob. + +The default implementation sets an appropriate QDeclarativeError. +*/ +void QDeclarativeDataBlob::networkError(QNetworkReply::NetworkError networkError) +{ + Q_UNUSED(networkError); + + QDeclarativeError error; + error.setUrl(m_finalUrl); + + const char *errorString = 0; + switch (networkError) { + default: + errorString = "Network error"; + break; + case QNetworkReply::ConnectionRefusedError: + errorString = "Connection refused"; + break; + case QNetworkReply::RemoteHostClosedError: + errorString = "Remote host closed the connection"; + break; + case QNetworkReply::HostNotFoundError: + errorString = "Host not found"; + break; + case QNetworkReply::TimeoutError: + errorString = "Timeout"; + break; + case QNetworkReply::ProxyConnectionRefusedError: + case QNetworkReply::ProxyConnectionClosedError: + case QNetworkReply::ProxyNotFoundError: + case QNetworkReply::ProxyTimeoutError: + case QNetworkReply::ProxyAuthenticationRequiredError: + case QNetworkReply::UnknownProxyError: + errorString = "Proxy error"; + break; + case QNetworkReply::ContentAccessDenied: + errorString = "Access denied"; + break; + case QNetworkReply::ContentNotFoundError: + errorString = "File not found"; + break; + case QNetworkReply::AuthenticationRequiredError: + errorString = "Authentication required"; + break; + }; + + error.setDescription(QLatin1String(errorString)); + + setError(error); +} + +/*! +Called if \a blob, which was previously waited for, has an error. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::dependencyError(QDeclarativeDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called if \a blob, which was previously waited for, has completed. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::dependencyComplete(QDeclarativeDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called when all blobs waited for have completed. This occurs regardless of +whether they are in error, or complete state. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::allDependenciesDone() +{ +} + +/*! +Called when the download progress of this blob changes. \a progress goes +from 0 to 1. +*/ +void QDeclarativeDataBlob::downloadProgressChanged(qreal progress) +{ + Q_UNUSED(progress); +} + +void QDeclarativeDataBlob::tryDone() +{ + if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) { + if (status() != Error) + m_status = Complete; + + m_isDone = true; + done(); + notifyAllWaitingOnMe(); + } +} + +void QDeclarativeDataBlob::cancelAllWaitingFor() +{ + while (m_waitingFor.count()) { + QDeclarativeDataBlob *blob = m_waitingFor.takeLast(); + + Q_ASSERT(blob->m_waitingOnMe.contains(this)); + + blob->m_waitingOnMe.removeOne(this); + + blob->release(); + } +} + +void QDeclarativeDataBlob::notifyAllWaitingOnMe() +{ + while (m_waitingOnMe.count()) { + QDeclarativeDataBlob *blob = m_waitingOnMe.takeLast(); + + Q_ASSERT(blob->m_waitingFor.contains(this)); + + blob->notifyComplete(this); + } +} + +void QDeclarativeDataBlob::notifyComplete(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(m_waitingFor.contains(blob)); + Q_ASSERT(blob->status() == Error || blob->status() == Complete); + + m_inCallback = true; + + if (blob->status() == Error) { + dependencyError(blob); + } else if (blob->status() == Complete) { + dependencyComplete(blob); + } + + m_waitingFor.removeOne(blob); + blob->release(); + + if (!isError() && m_waitingFor.isEmpty()) + allDependenciesDone(); + + m_inCallback = false; + + tryDone(); +} + +/*! +\class QDeclarativeDataLoader +\brief The QDeclarativeDataLoader class abstracts loading files and their dependecies over the network. +\internal + +The QDeclarativeDataLoader class is provided for the exclusive use of the QDeclarativeTypeLoader class. + +Clients create QDeclarativeDataBlob instances and submit them to the QDeclarativeDataLoader class +through the QDeclarativeDataLoader::load() or QDeclarativeDataLoader::loadWithStaticData() methods. +The loader then fetches the data over the network or from the local file system in an efficient way. +QDeclarativeDataBlob is an abstract class, so should always be specialized. + +Once data is received, the QDeclarativeDataBlob::dataReceived() method is invoked on the blob. The +derived class should use this callback to process the received data. Processing of the data can +result in an error being set (QDeclarativeDataBlob::setError()), or one or more dependencies being +created (QDeclarativeDataBlob::addDependency()). Dependencies are other QDeclarativeDataBlob's that +are required before processing can fully complete. + +To complete processing, the QDeclarativeDataBlob::done() callback is invoked. done() is called when +one of these three preconditions are met. + +1. The QDeclarativeDataBlob has no dependencies. +2. The QDeclarativeDataBlob has an error set. +3. All the QDeclarativeDataBlob's dependencies are themselves "done()". + +Thus QDeclarativeDataBlob::done() will always eventually be called, even if the blob has an error set. +*/ + +/*! +Create a new QDeclarativeDataLoader for \a engine. +*/ +QDeclarativeDataLoader::QDeclarativeDataLoader(QDeclarativeEngine *engine) +: m_engine(engine) +{ +} + +/*! \internal */ +QDeclarativeDataLoader::~QDeclarativeDataLoader() +{ + for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) + (*iter)->release(); +} + +/*! +Load the provided \a blob from the network or filesystem. +*/ +void QDeclarativeDataLoader::load(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(blob->status() == QDeclarativeDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_status = QDeclarativeDataBlob::Loading; + + if (blob->m_url.isEmpty()) { + QDeclarativeError error; + error.setDescription(QLatin1String("Invalid null URL")); + blob->setError(error); + return; + } + + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(blob->m_url); + + if (!lf.isEmpty()) { + QFile file(lf); + if (file.open(QFile::ReadOnly)) { + QByteArray data = file.readAll(); + + blob->m_progress = 1.; + blob->downloadProgressChanged(1.); + + setData(blob, data); + } else { + blob->networkError(QNetworkReply::ContentNotFoundError); + } + + } else { + + blob->m_manager = this; + QNetworkReply *reply = m_engine->networkAccessManager()->get(QNetworkRequest(blob->m_url)); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(networkReplyProgress(qint64,qint64))); + QObject::connect(reply, SIGNAL(finished()), + this, SLOT(networkReplyFinished())); + m_networkReplies.insert(reply, blob); + + blob->addref(); + } +} + +#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 + +void QDeclarativeDataLoader::networkReplyFinished() +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + QDeclarativeDataBlob *blob = m_networkReplies.take(reply); + + Q_ASSERT(blob); + + blob->m_redirectCount++; + + if (blob->m_redirectCount < DATALOADER_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + blob->m_finalUrl = url; + + QNetworkReply *reply = m_engine->networkAccessManager()->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + m_networkReplies.insert(reply, blob); + return; + } + } + + if (reply->error()) { + blob->networkError(reply->error()); + } else { + QByteArray data = reply->readAll(); + setData(blob, data); + } + + blob->release(); +} + +void QDeclarativeDataLoader::networkReplyProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + QDeclarativeDataBlob *blob = m_networkReplies.value(reply); + + Q_ASSERT(blob); + + if (bytesTotal != 0) { + blob->m_progress = bytesReceived / bytesTotal; + blob->downloadProgressChanged(blob->m_progress); + } +} + +/*! +Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case. +*/ +void QDeclarativeDataLoader::loadWithStaticData(QDeclarativeDataBlob *blob, const QByteArray &data) +{ + Q_ASSERT(blob->status() == QDeclarativeDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_status = QDeclarativeDataBlob::Loading; + + setData(blob, data); +} + +/*! +Return the QDeclarativeEngine associated with this loader +*/ +QDeclarativeEngine *QDeclarativeDataLoader::engine() const +{ + return m_engine; +} + +void QDeclarativeDataLoader::setData(QDeclarativeDataBlob *blob, const QByteArray &data) +{ + blob->m_inCallback = true; + + blob->dataReceived(data); + + if (!blob->isError() && !blob->isWaiting()) + blob->allDependenciesDone(); + + if (blob->status() != QDeclarativeDataBlob::Error) + blob->m_status = QDeclarativeDataBlob::WaitingForDependencies; + + blob->m_inCallback = false; + + blob->tryDone(); +} + +/*! +\class QDeclarativeTypeLoader +*/ +QDeclarativeTypeLoader::QDeclarativeTypeLoader(QDeclarativeEngine *engine) +: QDeclarativeDataLoader(engine) +{ +} + +QDeclarativeTypeLoader::~QDeclarativeTypeLoader() +{ + clearCache(); +} + +/*! +Return a QDeclarativeTypeData for \a url. The QDeclarativeTypeData may be cached. +*/ +QDeclarativeTypeData *QDeclarativeTypeLoader::get(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeTypeData *typeData = m_typeCache.value(url); + + if (!typeData) { + typeData = new QDeclarativeTypeData(url, None, this); + m_typeCache.insert(url, typeData); + QDeclarativeDataLoader::load(typeData); + } + + typeData->addref(); + return typeData; +} + +/*! +Return a QDeclarativeTypeData for \a data with the provided base \a url. The +QDeclarativeTypeData will not be cached. +*/ +QDeclarativeTypeData *QDeclarativeTypeLoader::get(const QByteArray &data, const QUrl &url, Options options) +{ + QDeclarativeTypeData *typeData = new QDeclarativeTypeData(url, options, this); + QDeclarativeDataLoader::loadWithStaticData(typeData, data); + return typeData; +} + +/*! +Return a QDeclarativeScriptData for \a url. The QDeclarativeScriptData may be cached. +*/ +QDeclarativeScriptData *QDeclarativeTypeLoader::getScript(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeScriptData *scriptData = m_scriptCache.value(url); + + if (!scriptData) { + scriptData = new QDeclarativeScriptData(url); + m_scriptCache.insert(url, scriptData); + QDeclarativeDataLoader::load(scriptData); + } + + scriptData->addref(); + return scriptData; +} + +/*! +Return a QDeclarativeQmldirData for \a url. The QDeclarativeQmldirData may be cached. +*/ +QDeclarativeQmldirData *QDeclarativeTypeLoader::getQmldir(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeQmldirData *qmldirData = m_qmldirCache.value(url); + + if (!qmldirData) { + qmldirData = new QDeclarativeQmldirData(url); + m_qmldirCache.insert(url, qmldirData); + QDeclarativeDataLoader::load(qmldirData); + } + + qmldirData->addref(); + return qmldirData; +} + +void QDeclarativeTypeLoader::clearCache() +{ + for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) + (*iter)->release(); + for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter) + (*iter)->release(); + for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) + (*iter)->release(); + + m_typeCache.clear(); + m_scriptCache.clear(); + m_qmldirCache.clear(); +} + + +QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options, + QDeclarativeTypeLoader *manager) +: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false), + m_compiledData(0), m_component(0), m_typeLoader(manager) +{ +} + +QDeclarativeTypeData::~QDeclarativeTypeData() +{ + for (int ii = 0; ii < m_scripts.count(); ++ii) + m_scripts.at(ii).script->release(); + for (int ii = 0; ii < m_qmldirs.count(); ++ii) + m_qmldirs.at(ii)->release(); + for (int ii = 0; ii < m_types.count(); ++ii) + if (m_types.at(ii).typeData) m_types.at(ii).typeData->release(); + if (m_compiledData) + m_compiledData->release(); +} + +QDeclarativeTypeLoader *QDeclarativeTypeData::typeLoader() const +{ + return m_typeLoader; +} + +const QDeclarativeImports &QDeclarativeTypeData::imports() const +{ + return m_imports; +} + +const QDeclarativeScriptParser &QDeclarativeTypeData::parser() const +{ + return scriptParser; +} + +const QList<QDeclarativeTypeData::TypeReference> &QDeclarativeTypeData::resolvedTypes() const +{ + return m_types; +} + +const QList<QDeclarativeTypeData::ScriptReference> &QDeclarativeTypeData::resolvedScripts() const +{ + return m_scripts; +} + +QDeclarativeCompiledData *QDeclarativeTypeData::compiledData() const +{ + if (m_compiledData) + m_compiledData->addref(); + + return m_compiledData; +} + +QDeclarativeComponent *QDeclarativeTypeData::component() const +{ + if (!m_component) { + + if (m_compiledData) { + m_component = new QDeclarativeComponent(typeLoader()->engine(), m_compiledData, -1, -1, 0); + } else { + m_component = new QDeclarativeComponent(typeLoader()->engine()); + QDeclarativeComponentPrivate::get(m_component)->url = finalUrl(); + QDeclarativeComponentPrivate::get(m_component)->state.errors = errors(); + } + + } + + return m_component; +} + +void QDeclarativeTypeData::registerCallback(TypeDataCallback *callback) +{ + Q_ASSERT(!m_callbacks.contains(callback)); + m_callbacks.append(callback); +} + +void QDeclarativeTypeData::unregisterCallback(TypeDataCallback *callback) +{ + Q_ASSERT(m_callbacks.contains(callback)); + m_callbacks.removeOne(callback); + Q_ASSERT(!m_callbacks.contains(callback)); +} + +void QDeclarativeTypeData::done() +{ + addref(); + + // Check all script dependencies for errors + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + Q_ASSERT(script.script->isCompleteOrError()); + if (script.script->isError()) { + QList<QDeclarativeError> errors = script.script->errors(); + QDeclarativeError error; + error.setUrl(finalUrl()); + error.setLine(script.location.line); + error.setColumn(script.location.column); + error.setDescription(typeLoader()->tr("Script %1 unavailable").arg(script.script->url().toString())); + errors.prepend(error); + setError(errors); + } + } + + // Check all type dependencies for errors + for (int ii = 0; !isError() && ii < m_types.count(); ++ii) { + const TypeReference &type = m_types.at(ii); + Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError()); + if (type.typeData && type.typeData->isError()) { + QString typeName = scriptParser.referencedTypes().at(ii)->name; + + QList<QDeclarativeError> errors = type.typeData->errors(); + QDeclarativeError error; + error.setUrl(finalUrl()); + error.setLine(type.location.line); + error.setColumn(type.location.column); + error.setDescription(typeLoader()->tr("Type %1 unavailable").arg(typeName)); + errors.prepend(error); + setError(errors); + } + } + + // Compile component + if (!isError()) + compile(); + + if (!(m_options & QDeclarativeTypeLoader::PreserveParser)) + scriptParser.clear(); + + // Notify callbacks + while (!m_callbacks.isEmpty()) { + TypeDataCallback *callback = m_callbacks.takeFirst(); + callback->typeDataReady(this); + } + + release(); +} + +void QDeclarativeTypeData::dataReceived(const QByteArray &data) +{ + if (!scriptParser.parse(data, finalUrl())) { + setError(scriptParser.errors()); + return; + } + + m_imports.setBaseUrl(finalUrl()); + + foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { + if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QDeclarativeQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } else if (import.type == QDeclarativeScriptParser::Import::Script) { + QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); + QDeclarativeScriptData *data = typeLoader()->getScript(scriptUrl); + addDependency(data); + + ScriptReference ref; + ref.location = import.location.start; + ref.qualifier = import.qualifier; + ref.script = data; + m_scripts << ref; + + } + } + + if (!finalUrl().scheme().isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir"))); + if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QDeclarativeQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } +} + +void QDeclarativeTypeData::allDependenciesDone() +{ + if (!m_typesResolved) { + resolveTypes(); + m_typesResolved = true; + } +} + +void QDeclarativeTypeData::downloadProgressChanged(qreal p) +{ + for (int ii = 0; ii < m_callbacks.count(); ++ii) { + TypeDataCallback *callback = m_callbacks.at(ii); + callback->typeDataProgress(this, p); + } +} + +void QDeclarativeTypeData::compile() +{ + Q_ASSERT(m_compiledData == 0); + + m_compiledData = new QDeclarativeCompiledData(typeLoader()->engine()); + m_compiledData->url = m_imports.baseUrl(); + m_compiledData->name = m_compiledData->url.toString(); + + QDeclarativeCompiler compiler; + if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { + setError(compiler.errors()); + m_compiledData->release(); + m_compiledData = 0; + } +} + +void QDeclarativeTypeData::resolveTypes() +{ + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_typeLoader->engine()); + QDeclarativeImportDatabase *importDatabase = &ep->importDatabase; + + // For local urls, add an implicit import "." as first (most overridden) lookup. + // This will also trigger the loading of the qmldir and the import of any native + // types from available plugins. + if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QDeclarativeScriptParser::Import::File, + qmldir->dirComponents(), 0); + } else { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QDeclarativeScriptParser::Import::File, + QDeclarativeDirComponents(), 0); + } + + foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { + QDeclarativeDirComponents qmldircomponentsnetwork; + if (import.type == QDeclarativeScriptParser::Import::Script) + continue; + + if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QDeclarativeQmldirData *qmldir = qmldirForUrl(qmldirUrl)) + qmldircomponentsnetwork = qmldir->dirComponents(); + } + + int vmaj = -1; + int vmin = -1; + + if (!import.version.isEmpty()) { + int dot = import.version.indexOf(QLatin1Char('.')); + if (dot < 0) { + vmaj = import.version.toInt(); + vmin = 0; + } else { + vmaj = import.version.left(dot).toInt(); + vmin = import.version.mid(dot+1).toInt(); + } + } + + QString errorString; + if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, + vmaj, vmin, import.type, qmldircomponentsnetwork, &errorString)) { + QDeclarativeError error; + error.setUrl(m_imports.baseUrl()); + error.setDescription(errorString); + error.setLine(import.location.start.line); + error.setColumn(import.location.start.column); + + setError(error); + return; + } + } + + foreach (QDeclarativeScriptParser::TypeReference *parserRef, scriptParser.referencedTypes()) { + QByteArray typeName = parserRef->name.toUtf8(); + + TypeReference ref; + + QUrl url; + int majorVersion; + int minorVersion; + QDeclarativeImportedNamespace *typeNamespace = 0; + QString errorString; + + if (!m_imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, + &typeNamespace, &errorString) || typeNamespace) { + // Known to not be a type: + // - known to be a namespace (Namespace {}) + // - type with unknown namespace (UnknownNamespace.SomeType {}) + QDeclarativeError error; + error.setUrl(m_imports.baseUrl()); + QString userTypeName = parserRef->name; + userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); + if (typeNamespace) + error.setDescription(typeLoader()->tr("Namespace %1 cannot be used as a type").arg(userTypeName)); + else + error.setDescription(typeLoader()->tr("%1 %2").arg(userTypeName).arg(errorString)); + + if (!parserRef->refObjects.isEmpty()) { + QDeclarativeParser::Object *obj = parserRef->refObjects.first(); + error.setLine(obj->location.start.line); + error.setColumn(obj->location.start.column); + } + + setError(error); + return; + } + + if (ref.type) { + foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { + // store namespace for DOM + obj->majorVersion = majorVersion; + obj->minorVersion = minorVersion; + } + } else { + ref.typeData = typeLoader()->get(url); + addDependency(ref.typeData); + } + + if (parserRef->refObjects.count()) + ref.location = parserRef->refObjects.first()->location.start; + + m_types << ref; + } +} + +QDeclarativeQmldirData *QDeclarativeTypeData::qmldirForUrl(const QUrl &url) +{ + for (int ii = 0; ii < m_qmldirs.count(); ++ii) { + if (m_qmldirs.at(ii)->url() == url) + return m_qmldirs.at(ii); + } + return 0; +} + +QDeclarativeScriptData::QDeclarativeScriptData(const QUrl &url) +: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None) +{ +} + +QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptData::pragmas() const +{ + return m_pragmas; +} + +QString QDeclarativeScriptData::scriptSource() const +{ + return m_source; +} + +void QDeclarativeScriptData::dataReceived(const QByteArray &data) +{ + m_source = QString::fromUtf8(data); + m_pragmas = QDeclarativeScriptParser::extractPragmas(m_source); +} + +QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url) +: QDeclarativeDataBlob(url, QmldirFile) +{ +} + +const QDeclarativeDirComponents &QDeclarativeQmldirData::dirComponents() const +{ + return m_components; +} + +void QDeclarativeQmldirData::dataReceived(const QByteArray &data) +{ + QDeclarativeDirParser parser; + parser.setSource(QString::fromUtf8(data)); + parser.parse(); + m_components = parser.components(); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h new file mode 100644 index 0000000..7381f28 --- /dev/null +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVETYPELOADER_P_H +#define QDECLARATIVETYPELOADER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtNetwork/qnetworkreply.h> +#include <QtDeclarative/qdeclarativeerror.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <private/qdeclarativescriptparser_p.h> +#include <private/qdeclarativedirparser_p.h> +#include <private/qdeclarativeimport_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeScriptData; +class QDeclarativeQmldirData; +class QDeclarativeTypeLoader; +class QDeclarativeCompiledData; +class QDeclarativeComponentPrivate; +class QDeclarativeTypeData; +class QDeclarativeDataLoader; + +class Q_AUTOTEST_EXPORT QDeclarativeDataBlob : public QDeclarativeRefCount +{ +public: + enum Status { + Null, // Prior to QDeclarativeDataLoader::load() + Loading, // Prior to data being received and dataReceived() being called + WaitingForDependencies, // While there are outstanding addDependency()s + Complete, // Finished + Error, // Error + }; + + enum Type { + QmlFile, + JavaScriptFile, + QmldirFile + }; + + QDeclarativeDataBlob(const QUrl &, Type); + virtual ~QDeclarativeDataBlob(); + + Type type() const; + + Status status() const; + bool isNull() const; + bool isLoading() const; + bool isWaiting() const; + bool isComplete() const; + bool isError() const; + bool isCompleteOrError() const; + + qreal progress() const; + + QUrl url() const; + QUrl finalUrl() const; + + QList<QDeclarativeError> errors() const; + + void setError(const QDeclarativeError &); + void setError(const QList<QDeclarativeError> &errors); + + void addDependency(QDeclarativeDataBlob *); + +protected: + virtual void dataReceived(const QByteArray &) = 0; + + virtual void done(); + virtual void networkError(QNetworkReply::NetworkError); + + virtual void dependencyError(QDeclarativeDataBlob *); + virtual void dependencyComplete(QDeclarativeDataBlob *); + virtual void allDependenciesDone(); + + virtual void downloadProgressChanged(qreal); + +private: + friend class QDeclarativeDataLoader; + void tryDone(); + void cancelAllWaitingFor(); + void notifyAllWaitingOnMe(); + void notifyComplete(QDeclarativeDataBlob *); + + Type m_type; + Status m_status; + qreal m_progress; + + QUrl m_url; + QUrl m_finalUrl; + + // List of QDeclarativeDataBlob's that are waiting for me to complete. + QList<QDeclarativeDataBlob *> m_waitingOnMe; + + // List of QDeclarativeDataBlob's that I am waiting for to complete. + QList<QDeclarativeDataBlob *> m_waitingFor; + + // Manager that is currently fetching data for me + QDeclarativeDataLoader *m_manager; + int m_redirectCount:30; + bool m_inCallback:1; + bool m_isDone:1; + + QList<QDeclarativeError> m_errors; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeDataLoader : public QObject +{ + Q_OBJECT +public: + QDeclarativeDataLoader(QDeclarativeEngine *); + ~QDeclarativeDataLoader(); + + void load(QDeclarativeDataBlob *); + void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &); + + QDeclarativeEngine *engine() const; + +private slots: + void networkReplyFinished(); + void networkReplyProgress(qint64,qint64); + +private: + void setData(QDeclarativeDataBlob *, const QByteArray &); + + QDeclarativeEngine *m_engine; + typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies; + NetworkReplies m_networkReplies; +}; + + +class Q_AUTOTEST_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader +{ + Q_OBJECT +public: + QDeclarativeTypeLoader(QDeclarativeEngine *); + ~QDeclarativeTypeLoader(); + + enum Option { + None, + PreserveParser + }; + Q_DECLARE_FLAGS(Options, Option) + + QDeclarativeTypeData *get(const QUrl &url); + QDeclarativeTypeData *get(const QByteArray &, const QUrl &url, Options = None); + void clearCache(); + + QDeclarativeScriptData *getScript(const QUrl &); + QDeclarativeQmldirData *getQmldir(const QUrl &); +private: + typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache; + typedef QHash<QUrl, QDeclarativeScriptData *> ScriptCache; + typedef QHash<QUrl, QDeclarativeQmldirData *> QmldirCache; + + TypeCache m_typeCache; + ScriptCache m_scriptCache; + QmldirCache m_qmldirCache; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options) + +class Q_AUTOTEST_EXPORT QDeclarativeTypeData : public QDeclarativeDataBlob +{ +public: + struct TypeReference + { + TypeReference() : type(0), typeData(0) {} + + QDeclarativeParser::Location location; + QDeclarativeType *type; + QDeclarativeTypeData *typeData; + }; + + struct ScriptReference + { + ScriptReference() : script(0) {} + + QDeclarativeParser::Location location; + QString qualifier; + QDeclarativeScriptData *script; + }; + + QDeclarativeTypeData(const QUrl &, QDeclarativeTypeLoader::Options, QDeclarativeTypeLoader *); + ~QDeclarativeTypeData(); + + QDeclarativeTypeLoader *typeLoader() const; + + const QDeclarativeImports &imports() const; + const QDeclarativeScriptParser &parser() const; + + const QList<TypeReference> &resolvedTypes() const; + const QList<ScriptReference> &resolvedScripts() const; + + QDeclarativeCompiledData *compiledData() const; + QDeclarativeComponent *component() const; + + // Used by QDeclarativeComponent to get notifications + struct TypeDataCallback { + ~TypeDataCallback() {} + virtual void typeDataProgress(QDeclarativeTypeData *, qreal) {} + virtual void typeDataReady(QDeclarativeTypeData *) {} + }; + void registerCallback(TypeDataCallback *); + void unregisterCallback(TypeDataCallback *); + +protected: + virtual void done(); + virtual void dataReceived(const QByteArray &); + virtual void allDependenciesDone(); + virtual void downloadProgressChanged(qreal); + +private: + void resolveTypes(); + void compile(); + + QDeclarativeTypeLoader::Options m_options; + + QDeclarativeQmldirData *qmldirForUrl(const QUrl &); + + QDeclarativeScriptParser scriptParser; + QDeclarativeImports m_imports; + + QList<ScriptReference> m_scripts; + QList<QDeclarativeQmldirData *> m_qmldirs; + + QList<TypeReference> m_types; + bool m_typesResolved:1; + + QDeclarativeCompiledData *m_compiledData; + mutable QDeclarativeComponent *m_component; + + QList<TypeDataCallback *> m_callbacks; + + QDeclarativeTypeLoader *m_typeLoader; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeDataBlob +{ +public: + QDeclarativeScriptData(const QUrl &); + + QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas() const; + QString scriptSource() const; + +protected: + virtual void dataReceived(const QByteArray &); + +private: + QDeclarativeParser::Object::ScriptBlock::Pragmas m_pragmas; + QString m_source; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeQmldirData : public QDeclarativeDataBlob +{ +public: + QDeclarativeQmldirData(const QUrl &); + + const QDeclarativeDirComponents &dirComponents() const; + +protected: + virtual void dataReceived(const QByteArray &); + +private: + QDeclarativeDirComponents m_components; + +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVETYPELOADER_P_H diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index f06d6ae..60f2cb3 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -168,7 +168,7 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier ref->type->read(ref->object, ref->property); QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); - if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::QReal) + if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 689ed92..3e32006 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -707,11 +707,19 @@ void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &val void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value) { - if (value.userType() == QMetaType::QObjectStar) + bool needActivate = false; + if (value.userType() == QMetaType::QObjectStar) { + QObject *o = qvariant_cast<QObject *>(value); + needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o); data[id].setValue(qvariant_cast<QObject *>(value)); - else + } else { + needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() || + data[id].asQVariant().userType() != value.userType() || + data[id].asQVariant() != value); data[id].setValue(value); - activate(object, methodOffset + id, 0); + } + if (needActivate) + activate(object, methodOffset + id, 0); } void QDeclarativeVMEMetaObject::listChanged(int id) diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp index 0954248..58f8811 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/qmetaobjectbuilder.cpp @@ -205,7 +205,7 @@ public: (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1) : name(_name), type(QMetaObject::normalizedType(_type.constData())), - flags(Readable | Writable), notifySignal(-1) + flags(Readable | Writable | Scriptable), notifySignal(-1) { if (notifierIdx >= 0) { flags |= Notify; @@ -2187,7 +2187,7 @@ bool QMetaPropertyBuilder::isDesignable() const /*! Returns true if the property is scriptable; otherwise returns false. - This default value is false. + This default value is true. \sa setScriptable(), isDesignable(), isStored() */ diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 12f9794..687ff52 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -24,7 +24,7 @@ SOURCES += \ $$PWD/qdeclarativestringconverters.cpp \ $$PWD/qdeclarativeclassfactory.cpp \ $$PWD/qdeclarativeparserstatus.cpp \ - $$PWD/qdeclarativecompositetypemanager.cpp \ + $$PWD/qdeclarativetypeloader.cpp \ $$PWD/qdeclarativeinfo.cpp \ $$PWD/qdeclarativeerror.cpp \ $$PWD/qdeclarativescriptparser.cpp \ @@ -94,8 +94,7 @@ HEADERS += \ $$PWD/qdeclarativeproperty_p.h \ $$PWD/qdeclarativecontext_p.h \ $$PWD/qdeclarativeinclude_p.h \ - $$PWD/qdeclarativecompositetypedata_p.h \ - $$PWD/qdeclarativecompositetypemanager_p.h \ + $$PWD/qdeclarativetypeloader_p.h \ $$PWD/qdeclarativelist.h \ $$PWD/qdeclarativelist_p.h \ $$PWD/qdeclarativedata_p.h \ diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 267642d..3c09747 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -332,7 +332,7 @@ void QDeclarativeAbstractAnimation::setAlwaysRunToEnd(bool f) stopped - either by setting the \c running property to false, or by calling the \c stop() method. - In the following example, the rectangle will spin indefinately. + In the following example, the rectangle will spin indefinitely. \code Rectangle { diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index de2de21..4fc52f5 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -155,7 +155,7 @@ protected: private: friend class QDeclarativePixmapReaderThreadObject; void processJobs(); - void processJob(QDeclarativePixmapReply *); + void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &); void networkRequestDone(QNetworkReply *); QList<QDeclarativePixmapReply*> jobs; @@ -434,23 +434,24 @@ void QDeclarativePixmapReader::processJobs() QDeclarativePixmapReply *runningJob = jobs.takeLast(); runningJob->loading = true; + QUrl url = runningJob->data->url; + QSize requestSize = runningJob->data->requestSize; locker.unlock(); - processJob(runningJob); + processJob(runningJob, url, requestSize); locker.relock(); } } } -void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob) +void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url, + const QSize &requestSize) { - QUrl url = runningJob->data->url; - // fetch if (url.scheme() == QLatin1String("image")) { // Use QmlImageProvider QSize readSize; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize); + QImage image = ep->getImageFromProvider(url, &readSize, requestSize); QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; QString errorStr; @@ -472,7 +473,7 @@ void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob) QFile f(lf); QSize readSize; if (f.open(QIODevice::ReadOnly)) { - if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize)) + if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize)) errorCode = QDeclarativePixmapReply::Loading; } else { errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString()); @@ -663,6 +664,7 @@ void QDeclarativePixmapStore::shrinkCache(int remove) data->prevUnreferenced = 0; remove -= data->cost(); + m_unreferencedCost -= data->cost(); data->removeFromCache(); delete data; } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0b3b164..fc122d2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5666,9 +5666,6 @@ void QGraphicsItem::update(const QRectF &rect) return; } - if (d_ptr->discardUpdateRequest()) - return; - if (d_ptr->scene) d_ptr->scene->d_func()->markDirty(this, rect); } @@ -7758,18 +7755,21 @@ void QGraphicsItemPrivate::resetHeight() } /*! - \property QGraphicsObject::children - \internal + \property QGraphicsObject::children + \since 4.7 + \internal */ /*! - \property QGraphicsObject::width - \internal + \property QGraphicsObject::width + \since 4.7 + \internal */ /*! - \property QGraphicsObject::height - \internal + \property QGraphicsObject::height + \since 4.7 + \internal */ /*! @@ -7985,24 +7985,6 @@ void QGraphicsItemPrivate::resetHeight() */ /*! - \property QGraphicsObject::children - \since 4.7 - \internal -*/ - -/*! - \property QGraphicsObject::width - \since 4.7 - \internal -*/ - -/*! - \property QGraphicsObject::height - \since 4.7 - \internal -*/ - -/*! \class QAbstractGraphicsShapeItem \brief The QAbstractGraphicsShapeItem class provides a common base for all path items. diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4c03d33..539685a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1074,7 +1074,7 @@ void QGraphicsScenePrivate::enableMouseTrackingOnViews() /*! Returns all items for the screen position in \a event. */ -QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &screenPos, +QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*screenPos*/, const QPointF &scenePos, QWidget *widget) const { @@ -1083,16 +1083,12 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre if (!view) return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform()); - const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); + const QRectF pointRect(scenePos, QSizeF(1, 1)); if (!view->isTransformed()) return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder); const QTransform viewTransform = view->viewportTransform(); - if (viewTransform.type() <= QTransform::TxScale) { - return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, - Qt::DescendingOrder, viewTransform); - } - return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, + return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder, viewTransform); } diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index bd3f2ef..1f155c6 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -346,21 +346,24 @@ void QGraphicsScale::applyTo(QMatrix4x4 *matrix) const /*! \fn QGraphicsScale::xScaleChanged() + \since 4.7 - QGraphicsScale emits this signal when its xScale changes. + This signal is emitted whenever the \l xScale property changes. */ /*! \fn QGraphicsScale::yScaleChanged() + \since 4.7 - QGraphicsScale emits this signal when its yScale changes. + This signal is emitted whenever the \l yScale property changes. */ /*! \fn QGraphicsScale::zScaleChanged() + \since 4.7 - QGraphicsScale emits this signal when its zScale changes. -*/ + This signal is emitted whenever the \l zScale property changes. +*/ /*! \fn QGraphicsScale::scaleChanged() @@ -583,27 +586,6 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const \sa QGraphicsRotation::axis */ -/*! - \fn QGraphicsScale::xScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l xScale property changes. -*/ - -/*! - \fn QGraphicsScale::yScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l yScale property changes. -*/ - -/*! - \fn QGraphicsScale::zScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l zScale property changes. -*/ - #include "moc_qgraphicstransform.cpp" QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 0fabd18..1bfe266 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -937,7 +937,9 @@ void QGraphicsWidget::setStyle(QStyle *style) QFont QGraphicsWidget::font() const { Q_D(const QGraphicsWidget); - return d->font; + QFont fnt = d->font; + fnt.resolve(fnt.resolve() | d->inheritedFontResolveMask); + return fnt; } void QGraphicsWidget::setFont(const QFont &font) { diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index f7850ca..3466733 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -254,7 +254,10 @@ void QGraphicsWidgetPrivate::setFont_helper(const QFont &font) void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask) { + Q_Q(QGraphicsWidget); inheritedFontResolveMask = inheritedMask; + if (QGraphicsWidget *p = q->parentWidget()) + inheritedFontResolveMask |= p->d_func()->inheritedFontResolveMask; QFont naturalFont = naturalWidgetFont(); QFont resolvedFont = font.resolve(naturalFont); updateFont(resolvedFont); diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index d5243c3..ac40bba 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -66,10 +66,10 @@ QT_BEGIN_NAMESPACE -class QCoeFepInputContext : public QInputContext, - public MCoeFepAwareTextEditor, - public MCoeFepAwareTextEditor_Extension1, - public MObjectProvider +class Q_AUTOTEST_EXPORT QCoeFepInputContext : public QInputContext, + public MCoeFepAwareTextEditor, + public MCoeFepAwareTextEditor_Extension1, + public MObjectProvider { Q_OBJECT @@ -84,6 +84,7 @@ public: void update(); bool filterEvent(const QEvent *event); + bool symbianFilterEvent(QWidget *keyWidget, const QSymbianEvent *event); void mouseHandler( int x, QMouseEvent *event); bool isComposing() const { return !m_preeditString.isEmpty(); } @@ -151,9 +152,10 @@ private: int m_inlinePosition; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; - int m_cursorPos; QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; + + friend class tst_QInputContext; }; QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index c4d60a5..b08b9a9 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -47,6 +47,7 @@ #include <qgraphicsview.h> #include <qgraphicsscene.h> #include <qgraphicswidget.h> +#include <qsymbianevent.h> #include <private/qcore_symbian_p.h> #include <fepitfr.h> @@ -79,7 +80,6 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_inlinePosition(0), m_formatRetriever(0), m_pointerHandler(0), - m_cursorPos(0), m_hasTempPreeditString(false) { m_fepState->SetObjectProvider(this); @@ -237,11 +237,17 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) break; } + QString widgetText = focusWidget()->inputMethodQuery(Qt::ImSurroundingText).toString(); + int maxLength = focusWidget()->inputMethodQuery(Qt::ImMaximumTextLength).toInt(); + if (!keyEvent->text().isEmpty() && widgetText.size() + m_preeditString.size() >= maxLength) { + // Don't send key events with string content if the widget is "full". + return true; + } + if (keyEvent->type() == QEvent::KeyPress && focusWidget()->inputMethodHints() & Qt::ImhHiddenText && !keyEvent->text().isEmpty()) { // Send some temporary preedit text in order to make text visible for a moment. - m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); m_preeditString = keyEvent->text(); QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent imEvent(m_preeditString, attributes); @@ -282,6 +288,18 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) return false; } +bool QCoeFepInputContext::symbianFilterEvent(QWidget *keyWidget, const QSymbianEvent *event) +{ + Q_UNUSED(keyWidget); + if (event->type() == QSymbianEvent::CommandEvent) + // A command basically means the same as a button being pushed. With Qt buttons + // that would normally result in a reset of the input method due to the focus change. + // This should also happen for commands. + reset(); + + return false; +} + void QCoeFepInputContext::timerEvent(QTimerEvent *timerEvent) { if (timerEvent->timerId() == m_tempPreeditStringTimeout.timerId()) @@ -297,10 +315,6 @@ void QCoeFepInputContext::commitTemporaryPreeditString() return; commitCurrentString(false); - - //update cursor position, now this pre-edit text has been committed. - //this prevents next keypress overwriting it (QTBUG-11673) - m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); } void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) @@ -596,8 +610,6 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, commitTemporaryPreeditString(); - m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); - QList<QInputMethodEvent::Attribute> attributes; m_cursorVisibility = aCursorVisibility ? 1 : 0; @@ -612,9 +624,10 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, // Let's remove the selected text if aInitialInlineText is empty and there is selected text if (m_preeditString.isEmpty()) { int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt(); - int replacementLength = qAbs(m_cursorPos-anchor); + int cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); + int replacementLength = qAbs(cursorPos-anchor); if (replacementLength > 0) { - int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength; + int replacementStart = cursorPos < anchor ? 0 : -replacementLength; QList<QInputMethodEvent::Attribute> clearSelectionAttributes; QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes); clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength); @@ -647,8 +660,13 @@ void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText, m_inlinePosition, m_cursorVisibility, QVariant())); - m_preeditString = qt_TDesC2QString(aNewInlineText); - QInputMethodEvent event(m_preeditString, attributes); + QString newPreeditString = qt_TDesC2QString(aNewInlineText); + QInputMethodEvent event(newPreeditString, attributes); + if (newPreeditString.isEmpty() && m_preeditString.isEmpty()) { + // In Symbian world this means "erase last character". + event.setCommitString(QLatin1String(""), -1, 1); + } + m_preeditString = newPreeditString; sendEvent(event); } @@ -818,25 +836,13 @@ void QCoeFepInputContext::DoCommitFepInlineEditL() void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction) { - int longPress = 0; - - if (m_preeditString.size() == 0) { - QWidget *w = focusWidget(); - if (!cancelFepTransaction && w) { - // We must replace the last character only if the input box has already accepted one - if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) - longPress = 1; - } - } - QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_preeditString, 0-longPress, longPress); + event.setCommitString(m_preeditString, 0, 0); m_preeditString.clear(); sendEvent(event); m_hasTempPreeditString = false; - longPress = 0; if (cancelFepTransaction) { CCoeFep* fep = CCoeEnv::Static()->Fep(); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index e197dc5..e937918 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -129,7 +129,13 @@ void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, boo statusPaneVisibilityChanged = (s->IsVisible() != statusPaneVisible); s->MakeVisible(statusPaneVisible); } - if (buttonGroupVisibilityChanged && !statusPaneVisibilityChanged) + if (buttonGroupVisibilityChanged || statusPaneVisibilityChanged) { + const QSize size = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()).size(); + const QSize oldSize; // note that QDesktopWidget::resizeEvent ignores the QResizeEvent contents + QResizeEvent event(size, oldSize); + QApplication::instance()->sendEvent(QApplication::desktop(), &event); + } + if (buttonGroupVisibilityChanged && !statusPaneVisibilityChanged && QApplication::activeWindow()) // Ensure that control rectangle is updated static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange(); } @@ -1242,17 +1248,28 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); #endif } else if (QApplication::activeWindow() == qwidget->window()) { - if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) { - QWidget *fw = QApplication::focusWidget(); - if (fw) { - QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); - QCoreApplication::sendEvent(fw, &event); - } - m_symbianPopupIsOpen = true; - return; + bool focusedControlFound = false; + WId winId = 0; + for (QWidget *w = qwidget->parentWidget(); w && (winId = w->internalWinId()); w = w->parentWidget()) { + if (winId->IsFocused() && winId->IsVisible()) { + focusedControlFound = true; + break; + } else if (w->isWindow()) + break; } + if (!focusedControlFound) { + if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = true; + return; + } - QApplication::setActiveWindow(0); + QApplication::setActiveWindow(0); + } } // else { We don't touch the active window unless we were explicitly activated or deactivated } } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index eb1aa18..7fd2baa 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -87,7 +87,7 @@ const TInt KInternalStatusPaneChange = 0x50000000; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) -class QS60ThreadLocalData +class Q_AUTOTEST_EXPORT QS60ThreadLocalData { public: QS60ThreadLocalData(); @@ -171,7 +171,7 @@ public: #endif }; -QS60Data* qGlobalS60Data(); +Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); #define S60 qGlobalS60Data() class QAbstractLongTapObserver diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 3d2bfe2..ea3dcab 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4864,6 +4864,8 @@ void QWidgetPrivate::resolveLayoutDirection() has been called for the parent do not inherit the parent's layout direction. + This method no longer affects text layout direction since Qt 4.7. + \sa QApplication::layoutDirection */ void QWidget::setLayoutDirection(Qt::LayoutDirection direction) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index fc13c93..c98c05a 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -503,8 +503,10 @@ void QWidgetPrivate::show_sys() // Can't use AppUi directly because it privately inherits from MEikStatusPaneObserver. QSymbianControl *desktopControl = static_cast<QSymbianControl *>(QApplication::desktop()->winId()); S60->statusPane()->SetObserver(desktopControl); - if (isFullscreen) - S60->statusPane()->MakeVisible(false); + if (isFullscreen) { + const bool cbaVisible = S60->buttonGroupContainer() && S60->buttonGroupContainer()->IsVisible(); + S60->setStatusPaneAndButtonGroupVisibility(false, cbaVisible); + } } } } diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 24908ce..0edf256 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -254,10 +254,10 @@ void qt_scale_image_argb32_on_rgb16(uchar *destPixels, int dbpl, } } -static void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, - const uchar *src, int sbpl, - int w, int h, - int const_alpha) +void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, + const uchar *src, int sbpl, + int w, int h, + int const_alpha) { #ifdef QT_DEBUG_DRAW printf("qt_blend_rgb16_on_rgb16: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 276da93..cf487b5 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -46,7 +46,6 @@ #include <private/qdrawhelper_armv6_p.h> #include <private/qdrawhelper_neon_p.h> #include <private/qmath_p.h> -#include <private/qsimd_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE @@ -656,6 +655,46 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const return buffer; } +/** \internal + interpolate 4 argb pixels with the distx and disty factor. + distx and disty bust be between 0 and 16 + */ +static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty, int idistx, int idisty) +{ + uint tlrb = ((tl & 0x00ff00ff) * idistx * idisty); + uint tlag = (((tl & 0xff00ff00) >> 8) * idistx * idisty); + uint trrb = ((tr & 0x00ff00ff) * distx * idisty); + uint trag = (((tr & 0xff00ff00) >> 8) * distx * idisty); + uint blrb = ((bl & 0x00ff00ff) * idistx * disty); + uint blag = (((bl & 0xff00ff00) >> 8) * idistx * disty); + uint brrb = ((br & 0x00ff00ff) * distx * disty); + uint brag = (((br & 0xff00ff00) >> 8) * distx * disty); + return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00); +} + + +template<TextureBlendType blendType> +Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) +{ + if (blendType == BlendTransformedBilinearTiled) { + v1 %= max; + if (v1 < 0) v1 += max; + v2 = v1 + 1; + v2 %= max; + } else { + if (v1 < l1) { + v2 = v1 = l1; + } else if (v1 >= l2) { + v2 = v1 = l2; + } else { + v2 = v1 + 1; + } + } + + Q_ASSERT(v1 >= 0 && v1 < max); + Q_ASSERT(v2 >= 0 && v2 < max); +} + template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, @@ -676,8 +715,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int image_x1 = data->texture.x1; int image_y1 = data->texture.y1; - int image_x2 = data->texture.x2; - int image_y2 = data->texture.y2; + int image_x2 = data->texture.x2 - 1; + int image_y2 = data->texture.y2 - 1; const qreal cx = x + 0.5; const qreal cy = y + 0.5; @@ -696,64 +735,230 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fx -= half_point; fy -= half_point; - while (b < end) { - int x1 = (fx >> 16); - int x2; + + if (fdy == 0) { //simple scale, no rotation int y1 = (fy >> 16); int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; + if (fdx <= fixed_scale && fdx > 0) { // scale up on X + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + int x = fx >> 16; + + // The idea is first to do the interpolation between the row s1 and the row s2 + // into an intermediate buffer, then we interpolate between two pixel of this buffer. + + // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB + // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG + quint32 intermediate_buffer[2][buffer_size + 2]; + // count is the size used in the intermediate_buffer. + int count = qCeil(length * data->m11) + 2; //+1 for the last pixel to interpolate with, and +1 for rounding errors. + Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case + int f = 0; + int lim = count; + if (blendType == BlendTransformedBilinearTiled) { + x %= image_width; + if (x < 0) x += image_width; } else { - x2 = x1 + 1; + lim = qMin(count, image_x2-x+1); + if (x < image_x1) { + Q_ASSERT(x <= image_x2); + uint t = fetch(s1, image_x1, data->texture.colorTable); + uint b = fetch(s2, image_x1, data->texture.colorTable); + quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + do { + intermediate_buffer[0][f] = rb; + intermediate_buffer[1][f] = ag; + f++; + x++; + } while (x < image_x1 && f < lim); + } } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; + +#if defined(QT_ALWAYS_HAVE_SSE2) + if (blendType != BlendTransformedBilinearTiled && + (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { + + const __m128i disty_ = _mm_set1_epi16(disty); + const __m128i idisty_ = _mm_set1_epi16(idisty); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + lim -= 3; + for (; f < lim; x += 4, f += 4) { + // Load 4 pixels from s1, and split the alpha-green and red-blue component + __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x)); + __m128i topAG = _mm_srli_epi16(top, 8); + __m128i topRB = _mm_and_si128(top, colorMask); + // Multiplies each colour component by idisty + topAG = _mm_mullo_epi16 (topAG, idisty_); + topRB = _mm_mullo_epi16 (topRB, idisty_); + + // Same for the s2 vector + __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x)); + __m128i bottomAG = _mm_srli_epi16(bottom, 8); + __m128i bottomRB = _mm_and_si128(bottom, colorMask); + bottomAG = _mm_mullo_epi16 (bottomAG, disty_); + bottomRB = _mm_mullo_epi16 (bottomRB, disty_); + + // Add the values, and shift to only keep 8 significant bits per colors + __m128i rAG =_mm_add_epi16(topAG, bottomAG); + rAG = _mm_srli_epi16(rAG, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); + __m128i rRB =_mm_add_epi16(topRB, bottomRB); + rRB = _mm_srli_epi16(rRB, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); + } + } +#endif + for (; f < count; f++) { // Same as above but without sse2 + if (blendType == BlendTransformedBilinearTiled) { + if (x >= image_width) x -= image_width; + } else { + x = qMin(x, image_x2); + } + + uint t = fetch(s1, x, data->texture.colorTable); + uint b = fetch(s2, x, data->texture.colorTable); + + intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + x++; + } + // Now interpolate the values from the intermediate_buffer to get the final result. + fx &= fixed_scale - 1; + Q_ASSERT((fx >> 16) == 0); + while (b < end) { + register int x1 = (fx >> 16); + register int x2 = x1 + 1; + Q_ASSERT(x1 >= 0); + Q_ASSERT(x2 < count); + + register int distx = (fx & 0x0000ffff) >> 8; + register int idistx = 256 - distx; + int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; + int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; + *b = rb | ag; + b++; + fx += fdx; + } + } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 8; + int idistx = 256 - distx; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + + fx += fdx; + ++b; + } + } else { //scale down + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 12; + int idisty = 16 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + int distx = (fx & 0x0000ffff) >> 12; + int idistx = 16 - distx; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + fx += fdx; + ++b; } } + } else { //rotation + if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { + //if we are zooming more than 8 times, we use 8bit precision for the position. + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int idisty = 256 - disty; + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + int idistx = 256 - distx; + int idisty = 256 - disty; - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - fx += fdx; - fy += fdy; - ++b; + fx += fdx; + fy += fdy; + ++b; + } + } else { + //we are zooming less than 8x, use 4bit precision + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 12; + int disty = (fy & 0x0000ffff) >> 12; + int idistx = 16 - distx; + int idisty = 16 - disty; + + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + + fx += fdx; + fy += fdy; + ++b; + } + } } } else { const qreal fdx = data->m11; @@ -779,37 +984,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int idistx = 256 - distx; int idisty = 256 - disty; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < 0) { - x2 = x1 = 0; - } else if (x1 >= image_width - 1) { - x2 = x1 = image_width - 1; - } else { - x2 = x1 + 1; - } - if (y1 < 0) { - y2 = y1 = 0; - } else if (y1 >= image_height - 1) { - y2 = y1 = image_height - 1; - } else { - y2 = y1 + 1; - } - } - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -1757,9 +1933,7 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int for (int i = 0; i < length; ++i) { PRELOAD_COND(dest) uint d = dest[i]; -#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) - d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); -#undef MIX + d = comp_func_Plus_one_pixel(d, s); coverage.store(&dest[i], d); } } @@ -1781,9 +1955,7 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uin uint d = dest[i]; uint s = src[i]; -#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) - d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); -#undef MIX + d = comp_func_Plus_one_pixel(d, s); coverage.store(&dest[i], d); } @@ -5163,239 +5335,6 @@ static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) blend_tiled_generic<RegularSpans>(count, spans, userData); } - -template <SpanMethod spanMethod, TextureBlendType blendType> /* blendType must be either BlendTransformedBilinear or BlendTransformedBilinearTiled */ -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - if (data->texture.format != QImage::Format_ARGB32_Premultiplied - && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData); - return; - } - - CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; - uint buffer[buffer_size]; - - const int image_x1 = data->texture.x1; - const int image_y1 = data->texture.y1; - const int image_x2 = data->texture.x2; - const int image_y2 = data->texture.y2; - const int image_width = data->texture.width; - const int image_height = data->texture.height; - const int scanline_offset = data->texture.bytesPerLine / 4; - - if (data->fast_matrix) { - // The increment pr x in the scanline - int fdx = (int)(data->m11 * fixed_scale); - int fdy = (int)(data->m12 * fixed_scale); - - while (count--) { - void *t = data->rasterBuffer->scanLine(spans->y); - - uint *target = ((uint *)t) + spans->x; - uint *image_bits = (uint *)data->texture.imageData; - - const qreal cx = spans->x + 0.5; - const qreal cy = spans->y + 0.5; - - int x = int((data->m21 * cy - + data->m11 * cx + data->dx) * fixed_scale) - half_point; - int y = int((data->m22 * cy - + data->m12 * cx + data->dy) * fixed_scale) - half_point; - - int length = spans->len; - const int coverage = (data->texture.const_alpha * spans->coverage) >> 8; - while (length) { - int l = qMin(length, buffer_size); - const uint *end = buffer + l; - uint *b = buffer; - while (b < end) { - int x1 = (x >> 16); - int x2; - int y1 = (y >> 16); - int y2; - - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } - - int y1_offset = y1 * scanline_offset; - int y2_offset = y2 * scanline_offset; - -#if defined(Q_IRIX_GCC3_3_WORKAROUND) - uint tl = gccBug(image_bits[y1_offset + x1]); - uint tr = gccBug(image_bits[y1_offset + x2]); - uint bl = gccBug(image_bits[y2_offset + x1]); - uint br = gccBug(image_bits[y2_offset + x2]); -#else - uint tl = image_bits[y1_offset + x1]; - uint tr = image_bits[y1_offset + x2]; - uint bl = image_bits[y2_offset + x1]; - uint br = image_bits[y2_offset + x2]; -#endif - - int distx = (x & 0x0000ffff) >> 8; - int disty = (y & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int idisty = 256 - disty; - - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - ++b; - - x += fdx; - y += fdy; - } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); - target += l; - length -= l; - } - ++spans; - } - } else { - const qreal fdx = data->m11; - const qreal fdy = data->m12; - const qreal fdw = data->m13; - - while (count--) { - void *t = data->rasterBuffer->scanLine(spans->y); - - uint *target = ((uint *)t) + spans->x; - uint *image_bits = (uint *)data->texture.imageData; - - const qreal cx = spans->x + 0.5; - const qreal cy = spans->y + 0.5; - - qreal x = data->m21 * cy + data->m11 * cx + data->dx; - qreal y = data->m22 * cy + data->m12 * cx + data->dy; - qreal w = data->m23 * cy + data->m13 * cx + data->m33; - - int length = spans->len; - const int coverage = (data->texture.const_alpha * spans->coverage) >> 8; - while (length) { - int l = qMin(length, buffer_size); - const uint *end = buffer + l; - uint *b = buffer; - while (b < end) { - const qreal iw = w == 0 ? 1 : 1 / w; - const qreal px = x * iw - 0.5; - const qreal py = y * iw - 0.5; - - int x1 = int(px) - (px < 0); - int x2; - int y1 = int(py) - (py < 0); - int y2; - - int distx = int((px - x1) * 256); - int disty = int((py - y1) * 256); - int idistx = 256 - distx; - int idisty = 256 - disty; - - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } - - int y1_offset = y1 * scanline_offset; - int y2_offset = y2 * scanline_offset; - -#if defined(Q_IRIX_GCC3_3_WORKAROUND) - uint tl = gccBug(image_bits[y1_offset + x1]); - uint tr = gccBug(image_bits[y1_offset + x2]); - uint bl = gccBug(image_bits[y2_offset + x1]); - uint br = gccBug(image_bits[y2_offset + x2]); -#else - uint tl = image_bits[y1_offset + x1]; - uint tr = image_bits[y1_offset + x2]; - uint bl = image_bits[y2_offset + x1]; - uint br = image_bits[y2_offset + x2]; -#endif - - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - ++b; - - x += fdx; - y += fdy; - w += fdw; - } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); - target += l; - length -= l; - } - ++spans; - } - } -} - template <class DST, class SRC> Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan *spans, void *userData) @@ -6646,7 +6585,7 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied + SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied blend_transformed_bilinear_rgb565, blend_transformed_bilinear_argb8565, blend_transformed_bilinear_rgb666, @@ -6665,7 +6604,7 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied + SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16 SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666 @@ -6764,7 +6703,7 @@ static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImag blend_src_generic<CallbackSpans>, // Indexed8 blend_src_generic<CallbackSpans>, // RGB32 blend_src_generic<CallbackSpans>, // ARGB32 - blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied + blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied blend_src_generic<CallbackSpans>, // RGB16 blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied blend_src_generic<CallbackSpans>, // RGB666 @@ -6783,7 +6722,7 @@ static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImag blend_src_generic<CallbackSpans>, // Indexed8 blend_src_generic<CallbackSpans>, // RGB32 blend_src_generic<CallbackSpans>, // ARGB32 - blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied + blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied blend_src_generic<CallbackSpans>, // RGB16 blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied blend_src_generic<CallbackSpans>, // RGB666 @@ -7900,6 +7839,7 @@ void qInitDrawhelperAsm() qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon; + qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon; qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon; qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon; @@ -7911,11 +7851,13 @@ void qInitDrawhelperAsm() functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; + functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon; destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon; qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon; + qt_memfill32 = qt_memfill32_neon; } #endif diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 03fe075..0afd077 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -51,6 +51,44 @@ QT_BEGIN_NAMESPACE +void qt_memfill32_neon(quint32 *dest, quint32 value, int count) +{ + const int epilogueSize = count % 16; + if (count >= 16) { + quint32 *const neonEnd = dest + count - epilogueSize; + register uint32x4_t valueVector1 asm ("q0") = vdupq_n_u32(value); + register uint32x4_t valueVector2 asm ("q1") = valueVector1; + while (dest != neonEnd) { + asm volatile ( + "vst2.32 { d0, d1, d2, d3 }, [%[DST]] !\n\t" + "vst2.32 { d0, d1, d2, d3 }, [%[DST]] !\n\t" + : [DST]"+r" (dest) + : [VALUE1]"w"(valueVector1), [VALUE2]"w"(valueVector2) + : "memory" + ); + } + } + + switch (epilogueSize) + { + case 15: *dest++ = value; + case 14: *dest++ = value; + case 13: *dest++ = value; + case 12: *dest++ = value; + case 11: *dest++ = value; + case 10: *dest++ = value; + case 9: *dest++ = value; + case 8: *dest++ = value; + case 7: *dest++ = value; + case 6: *dest++ = value; + case 5: *dest++ = value; + case 4: *dest++ = value; + case 3: *dest++ = value; + case 2: *dest++ = value; + case 1: *dest++ = value; + } +} + static inline uint16x8_t qvdiv_255_u16(uint16x8_t x, uint16x8_t half) { // result = (x + (x >> 8) + 0x80) >> 8 @@ -129,6 +167,14 @@ pixman_composite_scanline_over_asm_neon (int32_t w, const uint32_t *dst, const uint32_t *src); +extern "C" void +pixman_composite_src_0565_0565_asm_neon (int32_t w, + int32_t h, + uint16_t *dst, + int32_t dst_stride, + uint16_t *src, + int32_t src_stride); + // qblendfunctions.cpp void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, @@ -162,6 +208,96 @@ void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl, pixman_composite_src_0565_8888_asm_neon(w, h, dst, dbpl, src, sbpl); } +// qblendfunctions.cpp +void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, + const uchar *src, int sbpl, + int w, int h, + int const_alpha); + +template <int N> +static inline void scanLineBlit16(quint16 *dst, quint16 *src, int dstride) +{ + if (N >= 2) { + ((quint32 *)dst)[0] = ((quint32 *)src)[0]; + __builtin_prefetch(dst + dstride, 1, 0); + } + for (int i = 1; i < N/2; ++i) + ((quint32 *)dst)[i] = ((quint32 *)src)[i]; + if (N & 1) + dst[N-1] = src[N-1]; +} + +template <int Width> +static inline void blockBlit16(quint16 *dst, quint16 *src, int dstride, int sstride, int h) +{ + union { + quintptr address; + quint16 *pointer; + } u; + + u.pointer = dst; + + if (u.address & 2) { + while (h--) { + // align dst + dst[0] = src[0]; + if (Width > 1) + scanLineBlit16<Width-1>(dst + 1, src + 1, dstride); + dst += dstride; + src += sstride; + } + } else { + while (h--) { + scanLineBlit16<Width>(dst, src, dstride); + + dst += dstride; + src += sstride; + } + } +} + +void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + // testing show that the default memcpy is faster for widths 150 and up + if (const_alpha != 256 || w >= 150) { + qt_blend_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); + return; + } + + int dstride = dbpl / 2; + int sstride = sbpl / 2; + + quint16 *dst = (quint16 *) destPixels; + quint16 *src = (quint16 *) srcPixels; + + switch (w) { +#define BLOCKBLIT(n) case n: blockBlit16<n>(dst, src, dstride, sstride, h); return; + BLOCKBLIT(1); + BLOCKBLIT(2); + BLOCKBLIT(3); + BLOCKBLIT(4); + BLOCKBLIT(5); + BLOCKBLIT(6); + BLOCKBLIT(7); + BLOCKBLIT(8); + BLOCKBLIT(9); + BLOCKBLIT(10); + BLOCKBLIT(11); + BLOCKBLIT(12); + BLOCKBLIT(13); + BLOCKBLIT(14); + BLOCKBLIT(15); +#undef BLOCKBLIT + default: + break; + } + + pixman_composite_src_0565_0565_asm_neon (w, h, dst, dstride, src, sstride); +} + extern "C" void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha); void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl, @@ -622,6 +758,61 @@ void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, u } } +void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + uint *const end = dst + length; + uint *const neonEnd = end - 3; + + while (dst < neonEnd) { + asm volatile ( + "vld2.8 { d0, d1 }, [%[SRC]] !\n\t" + "vld2.8 { d2, d3 }, [%[DST]]\n\t" + "vqadd.u8 q0, q0, q1\n\t" + "vst2.8 { d0, d1 }, [%[DST]] !\n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : + : "memory", "d0", "d1", "d2", "d3", "q0", "q1" + ); + } + + while (dst != end) { + *dst = comp_func_Plus_one_pixel(*dst, *src); + ++dst; + ++src; + } + } else { + int x = 0; + const int one_minus_const_alpha = 255 - const_alpha; + const uint16x8_t constAlphaVector = vdupq_n_u16(const_alpha); + const uint16x8_t oneMinusconstAlphaVector = vdupq_n_u16(one_minus_const_alpha); + + const uint16x8_t half = vdupq_n_u16(0x80); + for (; x < length - 3; x += 4) { + const uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]); + const uint8x16_t src8 = vreinterpretq_u8_u32(src32); + uint8x16_t dst8 = vld1q_u8((uint8_t *)&dst[x]); + uint8x16_t result = vqaddq_u8(dst8, src8); + + uint16x8_t result_low = vmovl_u8(vget_low_u8(result)); + uint16x8_t result_high = vmovl_u8(vget_high_u8(result)); + + uint16x8_t dst_low = vmovl_u8(vget_low_u8(dst8)); + uint16x8_t dst_high = vmovl_u8(vget_high_u8(dst8)); + + result_low = qvinterpolate_pixel_255(result_low, constAlphaVector, dst_low, oneMinusconstAlphaVector, half); + result_high = qvinterpolate_pixel_255(result_high, constAlphaVector, dst_high, oneMinusconstAlphaVector, half); + + const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result_low)); + const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result_high)); + vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high)); + } + + for (; x < length; ++x) + dst[x] = comp_func_Plus_one_pixel_const_alpha(dst[x], src[x], const_alpha, one_minus_const_alpha); + } +} + static const int tileSize = 32; extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count); diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index cd2dbfc..d25b7ec 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -84,6 +84,11 @@ void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl, int w, int h, int const_alpha); +void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *bitmap, @@ -120,6 +125,7 @@ void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, const QTransform &targetRectTransform, int const_alpha); +void qt_memfill32_neon(quint32 *dest, quint32 value, int count); void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); @@ -131,6 +137,7 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha); +void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uint const_alpha); #endif // QT_HAVE_NEON diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index d04c70d..5747da5 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -62,6 +62,7 @@ #define QT_FT_END_HEADER #endif #include "private/qrasterdefs_p.h" +#include <private/qsimd_p.h> #ifdef Q_WS_QWS #include "QtGui/qscreen_qws.h" @@ -69,13 +70,6 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_MAC) && (defined(__ppc__) || defined(__ppc64__)) -#undef QT_HAVE_MMX -#undef QT_HAVE_SSE -#undef QT_HAVE_SSE2 -#undef QT_HAVE_3DNOW -#endif - #if defined(Q_CC_MSVC) && _MSCVER <= 1300 && !defined(Q_CC_INTEL) #define Q_STATIC_TEMPLATE_SPECIALIZATION static #else @@ -1944,6 +1938,30 @@ const uint qt_bayer_matrix[16][16] = { ((((argb >> 24) * alpha) >> 8) << 24) | (argb & 0x00ffffff) +#if QT_POINTER_SIZE == 8 // 64-bit versions +#define AMIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) +#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) +#else // 32 bits +// The mask for alpha can overflow over 32 bits +#define AMIX(mask) quint32(qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) +#define MIX(mask) (qMin(((quint32(s)&mask) + (quint32(d)&mask)), quint32(mask))) +#endif + +inline int comp_func_Plus_one_pixel_const_alpha(uint d, const uint s, const uint const_alpha, const uint one_minus_const_alpha) +{ + const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); + return INTERPOLATE_PIXEL_255(result, const_alpha, d, one_minus_const_alpha); +} + +inline int comp_func_Plus_one_pixel(uint d, const uint s) +{ + const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); + return result; +} + +#undef MIX +#undef AMIX + // prototypes of all the composition functions void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha); void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha); diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 22c0384..5b674b5 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -43,7 +43,6 @@ #ifdef QT_HAVE_SSE2 -#include <private/qsimd_p.h> #include <private/qdrawingprimitive_sse2_p.h> #include <private/qpaintengine_raster_p.h> @@ -161,22 +160,6 @@ void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixe } } -inline int comp_func_Plus_one_pixel_const_alpha(uint d, const uint s, const uint const_alpha, const uint one_minus_const_alpha) -{ -#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) - const int result = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); -#undef MIX - return INTERPOLATE_PIXEL_255(result, const_alpha, d, one_minus_const_alpha); -} - -inline int comp_func_Plus_one_pixel(uint d, const uint s) -{ -#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) - const int result = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); -#undef MIX - return result; -} - void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha) { int x = 0; diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp index 9c02009..4cb4089 100644 --- a/src/gui/painting/qdrawhelper_ssse3.cpp +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -39,11 +39,10 @@ ** ****************************************************************************/ +#include <private/qdrawhelper_x86_p.h> #ifdef QT_HAVE_SSSE3 -#include <private/qsimd_p.h> -#include <private/qdrawhelper_x86_p.h> #include <private/qdrawingprimitive_sse2_p.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index be90006..c6046ac 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -696,9 +696,9 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s) skip = false; - QBrush penBrush = s->pen.brush(); - Qt::BrushStyle brushStyle = s->brush.style(); - Qt::BrushStyle penBrushStyle = penBrush.style(); + QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen); + Qt::BrushStyle brushStyle = qbrush_style(s->brush); + Qt::BrushStyle penBrushStyle = qbrush_style(penBrush); alpha = (penBrushStyle != Qt::NoBrush && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255) && !penBrush.isOpaque()) @@ -5863,7 +5863,8 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText } bool paintEngineSupportsTransformations = d->extended->type() == QPaintEngine::OpenGL2 - || d->extended->type() == QPaintEngine::OpenVG; + || d->extended->type() == QPaintEngine::OpenVG + || d->extended->type() == QPaintEngine::OpenGL; if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) { staticText_d->untransformedCoordinates = true; @@ -5907,7 +5908,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText // Recreate the layout of the static text because the matrix or font has changed if (staticTextNeedsReinit) - staticText_d->init(); + staticText_d->init(); if (transformedPosition != staticText_d->position) { // Translate to actual position QFixed fx = QFixed::fromReal(transformedPosition.x()); @@ -9027,7 +9028,7 @@ void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragment { Q_D(QPainter); - if (!d->engine) + if (!d->engine || pixmap.isNull()) return; #ifndef QT_NO_DEBUG diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index ada5293..306219d 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -2157,7 +2157,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o } if (button->features & QStyleOptionButton::HasMenu) - ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0); + ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0); proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled), button->text, QPalette::ButtonText); } @@ -4014,8 +4014,8 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio switch (subControl) { case SC_SliderHandle: { if (slider->orientation == Qt::Horizontal) { - rect.setHeight(pixelMetric(PM_SliderThickness)); - rect.setWidth(pixelMetric(PM_SliderLength)); + rect.setHeight(proxy()->pixelMetric(PM_SliderThickness)); + rect.setWidth(proxy()->pixelMetric(PM_SliderLength)); int centerY = slider->rect.center().y() - rect.height() / 2; if (slider->tickPosition & QSlider::TicksAbove) centerY += tickSize; @@ -4023,8 +4023,8 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio centerY -= tickSize; rect.moveTop(centerY); } else { - rect.setWidth(pixelMetric(PM_SliderThickness)); - rect.setHeight(pixelMetric(PM_SliderLength)); + rect.setWidth(proxy()->pixelMetric(PM_SliderThickness)); + rect.setHeight(proxy()->pixelMetric(PM_SliderLength)); int centerX = slider->rect.center().x() - rect.width() / 2; if (slider->tickPosition & QSlider::TicksAbove) centerX += tickSize; diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index e28403b..358c6aa 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -154,6 +154,9 @@ QS60StylePrivate::~QS60StylePrivate() { clearCaches(); //deletes also background image deleteThemePalette(); +#ifdef Q_WS_S60 + removeAnimations(); +#endif } void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter, @@ -1097,8 +1100,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom } State mflags = bflags; if (toolBtn->state & State_Sunken) { - if (toolBtn->activeSubControls & SC_ToolButton) - bflags |= State_Sunken; + bflags |= State_Sunken; mflags |= State_Sunken; } @@ -1114,11 +1116,6 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom if (bflags & (State_Sunken | State_On | State_Raised | State_Enabled)) { tool.rect = button.unite(menuRect); tool.state = bflags; - const QToolButton *toolButtonWidget = qobject_cast<const QToolButton *>(widget); - const QS60StylePrivate::SkinElements element = - ((toolButtonWidget && toolButtonWidget->isDown()) || (option->state & State_Sunken)) ? - QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; - QS60StylePrivate::drawSkinElement(element, painter, tool.rect, flags); drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); } if (toolBtn->subControls & SC_ToolButtonMenu) { @@ -2174,9 +2171,12 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_PanelButtonBevel: case PE_FrameButtonBevel: if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget)) { - const bool isPressed = option->state & State_Sunken; - const QS60StylePrivate::SkinElements skinElement = - isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + const bool isPressed = (option->state & State_Sunken) || (option->state & State_On); + QS60StylePrivate::SkinElements skinElement; + if (element == PE_PanelButtonTool) + skinElement = isPressed ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; + else + skinElement = isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); } else { commonStyleDraws = true; @@ -2340,16 +2340,20 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti tableView = true; QS60StylePrivate::SkinElements element; + bool themeGraphicDefined = false; QRect elementRect = option->rect; //draw item is drawn as pressed, if it already has focus. if (isPressed && (hasFocus || isSelected)) { + themeGraphicDefined = true; element = tableView ? QS60StylePrivate::SE_TableItemPressed : QS60StylePrivate::SE_ListItemPressed; } else if (hasFocus || (isSelected && selectionBehavior != QAbstractItemView::SelectItems)) { element = QS60StylePrivate::SE_ListHighlight; elementRect = highlightRect; + themeGraphicDefined = true; } - QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags); + if (themeGraphicDefined) + QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags); } else { QCommonStyle::drawPrimitive(element, option, painter, widget); } diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 836969a..51ced96 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -571,6 +571,7 @@ public: void startAnimation(QS60StyleEnums::SkinParts animation); void stopAnimation(QS60StyleEnums::SkinParts animation); static QS60StyleAnimation* animationDefinition(QS60StyleEnums::SkinParts part); + static void removeAnimations(); #endif diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index f44b85e..5dda42e 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -1152,6 +1152,12 @@ QS60StylePrivate::QS60StylePrivate() setActiveLayout(); } +void QS60StylePrivate::removeAnimations() +{ + //currently only one animation in the list. + m_animations()->removeFirst(); +} + QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, int index, const QStyleOption *option) { diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp index ccd17a2..2d547a9 100644 --- a/src/gui/text/qfont_s60.cpp +++ b/src/gui/text/qfont_s60.cpp @@ -40,15 +40,26 @@ ****************************************************************************/ #include "qfont.h" +#include "qfont_p.h" #include <private/qt_s60_p.h> #include <private/qpixmap_s60_p.h> #include "qmutex.h" QT_BEGIN_NAMESPACE -#if 1 #ifdef QT_NO_FREETYPE Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); +Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, fontFamiliesOnFontServer, { + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + const int numTypeFaces = S60->screenDevice()->NumTypefaces(); + for (int i = 0; i < numTypeFaces; i++) { + TTypefaceSupport typefaceSupport; + S60->screenDevice()->TypefaceSupport(typefaceSupport, i); + const QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); + x->append(familyName); + } + lock.relock(); +}); #endif // QT_NO_FREETYPE QString QFont::lastResortFamily() const @@ -70,7 +81,7 @@ QString QFont::lastResortFamily() const lock.relock(); } return family; -#else +#else // QT_NO_FREETYPE // For the FreeType case we just hard code the face name, since otherwise on // East Asian systems we may get a name for a stroke based (non-ttf) font. @@ -82,15 +93,24 @@ QString QFont::lastResortFamily() const return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":"Series 60 Sans"); #endif // QT_NO_FREETYPE } -#else // 0 -QString QFont::lastResortFamily() const -{ - return QLatin1String("Series 60 Sans"); -} -#endif // 0 QString QFont::defaultFamily() const { +#ifdef QT_NO_FREETYPE + switch(d->request.styleHint) { + case QFont::SansSerif: { + static const char* const preferredSansSerif[] = {"Nokia Sans S60", "Series 60 Sans"}; + for (int i = 0; i < sizeof preferredSansSerif / sizeof preferredSansSerif[0]; ++i) { + const QString sansSerif = QLatin1String(preferredSansSerif[i]); + if (fontFamiliesOnFontServer()->contains(sansSerif)) + return sansSerif; + } + } + // No break. Intentional fall through. + default: + return lastResortFamily(); + } +#endif // QT_NO_FREETYPE return lastResortFamily(); } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 194c5f3..1e8461f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -874,8 +874,8 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy enum { Invalid, - Symbol, AppleRoman, + Symbol, Unicode11, Unicode, MicrosoftUnicode, @@ -939,7 +939,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy return 0; resolveTable: - *isSymbolFont = (score == Symbol); + *isSymbolFont = (symbolTable > -1); unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); @@ -1093,6 +1093,18 @@ const QVector<QRgb> &QFontEngine::grayPalette() return *qt_grayPalette(); } +QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) +{ + if (glyphs.numGlyphs >= 1) { + glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1]; + glyph_metrics_t gi = boundingBox(glyph); + if (gi.isValid()) + return round ? QFixed(qRound(gi.xoff - gi.x - gi.width)) + : QFixed(gi.xoff - gi.x - gi.width); + } + return 0; +} + // ------------------------------------------------------------------ // The box font engine // ------------------------------------------------------------------ diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 2c4fbab..a9b25f5 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -94,6 +94,13 @@ QT_BEGIN_NAMESPACE #define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6) #endif +/* FreeType 2.1.10 starts to provide FT_GlyphSlot_Embolden */ +#if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20110 +#define Q_FT_GLYPHSLOT_EMBOLDEN(slot) FT_GlyphSlot_Embolden(slot) +#else +#define Q_FT_GLYPHSLOT_EMBOLDEN(slot) +#endif + #define FLOOR(x) ((x) & -64) #define CEIL(x) (((x)+63) & -64) #define TRUNC(x) ((x) >> 6) @@ -794,7 +801,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph } FT_GlyphSlot slot = face->glyph; - if (embolden) FT_GlyphSlot_Embolden(slot); + if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot); int left = slot->metrics.horiBearingX; int right = slot->metrics.horiBearingX + slot->metrics.width; int top = slot->metrics.horiBearingY; @@ -940,7 +947,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph return 0; FT_GlyphSlot slot = face->glyph; - if (embolden) FT_GlyphSlot_Embolden(slot); + if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot); FT_Library library = qt_getFreetype(); info.xOff = TRUNC(ROUND(slot->advance.x)); @@ -1558,8 +1565,6 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs FT_Face face = freetype->face; for ( int i = 0; i < len; ++i ) { unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if ( !glyphs->glyphs[glyph_pos] ) { glyph_t glyph; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 91b6082..bdf3848 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -455,12 +455,13 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int * glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs) { QFixed w; + bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; + for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); + w += round ? glyphs.effectiveAdvance(i).round() + : glyphs.effectiveAdvance(i); } - return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); + return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); } glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) { @@ -1480,12 +1481,12 @@ void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs) { QFixed w; + bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); + w += round ? glyphs.effectiveAdvance(i).round() + : glyphs.effectiveAdvance(i); } - return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); + return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); } glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph) diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 922acfb..3b91cd8 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -253,6 +253,7 @@ public: protected: static const QVector<QRgb> &grayPalette(); + QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); private: struct GlyphCacheEntry { diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index a0593cc..53b6910 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -578,8 +578,6 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph if (symbol) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp index a7a95d0..decc89c 100644 --- a/src/gui/text/qfontengine_qws.cpp +++ b/src/gui/text/qfontengine_qws.cpp @@ -557,7 +557,7 @@ glyph_metrics_t QFontEngineQPF1::boundingBox(const QGlyphLayout &glyphs) QFixed w = 0; for (int i = 0; i < glyphs.numGlyphs; ++i) w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0); + return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); } glyph_metrics_t QFontEngineQPF1::boundingBox(glyph_t glyph) diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 52a1fe7..5980f20 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -166,6 +166,11 @@ const uchar *QSymbianTypeFaceExtras::cmap() const return reinterpret_cast<const uchar *>(m_cmapTable.constData()); } +bool QSymbianTypeFaceExtras::isSymbolCMap() const +{ + return m_symbolCMap; +} + CFont *QSymbianTypeFaceExtras::fontOwner() const { return m_cFont; @@ -256,7 +261,7 @@ bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout for (int i = 0; i < len; ++i) { const unsigned int uc = getChar(characters, i, len); *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, - isRtl ? QChar::mirroredChar(uc) : uc); + (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc); } glyphs->numGlyphs = g - glyphs->glyphs; @@ -345,7 +350,7 @@ glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs) for (int i = 0; i < glyphs.numGlyphs; ++i) w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0); + return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); } glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index d65f13b..d05c23c 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -81,6 +81,7 @@ public: bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; const uchar *cmap() const; CFont *fontOwner() const; + bool isSymbolCMap() const; private: CFont* m_cFont; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index a805612..4bed2b5 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -487,7 +487,7 @@ glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs) for (int i = 0; i < glyphs.numGlyphs; ++i) w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -tm.tmAscent, w, tm.tmHeight, w, 0); + return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0); } #ifndef Q_WS_WINCE diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index 21c2e02..b950b13 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -400,9 +400,9 @@ QStaticTextPrivate::QStaticTextPrivate() QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix), - items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), needsRelayout(true), - useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat), - untransformedCoordinates(other.untransformedCoordinates) + items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), textOption(other.textOption), + needsRelayout(true), useBackendOptimizations(other.useBackendOptimizations), + textFormat(other.textFormat), untransformedCoordinates(other.untransformedCoordinates) { } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8d6dd6c..119217a 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1646,7 +1646,6 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const for (int i = 0; i < layoutData->items.size(); i++) { const QScriptItem *si = layoutData->items.constData() + i; - QFontEngine *fe = fontEngine(*si); int pos = si->position; int ilen = length(i); @@ -1676,6 +1675,7 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const while (charFrom < ilen && logClusters[charFrom] == glyphStart) charFrom++; if (charFrom < ilen) { + QFontEngine *fe = fontEngine(*si); glyphStart = logClusters[charFrom]; int charEnd = from + len - 1 - pos; if (charEnd >= ilen) @@ -1694,11 +1694,6 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const gm.yoff += m.yoff; } } - - glyph_t glyph = glyphs.glyphs[logClusters[ilen - 1]]; - glyph_metrics_t gi = fe->boundingBox(glyph); - if (gi.isValid()) - gm.width -= qRound(gi.xoff - gi.x - gi.width); } } return gm; @@ -2144,8 +2139,11 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs) void **newMem = memory; newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); - Q_CHECK_PTR(newMem); - if (memory_on_stack && newMem) + if (!newMem) { + layoutState = LayoutFailed; + return false; + } + if (memory_on_stack) memcpy(newMem, memory, allocated*sizeof(void *)); memory = newMem; memory_on_stack = false; diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp index 24f6ccf..cd023cb 100644 --- a/src/gui/util/qdesktopservices_s60.cpp +++ b/src/gui/util/qdesktopservices_s60.cpp @@ -223,6 +223,7 @@ static void handleOtherSchemesL(const TDesC& aUrl) TApaTask task = taskList.FindApp(KUidBrowser); if (task.Exists()){ // Switch to existing browser instance + task.BringToForeground(); HBufC8* param8 = HBufC8::NewLC(buf16->Length()); param8->Des().Append(buf16->Des()); task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp index 7a61dc7..bd6c577 100644 --- a/src/gui/widgets/qdatetimeedit.cpp +++ b/src/gui/widgets/qdatetimeedit.cpp @@ -248,7 +248,7 @@ void QDateTimeEdit::setDateTime(const QDateTime &datetime) /*! \property QDateTimeEdit::date - \brief the QDate that is set in the QDateTimeEdit + \brief the QDate that is set in the widget By default, this property contains a date that refers to January 1, 2000. @@ -279,7 +279,7 @@ void QDateTimeEdit::setDate(const QDate &date) /*! \property QDateTimeEdit::time - \brief the QTime that is set in the QDateTimeEdit + \brief the QTime that is set in the widget By default, this property contains a time of 00:00:00 and 0 milliseconds. @@ -1555,13 +1555,6 @@ QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent) { } -/*! - \property QTimeEdit::time - \brief the QTime that is shown in the widget - - By default, this property contains a time of 00:00:00 and 0 milliseconds. -*/ - /*! \class QDateEdit @@ -1616,13 +1609,6 @@ QDateEdit::QDateEdit(const QDate &date, QWidget *parent) { } -/*! - \property QDateEdit::date - \brief the QDate that is shown in the widget - - By default, this property contains a date referring to January 1, 2000. -*/ - // --- QDateTimeEditPrivate --- diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index d027b91..b6dfd13 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -419,7 +419,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string - if (event->replacementStart() == 0) + if (event->replacementStart() <= 0) c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 837cf66..b35c318 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -201,7 +201,7 @@ static void ensureInitialized() deleteResource()) \value CustomOperation custom operation (created with - sendCustomRequest()) + sendCustomRequest()) \since 4.7 \omitvalue UnknownOperation diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index 65014a6..23d7800 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -45,12 +45,33 @@ #include "qbearerengine_p.h" #include <QtCore/qstringlist.h> +#include <QtCore/qcoreapplication.h> #ifndef QT_NO_BEARERMANAGEMENT QT_BEGIN_NAMESPACE -Q_GLOBAL_STATIC(QNetworkConfigurationManagerPrivate, connManager); +#define Q_GLOBAL_STATIC_QAPP_DESTRUCTION(TYPE, NAME) \ + Q_GLOBAL_STATIC_INIT(TYPE, NAME); \ + static void NAME##_cleanup() \ + { \ + delete this_##NAME.pointer; \ + this_##NAME.pointer = 0; \ + this_##NAME.destroyed = true; \ + } \ + static TYPE *NAME() \ + { \ + if (!this_##NAME.pointer && !this_##NAME.destroyed) { \ + TYPE *x = new TYPE; \ + if (!this_##NAME.pointer.testAndSetOrdered(0, x)) \ + delete x; \ + else \ + qAddPostRoutine(NAME##_cleanup); \ + } \ + return this_##NAME.pointer; \ + } + +Q_GLOBAL_STATIC_QAPP_DESTRUCTION(QNetworkConfigurationManagerPrivate, connManager); QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() { diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index d61c686..18cc14e 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -52,10 +52,13 @@ #include <qstring.h> #include <qdatetime.h> +//#define NTLMV1_CLIENT QT_BEGIN_NAMESPACE +#ifdef NTLMV1_CLIENT #include "../../3rdparty/des/des.cpp" +#endif static QByteArray qNtlmPhase1(); static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); @@ -203,17 +206,29 @@ QString QAuthenticator::user() const void QAuthenticator::setUser(const QString &user) { detach(); - int separatorPosn = 0; - separatorPosn = user.indexOf(QLatin1String("\\")); - if (separatorPosn == -1) { - //No domain name present + switch(d->method) { + case QAuthenticatorPrivate::DigestMd5: + case QAuthenticatorPrivate::Ntlm: + if((separatorPosn = user.indexOf(QLatin1String("\\"))) != -1) + { + //domain name is present + d->realm = user.left(separatorPosn); + d->user = user.mid(separatorPosn + 1); + } else if((separatorPosn = user.indexOf(QLatin1String("@"))) != -1) { + //domain name is present + d->realm = user.mid(separatorPosn + 1); + d->user = user.left(separatorPosn); + } else { + d->user = user; + d->realm.clear(); + } + break; + // For other auth mechanisms, domain name will be part of username + default: d->user = user; - } else { - //domain name is present - d->realm = user.left(separatorPosn); - d->user = user.mid(separatorPosn+1); + break; } } @@ -1178,11 +1193,9 @@ static QByteArray clientChallenge(const QAuthenticatorPrivate *ctx) } // caller has to ensure a valid targetInfoBuff -static bool qExtractServerTime(const QByteArray& targetInfoBuff, - quint64 *serverTime) +static QByteArray qExtractServerTime(const QByteArray& targetInfoBuff) { - Q_ASSERT(serverTime != 0); - bool retValue = false; + QByteArray timeArray; QDataStream ds(targetInfoBuff); ds.setByteOrder(QDataStream::LittleEndian); @@ -1193,19 +1206,16 @@ static bool qExtractServerTime(const QByteArray& targetInfoBuff, ds >> avLen; while(avId != 0) { if(avId == AVTIMESTAMP) { - QByteArray timeArray(avLen, 0); + timeArray.resize(avLen); //avLen size of QByteArray is allocated ds.readRawData(timeArray.data(), avLen); - bool ok; - *serverTime = timeArray.toHex().toLongLong(&ok, 16); - retValue = true; break; } ds.skipRawData(avLen); ds >> avId; ds >> avLen; } - return retValue; + return timeArray; } static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, @@ -1228,9 +1238,17 @@ static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, ds.writeRawData(reserved1.constData(), reserved1.size()); quint64 time = 0; + QByteArray timeArray; + + if(ch.targetInfo.len) + { + timeArray = qExtractServerTime(ch.targetInfoBuff); + } //if server sends time, use it instead of current time - if(!(ch.targetInfo.len && qExtractServerTime(ch.targetInfoBuff, &time))) { + if(timeArray.size()) { + ds.writeRawData(timeArray.constData(), timeArray.size()); + } else { QDateTime currentTime(QDate::currentDate(), QTime::currentTime(), Qt::UTC); @@ -1242,8 +1260,8 @@ static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, // represented as 100 nano seconds time = Q_UINT64_C(time * 10000000); + ds << time; } - ds << time; //8 byte client challenge QByteArray clientCh = clientChallenge(ctx); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 91265f3..f18c629 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1966,6 +1966,11 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri QMutexLocker locker(&globalData()->mutex); const QSslConfigurationPrivate *global = globalData()->config.constData(); + if (!global) { + ptr = 0; + return; + } + ptr->ref = 1; ptr->peerCertificate = global->peerCertificate; ptr->peerCertificateChain = global->peerCertificateChain; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 943a195..c49dba4 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2103,11 +2103,8 @@ void QGLContextPrivate::syncGlState() #ifdef QT_NO_EGL void QGLContextPrivate::swapRegion(const QRegion *) { - static bool firstWarning = true; - if (firstWarning) { - qWarning() << "::swapRegion called but not supported!"; - firstWarning = false; - } + Q_Q(QGLContext); + q->swapBuffers(); } #endif diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index b86fb78..d602000 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -426,6 +426,20 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, void QGLWindowSurface::beginPaint(const QRegion &) { + if (! context()) + return; + + int clearFlags = 0; + + if (context()->d_func()->workaround_needsFullClearOnEveryFrame) + clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + else if (context()->format().alpha()) + clearFlags = GL_COLOR_BUFFER_BIT; + + if (clearFlags) { + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(clearFlags); + } } void QGLWindowSurface::endPaint(const QRegion &rgn) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 32eb61a..19f13c2 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -48,6 +48,14 @@ #include <stdapis/sys/socket.h> #include <stdapis/net/if.h> +#ifdef SNAP_FUNCTIONALITY_AVAILABLE +#include <cmmanager.h> +#endif + +#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#include <extendedconnpref.h> +#endif + #ifndef QT_NO_BEARERMANAGEMENT QT_BEGIN_NAMESPACE @@ -113,7 +121,7 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() #endif } -void QNetworkSessionPrivateImpl::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState) +void QNetworkSessionPrivateImpl::configurationStateChanged(quint32 accessPointId, quint32 connMonId, QNetworkSession::State newState) { if (iHandleStateNotificationsFromManager) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG @@ -170,8 +178,10 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() return; if (iFirstSync) { - QObject::connect(engine, SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)), - this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State))); + QObject::connect(engine, + SIGNAL(configurationStateChanged(quint32,quint32,QNetworkSession::State)), + this, + SLOT(configurationStateChanged(quint32,quint32,QNetworkSession::State))); // Listen to configuration removals, so that in case the configuration // this session is based on is removed, session knows to enter Invalid -state. QObject::connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)), @@ -902,13 +912,13 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia if (iapId == 0) { _LIT(KSetting, "IAP\\Id"); iConnection.GetIntSetting(KSetting, iapId); -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE // Check if this is an Easy WLAN configuration. On Symbian^3 RConnection may report // the used configuration as 'EasyWLAN' IAP ID if someone has just opened the configuration // from WLAN Scan dialog, _and_ that connection is still up. We need to find the // real matching configuration. Function alters the Easy WLAN ID to real IAP ID (only if // easy WLAN): - engine->easyWlanTrueIapId(iapId); + easyWlanTrueIapId(iapId); #endif } @@ -948,7 +958,7 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia } } } else { -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE // On Symbian^3 (only, not earlier or Symbian^4) if the SNAP was not reachable, it triggers // user choice type of activity (EasyWLAN). As a result, a new IAP may be created, and // hence if was not found yet. Therefore update configurations and see if there is something new. @@ -1319,7 +1329,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint } } } -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE // If the retVal is not true here, it means that the status update may apply to an IAP outside of // SNAP (session is based on SNAP but follows IAP outside of it), which may occur on Symbian^3 EasyWlan. if (retVal == false && activeConfig.isValid() && @@ -1472,6 +1482,64 @@ void QNetworkSessionPrivateImpl::restoreDefaultIf() setdefaultif(&ifr); } +#if defined(SNAP_FUNCTIONALITY_AVAILABLE) +bool QNetworkSessionPrivateImpl::easyWlanTrueIapId(TUint32 &trueIapId) const +{ + RCmManager iCmManager; + TRAPD(err, iCmManager.OpenL()); + if (err != KErrNone) + return false; + + // Check if this is easy wlan id in the first place + if (trueIapId != iCmManager.EasyWlanIdL()) { + iCmManager.Close(); + return false; + } + + iCmManager.Close(); + + // Loop through all connections that connection monitor is aware + // and check for IAPs based on easy WLAN + TRequestStatus status; + TUint connectionCount; + iConnectionMonitor.GetConnectionCount(connectionCount, status); + User::WaitForRequest(status); + TUint connectionId; + TUint subConnectionCount; + TUint apId; + if (status.Int() == KErrNone) { + for (TUint i = 1; i <= connectionCount; i++) { + iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount); + iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, + KIAPId, apId, status); + User::WaitForRequest(status); + if (apId == trueIapId) { + TBuf<50>easyWlanNetworkName; + iConnectionMonitor.GetStringAttribute(connectionId, 0, KNetworkName, + easyWlanNetworkName, status); + User::WaitForRequest(status); + if (status.Int() != KErrNone) + continue; + + const QString ssid = QString::fromUtf16(easyWlanNetworkName.Ptr(), + easyWlanNetworkName.Length()); + + QNetworkConfigurationPrivatePointer ptr = engine->configurationFromSsid(ssid); + if (ptr) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNCM easyWlanTrueIapId(), found true IAP ID: " + << toSymbianConfig(ptr)->numericIdentifier(); +#endif + trueIapId = toSymbianConfig(ptr)->numericIdentifier(); + return true; + } + } + } + } + return false; +} +#endif + ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection) : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) { diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 1b0e968..51f2e70 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -64,9 +64,6 @@ #ifdef SNAP_FUNCTIONALITY_AVAILABLE #include <comms-infras/cs_mobility_apiext.h> #endif -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) - #include <extendedconnpref.h> -#endif QT_BEGIN_NAMESPACE @@ -132,7 +129,8 @@ protected: // From CActive void DoCancel(); private Q_SLOTS: - void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState); + void configurationStateChanged(quint32 accessPointId, quint32 connMonId, + QNetworkSession::State newState); void configurationRemoved(QNetworkConfigurationPrivatePointer config); void configurationAdded(QNetworkConfigurationPrivatePointer config); @@ -148,6 +146,11 @@ private: QNetworkInterface interface(TUint iapId) const; #endif +#if defined(SNAP_FUNCTIONALITY_AVAILABLE) + bool easyWlanTrueIapId(TUint32 &trueIapId) const; +#endif + + private: // data SymbianEngine *engine; diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index 9593461..2e2b671 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -692,7 +692,7 @@ void SymbianEngine::updateActiveAccessPoints() User::WaitForRequest(status); QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE if (!ptr) { // If IAP was not found, check if the update was about EasyWLAN ptr = configurationFromEasyWlan(apId, connectionId); @@ -1054,7 +1054,7 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE if (!ptr) { // Check if status was regarding EasyWLAN ptr = configurationFromEasyWlan(apId, connectionId); @@ -1079,7 +1079,7 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) User::WaitForRequest(status); QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE if (!ptr) { // Check for EasyWLAN ptr = configurationFromEasyWlan(apId, connectionId); @@ -1189,7 +1189,7 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) User::WaitForRequest(status); QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +#ifdef SNAP_FUNCTIONALITY_AVAILABLE if (!ptr) { // If IAP was not found, check if the update was about EasyWLAN ptr = configurationFromEasyWlan(apId, connectionId); @@ -1210,11 +1210,39 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) } } -#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE) +/* + Returns the network configuration that matches the given SSID. +*/ +QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromSsid(const QString &ssid) +{ + QMutexLocker locker(&mutex); + + // Browser through all items and check their name for match + QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i = + accessPointConfigurations.constBegin(); + while (i != accessPointConfigurations.constEnd()) { + QNetworkConfigurationPrivatePointer ptr = i.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if (ptr->name == ssid) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNCM EasyWlan uses real SSID: " << ssid; +#endif + return ptr; + } + ++i; + } + + return QNetworkConfigurationPrivatePointer(); +} + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE // Tries to derive configuration from EasyWLAN. // First checks if the interface brought up was EasyWLAN, then derives the real SSID, // and looks up configuration based on that one. -QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId, TUint connectionId) +QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId, + TUint connectionId) { if (apId == iCmManager.EasyWlanIdL()) { TRequestStatus status; @@ -1223,11 +1251,12 @@ QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUi easyWlanNetworkName, status ); User::WaitForRequest(status); if (status.Int() == KErrNone) { - QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(), easyWlanNetworkName.Length()); + const QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(), + easyWlanNetworkName.Length()); // Browser through all items and check their name for match - QHash<QString, QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> >::const_iterator i = - accessPointConfigurations.constBegin(); + QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i = + accessPointConfigurations.constBegin(); while (i != accessPointConfigurations.constEnd()) { QNetworkConfigurationPrivatePointer ptr = i.value(); @@ -1245,45 +1274,6 @@ QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUi } return QNetworkConfigurationPrivatePointer(); } - -bool SymbianEngine::easyWlanTrueIapId(TUint32& trueIapId) -{ - // Check if this is easy wlan id in the first place - if (trueIapId != iCmManager.EasyWlanIdL()) - return false; - - // Loop through all connections that connection monitor is aware - // and check for IAPs based on easy WLAN - TRequestStatus status; - TUint connectionCount; - iConnectionMonitor.GetConnectionCount(connectionCount, status); - User::WaitForRequest(status); - TUint connectionId; - TUint subConnectionCount; - TUint apId; - if (status.Int() == KErrNone) { - for (TUint i = 1; i <= connectionCount; i++) { - iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount); - iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, - KIAPId, apId, status); - User::WaitForRequest(status); - if (apId == trueIapId) { - QNetworkConfigurationPrivatePointer ptr = - configurationFromEasyWlan(apId, connectionId); - if (ptr) { -#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG - qDebug() << "QNCM easyWlanTrueIapId(), found true IAP ID: " - << toSymbianConfig(ptr)->numericIdentifier(); -#endif - trueIapId = toSymbianConfig(ptr)->numericIdentifier(); - return true; - } - } - } - } - return false; -} - #endif // Sessions may use this function to report configuration state changes, diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h index 1fe6395..7c1076e 100644 --- a/src/plugins/bearer/symbian/symbianengine.h +++ b/src/plugins/bearer/symbian/symbianengine.h @@ -138,10 +138,15 @@ public: QStringList accessPointConfigurationIdentifiers(); + QNetworkConfigurationPrivatePointer configurationFromSsid(const QString &ssid); + + // For QNetworkSessionPrivateImpl to indicate about state changes + void configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState); + Q_SIGNALS: void onlineStateChanged(bool isOnline); - void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, + void configurationStateChanged(quint32 accessPointId, quint32 connMonId, QNetworkSession::State newState); public Q_SLOTS: @@ -187,12 +192,9 @@ protected: private: // MConnectionMonitorObserver void EventL(const CConnMonEventBase& aEvent); - // For QNetworkSessionPrivate to indicate about state changes - void configurationStateChangeReport(TUint32 accessPointId, - QNetworkSession::State newState); -#ifdef OCC_FUNCTIONALITY_AVAILABLE - QNetworkConfigurationPrivatePointer configurationFromEasyWlan(TUint32 apId, TUint connectionId); - bool easyWlanTrueIapId(TUint32& trueIapId); +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + QNetworkConfigurationPrivatePointer configurationFromEasyWlan(TUint32 apId, + TUint connectionId); #endif private: // Data @@ -212,7 +214,6 @@ private: // Data friend class QNetworkSessionPrivate; friend class AccessPointsAvailabilityScanner; - friend class QNetworkSessionPrivateImpl; #ifdef SNAP_FUNCTIONALITY_AVAILABLE RCmManager iCmManager; diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 8347626..07aced4 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -2626,8 +2626,7 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file } /*! - \internal - \since 4.6 + \since 4.7 Evaluates the given \a program and returns the result of the evaluation. diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp index 02beba4..3857b75 100644 --- a/src/script/api/qscriptprogram.cpp +++ b/src/script/api/qscriptprogram.cpp @@ -32,9 +32,7 @@ QT_BEGIN_NAMESPACE /*! - \internal - - \since 4.6 + \since 4.7 \class QScriptProgram \brief The QScriptProgram class encapsulates a Qt Script program. diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index d545440..bf19a88 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE static const char *qt_inherit_text = "inherit"; #define QT_INHERIT QLatin1String(qt_inherit_text) -Q_DECL_IMPORT double qstrtod(const char *s00, char const **se, bool *ok); +Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); // ======== duplicated from qcolor_p |