diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-10-15 22:56:47 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-10-15 22:56:47 (GMT) |
commit | 2fe5ef7f13a2d7f586549938c348739bde40646d (patch) | |
tree | b16cf97b033966a9e52460b0d12b3ef9ec11455b /src | |
parent | b317eb32c495cbedf5553de333ffdafbf3d75fc4 (diff) | |
parent | 2c9ac0221562581b7d14c0b74b3f498725b5dff3 (diff) | |
download | Qt-2fe5ef7f13a2d7f586549938c348739bde40646d.zip Qt-2fe5ef7f13a2d7f586549938c348739bde40646d.tar.gz Qt-2fe5ef7f13a2d7f586549938c348739bde40646d.tar.bz2 |
Merge branch 'qt-master-from-4.7' of scm.dev.nokia.troll.no:qt/qt-integration into master-integration
* 'qt-master-from-4.7' of scm.dev.nokia.troll.no:qt/qt-integration: (47 commits)
tst_qdeclarativetext: Regenerate the baselines after the merge.
Giving Qt a default app server when Avkon is removed
TextInput autoscroll now scrolls when the cursor moves
Fix samegame tutorial js
Make minehunt less cheerful
Add new behavior example.
Fix autotest on windows
Added --remove-destination to qmake_emulator_deployment.flm
Fix worker ListModels to property emit countChanged()
Update color type docs to mention transparency
Update reference bitmaps used in bitmap comparison tests to follow changes in Text painting
Fix alignment bugs in Text element
Remove debug code added by 650a0078e2cef43eff107fe8d2505f64a0bfedf0
Compile on WinCE
Remove obsolete tweak in QFontEngineS60::alphaMapForGlyph
Optimize QFontEngineS60::recalcAdvances()
Delete qtdemoapps.iby.
Added bearer plugin deployment to qt.iby
Implement QFontEngineS60::emSquareSize()
Remove unnecessary calls to GetHorizBounds() + boundingBox()
...
Diffstat (limited to 'src')
47 files changed, 931 insertions, 596 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ceffa66..573bb50 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() {} @@ -1067,7 +1068,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 82023d4..effd3e6 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -90,6 +90,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/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 7c43e5b..cdfdc58 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 250a43b..51eb5f2 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> @@ -1181,7 +1180,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; @@ -1223,7 +1222,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; @@ -1248,7 +1247,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; @@ -1276,7 +1275,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/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 637dd77..0903427 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1464,6 +1464,7 @@ void QDeclarativeTextInputPrivate::init() void QDeclarativeTextInput::cursorPosChanged() { Q_D(QDeclarativeTextInput); + d->updateHorizontalScroll(); updateRect();//TODO: Only update rect between pos's updateMicroFocus(); emit cursorPositionChanged(); 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 9ca7858..c391568 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/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 83aafe9..3ad8f33 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -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/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/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 23be51b..38d7d2f 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3153,10 +3153,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); - const int y = qFloor(positions[i].y + metrics.y); - + const int x = qFloor(positions[i].x + tmetrics.HorizBearingX()); + const int y = qFloor(positions[i].y - tmetrics.HorizBearingY()); alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); } diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp index 74432af..24d2496 100644 --- a/src/gui/s60framework/qs60mainapplication.cpp +++ b/src/gui/s60framework/qs60mainapplication.cpp @@ -47,6 +47,9 @@ #include "qs60mainapplication.h" #include <bautils.h> #include <coemain.h> +#ifndef Q_WS_S60 +# include <eikserverapp.h> +#endif QT_BEGIN_NAMESPACE @@ -152,7 +155,11 @@ CDictionaryStore *QS60MainApplication::OpenIniFileLC(RFs &aFs) const */ void QS60MainApplication::NewAppServerL(CApaAppServer *&aAppServer) { +#ifdef Q_WS_S60 QS60MainApplicationBase::NewAppServerL(aAppServer); +#else + aAppServer = new(ELeave) CEikAppServer; +#endif } QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index e9dcfa0..134c1ed 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" @@ -177,6 +178,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) { @@ -249,6 +268,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) { @@ -278,10 +304,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; } } @@ -309,6 +338,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 @@ -316,29 +346,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; } @@ -360,13 +378,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/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 45138f6..e2a99c2 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -186,10 +186,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(); 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 bc9d98b..2e6d2fe 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -200,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)" } |