diff options
157 files changed, 2406 insertions, 1131 deletions
diff --git a/demos/spectrum/3rdparty/fftreal/fftreal.pro b/demos/spectrum/3rdparty/fftreal/fftreal.pro index 6305af4..e5093ba 100644 --- a/demos/spectrum/3rdparty/fftreal/fftreal.pro +++ b/demos/spectrum/3rdparty/fftreal/fftreal.pro @@ -40,7 +40,7 @@ symbian { macx { CONFIG += lib_bundle } else { - !symbian: DESTDIR = ../.. + !symbian: DESTDIR = ../..$${spectrum_build_dir} } # Install diff --git a/demos/spectrum/app/app.pro b/demos/spectrum/app/app.pro index 4fe8b6d..b3ff227 100644 --- a/demos/spectrum/app/app.pro +++ b/demos/spectrum/app/app.pro @@ -65,7 +65,7 @@ symbian { LIBS += -F$${fftreal_dir} LIBS += -framework fftreal } else { - LIBS += -L.. + LIBS += -L..$${spectrum_build_dir} LIBS += -lfftreal } } @@ -91,10 +91,8 @@ symbian { DEPLOYMENT += fftreal } } else { + DESTDIR = ..$${spectrum_build_dir} macx { - # Specify directory in which to create spectrum.app bundle - DESTDIR = .. - !contains(DEFINES, DISABLE_FFT) { # Relocate fftreal.framework into spectrum.app bundle framework_dir = ../spectrum.app/Contents/Frameworks @@ -110,10 +108,7 @@ symbian { ../spectrum.app/Contents/MacOS/spectrum } } else { - # Specify directory in which to create spectrum application - DESTDIR = .. - - unix: { + linux-g++*: { # Provide relative path from application to fftreal library QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN } diff --git a/demos/spectrum/spectrum.pri b/demos/spectrum/spectrum.pri index c09aa0d..5773900 100644 --- a/demos/spectrum/spectrum.pri +++ b/demos/spectrum/spectrum.pri @@ -35,3 +35,15 @@ DEFINES += SPECTRUM_ANALYSER_SEPARATE_THREAD # Suppress warnings about strncpy potentially being unsafe, emitted by MSVC win32: DEFINES += _CRT_SECURE_NO_WARNINGS +win32 { + # spectrum_build_dir is defined with a leading slash so that it can + # be used in contexts such as + # ..$${spectrum_build_dir} + # without the result having a trailing slash where spectrum_build_dir + # is undefined. + spectrum_build_dir = /release + if (!debug_and_release|build_pass): CONFIG(debug, debug|release) { + spectrum_build_dir = /debug + } +} + diff --git a/dist/changes-4.6.4 b/dist/changes-4.6.4 index 389aa3a..3949b9a 100644 --- a/dist/changes-4.6.4 +++ b/dist/changes-4.6.4 @@ -66,8 +66,6 @@ QtOpenGL - QGLShaderProgram * [QTBUG-12478] Don't resolve GLSL extensions if no shaders. * [QTBUG-12591] setUniformValue(QSize) was setting (w,w) not (w,h). - * [QTBUG-12862] Don't #define highp/mediump/lowp if the desktop OpenGL - implementation has the GL_ARB_ES2_compatibility extension. * [QTBUG-12554] Wrong OpenGLVersionFlags on OpenGL 4.0 systems. QtScript @@ -109,7 +107,7 @@ Third party components Qt for Unix (X11 and Mac OS X) ------------------------------ - - + - Qt for Linux/X11 ---------------- diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 9a616ea..6abe96f 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -156,8 +156,10 @@ Example: \qml Rectangle { color: "steelblue" } + Rectangle { color: "transparent" } Rectangle { color: "#FF0000" } Rectangle { color: "#800000FF" } + Rectangle { color: "#00000000" } // ARGB fully transparent \endqml Or with the \l{QML:Qt::rgba()}{Qt.rgba()}, \l{QML:Qt::hsla()}{Qt.hsla()}, \l{QML:Qt::darker()}{Qt.darker()}, diff --git a/doc/src/porting/qt4-designer.qdoc b/doc/src/porting/qt4-designer.qdoc index fff3e89..ea5147a 100644 --- a/doc/src/porting/qt4-designer.qdoc +++ b/doc/src/porting/qt4-designer.qdoc @@ -36,18 +36,14 @@ \QD has been completely re-written based on our experience with the previous versions of the product for Qt 3. One of the main new - ideas behind this new version is to release the application as a + ideas is to release the application as a collection of interchangeable components that include the property editor, the widget box, and other useful tools for creating graphical user interfaces with Qt. These components can either be used together in the \QD application, or independently integrated into other systems. As a result, certain features such as the project editor and code editor have been removed from the version - included with this release. - - The current version of \QD is near feature complete and can be used for - many tasks. However, it is still under continuous development. This - document will explain what is already in place. + included with release 4. See also the \l{Qt Designer Manual}. @@ -128,7 +124,7 @@ \row \i \bold{Widget Editing Mode} - The new \QD allows widgets to be dropped into existing layouts on + \QD now allows widgets to be dropped into existing layouts on the form. Previously, it was necessary to break layouts in order to add new widgets to them. @@ -189,7 +185,7 @@ \row \i \bold{The Resource Editor} - The new \QD fully supports The Qt Resource System, and provide the + \QD now fully supports The Qt Resource System, and provides the Resource Editor to help designers and developers manage the resources that are needed by their applications. @@ -210,8 +206,8 @@ \i \inlineimage designer-action-editor.png \i \bold{The Action Editor} - With the release of Qt 4.1, \QD introduces the Action Editor - simplifying the management of actions when creating main window + With the release of Qt 4.1, \QD the Action Editor was introduced + to simplify the management of actions when creating main window applications. When creating a main window, you can add a menu bar and toolbars @@ -261,7 +257,7 @@ \section1 Run-Time Support for Forms - With the Qt 4.1 release, the new QtUiTools module is introduced to + With the Qt 4.1 release, the new QtUiTools module was introduced to provide classes handling forms created with \QD. Currently the module only contains the QUiLoader class. diff --git a/doc/src/template/style/style.css b/doc/src/template/style/style.css index ec0202a..12d297d 100755 --- a/doc/src/template/style/style.css +++ b/doc/src/template/style/style.css @@ -650,7 +650,7 @@ margin-top: 5px; _margin: 0 0 0 -20px; padding: 10px; - width: 220px; + width: 30%; _width: 196px; height: 250px; overflow: auto; diff --git a/mkspecs/common/symbian/symbian-mmp.conf b/mkspecs/common/symbian/symbian-mmp.conf index 5292781..1fbd302 100644 --- a/mkspecs/common/symbian/symbian-mmp.conf +++ b/mkspecs/common/symbian/symbian-mmp.conf @@ -4,16 +4,6 @@ include(symbian.conf) -contains(QMAKE_HOST.os, "Windows") { - QMAKE_MOC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc.exe - QMAKE_UIC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic.exe - QMAKE_IDC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc.exe -} else { - QMAKE_MOC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc - QMAKE_UIC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic - QMAKE_IDC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc -} - load(symbian/add_mmp_rules) symbian-abld { diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index cc5b788..d8c38f4 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -95,6 +95,10 @@ contains(QMAKE_HOST.os,Windows) { QMAKE_DEL_DIR = rmdir QMAKE_DEL_TREE = rmdir /s /q QMAKE_CHK_DIR_EXISTS = if not exist + + QMAKE_MOC = $$[QT_INSTALL_BINS]\\moc.exe + QMAKE_UIC = $$[QT_INSTALL_BINS]\\uic.exe + QMAKE_IDC = $$[QT_INSTALL_BINS]\\idc.exe } else { QMAKE_COPY = cp QMAKE_COPY_DIR = cp -r @@ -104,6 +108,10 @@ contains(QMAKE_HOST.os,Windows) { QMAKE_DEL_DIR = rmdir QMAKE_DEL_TREE = rm -rf QMAKE_CHK_DIR_EXISTS = test -d + + QMAKE_MOC = $$[QT_INSTALL_BINS]/moc + QMAKE_UIC = $$[QT_INSTALL_BINS]/uic + QMAKE_IDC = $$[QT_INSTALL_BINS]/idc } QMAKE_IDL = midl diff --git a/mkspecs/features/symbian/symbian_building.prf b/mkspecs/features/symbian/symbian_building.prf index 614fb65..1a51cb2 100644 --- a/mkspecs/features/symbian/symbian_building.prf +++ b/mkspecs/features/symbian/symbian_building.prf @@ -229,7 +229,7 @@ symbian_resources_INCLUDES = $$replace(symbian_resources_INCLUDES, ",", " -I") symbian_resources_INCLUDES += $$join(INCLUDEPATH, " -I", "-I") symbian_resources_DEFINES = $$join(DEFINES, " -D", "-D") symbian_resources_RCC_DIR = $$replace(RCC_DIR, "/$", "") -symbian_resources_INCLUDES += "-I $$symbian_resources_RCC_DIR" +symbian_resources_INCLUDES += "-I$$symbian_resources_RCC_DIR" for(symbian_resource, SYMBIAN_RESOURCES) { symbian_resource = $$basename(symbian_resource) @@ -245,7 +245,7 @@ symbianresources.commands = cpp -nostdinc -undef \ $$symbian_resources_INCLUDES \ $$symbian_resources_DEFINES \ ${QMAKE_FILE_NAME} \ - -o $${symbian_resources_RCC_DIR}/${QMAKE_FILE_BASE}.rpp \ + > $${symbian_resources_RCC_DIR}/${QMAKE_FILE_BASE}.rpp \ && rcomp -u -m045,046,047 \ -s$${symbian_resources_RCC_DIR}/${QMAKE_FILE_BASE}.rpp \ -o$${symbianDestdir}/${QMAKE_FILE_BASE}$${QT_LIBINFIX}.rsc \ @@ -265,7 +265,7 @@ contains(TEMPLATE, "app"):!contains(CONFIG, "no_icon") { $$symbian_resources_INCLUDES \ $$symbian_resources_DEFINES \ $${baseTarget}.rss \ - -o $${symbian_resources_RCC_DIR}/$${baseTarget}.rpp \ + > $${symbian_resources_RCC_DIR}/$${baseTarget}.rpp \ && rcomp -u -m045,046,047 \ -s$${symbian_resources_RCC_DIR}/$${baseTarget}.rpp \ -o$${symbianDestdir}/$${baseTarget}.rsc \ @@ -284,7 +284,7 @@ contains(TEMPLATE, "app"):!contains(CONFIG, "no_icon") { $$symbian_resources_INCLUDES \ $$symbian_resources_DEFINES \ $${baseTarget}_reg.rss \ - -o $${symbian_resources_RCC_DIR}/$${baseTarget}_reg.rpp \ + > $${symbian_resources_RCC_DIR}/$${baseTarget}_reg.rpp \ && rcomp -u -m045,046,047 \ -s$${symbian_resources_RCC_DIR}/$${baseTarget}_reg.rpp \ -o$${symbianDestdir}/$${baseTarget}_reg.rsc \ diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm index 3877edb..a557cbb 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm @@ -21,7 +21,7 @@ CLEAN_TARGET:=$(1) $(1): $(2) $(call startrule,qmake_emulator_deployment) \ - $(GNUCP) --no-preserve=mode $(2) "$$@" && \ + $(GNUCP) --remove-destination --no-preserve=mode $(2) "$$@" && \ $(GNUCHMOD) a+rw "$$@" \ $(call endrule,qmake_emulator_deployment) endef diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8330e47..579c225 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -127,6 +127,7 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; +void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0; QObjectData::~QObjectData() {} @@ -1094,7 +1095,12 @@ QString QObject::objectName() const void QObject::setObjectName(const QString &name) { Q_D(QObject); + bool objectNameChanged = d->declarativeData && d->objectName != name; + d->objectName = name; + + if (objectNameChanged) + d->declarativeData->objectNameChanged(d->declarativeData, this); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 4800e6a..814769c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -89,6 +89,7 @@ class Q_CORE_EXPORT QAbstractDeclarativeData public: static void (*destroyed)(QAbstractDeclarativeData *, QObject *); static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); + static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *); }; class Q_CORE_EXPORT QObjectPrivate : public QObjectData diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index ab7530d..c252e64 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1630,6 +1630,7 @@ QString QTime::toString(Qt::DateFormat format) const \endtable If the datetime is invalid, an empty string will be returned. + If \a format is empty, the default format "hh:mm:ss" is used. \sa QDate::toString() QDateTime::toString() */ diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index 909d940..7213c6e 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -254,7 +254,7 @@ QLinkedListData QLinkedListData::shared_null = { \sa insert() */ -/*! +/*! \fn bool QLinkedList::removeOne(const T &value) \since 4.4 @@ -830,7 +830,7 @@ QLinkedListData QLinkedListData::shared_null = { QLinkedList\<T\>::const_iterator allows you to iterate over a QLinkedList\<T\>. If you want modify the QLinkedList as you iterate - over it, you must use QLinkedList::const_iterator instead. It is + over it, you must use QLinkedList::iterator instead. It is generally good practice to use QLinkedList::const_iterator on a non-const QLinkedList as well, unless you need to change the QLinkedList through the iterator. Const iterators are slightly diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 6cc6fc1..9ba3768 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -936,7 +936,7 @@ void **QListData::erase(void **xi) This function requires the value type to have an implementation of \c operator==(). - Note that QList uses 0-based indexes, just like C++ arrays. Negative + Note that QList uses 0-based indexes, just like C++ arrays. Negative indexes are not supported with the exception of the value mentioned above. diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 33c21b1..001abca 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -466,7 +466,7 @@ QDeclarativeFlickable::~QDeclarativeFlickable() qreal QDeclarativeFlickable::contentX() const { Q_D(const QDeclarativeFlickable); - return -d->hData.move.value(); + return -d->contentItem->x(); } void QDeclarativeFlickable::setContentX(qreal pos) @@ -484,7 +484,7 @@ void QDeclarativeFlickable::setContentX(qreal pos) qreal QDeclarativeFlickable::contentY() const { Q_D(const QDeclarativeFlickable); - return -d->vData.move.value(); + return -d->contentItem->y(); } void QDeclarativeFlickable::setContentY(qreal pos) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 8216ab7..6ee6b0d 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -218,7 +218,14 @@ public: return visibleItems.last()->rowPos() + rows * rowSize(); } } else { - return (modelIndex / columns) * rowSize(); + qreal pos = (modelIndex / columns) * rowSize(); + if (header) { + qreal headerSize = flow == QDeclarativeGridView::LeftToRight + ? header->item->height() + : header->item->width(); + pos += headerSize; + } + return pos; } return 0; } diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 02b4807..c3bac2d 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -46,8 +46,6 @@ #include <qdeclarativeinfo.h> #include <qdeclarativepixmapcache_p.h> -#include <QFile> - QT_BEGIN_NAMESPACE QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent) @@ -115,6 +113,7 @@ void QDeclarativeImageBase::setSourceSize(const QSize& size) return; d->sourcesize = size; + d->explicitSourceSize = true; emit sourceSizeChanged(); if (isComponentComplete()) load(); @@ -123,7 +122,10 @@ void QDeclarativeImageBase::setSourceSize(const QSize& size) QSize QDeclarativeImageBase::sourceSize() const { Q_D(const QDeclarativeImageBase); - return d->sourcesize.isValid() ? d->sourcesize : QSize(implicitWidth(),implicitHeight()); + + int width = d->sourcesize.width(); + int height = d->sourcesize.height(); + return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight()); } void QDeclarativeImageBase::load() @@ -141,7 +143,7 @@ void QDeclarativeImageBase::load() pixmapChange(); update(); } else { - d->pix.load(qmlEngine(this), d->url, d->sourcesize, d->async); + d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), d->async); if (d->pix.isLoading()) { d->progress = 0.0; @@ -186,11 +188,8 @@ void QDeclarativeImageBase::requestFinished() setImplicitWidth(d->pix.width()); setImplicitHeight(d->pix.height()); - if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) { - d->sourcesize.setWidth(d->pix.width()); - d->sourcesize.setHeight(d->pix.height()); + if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) emit sourceSizeChanged(); - } if (d->status != oldStatus) emit statusChanged(d->status); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index aee8b28..3d23ba9 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -69,6 +69,7 @@ public: QDeclarativeImageBasePrivate() : status(QDeclarativeImageBase::Null), progress(0.0), + explicitSourceSize(false), async(false) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; @@ -79,6 +80,7 @@ public: QUrl url; qreal progress; QSize sourcesize; + bool explicitSourceSize : 1; bool async : 1; }; diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index b135e84..95a4fd6 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -56,7 +56,6 @@ #include <QDebug> #include <QPen> -#include <QFile> #include <QEvent> #include <QGraphicsSceneMouseEvent> #include <QtCore/qnumeric.h> @@ -1180,7 +1179,7 @@ void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event, bool post) d->inPress = true; for (int ii = 0; ii < d->targets.count(); ++ii) { QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); - if (i) { + if (i && i->isVisible()) { d->item->scene()->sendEvent(i, event); if (event->isAccepted()) { d->inPress = false; @@ -1222,7 +1221,7 @@ void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event, bool post) d->inRelease = true; for (int ii = 0; ii < d->targets.count(); ++ii) { QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); - if (i) { + if (i && i->isVisible()) { d->item->scene()->sendEvent(i, event); if (event->isAccepted()) { d->inRelease = false; @@ -1247,7 +1246,7 @@ void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool p d->inIM = true; for (int ii = 0; ii < d->targets.count(); ++ii) { QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); - if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { + if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { d->item->scene()->sendEvent(i, event); if (event->isAccepted()) { d->imeItem = i; @@ -1275,7 +1274,7 @@ QVariant QDeclarativeKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) if (d->item) { for (int ii = 0; ii < d->targets.count(); ++ii) { QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); - if (i && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check? + if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check? QVariant v = static_cast<QDeclarativeItemAccessor *>(i)->doInputMethodQuery(query); if (v.userType() == QVariant::RectF) v = d->item->mapRectFromItem(i, v.toRectF()); //### cost? diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 6b46bc5..6fd3b71 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -775,7 +775,6 @@ void QDeclarativeListViewPrivate::layout() setPosition(0); return; } - updateSections(); if (!visibleItems.isEmpty()) { qreal oldEnd = visibleItems.last()->endPosition(); qreal pos = visibleItems.first()->endPosition() + spacing + 1; @@ -934,6 +933,7 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) return; if (listItem->attached->m_prevSection != listItem->attached->m_section) { if (!listItem->section) { + qreal pos = listItem->position(); int i = sectionCacheSize-1; while (i >= 0 && !sectionCache[i]) --i; @@ -961,8 +961,10 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) delete context; } } + listItem->setPosition(pos); } } else if (listItem->section) { + qreal pos = listItem->position(); int i = 0; do { if (!sectionCache[i]) { @@ -975,12 +977,13 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) } while (i < sectionCacheSize); delete listItem->section; listItem->section = 0; + listItem->setPosition(pos); } } void QDeclarativeListViewPrivate::updateSections() { - if (sectionCriteria) { + if (sectionCriteria && !visibleItems.isEmpty()) { QString prevSection; if (visibleIndex > 0) prevSection = sectionAt(visibleIndex-1); @@ -990,6 +993,8 @@ void QDeclarativeListViewPrivate::updateSections() if (visibleItems.at(i)->index != -1) { QDeclarativeListViewAttached *attached = visibleItems.at(i)->attached; attached->setPrevSection(prevSection); + QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property()); + attached->setSection(sectionCriteria->sectionString(propValue)); if (prevAtt) prevAtt->setNextSection(attached->section()); createSection(visibleItems.at(i)); @@ -1009,18 +1014,27 @@ void QDeclarativeListViewPrivate::updateSections() void QDeclarativeListViewPrivate::updateCurrentSection() { + Q_Q(QDeclarativeListView); if (!sectionCriteria || visibleItems.isEmpty()) { - currentSection.clear(); + if (!currentSection.isEmpty()) { + currentSection.clear(); + emit q->currentSectionChanged(); + } return; } int index = 0; while (index < visibleItems.count() && visibleItems.at(index)->endPosition() < position()) ++index; + QString newSection = currentSection; if (index < visibleItems.count()) - currentSection = visibleItems.at(index)->attached->section(); + newSection = visibleItems.at(index)->attached->section(); else - currentSection = visibleItems.first()->attached->section(); + newSection = visibleItems.first()->attached->section(); + if (newSection != currentSection) { + currentSection = newSection; + emit q->currentSectionChanged(); + } } void QDeclarativeListViewPrivate::updateCurrent(int modelIndex) @@ -1551,6 +1565,7 @@ void QDeclarativeListView::setModel(const QVariant &model) disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); + disconnect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int))); disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset())); disconnect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); @@ -1581,6 +1596,7 @@ void QDeclarativeListView::setModel(const QVariant &model) if (d->model) { d->bufferMode = QDeclarativeListViewPrivate::BufferBefore | QDeclarativeListViewPrivate::BufferAfter; if (isComponentComplete()) { + updateSections(); refill(); if (d->currentIndex >= d->model->count() || d->currentIndex < 0) { setCurrentIndex(0); @@ -1596,6 +1612,7 @@ void QDeclarativeListView::setModel(const QVariant &model) connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); + connect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int))); connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset())); connect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); @@ -1653,6 +1670,7 @@ void QDeclarativeListView::setDelegate(QDeclarativeComponent *delegate) d->visibleItems.clear(); d->releaseItem(d->currentItem); d->currentItem = 0; + updateSections(); refill(); d->moveReason = QDeclarativeListViewPrivate::SetIndex; d->updateCurrent(d->currentIndex); @@ -2066,8 +2084,10 @@ void QDeclarativeListView::setCacheBuffer(int b) QDeclarativeViewSection *QDeclarativeListView::sectionCriteria() { Q_D(QDeclarativeListView); - if (!d->sectionCriteria) + if (!d->sectionCriteria) { d->sectionCriteria = new QDeclarativeViewSection(this); + connect(d->sectionCriteria, SIGNAL(propertyChanged()), this, SLOT(updateSections())); + } return d->sectionCriteria; } @@ -2660,6 +2680,7 @@ void QDeclarativeListView::componentComplete() { Q_D(QDeclarativeListView); QDeclarativeFlickable::componentComplete(); + updateSections(); if (d->isValid()) { refill(); d->moveReason = QDeclarativeListViewPrivate::SetIndex; @@ -2676,6 +2697,18 @@ void QDeclarativeListView::componentComplete() } } +void QDeclarativeListView::updateSections() +{ + Q_D(QDeclarativeListView); + if (isComponentComplete() && d->model) { + QList<QByteArray> roles; + if (d->sectionCriteria && !d->sectionCriteria->property().isEmpty()) + roles << d->sectionCriteria->property().toUtf8(); + d->model->setWatchedRoles(roles); + d->updateSections(); + } +} + void QDeclarativeListView::refill() { Q_D(QDeclarativeListView); @@ -2885,6 +2918,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); + d->updateSections(); d->itemCount += count; emit countChanged(); } @@ -2977,6 +3011,7 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) } } + d->updateSections(); emit countChanged(); } @@ -3098,6 +3133,14 @@ void QDeclarativeListView::itemsMoved(int from, int to, int count) // Ensure we don't cause an ugly list scroll. d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy); + d->updateSections(); + d->layout(); +} + +void QDeclarativeListView::itemsChanged(int, int) +{ + Q_D(QDeclarativeListView); + d->updateSections(); d->layout(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 735b248..2678b90 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -250,11 +250,13 @@ protected: virtual void componentComplete(); private Q_SLOTS: + void updateSections(); void refill(); void trackedPositionChanged(); void itemsInserted(int index, int count); void itemsRemoved(int index, int count); void itemsMoved(int from, int to, int count); + void itemsChanged(int index, int count); void modelReset(); void destroyRemoved(); void createdItem(int index, QDeclarativeItem *item); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index a0208ef..1533d55 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -557,6 +557,7 @@ void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) ungrabMouse(); setKeepMouseGrab(false); } + d->doubleClick = false; } void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) @@ -565,14 +566,12 @@ void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even if (!d->absorb) { QDeclarativeItem::mouseDoubleClickEvent(event); } else { + d->doubleClick = true; d->saveEvent(event); QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false); me.setAccepted(d->isDoubleClickConnected()); emit this->doubleClicked(&me); - if (!me.isAccepted()) { - // Only deliver the press event if we haven't accepted the double click. - QDeclarativeItem::mouseDoubleClickEvent(event); - } + QDeclarativeItem::mouseDoubleClickEvent(event); } } @@ -841,7 +840,8 @@ bool QDeclarativeMouseArea::setPressed(bool p) d->pressed = p; QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress); if (d->pressed) { - emit pressed(&me); + if (!d->doubleClick) + emit pressed(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); emit mousePositionChanged(&me); @@ -849,7 +849,7 @@ bool QDeclarativeMouseArea::setPressed(bool p) emit released(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); - if (isclick && !d->longPress) + if (isclick && !d->longPress && !d->doubleClick) emit clicked(&me); } diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h index 48a56d9..06a01d3 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h @@ -68,7 +68,7 @@ class QDeclarativeMouseAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativeMouseAreaPrivate() : absorb(true), hovered(false), pressed(false), longPress(false), - moved(false), stealMouse(false), drag(0) + moved(false), stealMouse(false), doubleClick(false), drag(0) { } @@ -109,6 +109,7 @@ public: bool dragX : 1; bool dragY : 1; bool stealMouse : 1; + bool doubleClick : 1; QDeclarativeDrag *drag; QPointF startScene; qreal startX; diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp index a6db1fa..b470b3a 100644 --- a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp +++ b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp @@ -44,7 +44,6 @@ #include <QDebug> #include <QPen> -#include <QFile> #include <QEvent> #include <QApplication> #include <QGraphicsSceneMouseEvent> diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 31943b2..81c84f5 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1112,16 +1112,16 @@ void QDeclarativePathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (!interactive || !lastPosTime.isValid()) return; + qreal newPc; + QPointF pathPoint = pointNear(event->pos(), &newPc); if (!stealMouse) { - QPointF delta = event->pos() - startPoint; + QPointF delta = pathPoint - startPoint; if (qAbs(delta.x()) > QApplication::startDragDistance() || qAbs(delta.y()) > QApplication::startDragDistance()) stealMouse = true; } if (stealMouse) { moveReason = QDeclarativePathViewPrivate::Mouse; - qreal newPc; - pointNear(event->pos(), &newPc); qreal diff = (newPc - startPc)*modelCount*mappedRange; if (diff) { setOffset(offset + diff); diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 65f1564..308aefa 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -82,15 +82,16 @@ private: static QSet<QUrl> errors; }; -DEFINE_BOOL_CONFIG_OPTION(disableImageCache, QML_DISABLE_IMAGE_CACHE); +DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE); QDeclarativeTextPrivate::QDeclarativeTextPrivate() -: color((QRgb)0), style(QDeclarativeText::Normal), - hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - imgDirty(true), dirty(true), richText(false), singleline(false), cache(true), internalWidthUpdate(false), doc(0), - format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap) +: color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), + vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), imageCacheDirty(true), + updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true), + internalWidthUpdate(false), doc(0) { - cache = !disableImageCache(); + cacheAllTextAsImage = enableImageCache(); QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton; QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; } @@ -151,7 +152,6 @@ void QTextDocumentWithImageResources::requestFinished() #endif QDeclarativeTextPrivate *d = QDeclarativeTextPrivate::get(textItem); d->updateLayout(); - d->markImgDirty(); } } @@ -172,6 +172,382 @@ void QTextDocumentWithImageResources::setText(const QString &text) QSet<QUrl> QTextDocumentWithImageResources::errors; +QDeclarativeTextPrivate::~QDeclarativeTextPrivate() +{ +} + +void QDeclarativeTextPrivate::updateLayout() +{ + Q_Q(QDeclarativeText); + if (!q->isComponentComplete()) { + updateOnComponentComplete = true; + return; + } + + // Setup instance of QTextLayout for all cases other than richtext + if (!richText) { + layout.clearLayout(); + layout.setFont(font); + if (format != QDeclarativeText::StyledText) { + QString tmp = text; + tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); + singleline = !tmp.contains(QChar::LineSeparator); + if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { + QFontMetrics fm(font); + tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...? + } + layout.setText(tmp); + } else { + singleline = false; + QDeclarativeStyledText::parse(text, layout); + } + } + + updateSize(); +} + +void QDeclarativeTextPrivate::updateSize() +{ + Q_Q(QDeclarativeText); + + if (!q->isComponentComplete()) { + updateOnComponentComplete = true; + return; + } + + invalidateImageCache(); + + QFontMetrics fm(font); + if (text.isEmpty()) { + q->setImplicitHeight(fm.height()); + emit q->paintedSizeChanged(); + return; + } + + int dy = q->height(); + QSize size(0, 0); + + //setup instance of QTextLayout for all cases other than richtext + if (!richText) { + size = setupTextLayout(); + if (layedOutTextSize != size) { + q->prepareGeometryChange(); + layedOutTextSize = size; + } + dy -= size.height(); + } else { + singleline = false; // richtext can't elide or be optimized for single-line case + ensureDoc(); + doc->setDefaultFont(font); + QTextOption option((Qt::Alignment)int(hAlign | vAlign)); + option.setWrapMode(QTextOption::WrapMode(wrapMode)); + doc->setDefaultTextOption(option); + if (wrapMode != QDeclarativeText::NoWrap && q->widthValid()) + doc->setTextWidth(q->width()); + else + doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) + dy -= (int)doc->size().height(); + QSize dsize = doc->size().toSize(); + if (dsize != layedOutTextSize) { + q->prepareGeometryChange(); + layedOutTextSize = dsize; + } + size = QSize(int(doc->idealWidth()),dsize.height()); + } + int yoff = 0; + + if (q->heightValid()) { + if (vAlign == QDeclarativeText::AlignBottom) + yoff = dy; + else if (vAlign == QDeclarativeText::AlignVCenter) + yoff = dy/2; + } + q->setBaselineOffset(fm.ascent() + yoff); + + //### need to comfirm cost of always setting these for richText + internalWidthUpdate = true; + q->setImplicitWidth(size.width()); + internalWidthUpdate = false; + q->setImplicitHeight(size.height()); + emit q->paintedSizeChanged(); +} + +/*! + Lays out the QDeclarativeTextPrivate::layout QTextLayout in the constraints of the QDeclarativeText. + + Returns the size of the final text. This can be used to position the text vertically (the text is + already absolutely positioned horizontally). +*/ +QSize QDeclarativeTextPrivate::setupTextLayout() +{ + // ### text layout handling should be profiled and optimized as needed + // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine); + + Q_Q(QDeclarativeText); + layout.setCacheEnabled(true); + + int height = 0; + qreal widthUsed = 0; + qreal lineWidth = 0; + + //set manual width + if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) + lineWidth = q->width(); + + QTextOption textOption = layout.textOption(); + textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); + layout.setTextOption(textOption); + + layout.beginLayout(); + while (1) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + + if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) + line.setLineWidth(lineWidth); + } + layout.endLayout(); + + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + } + + qreal layoutWidth = q->widthValid()?q->width():widthUsed; + + int x = 0; + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); + line.setPosition(QPointF(0, height)); + height += int(line.height()); + + if (!cacheAllTextAsImage) { + if (hAlign == QDeclarativeText::AlignLeft) { + x = 0; + } else if (hAlign == QDeclarativeText::AlignRight) { + x = layoutWidth - (int)line.naturalTextWidth(); + } else if (hAlign == QDeclarativeText::AlignHCenter) { + x = (layoutWidth - (int)line.naturalTextWidth()) / 2; + } + line.setPosition(QPoint(x, (int)line.y())); + } + } + + return QSize(qCeil(widthUsed), height); +} + +/*! + Returns a painted version of the QDeclarativeTextPrivate::layout QTextLayout. + If \a drawStyle is true, the style color overrides all colors in the document. +*/ +QPixmap QDeclarativeTextPrivate::textLayoutImage(bool drawStyle) +{ + //do layout + QSize size = layedOutTextSize; + + int x = 0; + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); + if (hAlign == QDeclarativeText::AlignLeft) { + x = 0; + } else if (hAlign == QDeclarativeText::AlignRight) { + x = size.width() - (int)line.naturalTextWidth(); + } else if (hAlign == QDeclarativeText::AlignHCenter) { + x = (size.width() - (int)line.naturalTextWidth()) / 2; + } + line.setPosition(QPoint(x, (int)line.y())); + } + + //paint text + QPixmap img(size); + if (!size.isEmpty()) { + img.fill(Qt::transparent); +#ifdef Q_WS_MAC + bool oldSmooth = qt_applefontsmoothing_enabled; + qt_applefontsmoothing_enabled = false; +#endif + QPainter p(&img); +#ifdef Q_WS_MAC + qt_applefontsmoothing_enabled = oldSmooth; +#endif + drawTextLayout(&p, QPointF(0,0), drawStyle); + } + return img; +} + +/*! + Paints the QDeclarativeTextPrivate::layout QTextLayout into \a painter at \a pos. If + \a drawStyle is true, the style color overrides all colors in the document. +*/ +void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle) +{ + if (drawStyle) + painter->setPen(styleColor); + else + painter->setPen(color); + painter->setFont(font); + layout.draw(painter, pos); +} + +/*! + Returns a painted version of the QDeclarativeTextPrivate::doc QTextDocument. + If \a drawStyle is true, the style color overrides all colors in the document. +*/ +QPixmap QDeclarativeTextPrivate::textDocumentImage(bool drawStyle) +{ + QSize size = doc->size().toSize(); + + //paint text + QPixmap img(size); + img.fill(Qt::transparent); +#ifdef Q_WS_MAC + bool oldSmooth = qt_applefontsmoothing_enabled; + qt_applefontsmoothing_enabled = false; +#endif + QPainter p(&img); +#ifdef Q_WS_MAC + qt_applefontsmoothing_enabled = oldSmooth; +#endif + + QAbstractTextDocumentLayout::PaintContext context; + + QTextOption oldOption(doc->defaultTextOption()); + if (drawStyle) { + context.palette.setColor(QPalette::Text, styleColor); + QTextOption colorOption(doc->defaultTextOption()); + colorOption.setFlags(QTextOption::SuppressColors); + doc->setDefaultTextOption(colorOption); + } else { + context.palette.setColor(QPalette::Text, color); + } + doc->documentLayout()->draw(&p, context); + if (drawStyle) + doc->setDefaultTextOption(oldOption); + return img; +} + +/*! + Mark the image cache as dirty. +*/ +void QDeclarativeTextPrivate::invalidateImageCache() +{ + Q_Q(QDeclarativeText); + + if (imageCacheDirty) + return; + + imageCacheDirty = true; + imageCache = QPixmap(); + + if (q->isComponentComplete()) + q->update(); +} + +/*! + Tests if the image cache is dirty, and repaints it if it is. +*/ +void QDeclarativeTextPrivate::checkImageCache() +{ + if (!imageCacheDirty) + return; + + if (text.isEmpty()) { + + imageCache = QPixmap(); + + } else { + + QPixmap textImage; + QPixmap styledImage; + + if (richText) { + textImage = textDocumentImage(false); + if (style != QDeclarativeText::Normal) + styledImage = textDocumentImage(true); //### should use styleColor + } else { + textImage = textLayoutImage(false); + if (style != QDeclarativeText::Normal) + styledImage = textLayoutImage(true); //### should use styleColor + } + + switch (style) { + case QDeclarativeText::Outline: + imageCache = drawOutline(textImage, styledImage); + break; + case QDeclarativeText::Sunken: + imageCache = drawOutline(textImage, styledImage, -1); + break; + case QDeclarativeText::Raised: + imageCache = drawOutline(textImage, styledImage, 1); + break; + default: + imageCache = textImage; + break; + } + + } + + imageCacheDirty = false; +} + +/*! + Ensures the QDeclarativeTextPrivate::doc variable is set to a valid text document +*/ +void QDeclarativeTextPrivate::ensureDoc() +{ + if (!doc) { + Q_Q(QDeclarativeText); + doc = new QTextDocumentWithImageResources(q); + doc->setDocumentMargin(0); + } +} + +/*! + Draw \a styleSource as an outline around \a source and return the new image. +*/ +QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource) +{ + QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2); + img.fill(Qt::transparent); + + QPainter ppm(&img); + + QPoint pos(0, 0); + pos += QPoint(-1, 0); + ppm.drawPixmap(pos, styleSource); + pos += QPoint(2, 0); + ppm.drawPixmap(pos, styleSource); + pos += QPoint(-1, -1); + ppm.drawPixmap(pos, styleSource); + pos += QPoint(0, 2); + ppm.drawPixmap(pos, styleSource); + + pos += QPoint(0, -1); + ppm.drawPixmap(pos, source); + ppm.end(); + + return img; +} + +/*! + Draw \a styleSource below \a source at \a yOffset and return the new image. +*/ +QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset) +{ + QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2); + img.fill(Qt::transparent); + + QPainter ppm(&img); + + ppm.drawPixmap(QPoint(0, yOffset), styleSource); + ppm.drawPixmap(0, 0, source); + + ppm.end(); + + return img; +} + /*! \qmlclass Text QDeclarativeText \ingroup qml-basic-visual-elements @@ -211,10 +587,44 @@ QDeclarativeText::~QDeclarativeText() { } +/*! + \qmlproperty bool Text::clip + This property holds whether the text is clipped. -QDeclarativeTextPrivate::~QDeclarativeTextPrivate() -{ -} + Note that if the text does not fit in the bounding rectangle it will be abruptly chopped. + + If you want to display potentially long text in a limited space, you probably want to use \c elide instead. +*/ + +/*! + \qmlproperty bool Text::smooth + + This property holds whether the text is smoothly scaled or transformed. + + Smooth filtering gives better visual quality, but is slower. If + the item is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the item is stationary on + the screen. A common pattern when animating an item is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + +/*! + \qmlsignal Text::onLinkActivated(string link) + + This handler is called when the user clicks on a link embedded in the text. + The link must be in rich text or HTML format and the + \a link string provides access to the particular link. + + \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0 + + The example code will display the text + "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}." + + Clicking on the highlighted link will output + \tt{http://qt.nokia.com link activated} to the console. +*/ /*! \qmlproperty string Text::font.family @@ -320,7 +730,6 @@ QDeclarativeTextPrivate::~QDeclarativeTextPrivate() Text { text: "Hello"; font.capitalization: Font.AllLowercase } \endqml */ - QFont QDeclarativeText::font() const { Q_D(const QDeclarativeText); @@ -334,30 +743,9 @@ void QDeclarativeText::setFont(const QFont &font) return; d->font = font; - d->updateLayout(); - d->markImgDirty(); - emit fontChanged(d->font); -} - -void QDeclarativeText::setText(const QString &n) -{ - Q_D(QDeclarativeText); - if (d->text == n) - return; - d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n)); - if (d->richText) { - if (isComponentComplete()) { - d->ensureDoc(); - d->doc->setText(n); - } - } - - d->text = n; - d->updateLayout(); - d->markImgDirty(); - emit textChanged(d->text); + emit fontChanged(d->font); } /*! @@ -374,17 +762,25 @@ QString QDeclarativeText::text() const return d->text; } -void QDeclarativeText::setColor(const QColor &color) +void QDeclarativeText::setText(const QString &n) { Q_D(QDeclarativeText); - if (d->color == color) + if (d->text == n) return; - d->color = color; - d->markImgDirty(); - emit colorChanged(d->color); + d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n)); + if (d->richText && isComponentComplete()) { + d->ensureDoc(); + d->doc->setText(n); + } + + d->text = n; + d->updateLayout(); + + emit textChanged(d->text); } + /*! \qmlproperty color Text::color @@ -398,13 +794,23 @@ void QDeclarativeText::setColor(const QColor &color) Text { color: "steelblue"; ... } \endqml */ - QColor QDeclarativeText::color() const { Q_D(const QDeclarativeText); return d->color; } +void QDeclarativeText::setColor(const QColor &color) +{ + Q_D(QDeclarativeText); + if (d->color == color) + return; + + d->color = color; + d->invalidateImageCache(); + emit colorChanged(d->color); +} + /*! \qmlproperty enumeration Text::style @@ -445,21 +851,10 @@ void QDeclarativeText::setStyle(QDeclarativeText::TextStyle style) if (isComponentComplete() && (d->style == Normal || style == Normal)) prepareGeometryChange(); d->style = style; - d->markImgDirty(); + d->invalidateImageCache(); emit styleChanged(d->style); } -void QDeclarativeText::setStyleColor(const QColor &color) -{ - Q_D(QDeclarativeText); - if (d->styleColor == color) - return; - - d->styleColor = color; - d->markImgDirty(); - emit styleColorChanged(d->styleColor); -} - /*! \qmlproperty color Text::styleColor @@ -481,6 +876,18 @@ QColor QDeclarativeText::styleColor() const return d->styleColor; } +void QDeclarativeText::setStyleColor(const QColor &color) +{ + Q_D(QDeclarativeText); + if (d->styleColor == color) + return; + + d->styleColor = color; + d->invalidateImageCache(); + emit styleColorChanged(d->styleColor); +} + + /*! \qmlproperty enumeration Text::horizontalAlignment \qmlproperty enumeration Text::verticalAlignment @@ -511,7 +918,10 @@ void QDeclarativeText::setHAlign(HAlignment align) if (isComponentComplete()) prepareGeometryChange(); + d->hAlign = align; + d->updateLayout(); + emit horizontalAlignmentChanged(align); } @@ -559,9 +969,8 @@ void QDeclarativeText::setWrapMode(WrapMode mode) return; d->wrapMode = mode; - d->updateLayout(); - d->markImgDirty(); + emit wrapModeChanged(); } @@ -621,7 +1030,6 @@ Column { \o \image declarative-textformat.png \endtable */ - QDeclarativeText::TextFormat QDeclarativeText::textFormat() const { Q_D(const QDeclarativeText); @@ -637,19 +1045,13 @@ void QDeclarativeText::setTextFormat(TextFormat format) bool wasRich = d->richText; d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text)); - if (wasRich && !d->richText) { - //### delete control? (and vice-versa below) - d->updateLayout(); - d->markImgDirty(); - } else if (!wasRich && d->richText) { - if (isComponentComplete()) { - d->ensureDoc(); - d->doc->setText(d->text); - } - d->updateLayout(); - d->markImgDirty(); + if (!wasRich && d->richText && isComponentComplete()) { + d->ensureDoc(); + d->doc->setText(d->text); } + d->updateLayout(); + emit textFormatChanged(d->format); } @@ -688,12 +1090,12 @@ void QDeclarativeText::setElideMode(QDeclarativeText::TextElideMode mode) return; d->elideMode = mode; - d->updateLayout(); - d->markImgDirty(); + emit elideModeChanged(d->elideMode); } +/*! \internal */ QRectF QDeclarativeText::boundingRect() const { Q_D(const QDeclarativeText); @@ -704,7 +1106,7 @@ QRectF QDeclarativeText::boundingRect() const int x = 0; int y = 0; - QSize size = d->cachedLayoutSize; + QSize size = d->layedOutTextSize; if (d->style != Normal) size += QSize(2,2); @@ -737,117 +1139,23 @@ QRectF QDeclarativeText::boundingRect() const return QRectF(x,y,size.width(),size.height()); } -void QDeclarativeText::geometryChanged(const QRectF &newGeometry, - const QRectF &oldGeometry) +/*! \internal */ +void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QDeclarativeText); - if (!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width()) { - if (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone) { - //re-elide if needed - if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && - isComponentComplete() && widthValid()) { - - QFontMetrics fm(d->font); - QString tmp = fm.elidedText(d->text,(Qt::TextElideMode)d->elideMode,width()); // XXX still worth layout...? - d->layout.setText(tmp); - } + if (!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width() && + (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone)) { - d->imgDirty = true; + if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && widthValid()) { + // We need to re-elide + d->updateLayout(); + } else { + // We just need to re-layout d->updateSize(); } } - QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); -} - -void QDeclarativeTextPrivate::updateLayout() -{ - Q_Q(QDeclarativeText); - if (q->isComponentComplete()) { - //setup instance of QTextLayout for all cases other than richtext - if (!richText) { - layout.clearLayout(); - layout.setFont(font); - if (format != QDeclarativeText::StyledText) { - QString tmp = text; - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); - singleline = !tmp.contains(QChar::LineSeparator); - if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { - QFontMetrics fm(font); - tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...? - } - layout.setText(tmp); - } else { - singleline = false; - QDeclarativeStyledText::parse(text, layout); - } - } - updateSize(); - } else { - dirty = true; - } -} - - -void QDeclarativeTextPrivate::updateSize() -{ - Q_Q(QDeclarativeText); - if (q->isComponentComplete()) { - QFontMetrics fm(font); - if (text.isEmpty()) { - q->setImplicitHeight(fm.height()); - emit q->paintedSizeChanged(); - return; - } - - int dy = q->height(); - QSize size(0, 0); - - //setup instance of QTextLayout for all cases other than richtext - if (!richText) { - size = setupTextLayout(); - if (cachedLayoutSize != size) { - q->prepareGeometryChange(); - cachedLayoutSize = size; - } - dy -= size.height(); - } else { - singleline = false; // richtext can't elide or be optimized for single-line case - ensureDoc(); - doc->setDefaultFont(font); - QTextOption option((Qt::Alignment)int(hAlign | vAlign)); - option.setWrapMode(QTextOption::WrapMode(wrapMode)); - doc->setDefaultTextOption(option); - if (wrapMode != QDeclarativeText::NoWrap && q->widthValid()) - doc->setTextWidth(q->width()); - else - doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) - dy -= (int)doc->size().height(); - QSize dsize = doc->size().toSize(); - if (dsize != cachedLayoutSize) { - q->prepareGeometryChange(); - cachedLayoutSize = dsize; - } - size = QSize(int(doc->idealWidth()),dsize.height()); - } - int yoff = 0; - if (q->heightValid()) { - if (vAlign == QDeclarativeText::AlignBottom) - yoff = dy; - else if (vAlign == QDeclarativeText::AlignVCenter) - yoff = dy/2; - } - q->setBaselineOffset(fm.ascent() + yoff); - - //### need to comfirm cost of always setting these for richText - internalWidthUpdate = true; - q->setImplicitWidth(size.width()); - internalWidthUpdate = false; - q->setImplicitHeight(size.height()); - emit q->paintedSizeChanged(); - } else { - dirty = true; - } + QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); } /*! @@ -872,228 +1180,6 @@ qreal QDeclarativeText::paintedHeight() const return implicitHeight(); } - - -// ### text layout handling should be profiled and optimized as needed -// what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine); - -void QDeclarativeTextPrivate::drawOutline() -{ - QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2); - img.fill(Qt::transparent); - - QPainter ppm(&img); - - QPoint pos(imgCache.rect().topLeft()); - pos += QPoint(-1, 0); - ppm.drawPixmap(pos, imgStyleCache); - pos += QPoint(2, 0); - ppm.drawPixmap(pos, imgStyleCache); - pos += QPoint(-1, -1); - ppm.drawPixmap(pos, imgStyleCache); - pos += QPoint(0, 2); - ppm.drawPixmap(pos, imgStyleCache); - - pos += QPoint(0, -1); - ppm.drawPixmap(pos, imgCache); - ppm.end(); - - imgCache = img; -} - -void QDeclarativeTextPrivate::drawOutline(int yOffset) -{ - QPixmap img = QPixmap(imgStyleCache.width()+2,imgStyleCache.height()+2); - img.fill(Qt::transparent); - - QPainter ppm(&img); - - QPoint pos(imgCache.rect().topLeft()); - pos += QPoint(0, yOffset); - ppm.drawPixmap(pos, imgStyleCache); - - pos += QPoint(0, -yOffset); - ppm.drawPixmap(pos, imgCache); - ppm.end(); - - imgCache = img; -} - -QSize QDeclarativeTextPrivate::setupTextLayout() -{ - Q_Q(QDeclarativeText); - layout.setCacheEnabled(true); - - int height = 0; - qreal widthUsed = 0; - qreal lineWidth = 0; - - //set manual width - if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) - lineWidth = q->width(); - - QTextOption textOption = layout.textOption(); - textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); - layout.setTextOption(textOption); - - layout.beginLayout(); - - while (1) { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - - if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) - line.setLineWidth(lineWidth); - } - layout.endLayout(); - - int x = 0; - for (int i = 0; i < layout.lineCount(); ++i) { - QTextLine line = layout.lineAt(i); - widthUsed = qMax(widthUsed, line.naturalTextWidth()); - line.setPosition(QPointF(0, height)); - height += int(line.height()); - - if (!cache) { - if (hAlign == QDeclarativeText::AlignLeft) { - x = 0; - } else if (hAlign == QDeclarativeText::AlignRight) { - x = q->width() - (int)line.naturalTextWidth(); - } else if (hAlign == QDeclarativeText::AlignHCenter) { - x = (q->width() - (int)line.naturalTextWidth()) / 2; - } - line.setPosition(QPoint(x, (int)line.y())); - } - } - - return QSize(qCeil(widthUsed), height); -} - -QPixmap QDeclarativeTextPrivate::wrappedTextImage(bool drawStyle) -{ - //do layout - QSize size = cachedLayoutSize; - - int x = 0; - for (int i = 0; i < layout.lineCount(); ++i) { - QTextLine line = layout.lineAt(i); - if (hAlign == QDeclarativeText::AlignLeft) { - x = 0; - } else if (hAlign == QDeclarativeText::AlignRight) { - x = size.width() - (int)line.naturalTextWidth(); - } else if (hAlign == QDeclarativeText::AlignHCenter) { - x = (size.width() - (int)line.naturalTextWidth()) / 2; - } - line.setPosition(QPoint(x, (int)line.y())); - } - - //paint text - QPixmap img(size); - if (!size.isEmpty()) { - img.fill(Qt::transparent); -#ifdef Q_WS_MAC - bool oldSmooth = qt_applefontsmoothing_enabled; - qt_applefontsmoothing_enabled = false; -#endif - QPainter p(&img); -#ifdef Q_WS_MAC - qt_applefontsmoothing_enabled = oldSmooth; -#endif - drawWrappedText(&p, QPointF(0,0), drawStyle); - } - return img; -} - -void QDeclarativeTextPrivate::drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle) -{ - if (drawStyle) - p->setPen(styleColor); - else - p->setPen(color); - p->setFont(font); - layout.draw(p , pos); -} - -QPixmap QDeclarativeTextPrivate::richTextImage(bool drawStyle) -{ - QSize size = doc->size().toSize(); - - //paint text - QPixmap img(size); - img.fill(Qt::transparent); -#ifdef Q_WS_MAC - bool oldSmooth = qt_applefontsmoothing_enabled; - qt_applefontsmoothing_enabled = false; -#endif - QPainter p(&img); -#ifdef Q_WS_MAC - qt_applefontsmoothing_enabled = oldSmooth; -#endif - - QAbstractTextDocumentLayout::PaintContext context; - - QTextOption oldOption(doc->defaultTextOption()); - if (drawStyle) { - context.palette.setColor(QPalette::Text, styleColor); - QTextOption colorOption(doc->defaultTextOption()); - colorOption.setFlags(QTextOption::SuppressColors); - doc->setDefaultTextOption(colorOption); - } else { - context.palette.setColor(QPalette::Text, color); - } - doc->documentLayout()->draw(&p, context); - if (drawStyle) - doc->setDefaultTextOption(oldOption); - return img; -} - -void QDeclarativeTextPrivate::checkImgCache() -{ - if (!imgDirty) - return; - - bool empty = text.isEmpty(); - QPixmap newImgCache; - if (empty) { - imgStyleCache = QPixmap(); - } else if (richText) { - newImgCache = richTextImage(false); - if (style != QDeclarativeText::Normal) - imgStyleCache = richTextImage(true); //### should use styleColor - } else { - newImgCache = wrappedTextImage(false); - if (style != QDeclarativeText::Normal) - imgStyleCache = wrappedTextImage(true); //### should use styleColor - } - imgCache = newImgCache; - if (!empty) - switch (style) { - case QDeclarativeText::Outline: - drawOutline(); - break; - case QDeclarativeText::Sunken: - drawOutline(-1); - break; - case QDeclarativeText::Raised: - drawOutline(1); - break; - default: - break; - } - - imgDirty = false; -} - -void QDeclarativeTextPrivate::ensureDoc() -{ - if (!doc) { - Q_Q(QDeclarativeText); - doc = new QTextDocumentWithImageResources(q); - doc->setDocumentMargin(0); - } -} - /*! Returns the number of resources (images) that are being loaded asynchronously. */ @@ -1103,22 +1189,14 @@ int QDeclarativeText::resourcesLoading() const return d->doc ? d->doc->resourcesLoading() : 0; } -/*! - \qmlproperty bool Text::clip - This property holds whether the text is clipped. - - Note that if the text does not fit in the bounding rectangle it will be abruptly chopped. - - If you want to display potentially long text in a limited space, you probably want to use \c elide instead. -*/ - +/*! \internal */ void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QDeclarativeText); - if (d->cache || d->style != Normal) { - d->checkImgCache(); - if (d->imgCache.isNull()) + if (d->cacheAllTextAsImage || d->style != Normal) { + d->checkImageCache(); + if (d->imageCache.isNull()) return; bool oldAA = p->testRenderHint(QPainter::Antialiasing); @@ -1128,23 +1206,23 @@ void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid QRect br = boundingRect().toRect(); - bool needClip = clip() && (d->imgCache.width() > width() || - d->imgCache.height() > height()); + bool needClip = clip() && (d->imageCache.width() > width() || + d->imageCache.height() > height()); if (needClip) - p->drawPixmap(0, 0, width(), height(), d->imgCache, -br.x(), -br.y(), width(), height()); + p->drawPixmap(0, 0, width(), height(), d->imageCache, -br.x(), -br.y(), width(), height()); else - p->drawPixmap(br.x(), br.y(), d->imgCache); + p->drawPixmap(br.x(), br.y(), d->imageCache); if (d->smooth) { p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } } else { - qreal y = boundingRect().y(); + QRectF bounds = boundingRect(); - bool needClip = clip() && (d->cachedLayoutSize.width() > width() || - d->cachedLayoutSize.height() > height()); + bool needClip = clip() && (d->layedOutTextSize.width() > width() || + d->layedOutTextSize.height() > height()); if (needClip) { p->save(); @@ -1153,49 +1231,35 @@ void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid if (d->richText) { QAbstractTextDocumentLayout::PaintContext context; context.palette.setColor(QPalette::Text, d->color); - p->translate(0, y); + p->translate(bounds.x(), bounds.y()); d->doc->documentLayout()->draw(p, context); - p->translate(0, -y); + p->translate(-bounds.x(), -bounds.y()); } else { - d->drawWrappedText(p, QPointF(0,y), false); + d->drawTextLayout(p, QPointF(0, bounds.y()), false); } - if (needClip) + + if (needClip) { p->restore(); + } } } -/*! - \qmlproperty bool Text::smooth - - This property holds whether the text is smoothly scaled or transformed. - - Smooth filtering gives better visual quality, but is slower. If - the item is displayed at its natural size, this property has no visual or - performance effect. - - \note Generally scaling artifacts are only visible if the item is stationary on - the screen. A common pattern when animating an item is to disable smooth - filtering at the beginning of the animation and reenable it at the conclusion. -*/ - +/*! \internal */ void QDeclarativeText::componentComplete() { Q_D(QDeclarativeText); QDeclarativeItem::componentComplete(); - if (d->dirty) { + if (d->updateOnComponentComplete) { + d->updateOnComponentComplete = false; if (d->richText) { d->ensureDoc(); d->doc->setText(d->text); } d->updateLayout(); - d->dirty = false; } } -/*! - \overload - Handles the given mouse \a event. - */ +/*! \internal */ void QDeclarativeText::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeText); @@ -1214,26 +1278,7 @@ void QDeclarativeText::mousePressEvent(QGraphicsSceneMouseEvent *event) } -/*! - \qmlsignal Text::onLinkActivated(string link) - - This handler is called when the user clicks on a link embedded in the text. - The link must be in rich text or HTML format and the - \a link string provides access to the particular link. - - \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0 - - The example code will display the text - "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}." - - Clicking on the highlighted link will output - \tt{http://qt.nokia.com link activated} to the console. -*/ - -/*! - \overload - Handles the given mouse \a event. - */ +/*! \internal */ void QDeclarativeText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeText); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index db68558..e37f477 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -74,24 +74,8 @@ public: ~QDeclarativeTextPrivate(); - void ensureDoc(); void updateSize(); void updateLayout(); - void markImgDirty() { - Q_Q(QDeclarativeText); - imgDirty = true; - if (q->isComponentComplete()) - q->update(); - } - void checkImgCache(); - - void drawOutline(); - void drawOutline(int yOffset); - - QPixmap wrappedTextImage(bool drawStyle); - void drawWrappedText(QPainter *p, const QPointF &pos, bool drawStyle); - QPixmap richTextImage(bool drawStyle); - QSize setupTextLayout(); QString text; QFont font; @@ -99,23 +83,37 @@ public: QDeclarativeText::TextStyle style; QColor styleColor; QString activeLink; - QPixmap imgCache; - QPixmap imgStyleCache; QDeclarativeText::HAlignment hAlign; QDeclarativeText::VAlignment vAlign; QDeclarativeText::TextElideMode elideMode; - bool imgDirty:1; - bool dirty:1; + QDeclarativeText::TextFormat format; + QDeclarativeText::WrapMode wrapMode; + + void invalidateImageCache(); + void checkImageCache(); + QPixmap imageCache; + + bool imageCacheDirty:1; + bool updateOnComponentComplete:1; bool richText:1; bool singleline:1; - bool cache:1; + bool cacheAllTextAsImage:1; bool internalWidthUpdate:1; + + QSize layedOutTextSize; + + void ensureDoc(); + QPixmap textDocumentImage(bool drawStyle); QTextDocumentWithImageResources *doc; + + QSize setupTextLayout(); + QPixmap textLayoutImage(bool drawStyle); + void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle); QDeclarativeTextLayout layout; - QSize cachedLayoutSize; - QDeclarativeText::TextFormat format; - QDeclarativeText::WrapMode wrapMode; - + + static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource); + static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset); + static inline QDeclarativeTextPrivate *get(QDeclarativeText *t) { return t->d_func(); } diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 6f5608a..e05f4e4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -319,6 +319,7 @@ void QDeclarativeTextEdit::setTextFormat(TextFormat format) updateSize(); } d->format = format; + d->control->setAcceptRichText(d->format != PlainText); emit textFormatChanged(d->format); } diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 439f500..e569dd2 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -403,6 +403,8 @@ public: QDeclarativeListAccessor *m_listAccessor; QModelIndex m_root; + QList<QByteArray> watchedRoles; + QList<int> watchedRoleIds; }; class QDeclarativeVisualDataModelDataMetaObject : public QDeclarativeOpenMetaObject @@ -1170,10 +1172,25 @@ int QDeclarativeVisualDataModel::indexOf(QDeclarativeItem *item, QObject *) cons return -1; } +void QDeclarativeVisualDataModel::setWatchedRoles(QList<QByteArray> roles) +{ + Q_D(QDeclarativeVisualDataModel); + d->watchedRoles = roles; + d->watchedRoleIds.clear(); +} + void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count, const QList<int> &roles) { Q_D(QDeclarativeVisualDataModel); + bool changed = false; + if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) { + foreach (QByteArray r, d->watchedRoles) { + if (d->m_roleNames.contains(r)) + d->watchedRoleIds << d->m_roleNames.value(r); + } + } + for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin(); iter != d->m_cache.end(); ++iter) { const int idx = iter.key(); @@ -1183,6 +1200,8 @@ void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count, QDeclarativeVisualDataModelData *data = d->data(objRef.obj); for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) { int role = roles.at(roleIdx); + if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role)) + changed = true; int propId = data->propForRole(role); if (propId != -1) { if (data->hasValue(propId)) { @@ -1217,6 +1236,8 @@ void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count, } } } + if (changed) + emit itemsChanged(index, count); } void QDeclarativeVisualDataModel::_q_itemsInserted(int index, int count) diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h index f09d8dd..5e187c2 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h @@ -79,6 +79,7 @@ public: virtual bool completePending() const = 0; virtual void completeItem() = 0; virtual QString stringValue(int, const QString &) = 0; + virtual void setWatchedRoles(QList<QByteArray> roles) = 0; virtual int indexOf(QDeclarativeItem *item, QObject *objectContext) const = 0; @@ -87,6 +88,7 @@ Q_SIGNALS: void itemsInserted(int index, int count); void itemsRemoved(int index, int count); void itemsMoved(int from, int to, int count); + void itemsChanged(int index, int count); void modelReset(); void createdItem(int index, QDeclarativeItem *item); void destroyingItem(QDeclarativeItem *item); @@ -120,6 +122,7 @@ public: virtual bool completePending() const; virtual void completeItem(); virtual QString stringValue(int index, const QString &role); + virtual void setWatchedRoles(QList<QByteArray>) {} virtual int indexOf(QDeclarativeItem *item, QObject *objectContext) const; @@ -174,6 +177,7 @@ public: bool completePending() const; void completeItem(); virtual QString stringValue(int index, const QString &role); + virtual void setWatchedRoles(QList<QByteArray> roles); int indexOf(QDeclarativeItem *item, QObject *objectContext) const; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index dc28e22..74bc5bd 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1932,6 +1932,9 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property { obj->addValueProperty(prop); + if (prop->values.count() > 1) + COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign multiple values to a singular property") ); + for (int ii = 0; ii < prop->values.count(); ++ii) { Value *v = prop->values.at(ii); if (v->object) { @@ -2562,8 +2565,8 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, QStringList alias = astNodeToStringList(node); - if (alias.count() != 1 && alias.count() != 2) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>")); + if (alias.count() < 1 || alias.count() > 3) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>")); if (!compileState.ids.contains(alias.at(0))) COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); @@ -2575,11 +2578,14 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, int propIdx = -1; int flags = 0; bool writable = false; - if (alias.count() == 2) { + if (alias.count() == 2 || alias.count() == 3) { propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); - if (-1 == propIdx) + if (-1 == propIdx) { COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + } else if (propIdx > 0xFFFF) { + COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds")); + } QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); if (!aliasProperty.isScriptable()) @@ -2587,6 +2593,22 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, writable = aliasProperty.isWritable(); + if (alias.count() == 3) { + QDeclarativeValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()]; + if (!valueType) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + + propIdx |= ((unsigned int)aliasProperty.type()) << 24; + + int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData()); + if (valueTypeIndex == -1) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + Q_ASSERT(valueTypeIndex <= 0xFF); + + aliasProperty = valueType->metaObject()->property(valueTypeIndex); + propIdx |= (valueTypeIndex << 16); + } + if (aliasProperty.isEnumType()) typeName = "int"; // Avoid introducing a dependency on the aliased metaobject else diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index b532b0c..cfef9cf 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -57,7 +57,6 @@ #include <QStack> #include <QStringList> -#include <QFileInfo> #include <QtCore/qdebug.h> #include <QApplication> diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index e916273..def4188 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -64,6 +64,7 @@ class QDeclarativeAbstractBinding; class QDeclarativeContext; class QDeclarativePropertyCache; class QDeclarativeContextData; +class QDeclarativeNotifier; // This class is structured in such a way, that simply zero'ing it is the // default state for elemental object allocations. This is crucial in the // workings of the QDeclarativeInstruction::CreateSimpleObject instruction. @@ -75,20 +76,23 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - attachedProperties(0), scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0) { + scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) { init(); } static inline void init() { QAbstractDeclarativeData::destroyed = destroyed; QAbstractDeclarativeData::parentChanged = parentChanged; + QAbstractDeclarativeData::objectNameChanged = objectNameChanged; } static void destroyed(QAbstractDeclarativeData *, QObject *); static void parentChanged(QAbstractDeclarativeData *, QObject *, QObject *); + static void objectNameChanged(QAbstractDeclarativeData *, QObject *); void destroyed(QObject *); void parentChanged(QObject *, QObject *); + void objectNameChanged(QObject *); void setImplicitDestructible() { if (!explicitIndestructibleSet) indestructible = false; @@ -123,8 +127,6 @@ public: QDeclarativeCompiledData *deferredComponent; // Can't this be found from the context? unsigned int deferredIdx; - QHash<int, QObject *> *attachedProperties; - // ### Can we make this QScriptValuePrivate so we incur no additional allocation // cost? QScriptValue *scriptValue; @@ -147,6 +149,18 @@ public: return 0; } } + + QDeclarativeNotifier *objectNameNotifier() const; + QHash<int, QObject *> *attachedProperties() const; + + struct ExtendedData { + ExtendedData(); + ~ExtendedData(); + + QHash<int, QObject *> attachedProperties; + void *objectNameNotifier; + }; + mutable ExtendedData *extendedData; }; template<class T> diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 584c5ec..c3fdf36 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -68,6 +68,7 @@ #include "private/qdeclarativelist_p.h" #include "private/qdeclarativetypenamecache_p.h" #include "private/qdeclarativeinclude_p.h" +#include "private/qdeclarativenotifier_p.h" #include <QtCore/qmetaobject.h> #include <QScriptClass> @@ -104,6 +105,7 @@ #ifdef Q_OS_WIN // for %APPDATA% #include <qt_windows.h> #include <qlibrary.h> +#include <windows.h> #define CSIDL_APPDATA 0x001a // <username>\Application Data #endif @@ -468,6 +470,11 @@ void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QO static_cast<QDeclarativeData *>(d)->parentChanged(o, p); } +void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o) +{ + static_cast<QDeclarativeData *>(d)->objectNameChanged(o); +} + void QDeclarativeEnginePrivate::init() { Q_Q(QDeclarativeEngine); @@ -949,7 +956,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre if (!data) return 0; // Attached properties are only on objects created by QML - QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0; + QObject *rv = data->extendedData?data->attachedProperties()->value(id):0; if (rv || !create) return rv; @@ -959,11 +966,8 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre rv = pf(const_cast<QObject *>(object)); - if (rv) { - if (!data->attachedProperties) - data->attachedProperties = new QHash<int, QObject *>(); - data->attachedProperties->insert(id, rv); - } + if (rv) + data->attachedProperties()->insert(id, rv); return rv; } @@ -984,8 +988,6 @@ void QDeclarativeData::destroyed(QObject *object) { if (deferredComponent) deferredComponent->release(); - if (attachedProperties) - delete attachedProperties; if (nextContextObject) nextContextObject->prevContextObject = prevContextObject; @@ -1019,6 +1021,9 @@ void QDeclarativeData::destroyed(QObject *object) if (scriptValue) delete scriptValue; + if (extendedData) + delete extendedData; + if (ownMemory) delete this; } @@ -1028,6 +1033,11 @@ void QDeclarativeData::parentChanged(QObject *, QObject *parent) if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; } } +void QDeclarativeData::objectNameChanged(QObject *) +{ + if (extendedData) objectNameNotifier()->notify(); +} + bool QDeclarativeData::hasBindingBit(int bit) const { if (bindingBitsSize > bit) @@ -1064,6 +1074,28 @@ void QDeclarativeData::setBindingBit(QObject *obj, int bit) bindingBits[bit / 32] |= (1 << (bit % 32)); } +QDeclarativeData::ExtendedData::ExtendedData() +: objectNameNotifier(0) +{ +} + +QDeclarativeData::ExtendedData::~ExtendedData() +{ + ((QDeclarativeNotifier *)&objectNameNotifier)->~QDeclarativeNotifier(); +} + +QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const +{ + if (!extendedData) extendedData = new ExtendedData; + return (QDeclarativeNotifier *)&extendedData->objectNameNotifier; +} + +QHash<int, QObject *> *QDeclarativeData::attachedProperties() const +{ + if (!extendedData) extendedData = new ExtendedData; + return &extendedData->attachedProperties; +} + /*! Creates a QScriptValue allowing you to use \a object in QML script. \a engine is the QDeclarativeEngine it is to be created in. @@ -2159,4 +2191,42 @@ const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const } } +bool QDeclarative_isFileCaseCorrect(const QString &fileName) +{ +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + QFileInfo info(fileName); + + QString absolute = info.absoluteFilePath(); + +#if defined(Q_OS_MAC) + QString canonical = info.canonicalFilePath(); +#elif defined(Q_OS_WIN32) + wchar_t buffer[1024]; + + DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + rv = ::GetLongPathName(buffer, buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + + QString canonical((QChar *)buffer); +#endif + + int absoluteLength = absolute.length(); + int canonicalLength = canonical.length(); + + int length = qMin(absoluteLength, canonicalLength); + for (int ii = 0; ii < length; ++ii) { + const QChar &a = absolute.at(absoluteLength - 1 - ii); + const QChar &c = canonical.at(canonicalLength - 1 - ii); + + if (a.toLower() != c.toLower()) + return true; + if (a != c) + return false; + } +#endif + + return true; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativefastproperties.cpp b/src/declarative/qml/qdeclarativefastproperties.cpp index eb69b6a..78e3afd 100644 --- a/src/declarative/qml/qdeclarativefastproperties.cpp +++ b/src/declarative/qml/qdeclarativefastproperties.cpp @@ -51,10 +51,19 @@ QT_BEGIN_NAMESPACE // primarily read from bindings is a candidate for inclusion as a fast // property. +static void QObject_objectName(QObject *object, void *output, QDeclarativeNotifierEndpoint *endpoint) +{ + if (endpoint) + endpoint->connect(QDeclarativeData::get(object, true)->objectNameNotifier()); + *((QString *)output) = object->objectName(); +} + QDeclarativeFastProperties::QDeclarativeFastProperties() { add(&QDeclarativeItem::staticMetaObject, QDeclarativeItem::staticMetaObject.indexOfProperty("parent"), QDeclarativeItemPrivate::parentProperty); + add(&QObject::staticMetaObject, QObject::staticMetaObject.indexOfProperty("objectName"), + QObject_objectName); } int QDeclarativeFastProperties::accessorIndexForProperty(const QMetaObject *metaObject, int propertyIndex) diff --git a/src/declarative/qml/qdeclarativeglobal_p.h b/src/declarative/qml/qdeclarativeglobal_p.h index 1041992..65d9b24 100644 --- a/src/declarative/qml/qdeclarativeglobal_p.h +++ b/src/declarative/qml/qdeclarativeglobal_p.h @@ -75,6 +75,19 @@ struct QDeclarativeGraphics_DerivedObject : public QObject }; /*! + Returns true if the case of \a fileName is equivalent to the file case of + \a fileName on disk, and false otherwise. + + This is used to ensure that the behavior of QML on a case-insensitive file + system is the same as on a case-sensitive file system. This function + performs a "best effort" attempt to determine the real case of the file. + It may have false positives (say the case is correct when it isn't), but it + should never have a false negative (say the case is incorrect when it is + correct). +*/ +bool QDeclarative_isFileCaseCorrect(const QString &fileName); + +/*! Makes the \a object a child of \a parent. Note that when using this method, neither \a parent nor the object's previous parent (if it had one) will receive ChildRemoved or ChildAdded events. diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index fe4ed48..6f5216a 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -351,7 +351,11 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath { QFile file(absoluteFilePath); QString filecontent; - if (file.open(QFile::ReadOnly)) { + if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { + if (errorString) + *errorString = QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath); + return false; + } else if (file.open(QFile::ReadOnly)) { filecontent = QString::fromUtf8(file.readAll()); if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: " @@ -913,6 +917,11 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt } if (!engineInitialized || !typesRegistered) { + if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { + if (errorString) + *errorString = tr("File name case mismatch for \"%2\"").arg(absoluteFilePath); + return false; + } QPluginLoader loader(absoluteFilePath); if (!loader.load()) { diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index ab6ff74..61a1f55 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -239,8 +239,13 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) } } else { if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) { - enginePriv->capturedProperties << - QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + if (lastData->coreIndex == 0) { + enginePriv->capturedProperties << + QDeclarativeEnginePrivate::CapturedProperty(QDeclarativeData::get(obj, true)->objectNameNotifier()); + } else { + enginePriv->capturedProperties << + QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + } } if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) { diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 061f309..c8e1a07 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -44,6 +44,7 @@ #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativecompiler_p.h> #include <private/qdeclarativecomponent_p.h> +#include <private/qdeclarativeglobal_p.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <QtCore/qdebug.h> @@ -493,6 +494,13 @@ void QDeclarativeDataLoader::load(QDeclarativeDataBlob *blob) QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(blob->m_url); if (!lf.isEmpty()) { + if (!QDeclarative_isFileCaseCorrect(lf)) { + QDeclarativeError error; + error.setUrl(blob->m_url); + error.setDescription(QLatin1String("File name case mismatch")); + blob->setError(error); + return; + } QFile file(lf); if (file.open(QFile::ReadOnly)) { QByteArray data = file.readAll(); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 37f08fc..e28062b 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -459,7 +459,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) id -= propOffset; if (id < metaData->propertyCount) { - int t = (metaData->propertyData() + id)->propertyType; + int t = (metaData->propertyData() + id)->propertyType; bool needActivate = false; if (t == -1) { @@ -586,11 +586,26 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) connectAlias(id); - if (d->propertyIdx == -1) { + if (d->isObjectAlias()) { *reinterpret_cast<QObject **>(a[0]) = target; return -1; + } else if (d->isValueTypeAlias()) { + // Value type property + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); + + QDeclarativeValueType *valueType = ep->valueTypes[d->valueType()]; + Q_ASSERT(valueType); + + valueType->read(target, d->propertyIndex()); + int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a); + + if (c == QMetaObject::WriteProperty) + valueType->write(target, d->propertyIndex(), 0x00); + + return rv; + } else { - return QMetaObject::metacall(target, c, d->propertyIdx, a); + return QMetaObject::metacall(target, c, d->propertyIndex(), a); } } @@ -823,8 +838,8 @@ void QDeclarativeVMEMetaObject::connectAlias(int aliasId) int sigIdx = methodOffset + aliasId + metaData->propertyCount; QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); - if (d->propertyIdx != -1) { - QMetaProperty prop = target->metaObject()->property(d->propertyIdx); + if (!d->isObjectAlias()) { + QMetaProperty prop = target->metaObject()->property(d->propertyIndex()); if (prop.hasNotifySignal()) QDeclarativePropertyPrivate::connect(target, prop.notifySignalIndex(), object, sigIdx); } diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index 4ccaa73..5134763 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -84,6 +84,25 @@ struct QDeclarativeVMEMetaData int contextIdx; int propertyIdx; int flags; + + bool isObjectAlias() const { + return propertyIdx == -1; + } + bool isPropertyAlias() const { + return !isObjectAlias() && !(propertyIdx & 0xFF000000); + } + bool isValueTypeAlias() const { + return !isObjectAlias() && (propertyIdx & 0xFF000000); + } + int propertyIndex() const { + return propertyIdx & 0x0000FFFF; + } + int valueTypeIndex() const { + return (propertyIdx & 0x00FF0000) >> 16; + } + int valueType() const { + return ((unsigned int)propertyIdx) >> 24; + } }; struct PropertyData { diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index 3e4a81a..d2f65ef 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -49,7 +49,6 @@ #include <QDebug> #include <QNetworkRequest> #include <QNetworkReply> -#include <QFile> #include <QFontDatabase> #include <private/qobject_p.h> diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 6804d4a..852b055 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -208,7 +208,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) const QList<Change> &changes = s->data.changes; if (m_copy) { - bool cc = m_copy->count() != s->list->count(); + bool cc = m_orig->count() != s->list->count(); FlatListModel *orig = m_orig->m_flat; FlatListModel *copy = s->list->m_flat; diff --git a/src/gui/dialogs/qinputdialog.cpp b/src/gui/dialogs/qinputdialog.cpp index e996ee9..700b234 100644 --- a/src/gui/dialogs/qinputdialog.cpp +++ b/src/gui/dialogs/qinputdialog.cpp @@ -244,6 +244,9 @@ void QInputDialogPrivate::ensureLineEdit() Q_Q(QInputDialog); if (!lineEdit) { lineEdit = new QLineEdit(q); +#ifndef QT_NO_IM + qt_widget_private(lineEdit)->inheritsInputMethodHints = 1; +#endif lineEdit->hide(); QObject::connect(lineEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString))); @@ -255,6 +258,9 @@ void QInputDialogPrivate::ensureComboBox() Q_Q(QInputDialog); if (!comboBox) { comboBox = new QComboBox(q); +#ifndef QT_NO_IM + qt_widget_private(comboBox)->inheritsInputMethodHints = 1; +#endif comboBox->hide(); QObject::connect(comboBox, SIGNAL(editTextChanged(QString)), q, SLOT(_q_textChanged(QString))); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fc44a44..e63acac 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2125,7 +2125,7 @@ void QGraphicsItem::setToolTip(const QString &toolTip) \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 2 - If no cursor has been set, the parent's cursor is used. + If no cursor has been set, the cursor of the item beneath is used. \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor, QApplication::overrideCursor() @@ -2365,7 +2365,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible()) fsi = fsi->d_ptr->focusScopeItem; fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, - /* focusFromShow = */ true); + /* focusFromHide = */ false); } break; } @@ -2375,6 +2375,10 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo QGraphicsItem *fi = subFocusItem; if (fi && fi != scene->focusItem()) { scene->setFocusItem(fi); + } else if (flags & QGraphicsItem::ItemIsFocusScope && + !scene->focusItem() && + q->isAncestorOf(scene->d_func()->lastFocusItem)) { + q_ptr->setFocus(); } } } else { @@ -2385,7 +2389,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (p->flags() & QGraphicsItem::ItemIsFocusScope) { if (p->d_ptr->visible) { p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, - /* focusFromShow = */ true); + /* focusFromHide = */ true); } break; } @@ -3245,13 +3249,13 @@ bool QGraphicsItem::hasFocus() const */ void QGraphicsItem::setFocus(Qt::FocusReason focusReason) { - d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false); + d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false); } /*! \internal */ -void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow) +void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide) { // Disabled / unfocusable items cannot accept focus. if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable)) @@ -3272,7 +3276,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim if (p->flags() & QGraphicsItem::ItemIsFocusScope) { QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem; p->d_ptr->focusScopeItem = q_ptr; - if (!p->focusItem() && !focusFromShow) { + if (!p->focusItem() && !focusFromHide) { if (oldFocusScopeItem) oldFocusScopeItem->d_ptr->focusScopeItemChange(false); focusScopeItemChange(true); @@ -3334,7 +3338,7 @@ void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent) while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false, - /* focusFromShow = */ false); + /* focusFromHide = */ false); return; } p = p->d_ptr->parent; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c8a7699..8480c19 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -477,7 +477,7 @@ public: inline void markParentDirty(bool updateBoundingRect = false); - void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow); + void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide); void clearFocusHelper(bool giveFocusToParent); void setSubFocus(QGraphicsItem *rootItem = 0); void clearSubFocus(QGraphicsItem *rootItem = 0); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e58b93c..a0015dc 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4362,6 +4362,50 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion & } } +// Copied from qpaintengine_vg.cpp +// Returns true for 90, 180, and 270 degree rotations. +static inline bool transformIsSimple(const QTransform& transform) +{ + QTransform::TransformationType type = transform.type(); + if (type == QTransform::TxNone || type == QTransform::TxTranslate) { + return true; + } else if (type == QTransform::TxScale) { + // Check for 0 and 180 degree rotations. + // (0 might happen after 4 rotations of 90 degrees). + qreal m11 = transform.m11(); + qreal m12 = transform.m12(); + qreal m21 = transform.m21(); + qreal m22 = transform.m22(); + if (m12 == 0.0f && m21 == 0.0f) { + if (m11 == 1.0f && m22 == 1.0f) + return true; // 0 degrees + else if (m11 == -1.0f && m22 == -1.0f) + return true; // 180 degrees. + if(m11 == 1.0f && m22 == -1.0f) + return true; // 0 degrees inverted y. + else if(m11 == -1.0f && m22 == 1.0f) + return true; // 180 degrees inverted y. + } + } else if (type == QTransform::TxRotate) { + // Check for 90, and 270 degree rotations. + qreal m11 = transform.m11(); + qreal m12 = transform.m12(); + qreal m21 = transform.m21(); + qreal m22 = transform.m22(); + if (m11 == 0.0f && m22 == 0.0f) { + if (m12 == 1.0f && m21 == -1.0f) + return true; // 90 degrees. + else if (m12 == -1.0f && m21 == 1.0f) + return true; // 270 degrees. + else if (m12 == -1.0f && m21 == -1.0f) + return true; // 90 degrees inverted y. + else if (m12 == 1.0f && m21 == 1.0f) + return true; // 270 degrees inverted y. + } + } + return false; +} + /*! \internal @@ -4530,32 +4574,28 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte if (invertable) diff *= painter->worldTransform(); deviceData->lastTransform = painter->worldTransform(); - if (!invertable - || diff.type() > QTransform::TxTranslate - || painter->worldTransform().type() > QTransform::TxScale) { + bool allowPartialCacheExposure = false; + bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate + && transformIsSimple(painter->worldTransform()); + if (!simpleTransform) { pixModified = true; itemCache->allExposed = true; itemCache->exposed.clear(); + deviceData->cacheIndent = QPoint(); pix = QPixmap(); + } else { + allowPartialCacheExposure = deviceData->cacheIndent != QPoint(); } - // ### This is a pretty bad way to determine when to start partial - // exposure for DeviceCoordinateCache but it's the least intrusive - // approach for now. -#if 0 - // Only if the device rect isn't fully contained. - bool allowPartialCacheExposure = !viewRect.contains(deviceRect); -#else - // Only if deviceRect is 20% taller or wider than the desktop. - bool allowPartialCacheExposure = false; - if (widget) { - QRect desktopRect = QApplication::desktop()->availableGeometry(widget); - allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() - || desktopRect.height() * 1.2 < deviceRect.height()); + // Allow partial cache exposure if the device rect isn't fully contained and + // deviceRect is 20% taller or wider than the viewRect. + if (!allowPartialCacheExposure && !viewRect.contains(deviceRect)) { + allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width()) + || (viewRect.height() * 1.2 < deviceRect.height()); } -#endif + QRegion scrollExposure; - if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) { + if (allowPartialCacheExposure) { // Part of pixmap is drawn. Either device contains viewrect (big // item covers whole screen) or parts of device are outside the // viewport. In either case the device rect must be the intersect diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 1bfe266..4a733be 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -750,6 +750,22 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c /*! \property QGraphicsWidget::layout \brief The layout of the widget + + Any existing layout manager is deleted before the new layout is assigned. If + \a layout is 0, the widget is left without a layout. Existing subwidgets' + geometries will remain unaffected. + + QGraphicsWidget takes ownership of \a layout. + + All widgets that are currently managed by \a layout or all of its + sublayouts, are automatically reparented to this item. The layout is then + invalidated, and the child widget geometries are adjusted according to + this item's geometry() and contentsMargins(). Children who are not + explicitly managed by \a layout remain unaffected by the layout after + it has been assigned to this widget. + + If no layout is currently managing this widget, layout() will return 0. + */ /*! diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ac148ee..1157b93 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -6607,6 +6607,10 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla if (format == newFormat) return true; + // No in-place conversion if we have to detach + if (ref > 1) + return false; + const InPlace_Image_Converter *const converterPtr = &inplace_converter_map[format][newFormat]; InPlace_Image_Converter converter = *converterPtr; if (converter) diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 47249d9..b7c8acb 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -968,11 +968,12 @@ void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) if (needsCopy) { TSize size = sourceBitmap->SizeInPixels(); + int bytesPerLine = sourceBitmap->ScanLineLength(size.iWidth, displayMode); QSymbianBitmapDataAccess da; da.beginDataAccess(sourceBitmap); uchar *bytes = (uchar*)sourceBitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, format); + QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); img = img.copy(); da.endDataAccess(sourceBitmap); diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h index 821fb69..f171281 100644 --- a/src/gui/image/qpixmap_x11_p.h +++ b/src/gui/image/qpixmap_x11_p.h @@ -115,6 +115,7 @@ private: friend class QEglContext; // Needs gl_surface friend class QGLContext; // Needs gl_surface friend class QX11GLPixmapData; // Needs gl_surface + friend class QMeeGoGraphicsSystem; // Needs gl_surface and flags friend bool qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs gl_surface void release(); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 296f24f..5ff2fd4 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1237,10 +1237,11 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. - const bool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); + QWidget *const window = qwidget->window(); + const bool visible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); const bool statusPaneVisibility = visible; - const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; - const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; + const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; + const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint)); S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); #endif diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 7fd2baa..93f64f6 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -142,6 +142,7 @@ public: int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type + static CEikButtonGroupContainer *cba; enum ScanCodeState { Unpressed, @@ -162,6 +163,7 @@ public: static inline CAknTitlePane* titlePane(); static inline CAknContextPane* contextPane(); static inline CEikButtonGroupContainer* buttonGroupContainer(); + static inline void setButtonGroupContainer(CEikButtonGroupContainer* newCba); static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); #endif static void controlVisibilityChanged(CCoeControl *control, bool visible); @@ -383,7 +385,12 @@ inline CAknContextPane* QS60Data::contextPane() inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer() { - return CEikonEnv::Static()->AppUiFactory()->Cba(); + return QS60Data::cba; +} + +inline void QS60Data::setButtonGroupContainer(CEikButtonGroupContainer *newCba) +{ + QS60Data::cba = newCba; } #endif // Q_WS_S60 diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 2f85cd0..f7c795e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -273,6 +273,9 @@ QWidgetPrivate::QWidgetPrivate(int version) , isMoved(0) , isGLWidget(0) , usesDoubleBufferedGLContext(0) +#ifndef QT_NO_IM + , inheritsInputMethodHints(0) +#endif #if defined(Q_WS_X11) , picture(0) #elif defined(Q_WS_WIN) @@ -9228,9 +9231,13 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const */ Qt::InputMethodHints QWidget::inputMethodHints() const { - Q_D(const QWidget); #ifndef QT_NO_IM - return d->imHints; + const QWidgetPrivate *priv = d_func(); + while (priv->inheritsInputMethodHints) { + priv = priv->q_func()->parentWidget()->d_func(); + Q_ASSERT(priv); + } + return priv->imHints; #else //QT_NO_IM return 0; #endif //QT_NO_IM diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 4a79dc7..6c89659 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -748,6 +748,9 @@ public: uint isMoved : 1; uint isGLWidget : 1; uint usesDoubleBufferedGLContext : 1; +#ifndef QT_NO_IM + uint inheritsInputMethodHints : 1; +#endif // *************************** Platform specific ************************************ #if defined(Q_WS_X11) // <----------------------------------------------------------- X11 diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 4109ed8..9a451ce 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -69,6 +69,7 @@ extern bool qt_nograb(); QWidget *QWidgetPrivate::mouseGrabber = 0; QWidget *QWidgetPrivate::keyboardGrabber = 0; +CEikButtonGroupContainer *QS60Data::cba = 0; static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) { @@ -494,9 +495,27 @@ void QWidgetPrivate::show_sys() // Create the status pane and CBA here CEikAppUi *ui = static_cast<CEikAppUi *>(S60->appUi()); MEikAppUiFactory *factory = CEikonEnv::Static()->AppUiFactory(); - TRAP_IGNORE(factory->ReadAppInfoResourceL(0, ui)); - if (S60->buttonGroupContainer()) - S60->buttonGroupContainer()->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + + QT_TRAP_THROWING( + factory->CreateResourceIndependentFurnitureL(ui); + + TRect boundingRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + + CEikButtonGroupContainer *cba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba, + CEikButtonGroupContainer::EHorizontal,ui,R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + + CEikButtonGroupContainer *oldCba = CEikonEnv::Static()->AppUiFactory()->SwapButtonGroup(cba); + Q_ASSERT(!oldCba); + S60->setButtonGroupContainer(cba); + + CEikMenuBar *menuBar = new(ELeave) CEikMenuBar; + menuBar->ConstructL(ui, 0, R_AVKON_MENUPANE_EMPTY); + menuBar->SetMenuType(CEikMenuBar::EMenuOptions); + S60->appUi()->AddToStackL(menuBar,ECoeStackPriorityMenu,ECoeStackFlagRefusesFocus); + + CEikMenuBar *oldMenu = CEikonEnv::Static()->AppUiFactory()->SwapMenuBar(menuBar); + Q_ASSERT(!oldMenu); + ) if (S60->statusPane()) { // Use QDesktopWidget as the status pane observer to proxy for the AppUi. @@ -1233,7 +1252,8 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) // At this point the backing store should already be destroyed // so we flush the command buffer to ensure that the freeing of // those resources and deleting the window can happen "atomically" - S60->wsSession().Flush(); + if (qApp) + S60->wsSession().Flush(); } } diff --git a/src/gui/painting/qcups_p.h b/src/gui/painting/qcups_p.h index 9259679..239c244 100644 --- a/src/gui/painting/qcups_p.h +++ b/src/gui/painting/qcups_p.h @@ -59,6 +59,7 @@ #ifndef QT_NO_CUPS #include <QtCore/qlibrary.h> #include <cups/cups.h> +#include <cups/ppd.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 9749244..c92d291 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3164,10 +3164,8 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti) const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize); - const glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); - const int x = qFloor(positions[i].x + metrics.x + aliasDelta); - const int y = qFloor(positions[i].y + metrics.y + aliasDelta); - + const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta); + const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta); alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); } diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 8bac1f5..ea19fcd 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -101,9 +101,11 @@ QS60WindowSurface::~QS60WindowSurface() // Issue empty redraw to clear the UI surface QWidget *w = window(); - RWindow *const window = static_cast<RWindow *>(w->winId()->DrawableWindow()); - window->BeginRedraw(); - window->EndRedraw(); + if (w->testAttribute(Qt::WA_WState_Created)) { + RWindow *const window = static_cast<RWindow *>(w->winId()->DrawableWindow()); + window->BeginRedraw(); + window->EndRedraw(); + } } } #endif diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp index 5d4c54e..74432af 100644 --- a/src/gui/s60framework/qs60mainapplication.cpp +++ b/src/gui/s60framework/qs60mainapplication.cpp @@ -58,7 +58,6 @@ CApaApplication *newS60Application() return new QS60MainApplication; } -_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main" QT_LIBINFIX_UNICODE L".rsc"); /*! \class QS60MainApplication @@ -129,10 +128,6 @@ TUid QS60MainApplication::AppDllUid() const */ TFileName QS60MainApplication::ResourceFileName() const { - TFindFile finder(iCoeEnv->FsSession()); - TInt err = finder.FindByDir(KQtWrapperResourceFile, KNullDesC); - if (err == KErrNone) - return finder.File(); return KNullDesC(); } diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index ea9dbb3..92b3b55 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -50,16 +50,6 @@ #endif #include <barsread.h> #include <qconfig.h> -#ifdef Q_WS_S60 -# if defined(QT_LIBINFIX_UNQUOTED) -// Two level macro needed for proper expansion of libinfix -# define QT_S60MAIN_RSG_2(x) <s60main##x##.rsg> -# define QT_S60MAIN_RSG(x) QT_S60MAIN_RSG_2(x) -# include QT_S60MAIN_RSG(QT_LIBINFIX_UNQUOTED) -# else -# include <s60main.rsg> -# endif -#endif #include "qs60mainappui.h" #include <QtGui/qapplication.h> @@ -125,8 +115,8 @@ void QS60MainAppUi::ConstructL() #ifdef Q_WS_S60 flags |= CAknAppUi::EAknEnableSkin; // After 5th Edition S60, native side supports animated wallpapers. - // However, there is no support for that feature on Qt side, so indicate to - // native UI framework that this application will not support background animations. + // However, there is no support for that feature on Qt side, so indicate to + // native UI framework that this application will not support background animations. if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) flags |= KAknDisableAnimationBackground; #endif @@ -244,7 +234,7 @@ void QS60MainAppUi::DynInitMenuBarL(TInt /* resourceId */, CEikMenuBar * /* menu void QS60MainAppUi::DynInitMenuPaneL(TInt resourceId, CEikMenuPane *menuPane) { #ifdef Q_WS_S60 - if (resourceId == R_QT_WRAPPERAPP_MENU) { + if (resourceId == R_AVKON_MENUPANE_EMPTY) { if (menuPane->NumberOfItemsInPane() <= 1) QT_TRYCATCH_LEAVING(qt_symbian_show_toplevel(menuPane)); @@ -274,7 +264,17 @@ void QS60MainAppUi::RestoreMenuL(CCoeControl *menuWindow, TInt resourceId, TMenu DynInitMenuPaneL(resourceId, (CEikMenuPane*)menuWindow); else DynInitMenuBarL(resourceId, (CEikMenuBar*)menuWindow); - } else + } else if(resourceId == R_AVKON_MENUPANE_EMPTY) { + CEikMenuBarTitle *title = new(ELeave) CEikMenuBarTitle; + CleanupStack::PushL(title); + + title->iData.iMenuPaneResourceId = R_AVKON_MENUPANE_EMPTY; + title->iTitleFlags = 0; + + S60->menuBar()->TitleArray()->AddTitleL(title); + CleanupStack::Pop( title ); + } + else #endif { QS60MainAppUiBase::RestoreMenuL(menuWindow, resourceId, menuType); diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri index edbacc0..19525b7 100644 --- a/src/gui/s60framework/s60framework.pri +++ b/src/gui/s60framework/s60framework.pri @@ -1,21 +1,3 @@ -contains(QT_CONFIG, s60) { -# This block serves the minimalistic resource file for S60 3.1 platforms. -# Note there is no way to ifdef S60 version in mmp file, that is why the resource -# file is always compiled for WINSCW - - minimalAppResource31 = \ - "SOURCEPATH s60framework" \ - "START RESOURCE s60main.rss" \ - "TARGET s60main$${QT_LIBINFIX}" \ - "HEADER" \ - "TARGETPATH /resource/apps" \ - "END" - - MMP_RULES += minimalAppResource31 - - SYMBIAN_RESOURCES += s60framework/s60main.rss -} - SOURCES += s60framework/qs60mainapplication.cpp \ s60framework/qs60mainappui.cpp \ s60framework/qs60maindocument.cpp diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 5980f20..bf30e1c 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -41,6 +41,7 @@ #include "qfontengine_s60_p.h" #include "qtextengine_p.h" +#include "qendian.h" #include "qglobal.h" #include <private/qapplication_p.h> #include "qimage.h" @@ -176,6 +177,24 @@ CFont *QSymbianTypeFaceExtras::fontOwner() const return m_cFont; } +QFixed QSymbianTypeFaceExtras::unitsPerEm() const +{ + if (m_unitsPerEm.value() != 0) + return m_unitsPerEm; + const QByteArray head = getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); + const int unitsPerEmOffset = 18; + if (head.size() > unitsPerEmOffset + sizeof(quint16)) { + const uchar* tableData = reinterpret_cast<const uchar*>(head.constData()); + const uchar* unitsPerEm = tableData + unitsPerEmOffset; + m_unitsPerEm = qFromBigEndian<quint16>(unitsPerEm); + } else { + // Bitmap font? Corrupt font? + // We return -1 and let the QFontEngineS60 return the pixel size. + m_unitsPerEm = -1; + } + return m_unitsPerEm; +} + // duplicated from qfontengine_xyz.cpp static inline unsigned int getChar(const QChar *str, int &i, const int len) { @@ -248,6 +267,13 @@ QFontEngineS60::~QFontEngineS60() releaseFont(m_scaledFont); } +QFixed QFontEngineS60::emSquareSize() const +{ + const QFixed unitsPerEm = m_extras->unitsPerEm(); + return unitsPerEm.toInt() == -1 ? + QFixed::fromReal(m_originalFontSizeInPixels) : unitsPerEm; +} + bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const { if (*nglyphs < len) { @@ -277,10 +303,13 @@ bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const { Q_UNUSED(flags); + TOpenFontCharMetrics metrics; + const TUint8 *glyphBitmapBytes; + TSize glyphBitmapSize; for (int i = 0; i < glyphs->numGlyphs; i++) { - const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]); - glyphs->advances_x[i] = bbox.xoff; - glyphs->advances_y[i] = bbox.yoff; + getCharacterData(glyphs->glyphs[i], metrics, glyphBitmapBytes, glyphBitmapSize); + glyphs->advances_x[i] = metrics.HorizAdvance(); + glyphs->advances_y[i] = 0; } } @@ -308,6 +337,7 @@ void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, parseGlyphPathData(outlineChar, outlineEnd, *path, fontSizeInPixels, positions[count++].toPointF(), false); } while(KErrNone == iterator.Next() && count <= nglyphs); + iterator.Close(); #else // Q_SYMBIAN_HAS_GLYPHOUTLINE_API QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags); #endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API @@ -315,29 +345,17 @@ void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph) { + // Note: On some Symbian versions (apparently <= Symbian^1), this + // function will return gray values 0x00, 0x10 ... 0xe0, 0xf0 due + // to a bug. The glyphs are nowhere perfectly opaque. + // This has been fixed for Symbian^3. + TOpenFontCharMetrics metrics; const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8); result.setColorTable(grayPalette()); - - // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can. - // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly. - // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished - // for every time we want to blit this glyph in the raster paint engine. - // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values. - // Blitting is however, evidentially faster now. - const int bpl = result.bytesPerLine(); - for (int row = 0; row < result.height(); ++row) { - uchar *scanLine = result.scanLine(row); - for (int column = 0; column < bpl; ++column) { - if (*scanLine == 0xf0) - *scanLine = 0xff; - scanLine++; - } - } - return result; } @@ -359,13 +377,11 @@ glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); - TRect glyphBounds; - metrics.GetHorizBounds(glyphBounds); const glyph_metrics_t result( - glyphBounds.iTl.iX, - glyphBounds.iTl.iY, - glyphBounds.Width(), - glyphBounds.Height(), + metrics.HorizBearingX(), + -metrics.HorizBearingY(), + metrics.Width(), + metrics.Height(), metrics.HorizAdvance(), 0 ); diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index d05c23c..c65ce55 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -82,11 +82,13 @@ public: const uchar *cmap() const; CFont *fontOwner() const; bool isSymbolCMap() const; + QFixed unitsPerEm() const; private: CFont* m_cFont; mutable bool m_symbolCMap; mutable QByteArray m_cmapTable; + mutable QFixed m_unitsPerEm; #ifndef Q_SYMBIAN_HAS_FONTTABLE_API COpenFont *m_openFont; mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; @@ -99,6 +101,7 @@ public: QFontEngineS60(const QFontDef &fontDef, const QSymbianTypeFaceExtras *extras); ~QFontEngineS60(); + QFixed emSquareSize() const; bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 05de8f5..3bd6122 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1949,9 +1949,11 @@ void QTextEngine::justify(const QScriptLine &line) if (kashida_pos >= 0) { // qDebug("kashida position at %d in word", kashida_pos); set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si)); - minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); - maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); - ++nPoints; + if (justificationPoints[nPoints].kashidaWidth > 0) { + minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); + maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); + ++nPoints; + } } kashida_pos = -1; kashida_type = HB_Arabic_Normal; @@ -1975,9 +1977,11 @@ void QTextEngine::justify(const QScriptLine &line) } if (kashida_pos >= 0) { set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si)); - minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); - maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); - ++nPoints; + if (justificationPoints[nPoints].kashidaWidth > 0) { + minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); + maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); + ++nPoints; + } } } diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 9a5bac0..919c542 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -137,7 +137,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); glDeleteTextures(1, &oldTexture); return; } diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 9e74e04..7f25887 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -5264,8 +5264,6 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() glExtensions |= FragmentShader; if (extensions.match("GL_ARB_shader_objects")) glExtensions |= FragmentShader; - if (extensions.match("GL_ARB_ES2_compatibility")) - glExtensions |= ES2Compatibility; if (extensions.match("GL_ARB_texture_mirrored_repeat")) glExtensions |= MirroredRepeat; if (extensions.match("GL_EXT_framebuffer_object")) @@ -5286,7 +5284,6 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() glExtensions |= FramebufferObject; glExtensions |= GenerateMipmap; glExtensions |= FragmentShader; - glExtensions |= ES2Compatibility; #endif #if defined(QT_OPENGL_ES_1) if (extensions.match("GL_OES_framebuffer_object")) diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 623eeaf..387c8f7 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -284,8 +284,7 @@ public: DDSTextureCompression = 0x00008000, ETC1TextureCompression = 0x00010000, PVRTCTextureCompression = 0x00020000, - FragmentShader = 0x00040000, - ES2Compatibility = 0x00080000 + FragmentShader = 0x00040000 }; Q_DECLARE_FLAGS(Extensions, Extension) diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index bc1c009..74382b0 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -97,10 +97,6 @@ QT_BEGIN_NAMESPACE to just features that are present in GLSL/ES, and avoid standard variable names that only work on the desktop. - If the \c{GL_ARB_ES2_compatibility} extension is present, - then the above prefix is not added because the desktop OpenGL - implementation supports precision qualifiers. - \section1 Simple shader example \snippet doc/src/snippets/code/src_opengl_qglshaderprogram.cpp 1 @@ -398,10 +394,8 @@ bool QGLShader::compileSourceCode(const char *source) srclen.append(GLint(headerLen)); } #ifdef QGL_DEFINE_QUALIFIERS - if (!(QGLExtensions::glExtensions() & QGLExtensions::ES2Compatibility)) { - src.append(qualifierDefines); - srclen.append(GLint(sizeof(qualifierDefines) - 1)); - } + src.append(qualifierDefines); + srclen.append(GLint(sizeof(qualifierDefines) - 1)); #endif #ifdef QGL_REDEFINE_HIGHP if (d->shaderType == Fragment) { diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index f6d2435..ce9d11a 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -61,11 +61,6 @@ QT_BEGIN_NAMESPACE -// vgDrawGlyphs() only exists in OpenVG 1.1 and higher. -#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_DRAW_GLYPHS) -#define QVG_NO_DRAW_GLYPHS 1 -#endif - // vgRenderToMask() only exists in OpenVG 1.1 and higher. // Also, disable masking completely if we are using the scissor to clip. #if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_RENDER_TO_MASK) @@ -75,11 +70,11 @@ QT_BEGIN_NAMESPACE #define QVG_NO_RENDER_TO_MASK 1 #endif -#if !defined(QVG_NO_DRAW_GLYPHS) - // use the same rounding as in qrasterizer.cpp (6 bit fixed point) static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; +#if !defined(QVG_NO_DRAW_GLYPHS) + Q_DECL_IMPORT extern int qt_defaultDpiX(); Q_DECL_IMPORT extern int qt_defaultDpiY(); diff --git a/src/openvg/qvg_p.h b/src/openvg/qvg_p.h index 51abbee..94d1eae 100644 --- a/src/openvg/qvg_p.h +++ b/src/openvg/qvg_p.h @@ -55,6 +55,11 @@ // We mean it. // +// vgDrawGlyphs() only exists in OpenVG 1.1 and higher. +#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_DRAW_GLYPHS) +#define QVG_NO_DRAW_GLYPHS 1 +#endif + #include <QtGui/qimage.h> #if !defined(QT_NO_EGL) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index ef0160c..41b35fc 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -185,10 +185,11 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) QImage::Format format = qt_TDisplayMode2Format(displayMode); TSize size = bitmap->SizeInPixels(); + int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode); bitmap->BeginDataAccess(); uchar *bytes = (uchar*)bitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, format); + QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); img = img.copy(); bitmap->EndDataAccess(); @@ -228,7 +229,7 @@ void* QVGPixmapData::toNativeType(NativeType type) sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; - RSgImage *sgImage = q_check_ptr(new RSgImage()); + QScopedPointer<RSgImage> sgImage(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); @@ -239,7 +240,7 @@ void* QVGPixmapData::toNativeType(NativeType type) EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer)sgImage, + (EGLClientBuffer)sgImage.data(), (EGLint*)KEglImageAttribs); if (!eglImage || eglGetError() != EGL_SUCCESS) { sgImage->Close(); @@ -261,13 +262,14 @@ void* QVGPixmapData::toNativeType(NativeType type) if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); - sgImage = 0; + sgImage.reset(); } + // release stuff vgDestroyImage(dstVgImage); QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); - return reinterpret_cast<void*>(sgImage); + return reinterpret_cast<void*>(sgImage.take()); #endif } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index b32a873..8bcdcc7 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -56,10 +56,14 @@ #include <QtCore/qvarlengtharray.h> #include <QtGui/private/qfontengine_p.h> +#include <qvg_p.h> + QT_BEGIN_NAMESPACE class QVGPaintEnginePrivate; +#ifndef QVG_NO_DRAW_GLYPHS + class QVGFontGlyphCache { public: @@ -90,6 +94,8 @@ public: }; #endif +#endif + QT_END_NAMESPACE #endif // QVGFONTGLYPHCACHE_H diff --git a/src/plugins/graphicssystems/meego/qmeegoextensions.cpp b/src/plugins/graphicssystems/meego/qmeegoextensions.cpp index e7f6439..611c962 100644 --- a/src/plugins/graphicssystems/meego/qmeegoextensions.cpp +++ b/src/plugins/graphicssystems/meego/qmeegoextensions.cpp @@ -46,6 +46,7 @@ bool QMeeGoExtensions::initialized = false; bool QMeeGoExtensions::hasImageShared = false; bool QMeeGoExtensions::hasSurfaceScaling = false; +bool QMeeGoExtensions::hasLockSurface = false; /* Extension funcs */ @@ -53,11 +54,15 @@ typedef EGLBoolean (EGLAPIENTRY *eglQueryImageNOKFunc)(EGLDisplay, EGLImageKHR, typedef EGLNativeSharedImageTypeNOK (EGLAPIENTRY *eglCreateSharedImageNOKFunc)(EGLDisplay, EGLImageKHR, EGLint*); typedef EGLBoolean (EGLAPIENTRY *eglDestroySharedImageNOKFunc)(EGLDisplay, EGLNativeSharedImageTypeNOK); typedef EGLBoolean (EGLAPIENTRY *eglSetSurfaceScalingNOKFunc)(EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint); +typedef EGLBoolean (EGLAPIENTRY *eglLockSurfaceKHRFunc)(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRY *eglUnlockSurfaceKHRFunc)(EGLDisplay display, EGLSurface surface); static eglQueryImageNOKFunc _eglQueryImageNOK = 0; static eglCreateSharedImageNOKFunc _eglCreateSharedImageNOK = 0; static eglDestroySharedImageNOKFunc _eglDestroySharedImageNOK = 0; static eglSetSurfaceScalingNOKFunc _eglSetSurfaceScalingNOK = 0; +static eglLockSurfaceKHRFunc _eglLockSurfaceKHR = 0; +static eglUnlockSurfaceKHRFunc _eglUnlockSurfaceKHR = 0; /* Public */ @@ -101,6 +106,22 @@ bool QMeeGoExtensions::eglSetSurfaceScalingNOK(EGLDisplay dpy, EGLSurface surfac return _eglSetSurfaceScalingNOK(dpy, surface, x, y, width, height); } +bool QMeeGoExtensions::eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list) +{ + if (! hasLockSurface) + qFatal("EGL_KHR_lock_surface2 not found but trying to use capability!"); + + return _eglLockSurfaceKHR(display, surface, attrib_list); +} + +bool QMeeGoExtensions::eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface) +{ + if (! hasLockSurface) + qFatal("EGL_KHR_lock_surface2 not found but trying to use capability!"); + + return _eglUnlockSurfaceKHR(display, surface); +} + /* Private */ void QMeeGoExtensions::initialize() @@ -113,6 +134,8 @@ void QMeeGoExtensions::initialize() _eglQueryImageNOK = (eglQueryImageNOKFunc) eglGetProcAddress("eglQueryImageNOK"); _eglCreateSharedImageNOK = (eglCreateSharedImageNOKFunc) eglGetProcAddress("eglCreateSharedImageNOK"); _eglDestroySharedImageNOK = (eglDestroySharedImageNOKFunc) eglGetProcAddress("eglDestroySharedImageNOK"); + _eglLockSurfaceKHR = (eglLockSurfaceKHRFunc) eglGetProcAddress("eglLockSurfaceKHR"); + _eglUnlockSurfaceKHR = (eglUnlockSurfaceKHRFunc) eglGetProcAddress("eglUnlockSurfaceKHR"); Q_ASSERT(_eglQueryImageNOK && _eglCreateSharedImageNOK && _eglDestroySharedImageNOK); hasImageShared = true; @@ -125,5 +148,14 @@ void QMeeGoExtensions::initialize() Q_ASSERT(_eglSetSurfaceScalingNOK); hasSurfaceScaling = true; } + + if (QEgl::hasExtension("EGL_KHR_lock_surface2")) { + qDebug("MeegoGraphics: found EGL_KHR_lock_surface2"); + _eglLockSurfaceKHR = (eglLockSurfaceKHRFunc) eglGetProcAddress("eglLockSurfaceKHR"); + _eglUnlockSurfaceKHR = (eglUnlockSurfaceKHRFunc) eglGetProcAddress("eglUnlockSurfaceKHR"); + + Q_ASSERT(_eglLockSurfaceKHR && _eglUnlockSurfaceKHR); + hasLockSurface = true; + } } diff --git a/src/plugins/graphicssystems/meego/qmeegoextensions.h b/src/plugins/graphicssystems/meego/qmeegoextensions.h index ee20bd8..9e78caf 100644 --- a/src/plugins/graphicssystems/meego/qmeegoextensions.h +++ b/src/plugins/graphicssystems/meego/qmeegoextensions.h @@ -65,6 +65,18 @@ typedef void* EGLNativeSharedImageTypeNOK; #define EGL_FIXED_HEIGHT_NOK 0x30DC #endif +#ifndef EGL_BITMAP_POINTER_KHR +#define EGL_BITMAP_POINTER_KHR 0x30C6 +#define EGL_BITMAP_PITCH_KHR 0x30C7 +#endif + +#ifndef EGL_MAP_PRESERVE_PIXELS_KHR +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#endif + /* Class */ class QMeeGoExtensions @@ -76,6 +88,8 @@ public: static bool eglQueryImageNOK(EGLDisplay dpy, EGLImageKHR image, EGLint prop, EGLint *v); static bool eglDestroySharedImageNOK(EGLDisplay dpy, EGLNativeSharedImageTypeNOK img); static bool eglSetSurfaceScalingNOK(EGLDisplay dpy, EGLSurface surface, int x, int y, int width, int height); + static bool eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); + static bool eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface); private: static void initialize(); @@ -83,6 +97,7 @@ private: static bool initialized; static bool hasImageShared; static bool hasSurfaceScaling; + static bool hasLockSurface; }; #endif diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 2a64d49..f8b228c 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -51,6 +51,7 @@ #include <private/qimage_p.h> #include <private/qeglproperties_p.h> #include <private/qeglcontext_p.h> +#include <private/qpixmap_x11_p.h> #include "qmeegopixmapdata.h" #include "qmeegographicssystem.h" @@ -58,6 +59,8 @@ bool QMeeGoGraphicsSystem::surfaceWasCreated = false; +QHash <Qt::HANDLE, QPixmap*> QMeeGoGraphicsSystem::liveTexturePixmaps; + QMeeGoGraphicsSystem::QMeeGoGraphicsSystem() { qDebug("Using the meego graphics system"); @@ -170,6 +173,22 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handl } } +QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLImage(Qt::HANDLE handle) +{ + if (QMeeGoGraphicsSystem::meeGoRunning()) { + QMeeGoPixmapData *pmd = new QMeeGoPixmapData; + pmd->fromEGLImage(handle); + + // FIXME Ok. This is a bit BAD BAD BAD. We're abusing here the fact that we KNOW + // that this function is used for the live pixmap... + pmd->texture()->options &= ~QGLContext::InvertedYBindOption; + return QMeeGoGraphicsSystem::wrapPixmapData(pmd); + } else { + qFatal("Can't create from EGL image when not running meego graphics system!"); + return NULL; + } +} + void QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(QPixmap *pixmap) { QMeeGoPixmapData *pmd = (QMeeGoPixmapData *) pixmap->pixmapData(); @@ -188,6 +207,109 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataWithGLTexture(int w, int h) return QMeeGoGraphicsSystem::wrapPixmapData(pmd); } +Qt::HANDLE QMeeGoGraphicsSystem::createLiveTexture(int w, int h, QImage::Format format) +{ + // No need to wrap the QPixmapData here. This QPixmap(Data) is a + // internal implementation and we don't migrate it between + // graphics system switching. + + // We use a bit ugly way of enforcing a color format on the X pixmap -- we create + // a local QImage and fromImage from there. This is quite redundant (extra overhead of creating + // the useless image only to delete it) but shouldn't be too bad for now... you're not expected + // to call createLiveTexture too often anyways. Would be great if QX11PixmapData had a way to + // force the X format upon creation or resize. + + QImage image(w, h, format); + QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); + pmd->fromImage(image, Qt::NoOpaqueDetection); + QPixmap *p = new QPixmap(pmd); + + liveTexturePixmaps.insert(p->handle(), p); + return p->handle(); +} + +void QMeeGoGraphicsSystem::destroyLiveTexture(Qt::HANDLE h) +{ + if (liveTexturePixmaps.contains(h)) { + QPixmap *p = liveTexturePixmaps.value(h); + delete p; + liveTexturePixmaps.remove(h); + } else + qWarning("Trying to destroy live texture %ld which was not found!", h); +} + +bool QMeeGoGraphicsSystem::lockLiveTexture(Qt::HANDLE h) +{ + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to lock live texture %ld which was not found!", h); + return false; + } + + EGLint attribs[] = { + EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, + EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, + EGL_NONE + }; + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + return QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, attribs); +} + +bool QMeeGoGraphicsSystem::unlockLiveTexture(Qt::HANDLE h) +{ + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to lock live texture %ld which was not found!", h); + return false; + } + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface)) { + glFinish(); + return true; + } else { + return false; + } +} + +void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) +{ + // FIXME Only allow this on locked surfaces + if (! liveTexturePixmaps.contains(h)) { + qWarning("Trying to query live texture %ld which was not found!", h); + return; + } + + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) data); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) pitch); +} + +Qt::HANDLE QMeeGoGraphicsSystem::liveTextureToEGLImage(Qt::HANDLE h) +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLint attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE + }; + + EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer) h, attribs); + + if (eglImage == EGL_NO_IMAGE_KHR) + qWarning("eglCreateImageKHR failed!"); + + return (Qt::HANDLE) eglImage; +} + bool QMeeGoGraphicsSystem::meeGoRunning() { if (! QApplicationPrivate::instance()) { @@ -204,6 +326,52 @@ bool QMeeGoGraphicsSystem::meeGoRunning() return (name == "meego"); } +void QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(QPixmapData* pmd) +{ + Q_ASSERT(pmd->classId() == QPixmapData::X11Class); + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); + if (pixmapData->gl_surface) { + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = 0; + } +} + +EGLSurface QMeeGoGraphicsSystem::getSurfaceForLiveTexturePixmap(QPixmap *pixmap) +{ + // This code is a crative remix of the stuff that can be found in the + // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + bool hasAlpha = pixmapData->hasAlphaChannel(); + + if (pixmapData->gl_surface && + hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + return pixmapData->gl_surface; + + // Check to see if the surface is still valid + if (pixmapData->gl_surface && + hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { + // Surface is invalid! + QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(pixmapData); + } + + if (pixmapData->gl_surface == 0) { + EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, + QEgl::OpenGL, + hasAlpha ? QEgl::Translucent : QEgl::NoOptions); + + pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); + + if (hasAlpha) + pixmapData->flags = pixmapData->flags | QX11PixmapData::GlSurfaceCreatedWithAlpha; + + if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) + return NULL; + } + + return pixmapData->gl_surface; +} + /* C API */ int qt_meego_image_to_egl_shared_image(const QImage &image) @@ -216,6 +384,11 @@ QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const return QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(handle, softImage); } +QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle) +{ + return QMeeGoGraphicsSystem::pixmapDataFromEGLImage(handle); +} + QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h) { return QMeeGoGraphicsSystem::pixmapDataWithGLTexture(w, h); @@ -245,3 +418,33 @@ void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap) { QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(pixmap); } + +Qt::HANDLE qt_meego_live_texture_create(int w, int h, QImage::Format format) +{ + return QMeeGoGraphicsSystem::createLiveTexture(w, h, format); +} + +void qt_meego_live_texture_destroy(Qt::HANDLE h) +{ + QMeeGoGraphicsSystem::destroyLiveTexture(h); +} + +bool qt_meego_live_texture_lock(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::lockLiveTexture(h); +} + +bool qt_meego_live_texture_unlock(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::unlockLiveTexture(h); +} + +void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch) +{ + return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch); +} + +Qt::HANDLE qt_meego_live_texture_to_egl_image(Qt::HANDLE h) +{ + return QMeeGoGraphicsSystem::liveTextureToEGLImage(h); +} diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 905f0c3..934d32d 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -43,6 +43,9 @@ #define MGRAPHICSSYSTEM_H #include <private/qgraphicssystem_p.h> +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> class QMeeGoGraphicsSystem : public QGraphicsSystem { @@ -60,13 +63,24 @@ public: static void setTranslucent(bool translucent); static QPixmapData *pixmapDataFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); + static QPixmapData *pixmapDataFromEGLImage(Qt::HANDLE handle); static QPixmapData *pixmapDataWithGLTexture(int w, int h); static void updateEGLSharedImagePixmap(QPixmap *pixmap); + static Qt::HANDLE createLiveTexture(int w, int h, QImage::Format format); + static void destroyLiveTexture(Qt::HANDLE h); + static bool lockLiveTexture(Qt::HANDLE h); + static bool unlockLiveTexture(Qt::HANDLE h); + static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); + static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE h); + private: static bool meeGoRunning(); + static EGLSurface getSurfaceForLiveTexturePixmap(QPixmap *pixmap); + static void destroySurfaceForLiveTexturePixmap(QPixmapData* pmd); static bool surfaceWasCreated; + static QHash <Qt::HANDLE, QPixmap*> liveTexturePixmaps; }; /* C api */ @@ -74,12 +88,19 @@ private: extern "C" { Q_DECL_EXPORT int qt_meego_image_to_egl_shared_image(const QImage &image); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const QImage &softImage); + Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h); Q_DECL_EXPORT void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap); Q_DECL_EXPORT bool qt_meego_destroy_egl_shared_image(Qt::HANDLE handle); Q_DECL_EXPORT void qt_meego_set_surface_fixed_size(int width, int height); Q_DECL_EXPORT void qt_meego_set_surface_scaling(int x, int y, int width, int height); Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); + Q_DECL_EXPORT Qt::HANDLE m_live_texture_create(int w, int h, QImage::Format format); + Q_DECL_EXPORT void m_live_texture_destroy(Qt::HANDLE h); + Q_DECL_EXPORT bool m_live_texture_lock(Qt::HANDLE h); + Q_DECL_EXPORT bool m_live_texture_unlock(Qt::HANDLE h); + Q_DECL_EXPORT void m_live_texture_query(Qt::HANDLE h, void **data, int *pitch); + Q_DECL_EXPORT Qt::HANDLE m_live_texture_to_egl_image(Qt::HANDLE h); } #endif diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp index 33611dc..84fc593 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp @@ -87,6 +87,36 @@ void QMeeGoPixmapData::fromImage(const QImage &image, } } +void QMeeGoPixmapData::fromEGLImage(Qt::HANDLE handle) +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + bool textureIsBound = false; + GLuint newTextureId; + GLint newWidth, newHeight; + + glGenTextures(1, &newTextureId); + glBindTexture(GL_TEXTURE_2D, newTextureId); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) handle); + GLint err = glGetError(); + if (err == GL_NO_ERROR) + textureIsBound = true; + + QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_WIDTH, &newWidth); + QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_HEIGHT, &newHeight); + + if (textureIsBound) { + // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix + // for QGLPixmapData. + fromTexture(newTextureId, newWidth, newHeight, true); + } else { + qWarning("Failed to create a texture from an egl image!"); + glDeleteTextures(1, &newTextureId); + } +} + void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) { if (si.isNull()) diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h index 8af33bd..8b1ae14 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h @@ -56,6 +56,7 @@ public: QMeeGoPixmapData(); void fromTexture(GLuint textureId, int w, int h, bool alpha); + virtual void fromEGLImage(Qt::HANDLE handle); virtual void fromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); virtual void fromImage (const QImage &image, Qt::ImageConversionFlags flags); virtual QImage toImage() const; diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp index 2c7c0b7..9674233 100644 --- a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp +++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp @@ -42,6 +42,9 @@ #include "qgraphicssystem_vg_p.h" #include <QtOpenVG/private/qpixmapdata_vg_p.h> #include <QtOpenVG/private/qwindowsurface_vg_p.h> +#if defined(Q_OS_SYMBIAN) && !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) +#include <QtGui/private/qwidget_p.h> +#endif QT_BEGIN_NAMESPACE @@ -64,6 +67,11 @@ QPixmapData *QVGGraphicsSystem::createPixmapData(QPixmapData::PixelType type) co QWindowSurface *QVGGraphicsSystem::createWindowSurface(QWidget *widget) const { +#if defined(Q_OS_SYMBIAN) && !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) + QWidgetPrivate *d = qt_widget_private(widget); + if (!d->isOpaque && widget->testAttribute(Qt::WA_TranslucentBackground)) + return d->createDefaultWindowSurface_sys(); +#endif return new QVGWindowSurface(widget); } diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 5eeb244..f4e3a28 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4483,4 +4483,5 @@ EXPORTS ?msecsSinceReference@QElapsedTimer@@QBE_JXZ @ 4482 NONAME ; long long QElapsedTimer::msecsSinceReference(void) const ?selectThread@QEventDispatcherSymbian@@AAEAAVQSelectThread@@XZ @ 4483 NONAME ; class QSelectThread & QEventDispatcherSymbian::selectThread(void) ?qt_symbian_SetupThreadHeap@@YAHHAAUSStdEpocThreadCreateInfo@@@Z @ 4484 NONAME ; int qt_symbian_SetupThreadHeap(int, struct SStdEpocThreadCreateInfo &) + ?objectNameChanged@QAbstractDeclarativeData@@2P6AXPAV1@PAVQObject@@@ZA @ 4485 NONAME ; void (*QAbstractDeclarativeData::objectNameChanged)(class QAbstractDeclarativeData *, class QObject *) diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index cf0398a..b72147e 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -1838,4 +1838,5 @@ EXPORTS ?addChanged@QDeclarativeBasePositioner@@IAEXXZ @ 1837 NONAME ; void QDeclarativeBasePositioner::addChanged(void) ?start@QDeclarativeAbstractAnimation@@QAEXXZ @ 1838 NONAME ; void QDeclarativeAbstractAnimation::start(void) ?qt_metacall@QDeclarativeAbstractAnimation@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1839 NONAME ; int QDeclarativeAbstractAnimation::qt_metacall(enum QMetaObject::Call, int, void * *) + ?connect@QDeclarativePropertyPrivate@@SA_NPBVQObject@@H0HHPAH@Z @ 1840 NONAME ; bool QDeclarativePropertyPrivate::connect(class QObject const *, int, class QObject const *, int, int, int *) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index f496839..eb53dca 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3712,4 +3712,5 @@ EXPORTS _ZltRK13QElapsedTimerS1_ @ 3711 NONAME _ZrsR11QDataStreamR12QEasingCurve @ 3712 NONAME _Z26qt_symbian_SetupThreadHeapiR24SStdEpocThreadCreateInfo @ 3713 NONAME + _ZN24QAbstractDeclarativeData17objectNameChangedE @ 3714 NONAME DATA 4 diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index d4084cc..cbfafdc 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -1883,4 +1883,5 @@ EXPORTS _ZThn8_N29QDeclarativeAbstractAnimation9setTargetERK20QDeclarativeProperty @ 1882 NONAME _ZThn8_N29QDeclarativeAbstractAnimationD0Ev @ 1883 NONAME _ZThn8_N29QDeclarativeAbstractAnimationD1Ev @ 1884 NONAME + _ZN27QDeclarativePropertyPrivate7connectEPK7QObjectiS2_iiPi @ 1885 NONAME diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby index b6cdce9..4afbf05 100644 --- a/src/s60installs/qt.iby +++ b/src/s60installs/qt.iby @@ -53,6 +53,9 @@ file=ABI_DIR\BUILD_DIR\qaudio.dll SHARED_LIB_DIR\qaudio.dll file=ABI_DIR\BUILD_DIR\qvggraphicssystem.dll SHARED_LIB_DIR\qvggraphicssystem.dll file=ABI_DIR\BUILD_DIR\qglgraphicssystem.dll SHARED_LIB_DIR\qglgraphicssystem.dll +// bearer +file=ABI_DIR\BUILD_DIR\qsymbianbearer.dll SHARED_LIB_DIR\qsymbianbearer.dll + // S60 version compatibility plugins for 5.0 (3.1 and 3.2 devices are never likely to have this in ROM, // so don't bother including those plugins file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll @@ -99,6 +102,9 @@ data=\epoc32\data\qt\qtlibspluginstubs\qaudio.qtplugin resource\qt\plugins\audio data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplugin +// bearer stub +data=\epoc32\data\z\resource\qt\plugins\bearer\qsymbianbearer.qtplugin resource\qt\plugins\bearer\qsymbianbearer.qtplugin + // Stub sis file data=ZSYSTEM\install\qt_stub.sis System\Install\qt_stub.sis data=ZSYSTEM\install\qtwebkit_stub.sis System\Install\qtwebkit_stub.sis diff --git a/src/s60installs/qtdemoapps.iby b/src/s60installs/qtdemoapps.iby deleted file mode 100644 index d888135..0000000 --- a/src/s60installs/qtdemoapps.iby +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef QTDEMOAPPS_IBY -#define QTDEMOAPPS_IBY - -// A subset of Qt demo & example applications - -// Note that star requires OpenVG and the Qt OpenVG paint engine -S60_APP_EXE(star) -S60_APP_RESOURCE(star) -data=\epoc32\data\Z\private\10003a3f\import\Apps\star_reg.rsc \private\10003a3f\import\apps\star_reg.rsc - -S60_APP_EXE(wiggly) -S60_APP_RESOURCE(wiggly) -data=\epoc32\data\Z\private\10003a3f\import\Apps\wiggly_reg.rsc \private\10003a3f\import\apps\wiggly_reg.rsc - -#endif // QTDEMOAPPS_IBY diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 1f622c0..d63b97c 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -11,10 +11,10 @@ symbian: { isEmpty(QT_LIBINFIX) { TARGET.UID3 = 0x2001E61C - + # Sqlite3 is expected to be already found on phone if infixed configuration is built. # It is also expected that devices newer than those based on S60 5.0 all have sqlite3.dll. - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { BLD_INF_RULES.prj_exports += \ "sqlite3.sis /epoc32/data/qt/sis/sqlite3.sis" \ "sqlite3_selfsigned.sis /epoc32/data/qt/sis/sqlite3_selfsigned.sis" @@ -35,15 +35,6 @@ symbian: { } VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} - symbian-abld|symbian-sbsv2 { - qtresources.sources = $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/s60main$${QT_LIBINFIX}.rsc - } else { - qtresources.sources = $$QMAKE_LIBDIR_QT/s60main$${QT_LIBINFIX}.rsc - DESTDIR = $$QMAKE_LIBDIR_QT - } - qtresources.path = c:$$APP_RESOURCE_DIR - DEPLOYMENT += qtresources - qtlibraries.sources = \ $$QMAKE_LIBDIR_QT/QtCore$${QT_LIBINFIX}.dll \ $$QMAKE_LIBDIR_QT/QtXml$${QT_LIBINFIX}.dll \ @@ -109,9 +100,9 @@ symbian: { qtlibraries.pkg_prerules = vendorinfo qtlibraries.pkg_prerules += "; Dependencies of Qt libraries" - + # It is expected that Symbian^3 and newer phones will have sufficiently new OpenC already installed - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { qtlibraries.pkg_prerules += "(0x20013851), 1, 5, 1, {\"PIPS Installer\"}" contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { qtlibraries.pkg_prerules += "(0x200110CB), 1, 5, 1, {\"Open C LIBSSL Common\"}" @@ -209,5 +200,4 @@ symbian: { } BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" - BLD_INF_RULES.prj_exports += "qtdemoapps.iby $$CUSTOMER_VARIANT_APP_LAYER_IBY_EXPORT_PATH(qtdemoapps.iby)" } diff --git a/src/s60main/newallocator_hook.cpp b/src/s60main/newallocator_hook.cpp index 9cc6afb..9ea2ef0 100644 --- a/src/s60main/newallocator_hook.cpp +++ b/src/s60main/newallocator_hook.cpp @@ -41,6 +41,11 @@ #include <e32std.h> #include <qglobal.h> +#ifdef QT_EXPORTS_NOT_FROZEN +// If exports in Qt DLLs are not frozen in this build, then we have to pick up the +// allocator creation function by import link. We know the function will be present +// in the DLLs we test with, as we have to use the DLLs we have built. + struct SStdEpocThreadCreateInfo; Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo); @@ -51,8 +56,88 @@ Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCre * Uses link-time symbol preemption to capture a call from the application * startup. On return, there is some kind of heap allocator installed on the * thread. -*/ +*/ TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo) { return qt_symbian_SetupThreadHeap(aNotFirst, aInfo); } + +#else // QT_EXPORTS_NOT_FROZEN +// If we are using an export frozen build, it should be compatible with all 4.7.x Qt releases. +// We want to use the allocator creation function introduced in qtcore.dll after 4.7.1. But we +// can't import link to it, as it may not be present in whatever 4.7.x DLLs we are running with. +// So the function is found and called dynamically, by library lookup. If it is not found, we +// use the OS allocator creation functions instead. + +struct SThreadCreateInfo + { + TAny* iHandle; + TInt iType; + TThreadFunction iFunction; + TAny* iPtr; + TAny* iSupervisorStack; + TInt iSupervisorStackSize; + TAny* iUserStack; + TInt iUserStackSize; + TInt iInitialThreadPriority; + TPtrC iName; + TInt iTotalSize; // Size including any extras (must be a multiple of 8 bytes) + }; + +struct SStdEpocThreadCreateInfo : public SThreadCreateInfo + { + RAllocator* iAllocator; + TInt iHeapInitialSize; + TInt iHeapMaxSize; + TInt iPadding; // Make structure size a multiple of 8 bytes + }; + + +/* \internal + * + * Uses link-time symbol preemption to capture a call from the application + * startup. On return, there is some kind of heap allocator installed on the + * thread. +*/ +TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo) +{ + TInt r = KErrNone; + +#ifndef __WINS__ + // attempt to create the fast allocator through a known export ordinal in qtcore.dll + RLibrary qtcore; + if (qtcore.Load(_L("qtcore.dll")) == KErrNone) + { + const int qt_symbian_SetupThreadHeap_eabi_ordinal = 3713; + TLibraryFunction libFunc = qtcore.Lookup(qt_symbian_SetupThreadHeap_eabi_ordinal); + if (libFunc) + { + typedef int (*TSetupThreadHeapFunc)(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo); + TSetupThreadHeapFunc p_qt_symbian_SetupThreadHeap = TSetupThreadHeapFunc(libFunc); + r = (*p_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo); + } + qtcore.Close(); + if (libFunc) + return r; + } +#endif + + // no fast allocator support - use default allocator creation + if (!aInfo.iAllocator && aInfo.iHeapInitialSize>0) + { + // new heap required + RHeap* pH = NULL; + r = UserHeap::CreateThreadHeap(aInfo, pH); + } + else if (aInfo.iAllocator) + { + // sharing a heap + RAllocator* pA = aInfo.iAllocator; + pA->Open(); + User::SwitchAllocator(pA); + r = KErrNone; + } + return r; +} + +#endif // QT_EXPORTS_NOT_FROZEN diff --git a/src/s60main/s60main.pro b/src/s60main/s60main.pro index 664f155..8ab3bd3 100644 --- a/src/s60main/s60main.pro +++ b/src/s60main/s60main.pro @@ -31,6 +31,9 @@ symbian { # against GCCE apps, so remove it MMP_RULES -= $$MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA linux-armcc:QMAKE_CXXFLAGS *= --export_all_vtbl + + # Flag if exports are not frozen to avoid lookup of qtcore allocator creation function by ordinal + contains(CONFIG, def_files_disabled): DEFINES += QT_EXPORTS_NOT_FROZEN } else { error("$$_FILE_ is intended only for Symbian!") } diff --git a/src/s60main/s60main.rsg b/src/s60main/s60main.rsg deleted file mode 100644 index 8cdf3ba..0000000 --- a/src/s60main/s60main.rsg +++ /dev/null @@ -1,3 +0,0 @@ -#define R_DEFAULT_DOCUMENT_NAME 0x55567002 -#define R_QT_WRAPPERAPP_MENUBAR 0x55567004 -#define R_QT_WRAPPERAPP_MENU 0x55567005 diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml index 9fca5c3..56ac216 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml @@ -7,9 +7,9 @@ Rectangle { objectName: "MyRect" width: 100; height: 100; color: "green" Behavior on x { + id: myBehavior objectName: "MyBehavior" NumberAnimation {id: na1; duration: 200 } - NumberAnimation {id: na2; duration: 1000 } } } MouseArea { @@ -24,4 +24,9 @@ Rectangle { x: 200 } } + + NumberAnimation {id: na2; duration: 1000 } + Component.onCompleted: { + myBehavior.animation = na2; + } } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/objectName.qml b/tests/auto/declarative/qdeclarativeecmascript/data/objectName.qml new file mode 100644 index 0000000..ca8c90d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/objectName.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +QtObject { + objectName: "hello" + + property string test1: objectName + property string test2: objectName.substr(1, 3) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 4feb630..02832f3 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -162,6 +162,7 @@ private slots: void deleteLater(); void in(); void sharedAttachedObject(); + void objectName(); void include(); @@ -2594,6 +2595,24 @@ void tst_qdeclarativeecmascript::sharedAttachedObject() delete o; } +// QTBUG-13999 +void tst_qdeclarativeecmascript::objectName() +{ + QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test1").toString(), QString("hello")); + QCOMPARE(o->property("test2").toString(), QString("ell")); + + o->setObjectName("world"); + + QCOMPARE(o->property("test1").toString(), QString("world")); + QCOMPARE(o->property("test2").toString(), QString("orl")); + + delete o; +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" diff --git a/tests/auto/declarative/qdeclarativefocusscope/data/qtBug13380.qml b/tests/auto/declarative/qdeclarativefocusscope/data/qtBug13380.qml new file mode 100644 index 0000000..1784202 --- /dev/null +++ b/tests/auto/declarative/qdeclarativefocusscope/data/qtBug13380.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 + +Rectangle { + width: 400; height: 400 + + property bool showRect: false + onShowRectChanged: if (showRect) rect.visible = true + property bool noFocus: !fs2.activeFocus + + FocusScope { + id: fs1 + focus: true + } + Rectangle { + id: rect + visible: false + FocusScope { + id: fs2 + Rectangle { + focus: true + } + } + } +} diff --git a/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp b/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp index ec8f048..4cafbd9 100644 --- a/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp +++ b/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp @@ -70,6 +70,7 @@ private slots: void forceFocus(); void noParentFocus(); void signalEmission(); + void qtBug13380(); }; /* @@ -400,6 +401,31 @@ void tst_qdeclarativefocusscope::signalEmission() delete view; } +void tst_qdeclarativefocusscope::qtBug13380() +{ + QDeclarativeView *view = new QDeclarativeView; + view->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtBug13380.qml")); + + view->show(); + QVERIFY(view->rootObject()); + qApp->setActiveWindow(view); + qApp->processEvents(); + +#ifdef Q_WS_X11 + // to be safe and avoid failing setFocus with window managers + qt_x11_wait_for_window_manager(view); +#endif + + QVERIFY(view->hasFocus()); + QVERIFY(view->scene()->hasFocus()); + QVERIFY(view->rootObject()->property("noFocus").toBool()); + + view->rootObject()->setProperty("showRect", true); + QVERIFY(view->rootObject()->property("noFocus").toBool()); + + delete view; +} + QTEST_MAIN(tst_qdeclarativefocusscope) #include "tst_qdeclarativefocusscope.moc" diff --git a/tests/auto/declarative/qdeclarativegridview/data/header.qml b/tests/auto/declarative/qdeclarativegridview/data/header.qml new file mode 100644 index 0000000..99baacd --- /dev/null +++ b/tests/auto/declarative/qdeclarativegridview/data/header.qml @@ -0,0 +1,32 @@ +import QtQuick 1.0 + +Rectangle { + width: 240 + height: 320 + color: "#ffffff" + Component { + id: myDelegate + Rectangle { + id: wrapper + objectName: "wrapper" + width: 80 + height: 60 + border.color: "blue" + Text { + text: index + } + color: GridView.isCurrentItem ? "lightsteelblue" : "white" + } + } + GridView { + id: grid + objectName: "grid" + width: 240 + height: 320 + cellWidth: 80 + cellHeight: 60 + model: testModel + delegate: myDelegate + header: Text { objectName: "header"; text: "Header"; height: 30 } + } +} diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index 975cf8f..f7acd87 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -82,6 +82,7 @@ private slots: void QTBUG_8456(); void manualHighlight(); void footer(); + void header(); private: QDeclarativeView *createView(); @@ -1214,6 +1215,40 @@ void tst_QDeclarativeGridView::footer() QTRY_COMPARE(footer->y(), 0.0); } +void tst_QDeclarativeGridView::header() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 7; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + + QDeclarativeItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header"); + QVERIFY(header); + + QCOMPARE(header->y(), 0.0); + QCOMPARE(gridview->contentY(), 0.0); + + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0); + QVERIFY(item); + QCOMPARE(item->y(), 30.0); + + model.clear(); + QTRY_COMPARE(header->y(), 0.0); +} + QDeclarativeView *tst_QDeclarativeGridView::createView() { diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index 8f9b2ea..f1e026f 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -84,6 +84,7 @@ private slots: void tiling_QTBUG_6716(); void noLoading(); void paintedWidthHeight(); + void sourceSize_QTBUG_14303(); private: template<typename T> @@ -377,7 +378,7 @@ void tst_qdeclarativeimage::noLoading() QTRY_COMPARE(statusSpy.count(), 0); // Loading remote file - ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/oldcolors.png"); + ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/heart200.png"); QTRY_VERIFY(obj->status() == QDeclarativeImage::Loading); QTRY_VERIFY(obj->progress() == 0.0); QTRY_VERIFY(obj->status() == QDeclarativeImage::Ready); @@ -388,7 +389,7 @@ void tst_qdeclarativeimage::noLoading() // Loading remote file again - should not go through 'Loading' state. ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png")); - ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/oldcolors.png"); + ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/heart200.png"); QTRY_VERIFY(obj->status() == QDeclarativeImage::Ready); QTRY_VERIFY(obj->progress() == 1.0); QTRY_COMPARE(sourceSpy.count(), 4); @@ -436,6 +437,35 @@ void tst_qdeclarativeimage::paintedWidthHeight() } } +void tst_qdeclarativeimage::sourceSize_QTBUG_14303() +{ + QString componentStr = "import QtQuick 1.0\nImage { source: srcImage }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/heart200.png")); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); + + QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged())); + + QTRY_VERIFY(obj != 0); + QTRY_VERIFY(obj->status() == QDeclarativeImage::Ready); + + QTRY_COMPARE(obj->sourceSize().width(), 200); + QTRY_COMPARE(obj->sourceSize().height(), 200); + QTRY_COMPARE(sourceSizeSpy.count(), 0); + + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png")); + QTRY_COMPARE(obj->sourceSize().width(), 120); + QTRY_COMPARE(obj->sourceSize().height(), 120); + QTRY_COMPARE(sourceSizeSpy.count(), 1); + + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/heart200.png")); + QTRY_COMPARE(obj->sourceSize().width(), 200); + QTRY_COMPARE(obj->sourceSize().height(), 200); + QTRY_COMPARE(sourceSizeSpy.count(), 2); +} + /* Find an item with the specified objectName. If index is supplied then the item must also evaluate the {index} expression equal to index diff --git a/tests/auto/declarative/qdeclarativeitem/data/keystest.qml b/tests/auto/declarative/qdeclarativeitem/data/keystest.qml index 3927f42..9af6e9f 100644 --- a/tests/auto/declarative/qdeclarativeitem/data/keystest.qml +++ b/tests/auto/declarative/qdeclarativeitem/data/keystest.qml @@ -17,6 +17,7 @@ Item { Item { id: item2 + visible: forwardeeVisible Keys.onPressed: keysTestObject.forwardedKey(event.key) Keys.onReleased: keysTestObject.forwardedKey(event.key) } diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index bbbf73e..b4903ae 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -204,6 +204,7 @@ void tst_QDeclarativeItem::keys() canvas->rootContext()->setContextProperty("keysTestObject", testObject); canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true)); + canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(true)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/keystest.qml")); canvas->show(); @@ -287,6 +288,17 @@ void tst_QDeclarativeItem::keys() testObject->reset(); + canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(false)); + key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1); + QApplication::sendEvent(canvas, &key); + QCOMPARE(testObject->mKey, int(Qt::Key_A)); + QCOMPARE(testObject->mForwardedKey, 0); + QCOMPARE(testObject->mText, QLatin1String("A")); + QVERIFY(testObject->mModifiers == Qt::NoModifier); + QVERIFY(!key.isAccepted()); + + testObject->reset(); + canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(false)); QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), false); diff --git a/tests/auto/declarative/qdeclarativelanguage/data/alias.10.qml b/tests/auto/declarative/qdeclarativelanguage/data/alias.10.qml new file mode 100644 index 0000000..bf6352e --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/alias.10.qml @@ -0,0 +1,8 @@ +import Test 1.0 + +MyTypeObject { + id: root + property alias valueAlias: root.rectProperty + + rectProperty: "10,11,9x8" +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/alias.11.qml b/tests/auto/declarative/qdeclarativelanguage/data/alias.11.qml new file mode 100644 index 0000000..fbd50d9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/alias.11.qml @@ -0,0 +1,8 @@ +import Test 1.0 + +MyTypeObject { + id: root + + property alias aliasProperty: root.rectProperty.x + rectProperty: "19,13,100x120" +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/importIncorrectCase.qml b/tests/auto/declarative/qdeclarativelanguage/data/importIncorrectCase.qml new file mode 100644 index 0000000..247f527 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/importIncorrectCase.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 +import com.Nokia.installedtest 1.0 + +QtObject { +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.insensitive.txt b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.insensitive.txt new file mode 100644 index 0000000..3813680 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.insensitive.txt @@ -0,0 +1,2 @@ +3:1:Type IncorrectCaseType unavailable +-1:-1:File name case mismatch diff --git a/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.sensitive.txt b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.sensitive.txt new file mode 100644 index 0000000..abed1a7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.errors.sensitive.txt @@ -0,0 +1 @@ +3:1:IncorrectCaseType is not a type diff --git a/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.qml b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.qml new file mode 100644 index 0000000..d11000b --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCase.qml @@ -0,0 +1,4 @@ +import QtQuick 1.0 + +IncorrectCaseType { +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/incorrectCaseType.qml b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCaseType.qml new file mode 100644 index 0000000..cf32b45 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/incorrectCaseType.qml @@ -0,0 +1,4 @@ +import QtQuick 1.0 + +QtObject { +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.errors.txt new file mode 100644 index 0000000..93652a7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.errors.txt @@ -0,0 +1 @@ +5:23:Invalid alias location diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.qml b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.qml new file mode 100644 index 0000000..3ff7b16 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.10.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyTypeObject { + id: root + property alias a: root.rectProperty.blah +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.errors.txt index 7260be4..fbf1b58 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.errors.txt @@ -1 +1 @@ -5:23:Invalid alias reference. An alias reference must be specified as <id> or <id>.<property> +5:23:Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property> diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.qml b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.qml index cc71753..a363373 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.qml +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.3.qml @@ -2,5 +2,5 @@ import Test 1.0 MyTypeObject { id: root - property alias a: root.rectProperty.x + property alias a: root.rectProperty.x.y } diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.4.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.4.errors.txt index 7260be4..fbf1b58 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.4.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.4.errors.txt @@ -1 +1 @@ -5:23:Invalid alias reference. An alias reference must be specified as <id> or <id>.<property> +5:23:Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property> diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.errors.txt new file mode 100644 index 0000000..93652a7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.errors.txt @@ -0,0 +1 @@ +5:23:Invalid alias location diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.qml b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.qml new file mode 100644 index 0000000..4faa52d --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.8.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyTypeObject { + id: root + property alias a: root.imaginary.x +} + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.errors.txt new file mode 100644 index 0000000..93652a7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.errors.txt @@ -0,0 +1 @@ +5:23:Invalid alias location diff --git a/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.qml b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.qml new file mode 100644 index 0000000..f183912 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/invalidAlias.9.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyTypeObject { + id: root + property alias a: root.floatProperty.x +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.errors.txt new file mode 100644 index 0000000..beae562 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.errors.txt @@ -0,0 +1 @@ +5:10:Cannot assign multiple values to a singular property diff --git a/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.qml b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.qml new file mode 100644 index 0000000..2fd7fd2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.2.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +QtObject { + property QtObject a + a: [ QtObject {}, QtObject {} ] +} + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.errors.txt new file mode 100644 index 0000000..beae562 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.errors.txt @@ -0,0 +1 @@ +5:10:Cannot assign multiple values to a singular property diff --git a/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.qml b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.qml new file mode 100644 index 0000000..da56cb8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/singularProperty.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +QtObject { + property variant a + a: [ QtObject {}, QtObject {} ] +} diff --git a/tests/auto/declarative/qdeclarativelanguage/qtest/declarative/qmllanguage/noqmldir/Test.qml b/tests/auto/declarative/qdeclarativelanguage/qtest/declarative/qmllanguage/noqmldir/Test.qml new file mode 100644 index 0000000..0b054d0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/qtest/declarative/qmllanguage/noqmldir/Test.qml @@ -0,0 +1,2 @@ +import QtQuick 1.0 +Rectangle { } diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 9a8c944..061ac48 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -144,6 +144,7 @@ private slots: void importsInstalled(); void importsOrder_data(); void importsOrder(); + void importIncorrectCase(); void qmlAttachedPropertiesObjectMethod(); void customOnProperty(); @@ -348,6 +349,9 @@ void tst_qdeclarativelanguage::errors_data() QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false; QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false; QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false; + QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false; + QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false; + QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false; QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false; QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false; @@ -380,6 +384,15 @@ void tst_qdeclarativelanguage::errors_data() QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false; QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false; QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false; + QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false; + QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false; + QTest::newRow("incorrectCase") << "incorrectCase.qml" +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + << "incorrectCase.errors.insensitive.txt" +#else + << "incorrectCase.errors.sensitive.txt" +#endif + << false; } @@ -1054,6 +1067,47 @@ void tst_qdeclarativelanguage::aliasProperties() delete object; } + + // Valuetype alias + // Simple "int" alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.10.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8)); + object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100))); + QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100)); + + // Write throught alias + object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9))); + QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9)); + QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9)); + + delete object; + } + + // Valuetype sub-alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.11.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + QCOMPARE(object->property("aliasProperty").toInt(), 19); + object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111))); + QCOMPARE(object->property("aliasProperty").toInt(), 33); + + // Write throught alias + object->setProperty("aliasProperty", QVariant(4)); + QCOMPARE(object->property("aliasProperty").toInt(), 4); + QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111)); + + delete object; + } } // QTBUG-13374 Test that alias properties and signals can coexist @@ -1515,6 +1569,7 @@ void tst_qdeclarativelanguage::basicRemote_data() QString serverdir = "http://127.0.0.1:14447/qtest/declarative/qmllanguage/"; QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << ""; + QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << ""; QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << ""; } @@ -1722,6 +1777,22 @@ void tst_qdeclarativelanguage::importsOrder() testType(qml,type,error); } +void tst_qdeclarativelanguage::importIncorrectCase() +{ + QDeclarativeComponent component(&engine, TEST_FILE("importIncorrectCase.qml")); + + QList<QDeclarativeError> errors = component.errors(); + QCOMPARE(errors.count(), 1); + +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + QFileInfo(__FILE__).absoluteDir().filePath("data/lib/com/Nokia/installedtest/qmldir") + QLatin1String("\""); +#else + QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed"); +#endif + + QCOMPARE(errors.at(0).description(), expectedError); +} + void tst_qdeclarativelanguage::qmlAttachedPropertiesObjectMethod() { QObject object; diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index be77f8e..4b8d772 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -320,11 +320,16 @@ void tst_qdeclarativelistmodel::dynamic() if (!warning.isEmpty()) QTest::ignoreMessage(QtWarningMsg, warning.toLatin1()); + QSignalSpy spyCount(&model, SIGNAL(countChanged())); + int actual = e.evaluate().toInt(); if (e.hasError()) qDebug() << e.error(); // errors not expected QCOMPARE(actual,result); + + if (model.count() > 0) + QVERIFY(spyCount.count() > 0); } void tst_qdeclarativelistmodel::dynamic_worker_data() @@ -351,6 +356,8 @@ void tst_qdeclarativelistmodel::dynamic_worker() QDeclarativeItem *item = createWorkerTest(&eng, &component, &model); QVERIFY(item != 0); + QSignalSpy spyCount(&model, SIGNAL(countChanged())); + if (script[0] == QLatin1Char('{') && script[script.length()-1] == QLatin1Char('}')) script = script.mid(1, script.length() - 2); QVariantList operations; @@ -367,6 +374,9 @@ void tst_qdeclarativelistmodel::dynamic_worker() waitForWorker(item); QCOMPARE(QDeclarativeProperty(item, "result").read().toInt(), result); + if (model.count() > 0) + QVERIFY(spyCount.count() > 0); + delete item; qApp->processEvents(); } diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 6452bae..2649c0d 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -937,6 +937,8 @@ void tst_QDeclarativeListView::sections() QCOMPARE(next->text().toInt(), (i+1)/5); } + QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged())); + // Remove section boundary model.removeItem(5); @@ -972,13 +974,25 @@ void tst_QDeclarativeListView::sections() listview->setContentY(140); QTRY_COMPARE(listview->currentSection(), QString("1")); + QTRY_COMPARE(currentSectionChangedSpy.count(), 1); + listview->setContentY(20); QTRY_COMPARE(listview->currentSection(), QString("0")); + QTRY_COMPARE(currentSectionChangedSpy.count(), 2); + item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1); QTRY_VERIFY(item); QTRY_COMPARE(item->height(), 20.0); + // check that headers change when item changes + listview->setContentY(0); + model.modifyItem(0, "changed", "2"); + + item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1); + QTRY_VERIFY(item); + QTRY_COMPARE(item->height(), 40.0); + delete canvas; } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/incorrectCase.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/incorrectCase.qml new file mode 100644 index 0000000..a21ece7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/incorrectCase.qml @@ -0,0 +1,4 @@ +import com.nokia.WrongCase 1.0 + +MyPluginType { value: 123 } + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/WrongCase/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/WrongCase/qmldir new file mode 100644 index 0000000..6c87874 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/WrongCase/qmldir @@ -0,0 +1 @@ +plugin PluGin diff --git a/tools/qmeegographicssystemhelper/qmeegoliveimage_p.h b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWrongCase/plugin.cpp index 085fed4..5e91f4e 100644 --- a/tools/qmeegographicssystemhelper/qmeegoliveimage_p.h +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWrongCase/plugin.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -38,26 +38,46 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> -#include "qmeegoliveimage.h" +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; -#ifndef QMEEGOLIVEIMAGE_P_H -#define QMEEGOLIVEIMAGE_P_H -class QMeeGoLiveImagePrivate +class MyPlugin : public QDeclarativeExtensionPlugin { + Q_OBJECT public: - Q_DECLARE_PUBLIC(QMeeGoLiveImage); - QMeeGoLiveImagePrivate(); - virtual ~QMeeGoLiveImagePrivate(); - void attachPixmap(QMeeGoLivePixmap* pixmap); - void detachPixmap(QMeeGoLivePixmap* pixmap); - - QList <QMeeGoLivePixmap*> attachedPixmaps; - QMeeGoLiveImage *q_ptr; - - friend class QMeeGoLivePixmap; - friend class QMeeGoLivePixmapPrivate; + MyPlugin() + { + qWarning("plugin created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.WrongCase"); + qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType"); + } }; -#endif +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginWrongCase/pluginWrongCase.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWrongCase/pluginWrongCase.pro new file mode 100644 index 0000000..c7337ca --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWrongCase/pluginWrongCase.pro @@ -0,0 +1,10 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +TARGET = Plugin +DESTDIR = ../imports/com/nokia/WrongCase + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro index 824b402..221e465 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro @@ -1,6 +1,6 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin +SUBDIRS = plugin pluginWrongCase tst_qdeclarativemoduleplugin_pro.depends += plugin SUBDIRS += tst_qdeclarativemoduleplugin.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index e1022e0..85fa718 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -54,6 +54,7 @@ public: private slots: void importsPlugin(); + void incorrectPluginCase(); }; #ifdef Q_OS_SYMBIAN @@ -120,6 +121,30 @@ void tst_qdeclarativemoduleplugin::importsPlugin() delete object; } +void tst_qdeclarativemoduleplugin::incorrectPluginCase() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + + QDeclarativeComponent component(&engine, TEST_FILE("data/incorrectCase.qml")); + + QList<QDeclarativeError> errors = component.errors(); + QCOMPARE(errors.count(), 1); + +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) +#if defined(Q_OS_MAC) + QString libname = "libPluGin.dylib"; +#elif defined(Q_OS_WIN32) + QString libname = "PluGin.dll"; +#endif + QString expectedError = QLatin1String("plugin cannot be loaded for module \"com.nokia.WrongCase\": File name case mismatch for \"") + QFileInfo(__FILE__).absoluteDir().filePath("imports/com/nokia/WrongCase/" + libname) + QLatin1String("\""); +#else + QString expectedError = QLatin1String("module \"com.nokia.WrongCase\" plugin \"PluGin\" not found"); +#endif + + QCOMPARE(errors.at(0).description(), expectedError); +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" diff --git a/tests/auto/declarative/qdeclarativemousearea/data/doubleclick.qml b/tests/auto/declarative/qdeclarativemousearea/data/doubleclick.qml index 2348444..55b0812 100644 --- a/tests/auto/declarative/qdeclarativemousearea/data/doubleclick.qml +++ b/tests/auto/declarative/qdeclarativemousearea/data/doubleclick.qml @@ -4,11 +4,13 @@ Item { id: root property int clicked: 0 property int doubleClicked: 0 + property int released: 0 MouseArea { width: 200; height: 200 onClicked: { root.clicked++ } onDoubleClicked: { root.doubleClicked++ } + onReleased: { root.released++ } } } diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 5e88450..5a50e0d 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -413,14 +413,19 @@ void tst_QDeclarativeMouseArea::doubleClick() releaseEvent.setButtons(Qt::LeftButton); QApplication::sendEvent(scene, &releaseEvent); + QCOMPARE(canvas->rootObject()->property("released").toInt(), 1); + QGraphicsSceneMouseEvent dblClickEvent(QEvent::GraphicsSceneMouseDoubleClick); dblClickEvent.setScenePos(QPointF(100, 100)); dblClickEvent.setButton(Qt::LeftButton); dblClickEvent.setButtons(Qt::LeftButton); QApplication::sendEvent(scene, &dblClickEvent); + QApplication::sendEvent(scene, &releaseEvent); + QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1); QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1); + QCOMPARE(canvas->rootObject()->property("released").toInt(), 2); } QTEST_MAIN(tst_QDeclarativeMouseArea) diff --git a/tests/auto/declarative/qdeclarativetext/data/alignments_cb.png b/tests/auto/declarative/qdeclarativetext/data/alignments_cb.png Binary files differindex 99de219..cf6199a 100644 --- a/tests/auto/declarative/qdeclarativetext/data/alignments_cb.png +++ b/tests/auto/declarative/qdeclarativetext/data/alignments_cb.png diff --git a/tests/auto/declarative/qdeclarativetext/data/alignments_cc.png b/tests/auto/declarative/qdeclarativetext/data/alignments_cc.png Binary files differindex cb85251..f81ccb4 100644 --- a/tests/auto/declarative/qdeclarativetext/data/alignments_cc.png +++ b/tests/auto/declarative/qdeclarativetext/data/alignments_cc.png diff --git a/tests/auto/declarative/qdeclarativetext/data/alignments_ct.png b/tests/auto/declarative/qdeclarativetext/data/alignments_ct.png Binary files differindex ddca549..9ba6412 100644 --- a/tests/auto/declarative/qdeclarativetext/data/alignments_ct.png +++ b/tests/auto/declarative/qdeclarativetext/data/alignments_ct.png diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 472c5ef..a7971cc 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -56,6 +56,8 @@ #include <QDir> #include <QStyle> #include <QInputContext> +#include <QClipboard> +#include <QMimeData> #include <private/qapplication_p.h> #include <private/qtextcontrol_p.h> @@ -119,6 +121,8 @@ private slots: void openInputPanelOnClick(); void openInputPanelOnFocus(); void geometrySignals(); + void pastingRichText_QTBUG_14003(); + private: void simulateKey(QDeclarativeView *, int key); QDeclarativeView *createView(const QString &filename); @@ -1174,6 +1178,27 @@ void tst_qdeclarativetextedit::geometrySignals() delete o; } +void tst_qdeclarativetextedit::pastingRichText_QTBUG_14003() +{ +#ifndef QT_NO_CLIPBOARD + QString componentStr = "import QtQuick 1.0\nTextEdit { textFormat: TextEdit.PlainText }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeTextEdit *obj = qobject_cast<QDeclarativeTextEdit*>(component.create()); + + QTRY_VERIFY(obj != 0); + QTRY_VERIFY(obj->textFormat() == QDeclarativeTextEdit::PlainText); + + QMimeData *mData = new QMimeData; + mData->setHtml("<font color=\"red\">Hello</font>"); + QApplication::clipboard()->setMimeData(mData); + + obj->paste(); + QTRY_VERIFY(obj->text() == ""); + QTRY_VERIFY(obj->textFormat() == QDeclarativeTextEdit::PlainText); +#endif +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp index 91ae921..a198d7f 100644 --- a/tests/auto/qapplication/tst_qapplication.cpp +++ b/tests/auto/qapplication/tst_qapplication.cpp @@ -147,6 +147,10 @@ private slots: void symbianNeedForTraps(); void symbianLeaveThroughMain(); void qtbug_12673(); + + + + void globalStaticObjectDestruction(); // run this last }; class EventSpy : public QObject @@ -2257,6 +2261,42 @@ void tst_QApplication::qtbug_12673() #endif // Q_OS_SYMBIAN } +/* + This test is meant to ensure that certain objects (public & commonly used) + can safely be used in a Q_GLOBAL_STATIC such that their destructors are + executed *after* the destruction of QApplication. + */ +Q_GLOBAL_STATIC(QLocale, tst_qapp_locale); +Q_GLOBAL_STATIC(QProcess, tst_qapp_process); +Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher); +Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory); +Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer); +Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex); +Q_GLOBAL_STATIC(QWidget, tst_qapp_widget); +Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap); +Q_GLOBAL_STATIC(QFont, tst_qapp_font); +Q_GLOBAL_STATIC(QRegion, tst_qapp_region); +Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase); +Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor); + +void tst_QApplication::globalStaticObjectDestruction() +{ + int argc = 1; + QApplication app(argc, &argv0, QApplication::GuiServer); + QVERIFY(tst_qapp_locale()); + QVERIFY(tst_qapp_process()); + QVERIFY(tst_qapp_fileSystemWatcher()); + QVERIFY(tst_qapp_sharedMemory()); + QVERIFY(tst_qapp_elapsedTimer()); + QVERIFY(tst_qapp_mutex()); + QVERIFY(tst_qapp_widget()); + QVERIFY(tst_qapp_pixmap()); + QVERIFY(tst_qapp_font()); + QVERIFY(tst_qapp_region()); + QVERIFY(tst_qapp_fontDatabase()); + QVERIFY(tst_qapp_cursor()); +} + //QTEST_APPLESS_MAIN(tst_QApplication) int main(int argc, char *argv[]) { diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 25ec040..2ddccd2 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -445,6 +445,7 @@ private slots: void textItem_shortcuts(); void scroll(); void stopClickFocusPropagation(); + void deviceCoordinateCache_simpleRotations(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -9064,6 +9065,9 @@ void tst_QGraphicsItem::focusScope() scope2->hide(); scope2->show(); QVERIFY(!scope2->hasFocus()); + QVERIFY(scope1->hasFocus()); + scope2->setFocus(); + scope3->setFocus(); QVERIFY(scope3->hasFocus()); QGraphicsRectItem *rect4 = new QGraphicsRectItem; @@ -10560,6 +10564,81 @@ void tst_QGraphicsItem::stopClickFocusPropagation() QVERIFY(itemWithFocus->hasFocus()); } +void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations() +{ + // Make sure we don't invalidate the cache when applying simple + // (90, 180, 270, 360) rotation transforms to the item. + QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200); + item->setBrush(Qt::red); + item->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + + QGraphicsScene scene; + scene.setSceneRect(0, 0, 300, 200); + scene.addItem(item); + + MyGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + QTRY_VERIFY(view.repaints > 0); + + QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache(); + Q_ASSERT(itemCache); + QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key; + + // Trigger an update and verify that the cache is unchanged. + QPixmapCache::Key oldKey = currentKey; + view.reset(); + view.viewport()->update(); + QTRY_VERIFY(view.repaints > 0); + currentKey = itemCache->deviceData.value(view.viewport()).key; + QCOMPARE(currentKey, oldKey); + + // Check 90, 180, 270 and 360 degree rotations. + for (int angle = 90; angle <= 360; angle += 90) { + // Rotate item and verify that the cache was invalidated. + oldKey = currentKey; + view.reset(); + QTransform transform; + transform.translate(150, 100); + transform.rotate(angle); + transform.translate(-150, -100); + item->setTransform(transform); + QTRY_VERIFY(view.repaints > 0); + currentKey = itemCache->deviceData.value(view.viewport()).key; + QVERIFY(currentKey != oldKey); + + // IMPORTANT PART: + // Trigger an update and verify that the cache is unchanged. + oldKey = currentKey; + view.reset(); + view.viewport()->update(); + QTRY_VERIFY(view.repaints > 0); + currentKey = itemCache->deviceData.value(view.viewport()).key; + QCOMPARE(currentKey, oldKey); + } + + // 45 degree rotation. + oldKey = currentKey; + view.reset(); + QTransform transform; + transform.translate(150, 100); + transform.rotate(45); + transform.translate(-150, -100); + item->setTransform(transform); + QTRY_VERIFY(view.repaints > 0); + currentKey = itemCache->deviceData.value(view.viewport()).key; + QVERIFY(currentKey != oldKey); + + // Trigger an update and verify that the cache was invalidated. + // We should always invalidate the cache for non-trivial transforms. + oldKey = currentKey; + view.reset(); + view.viewport()->update(); + QTRY_VERIFY(view.repaints > 0); + currentKey = itemCache->deviceData.value(view.viewport()).key; + QVERIFY(currentKey != oldKey); +} + void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() { struct Item : public QGraphicsTextItem diff --git a/tests/auto/qinputdialog/tst_qinputdialog.cpp b/tests/auto/qinputdialog/tst_qinputdialog.cpp index 0d6644a..5d03142 100644 --- a/tests/auto/qinputdialog/tst_qinputdialog.cpp +++ b/tests/auto/qinputdialog/tst_qinputdialog.cpp @@ -74,6 +74,7 @@ private slots: void getItem_data(); void getItem(); void task256299_getTextReturnNullStringOnRejected(); + void inputMethodHintsOfChildWidget(); }; QString stripFraction(const QString &s) @@ -404,5 +405,24 @@ void tst_QInputDialog::getItem() delete parent; } +void tst_QInputDialog::inputMethodHintsOfChildWidget() +{ + QInputDialog dialog; + dialog.setInputMode(QInputDialog::TextInput); + QList<QObject *> children = dialog.children(); + QLineEdit *editWidget = 0; + for (int c = 0; c < children.size(); c++) { + editWidget = qobject_cast<QLineEdit *>(children.at(c)); + if (editWidget) + break; + } + QVERIFY(editWidget); + QCOMPARE(editWidget->inputMethodHints(), dialog.inputMethodHints()); + QCOMPARE(editWidget->inputMethodHints(), Qt::ImhNone); + dialog.setInputMethodHints(Qt::ImhDigitsOnly); + QCOMPARE(editWidget->inputMethodHints(), dialog.inputMethodHints()); + QCOMPARE(editWidget->inputMethodHints(), Qt::ImhDigitsOnly); +} + QTEST_MAIN(tst_QInputDialog) #include "tst_qinputdialog.moc" diff --git a/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif b/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif Binary files differnew file mode 100644 index 0000000..86a3a2e --- /dev/null +++ b/tests/auto/qpixmap/loadFromData/designer_indexed8_no_alpha_animated.gif diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index 8005ec5..fdf8311 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -179,6 +179,7 @@ private slots: void fromImageReader_data(); void fromImageReader(); + void fromImageReaderAnimatedGif_data(); void fromImageReaderAnimatedGif(); void preserveDepth(); @@ -1159,6 +1160,8 @@ void tst_QPixmap::fromSymbianCFbsBitmap_data() const int smallHeight = 20; const int largeWidth = 240; const int largeHeight = 320; + const int notAlignedWidth = 250; + const int notAlignedHeight = 250; // Indexed Color Formats - Disabled since images seem to be blank -> no palette? // QTest::newRow("EGray2 small") << EGray2 << smallWidth << smallHeight << QColor(Qt::black); @@ -1171,14 +1174,19 @@ void tst_QPixmap::fromSymbianCFbsBitmap_data() // Direct Color Formats QTest::newRow("EColor4K small") << EColor4K << smallWidth << smallHeight << QColor(Qt::red); QTest::newRow("EColor4K big") << EColor4K << largeWidth << largeHeight << QColor(Qt::red); + QTest::newRow("EColor4K not aligned") << EColor4K << notAlignedWidth << notAlignedHeight << QColor(Qt::red); QTest::newRow("EColor64K small") << EColor64K << smallWidth << smallHeight << QColor(Qt::green); QTest::newRow("EColor64K big") << EColor64K << largeWidth << largeHeight << QColor(Qt::green); + QTest::newRow("EColor64K not aligned") << EColor64K << notAlignedWidth << notAlignedHeight << QColor(Qt::green); QTest::newRow("EColor16M small") << EColor16M << smallWidth << smallHeight << QColor(Qt::yellow); QTest::newRow("EColor16M big") << EColor16M << largeWidth << largeHeight << QColor(Qt::yellow); + QTest::newRow("EColor16M not aligned") << EColor16M << notAlignedWidth << notAlignedHeight << QColor(Qt::yellow); QTest::newRow("EColor16MU small") << EColor16MU << smallWidth << smallHeight << QColor(Qt::red); QTest::newRow("EColor16MU big") << EColor16MU << largeWidth << largeHeight << QColor(Qt::red); + QTest::newRow("EColor16MU not aligned") << EColor16MU << notAlignedWidth << notAlignedHeight << QColor(Qt::red); QTest::newRow("EColor16MA small opaque") << EColor16MA << smallWidth << smallHeight << QColor(255, 255, 0); QTest::newRow("EColor16MA big opaque") << EColor16MA << largeWidth << largeHeight << QColor(255, 255, 0); + QTest::newRow("EColor16MA not aligned opaque") << EColor16MA << notAlignedWidth << notAlignedHeight << QColor(255, 255, 0); // Semi-transparent Colors - Disabled for now, since the QCOMPARE fails, but visually confirmed to work // QTest::newRow("EColor16MA small semi") << EColor16MA << smallWidth << smallHeight << QColor(255, 255, 0, 127); @@ -1236,6 +1244,10 @@ void tst_QPixmap::fromSymbianCFbsBitmap() QColor actualColor(image.pixel(1, 1)); QCOMPARE(actualColor, color); + + QImage shouldBe(pixmap.width(), pixmap.height(), image.format()); + shouldBe.fill(color.rgba()); + QCOMPARE(image, shouldBe); } __UHEAP_MARKEND; @@ -1605,6 +1617,8 @@ void tst_QPixmap::fromImageReader_data() QTest::newRow("designer_indexed8_no_alpha.gif") << prefix + "/designer_indexed8_no_alpha.gif"; QTest::newRow("designer_indexed8_with_alpha.gif") << prefix + "/designer_indexed8_with_alpha.gif"; QTest::newRow("designer_rgb32.jpg") << prefix + "/designer_rgb32.jpg"; + QTest::newRow("designer_indexed8_with_alpha_animated") << prefix + "/designer_indexed8_with_alpha_animated.gif"; + QTest::newRow("designer_indexed8_with_alpha_animated") << prefix + "/designer_indexed8_no_alpha_animated.gif"; } void tst_QPixmap::fromImageReader() @@ -1621,14 +1635,22 @@ void tst_QPixmap::fromImageReader() QVERIFY(pixmapsAreEqual(&pixmapWithCopy, &directLoadingPixmap)); } +void tst_QPixmap::fromImageReaderAnimatedGif_data() +{ + QTest::addColumn<QString>("imagePath"); + QTest::newRow("gif with alpha") << QString::fromLatin1("/designer_indexed8_with_alpha_animated.gif"); + QTest::newRow("gif without alpha") << QString::fromLatin1("/designer_indexed8_no_alpha_animated.gif"); +} + void tst_QPixmap::fromImageReaderAnimatedGif() { + QFETCH(QString, imagePath); #ifdef Q_OS_SYMBIAN const QString prefix = QLatin1String(SRCDIR) + "loadFromData"; #else const QString prefix = QLatin1String(SRCDIR) + "/loadFromData"; #endif - const QString path = prefix + QString::fromLatin1("/designer_indexed8_with_alpha_animated.gif"); + const QString path = prefix + imagePath; QImageReader referenceReader(path); QImageReader pixmapReader(path); diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp index 15775f6..38a0544 100644 --- a/tools/designer/src/components/formeditor/formwindow.cpp +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -1683,10 +1683,13 @@ void FormWindow::cut() // for cases like QMainWindow (central widget is an inner container) or QStackedWidget (page is an inner container) QWidget *FormWindow::innerContainer(QWidget *outerContainer) const { - bool isContainer = m_core->widgetDataBase()->isContainer(outerContainer); - if (isContainer) - if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer)) - return container->widget(container->currentIndex()); + if (m_core->widgetDataBase()->isContainer(outerContainer)) + if (const QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer)) { + const int currentIndex = container->currentIndex(); + return currentIndex >= 0 ? + container->widget(currentIndex) : + static_cast<QWidget *>(0); + } return outerContainer; } @@ -1706,8 +1709,10 @@ QWidget *FormWindow::containerForPaste() const QWidget *containerOfW = findContainer(selection.first(), /* exclude layouts */ true); if (!containerOfW || containerOfW == mainContainer()) break; - // No layouts, must be container + // No layouts, must be container. No empty page-based containers. containerOfW = innerContainer(containerOfW); + if (!containerOfW) + break; if (LayoutInfo::layoutType(m_core, containerOfW) != LayoutInfo::NoLayout || !m_core->widgetDataBase()->isContainer(containerOfW)) break; w = containerOfW; @@ -1716,6 +1721,8 @@ QWidget *FormWindow::containerForPaste() const // and the like as the central widget has the layout). w = innerContainer(w); + if (!w) + return 0; if (LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout) return 0; // Go up via container extension (also includes step from QMainWindow to its central widget) diff --git a/tools/designer/src/plugins/plugins.pro b/tools/designer/src/plugins/plugins.pro index cf4fa8a..bcebb82 100644 --- a/tools/designer/src/plugins/plugins.pro +++ b/tools/designer/src/plugins/plugins.pro @@ -3,7 +3,7 @@ CONFIG += ordered REQUIRES = !CONFIG(static,shared|static) contains(QT_CONFIG, qt3support): SUBDIRS += widgets -win32:!contains(QT_EDITION, OpenSource):SUBDIRS += activeqt +win32: SUBDIRS += activeqt # contains(QT_CONFIG, opengl): SUBDIRS += tools/view3d contains(QT_CONFIG, webkit): SUBDIRS += qwebview contains(QT_CONFIG, phonon): SUBDIRS += phononwidgets diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index b78b512..5d52a47 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -71,8 +71,9 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QT_END_INCLUDE_NAMESPACE \ PHONON_EXPORT \ Q_DECLARATIVE_EXPORT \ - Q_GADGET \ - QWEBKIT_EXPORT + Q_GADGET \ + QWEBKIT_EXPORT \ + Q_INVOKABLE Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ diff --git a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp index 0670ac4..d348e70 100644 --- a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp +++ b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp @@ -68,6 +68,11 @@ bool QMeeGoGraphicsSystemHelper::isRunningMeeGo() return (runningGraphicsSystemName() == QLatin1String("meego")); } +bool QMeeGoGraphicsSystemHelper::isRunningRuntime() +{ + return (QApplicationPrivate::instance()->graphics_system_name == QLatin1String("runtime")); +} + void QMeeGoGraphicsSystemHelper::switchToMeeGo() { if (isRunningMeeGo()) @@ -105,13 +110,13 @@ QPixmap QMeeGoGraphicsSystemHelper::pixmapFromEGLSharedImage(Qt::HANDLE handle, // This function is supported when not running meego too. A raster-backed // pixmap will be created... but when you switch back to 'meego', it'll // be replaced with a EGL shared image backing. - return QMeeGoRuntime::pixmapFromEGLSharedImage(handle, softImage); + return QPixmap(QMeeGoRuntime::pixmapDataFromEGLSharedImage(handle, softImage)); } QPixmap QMeeGoGraphicsSystemHelper::pixmapWithGLTexture(int w, int h) { ENSURE_RUNNING_MEEGO; - return QMeeGoRuntime::pixmapWithGLTexture(w, h); + return QPixmap(QMeeGoRuntime::pixmapDataWithGLTexture(w, h)); } bool QMeeGoGraphicsSystemHelper::destroyEGLSharedImage(Qt::HANDLE handle) diff --git a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.h b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.h index 02f2fa2..2bb75eb 100644 --- a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.h +++ b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.h @@ -89,6 +89,13 @@ public: switching is 'meego'. */ static bool isRunningMeeGo(); + + //! Returns true if running with a 'runtime' graphicssystem. + /*! + This function can be used in combination with ::runningGraphicsSystemName to figure out + the existing situation. + */ + static bool isRunningRuntime(); //! Switches to meego graphics system. /*! diff --git a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.pro b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.pro index 1e6e233..4d69fac 100644 --- a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.pro +++ b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.pro @@ -6,5 +6,5 @@ include(../../src/qbase.pri) QT += gui INCLUDEPATH += '../../src/plugins/graphicssystems/meego' -HEADERS = qmeegographicssystemhelper.h qmeegooverlaywidget.h qmeegolivepixmap.h qmeegoliveimage.h qmeegoruntime.h qmeegoliveimage_p.h qmeegolivepixmap_p.h -SOURCES = qmeegographicssystemhelper.cpp qmeegooverlaywidget.cpp qmeegoruntime.cpp qmeegolivepixmap.cpp qmeegoliveimage.cpp +HEADERS = qmeegographicssystemhelper.h qmeegooverlaywidget.h qmeegolivepixmap.h qmeegoruntime.h qmeegolivepixmap_p.h +SOURCES = qmeegographicssystemhelper.cpp qmeegooverlaywidget.cpp qmeegoruntime.cpp qmeegolivepixmap.cpp diff --git a/tools/qmeegographicssystemhelper/qmeegoliveimage.cpp b/tools/qmeegographicssystemhelper/qmeegoliveimage.cpp deleted file mode 100644 index 83a1e28..0000000 --- a/tools/qmeegographicssystemhelper/qmeegoliveimage.cpp +++ /dev/null @@ -1,115 +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 plugins 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 "qmeegoliveimage.h" -#include "qmeegoliveimage_p.h" -#include "qmeegolivepixmap.h" -#include "qmeegolivepixmap_p.h" - -/* QMeeGoLiveImagePrivate */ - -QMeeGoLiveImagePrivate::QMeeGoLiveImagePrivate() -{ -} - -QMeeGoLiveImagePrivate::~QMeeGoLiveImagePrivate() -{ - if (attachedPixmaps.length() > 0) - qWarning("Destroying QMeeGoLiveImage but it still has QMeeGoLivePixmaps attached!"); -} - -void QMeeGoLiveImagePrivate::attachPixmap(QMeeGoLivePixmap* pixmap) -{ - attachedPixmaps << pixmap; -} - -void QMeeGoLiveImagePrivate::detachPixmap(QMeeGoLivePixmap* pixmap) -{ - attachedPixmaps.removeAll(pixmap); -} - -/* QMeeGoLiveImage */ - -QMeeGoLiveImage* QMeeGoLiveImage::liveImageWithSize(int w, int h, Format format, int buffers) -{ - if (format != Format_ARGB32_Premultiplied) { - qWarning("Only _ARGB32_Premultiplied format is supported for live images now!"); - return 0; - } - - if (buffers != 1) { - qWarning("Only single-buffer streams are supported at the moment"); - return 0; - } - - QMeeGoLiveImage *liveImage = new QMeeGoLiveImage(w, h); - return liveImage; -} - -QMeeGoLiveImage::QMeeGoLiveImage(int w, int h) : QImage(w, h, QImage::Format_ARGB32_Premultiplied), d_ptr(new QMeeGoLiveImagePrivate()) -{ - Q_D(QMeeGoLiveImage); - d->q_ptr = this; -} - -QMeeGoLiveImage::~QMeeGoLiveImage() -{ -} - -void QMeeGoLiveImage::lock(int buffer) -{ - if (buffer != 0) - qWarning("Only locking 0 buffer is supported at the moment!"); -} - -void QMeeGoLiveImage::release(int buffer) -{ - Q_D(QMeeGoLiveImage); - - if (buffer != 0) { - qWarning("Only locking 0 buffer is supported at the moment!"); - return; - } - - // We need to copy the update image to all the client QMeeGoLivePixmap's - foreach (QMeeGoLivePixmap* livePixmap, d->attachedPixmaps) - livePixmap->d_ptr->copyBackFrom((const void *) bits()); -} diff --git a/tools/qmeegographicssystemhelper/qmeegoliveimage.h b/tools/qmeegographicssystemhelper/qmeegoliveimage.h deleted file mode 100644 index 1e21e7b..0000000 --- a/tools/qmeegographicssystemhelper/qmeegoliveimage.h +++ /dev/null @@ -1,106 +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 plugins 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 QMEEGOLIVEIMAGE_H -#define QMEEGOLIVEIMAGE_H - -#include <QImage> - -class QMeeGoLivePixmap; -class QMeeGoLiveImagePrivate; - -//! A streamable QImage subclass. -/*! -*/ - -class QMeeGoLiveImage : public QImage -{ -public: - //! Format specifier. - /*! - Used to specify the format of the underlying image data for QMeeGoLiveImage. - */ - enum Format { - Format_ARGB32_Premultiplied //! 32bit, AARRGGBB format. The typical Qt format. - }; - - //! Locks the access to the image. - /*! - All drawing/access to the underlying image data needs to happen between - ::lock() and ::unlock() pairs. - */ - void lock(int buffer = 0); - - //! Unlocks the access to the image. - /*! - All drawing/access to the underlying image data needs to happen between - ::lock() and ::unlock() pairs. - */ - void release(int buffer = 0); - - //! Destroys the image. - /*! - It's a mistake to destroy an image before destroying all the QMeeGoLivePixmaps - built on top of it. You should first destroy all the QMeeGoLivePixmaps. - */ - virtual ~QMeeGoLiveImage(); - - //! Creates and returns a new live image with the given parameters. - /*! - The new image is created with the given width w and the given height h. - The format specifies the color format used by the image. Optionally, a - number of buffers can be specfied for a stream-like behavior. - */ - static QMeeGoLiveImage* liveImageWithSize(int w, int h, Format format, int buffers = 1); - -private: - QMeeGoLiveImage(int w, int h); //! Private bits. - Q_DISABLE_COPY(QMeeGoLiveImage) - Q_DECLARE_PRIVATE(QMeeGoLiveImage) - -protected: - QScopedPointer<QMeeGoLiveImagePrivate> d_ptr; - - friend class QMeeGoLivePixmap; - friend class QMeeGoLivePixmapPrivate; -}; - -#endif diff --git a/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp b/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp index 2a1c04b..b9dbb2b 100644 --- a/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp +++ b/tools/qmeegographicssystemhelper/qmeegolivepixmap.cpp @@ -43,121 +43,101 @@ #include <private/qimage_p.h> #include <private/qpixmap_raster_p.h> #include "qmeegolivepixmap_p.h" -#include "qmeegoliveimage_p.h" +#include "qmeegoruntime.h" #include <QSharedMemory> /* QMeeGoLivePixmapPrivate */ -QMeeGoLivePixmapPrivate::QMeeGoLivePixmapPrivate() : shm(0), shmSerial(0), owns(true), parentImage(0) +QMeeGoLivePixmapPrivate::QMeeGoLivePixmapPrivate(Qt::HANDLE h) : handle(h) { } -void QMeeGoLivePixmapPrivate::copyBackFrom(const void *raw) +QMeeGoLivePixmapPrivate::~QMeeGoLivePixmapPrivate() { - Q_Q(QMeeGoLivePixmap); - - q->detach(); - shm->lock(); - uchar *dest = ((uchar *) shm->data()) + (2 * sizeof(int)); - memcpy(dest, raw, q->width() * q->height() * 4); - shm->unlock(); } -QMeeGoLivePixmapPrivate::~QMeeGoLivePixmapPrivate() +/* QMeeGoLivePixmap */ + +QMeeGoLivePixmap* QMeeGoLivePixmap::livePixmapWithSize(int w, int h, Format format) { - Q_Q(QMeeGoLivePixmap); + QImage::Format qtFormat; + if (format == Format_RGB16) + qtFormat = QImage::Format_RGB16; + else if (format == Format_ARGB32_Premultiplied) + qtFormat = QImage::Format_ARGB32_Premultiplied; + else { + qWarning("Unsupported live pixmap format!"); + return 0; + } - if (parentImage) - parentImage->d_ptr->detachPixmap(q); - - if (shm) - shm->detach(); - - if (owns) - delete shm; -} + Qt::HANDLE liveTextureHandle = QMeeGoRuntime::createLiveTexture(w, h, qtFormat); + if (! liveTextureHandle) { + qWarning("Failed to create a live texture with given size!"); + return NULL; + } -/* QMeeGoLivePixmap */ + return QMeeGoLivePixmap::fromHandle(liveTextureHandle); +} -QMeeGoLivePixmap::QMeeGoLivePixmap(QPixmapData *p) : QPixmap(p), d_ptr(new QMeeGoLivePixmapPrivate()) +QMeeGoLivePixmap::QMeeGoLivePixmap(QPixmapData *p, Qt::HANDLE h) : QPixmap(p), d_ptr(new QMeeGoLivePixmapPrivate(h)) { Q_D(QMeeGoLivePixmap); d->q_ptr = this; } -QMeeGoLivePixmap* QMeeGoLivePixmap::fromLiveImage(QMeeGoLiveImage *liveImage) +QMeeGoLivePixmap* QMeeGoLivePixmap::fromHandle(Qt::HANDLE liveTextureHandle) { - static int counter = 100; - QSharedMemory *shm = NULL; - uchar* imgData = NULL; - int *header = NULL; - int w = liveImage->width(); - int h = liveImage->height(); - - counter++; - shm = new QSharedMemory(QString(QLatin1String("QMeeGoLivePixmap%1")).arg(counter)); - shm->create((w * h * 4) + 2 * sizeof(int)); // +2 to store width & height - shm->attach(); - - imgData = ((uchar *) shm->data()) + (2 * sizeof(int)); - header = (int *) shm->data(); - - header[0] = w; - header[1] = h; - - QImage img(imgData, w, h, QImage::Format_ARGB32_Premultiplied); - - QPixmapData *pmd = new QRasterPixmapData(QPixmapData::PixmapType); - pmd->fromImage(img, Qt::NoOpaqueDetection); - - QMeeGoLivePixmap *livePixmap = new QMeeGoLivePixmap(pmd); - livePixmap->d_ptr->shm = shm; - livePixmap->d_ptr->owns = true; - livePixmap->d_ptr->shmSerial = counter; - livePixmap->d_ptr->parentImage = liveImage; - - liveImage->d_ptr->attachPixmap(livePixmap); + Qt::HANDLE eglImage = QMeeGoRuntime::liveTextureToEGLImage(liveTextureHandle); + if (! eglImage) { + qWarning("Failed to bind the live texture as an egl image!"); + return NULL; + } - return livePixmap; + QPixmapData *pmd = QMeeGoRuntime::pixmapDataFromEGLImage(eglImage); + if (! pmd) { + qWarning("Failed to allocate a pixmap data from a given live texture egl image!"); + return NULL; + } + + return new QMeeGoLivePixmap(pmd, liveTextureHandle); } -QMeeGoLivePixmap* QMeeGoLivePixmap::fromHandle(Qt::HANDLE handle) +Qt::HANDLE QMeeGoLivePixmap::handle() { - QSharedMemory *shm = NULL; - int *header; - int width; - int height; - uchar* imgData; - - shm = new QSharedMemory(QString(QLatin1String("QMeeGoLivePixmap%1")).arg(handle)); - shm->attach(); - - shm->lock(); - header = (int *) shm->data(); - width = header[0]; - height = header[1]; - shm->unlock(); - - imgData = ((uchar *) shm->data()) + (2 * sizeof(int)); - QImage img(imgData, width, height, QImage::Format_ARGB32_Premultiplied); - - QPixmapData *pmd = new QRasterPixmapData(QPixmapData::PixmapType); - pmd->fromImage(img, Qt::NoOpaqueDetection); - - QMeeGoLivePixmap *livePixmap = new QMeeGoLivePixmap(pmd); - livePixmap->d_ptr->shm = shm; - livePixmap->d_ptr->owns = false; - livePixmap->d_ptr->shmSerial = handle; - - return livePixmap; + Q_D(QMeeGoLivePixmap); + return d->handle; } QMeeGoLivePixmap::~QMeeGoLivePixmap() { } -Qt::HANDLE QMeeGoLivePixmap::handle() +QImage* QMeeGoLivePixmap::lock() +{ + Q_D(QMeeGoLivePixmap); + + void *data = NULL; + int pitch = 0; + + if (! QMeeGoRuntime::lockLiveTexture(d->handle)) { + qWarning("Failed to lock a live texture!"); + return new QImage(); + } + + QMeeGoRuntime::queryLiveTexture(d->handle, &data, &pitch); + if (data == NULL || pitch == 0) { + qWarning("Failed to query the live texture!"); + return new QImage(); + } + + // FIXME Bug here! FIX FIX FIX FIX FIX FIX + return new QImage((uchar *) data, width(), height(), QImage::Format_RGB16); +} + +void QMeeGoLivePixmap::release(QImage *img) { Q_D(QMeeGoLivePixmap); - return d->shmSerial; + // FIXME Make sure we're locked! + QMeeGoRuntime::unlockLiveTexture(d->handle); + delete img; } diff --git a/tools/qmeegographicssystemhelper/qmeegolivepixmap.h b/tools/qmeegographicssystemhelper/qmeegolivepixmap.h index 2fa9db2..12fe994 100644 --- a/tools/qmeegographicssystemhelper/qmeegolivepixmap.h +++ b/tools/qmeegographicssystemhelper/qmeegolivepixmap.h @@ -43,7 +43,6 @@ #define QMEEGOLIVEPIXMAP_H #include <QPixmap> -#include "qmeegoliveimage.h" class QMeeGoLivePixmapPrivate; class QSharedMemory; @@ -56,13 +55,17 @@ class QImage; class QMeeGoLivePixmap : public QPixmap { public: - //! Creates new pixmap from the given QMeeGoLiveImage. - /*! - The created QMeeGoLivePixmap will be attached to the given QMeeGoLiveImage. - Updates to the QMeeGoLiveImage will be represented on this newly created - QMeeGoLivePixmap. + enum Format { + Format_RGB16, //! 16bit, 5-6-5 RGB format. + Format_ARGB32_Premultiplied //! 32bit, AARRGGBB format. The typical Qt format. + }; + + //! Creates and returns a new live pixmap with the given parameters. + /*! + The new pixmap is created with the given width w and the given height h. + The format specifies the color format used by the pixmap. */ - static QMeeGoLivePixmap* fromLiveImage(QMeeGoLiveImage *liveImage); + static QMeeGoLivePixmap* livePixmapWithSize(int w, int h, Format format); //! Creates a new QMeeGoLivePixmap from the specified handle. /*! @@ -75,24 +78,30 @@ public: The handle can be used to share QMeeGoLivePixmap cross-process. */ Qt::HANDLE handle(); + + //! Locks the access to the pixmap. + /*! + The returned image can be used for direct access. + */ + QImage* lock(); + + //! Unlocks the access to the pixmap. + /*! + */ + void release(QImage *img); //! Destroys the QMeeGoLivePixmap. /*! - All QMeeGoLivePixmaps attached to a given QMeeGoLiveImage have to be destroyed - before the QMeeGoLiveImage itself is destroyed. */ virtual ~QMeeGoLivePixmap(); private: - QMeeGoLivePixmap(QPixmapData *p); + QMeeGoLivePixmap(QPixmapData *p, Qt::HANDLE h); Q_DISABLE_COPY(QMeeGoLivePixmap) Q_DECLARE_PRIVATE(QMeeGoLivePixmap) protected: QScopedPointer<QMeeGoLivePixmapPrivate> d_ptr; //! Private bits. - - friend class QMeeGoLiveImage; - friend class QMeeGoLiveImagePrivate; }; #endif diff --git a/tools/qmeegographicssystemhelper/qmeegolivepixmap_p.h b/tools/qmeegographicssystemhelper/qmeegolivepixmap_p.h index c2591dc..22347d6 100644 --- a/tools/qmeegographicssystemhelper/qmeegolivepixmap_p.h +++ b/tools/qmeegographicssystemhelper/qmeegolivepixmap_p.h @@ -48,19 +48,12 @@ class QMeeGoLivePixmapPrivate { public: Q_DECLARE_PUBLIC(QMeeGoLivePixmap); - QMeeGoLivePixmapPrivate(); - void copyBackFrom(const void *raw); + QMeeGoLivePixmapPrivate(Qt::HANDLE handle); virtual ~QMeeGoLivePixmapPrivate(); - QSharedMemory *shm; - int shmSerial; - bool owns; - QMeeGoLiveImage *parentImage; + Qt::HANDLE handle; QMeeGoLivePixmap *q_ptr; - - friend class QMeeGoLiveImage; - friend class QMeeGoLiveImagePrivate; }; #endif diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp index 70b5dc1..44f9f58 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp @@ -51,21 +51,36 @@ bool QMeeGoRuntime::initialized = false; typedef int (*QMeeGoImageToEglSharedImageFunc) (const QImage&); typedef QPixmapData* (*QMeeGoPixmapDataFromEglSharedImageFunc) (Qt::HANDLE handle, const QImage&); +typedef QPixmapData* (*QMeeGoPixmapDataFromEglImageFunc) (Qt::HANDLE handle); typedef QPixmapData* (*QMeeGoPixmapDataWithGLTextureFunc) (int w, int h); typedef bool (*QMeeGoDestroyEGLSharedImageFunc) (Qt::HANDLE handle); typedef void (*QMeeGoUpdateEglSharedImagePixmapFunc) (QPixmap*); typedef void (*QMeeGoSetSurfaceFixedSizeFunc) (int w, int h); typedef void (*QMeeGoSetSurfaceScalingFunc) (int x, int y, int w, int h); typedef void (*QMeeGoSetTranslucentFunc) (bool translucent); +typedef Qt::HANDLE (*QMeeGoLiveTextureCreateFunc) (int w, int h, QImage::Format format); +typedef bool (*QMeeGoLiveTextureLockFunc) (Qt::HANDLE h); +typedef bool (*QMeeGoLiveTextureUnlockFunc) (Qt::HANDLE h); +typedef void (*QMeeGoLiveTextureDestroyFunc) (Qt::HANDLE h); +typedef void (*QMeeGoLiveTextureQueryFunc) (Qt::HANDLE h, void **data, int *pitch); +typedef Qt::HANDLE (*QMeeGoLiveTextureToEglImageFunc) (Qt::HANDLE h); static QMeeGoImageToEglSharedImageFunc qt_meego_image_to_egl_shared_image = NULL; static QMeeGoPixmapDataFromEglSharedImageFunc qt_meego_pixmapdata_from_egl_shared_image = NULL; +static QMeeGoPixmapDataFromEglImageFunc qt_meego_pixmapdata_from_egl_image = NULL; static QMeeGoPixmapDataWithGLTextureFunc qt_meego_pixmapdata_with_gl_texture = NULL; static QMeeGoDestroyEGLSharedImageFunc qt_meego_destroy_egl_shared_image = NULL; static QMeeGoUpdateEglSharedImagePixmapFunc qt_meego_update_egl_shared_image_pixmap = NULL; static QMeeGoSetSurfaceFixedSizeFunc qt_meego_set_surface_fixed_size = NULL; static QMeeGoSetSurfaceScalingFunc qt_meego_set_surface_scaling = NULL; static QMeeGoSetTranslucentFunc qt_meego_set_translucent = NULL; +static QMeeGoLiveTextureCreateFunc qt_meego_live_texture_create = NULL; +static QMeeGoLiveTextureLockFunc qt_meego_live_texture_lock = NULL; +static QMeeGoLiveTextureUnlockFunc qt_meego_live_texture_unlock = NULL; +static QMeeGoLiveTextureDestroyFunc qt_meego_live_texture_destroy = NULL; +static QMeeGoLiveTextureQueryFunc qt_meego_live_texture_query = NULL; +static QMeeGoLiveTextureToEglImageFunc qt_meego_live_texture_to_egl_image = NULL; + void QMeeGoRuntime::initialize() { @@ -80,17 +95,26 @@ void QMeeGoRuntime::initialize() if (success) { qt_meego_image_to_egl_shared_image = (QMeeGoImageToEglSharedImageFunc) library.resolve("qt_meego_image_to_egl_shared_image"); - qt_meego_pixmapdata_from_egl_shared_image = (QMeeGoPixmapDataFromEglSharedImageFunc) library.resolve("qt_meego_pixmapdata_from_egl_shared_image"); + qt_meego_pixmapdata_from_egl_shared_image = (QMeeGoPixmapDataFromEglSharedImageFunc) library.resolve("qt_meego_pixmapdata_from_egl_shared_image"); + qt_meego_pixmapdata_from_egl_image = (QMeeGoPixmapDataFromEglImageFunc) library.resolve("qt_meego_pixmapdata_from_egl_image"); qt_meego_pixmapdata_with_gl_texture = (QMeeGoPixmapDataWithGLTextureFunc) library.resolve("qt_meego_pixmapdata_with_gl_texture"); qt_meego_destroy_egl_shared_image = (QMeeGoDestroyEGLSharedImageFunc) library.resolve("qt_meego_destroy_egl_shared_image"); qt_meego_update_egl_shared_image_pixmap = (QMeeGoUpdateEglSharedImagePixmapFunc) library.resolve("qt_meego_update_egl_shared_image_pixmap"); qt_meego_set_surface_fixed_size = (QMeeGoSetSurfaceFixedSizeFunc) library.resolve("qt_meego_set_surface_fixed_size"); qt_meego_set_surface_scaling = (QMeeGoSetSurfaceScalingFunc) library.resolve("qt_meego_set_surface_scaling"); qt_meego_set_translucent = (QMeeGoSetTranslucentFunc) library.resolve("qt_meego_set_translucent"); - - if (qt_meego_image_to_egl_shared_image && qt_meego_pixmapdata_from_egl_shared_image && qt_meego_pixmapdata_with_gl_texture - && qt_meego_destroy_egl_shared_image && qt_meego_update_egl_shared_image_pixmap && qt_meego_set_surface_fixed_size - && qt_meego_set_surface_scaling && qt_meego_set_translucent) + qt_meego_live_texture_create = (QMeeGoLiveTextureCreateFunc) library.resolve("qt_meego_live_texture_create"); + qt_meego_live_texture_lock = (QMeeGoLiveTextureLockFunc) library.resolve("qt_meego_live_texture_lock"); + qt_meego_live_texture_unlock = (QMeeGoLiveTextureUnlockFunc) library.resolve("qt_meego_live_texture_unlock"); + qt_meego_live_texture_destroy = (QMeeGoLiveTextureDestroyFunc) library.resolve("qt_meego_live_texture_destroy"); + qt_meego_live_texture_query = (QMeeGoLiveTextureQueryFunc) library.resolve("qt_meego_live_texture_query"); + qt_meego_live_texture_to_egl_image = (QMeeGoLiveTextureToEglImageFunc) library.resolve("qt_meego_live_texture_to_egl_image"); + + if (qt_meego_image_to_egl_shared_image && qt_meego_pixmapdata_from_egl_shared_image && qt_meego_pixmapdata_from_egl_image && + qt_meego_pixmapdata_with_gl_texture && qt_meego_destroy_egl_shared_image && qt_meego_update_egl_shared_image_pixmap && + qt_meego_set_surface_fixed_size && qt_meego_set_surface_scaling && qt_meego_set_translucent && + qt_meego_live_texture_create && qt_meego_live_texture_lock && qt_meego_live_texture_unlock && + qt_meego_live_texture_destroy && qt_meego_live_texture_query && qt_meego_live_texture_to_egl_image) { qDebug("Successfully resolved MeeGo graphics system: %s %s\n", qPrintable(libraryPrivate->fileName), qPrintable(libraryPrivate->fullVersion)); } @@ -108,18 +132,25 @@ Qt::HANDLE QMeeGoRuntime::imageToEGLSharedImage(const QImage &image) return qt_meego_image_to_egl_shared_image(image); } -QPixmap QMeeGoRuntime::pixmapFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage) +QPixmapData* QMeeGoRuntime::pixmapDataFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage) { ENSURE_INITIALIZED; Q_ASSERT(qt_meego_pixmapdata_from_egl_shared_image); - return QPixmap(qt_meego_pixmapdata_from_egl_shared_image(handle, softImage)); + return qt_meego_pixmapdata_from_egl_shared_image(handle, softImage); +} + +QPixmapData* QMeeGoRuntime::pixmapDataFromEGLImage(Qt::HANDLE handle) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_pixmapdata_from_egl_image); + return qt_meego_pixmapdata_from_egl_image(handle); } -QPixmap QMeeGoRuntime::pixmapWithGLTexture(int w, int h) +QPixmapData* QMeeGoRuntime::pixmapDataWithGLTexture(int w, int h) { ENSURE_INITIALIZED; Q_ASSERT(qt_meego_pixmapdata_with_gl_texture); - return QPixmap(qt_meego_pixmapdata_with_gl_texture(w, h)); + return qt_meego_pixmapdata_with_gl_texture(w, h); } bool QMeeGoRuntime::destroyEGLSharedImage(Qt::HANDLE handle) @@ -156,3 +187,46 @@ void QMeeGoRuntime::setTranslucent(bool translucent) Q_ASSERT(qt_meego_set_translucent); qt_meego_set_translucent(translucent); } + +Qt::HANDLE QMeeGoRuntime::createLiveTexture(int w, int h, QImage::Format format) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_create); + return qt_meego_live_texture_create(w, h, format); +} + +bool QMeeGoRuntime::lockLiveTexture(Qt::HANDLE h) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_lock); + return qt_meego_live_texture_lock(h); +} + +bool QMeeGoRuntime::unlockLiveTexture(Qt::HANDLE h) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_unlock); + return qt_meego_live_texture_unlock(h); +} + +void QMeeGoRuntime::destroyLiveTexture(Qt::HANDLE h) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_destroy); + qt_meego_live_texture_destroy(h); +} + +void QMeeGoRuntime::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_query); + qt_meego_live_texture_query(h, data, pitch); +} + +Qt::HANDLE QMeeGoRuntime::liveTextureToEGLImage(Qt::HANDLE handle) +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_live_texture_to_egl_image); + return qt_meego_live_texture_to_egl_image(handle); +} + diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.h b/tools/qmeegographicssystemhelper/qmeegoruntime.h index 82fdb52..048b9be 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.h +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.h @@ -48,13 +48,20 @@ public: static void initialize(); static Qt::HANDLE imageToEGLSharedImage(const QImage &image); - static QPixmap pixmapFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); - static QPixmap pixmapWithGLTexture(int w, int h); + static QPixmapData* pixmapDataFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); + static QPixmapData* pixmapDataFromEGLImage(Qt::HANDLE handle); + static QPixmapData* pixmapDataWithGLTexture(int w, int h); static bool destroyEGLSharedImage(Qt::HANDLE handle); static void updateEGLSharedImagePixmap(QPixmap *p); static void setSurfaceFixedSize(int w, int h); static void setSurfaceScaling(int x, int y, int w, int h); static void setTranslucent(bool translucent); + static Qt::HANDLE createLiveTexture(int w, int h, QImage::Format format); + static bool lockLiveTexture(Qt::HANDLE h); + static bool unlockLiveTexture(Qt::HANDLE h); + static void destroyLiveTexture(Qt::HANDLE h); + static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); + static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE); private: static bool initialized; diff --git a/tools/qtconfig/paletteeditoradvanced.cpp b/tools/qtconfig/paletteeditoradvanced.cpp index 2728557..f59584e 100644 --- a/tools/qtconfig/paletteeditoradvanced.cpp +++ b/tools/qtconfig/paletteeditoradvanced.cpp @@ -182,6 +182,7 @@ QColorGroup::ColorRole PaletteEditorAdvanced::centralFromItem( int item ) } QColorGroup::ColorRole PaletteEditorAdvanced::effectFromItem( int item ) + { switch( item ) { case 0: |