diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-11-06 21:55:48 (GMT) |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-11-06 21:55:48 (GMT) |
commit | 360a51d64c607f5efae7a4f25a9a519424399b69 (patch) | |
tree | 874eb46ab469865ce9d9b58b9d1cf86d49e5bd1c /src/gui | |
parent | 7359baee83f6691c31a0a14ffd6f6cc147ed71fd (diff) | |
parent | 2b91557c93354b766c78cbc4ab48bcd58207bf1a (diff) | |
download | Qt-360a51d64c607f5efae7a4f25a9a519424399b69.zip Qt-360a51d64c607f5efae7a4f25a9a519424399b69.tar.gz Qt-360a51d64c607f5efae7a4f25a9a519424399b69.tar.bz2 |
Merge remote branch 'mainline/4.6' into 4.6
Diffstat (limited to 'src/gui')
95 files changed, 1674 insertions, 712 deletions
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 8f6d9d9..c493054 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -311,7 +311,8 @@ namespace QAccessible2 EditableTextInterface, ValueInterface, TableInterface, - ActionInterface + ActionInterface, + ImageInterface }; } @@ -321,6 +322,7 @@ class QAccessibleEditableTextInterface; class QAccessibleValueInterface; class QAccessibleTableInterface; class QAccessibleActionInterface; +class QAccessibleImageInterface; class Q_GUI_EXPORT QAccessibleInterface : public QAccessible { @@ -381,6 +383,9 @@ public: inline QAccessibleActionInterface *actionInterface() { return reinterpret_cast<QAccessibleActionInterface *>(cast_helper(QAccessible2::ActionInterface)); } + inline QAccessibleImageInterface *imageInterface() + { return reinterpret_cast<QAccessibleImageInterface *>(cast_helper(QAccessible2::ImageInterface)); } + private: QAccessible2Interface *cast_helper(QAccessible2::InterfaceType); }; diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp index 0867368..b878cf1 100644 --- a/src/gui/accessible/qaccessible2.cpp +++ b/src/gui/accessible/qaccessible2.cpp @@ -120,6 +120,18 @@ QT_BEGIN_NAMESPACE \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink */ +/*! + \class QAccessibleImageInterface + \ingroup accessibility + \internal + \preliminary + + \brief The QAccessibleImageInterface class implements support for + the IAccessibleImage interface. + + \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink +*/ + QAccessibleSimpleEditableTextInterface::QAccessibleSimpleEditableTextInterface( QAccessibleInterface *accessibleInterface) : iface(accessibleInterface) diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index 435c640..ba12a7c 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -82,6 +82,7 @@ inline QAccessible2Interface *qAccessibleTextCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleTableCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; } +inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; } #define Q_ACCESSIBLE_OBJECT \ public: \ @@ -98,6 +99,8 @@ inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; } return qAccessibleTableCastHelper(); \ case QAccessible2::ActionInterface: \ return qAccessibleActionCastHelper(); \ + case QAccessible2::ImageInterface: \ + return qAccessibleImageCastHelper(); \ } \ return 0; \ } \ @@ -224,6 +227,16 @@ public: virtual QStringList keyBindings(int actionIndex) = 0; }; +class Q_GUI_EXPORT QAccessibleImageInterface : public QAccessible2Interface +{ +public: + inline QAccessible2Interface *qAccessibleImageCastHelper() { return this; } + + virtual QString imageDescription() = 0; + virtual QSize imageSize() = 0; + virtual QRect imagePosition(QAccessible2::CoordinateType coordType) = 0; +}; + #endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm index 9575ad8..030c1a9 100644 --- a/src/gui/accessible/qaccessible_mac.mm +++ b/src/gui/accessible/qaccessible_mac.mm @@ -504,11 +504,6 @@ QAElement::QAElement(const QAElement &element) } QAElement::QAElement(HIObjectRef object, int child) - :elementRef( -#ifndef QT_MAC_USE_COCOA - AXUIElementCreateWithHIObjectAndIdentifier(object, child) -#endif -) { #ifndef QT_MAC_USE_COCOA if (object == 0) { diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm index 9e4fdd1..5f074c0 100644 --- a/src/gui/dialogs/qcolordialog_mac.mm +++ b/src/gui/dialogs/qcolordialog_mac.mm @@ -252,15 +252,20 @@ QT_USE_NAMESPACE delete mQtColor; mQtColor = new QColor(); NSColor *color = [mColorPanel color]; - NSString *colorSpace = [color colorSpaceName]; - if (colorSpace == NSDeviceCMYKColorSpace) { - CGFloat cyan, magenta, yellow, black, alpha; + NSString *colorSpaceName = [color colorSpaceName]; + if (colorSpaceName == NSDeviceCMYKColorSpace) { + CGFloat cyan = 0, magenta = 0, yellow = 0, black = 0, alpha = 0; [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; mQtColor->setCmykF(cyan, magenta, yellow, black, alpha); - } else if (colorSpace == NSCalibratedRGBColorSpace || colorSpace == NSDeviceRGBColorSpace) { - CGFloat red, green, blue, alpha; + } else if (colorSpaceName == NSCalibratedRGBColorSpace || colorSpaceName == NSDeviceRGBColorSpace) { + CGFloat red = 0, green = 0, blue = 0, alpha = 0; [color getRed:&red green:&green blue:&blue alpha:&alpha]; mQtColor->setRgbF(red, green, blue, alpha); + } else if (colorSpaceName == NSNamedColorSpace) { + NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + CGFloat red = 0, green = 0, blue = 0, alpha = 0; + [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; + mQtColor->setRgbF(red, green, blue, alpha); } else { NSColorSpace *colorSpace = [color colorSpace]; if ([colorSpace colorSpaceModel] == NSCMYKColorSpaceModel && [color numberOfComponents] == 5){ @@ -269,7 +274,7 @@ QT_USE_NAMESPACE mQtColor->setCmykF(components[0], components[1], components[2], components[3], components[4]); } else { NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - CGFloat red, green, blue, alpha; + CGFloat red = 0, green = 0, blue = 0, alpha = 0; [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; mQtColor->setRgbF(red, green, blue, alpha); } @@ -319,7 +324,18 @@ QT_USE_NAMESPACE QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active); QMacCocoaAutoReleasePool pool; mDialogIsExecuting = true; - [NSApp runModalForWindow:mColorPanel]; + bool modalEnded = false; + while (!modalEnded) { + @try { + [NSApp runModalForWindow:mColorPanel]; + modalEnded = true; + } @catch (NSException *) { + // For some reason, NSColorPanel throws an exception when + // clicking on 'SelectedMenuItemColor' from the 'Developer' + // palette (tab three). + } + } + QAbstractEventDispatcher::instance()->interrupt(); if (mResultCode == NSCancelButton) mPriv->colorDialog()->reject(); diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index 4af5688..b0e6575 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -830,8 +830,8 @@ void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMess || mode == QFileDialog::ExistingFiles){ // When changing directory, the current selection is cleared if // we are supposed to be selecting files only: - fileDialogPrivate->mCurrentSelectionList.clear(); if (!fileDialogPrivate->mCurrentSelection.isEmpty()){ + fileDialogPrivate->mCurrentSelectionList.clear(); fileDialogPrivate->mCurrentSelection.clear(); emit fileDialogPrivate->q_func()->currentChanged(fileDialogPrivate->mCurrentSelection); } diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 83f4f79..568ff73 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -108,6 +108,7 @@ #include <QtCore/qdebug.h> #include <private/qdrawhelper_p.h> +#ifndef QT_NO_GRAPHICSEFFECT QT_BEGIN_NAMESPACE /*! @@ -127,6 +128,19 @@ QT_BEGIN_NAMESPACE */ /*! + \enum QGraphicsEffectSource::PixmapPadMode + + This enum describes how much of the effect will be rendered to a pixmap + created using the pixmap() function. + + \value NoExpandPadMode The pixmap is the size of the widget or graphics item. + \value ExpandToTransparentBorderPadMode The pixmap is expanded to include + the widget or graphics item plus a transparent border. + \value ExpandToEffectRectPadMode The pixmap is expanded to include the widget + or graphics item and the effect. +*/ + +/*! \internal */ QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) @@ -263,6 +277,9 @@ bool QGraphicsEffectSource::isPixmap() const The optional \a offset parameter returns the offset where the pixmap should be painted at using the current painter. + The \a mode determines how much of the effect the pixmap will contain. + By default, the pixmap will contain the whole effect. + The returned pixmap is bound to the current painter's device rectangle when \a system is Qt::DeviceCoordinates. @@ -303,6 +320,11 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse return pm; } +QGraphicsEffectSourcePrivate::~QGraphicsEffectSourcePrivate() +{ + invalidateCache(); +} + void QGraphicsEffectSourcePrivate::invalidateCache(bool effectRectChanged) const { if (effectRectChanged && m_cachedMode != QGraphicsEffectSource::ExpandToEffectRectPadMode) @@ -734,7 +756,7 @@ void QGraphicsBlurEffect::setBlurHint(QGraphicsBlurEffect::BlurHint hint) } /*! - \fn void QGraphicsBlurEffect::blurHintChanged(Qt::BlurHint hint) + \fn void QGraphicsBlurEffect::blurHintChanged(QGraphicsBlurEffect::BlurHint hint) This signal is emitted whenever the effect's blur hint changes. The \a hint parameter holds the effect's new blur hint. @@ -1128,3 +1150,4 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSEFFECT diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 7335a25..5c73f4b 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -48,6 +48,7 @@ #include <QtGui/qcolor.h> #include <QtGui/qbrush.h> +#ifndef QT_NO_GRAPHICSEFFECT QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -302,6 +303,7 @@ private: QT_END_NAMESPACE QT_END_HEADER +#endif //QT_NO_GRAPHICSEFFECT #endif // QGRAPHICSEFFECT_H diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 0ff5794..d94d08d 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -60,6 +60,7 @@ #include <private/qobject_p.h> #include <private/qpixmapfilter_p.h> +#ifndef QT_NO_GRAPHICSEFFECT QT_BEGIN_NAMESPACE class QGraphicsEffectSourcePrivate : public QObjectPrivate @@ -72,7 +73,7 @@ public: , m_cachedMode(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) {} - virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); } + virtual ~QGraphicsEffectSourcePrivate(); virtual void detach() = 0; virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; virtual QRect deviceRect() const = 0; @@ -179,5 +180,6 @@ public: QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSEFFECT #endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h index f1fa185..0a2bf27 100644 --- a/src/gui/graphicsview/qgraph_p.h +++ b/src/gui/graphicsview/qgraph_p.h @@ -201,11 +201,6 @@ public: return l; } - void setRootVertex(Vertex *vertex) - { - userVertex = vertex; - } - QSet<Vertex*> vertices() const { QSet<Vertex *> setOfVertices; for (const_iterator it = constBegin(); it != constEnd(); ++it) { @@ -241,7 +236,7 @@ public: EdgeData *data = edgeData(v, v1); bool forward = data->from == v; if (forward) { - edges += QString::fromAscii("%1->%2 [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n") + edges += QString::fromAscii("\"%1\"->\"%2\" [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n") .arg(v->toString()) .arg(v1->toString()) .arg(data->minSize) @@ -250,17 +245,12 @@ public: ; } } - strVertices += QString::fromAscii("%1 [label=\"%2\"]\n").arg(v->toString()).arg(v->toString()); + strVertices += QString::fromAscii("\"%1\" [label=\"%2\"]\n").arg(v->toString()).arg(v->toString()); } return QString::fromAscii("%1\n%2\n").arg(strVertices).arg(edges); } #endif - Vertex *rootVertex() const - { - return userVertex; - } - protected: void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data) { @@ -286,8 +276,6 @@ protected: } private: - Vertex *userVertex; - QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph; }; diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 56d70e1..872ec3c 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -83,10 +83,8 @@ \clearfloat \section1 Size Hints and Size Policies in an Anchor Layout - QGraphicsAnchorLayout respects each item's size hints and size policies. However it does - not currently respect their stretch factors. This might change in the future, so avoid - using stretch factors in anchor layouts if you want to avoid any future regressions in - behavior. + QGraphicsAnchorLayout respects each item's size hints and size policies. + Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}. \section1 Spacing within an Anchor Layout @@ -101,6 +99,21 @@ If the spacing is negative, the items will overlap to some extent. + + \section1 Known issues + There are some features that QGraphicsAnchorLayout currently does not support. + This might change in the future, so avoid using these features if you want to + avoid any future regressions in behaviour: + \list + + \o Stretch factors are not respected. + + \o QSizePolicy::ExpandFlag is not respected. + + \o Height for width is not respected. + + \endlist + \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout */ diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 41aa8aa..96f8930 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -105,7 +105,7 @@ qreal QGraphicsAnchorPrivate::spacing() const static void internalSizeHints(QSizePolicy::Policy policy, qreal minSizeHint, qreal prefSizeHint, qreal maxSizeHint, qreal *minSize, qreal *prefSize, - qreal *expSize, qreal *maxSize) + qreal *maxSize) { // minSize, prefSize and maxSize are initialized // with item's preferred Size: this is QSizePolicy::Fixed. @@ -135,11 +135,6 @@ static void internalSizeHints(QSizePolicy::Policy policy, *prefSize = *minSize; else *prefSize = prefSizeHint; - - if (policy & QSizePolicy::ExpandFlag) - *expSize = *maxSize; - else - *expSize = *prefSize; } bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) @@ -154,7 +149,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) if (isLayoutAnchor) { minSize = 0; prefSize = 0; - expSize = 0; maxSize = QWIDGETSIZE_MAX; if (isCenterAnchor) maxSize /= 2; @@ -205,8 +199,8 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) } maxSizeHint = QWIDGETSIZE_MAX; } - internalSizeHints(policy, minSizeHint, prefSizeHint, maxSizeHint, - &minSize, &prefSize, &expSize, &maxSize); + internalSizeHints(policy, minSizeHint, prefSizeHint, maxSizeHint, + &minSize, &prefSize, &maxSize); // Set the anchor effective sizes to preferred. // @@ -217,7 +211,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) // recalculate and override the values we set here. sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; - sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; return true; @@ -227,7 +220,6 @@ void ParallelAnchorData::updateChildrenSizes() { firstEdge->sizeAtMinimum = secondEdge->sizeAtMinimum = sizeAtMinimum; firstEdge->sizeAtPreferred = secondEdge->sizeAtPreferred = sizeAtPreferred; - firstEdge->sizeAtExpanding = secondEdge->sizeAtExpanding = sizeAtExpanding; firstEdge->sizeAtMaximum = secondEdge->sizeAtMaximum = sizeAtMaximum; firstEdge->updateChildrenSizes(); @@ -257,16 +249,12 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn return false; } - expSize = qMax(firstEdge->expSize, secondEdge->expSize); - expSize = qMin(expSize, maxSize); - prefSize = qMax(firstEdge->prefSize, secondEdge->prefSize); - prefSize = qMin(prefSize, expSize); + prefSize = qMin(prefSize, maxSize); // See comment in AnchorData::refreshSizeHints() about sizeAt* values sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; - sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; return true; @@ -280,8 +268,7 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn 1 is at Maximum */ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal value, qreal min, - qreal pref, qreal exp, - qreal max) + qreal pref, qreal max) { QGraphicsAnchorLayoutPrivate::Interval interval; qreal lower; @@ -291,13 +278,9 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu interval = QGraphicsAnchorLayoutPrivate::MinToPreferred; lower = min; upper = pref; - } else if (value < exp) { - interval = QGraphicsAnchorLayoutPrivate::PreferredToExpanding; - lower = pref; - upper = exp; } else { - interval = QGraphicsAnchorLayoutPrivate::ExpandingToMax; - lower = exp; + interval = QGraphicsAnchorLayoutPrivate::PreferredToMax; + lower = pref; upper = max; } @@ -313,7 +296,7 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor, qreal min, qreal pref, - qreal exp, qreal max) + qreal max) { qreal lower; qreal upper; @@ -323,12 +306,8 @@ static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qre lower = min; upper = pref; break; - case QGraphicsAnchorLayoutPrivate::PreferredToExpanding: + case QGraphicsAnchorLayoutPrivate::PreferredToMax: lower = pref; - upper = exp; - break; - case QGraphicsAnchorLayoutPrivate::ExpandingToMax: - lower = exp; upper = max; break; } @@ -341,34 +320,31 @@ void SequentialAnchorData::updateChildrenSizes() // ### REMOVE ME // ### check whether we are guarantee to get those or we need to warn stuff at this // point. - Q_ASSERT(sizeAtMinimum > minSize || qFuzzyCompare(sizeAtMinimum, minSize)); - Q_ASSERT(sizeAtMinimum < maxSize || qFuzzyCompare(sizeAtMinimum, maxSize)); - Q_ASSERT(sizeAtPreferred > minSize || qFuzzyCompare(sizeAtPreferred, minSize)); - Q_ASSERT(sizeAtPreferred < maxSize || qFuzzyCompare(sizeAtPreferred, maxSize)); - Q_ASSERT(sizeAtExpanding > minSize || qFuzzyCompare(sizeAtExpanding, minSize)); - Q_ASSERT(sizeAtExpanding < maxSize || qFuzzyCompare(sizeAtExpanding, maxSize)); - Q_ASSERT(sizeAtMaximum > minSize || qFuzzyCompare(sizeAtMaximum, minSize)); - Q_ASSERT(sizeAtMaximum < maxSize || qFuzzyCompare(sizeAtMaximum, maxSize)); + Q_ASSERT(sizeAtMinimum > minSize || qAbs(sizeAtMinimum - minSize) < 0.00000001); + Q_ASSERT(sizeAtPreferred > minSize || qAbs(sizeAtPreferred - minSize) < 0.00000001); + Q_ASSERT(sizeAtMaximum > minSize || qAbs(sizeAtMaximum - minSize) < 0.00000001); + + // These may be false if this anchor was in parallel with the layout stucture + // Q_ASSERT(sizeAtMinimum < maxSize || qAbs(sizeAtMinimum - maxSize) < 0.00000001); + // Q_ASSERT(sizeAtPreferred < maxSize || qAbs(sizeAtPreferred - maxSize) < 0.00000001); + // Q_ASSERT(sizeAtMaximum < maxSize || qAbs(sizeAtMaximum - maxSize) < 0.00000001); // Band here refers if the value is in the Minimum To Preferred // band (the lower band) or the Preferred To Maximum (the upper band). const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> minFactor = - getFactor(sizeAtMinimum, minSize, prefSize, expSize, maxSize); + getFactor(sizeAtMinimum, minSize, prefSize, maxSize); const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> prefFactor = - getFactor(sizeAtPreferred, minSize, prefSize, expSize, maxSize); - const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> expFactor = - getFactor(sizeAtExpanding, minSize, prefSize, expSize, maxSize); + getFactor(sizeAtPreferred, minSize, prefSize, maxSize); const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> maxFactor = - getFactor(sizeAtMaximum, minSize, prefSize, expSize, maxSize); + getFactor(sizeAtMaximum, minSize, prefSize, maxSize); for (int i = 0; i < m_edges.count(); ++i) { AnchorData *e = m_edges.at(i); - e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->prefSize, e->expSize, e->maxSize); - e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->prefSize, e->expSize, e->maxSize); - e->sizeAtExpanding = interpolate(expFactor, e->minSize, e->prefSize, e->expSize, e->maxSize); - e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->prefSize, e->expSize, e->maxSize); + e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->prefSize, e->maxSize); + e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->prefSize, e->maxSize); + e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->prefSize, e->maxSize); e->updateChildrenSizes(); } @@ -384,7 +360,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style { minSize = 0; prefSize = 0; - expSize = 0; maxSize = 0; for (int i = 0; i < m_edges.count(); ++i) { @@ -396,14 +371,12 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style minSize += edge->minSize; prefSize += edge->prefSize; - expSize += edge->expSize; maxSize += edge->maxSize; } // See comment in AnchorData::refreshSizeHints() about sizeAt* values sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; - sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; return true; @@ -478,12 +451,15 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() for (int j = 0; j < 3; ++j) { sizeHints[i][j] = -1; } - sizeAtExpanding[i] = -1; interpolationProgress[i] = -1; spacings[i] = -1; graphSimplified[i] = false; graphHasConflicts[i] = false; + + layoutFirstVertex[i] = 0; + layoutCentralVertex[i] = 0; + layoutLastVertex[i] = 0; } } @@ -529,13 +505,14 @@ inline static qreal checkAdd(qreal a, qreal b) Adds \a newAnchor to the graph \a g. Returns the newAnchor itself if it could be added without further changes to the graph. If a - new parallel anchor had to be created, then returns the new parallel anchor. In case the - addition is unfeasible -- because a parallel setup is not possible, returns 0. + new parallel anchor had to be created, then returns the new parallel anchor. If a parallel anchor + had to be created and it results in an unfeasible setup, \a feasible is set to false, otherwise + true. */ static AnchorData *addAnchorMaybeParallel(Graph<AnchorVertex, AnchorData> *g, - AnchorData *newAnchor) + AnchorData *newAnchor, bool *feasible) { - bool feasible = true; + *feasible = true; // If already exists one anchor where newAnchor is supposed to be, we create a parallel // anchor. @@ -544,12 +521,12 @@ static AnchorData *addAnchorMaybeParallel(Graph<AnchorVertex, AnchorData> *g, // At this point we can identify that the parallel anchor is not feasible, e.g. one // anchor minimum size is bigger than the other anchor maximum size. - feasible = parallel->refreshSizeHints_helper(0, false); + *feasible = parallel->refreshSizeHints_helper(0, false); newAnchor = parallel; } g->createEdge(newAnchor->from, newAnchor->to, newAnchor); - return feasible ? newAnchor : 0; + return newAnchor; } @@ -663,7 +640,7 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) orientation == Horizontal ? "Horizontal" : "Vertical"); #endif - if (!graph[orientation].rootVertex()) + if (!layoutFirstVertex[orientation]) return true; bool dirty; @@ -700,7 +677,7 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP QSet<AnchorVertex *> visited; QStack<QPair<AnchorVertex *, AnchorVertex *> > stack; - stack.push(qMakePair(static_cast<AnchorVertex *>(0), g.rootVertex())); + stack.push(qMakePair(static_cast<AnchorVertex *>(0), layoutFirstVertex[orientation])); QVector<AnchorVertex*> candidates; bool candidatesForward; @@ -835,13 +812,21 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP // Add the sequence to the graph. // + // ### At this point we assume that if some parallel anchor will be created because + // of the new sequence, the other anchor will not be a center anchor (since we + // not deal with that case yet). This assumption will break once we start simplifying + // vertices. + AnchorData *possibleParallel = g.edgeData(beforeSequence, afterSequence); + Q_ASSERT(!possibleParallel || !possibleParallel->isCenterAnchor); + AnchorData *sequence = createSequence(&g, beforeSequence, candidates, afterSequence); // If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll // create a parallel anchor between the new sequence and the old anchor. - AnchorData *newAnchor = addAnchorMaybeParallel(&g, sequence); + bool newFeasible; + AnchorData *newAnchor = addAnchorMaybeParallel(&g, sequence, &newFeasible); - if (!newAnchor) { + if (!newFeasible) { *feasible = false; return false; } @@ -959,9 +944,10 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() data->maxSize = QWIDGETSIZE_MAX; data->skipInPreferred = 1; - // Set the Layout Left edge as the root of the horizontal graph. - AnchorVertex *v = internalVertex(layout, Qt::AnchorLeft); - graph[Horizontal].setRootVertex(v); + // Save a reference to layout vertices + layoutFirstVertex[Horizontal] = internalVertex(layout, Qt::AnchorLeft); + layoutCentralVertex[Horizontal] = 0; + layoutLastVertex[Horizontal] = internalVertex(layout, Qt::AnchorRight); // Vertical data = new AnchorData; @@ -970,17 +956,18 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() data->maxSize = QWIDGETSIZE_MAX; data->skipInPreferred = 1; - // Set the Layout Top edge as the root of the vertical graph. - v = internalVertex(layout, Qt::AnchorTop); - graph[Vertical].setRootVertex(v); + // Save a reference to layout vertices + layoutFirstVertex[Vertical] = internalVertex(layout, Qt::AnchorTop); + layoutCentralVertex[Vertical] = 0; + layoutLastVertex[Vertical] = internalVertex(layout, Qt::AnchorBottom); } void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() { Q_Q(QGraphicsAnchorLayout); - Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL); - Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL); + Q_ASSERT(!internalVertex(q, Qt::AnchorHorizontalCenter)); + Q_ASSERT(!internalVertex(q, Qt::AnchorVerticalCenter)); removeAnchor_helper(internalVertex(q, Qt::AnchorLeft), internalVertex(q, Qt::AnchorRight)); @@ -1019,6 +1006,8 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) void QGraphicsAnchorLayoutPrivate::createCenterAnchors( QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge) { + Q_Q(QGraphicsAnchorLayout); + Orientation orientation; switch (centerEdge) { case Qt::AnchorHorizontalCenter: @@ -1061,24 +1050,33 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( c->variables.insert(data, 1.0); addAnchor_helper(item, firstEdge, item, centerEdge, data); data->isCenterAnchor = true; + data->dependency = AnchorData::Master; data->refreshSizeHints(0); data = new AnchorData; c->variables.insert(data, -1.0); addAnchor_helper(item, centerEdge, item, lastEdge, data); data->isCenterAnchor = true; + data->dependency = AnchorData::Slave; data->refreshSizeHints(0); itemCenterConstraints[orientation].append(c); // Remove old one removeAnchor_helper(first, last); + + if (item == q) { + layoutCentralVertex[orientation] = internalVertex(q, centerEdge); + } + } void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute) { + Q_Q(QGraphicsAnchorLayout); + Orientation orientation; switch (centerEdge) { case Qt::AnchorHorizontalCenter: @@ -1151,6 +1149,10 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( // by this time, the center vertex is deleted and merged into a non-centered internal anchor removeAnchor_helper(first, internalVertex(item, lastEdge)); } + + if (item == q) { + layoutCentralVertex[orientation] = 0; + } } @@ -1724,8 +1726,6 @@ QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints) void QGraphicsAnchorLayoutPrivate::calculateGraphs( QGraphicsAnchorLayoutPrivate::Orientation orientation) { - Q_Q(QGraphicsAnchorLayout); - #if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) lastCalculationUsedSimplex[orientation] = false; #endif @@ -1773,7 +1773,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( // For minimum and maximum, use the path between the two layout sides as the // objective function. - AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation)); + AnchorVertex *v = layoutLastVertex[orientation]; GraphPath trunkPath = graphPaths[orientation].value(v); bool feasible = calculateTrunk(orientation, trunkPath, trunkConstraints, trunkVariables); @@ -1836,27 +1836,19 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const if (feasible) { solvePreferred(allConstraints, variables); - // Note that we don't include the sizeHintConstraints, since they - // have a different logic for solveExpanding(). - solveExpanding(constraints, variables); - - // Calculate and set the preferred and expanding sizes for the layout, + // Calculate and set the preferred size for the layout, // from the edge sizes that were calculated above. qreal pref(0.0); - qreal expanding(0.0); foreach (const AnchorData *ad, path.positives) { pref += ad->sizeAtPreferred; - expanding += ad->sizeAtExpanding; } foreach (const AnchorData *ad, path.negatives) { pref -= ad->sizeAtPreferred; - expanding -= ad->sizeAtExpanding; } sizeHints[orientation][Qt::MinimumSize] = min; sizeHints[orientation][Qt::PreferredSize] = pref; sizeHints[orientation][Qt::MaximumSize] = max; - sizeAtExpanding[orientation] = expanding; } qDeleteAll(sizeHintConstraints); @@ -1870,13 +1862,11 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const AnchorData *ad = path.positives.toList()[0]; ad->sizeAtMinimum = ad->minSize; ad->sizeAtPreferred = ad->prefSize; - ad->sizeAtExpanding = ad->expSize; ad->sizeAtMaximum = ad->maxSize; sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum; sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred; sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum; - sizeAtExpanding[orientation] = ad->sizeAtExpanding; } #if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) @@ -1902,7 +1892,6 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra AnchorData *ad = variables[j]; Q_ASSERT(ad); ad->sizeAtMinimum = ad->sizeAtPreferred; - ad->sizeAtExpanding = ad->sizeAtPreferred; ad->sizeAtMaximum = ad->sizeAtPreferred; } } @@ -1955,7 +1944,7 @@ void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) QSet<AnchorData *> visited; - AnchorVertex *root = graph[orientation].rootVertex(); + AnchorVertex *root = layoutFirstVertex[orientation]; graphPaths[orientation].insert(root, GraphPath()); @@ -2041,16 +2030,45 @@ void QGraphicsAnchorLayoutPrivate::updateAnchorSizes(Orientation orientation) QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints( const QList<AnchorData *> &anchors) { + if (anchors.isEmpty()) + return QList<QSimplexConstraint *>(); + + // Look for the layout edge. That can be either the first half in case the + // layout is split in two, or the whole layout anchor. + Orientation orient = Orientation(anchors.first()->orientation); + AnchorData *layoutEdge = 0; + if (layoutCentralVertex[orient]) { + layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutCentralVertex[orient]); + } else { + layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutLastVertex[orient]); + + // If maxSize is less then "infinite", that means there are other anchors + // grouped together with this one. We can't ignore its maximum value so we + // set back the variable to NULL to prevent the continue condition from being + // satisfied in the loop below. + if (layoutEdge->maxSize < QWIDGETSIZE_MAX) + layoutEdge = 0; + } + + // For each variable, create constraints based on size hints QList<QSimplexConstraint *> anchorConstraints; + bool unboundedProblem = true; for (int i = 0; i < anchors.size(); ++i) { AnchorData *ad = anchors[i]; + // Anchors that have their size directly linked to another one don't need constraints + // For exammple, the second half of an item has exactly the same size as the first half + // thus constraining the latter is enough. + if (ad->dependency == AnchorData::Slave) + continue; + if ((ad->minSize == ad->maxSize) || qFuzzyCompare(ad->minSize, ad->maxSize)) { QSimplexConstraint *c = new QSimplexConstraint; c->variables.insert(ad, 1.0); c->constant = ad->minSize; c->ratio = QSimplexConstraint::Equal; anchorConstraints += c; + unboundedProblem = false; } else { QSimplexConstraint *c = new QSimplexConstraint; c->variables.insert(ad, 1.0); @@ -2058,14 +2076,30 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin c->ratio = QSimplexConstraint::MoreOrEqual; anchorConstraints += c; + // We avoid adding restrictions to the layout internal anchors. That's + // to prevent unnecessary fair distribution from happening due to this + // artificial restriction. + if (ad == layoutEdge) + continue; + c = new QSimplexConstraint; c->variables.insert(ad, 1.0); c->constant = ad->maxSize; c->ratio = QSimplexConstraint::LessOrEqual; anchorConstraints += c; + unboundedProblem = false; } } + // If no upper boundary restriction was added, add one to avoid unbounded problem + if (unboundedProblem) { + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(layoutEdge, 1.0); + c->constant = QWIDGETSIZE_MAX; + c->ratio = QSimplexConstraint::LessOrEqual; + anchorConstraints += c; + } + return anchorConstraints; } @@ -2075,30 +2109,18 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin QList< QList<QSimplexConstraint *> > QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) { - Q_Q(QGraphicsAnchorLayout); - - // Find layout vertices and edges for the current orientation. - AnchorVertex *layoutFirstVertex = \ - internalVertex(q, pickEdge(Qt::AnchorLeft, orientation)); - - AnchorVertex *layoutCentralVertex = \ - internalVertex(q, pickEdge(Qt::AnchorHorizontalCenter, orientation)); - - AnchorVertex *layoutLastVertex = \ - internalVertex(q, pickEdge(Qt::AnchorRight, orientation)); + Q_ASSERT(layoutFirstVertex[orientation] && layoutLastVertex[orientation]); - Q_ASSERT(layoutFirstVertex && layoutLastVertex); - - AnchorData *edgeL1 = NULL; - AnchorData *edgeL2 = NULL; + AnchorData *edgeL1 = 0; + AnchorData *edgeL2 = 0; // The layout may have a single anchor between Left and Right or two half anchors // passing through the center - if (layoutCentralVertex) { - edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutCentralVertex); - edgeL2 = graph[orientation].edgeData(layoutCentralVertex, layoutLastVertex); + if (layoutCentralVertex[orientation]) { + edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutCentralVertex[orientation]); + edgeL2 = graph[orientation].edgeData(layoutCentralVertex[orientation], layoutLastVertex[orientation]); } else { - edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutLastVertex); + edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutLastVertex[orientation]); } QLinkedList<QSimplexConstraint *> remainingConstraints; @@ -2288,7 +2310,7 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( QSet<AnchorVertex *> visited; // Get root vertex - AnchorVertex *root = graph[orientation].rootVertex(); + AnchorVertex *root = layoutFirstVertex[orientation]; root->distance = 0; visited.insert(root); @@ -2343,7 +2365,6 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( result = getFactor(current, sizeHints[orientation][Qt::MinimumSize], sizeHints[orientation][Qt::PreferredSize], - sizeAtExpanding[orientation], sizeHints[orientation][Qt::MaximumSize]); interpolationInterval[orientation] = result.first; @@ -2358,7 +2379,6 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( - minimum size, - preferred size, - - size when all expanding anchors are expanded, - maximum size. These three key values are calculated in advance using linear @@ -2378,7 +2398,7 @@ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, interpolationProgress[orientation]); qreal edgeDistance = interpolate(factor, edge->sizeAtMinimum, edge->sizeAtPreferred, - edge->sizeAtExpanding, edge->sizeAtMaximum); + edge->sizeAtMaximum); Q_ASSERT(edge->from == base || edge->to == base); @@ -2473,8 +2493,9 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> QList<AnchorData *> variables = getVariables(constraints); for (int i = 0; i < variables.size(); ++i) { AnchorData *ad = static_cast<AnchorData *>(variables[i]); - Q_ASSERT(ad->result >= ad->minSize || qFuzzyCompare(ad->result, ad->minSize)); ad->sizeAtMinimum = ad->result; + Q_ASSERT(ad->sizeAtMinimum >= ad->minSize || + qAbs(ad->sizeAtMinimum - ad->minSize) < 0.00000001); } // Calculate maximum values @@ -2483,8 +2504,9 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> // Save sizeAtMaximum results for (int i = 0; i < variables.size(); ++i) { AnchorData *ad = static_cast<AnchorData *>(variables[i]); - Q_ASSERT(ad->result <= ad->maxSize || qFuzzyCompare(ad->result, ad->maxSize)); ad->sizeAtMaximum = ad->result; + // Q_ASSERT(ad->sizeAtMaximum <= ad->maxSize || + // qAbs(ad->sizeAtMaximum - ad->maxSize) < 0.00000001); } } return feasible; @@ -2563,139 +2585,6 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint /*! \internal - Calculate the "expanding" keyframe - - This new keyframe sits between the already existing sizeAtPreferred and - sizeAtMaximum keyframes. Its goal is to modify the interpolation between - the latter as to respect the "expanding" size policy of some anchors. - - Previously all items would be subject to a linear interpolation between - sizeAtPreferred and sizeAtMaximum values. This will change now, the - expanding anchors will change their size before the others. To calculate - this keyframe we use the following logic: - - 1) Ask each anchor for their desired expanding size (ad->expSize), this - value depends on the anchor expanding property in the following way: - - - Expanding normal anchors want to grow towards their maximum size - - Non-expanding normal anchors want to remain at their preferred size. - - Sequential anchors wants to grow towards a size that is calculated by: - summarizing it's child anchors, where it will use preferred size for non-expanding anchors - and maximum size for expanding anchors. - - Parallel anchors want to grow towards the smallest maximum size of all the expanding anchors. - - 2) Clamp their desired values to the value they assume in the neighbour - keyframes (sizeAtPreferred and sizeAtExpanding) - - 3) Run simplex with a setup that ensures the following: - - a. Anchors will change their value from their sizeAtPreferred towards - their sizeAtMaximum as much as required to ensure that ALL anchors - reach their respective "desired" expanding sizes. - - b. No anchors will change their value beyond what is NEEDED to satisfy - the requirement above. - - The final result is that, at the "expanding" keyframe expanding anchors - will grow and take with them all anchors that are parallel to them. - However, non-expanding anchors will remain at their preferred size unless - they are forced to grow by a parallel expanding anchor. - - Note: For anchors where the sizeAtPreferred is bigger than sizeAtMaximum, - the visual effect when the layout grows from its preferred size is - the following: Expanding anchors will keep their size while non - expanding ones will shrink. Only after non-expanding anchors have - shrinked all the way, the expanding anchors will start to shrink too. -*/ -void QGraphicsAnchorLayoutPrivate::solveExpanding(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables) -{ - QList<QSimplexConstraint *> itemConstraints; - QSimplexConstraint *objective = new QSimplexConstraint; - bool hasExpanding = false; - - // Construct the simplex constraints and objective - for (int i = 0; i < variables.size(); ++i) { - // For each anchor - AnchorData *ad = variables[i]; - - // Clamp the desired expanding size - qreal upperBoundary = qMax(ad->sizeAtPreferred, ad->sizeAtMaximum); - qreal lowerBoundary = qMin(ad->sizeAtPreferred, ad->sizeAtMaximum); - qreal boundedExpSize = qBound(lowerBoundary, ad->expSize, upperBoundary); - - // Expanding anchors are those that want to move from their preferred size - if (boundedExpSize != ad->sizeAtPreferred) - hasExpanding = true; - - // Lock anchor between boundedExpSize and sizeAtMaximum (ensure 3.a) - if (boundedExpSize == ad->sizeAtMaximum || qFuzzyCompare(boundedExpSize, ad->sizeAtMaximum)) { - // The interval has only one possible value, we can use an "Equal" - // constraint and don't need to add this variable to the objective. - QSimplexConstraint *itemC = new QSimplexConstraint; - itemC->ratio = QSimplexConstraint::Equal; - itemC->variables.insert(ad, 1.0); - itemC->constant = boundedExpSize; - itemConstraints << itemC; - } else { - // Add MoreOrEqual and LessOrEqual constraints. - QSimplexConstraint *itemC = new QSimplexConstraint; - itemC->ratio = QSimplexConstraint::MoreOrEqual; - itemC->variables.insert(ad, 1.0); - itemC->constant = qMin(boundedExpSize, ad->sizeAtMaximum); - itemConstraints << itemC; - - itemC = new QSimplexConstraint; - itemC->ratio = QSimplexConstraint::LessOrEqual; - itemC->variables.insert(ad, 1.0); - itemC->constant = qMax(boundedExpSize, ad->sizeAtMaximum); - itemConstraints << itemC; - - // Create objective to avoid the anchors from moving away from - // the preferred size more than the needed amount. (ensure 3.b) - // The objective function is the distance between sizeAtPreferred - // and sizeAtExpanding, it will be minimized. - if (ad->sizeAtExpanding < ad->sizeAtMaximum) { - // Try to shrink this variable towards its sizeAtPreferred value - objective->variables.insert(ad, 1.0); - } else { - // Try to grow this variable towards its sizeAtPreferred value - objective->variables.insert(ad, -1.0); - } - } - } - - // Solve - if (hasExpanding == false) { - // If no anchors are expanding, we don't need to run the simplex - // Set all variables to their preferred size - for (int i = 0; i < variables.size(); ++i) { - variables[i]->sizeAtExpanding = variables[i]->sizeAtPreferred; - } - } else { - // Run simplex - QSimplex simplex; - - // Satisfy expanding (3.a) - bool feasible = simplex.setConstraints(constraints + itemConstraints); - Q_ASSERT(feasible); - - // Reduce damage (3.b) - simplex.setObjective(objective); - simplex.solveMin(); - - // Collect results - for (int i = 0; i < variables.size(); ++i) { - variables[i]->sizeAtExpanding = variables[i]->result; - } - } - - delete objective; - qDeleteAll(itemConstraints); -} - -/*! - \internal Returns true if there are no arrangement that satisfies all constraints. Otherwise returns false. diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 7dd0d65..1e11ee2 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -150,14 +150,21 @@ struct AnchorData : public QSimplexVariable { Parallel }; + enum Dependency { + Independent = 0, + Master, + Slave + }; + AnchorData() : QSimplexVariable(), item(0), from(0), to(0), - minSize(0), prefSize(0), expSize(0), maxSize(0), + minSize(0), prefSize(0), maxSize(0), sizeAtMinimum(0), sizeAtPreferred(0), - sizeAtExpanding(0), sizeAtMaximum(0), + sizeAtMaximum(0), graphicsAnchor(0), skipInPreferred(0), type(Normal), hasSize(true), isLayoutAnchor(false), - isCenterAnchor(false), orientation(0) {} + isCenterAnchor(false), orientation(0), + dependency(Independent) {} virtual void updateChildrenSizes() {} virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); @@ -194,7 +201,6 @@ struct AnchorData : public QSimplexVariable { // size. qreal minSize; qreal prefSize; - qreal expSize; qreal maxSize; // These attributes define which sizes should that anchor be in when the @@ -202,7 +208,6 @@ struct AnchorData : public QSimplexVariable { // calculated by the Simplex solver based on the current layout setup. qreal sizeAtMinimum; qreal sizeAtPreferred; - qreal sizeAtExpanding; qreal sizeAtMaximum; QGraphicsAnchor *graphicsAnchor; @@ -212,6 +217,7 @@ struct AnchorData : public QSimplexVariable { uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor uint isCenterAnchor : 1; uint orientation : 1; + uint dependency : 2; // either Independent, Master or Slave }; #ifdef QT_DEBUG @@ -337,8 +343,7 @@ public: // Interval represents which interpolation interval are we operating in. enum Interval { MinToPreferred = 0, - PreferredToExpanding, - ExpandingToMax + PreferredToMax }; // Several structures internal to the layout are duplicated to handle @@ -479,8 +484,6 @@ public: GraphPath path, qreal *min, qreal *max); bool solvePreferred(const QList<QSimplexConstraint *> &constraints, const QList<AnchorData *> &variables); - void solveExpanding(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables); bool hasConflicts() const; #ifdef QT_DEBUG @@ -491,7 +494,6 @@ public: qreal spacings[NOrientations]; // Size hints from simplex engine qreal sizeHints[2][3]; - qreal sizeAtExpanding[2]; // Items QVector<QGraphicsLayoutItem *> items; @@ -504,6 +506,10 @@ public: // Internal graph of anchorage points and anchors, for both orientations Graph<AnchorVertex, AnchorData> graph[2]; + AnchorVertex *layoutFirstVertex[2]; + AnchorVertex *layoutCentralVertex[2]; + AnchorVertex *layoutLastVertex[2]; + // Graph paths and constraints, for both orientations QMultiHash<AnchorVertex *, GraphPath> graphPaths[2]; QList<QSimplexConstraint *> constraints[2]; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2fd499d..a236b14 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -386,6 +386,12 @@ introduced in Qt 4.6. \omitvalue ItemIsFocusScope Internal only (for now). + + \value ItemSendsScenePositionChanges The item enables itemChange() + notifications for ItemScenePositionHasChanged. For performance reasons, + these notifications are disabled by default. You must enable this flag + to receive notifications for scene position changes. This flag was + introduced in Qt 4.6. */ /*! @@ -562,6 +568,14 @@ \value ItemOpacityHasChanged The item's opacity has changed. The value argument is the new opacity (i.e., a double). Do not call setOpacity() as this notification is delivered. The return value is ignored. + + \value ItemScenePositionHasChanged The item's scene position has changed. + This notification is sent if the ItemSendsScenePositionChanges flag is + enabled, and after the item's scene position has changed (i.e., the + position or transformation of the item itself or the position or + transformation of any ancestor has changed). The value argument is the + new scene position (the same as scenePos()), and QGraphicsItem ignores + the return value for this notification (i.e., a read-only notification). */ /*! @@ -990,6 +1004,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (scene) { // Deliver the change to the index scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + + // Disable scene pos notifications for old ancestors + if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) + scene->d_func()->setScenePosItemEnabled(q, false); } if (subFocusItem && parent) { @@ -1084,10 +1102,15 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) parent->d_ptr->addChild(q); parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant); - if (!implicitUpdate && scene) { - scene->d_func()->markDirty(q_ptr, QRect(), - /*invalidateChildren=*/false, - /*maybeDirtyClipPath=*/true); + if (scene) { + if (!implicitUpdate) + scene->d_func()->markDirty(q_ptr, QRect(), + /*invalidateChildren=*/false, + /*maybeDirtyClipPath=*/true); + + // Re-enable scene pos notifications for new ancestors + if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) + scene->d_func()->setScenePosItemEnabled(q, true); } // Inherit ancestor flags from the new parent. @@ -1336,7 +1359,9 @@ QGraphicsItem::~QGraphicsItem() d_ptr->setParentItemHelper(0); } +#ifndef QT_NO_GRAPHICSEFFECT delete d_ptr->graphicsEffect; +#endif //QT_NO_GRAPHICSEFFECT if (d_ptr->transformData) { for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) { QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i); @@ -1746,6 +1771,12 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) } if (d_ptr->scene) { + if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) { + if (flags & ItemSendsScenePositionChanges) + d_ptr->scene->d_func()->registerScenePosItem(this); + else + d_ptr->scene->d_func()->unregisterScenePosItem(this); + } d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*maybeDirtyClipPath*/true); @@ -2506,7 +2537,9 @@ void QGraphicsItem::setOpacity(qreal opacity) // Update. if (d_ptr->scene) { +#ifndef QT_NO_GRAPHICSEFFECT d_ptr->invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*maybeDirtyClipPath=*/false, @@ -2523,6 +2556,7 @@ void QGraphicsItem::setOpacity(qreal opacity) \since 4.6 */ +#ifndef QT_NO_GRAPHICSEFFECT QGraphicsEffect *QGraphicsItem::graphicsEffect() const { return d_ptr->graphicsEffect; @@ -2569,6 +2603,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) prepareGeometryChange(); } +#endif //QT_NO_GRAPHICSEFFECT /*! \internal @@ -2582,6 +2617,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) */ QRectF QGraphicsItemPrivate::effectiveBoundingRect() const { +#ifndef QT_NO_GRAPHICSEFFECT QGraphicsEffect *effect = graphicsEffect; QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : q_ptr->boundingRect(); if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) @@ -2598,6 +2634,10 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect() const } return brect; +#else //QT_NO_GRAPHICSEFFECT + return q_ptr->boundingRect(); +#endif //QT_NO_GRAPHICSEFFECT + } /*! @@ -2951,7 +2991,7 @@ bool QGraphicsItem::hasFocus() const { if (d_ptr->focusProxy) return d_ptr->focusProxy->hasFocus(); - return (d_ptr->scene && d_ptr->scene->focusItem() == this); + return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this); } /*! @@ -3412,6 +3452,7 @@ void QGraphicsItem::setPos(const QPointF &pos) // Send post-notification. itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); + d_ptr->sendScenePosChange(); } /*! @@ -4022,6 +4063,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Send post-notification. itemChange(ItemTransformHasChanged, newTransformVariant); + d_ptr->sendScenePosChange(); } /*! @@ -4246,6 +4288,24 @@ void QGraphicsItemPrivate::ensureSequentialSiblingIndex() } /*! + \internal +*/ +inline void QGraphicsItemPrivate::sendScenePosChange() +{ + Q_Q(QGraphicsItem); + if (scene) { + if (flags & QGraphicsItem::ItemSendsScenePositionChanges) + q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos()); + if (scenePosDescendants) { + foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) { + if (q->isAncestorOf(item)) + item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos()); + } + } + } +} + +/*! \since 4.6 Stacks this item before \a sibling, which must be a sibling item (i.e., the @@ -4296,6 +4356,12 @@ void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) ++index; } d_ptr->siblingIndex = siblingIndex; + for (int i = 0; i < siblings->size(); ++i) { + int &index = siblings->at(i)->d_ptr->siblingIndex; + if (i != siblingIndex && index >= siblingIndex && index <= myIndex) + siblings->at(i)->d_ptr->siblingOrderChange(); + } + d_ptr->siblingOrderChange(); } } @@ -4977,6 +5043,7 @@ int QGraphicsItemPrivate::depth() const /*! \internal */ +#ifndef QT_NO_GRAPHICSEFFECT void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() { QGraphicsItemPrivate *itemPrivate = this; @@ -4989,6 +5056,7 @@ void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() } } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); } +#endif //QT_NO_GRAPHICSEFFECT /*! \internal @@ -5293,6 +5361,16 @@ void QGraphicsItemPrivate::subFocusItemChange() /*! \internal + Subclasses can reimplement this function to be notified when its + siblingIndex order is changed. +*/ +void QGraphicsItemPrivate::siblingOrderChange() +{ +} + +/*! + \internal + Tells us if it is a proxy widget */ bool QGraphicsItemPrivate::isProxyWidget() const @@ -5324,7 +5402,9 @@ void QGraphicsItem::update(const QRectF &rect) return; // Make sure we notify effects about invalidated source. +#ifndef QT_NO_GRAPHICSEFFECT d_ptr->invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT if (CacheMode(d_ptr->cacheMode) != NoCache) { // Invalidate cache. @@ -10678,6 +10758,7 @@ int QGraphicsItemGroup::type() const return Type; } +#ifndef QT_NO_GRAPHICSEFFECT QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); @@ -10817,6 +10898,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP return pixmap; } +#endif //QT_NO_GRAPHICSEFFECT #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, QGraphicsItem *item) @@ -10940,6 +11022,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change) case QGraphicsItem::ItemOpacityHasChanged: str = "ItemOpacityHasChanged"; break; + case QGraphicsItem::ItemScenePositionHasChanged: + str = "ItemScenePositionHasChanged"; + break; } debug << str; return debug; @@ -10997,6 +11082,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemIsFocusScope: str = "ItemIsFocusScope"; break; + case QGraphicsItem::ItemSendsScenePositionChanges: + str = "ItemSendsScenePositionChanges"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index f091e34..8bbe9f1 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -105,7 +105,8 @@ public: ItemAcceptsInputMethod = 0x1000, ItemNegativeZStacksBehindParent = 0x2000, ItemIsPanel = 0x4000, - ItemIsFocusScope = 0x8000 // internal + ItemIsFocusScope = 0x8000, // internal + ItemSendsScenePositionChanges = 0x10000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) @@ -137,7 +138,8 @@ public: ItemZValueChange, ItemZValueHasChanged, ItemOpacityChange, - ItemOpacityHasChanged + ItemOpacityHasChanged, + ItemScenePositionHasChanged }; enum CacheMode { @@ -225,9 +227,11 @@ public: qreal effectiveOpacity() const; void setOpacity(qreal opacity); +#ifndef QT_NO_GRAPHICSEFFECT // Effect QGraphicsEffect *graphicsEffect() const; void setGraphicsEffect(QGraphicsEffect *effect); +#endif //QT_NO_GRAPHICSEFFECT Qt::MouseButtons acceptedMouseButtons() const; void setAcceptedMouseButtons(Qt::MouseButtons buttons); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 51d2ffd..afc2198 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -179,6 +179,7 @@ public: holesInSiblingIndex(0), sequentialOrdering(1), updateDueToGraphicsEffect(0), + scenePosDescendants(0), globalStackingOrder(-1), q_ptr(0) { @@ -223,7 +224,9 @@ public: bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; int depth() const; +#ifndef QT_NO_GRAPHICSEFFECT void invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT void invalidateDepthRecursively(); void resolveDepth(); void addChild(QGraphicsItem *child); @@ -429,6 +432,8 @@ public: inline void ensureSortedChildren(); static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); void ensureSequentialSiblingIndex(); + inline void sendScenePosChange(); + virtual void siblingOrderChange(); QPainterPath cachedClipPath; QRectF childrenBoundingRect; @@ -483,7 +488,7 @@ public: // Packed 32 bits quint32 fullUpdatePending : 1; - quint32 flags : 16; + quint32 flags : 17; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; @@ -498,14 +503,15 @@ public: quint32 sceneTransformTranslateOnly : 1; quint32 notifyBoundingRectChanged : 1; quint32 notifyInvalidated : 1; - quint32 mouseSetsFocus : 1; // New 32 bits + quint32 mouseSetsFocus : 1; quint32 explicitActivate : 1; quint32 wantsActive : 1; quint32 holesInSiblingIndex : 1; quint32 sequentialOrdering : 1; quint32 updateDueToGraphicsEffect : 1; + quint32 scenePosDescendants : 1; // Optional stacking order int globalStackingOrder; @@ -577,6 +583,7 @@ struct QGraphicsItemPaintInfo quint32 drawItem : 1; }; +#ifndef QT_NO_GRAPHICSEFFECT class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate { public: @@ -632,7 +639,7 @@ public: QGraphicsItemPaintInfo *info; QTransform lastEffectTransform; }; - +#endif //QT_NO_GRAPHICSEFFECT /*! Returns true if \a item1 is on top of \a item2. diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp index 5684f0e..cb68741 100644 --- a/src/gui/graphicsview/qgraphicslinearlayout.cpp +++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp @@ -542,6 +542,9 @@ void QGraphicsLinearLayout::invalidate() QGraphicsLayout::invalidate(); } +/*! + \internal +*/ void QGraphicsLinearLayout::dump(int indent) const { #ifdef QT_DEBUG diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dc036f8..d1845c2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -294,6 +294,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() needSortTopLevelItems(true), holesInTopLevelSiblingIndex(false), topLevelSequentialOrdering(true), + scenePosDescendantsUpdatePending(false), stickyFocus(false), hasFocus(false), focusItem(0), @@ -488,6 +489,55 @@ void QGraphicsScenePrivate::_q_processDirtyItems() /*! \internal +*/ +void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled) +{ + QGraphicsItem *p = item->d_ptr->parent; + while (p) { + p->d_ptr->scenePosDescendants = enabled; + p = p->d_ptr->parent; + } + if (!enabled && !scenePosDescendantsUpdatePending) { + scenePosDescendantsUpdatePending = true; + QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection); + } +} + +/*! + \internal +*/ +void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item) +{ + scenePosItems.insert(item); + setScenePosItemEnabled(item, true); +} + +/*! + \internal +*/ +void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item) +{ + scenePosItems.remove(item); + setScenePosItemEnabled(item, false); +} + +/*! + \internal +*/ +void QGraphicsScenePrivate::_q_updateScenePosDescendants() +{ + foreach (QGraphicsItem *item, scenePosItems) { + QGraphicsItem *p = item->d_ptr->parent; + while (p) { + p->d_ptr->scenePosDescendants = 1; + p = p->d_ptr->parent; + } + } + scenePosDescendantsUpdatePending = false; +} + +/*! + \internal Schedules an item for removal. This function leaves some stale indexes around in the BSP tree if called from the item's destructor; these will @@ -523,6 +573,9 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) widget->d_func()->fixFocusChainBeforeReparenting(0, 0); } + if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) + unregisterScenePosItem(item); + item->d_func()->scene = 0; //We need to remove all children first because they might use their parent @@ -2293,8 +2346,9 @@ void QGraphicsScene::clear() // NB! We have to clear the index before deleting items; otherwise the // index might try to access dangling item pointers. d->index->clear(); - const QList<QGraphicsItem *> items = d->topLevelItems; - qDeleteAll(items); + // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items + while (!d->topLevelItems.isEmpty()) + delete d->topLevelItems.first(); Q_ASSERT(d->topLevelItems.isEmpty()); d->lastItemCount = 0; d->allItemsIgnoreHoverEvents = true; @@ -2540,6 +2594,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) } } + if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) + d->registerScenePosItem(item); + // Ensure that newly added items that have subfocus set, gain // focus automatically if there isn't a focus item already. if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) @@ -2826,18 +2883,20 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) } /*! - Returns the scene's current focus item, or 0 if no item currently has - focus. + When the scene is active, this functions returns the scene's current focus + item, or 0 if no item currently has focus. When the scene is inactive, this + functions returns the item that will gain input focus when the scene becomes + active. The focus item receives keyboard input when the scene receives a key event. - \sa setFocusItem(), QGraphicsItem::hasFocus() + \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive() */ QGraphicsItem *QGraphicsScene::focusItem() const { Q_D(const QGraphicsScene); - return d->focusItem; + return isActive() ? d->focusItem : d->lastFocusItem; } /*! @@ -4577,6 +4636,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (itemHasChildren && itemClipsChildrenToShape) ENSURE_TRANSFORM_PTR; +#ifndef QT_NO_GRAPHICSEFFECT if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, @@ -4599,7 +4659,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * item->d_ptr->graphicsEffect->draw(painter, source); painter->setWorldTransform(restoreTransform); sourced->info = 0; - } else { + } else +#endif //QT_NO_GRAPHICSEFFECT + { draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, effectTransform, wasDirtyParentSceneTransform, drawItem); } @@ -4768,10 +4830,12 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b QGraphicsItem *p = item->d_ptr->parent; while (p) { p->d_ptr->dirtyChildren = 1; +#ifndef QT_NO_GRAPHICSEFFECT if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { p->d_ptr->dirty = 1; p->d_ptr->fullUpdatePending = 1; } +#endif //QT_NO_GRAPHICSEFFECT p = p->d_ptr->parent; } } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index d6d48d7..a47574e 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -299,6 +299,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) + Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants()) friend class QGraphicsItem; friend class QGraphicsItemPrivate; friend class QGraphicsView; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f8db084..fdec466 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -122,6 +122,13 @@ public: void _q_processDirtyItems(); + QSet<QGraphicsItem *> scenePosItems; + bool scenePosDescendantsUpdatePending; + void setScenePosItemEnabled(QGraphicsItem *item, bool enabled); + void registerScenePosItem(QGraphicsItem *item); + void unregisterScenePosItem(QGraphicsItem *item); + void _q_updateScenePosDescendants(); + void removeItemHelper(QGraphicsItem *item); QBrush backgroundBrush; @@ -234,6 +241,7 @@ public: item->d_ptr->fullUpdatePending = 0; item->d_ptr->ignoreVisible = 0; item->d_ptr->ignoreOpacity = 0; +#ifndef QT_NO_GRAPHICSEFFECT QGraphicsEffect::ChangeFlags flags; if (item->d_ptr->notifyBoundingRectChanged) { flags |= QGraphicsEffect::SourceBoundingRectChanged; @@ -243,12 +251,15 @@ public: flags |= QGraphicsEffect::SourceInvalidated; item->d_ptr->notifyInvalidated = 0; } +#endif //QT_NO_GRAPHICSEFFECT if (recursive) { for (int i = 0; i < item->d_ptr->children.size(); ++i) resetDirtyItem(item->d_ptr->children.at(i), recursive); } +#ifndef QT_NO_GRAPHICSEFFECT if (flags && item->d_ptr->graphicsEffect) item->d_ptr->graphicsEffect->sourceChanged(flags); +#endif //QT_NO_GRAPHICSEFFECT } inline void ensureSortedTopLevelItems() diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c88f678..87585a2 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1512,6 +1512,11 @@ void QGraphicsView::setScene(QGraphicsScene *scene) this, SLOT(updateSceneRect(QRectF))); d->scene->d_func()->removeView(this); d->connectedToScene = false; + + if (isActiveWindow() && isVisible()) { + QEvent windowDeactivate(QEvent::WindowDeactivate); + QApplication::sendEvent(d->scene, &windowDeactivate); + } } // Assign the new scene and update the contents (scrollbars, etc.)). @@ -1533,6 +1538,11 @@ void QGraphicsView::setScene(QGraphicsScene *scene) // enable touch events if any items is interested in them if (!d->scene->d_func()->allItemsIgnoreTouchEvents) d->viewport->setAttribute(Qt::WA_AcceptTouchEvents); + + if (isActiveWindow() && isVisible()) { + QEvent windowActivate(QEvent::WindowActivate); + QApplication::sendEvent(d->scene, &windowActivate); + } } else { d->recalculateContentSize(); } @@ -2638,6 +2648,19 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); QApplication::sendEvent(d->scene, event); break; + case QEvent::Show: + if (d->scene && isActiveWindow()) { + QEvent windowActivate(QEvent::WindowActivate); + QApplication::sendEvent(d->scene, &windowActivate); + } + break; + case QEvent::Hide: + // spontaneous event will generate a WindowDeactivate. + if (!event->spontaneous() && d->scene && isActiveWindow()) { + QEvent windowDeactivate(QEvent::WindowDeactivate); + QApplication::sendEvent(d->scene, &windowDeactivate); + } + break; case QEvent::Leave: // ### This is a temporary fix for until we get proper mouse grab // events. activeMouseGrabberItem should be set to 0 if we lose the @@ -3252,10 +3275,13 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Determine the exposed region d->exposedRegion = event->region(); + if (d->exposedRegion.isEmpty()) + d->exposedRegion = viewport()->rect(); QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); // Set up the painter QPainter painter(viewport()); + painter.setClipRect(event->rect(), Qt::IntersectClip); #ifndef QT_NO_RUBBERBAND if (d->rubberBanding && !d->rubberBandRect.isEmpty()) painter.save(); diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index d70a281..6f910c7 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -410,6 +410,27 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) */ /*! + \property QGraphicsWidget::minimumSize + \brief the minimum size of the widget + + \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize +*/ + +/*! + \property QGraphicsWidget::preferredSize + \brief the preferred size of the widget + + \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize +*/ + +/*! + \property QGraphicsWidget::maximumSize + \brief the maximum size of the widget + + \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize +*/ + +/*! Sets the widget's contents margins to \a left, \a top, \a right and \a bottom. diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 9c71140..38f72f0 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -74,6 +74,9 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) Q_PROPERTY(QSizeF size READ size WRITE resize) + Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) + Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) + Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy) Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp index 86b10b4..cd40f9e 100644 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -288,7 +288,7 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) // original problem. // Otherwise, we clean up our structures and report there is // no feasible solution. - if (valueAt(0, columns - 1) != 0.0) { + if ((valueAt(0, columns - 1) != 0.0) && (qAbs(valueAt(0, columns - 1)) > 0.00001)) { qWarning() << "QSimplex: No feasible solution!"; clearDataStructures(); return false; diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h index 084ad7f..a5816d1 100644 --- a/src/gui/graphicsview/qsimplex_p.h +++ b/src/gui/graphicsview/qsimplex_p.h @@ -107,7 +107,7 @@ struct QSimplexConstraint Q_ASSERT(constant > 0 || qFuzzyCompare(1, 1 + constant)); - if ((leftHandSide == constant) || qFuzzyCompare(1000 + leftHandSide, 1000 + constant)) + if ((leftHandSide == constant) || qAbs(leftHandSide - constant) < 0.00000001) return true; switch (ratio) { diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp index e081735..4b8d4b8 100644 --- a/src/gui/image/qbitmap.cpp +++ b/src/gui/image/qbitmap.cpp @@ -86,7 +86,7 @@ QT_BEGIN_NAMESPACE object. Just like the QPixmap class, QBitmap is optimized by the use of - implicit data sharing. For more information, see the {Implicit + implicit data sharing. For more information, see the \l {Implicit Data Sharing} documentation. \sa QPixmap, QImage, QImageReader, QImageWriter diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index c452b9a..dfeea76 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -639,13 +639,13 @@ void QPixmap::resize_helper(const QSize &s) QPixmap pm(QSize(w, h), data ? data->type : QPixmapData::PixmapType); bool uninit = false; #if defined(Q_WS_X11) - QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0; + QX11PixmapData *x11Data = data && data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0; if (x11Data) { pm.x11SetScreen(x11Data->xinfo.screen()); uninit = x11Data->flags & QX11PixmapData::Uninitialized; } #elif defined(Q_WS_MAC) - QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0; + QMacPixmapData *macData = data && data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0; if (macData) uninit = macData->uninit; #endif diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index e50cc8b..d83ef2c 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -53,6 +53,7 @@ #include "private/qpaintengineex_p.h" #include "private/qpaintengine_raster_p.h" +#ifndef QT_NO_GRAPHICSEFFECT QT_BEGIN_NAMESPACE class QPixmapFilterPrivate : public QObjectPrivate @@ -1107,3 +1108,5 @@ void QPixmapDropShadowFilter::draw(QPainter *p, } QT_END_NAMESPACE + +#endif //QT_NO_GRAPHICSEFFECT diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 6a96676..2573fc7 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -57,6 +57,7 @@ #include <QtGui/qpixmap.h> #include <QtGui/qgraphicseffect.h> +#ifndef QT_NO_GRAPHICSEFFECT QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -191,4 +192,5 @@ QT_END_NAMESPACE QT_END_HEADER +#endif //QT_NO_GRAPHICSEFFECT #endif // QPIXMAPFILTER_H diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 1531036..452aa75 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -65,10 +65,10 @@ QT_BEGIN_NAMESPACE -class Q_GUI_EXPORT QCoeFepInputContext : public QInputContext, - public MCoeFepAwareTextEditor, - public MCoeFepAwareTextEditor_Extension1, - public MObjectProvider +class QCoeFepInputContext : public QInputContext, + public MCoeFepAwareTextEditor, + public MCoeFepAwareTextEditor_Extension1, + public MObjectProvider { Q_OBJECT @@ -97,6 +97,7 @@ private: void applyHints(Qt::InputMethodHints hints); void applyFormat(QList<QInputMethodEvent::Attribute> *attributes); void queueInputCapabilitiesChanged(); + bool needsInputPanel(); private Q_SLOTS: void ensureInputCapabilitiesChanged(); diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 3f21bc3..25b2313 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -47,6 +47,7 @@ #include <private/qcore_symbian_p.h> #include <fepitfr.h> +#include <hal.h> #include <limits.h> // You only find these enumerations on SDK 5 onwards, so we need to provide our own @@ -153,6 +154,44 @@ QString QCoeFepInputContext::language() } } +bool QCoeFepInputContext::needsInputPanel() +{ + switch (QSysInfo::s60Version()) { + case QSysInfo::SV_S60_3_1: + case QSysInfo::SV_S60_3_2: + // There are no touch phones for pre-5.0 SDKs. + return false; +#ifdef Q_CC_NOKIAX86 + default: + // For emulator we assume that we need an input panel, since we can't + // separate between phone types. + return true; +#else + case QSysInfo::SV_S60_5_0: { + // For SDK == 5.0, we need phone specific detection, since the HAL API + // is no good on most phones. However, all phones at the time of writing use the + // input panel, except N97 in landscape mode, but in this mode it refuses to bring + // up the panel anyway, so we don't have to care. + return true; + } + default: + // For unknown/newer types, we try to use the HAL API. + int keyboardEnabled; + int keyboardType; + int err[2]; + err[0] = HAL::Get(HAL::EKeyboard, keyboardType); + err[1] = HAL::Get(HAL::EKeyboardState, keyboardEnabled); + if (err[0] == KErrNone && err[1] == KErrNone + && keyboardType != 0 && keyboardEnabled) + // Means that we have some sort of keyboard. + return false; + + // Fall back to using the input panel. + return true; +#endif // !Q_CC_NOKIAX86 + } +} + bool QCoeFepInputContext::filterEvent(const QEvent *event) { // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically @@ -174,10 +213,8 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) } } - // For pre-5.0 SDKs, we don't launch the keyboard. - if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { + if (!needsInputPanel()) return false; - } if (event->type() == QEvent::RequestSoftwareInputPanel) { // Notify S60 that we want the virtual keyboard to show up. diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index d680af8..15db9a6 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -357,7 +357,7 @@ QListView::LayoutMode QListView::layoutMode() const /*! \property QListView::spacing - \brief the space between items in the layout + \brief the space around the items in the layout This property is the size of the empty space that is padded around an item in the layout. @@ -972,9 +972,9 @@ void QListView::paintEvent(QPaintEvent *e) option.rect = visualRect(*it); if (flow() == TopToBottom) - option.rect.setWidth(qMin(viewport()->size().width(), option.rect.width())); + option.rect.setWidth(qMin(viewport()->size().width() - 2 * d->spacing(), option.rect.width())); else - option.rect.setHeight(qMin(viewport()->size().height(), option.rect.height())); + option.rect.setHeight(qMin(viewport()->size().height() - 2 * d->spacing(), option.rect.height())); option.state = state; if (selections && selections->isSelected(*it)) @@ -1837,14 +1837,14 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) { horizontalScrollBar()->setSingleStep(step.width() + spacing()); horizontalScrollBar()->setPageStep(viewport()->width()); - horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); + horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width() - 2 * spacing()); } void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) { verticalScrollBar()->setSingleStep(step.height() + spacing()); verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); + verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height() - 2 * spacing()); } void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 3856293..a3cbc0d 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2113,6 +2113,12 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie if (vi < 0) vi = qMax(0, d->viewIndex(current)); + if (isRightToLeft()) { + if (cursorAction == MoveRight) + cursorAction = MoveLeft; + else if (cursorAction == MoveLeft) + cursorAction = MoveRight; + } switch (cursorAction) { case MoveNext: case MoveDown: diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index aad5837..d58dea3 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -105,7 +105,7 @@ public: int top() const { return startValue().toInt(); } QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(top()); return rect; } void updateCurrentValue(const QVariant &) { viewport->update(rect()); } - void updateState(State, State state) { if (state == Stopped) before = after = QPixmap(); } + void updateState(State state, State) { if (state == Stopped) before = after = QPixmap(); } } animatedOperation; void prepareAnimatedOperation(int item, QVariantAnimation::Direction d); void beginAnimatedOperation(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 84e0d50..84da56e 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -104,6 +104,7 @@ #include "qdir.h" #include "qdebug.h" #include "qtimer.h" +#include "qurl.h" #include "private/qmacinputcontext_p.h" #include "private/qpaintengine_mac_p.h" #include "private/qcursor_p.h" @@ -966,7 +967,8 @@ struct QMacAppleEventTypeSpec { AEEventID mac_id; } app_apple_events[] = { { kCoreEventClass, kAEQuitApplication }, - { kCoreEventClass, kAEOpenDocuments } + { kCoreEventClass, kAEOpenDocuments }, + { kInternetEventClass, kAEGetURL }, }; #ifndef QT_MAC_USE_COCOA @@ -1201,7 +1203,7 @@ void qt_init(QApplicationPrivate *priv, int) app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, - app_proc_ae_handlerUPP, SRefCon(qApp), true); + app_proc_ae_handlerUPP, SRefCon(qApp), false); } if (QApplicationPrivate::app_style) { @@ -1237,6 +1239,10 @@ void qt_init(QApplicationPrivate *priv, int) [cocoaApp setMenu:[qtMenuLoader menu]]; [newDelegate setMenuLoader:qtMenuLoader]; [qtMenuLoader release]; + + NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager]; + [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:) + forEventClass:kInternetEventClass andEventID:kAEGetURL]; } #endif // Register for Carbon tablet proximity events on the event monitor target. @@ -2477,6 +2483,22 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap default: break; } + } else if (aeClass == kInternetEventClass) { + switch (aeID) { + case kAEGetURL: { + char urlData[1024]; + Size actualSize; + if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData, + sizeof(urlData) - 1, &actualSize) == noErr) { + urlData[actualSize] = 0; + QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData))); + QApplication::sendSpontaneousEvent(app, &ev); + } + break; + } + default: + break; + } } #ifdef DEBUG_EVENTS qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "", diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 8df4d08..992e4be 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -72,7 +72,7 @@ #include <private/qgraphicssystem_qws_p.h> #endif #ifdef Q_OS_SYMBIAN -#include <w32std.h> +#include <w32std.h> #endif QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 1b0659a..5578a72 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -357,6 +357,9 @@ QSymbianControl::~QSymbianControl() setFocusSafely(false); S60->appUi()->RemoveFromStack(this); delete m_longTapDetector; + + if(m_previousEventLongTap) + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton; } void QSymbianControl::setWidget(QWidget *w) @@ -866,6 +869,11 @@ void QSymbianControl::SizeChanged() tlwExtra->inTopLevelResize = false; } } + + // CCoeControl::SetExtent calls SizeChanged, but does not call + // PositionChanged, so we call it here to ensure that the widget's + // position is updated. + PositionChanged(); } void QSymbianControl::PositionChanged() @@ -1255,7 +1263,7 @@ bool QApplicationPrivate::modalState() void QApplicationPrivate::enterModal_sys(QWidget *widget) { if (widget) { - widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue); + static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue); // Modal partial screen dialogs (like queries) capture pointer events. // ### FixMe: Add specialized behaviour for fullscreen modal dialogs widget->effectiveWinId()->SetGloballyCapturing(ETrue); @@ -1270,7 +1278,7 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget) void QApplicationPrivate::leaveModal_sys(QWidget *widget) { if (widget) { - widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse); + static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse); // ### FixMe: Add specialized behaviour for fullscreen modal dialogs widget->effectiveWinId()->SetGloballyCapturing(EFalse); widget->effectiveWinId()->SetPointerCapture(EFalse); diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index d103cbd..37dcc67 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -83,6 +83,7 @@ #include <private/qt_cocoa_helpers_mac_p.h> #include <private/qdesktopwidget_mac_p.h> #include <qevent.h> +#include <qurl.h> #include <qapplication.h> QT_BEGIN_NAMESPACE @@ -303,5 +304,15 @@ static void cleanupCocoaApplicationDelegate() [self doesNotRecognizeSelector:invocationSelector]; } +- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent +{ + Q_UNUSED(replyEvent); + + NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; + QUrl url(qt_mac_NSStringToQString(urlString)); + QFileOpenEvent qtEvent(url); + qt_sendSpontaneousEvent(qAppInstance(), &qtEvent); +} + @end #endif diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h index 80df645..a137744 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h @@ -123,5 +123,6 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate); - (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader; - (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader; - (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate; +- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent; @end #endif diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 803a1b1..9fb674e 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -307,6 +307,18 @@ static void cleanupCocoaWindowDelegate() return m_windowHash->value(window); } +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame +{ + Q_UNUSED(newFrame); + // saving the current window geometry before the window is maximized + QWidget *qwidget = m_windowHash->value(window); + if (qwidget->isWindow() && !(qwidget->windowState() & Qt::WindowMaximized)) { + QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); + widgetPrivate->topData()->normalGeometry = qwidget->geometry(); + } + return YES; +} + - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame { NSRect frameToReturn = defaultFrame; diff --git a/src/gui/kernel/qcocoawindowdelegate_mac_p.h b/src/gui/kernel/qcocoawindowdelegate_mac_p.h index 3728002..243ba03 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac_p.h +++ b/src/gui/kernel/qcocoawindowdelegate_mac_p.h @@ -78,6 +78,7 @@ QT_FORWARD_DECLARE_CLASS(QWidgetData) - (void)windowDidResignKey:(NSNotification*)notification; - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu; - (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard; +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; @end @protocol NSDrawerDelegate <NSObject> diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm index 88dc173..c2d05d7 100644 --- a/src/gui/kernel/qdesktopwidget_mac.mm +++ b/src/gui/kernel/qdesktopwidget_mac.mm @@ -136,16 +136,19 @@ void QDesktopWidgetImplementation::onResize() screenRects.clear(); availableRects.clear(); NSRect primaryRect = [[displays objectAtIndex:0] frame]; - for (int i = 0; i<screenCount; i++) { - NSRect r = [[displays objectAtIndex:i] frame]; - const int flippedY = - r.origin.y + // account for position offset and + for (int i = 0; i<screenCount; i++) { + NSRect r = [[displays objectAtIndex:i] frame]; + int flippedY = - r.origin.y + // account for position offset and primaryRect.size.height - r.size.height; // height difference. screenRects.append(QRectF(r.origin.x, flippedY, r.size.width, r.size.height)); - r = [[displays objectAtIndex:i] visibleFrame]; + + r = [[displays objectAtIndex:i] visibleFrame]; + flippedY = - r.origin.y + // account for position offset and + primaryRect.size.height - r.size.height; // height difference. availableRects.append(QRectF(r.origin.x, flippedY, r.size.width, r.size.height)); - } + } } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index bcebe06..ff97405 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2976,13 +2976,13 @@ QShowEvent::~QShowEvent() /*! \class QFileOpenEvent \brief The QFileOpenEvent class provides an event that will be - sent when there is a request to open a file. + sent when there is a request to open a file or a URL. \ingroup events File open events will be sent to the QApplication::instance() - when the operating system requests that a file be opened. This is - a high-level event that can be caused by different user actions + when the operating system requests that a file or URL should be opened. + This is a high-level event that can be caused by different user actions depending on the user's desktop environment; for example, double clicking on an file icon in the Finder on Mac OS X. @@ -2999,12 +2999,27 @@ QShowEvent::~QShowEvent() */ QFileOpenEvent::QFileOpenEvent(const QString &file) : QEvent(FileOpen), f(file) -{} +{ + d = reinterpret_cast<QEventPrivate *>(new QFileOpenEventPrivate(QUrl::fromLocalFile(file))); +} + +/*! + \internal + + Constructs a file open event for the given \a url. +*/ +QFileOpenEvent::QFileOpenEvent(const QUrl &url) + : QEvent(FileOpen) +{ + d = reinterpret_cast<QEventPrivate *>(new QFileOpenEventPrivate(url)); + f = url.toLocalFile(); +} /*! \internal */ QFileOpenEvent::~QFileOpenEvent() { + delete reinterpret_cast<QFileOpenEventPrivate *>(d); } /*! @@ -3013,6 +3028,16 @@ QFileOpenEvent::~QFileOpenEvent() Returns the file that is being opened. */ +/*! + \fn QUrl QFileOpenEvent::url() const + + Returns the url that is being opened. +*/ +QUrl QFileOpenEvent::url() const +{ + return reinterpret_cast<const QFileOpenEventPrivate *>(d)->url; +} + #ifndef QT_NO_TOOLBAR /*! \internal @@ -4345,9 +4370,9 @@ bool QGestureEvent::isAccepted(QGesture *gesture) const Sets the accept flag of the given \a gestureType object to the specified \a value. - Setting the accept flag indicates that the event receiver wants the gesture - of type \a gestureType. Unwanted gestures may be propagated to the parent - widget. + Setting the accept flag indicates that the event receiver wants to receive + gestures of the specified type, \a gestureType. Unwanted gestures may be + propagated to the parent widget. By default, gestures in events of type QEvent::Gesture are accepted, and gestures in QEvent::GestureOverride events are ignored. diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index b9512fa..9839269 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -638,9 +638,11 @@ class Q_GUI_EXPORT QFileOpenEvent : public QEvent { public: QFileOpenEvent(const QString &file); + QFileOpenEvent(const QUrl &url); ~QFileOpenEvent(); inline QString file() const { return f; } + QUrl url() const; private: QString f; }; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 6e6ab01..4aaaa8b 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -43,6 +43,7 @@ #define QEVENT_P_H #include <QtCore/qglobal.h> +#include <QtCore/qurl.h> #include <QtGui/qevent.h> QT_BEGIN_NAMESPACE @@ -164,6 +165,18 @@ public: QMap<Qt::GestureType, QWidget *> targetWidgets; }; + +class QFileOpenEventPrivate +{ +public: + inline QFileOpenEventPrivate(const QUrl &url) + : url(url) + { + } + + QUrl url; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index e322af2..e8c2f8a 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -174,6 +174,16 @@ void QGesture::unsetHotSpot() } /*! + \property QGesture::gestureCancelPolicy + \brief the policy for deciding what happens on accepting a gesture + + On accepting one gesture Qt can automatically cancel other gestures + that belong to other targets. The policy is normally set to not cancel + any other gestures and can be set to cancel all active gestures in the + context. For example for all child widgets. +*/ + +/*! \enum QGesture::GestureCancelPolicy This enum describes how accepting a gesture can cancel other gestures @@ -210,16 +220,6 @@ QGesture::GestureCancelPolicy QGesture::gestureCancelPolicy() const */ /*! - \property QGesture::gestureCancelPolicy - \brief the policy for deciding what happens on accepting a gesture - - On accepting one gesture Qt can automatically cancel other gestures - that belong to other targets. The policy is normally set to not cancel - any other gestures and can be set to cancel all active gestures in the - context. For example for all child widgets. -*/ - -/*! \property QPanGesture::lastOffset \brief the last offset recorded for this gesture @@ -658,4 +658,70 @@ void QSwipeGesture::setSwipeAngle(qreal value) d_func()->swipeAngle = value; } +/*! + \class QTapGesture + \since 4.6 + \brief The QTapGesture class describes a tap gesture made by the user. + \ingroup gestures + + \sa {Gestures Programming}, QPanGesture, QPinchGesture +*/ + +/*! + \property QTapGesture::position + \brief the position of the tap +*/ + +/*! + \internal +*/ +QTapGesture::QTapGesture(QObject *parent) + : QGesture(*new QTapGesturePrivate, parent) +{ + d_func()->gestureType = Qt::TapGesture; +} + +QPointF QTapGesture::position() const +{ + return d_func()->position; +} + +void QTapGesture::setPosition(const QPointF &value) +{ + d_func()->position = value; +} +/*! + \class QTapAndHoldGesture + \since 4.6 + \brief The QTapAndHoldGesture class describes a tap-and-hold (aka LongTap) + gesture made by the user. + \ingroup gestures + + \sa {Gestures Programming}, QPanGesture, QPinchGesture +*/ + +/*! + \property QTapAndHoldGesture::position + \brief the position of the tap +*/ + +/*! + \internal +*/ +QTapAndHoldGesture::QTapAndHoldGesture(QObject *parent) + : QGesture(*new QTapAndHoldGesturePrivate, parent) +{ + d_func()->gestureType = Qt::TapAndHoldGesture; +} + +QPointF QTapAndHoldGesture::position() const +{ + return d_func()->position; +} + +void QTapAndHoldGesture::setPosition(const QPointF &value) +{ + d_func()->position = value; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index dd322ad..f995d7b 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -219,6 +219,40 @@ public: friend class QSwipeGestureRecognizer; }; +class QTapGesturePrivate; +class Q_GUI_EXPORT QTapGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTapGesture) + + Q_PROPERTY(QPointF position READ position WRITE setPosition) + +public: + QTapGesture(QObject *parent = 0); + + QPointF position() const; + void setPosition(const QPointF &pos); + + friend class QTapGestureRecognizer; +}; + +class QTapAndHoldGesturePrivate; +class Q_GUI_EXPORT QTapAndHoldGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTapAndHoldGesture) + + Q_PROPERTY(QPointF position READ position WRITE setPosition) + +public: + QTapAndHoldGesture(QObject *parent = 0); + + QPointF position() const; + void setPosition(const QPointF &pos); + + friend class QTapAndHoldGestureRecognizer; +}; + QT_END_NAMESPACE Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy) diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index ae2e287..2537f47 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -136,13 +136,45 @@ public: QSwipeGesturePrivate() : horizontalDirection(QSwipeGesture::NoDirection), verticalDirection(QSwipeGesture::NoDirection), - swipeAngle(0) + swipeAngle(0), + started(false), speed(0) { } QSwipeGesture::SwipeDirection horizontalDirection; QSwipeGesture::SwipeDirection verticalDirection; qreal swipeAngle; + + QPoint lastPositions[3]; + bool started; + qreal speed; + QTime time; +}; + +class QTapGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QTapGesture) + +public: + QTapGesturePrivate() + { + } + + QPointF position; +}; + +class QTapAndHoldGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QTapAndHoldGesture) + +public: + QTapAndHoldGesturePrivate() + : timerId(0) + { + } + + QPointF position; + int timerId; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 628892d..abd2128 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -90,9 +90,13 @@ QGestureManager::QGestureManager(QObject *parent) #else registerGestureRecognizer(new QPanGestureRecognizer); registerGestureRecognizer(new QPinchGestureRecognizer); + registerGestureRecognizer(new QSwipeGestureRecognizer); + registerGestureRecognizer(new QTapGestureRecognizer); +#endif #if defined(Q_OS_WIN) registerGestureRecognizer(new QWinNativePanGestureRecognizer); -#endif +#else + registerGestureRecognizer(new QTapAndHoldGestureRecognizer); #endif } @@ -175,8 +179,10 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni return 0; } else if (QGesture *g = qobject_cast<QGesture *>(object)) { return g; +#ifndef QT_NO_GRAPHICSVIEW } else { Q_ASSERT(qobject_cast<QGraphicsObject *>(object)); +#endif } QList<QGesture *> states = diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm index d842322..f142d71 100644 --- a/src/gui/kernel/qmacgesturerecognizer_mac.mm +++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm @@ -120,7 +120,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e case QNativeGestureEvent::Zoom: g->setLastScaleFactor(g->scaleFactor()); g->setLastRotationAngle(g->rotationAngle()); - g->setScaleFactor(g->scaleFactor() + ev->percentage); + g->setScaleFactor(g->scaleFactor() * (1 + ev->percentage)); g->setChangeFlags(QPinchGesture::ScaleFactorChanged); g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 21795b4..a914220 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -197,8 +197,7 @@ bool QSoftKeyManager::event(QEvent *e) } while (source); QSoftKeyManagerPrivate::softKeySource = source; - if (source) - QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); + QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); return true; } return false; @@ -247,7 +246,10 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) } } - Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource->window()->windowType(); + const Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource + ? QSoftKeyManagerPrivate::softKeySource->window()->windowType() + : Qt::Widget; + if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index dfd49eb..0ea4764 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,6 +45,7 @@ #include "qevent.h" #include "qwidget.h" #include "qabstractscrollarea.h" +#include "qdebug.h" QT_BEGIN_NAMESPACE @@ -66,7 +67,9 @@ QGesture *QPanGestureRecognizer::create(QObject *target) return new QPanGesture; } -QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) +QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) { QPanGesture *q = static_cast<QPanGesture *>(state); QPanGesturePrivate *d = q->d_func(); @@ -155,7 +158,9 @@ QGesture *QPinchGestureRecognizer::create(QObject *target) return new QPinchGesture; } -QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) +QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) { QPinchGesture *q = static_cast<QPinchGesture *>(state); QPinchGesturePrivate *d = q->d_func(); @@ -199,8 +204,9 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q d->centerPoint = centerPoint; d->changeFlags |= QPinchGesture::CenterPointChanged; - const qreal scaleFactor = QLineF(p1.pos(), p2.pos()).length() - / QLineF(d->startPosition[0], d->startPosition[1]).length(); + const qreal scaleFactor = + QLineF(p1.screenPos(), p2.screenPos()).length() + / QLineF(d->startPosition[0], d->startPosition[1]).length(); if (d->isNewSequence) { d->lastScaleFactor = scaleFactor; } else { @@ -210,7 +216,13 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q d->totalScaleFactor += d->scaleFactor - d->lastScaleFactor; d->changeFlags |= QPinchGesture::ScaleFactorChanged; - const qreal rotationAngle = -line.angle(); + qreal angle = QLineF(p1.screenPos(), p2.screenPos()).angle(); + if (angle > 180) + angle -= 360; + qreal startAngle = QLineF(p1.startScreenPos(), p2.startScreenPos()).angle(); + if (startAngle > 180) + startAngle -= 360; + const qreal rotationAngle = startAngle - angle; if (d->isNewSequence) d->lastRotationAngle = rotationAngle; else @@ -224,7 +236,10 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q result = QGestureRecognizer::TriggerGesture; } else { d->isNewSequence = true; - result = QGestureRecognizer::MayBeGesture; + if (q->state() == Qt::NoGesture) + result = QGestureRecognizer::Ignore; + else + result = QGestureRecognizer::FinishGesture; } break; } @@ -252,6 +267,299 @@ void QPinchGestureRecognizer::reset(QGesture *state) d->totalRotationAngle = d->lastRotationAngle = d->rotationAngle = 0; d->isNewSequence = true; + d->startPosition[0] = d->startPosition[1] = QPointF(); + + QGestureRecognizer::reset(state); +} + +// +// QSwipeGestureRecognizer +// + +QSwipeGestureRecognizer::QSwipeGestureRecognizer() +{ +} + +QGesture *QSwipeGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QSwipeGesture; +} + +QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) +{ + QSwipeGesture *q = static_cast<QSwipeGesture *>(state); + QSwipeGesturePrivate *d = q->d_func(); + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result; + + switch (event->type()) { + case QEvent::TouchBegin: { + d->speed = 1; + d->time = QTime::currentTime(); + d->started = true; + result = QGestureRecognizer::MayBeGesture; + break; + } + case QEvent::TouchEnd: { + if (q->state() != Qt::NoGesture) { + result = QGestureRecognizer::FinishGesture; + } else { + result = QGestureRecognizer::CancelGesture; + } + break; + } + case QEvent::TouchUpdate: { + if (!d->started) + result = QGestureRecognizer::CancelGesture; + else if (ev->touchPoints().size() == 3) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2); + + if (d->lastPositions[0].isNull()) { + d->lastPositions[0] = p1.startScreenPos().toPoint(); + d->lastPositions[1] = p2.startScreenPos().toPoint(); + d->lastPositions[2] = p3.startScreenPos().toPoint(); + } + d->hotSpot = p1.screenPos(); + d->isHotSpotSet = true; + + int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() + + p2.screenPos().x() - d->lastPositions[1].x() + + p3.screenPos().x() - d->lastPositions[2].x()) / 3; + int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() + + p2.screenPos().y() - d->lastPositions[1].y() + + p3.screenPos().y() - d->lastPositions[2].y()) / 3; + + const int distance = xDistance >= yDistance ? xDistance : yDistance; + int elapsedTime = d->time.msecsTo(QTime::currentTime()); + if (!elapsedTime) + elapsedTime = 1; + d->speed = 0.9 * d->speed + distance / elapsedTime; + d->time = QTime::currentTime(); + d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle(); + + static const int MoveThreshold = 50; + if (xDistance > MoveThreshold || yDistance > MoveThreshold) { + // measure the distance to check if the direction changed + d->lastPositions[0] = p1.screenPos().toPoint(); + d->lastPositions[1] = p2.screenPos().toPoint(); + d->lastPositions[2] = p3.screenPos().toPoint(); + QSwipeGesture::SwipeDirection horizontal = + xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left; + QSwipeGesture::SwipeDirection vertical = + yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up; + if (d->verticalDirection == QSwipeGesture::NoDirection) + d->verticalDirection = vertical; + if (d->horizontalDirection == QSwipeGesture::NoDirection) + d->horizontalDirection = horizontal; + if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) { + // the user has changed the direction! + result = QGestureRecognizer::CancelGesture; + } + result = QGestureRecognizer::TriggerGesture; + } else { + if (q->state() != Qt::NoGesture) + result = QGestureRecognizer::TriggerGesture; + else + result = QGestureRecognizer::MayBeGesture; + } + } else if (ev->touchPoints().size() > 3) { + result = QGestureRecognizer::CancelGesture; + } else { // less than 3 touch points + if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed)) + result = QGestureRecognizer::CancelGesture; + else if (d->started) + result = QGestureRecognizer::Ignore; + else + result = QGestureRecognizer::MayBeGesture; + } + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QSwipeGestureRecognizer::reset(QGesture *state) +{ + QSwipeGesture *q = static_cast<QSwipeGesture *>(state); + QSwipeGesturePrivate *d = q->d_func(); + + d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection; + d->swipeAngle = 0; + + d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint(); + d->started = false; + d->speed = 0; + d->time = QTime(); + + QGestureRecognizer::reset(state); +} + +// +// QTapGestureRecognizer +// + +QTapGestureRecognizer::QTapGestureRecognizer() +{ +} + +QGesture *QTapGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QTapGesture; +} + +QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) +{ + QTapGesture *q = static_cast<QTapGesture *>(state); + QTapGesturePrivate *d = q->d_func(); + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + + switch (event->type()) { + case QEvent::TouchBegin: { + d->position = ev->touchPoints().at(0).pos(); + result = QGestureRecognizer::TriggerGesture; + break; + } + case QEvent::TouchUpdate: + case QEvent::TouchEnd: { + if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); + enum { TapRadius = 40 }; + if (delta.manhattanLength() <= TapRadius) { + if (event->type() == QEvent::TouchEnd) + result = QGestureRecognizer::FinishGesture; + else + result = QGestureRecognizer::TriggerGesture; + } + } + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QTapGestureRecognizer::reset(QGesture *state) +{ + QTapGesture *q = static_cast<QTapGesture *>(state); + QTapGesturePrivate *d = q->d_func(); + + d->position = QPointF(); + + QGestureRecognizer::reset(state); +} + +// +// QTapAndHoldGestureRecognizer +// + +QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer() +{ +} + +QGesture *QTapAndHoldGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QTapAndHoldGesture; +} + +QGestureRecognizer::Result +QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, + QEvent *event) +{ + QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); + QTapAndHoldGesturePrivate *d = q->d_func(); + + if (object == state && event->type() == QEvent::Timer) { + q->killTimer(d->timerId); + d->timerId = 0; + return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + } + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + + enum { TimerInterval = 2000 }; + enum { TapRadius = 40 }; + + switch (event->type()) { + case QEvent::TouchBegin: + d->position = ev->touchPoints().at(0).pos(); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + result = QGestureRecognizer::TriggerGesture; + break; + case QEvent::TouchEnd: + if (d->timerId) + result = QGestureRecognizer::CancelGesture; + else + result = QGestureRecognizer::FinishGesture; + break; + case QEvent::TouchUpdate: + if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); + if (delta.manhattanLength() <= TapRadius) + result = QGestureRecognizer::TriggerGesture; + } + break; + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QTapAndHoldGestureRecognizer::reset(QGesture *state) +{ + QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); + QTapAndHoldGesturePrivate *d = q->d_func(); + + d->position = QPointF(); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = 0; QGestureRecognizer::reset(state); } diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index e6f346c..8fea2bc 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -74,7 +74,36 @@ public: QPinchGestureRecognizer(); QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QSwipeGestureRecognizer : public QGestureRecognizer +{ +public: + QSwipeGestureRecognizer(); + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QTapGestureRecognizer : public QGestureRecognizer +{ +public: + QTapGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QTapAndHoldGestureRecognizer : public QGestureRecognizer +{ +public: + QTapAndHoldGestureRecognizer(); + + QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); void reset(QGesture *state); }; diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 789d89e..3405bcf 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -73,6 +73,7 @@ #include <akntitle.h> // CAknTitlePane #include <akncontext.h> // CAknContextPane #include <eikspane.h> // CEikStatusPane +#include <aknpopupfader.h> // MAknFadedComponent and TAknPopupFader #endif QT_BEGIN_NAMESPACE @@ -114,7 +115,7 @@ public: int supportsPremultipliedAlpha : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static inline void updateScreenSize(); - static inline RWsSession& wsSession(); + static inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); static inline CWsScreenDevice* screenDevice(); static inline CCoeAppUi* appUi(); @@ -140,7 +141,11 @@ public: }; class QLongTapTimer; + class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver +#ifdef Q_WS_S60 +, public MAknFadedComponent +#endif { public: DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII. @@ -165,6 +170,17 @@ public: void setFocusSafely(bool focus); +#ifdef Q_WS_S60 + void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } + +protected: // from MAknFadedComponent + TInt CountFadedComponents() {return 1;} + CCoeControl* FadedComponent(TInt aIndex) {return this;} +#else + #warning No fallback implementation for QSymbianControl::FadeBehindPopup + void FadeBehindPopup(bool /*fade*/){ } +#endif + protected: void Draw(const TRect& aRect) const; void SizeChanged(); @@ -189,6 +205,11 @@ private: bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; bool m_previousEventLongTap; + +#ifdef Q_WS_S60 + // Fader object used to fade everything except this menu and the CBA. + TAknPopupFader popupFader; +#endif }; inline QS60Data::QS60Data() diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 6a72cfa..271b939 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -230,7 +230,9 @@ QWidgetPrivate::~QWidgetPrivate() if (extra) deleteExtra(); +#ifndef QT_NO_GRAPHICSEFFECT delete graphicsEffect; +#endif //QT_NO_GRAPHICSEFFECT } QWindowSurface *QWidgetPrivate::createDefaultWindowSurface() @@ -1793,6 +1795,7 @@ QRegion QWidgetPrivate::clipRegion() const return r; } +#ifndef QT_NO_GRAPHICSEFFECT void QWidgetPrivate::invalidateGraphicsEffectsRecursively() { Q_Q(QWidget); @@ -1807,6 +1810,7 @@ void QWidgetPrivate::invalidateGraphicsEffectsRecursively() w = w->parentWidget(); } while (w); } +#endif //QT_NO_GRAPHICSEFFECT void QWidgetPrivate::setDirtyOpaqueRegion() { @@ -1814,7 +1818,9 @@ void QWidgetPrivate::setDirtyOpaqueRegion() dirtyOpaqueChildren = true; +#ifndef QT_NO_GRAPHICSEFFECT invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT if (q->isWindow()) return; @@ -1963,10 +1969,12 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const const QWidget *w = q; QPoint offset; +#ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect) { w = q->parentWidget(); offset -= data.crect.topLeft(); } +#endif //QT_NO_GRAPHICSEFFECT while (w) { const QWidgetPrivate *wd = w->d_func(); @@ -2001,11 +2009,13 @@ void QWidgetPrivate::updateIsOpaque() // hw: todo: only needed if opacity actually changed setDirtyOpaqueRegion(); +#ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect) { // ### We should probably add QGraphicsEffect::isOpaque at some point. setOpaque(false); return; } +#endif //QT_NO_GRAPHICSEFFECT Q_Q(QWidget); #ifdef Q_WS_X11 @@ -5013,11 +5023,13 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, \sa setGraphicsEffect() */ +#ifndef QT_NO_GRAPHICSEFFECT QGraphicsEffect *QWidget::graphicsEffect() const { Q_D(const QWidget); return d->graphicsEffect; } +#endif //QT_NO_GRAPHICSEFFECT /*! @@ -5036,6 +5048,7 @@ QGraphicsEffect *QWidget::graphicsEffect() const \sa graphicsEffect() */ +#ifndef QT_NO_GRAPHICSEFFECT void QWidget::setGraphicsEffect(QGraphicsEffect *effect) { Q_D(QWidget); @@ -5065,6 +5078,7 @@ void QWidget::setGraphicsEffect(QGraphicsEffect *effect) d->updateIsOpaque(); update(); } +#endif //QT_NO_GRAPHICSEFFECT bool QWidgetPrivate::isAboutToShow() const { @@ -5157,8 +5171,7 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset return; QPixmap pixmap(size); - if (!(renderFlags & QWidget::DrawWindowBackground) - || !q->palette().brush(q->backgroundRole()).isOpaque()) + if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque) pixmap.fill(Qt::transparent); q->render(&pixmap, QPoint(), toBePainted, renderFlags); @@ -5211,6 +5224,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP return; Q_Q(QWidget); +#ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect && graphicsEffect->isEnabled()) { QGraphicsEffectSource *source = graphicsEffect->d_func()->source; QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *> @@ -5241,6 +5255,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP return; } } +#endif //QT_NO_GRAFFICSEFFECT const bool asRoot = flags & DrawAsRoot; const bool alsoOnScreen = flags & DrawPaintOnScreen; @@ -5395,7 +5410,6 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis QWidgetPrivate *wd = w->d_func(); const QPoint widgetPos(w->data->crect.topLeft()); const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect; - if (index > 0) { QRegion wr(rgn); if (wd->isOpaque) @@ -5421,6 +5435,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis } } +#ifndef QT_NO_GRAPHICSEFFECT QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const { if (system != Qt::DeviceCoordinates) @@ -5521,6 +5536,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * m_widget->render(&pixmap, pixmapOffset); return pixmap; } +#endif //QT_NO_GRAPHICSEFFECT #ifndef QT_NO_GRAPHICSVIEW /*! diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 05f0069..b7c55f9 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -351,8 +351,10 @@ public: const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren)); +#ifndef QT_NO_GRAPHICSEFFECT QGraphicsEffect *graphicsEffect() const; void setGraphicsEffect(QGraphicsEffect *effect); +#endif //QT_NO_GRAPHICSEFFECT void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags()); void ungrabGesture(Qt::GestureType type); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 9270220..75f9a59 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -730,6 +730,7 @@ static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowExpanded }, { kEventClassWindow, kEventWindowHidden }, + { kEventClassWindow, kEventWindowZoom }, { kEventClassWindow, kEventWindowZoomed }, { kEventClassWindow, kEventWindowCollapsed }, { kEventClassWindow, kEventWindowToolbarSwitchMode }, @@ -812,6 +813,9 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, QShowEvent qse; QApplication::sendSpontaneousEvent(widget, &qse); + } else if(ekind == kEventWindowZoom) { + widget->d_func()->topData()->normalGeometry = widget->geometry(); + handled_event = false; } else if(ekind == kEventWindowZoomed) { WindowPartCode windowPart; GetEventParameter(event, kEventParamWindowPartCode, @@ -3487,10 +3491,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate) qt_mac_set_fullscreen_mode(true); } else { needShow = isVisible(); - setParent(parentWidget(), d->topData()->savedFlags); - setGeometry(d->topData()->normalGeometry); if(!qApp->desktop()->screenNumber(this)) qt_mac_set_fullscreen_mode(false); + setParent(parentWidget(), d->topData()->savedFlags); + setGeometry(d->topData()->normalGeometry); d->topData()->normalGeometry.setRect(0, 0, -1, -1); } } @@ -3592,7 +3596,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) [window zoom:window]; #endif needSendStateChange = oldstate == windowState(); // Zoom didn't change flags. - } else if(oldstate & Qt::WindowMaximized) { + } else if(oldstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) { #ifndef QT_MAC_USE_COCOA Point idealSize; ZoomWindowIdeal(window, inZoomIn, &idealSize); @@ -3787,7 +3791,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget *w) /* Modifies the bounds for a widgets backing HIView during moves and resizes. Also updates the widget, either by scrolling its contents or repainting, depending on the WA_StaticContents - and QWidgetPrivate::isOpaque flags. + flag */ static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newRect) { @@ -3804,8 +3808,8 @@ static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newR // Perform a normal (complete repaint) update in some cases: if ( - // move-by-scroll requires QWidgetPrivate::isOpaque set - (isMove && q->testAttribute(Qt::WA_OpaquePaintEvent) == false) || + // always repaint on move. + (isMove) || // limited update on resize requires WA_StaticContents. (isResize && q->testAttribute(Qt::WA_StaticContents) == false) || diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 8b03a85..151b90a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -384,7 +384,9 @@ public: void setOpaque(bool opaque); void updateIsTranslucent(); bool paintOnScreen() const; +#ifndef QT_NO_GRAPHICSEFFECT void invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT const QRegion &getOpaqueChildren() const; void setDirtyOpaqueRegion(); @@ -530,8 +532,10 @@ public: inline QRect effectiveRectFor(const QRect &rect) const { +#ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect && graphicsEffect->isEnabled()) return graphicsEffect->boundingRectFor(rect).toAlignedRect(); +#endif //QT_NO_GRAPHICSEFFECT return rect; } @@ -774,6 +778,7 @@ struct QWidgetPaintContext QPainter *painter; }; +#ifndef QT_NO_GRAPHICSEFFECT class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate { public: @@ -826,6 +831,7 @@ public: QTransform lastEffectTransform; bool updateDueToGraphicsEffect; }; +#endif //QT_NO_GRAPHICSEFFECT inline QWExtra *QWidgetPrivate::extraData() const { diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index a6d8ed7..88cd63d 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -434,8 +434,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de drawableWindow->PointerFilter(EPointerFilterEnterExit | EPointerFilterMove | EPointerFilterDrag, 0); - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) + if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) { activateSymbianWindow(control.data()); + control->MakeVisible(true); + } // We wait until the control is fully constructed before calling setWinId, because // this generates a WinIdChanged event. diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index f36470a..8226797 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -529,7 +529,9 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up Q_ASSERT(widget->window() == tlw); Q_ASSERT(!rgn.isEmpty()); +#ifndef QT_NO_GRAPHICSEFFECT widget->d_func()->invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT if (widget->d_func()->paintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { @@ -559,9 +561,11 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up if (invalidateBuffer) { const bool eventAlreadyPosted = !dirty.isEmpty(); +#ifndef QT_NO_GRAPHICSEFFECT if (widget->d_func()->graphicsEffect) dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset); else +#endif //QT_NO_GRAPHICSEFFECT dirty += rgn.translated(offset); if (!eventAlreadyPosted || updateImmediately) sendUpdateRequest(tlw, updateImmediately); @@ -576,9 +580,11 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up if (widget->d_func()->inDirtyList) { if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) { +#ifndef QT_NO_GRAPHICSEFFECT if (widget->d_func()->graphicsEffect) widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()); else +#endif //QT_NO_GRAPHICSEFFECT widget->d_func()->dirty += rgn; } } else { @@ -606,7 +612,9 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd Q_ASSERT(widget->window() == tlw); Q_ASSERT(!rect.isEmpty()); +#ifndef QT_NO_GRAPHICSEFFECT widget->d_func()->invalidateGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT if (widget->d_func()->paintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index 3288dae..fbef980 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -146,9 +146,11 @@ private: { if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { QWidgetPrivate *widgetPrivate = widget->d_func(); +#ifndef QT_NO_GRAPHICSEFFECT if (widgetPrivate->graphicsEffect) widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); else +#endif //QT_NO_GRAPHICSEFFECT widgetPrivate->dirty = rgn; dirtyWidgets.append(widget); widgetPrivate->inDirtyList = true; diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index f8dd424..8737f10 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -223,11 +223,23 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; - const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + quint32 basex; + quint32 srcy; - quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; - quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; + if (sx < 0) { + int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + basex = quint32(srcRect.right() * 65536) + dstx; + } else { + int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + basex = quint32(srcRect.left() * 65536) + dstx; + } + if (sy < 0) { + int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + srcy = quint32(srcRect.bottom() * 65536) + dsty; + } else { + int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + srcy = quint32(srcRect.top() * 65536) + dsty; + } quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1; @@ -723,11 +735,23 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; - const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + quint32 basex; + quint32 srcy; - quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; - quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; + if (sx < 0) { + int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + basex = quint32(srcRect.right() * 65536) + dstx; + } else { + int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + basex = quint32(srcRect.left() * 65536) + dstx; + } + if (sy < 0) { + int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + srcy = quint32(srcRect.bottom() * 65536) + dsty; + } else { + int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + srcy = quint32(srcRect.top() * 65536) + dsty; + } quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1; diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index cbfbba6..6f5d892 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -970,7 +970,29 @@ bool QBrush::operator==(const QBrush &b) const QDebug operator<<(QDebug dbg, const QBrush &b) { #ifndef Q_BROKEN_DEBUG_STREAM - dbg.nospace() << "QBrush(" << b.color() << ',' << b.style() << ')'; + char *BRUSH_STYLES[] = { + "NoBrush", + "SolidPattern", + "Dense1Pattern", + "Dense2Pattern", + "Dense3Pattern", + "Dense4Pattern", + "Dense5Pattern", + "Dense6Pattern", + "Dense7Pattern", + "HorPattern", + "VerPattern", + "CrossPattern", + "BDiagPattern", + "FDiagPattern", + "DiagCrossPattern", + "LinearGradientPattern", + "RadialGradientPattern", + "ConicalGradientPattern", + "TexturePattern" + }; + + dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')'; return dbg.space(); #else qWarning("This compiler doesn't support streaming QBrush to QDebug"); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 41602a1..4df7f8a 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2386,12 +2386,12 @@ static void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int len } /* - if 2.Sca < Sa - Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise if 8.Dca <= Da - Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) - otherwise - Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + if 2.Sca <= Sa + Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise if 2.Sca > Sa and 4.Dca <= Da + Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) + otherwise if 2.Sca > Sa and 4.Dca > Da + Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) */ static inline int soft_light_op(int dst, int src, int da, int sa) { @@ -2400,13 +2400,11 @@ static inline int soft_light_op(int dst, int src, int da, int sa) const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; if (src2 < sa) - return (dst * ((sa * 255) - (255 - dst_np) * (src2 - sa)) + temp) / 65025; - else if (8 * dst <= da) - return (dst * ((sa * 255) - ((255 - dst_np) * (src2 - sa) * ((3 * 255) - 8 * dst_np)) / 255) + temp) / 65025; + return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; + else if (4 * dst <= da) + return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; else { - // sqrt is too expensive to do three times per pixel, so skipping it for now - // a future possibility is to use a LUT - return ((dst * sa * 255) + (int(dst_np) * da - (dst * 255)) * (src2 - sa) + temp) / 65025; + return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; } } diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 6b9d77c..b8700c3 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -48,7 +48,7 @@ #include <QDebug> -//#define QPAINTBUFFER_DEBUG_DRAW +// #define QPAINTBUFFER_DEBUG_DRAW QT_BEGIN_NAMESPACE @@ -247,23 +247,24 @@ void QPaintBuffer::draw(QPainter *painter, int frame) const #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << "QPaintBuffer::draw() --------------------------------"; -// printf("Float buffer:"); -// for (int i=0; i<d->floats.size(); i++) { -// if ((i % 10) == 0) { -// printf("\n%4d-%4d: ", i, i+9); -// } -// printf("%4.2f ", d->floats[i]); -// } -// printf("\n"); - -// printf("Int Buffer:"); -// for (int i=0; i<d->ints.size(); i++) { -// if ((i % 10) == 0) { -// printf("\n%4d-%4d: ", i, i+10); -// } -// printf("%5d", d->ints[i]); -// } -// printf("\n"); + Q_D(const QPaintBuffer); + printf("Float buffer:"); + for (int i=0; i<d->floats.size(); i++) { + if ((i % 10) == 0) { + printf("\n%4d-%4d: ", i, i+9); + } + printf("%4.2f ", d->floats[i]); + } + printf("\n"); + + printf("Int Buffer:"); + for (int i=0; i<d->ints.size(); i++) { + if ((i % 10) == 0) { + printf("\n%4d-%4d: ", i, i+10); + } + printf("%5d", d->ints[i]); + } + printf("\n"); #endif if (painter && !painter->isActive()) @@ -406,16 +407,17 @@ void QPaintBufferEngine::clipEnabledChanged() void QPaintBufferEngine::penChanged() { -#ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << "QPaintBufferEngine:" << state()->pen; -#endif const QPen &pen = state()->pen; if (!buffer->commands.isEmpty() && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetPen) { +#ifdef QPAINTBUFFER_DEBUG_DRAW + qDebug() << "QPaintBufferEngine: penChanged (compressed)" << state()->pen; +#endif buffer->variants[buffer->commands.last().offset] = pen; return; } + if (buffer->calculateBoundingRect) { if (pen.style() == Qt::NoPen) { buffer->penWidthAdjustment = 0; @@ -427,22 +429,28 @@ void QPaintBufferEngine::penChanged() buffer->penWidthAdjustment = transformedWidth.x() / 2.0; } } +#ifdef QPAINTBUFFER_DEBUG_DRAW + qDebug() << "QPaintBufferEngine: penChanged" << state()->pen; +#endif buffer->addCommand(QPaintBufferPrivate::Cmd_SetPen, pen); } void QPaintBufferEngine::brushChanged() { -#ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << "QPaintBufferEngine:" << state()->brush; -#endif const QBrush &brush = state()->brush; if (!buffer->commands.isEmpty() && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetBrush) { +#ifdef QPAINTBUFFER_DEBUG_DRAW + qDebug() << "QPaintBufferEngine: brushChanged (compressed)" << state()->brush; +#endif buffer->variants[buffer->commands.last().offset] = brush; return; } +#ifdef QPAINTBUFFER_DEBUG_DRAW + qDebug() << "QPaintBufferEngine: brushChanged" << state()->brush; +#endif buffer->addCommand(QPaintBufferPrivate::Cmd_SetBrush, brush); } @@ -488,14 +496,14 @@ void QPaintBufferEngine::transformChanged() if (!buffer->commands.isEmpty() && buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) { #ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << "QPaintBufferEngine: compressing " << state()->matrix; + qDebug() << "QPaintBufferEngine: transformChanged (compressing) " << state()->matrix; #endif buffer->variants[buffer->commands.last().offset] = state()->matrix; return; } #ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << "QPaintBufferEngine: " << state()->matrix; + qDebug() << "QPaintBufferEngine: transformChanged:" << state()->matrix; #endif buffer->addCommand(QPaintBufferPrivate::Cmd_SetTransform, state()->matrix); } @@ -514,7 +522,18 @@ void QPaintBufferEngine::draw(const QVectorPath &path) #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << "QPaintBufferEngine: draw vpath:" << path.elementCount(); #endif - buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path); + + bool hasBrush = qbrush_style(state()->brush) != Qt::NoBrush; + bool hasPen = qpen_style(state()->pen) != Qt::NoPen + && qbrush_style(qpen_brush(state()->pen)) != Qt::NoBrush; + + if (hasPen || hasBrush) + buffer->addCommand(QPaintBufferPrivate::Cmd_DrawVectorPath, path); +#ifdef QPAINTBUFFER_DEBUG_DRAW + else + qDebug() << " - no pen or brush active, discarded...\n"; +#endif + // if (buffer->calculateBoundingRect) { // QRealRect r = path.controlPointRect(); // buffer->updateBoundingRect(QRectF(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1)); @@ -745,15 +764,15 @@ void QPaintBufferEngine::drawEllipse(const QRect &r) void QPaintBufferEngine::drawPath(const QPainterPath &path) { -#ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount(); -#endif - // ### Path -> QVariant - // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path)); +// #ifdef QPAINTBUFFER_DEBUG_DRAW +// qDebug() << "QPaintBufferEngine: drawPath: element count:" << path.elementCount(); +// #endif +// // ### Path -> QVariant +// // buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPath, QVariant(path)); QPaintEngineEx::drawPath(path); - if (buffer->calculateBoundingRect) - buffer->updateBoundingRect(path.boundingRect()); +// if (buffer->calculateBoundingRect) +// buffer->updateBoundingRect(path.boundingRect()); } void QPaintBufferEngine::drawPoints(const QPoint *points, int pointCount) @@ -1424,10 +1443,6 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); -#ifdef QPAINTBUFFER_DEBUG_DRAW - qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor; -#endif - QFont font(ti.font()); font.setUnderline(false); font.setStrikeOut(false); @@ -1439,6 +1454,10 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) justificationWidth = si.width.toReal(); qreal scaleFactor = font.d->dpi/qreal(qt_defaultDpiY()); +#ifdef QPAINTBUFFER_DEBUG_DRAW + qDebug() << " -> Cmd_DrawTextItem:" << pos << " " << text << " " << scaleFactor; +#endif + if (scaleFactor != 1.0) { QFont fnt(font); QFakeDevice fake; diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h index 6a7ac73..adf0564 100644 --- a/src/gui/painting/qpaintbuffer_p.h +++ b/src/gui/painting/qpaintbuffer_p.h @@ -66,6 +66,7 @@ class QPaintBufferPlayback; class Q_GUI_EXPORT QPaintBuffer : public QPaintDevice { + Q_DECLARE_PRIVATE(QPaintBuffer); public: QPaintBuffer(); QPaintBuffer(const QPaintBuffer &other); @@ -311,7 +312,7 @@ public: virtual ~QPainterReplayer() { } void setupTransform(QPainter *painter); - void process(const QPaintBufferCommand &cmd); + virtual void process(const QPaintBufferCommand &cmd); void draw(const QPaintBuffer &buffer, QPainter *painter, int frame); protected: @@ -326,7 +327,7 @@ class Q_GUI_EXPORT QPaintEngineExReplayer : public QPainterReplayer public: QPaintEngineExReplayer() { } - void process(const QPaintBufferCommand &cmd); + virtual void process(const QPaintBufferCommand &cmd); }; class QPaintBufferEnginePrivate; diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 9e21182..1fb8aab 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -431,6 +431,10 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) // Some engines might decide to optimize for the non-shape hint later on... uint flags = QVectorPath::WindingFill; + + if (path.elementCount() > 2) + flags |= QVectorPath::NonConvexShapeMask; + if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) flags |= QVectorPath::CurvedShapeMask; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 09a4563..48629d1 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -3787,27 +3787,14 @@ void QPainter::setPen(const QPen &pen) if (d->state->pen == pen) return; + d->state->pen = pen; + if (d->extended) { - d->state->pen = pen; d->checkEmulation(); d->extended->penChanged(); return; } - // Do some checks to see if we are the same pen. - Qt::PenStyle currentStyle = d->state->pen.style(); - if (currentStyle == pen.style() && currentStyle != Qt::CustomDashLine) { - if (currentStyle == Qt::NoPen || - (d->state->pen.isSolid() && pen.isSolid() - && d->state->pen.color() == pen.color() - && d->state->pen.widthF() == pen.widthF() - && d->state->pen.capStyle() == pen.capStyle() - && d->state->pen.joinStyle() == pen.joinStyle() - && d->state->pen.isCosmetic() == pen.isCosmetic())) - return; - } - - d->state->pen = pen; d->state->dirtyFlags |= QPaintEngine::DirtyPen; } @@ -3890,14 +3877,6 @@ void QPainter::setBrush(const QBrush &brush) return; } - Qt::BrushStyle currentStyle = d->state->brush.style(); - if (currentStyle == brush.style()) { - if (currentStyle == Qt::NoBrush - || (currentStyle == Qt::SolidPattern - && d->state->brush.color() == brush.color())) - return; - } - d->state->brush = brush; d->state->dirtyFlags |= QPaintEngine::DirtyBrush; } diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 41efc80..77aa748 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -835,16 +835,17 @@ bool QPen::operator==(const QPen &p) const { QPenData *dd = static_cast<QPenData *>(d); QPenData *pdd = static_cast<QPenData *>(p.d); - return (p.d == d) || (p.d->style == d->style - && p.d->capStyle == d->capStyle - && p.d->joinStyle == d->joinStyle - && p.d->width == d->width - && pdd->miterLimit == dd->miterLimit - && (d->style != Qt::CustomDashLine - || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) && - pdd->dashPattern == dd->dashPattern)) - && p.d->brush == d->brush - && pdd->cosmetic == dd->cosmetic); + return (p.d == d) + || (p.d->style == d->style + && p.d->capStyle == d->capStyle + && p.d->joinStyle == d->joinStyle + && p.d->width == d->width + && pdd->miterLimit == dd->miterLimit + && (d->style != Qt::CustomDashLine + || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) && + pdd->dashPattern == dd->dashPattern)) + && p.d->brush == d->brush + && pdd->cosmetic == dd->cosmetic); } @@ -983,8 +984,18 @@ QDataStream &operator>>(QDataStream &s, QPen &p) QDebug operator<<(QDebug dbg, const QPen &p) { #ifndef Q_BROKEN_DEBUG_STREAM + const char *PEN_STYLES[] = { + "NoPen", + "SolidLine", + "DashLine", + "DotLine", + "DashDotLine", + "DashDotDotLine", + "CustomDashLine" + }; + dbg.nospace() << "QPen(" << p.width() << ',' << p.brush() - << ',' << int(p.style()) << ',' << int(p.capStyle()) + << ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle()) << ',' << int(p.joinStyle()) << ',' << p.dashPattern() << ',' << p.dashOffset() << ',' << p.miterLimit() << ')'; diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 8118450..1bd5842 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -2214,12 +2214,14 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale) { const QTransform::TransformationType type = transform.type(); if (type <= QTransform::TxTranslate) { - *scale = 1; + if (scale) + *scale = 1; return true; } else if (type == QTransform::TxScale) { const qreal xScale = qAbs(transform.m11()); const qreal yScale = qAbs(transform.m22()); - *scale = qMax(xScale, yScale); + if (scale) + *scale = qMax(xScale, yScale); return qFuzzyCompare(xScale, yScale); } @@ -2227,7 +2229,8 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale) + transform.m21() * transform.m21(); const qreal yScale = transform.m12() * transform.m12() + transform.m22() * transform.m22(); - *scale = qSqrt(qMax(xScale, yScale)); + if (scale) + *scale = qSqrt(qMax(xScale, yScale)); return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale); } diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index 1de5ffa..4f7806f 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -106,8 +106,10 @@ static QEvent *cloneEvent(QEvent *e) return new QEvent(*e); case QEvent::HideToParent: return new QEvent(*e); +#ifndef QT_NO_WHEELEVENT case QEvent::Wheel: return new QWheelEvent(*static_cast<QWheelEvent*>(e)); +#endif //QT_NO_WHEELEVENT case QEvent::WindowTitleChange: return new QEvent(*e); case QEvent::WindowIconChange: @@ -190,8 +192,10 @@ static QEvent *cloneEvent(QEvent *e) return new QInputMethodEvent(*static_cast<QInputMethodEvent*>(e)); case QEvent::AccessibilityPrepare: return new QEvent(*e); +#ifndef QT_NO_TABLETEVENT case QEvent::TabletMove: return new QTabletEvent(*static_cast<QTabletEvent*>(e)); +#endif //QT_NO_TABLETEVENT case QEvent::LocaleChange: return new QEvent(*e); case QEvent::LanguageChange: @@ -200,10 +204,12 @@ static QEvent *cloneEvent(QEvent *e) return new QEvent(*e); case QEvent::Style: return new QEvent(*e); +#ifndef QT_NO_TABLETEVENT case QEvent::TabletPress: return new QTabletEvent(*static_cast<QTabletEvent*>(e)); case QEvent::TabletRelease: return new QTabletEvent(*static_cast<QTabletEvent*>(e)); +#endif //QT_NO_TABLETEVENT case QEvent::OkRequest: return new QEvent(*e); case QEvent::HelpRequest: @@ -238,8 +244,10 @@ static QEvent *cloneEvent(QEvent *e) return new QHelpEvent(*static_cast<QHelpEvent*>(e)); case QEvent::WhatsThis: return new QHelpEvent(*static_cast<QHelpEvent*>(e)); +#ifndef QT_NO_STATUSTIP case QEvent::StatusTip: return new QStatusTipEvent(*static_cast<QStatusTipEvent*>(e)); +#endif //QT_NO_STATUSTIP #ifndef QT_NO_ACTION case QEvent::ActionChanged: case QEvent::ActionAdded: @@ -249,8 +257,10 @@ static QEvent *cloneEvent(QEvent *e) case QEvent::FileOpen: return new QFileOpenEvent(*static_cast<QFileOpenEvent*>(e)); +#ifndef QT_NO_SHORTCUT case QEvent::Shortcut: return new QShortcutEvent(*static_cast<QShortcutEvent*>(e)); +#endif //QT_NO_SHORTCUT case QEvent::ShortcutOverride: return new QKeyEvent(*static_cast<QKeyEvent*>(e)); @@ -263,11 +273,15 @@ static QEvent *cloneEvent(QEvent *e) break; #endif +#ifndef QT_NO_WHATSTHIS case QEvent::WhatsThisClicked: return new QWhatsThisClickedEvent(*static_cast<QWhatsThisClickedEvent*>(e)); +#endif //QT_NO_WHATSTHIS +#ifndef QT_NO_TOOLBAR case QEvent::ToolBarChange: return new QToolBarChangeEvent(*static_cast<QToolBarChangeEvent*>(e)); +#endif //QT_NO_TOOLBAR case QEvent::ApplicationActivate: return new QEvent(*e); @@ -397,9 +411,11 @@ static QEvent *cloneEvent(QEvent *e) case QEvent::DynamicPropertyChange: return new QDynamicPropertyChangeEvent(*static_cast<QDynamicPropertyChangeEvent*>(e)); +#ifndef QT_NO_TABLETEVENT case QEvent::TabletEnterProximity: case QEvent::TabletLeaveProximity: return new QTabletEvent(*static_cast<QTabletEvent*>(e)); +#endif //QT_NO_TABLETEVENT case QEvent::NonClientAreaMouseMove: case QEvent::NonClientAreaMouseButtonPress: diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 350a8e6..e0fcb92 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -281,7 +281,7 @@ void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter, drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth); break; case SE_Editor: - drawFrame(SF_Editor, painter, rect, flags | SF_PointNorth); + drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth); break; default: break; @@ -831,6 +831,11 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio); break; + case QS60StyleEnums::SP_QgnGrafBarFrameSideL: + case QS60StyleEnums::SP_QgnGrafBarFrameSideR: + result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth)); + break; + case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed: case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed: case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed: @@ -1676,18 +1681,18 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (!styleHint(SH_UnderlineShortcut, menuItem, widget)) text_flags |= Qt::TextHideMnemonic; - QRect iconRect = - subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget); - QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget); - if ((option->state & State_Selected) && (option->state & State_Enabled)) QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget); + QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget); + //todo: move the vertical spacing stuff into subElementRect const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); if (checkable){ + const int hSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing); QStyleOptionMenuItem optionCheckBox; - optionCheckBox.QStyleOption::operator=(*menuItem); + optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem); optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth)); optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight)); const int moveByX = optionCheckBox.rect.width()+vSpacing; @@ -1696,6 +1701,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, iconRect.translate(moveByX, 0); iconRect.setWidth(iconRect.width()+vSpacing); textRect.setWidth(textRect.width()-moveByX-vSpacing); + optionCheckBox.rect.translate(vSpacing/2, hSpacing/2); } else { textRect.setWidth(textRect.width()-moveByX); iconRect.setWidth(iconRect.width()+vSpacing); @@ -2292,8 +2298,18 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, { QSize sz(csz); switch (ct) { + case CT_ToolButton: + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + //FIXME properly - style should calculate the location of border frame-part + sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin)); + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) + if (toolBtn->subControls & SC_ToolButtonMenu) + sz += QSize(pixelMetric(PM_MenuButtonIndicator),0); + break; case CT_PushButton: sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + //FIXME properly - style should calculate the location of border frame-part + sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin)); if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget))) if (buttonWidget->isCheckable()) sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0); @@ -2572,8 +2588,8 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple break; case CC_ToolButton: if (const QStyleOptionToolButton *toolButton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { - const int indicatorRect = pixelMetric(PM_MenuButtonIndicator, toolButton, widget) + - 2*pixelMetric(PM_ButtonMargin, toolButton, widget); + const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2*pixelMetric(PM_ButtonMargin); + const int border = pixelMetric(PM_ButtonMargin) + pixelMetric(PM_DefaultFrameWidth); ret = toolButton->rect; const bool popup = (toolButton->features & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay)) @@ -2585,7 +2601,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple break; case SC_ToolButtonMenu: if (popup) - ret.adjust(ret.width() - indicatorRect, ret.height() - indicatorRect, 0, 0); + ret.adjust(ret.width() - indicatorRect, border, -pixelMetric(PM_ButtonMargin), -border); break; default: break; @@ -2607,8 +2623,8 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con QRect ret; switch (element) { case SE_LineEditContents: { - // in S60 the input text box doesn't start from line Edit's TL, but - // a bit indented. + // in S60 the input text box doesn't start from line Edit's TL, but + // a bit indented. QRect lineEditRect = opt->rect; const int adjustment = opt->rect.height()>>2; lineEditRect.adjust(adjustment,0,0,0); diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 54af757..46547bf 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -361,7 +361,6 @@ public: SF_ToolBarButtonPressed, SF_PanelBackground, SF_ButtonInactive, - SF_Editor, }; enum SkinElementFlag { diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 0cd87bd..c2a207c 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -319,16 +319,6 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { /* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b8}, /* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b9}, - /* SP_QsnFrNotepadCornerTl */ {KAknsIIDQsnFrNotepadContCornerTl, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadCornerTr */ {KAknsIIDQsnFrNotepadContCornerTr, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadCornerBl */ {KAknsIIDQsnFrNotepadCornerBl, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadCornerBr */ {KAknsIIDQsnFrNotepadCornerBr, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadSideT */ {KAknsIIDQsnFrNotepadContSideT, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadSideB */ {KAknsIIDQsnFrNotepadSideB, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadSideL */ {KAknsIIDQsnFrNotepadSideL, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadSideR */ {KAknsIIDQsnFrNotepadSideR, ENoDraw, ES60_AllReleases, -1,-1}, - /* SP_QsnFrNotepadCenter */ {KAknsIIDQsnFrNotepadCenter, EDrawIcon, ES60_AllReleases, -1,-1}, - }; QPixmap QS60StyleModeSpecifics::skinnedGraphics( @@ -852,10 +842,6 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme centerId.Set(KAknsIIDNone); frameId.Set(KAknsIIDQsnFrSetOpt); break; - case QS60StylePrivate::SF_Editor: - centerId.Set(KAknsIIDQsnFrNotepadCenter); - frameId.Set(KAknsIIDQsnFrNotepadCont); - break; default: // center should be correct here frameId.iMinor = centerId.iMinor - 9; diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp index f5a2b94..d73a563 100644 --- a/src/gui/styles/qstyleoption.cpp +++ b/src/gui/styles/qstyleoption.cpp @@ -4736,8 +4736,9 @@ QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(const QStyleOptionTab QStyleOptionFrame types. If the \a{other} style option's version is 1, this style option's - \l FrameFeature value is set to \l QStyleOptionFrameV2::None. If - its version is 2, its \l FrameFeature value is simply copied to + QStyleOptionFrameV2::FrameFeature value is set to + QStyleOptionFrameV2::None. If its version is 2, its + \l{QStyleOptionFrameV2::}{FrameFeature} value is simply copied to this style option. */ QStyleOptionTabWidgetFrameV2 &QStyleOptionTabWidgetFrameV2::operator=(const QStyleOptionTabWidgetFrame &other) diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index ae1d33a..ce73fd8 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -3325,9 +3325,14 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q break; case CE_PushButton: - ParentStyle::drawControl(ce, opt, p, w); - return; - + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() || + ((btn->features & QStyleOptionButton::HasMenu) && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator))) { + ParentStyle::drawControl(ce, opt, p, w); + return; + } + } + break; case CE_PushButtonBevel: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { QStyleOptionButton btnOpt(*btn); @@ -3370,7 +3375,9 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if (rule.hasPosition() && rule.position()->textAlignment != 0) { Qt::Alignment textAlignment = rule.position()->textAlignment; QRect textRect = button->rect; - uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + uint tf = Qt::TextShowMnemonic; + const uint verticalAlignMask = Qt::AlignVCenter | Qt::AlignTop | Qt::AlignLeft; + tf |= (textAlignment & verticalAlignMask) ? (textAlignment & verticalAlignMask) : Qt::AlignVCenter; if (!styleHint(SH_UnderlineShortcut, button, w)) tf |= Qt::TextHideMnemonic; if (!button->icon.isNull()) { @@ -3599,6 +3606,27 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q } } else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) { QWindowsStyle::drawControl(ce, &mi, p, w); + if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) { + // We have a style defined, but QWindowsStyle won't draw anything if not checked. + // So we mimick what QWindowsStyle would do. + int checkcol = qMax<int>(mi.maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth); + QRect vCheckRect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x(), mi.rect.y(), checkcol, mi.rect.height())); + if (mi.state.testFlag(State_Enabled) && mi.state.testFlag(State_Selected)) { + qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &mi.palette.brush(QPalette::Button)); + } else { + QBrush fill(mi.palette.light().color(), Qt::Dense4Pattern); + qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &fill); + } + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); + if (subSubRule.hasDrawable()) { + QStyleOptionMenuItem newMi(mi); + newMi.rect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x() + QWindowsStylePrivate::windowsItemFrame, + mi.rect.y() + QWindowsStylePrivate::windowsItemFrame, + checkcol - 2 * QWindowsStylePrivate::windowsItemFrame, + mi.rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame)); + drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w); + } + } } else { if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) { mi.palette.setColor(QPalette::Window, Qt::transparent); @@ -3668,7 +3696,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q } if (!cb->currentText.isEmpty() && !cb->editable) { drawItemText(p, editRect.adjusted(0, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->palette, - cb->state & State_Enabled, cb->currentText); + cb->state & State_Enabled, cb->currentText, QPalette::Text); } p->restore(); return; @@ -4275,23 +4303,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op p->fillRect(v2->rect, v2->palette.alternateBase()); subRule.drawRule(p, opt->rect); } else { - QStyleOptionViewItemV2 v2Copy(*v2); - if (v2->showDecorationSelected) { - QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ViewItem); - if (v2->state & QStyle::State_Selected) { - subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::Highlight); - } else if (v2->features & QStyleOptionViewItemV2::Alternate) { - subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase); - } else if (subRule2.hasBackground()) { - p->fillRect(v2->rect, subRule2.background()->brush); - } - } else if (v2->features & QStyleOptionViewItemV2::Alternate) { - quint64 pc = v2->state & QStyle::State_Enabled ? PseudoClass_Enabled : PseudoClass_Disabled; - pc |= PseudoClass_Alternate; - QRenderRule subRule2 = renderRule(w, PseudoElement_ViewItem, pc); - subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase); - } - baseStyle()->drawPrimitive(pe, &v2Copy, p, w); + baseStyle()->drawPrimitive(pe, v2, p, w); } } return; @@ -4356,18 +4368,6 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op break; case PE_PanelItemViewItem: - if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) { - rect = subElementRect(QStyle::SE_ItemViewItemText, opt, w) - | subElementRect(QStyle::SE_ItemViewItemDecoration, opt, w) - | subElementRect(QStyle::SE_ItemViewItemCheckIndicator, opt, w); - } - pseudoElement = PseudoElement_ViewItem; - break; - - case PE_PanelItemViewRow: - ParentStyle::drawPrimitive(pe, opt, p, w); - if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) - return; pseudoElement = PseudoElement_ViewItem; break; diff --git a/src/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp index 406633e..f79f8e0 100644 --- a/src/gui/styles/qstylesheetstyle_default.cpp +++ b/src/gui/styles/qstylesheetstyle_default.cpp @@ -203,49 +203,6 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const ADD_STYLE_RULE; } - /*QLineEdit[style="QCleanlooksStyle"] { - padding-top: 2px; - padding-bottom: 2px; - }*/ - if (baseStyle()->inherits("QCleanlooksStyle")) - { - SET_ELEMENT_NAME(QLatin1String("QLineEdit")); - ADD_BASIC_SELECTOR; - ADD_SELECTOR; - - - SET_PROPERTY(QLatin1String("padding-top"), PaddingTop); - ADD_VALUE(Value::Identifier, QString::fromLatin1("2px")); - ADD_DECLARATION; - - SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom); - ADD_VALUE(Value::Identifier, QString::fromLatin1("2px")); - ADD_DECLARATION; - - ADD_STYLE_RULE; - } - - /*QLineEdit[style="QWindowsXPStyle"], - QLineEdit[style="QWindowsVistaStyle"], - QLineEdit[style="QGtkStyle"] { - padding-top: 1px; - padding-bottom: 1px; - }*/ - if (baseStyle()->inherits("QWindowsXPStyle") || baseStyle()->inherits("QGtkStyle")) - { - SET_ELEMENT_NAME(QLatin1String("QLineEdit")); - - SET_PROPERTY(QLatin1String("padding-top"), PaddingTop); - ADD_VALUE(Value::Identifier, QString::fromLatin1("1px")); - ADD_DECLARATION; - - SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom); - ADD_VALUE(Value::Identifier, QString::fromLatin1("1px")); - ADD_DECLARATION; - - ADD_STYLE_RULE; - } - /*QFrame { border: native; }*/ diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 5cf738e..f894b82 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -115,14 +115,6 @@ QT_BEGIN_INCLUDE_NAMESPACE #include <limits.h> QT_END_INCLUDE_NAMESPACE -static const int windowsItemFrame = 2; // menu item frame width -static const int windowsSepHeight = 9; // separator item height -static const int windowsItemHMargin = 3; // menu item hor text margin -static const int windowsItemVMargin = 2; // menu item ver text margin -static const int windowsArrowHMargin = 6; // arrow horizontal margin -static const int windowsRightBorder = 15; // right border on windows -static const int windowsCheckMarkWidth = 12; // checkmarks width on windows - enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* @@ -1847,7 +1839,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai bool act = menuitem->state & State_Selected; // windows always has a check column, regardless whether we have an icon or not - int checkcol = qMax(menuitem->maxIconWidth, windowsCheckMarkWidth); + int checkcol = qMax<int>(menuitem->maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth); QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); p->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill); @@ -1903,8 +1895,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai newMi.state |= State_Enabled; if (act) newMi.state |= State_On; - newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame, - checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame)); + newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + QWindowsStylePrivate::windowsItemFrame, + menuitem->rect.y() + QWindowsStylePrivate::windowsItemFrame, + checkcol - 2 * QWindowsStylePrivate::windowsItemFrame, + menuitem->rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame)); proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget); } p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color()); @@ -1915,9 +1909,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->setPen(discol); } - int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xm = QWindowsStylePrivate::windowsItemFrame + checkcol + QWindowsStylePrivate::windowsItemHMargin; int xpos = menuitem->rect.x() + xm; - QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin, + w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin); QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); QString s = menuitem->text; if (!s.isEmpty()) { // draw text @@ -1951,10 +1946,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->restore(); } if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow - int dim = (h - 2 * windowsItemFrame) / 2; + int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2; PrimitiveElement arrow; arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; - xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; + xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim; QRect vSubMenuRect = visualRect(opt->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); QStyleOptionMenuItem newMI = *menuitem; newMI.rect = vSubMenuRect; @@ -2994,6 +2989,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp #ifndef QT_NO_COMBOBOX case CC_ComboBox: if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { + p->save(); QBrush editBrush = cmb->palette.brush(QPalette::Base); if ((cmb->subControls & SC_ComboBoxFrame)) { if (cmb->frame) { @@ -3063,6 +3059,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget); } } + p->restore(); } break; #endif // QT_NO_COMBOBOX @@ -3191,7 +3188,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); if (mi->menuItemType == QStyleOptionMenuItem::Separator) { - sz = QSize(10, windowsSepHeight); + sz = QSize(10, QWindowsStylePrivate::windowsSepHeight); } else if (mi->icon.isNull()) { sz.setHeight(sz.height() - 2); @@ -3202,14 +3199,14 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); sz.setHeight(qMax(sz.height(), mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() - + 2 * windowsItemFrame)); + + 2 * QWindowsStylePrivate::windowsItemFrame)); } int maxpmw = mi->maxIconWidth; int tabSpacing = 20; if (mi->text.contains(QLatin1Char('\t'))) w += tabSpacing; else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 2 * windowsArrowHMargin; + w += 2 * QWindowsStylePrivate::windowsArrowHMargin; else if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem) { // adjust the font and add the difference in size. // it would be better if the font could be adjusted in the initStyleOption qmenu func!! @@ -3220,9 +3217,9 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, w += fmBold.width(mi->text) - fm.width(mi->text); } - int checkcol = qMax(maxpmw, windowsCheckMarkWidth); // Windows always shows a check column + int checkcol = qMax<int>(maxpmw, QWindowsStylePrivate::windowsCheckMarkWidth); // Windows always shows a check column w += checkcol; - w += windowsRightBorder + 10; + w += QWindowsStylePrivate::windowsRightBorder + 10; sz.setWidth(w); } break; @@ -3230,7 +3227,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, #ifndef QT_NO_MENUBAR case CT_MenuBarItem: if (!sz.isEmpty()) - sz += QSize(windowsItemHMargin * 4, windowsItemVMargin * 2); + sz += QSize(QWindowsStylePrivate::windowsItemHMargin * 4, QWindowsStylePrivate::windowsItemVMargin * 2); break; #endif // Otherwise, fall through diff --git a/src/gui/styles/qwindowsstyle_p.h b/src/gui/styles/qwindowsstyle_p.h index fb84dce..d81c82b 100644 --- a/src/gui/styles/qwindowsstyle_p.h +++ b/src/gui/styles/qwindowsstyle_p.h @@ -87,7 +87,17 @@ public: QColor activeGradientCaptionColor; QColor inactiveCaptionColor; QColor inactiveGradientCaptionColor; + + enum { + windowsItemFrame = 2, // menu item frame width + windowsSepHeight = 9, // separator item height + windowsItemHMargin = 3, // menu item hor text margin + windowsItemVMargin = 2, // menu item ver text margin + windowsArrowHMargin = 6, // arrow horizontal margin + windowsRightBorder = 15, // right border on windows + windowsCheckMarkWidth = 12 // checkmarks width on windows }; +}; QT_END_NAMESPACE diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 6db86bd..93b9fc6 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1129,19 +1129,22 @@ static bool setFontWeightFromValue(const Value &value, QFont *font) static bool setFontFamilyFromValues(const QVector<Value> &values, QFont *font, int start = 0) { QString family; + bool shouldAddSpace = false; for (int i = start; i < values.count(); ++i) { const Value &v = values.at(i); if (v.type == Value::TermOperatorComma) { family += QLatin1Char(','); + shouldAddSpace = false; continue; } const QString str = v.variant.toString(); if (str.isEmpty()) break; + if (shouldAddSpace) + family += QLatin1Char(' '); family += str; - family += QLatin1Char(' '); + shouldAddSpace = true; } - family = family.simplified(); if (family.isEmpty()) return false; font->setFamily(family); diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index fb8444e..7e93aa0 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -533,7 +533,13 @@ static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Vietnamese, { 0, 127 }, // same as latin1 // Other, - { 126, 127 } + { 126, 127 }, + // Ogham, + { 78, 127 }, + // Runic, + { 79, 127 }, + // Nko, + { 14, 127 }, }; #define SimplifiedChineseCsbBit 18 @@ -873,7 +879,8 @@ static const int scriptForWritingSystem[] = { QUnicodeTables::Common, // Braille QUnicodeTables::Common, // Symbol QUnicodeTables::Ogham, // Ogham - QUnicodeTables::Runic // Runic + QUnicodeTables::Runic, // Runic + QUnicodeTables::Nko // Nko }; @@ -881,12 +888,12 @@ static const int scriptForWritingSystem[] = { static inline bool requiresOpenType(int writingSystem) { return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) - || writingSystem == QFontDatabase::Khmer); + || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); } static inline bool scriptRequiresOpenType(int script) { return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) - || script == QUnicodeTables::Khmer); + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); } #endif @@ -1558,6 +1565,7 @@ QFontDatabase::QFontDatabase() \value Other (the same as Symbol) \value Ogham \value Runic + \value Nko \omitvalue WritingSystemsCount */ @@ -2232,6 +2240,9 @@ QString QFontDatabase::writingSystemName(WritingSystem writingSystem) case Runic: name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic"); break; + case Nko: + name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko"); + break; default: Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter"); break; @@ -2445,6 +2456,12 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem) sample += QChar(0x16a2); sample += QChar(0x16a3); break; + case Nko: + sample += QChar(0x7ca); + sample += QChar(0x7cb); + sample += QChar(0x7cc); + sample += QChar(0x7cd); + break; default: break; } diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index e6dcfc9..37b5860 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -108,6 +108,7 @@ public: Ogham, Runic, + Nko, WritingSystemsCount }; diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index f184811..dd575f9 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -155,187 +155,187 @@ static const char writingSystems_for_xlfd_encoding[sizeof(xlfd_encoding)][QFontD { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-2 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-3 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-4 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-9 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-10 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-13 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-14 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-15 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // hp-roman8 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-5 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // *-cp1251 { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // koi8-ru { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // koi8-u { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // koi8-r { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-7 { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-8 { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // gb18030-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0 }, + 0, 0 }, // gb18030.2000-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0 }, + 0, 0 }, // gbk-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0 }, + 0, 0 }, // gb2312.*-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0 }, + 0, 0 }, // jisx0201*-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0 }, + 0, 0 }, // jisx0208*-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0 }, + 0, 0 }, // ksc5601*-* { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0 }, + 0, 0 }, // big5hkscs-0 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0 }, + 0, 0 }, // hkscs-1 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0 }, + 0, 0 }, // big5*-* { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0 }, + 0, 0 }, // tscii-* { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // tis620*-* { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso8859-11 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // mulelao-1 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // ethiopic-unicode { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 }, + 0, 0 }, // iso10646-1 { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0 }, + 0, 0 }, // unicode-* { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0 }, + 0, 0 }, // *-symbol { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1 }, + 1, 0 }, // *-fontspecific { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1 }, + 1, 0 }, // fontspecific-* { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1 } + 1, 0 } }; @@ -835,7 +835,8 @@ static const char *specialLanguages[] = { "ko", // Hangul "", // Ogham "", // Runic - "km" // Khmer + "km", // Khmer + "" // N'Ko }; enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; @@ -866,7 +867,8 @@ static const ushort specialChars[] = { 0, // Hangul 0x1681, // Ogham 0x16a0, // Runic - 0 // Khmer + 0, // Khmer + 0x7ca // N'Ko }; enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; @@ -905,7 +907,8 @@ static const char *languageForWritingSystem[] = { "vi", // Vietnamese 0, // Symbol 0, // Ogham - 0 // Runic + 0, // Runic + 0 // N'Ko }; enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; @@ -944,7 +947,8 @@ static const ushort sampleCharForWritingSystem[] = { 0, // Vietnamese 0, // Symbol 0x1681, // Ogham - 0x16a0 // Runic + 0x16a0, // Runic + 0x7ca // N'Ko }; enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; @@ -984,7 +988,8 @@ static const char *openType[] = { 0, // Vietnamese 0, // Symbol 0, // Ogham - 0 // Runic + 0, // Runic + "nko " // N'Ko }; enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) }; @@ -1472,7 +1477,7 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD !(request.styleStrategy & QFont::NoAntialias)); } - if (script != QUnicodeTables::Common) { + if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { Q_ASSERT(script < QUnicodeTables::ScriptCount); FcLangSet *ls = FcLangSetCreate(); FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); @@ -1615,7 +1620,7 @@ static QFontEngine *tryPatternLoad(FcPattern *p, int screen, goto done; if (!FcCharSetHasChar(cs, specialChars[script])) goto done; - } else { + } else if (*specialLanguages[script] != '\0'){ FcLangSet *langSet = 0; if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch) goto done; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 9ffedf9..2bfe33c 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -911,7 +911,7 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; case QEvent::MouseButtonPress: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mousePressEvent(ev->button(), matrix.map(ev->pos()), ev->modifiers(), + d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), ev->globalPos()); break; } case QEvent::MouseMove: { @@ -979,7 +979,7 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMousePress: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mousePressEvent(ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), ev->screenPos()); break; } case QEvent::GraphicsSceneMouseMove: { @@ -1467,7 +1467,7 @@ QRectF QTextControl::selectionRect() const return selectionRect(d->cursor); } -void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, +void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); @@ -1481,11 +1481,11 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF cursor.clearSelection(); } } - if (!(button & Qt::LeftButton)) - return; - - if (!((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) - return; + if (!(button & Qt::LeftButton) || + !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) { + e->ignore(); + return; + } cursorIsFocusIndicator = false; const QTextCursor oldSelection = cursor; @@ -1509,8 +1509,10 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF trippleClickTimer.stop(); } else { int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) + if (cursorPos == -1) { + e->ignore(); return; + } #if !defined(QT_NO_IM) QTextLayout *layout = cursor.block().layout(); @@ -1521,8 +1523,10 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF button, buttons, modifiers); ctx->mouseHandler(cursorPos - cursor.position(), &ev); } - if (!layout->preeditAreaText().isEmpty()) + if (!layout->preeditAreaText().isEmpty()) { + e->ignore(); return; + } } #endif if (modifiers == Qt::ShiftModifier) { diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index ca9db9f..66459f6 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -131,10 +131,10 @@ public: QString anchorForCursor(const QTextCursor &anchor) const; void keyPressEvent(QKeyEvent *e); - void mousePressEvent(Qt::MouseButton button, const QPointF &pos, + void mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, - const QPoint &globalPos = QPoint()); + const QPoint &globalPos); void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos); void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos); void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos); diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 85b539f..fd84949 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -293,8 +293,6 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme) have desktop concept, DesktopLocation returns same path as DocumentsLocation. Rest of the standard locations point to folder on same drive with executable, except that if executable is in ROM the folder from C drive is returned. - - \endcode */ /*! diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 1879db4..bd1d8ba 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -1111,6 +1111,32 @@ void QComboBoxPrivate::updateLineEditGeometry() lineEdit->setGeometry(editRect); } +Qt::MatchFlags QComboBoxPrivate::matchFlags() const +{ + // Base how duplicates are determined on the autocompletion case sensitivity + Qt::MatchFlags flags = Qt::MatchFixedString; +#ifndef QT_NO_COMPLETER + if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive) +#endif + flags |= Qt::MatchCaseSensitive; + return flags; +} + + +void QComboBoxPrivate::_q_editingFinished() +{ + Q_Q(QComboBox); + if (lineEdit && !lineEdit->text().isEmpty()) { + //here we just check if the current item was entered + const int index = q_func()->findText(lineEdit->text(), matchFlags()); + if (index != -1 && itemText(currentIndex) != lineEdit->text()) { + q->setCurrentIndex(index); + emitActivated(currentIndex); + } + } + +} + void QComboBoxPrivate::_q_returnPressed() { Q_Q(QComboBox); @@ -1123,13 +1149,7 @@ void QComboBoxPrivate::_q_returnPressed() // check for duplicates (if not enabled) and quit int index = -1; if (!duplicatesEnabled) { - // Base how duplicates are determined on the autocompletion case sensitivity - Qt::MatchFlags flags = Qt::MatchFixedString; -#ifndef QT_NO_COMPLETER - if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive) -#endif - flags |= Qt::MatchCaseSensitive; - index = q->findText(text, flags); + index = q->findText(text, matchFlags()); if (index != -1) { q->setCurrentIndex(index); emitActivated(currentIndex); @@ -1664,6 +1684,7 @@ void QComboBox::setLineEdit(QLineEdit *edit) if (d->lineEdit->parent() != this) d->lineEdit->setParent(this); connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed())); + connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished())); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString))); #ifdef QT3_SUPPORT connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString))); @@ -1960,7 +1981,7 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) if (lineEdit) { QString newText = q->itemText(currentIndex.row()); if (lineEdit->text() != newText) - lineEdit->setText(q->itemText(currentIndex.row())); + lineEdit->setText(newText); updateLineEditGeometry(); } if (indexChanged) { diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h index 0652594..5d5ea21 100644 --- a/src/gui/widgets/qcombobox.h +++ b/src/gui/widgets/qcombobox.h @@ -304,6 +304,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_itemSelected(const QModelIndex &item)) Q_PRIVATE_SLOT(d_func(), void _q_emitHighlighted(const QModelIndex &)) Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentIndexChanged(const QModelIndex &index)) + Q_PRIVATE_SLOT(d_func(), void _q_editingFinished()) Q_PRIVATE_SLOT(d_func(), void _q_returnPressed()) Q_PRIVATE_SLOT(d_func(), void _q_resetButton()) Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &, const QModelIndex &)) diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index fe42c47..f6ba57c 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -342,6 +342,8 @@ public: void init(); QComboBoxPrivateContainer* viewContainer(); void updateLineEditGeometry(); + Qt::MatchFlags matchFlags() const; + void _q_editingFinished(); void _q_returnPressed(); void _q_complete(); void _q_itemSelected(const QModelIndex &item); diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 0fc94c9..2914164 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1511,6 +1511,18 @@ void QLineControl::processKeyEvent(QKeyEvent* event) } #endif // QT_NO_COMPLETER + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + if (hasAcceptableInput() || fixup()) { + emit accepted(); + emit editingFinished(); + } + if (inlineCompletionAccepted) + event->accept(); + else + event->ignore(); + return; + } + if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing() && !isReadOnly() @@ -1531,17 +1543,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event) clear(); } - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - if (hasAcceptableInput() || fixup()) { - emit accepted(); - emit editingFinished(); - } - if (inlineCompletionAccepted) - event->accept(); - else - event->ignore(); - return; - } bool unknown = false; if (false) { diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 1b5d1cd..cc39b7f 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -273,7 +273,7 @@ void QMenuPrivate::updateActionRects() const for (int i = 0; i < actions.count(); ++i) { QAction *action = actions.at(i); - if (action->isSeparator() || !action->isVisible() || widgetItems.at(i)) + if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action)) continue; //..and some members hasCheckableItems |= action->isCheckable(); @@ -301,7 +301,7 @@ void QMenuPrivate::updateActionRects() const const QFontMetrics &fm = opt.fontMetrics; QSize sz; - if (QWidget *w = widgetItems.at(i)) { + if (QWidget *w = widgetItems.value(action)) { sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize()); } else { //calc what I think the size is.. @@ -370,7 +370,7 @@ void QMenuPrivate::updateActionRects() const rect.setWidth(max_column_width); //uniform width //we need to update the widgets geometry - if (QWidget *widget = widgetItems.at(i)) { + if (QWidget *widget = widgetItems.value(actions.at(i))) { widget->setGeometry(rect); widget->setVisible(actions.at(i)->isVisible()); } @@ -583,8 +583,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason q->update(actionRect(action)); if (reason == SelectedFromKeyboard) { - const int actionIndex = actions.indexOf(action); - QWidget *widget = widgetItems.at(actionIndex); + QWidget *widget = widgetItems.value(action); if (widget) { if (widget->focusPolicy() != Qt::NoFocus) widget->setFocus(Qt::TabFocusReason); @@ -800,7 +799,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc current.moveTop(current.top() + delta); //we need to update the widgets geometry - if (QWidget *w = widgetItems.at(i)) + if (QWidget *w = widgetItems.value(actions.at(i))) w->setGeometry(current); } } @@ -1392,11 +1391,12 @@ QMenu::QMenu(QMenuPrivate &dd, QWidget *parent) QMenu::~QMenu() { Q_D(QMenu); - for (int i = 0; i < d->widgetItems.count(); ++i) { - if (QWidget *widget = d->widgetItems.at(i)) { - QWidgetAction *action = static_cast<QWidgetAction *>(d->actions.at(i)); + QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin(); + for (; it != d->widgetItems.end(); ++it) { + if (QWidget *widget = it.value()) { + QWidgetAction *action = static_cast<QWidgetAction *>(it.key()); action->releaseWidget(widget); - d->widgetItems[i] = 0; + *it = 0; } } @@ -1878,9 +1878,11 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if(snapToMouse) //position flowing left from the mouse pos.setX(mouse.x()-size.width()); +#ifndef QT_NO_MENUBAR //if in a menubar, it should be right-aligned if (qobject_cast<QMenuBar*>(d->causedPopup.widget)) pos.rx() -= size.width(); +#endif //QT_NO_MENUBAR if (pos.x() < screen.left()+desktopFrame) pos.setX(qMax(p.x(), screen.left()+desktopFrame)); @@ -2151,7 +2153,7 @@ void QMenu::paintEvent(QPaintEvent *e) QAction *action = d->actions.at(i); QRect adjustedActionRect = d->actionRects.at(i); if (!e->rect().intersects(adjustedActionRect) - || d->widgetItems.at(i)) + || d->widgetItems.value(action)) continue; //set the clip region to be extra safe (and adjust for the scrollers) QRegion adjustedActionReg(adjustedActionRect); @@ -2862,25 +2864,20 @@ void QMenu::actionEvent(QActionEvent *e) connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered())); } - QWidget *widget = 0; - if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) - widget = wa->requestWidget(this); - - int index = d->actions.indexOf(e->action()); - Q_ASSERT(index != -1); - d->widgetItems.insert(index, widget); - + if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) { + QWidget *widget = wa->requestWidget(this); + if (widget) + d->widgetItems.insert(wa, widget); + } } else if (e->type() == QEvent::ActionRemoved) { e->action()->disconnect(this); if (e->action() == d->currentAction) d->currentAction = 0; - int index = d->actions.indexOf(e->before()) + 1; if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) { - if (QWidget *widget = d->widgetItems.at(index)) + if (QWidget *widget = d->widgetItems.value(wa)) wa->releaseWidget(widget); } - Q_ASSERT(index != -1); - d->widgetItems.removeAt(index); + d->widgetItems.remove(e->action()); } #ifdef Q_WS_MAC diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index b238faf..9510cc6 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1191,7 +1191,7 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction #endif } - QWidget *widget = qmenu ? qmenu->widgetItems.value(qmenu->actions.indexOf(action->action)) : 0; + QWidget *widget = qmenu ? qmenu->widgetItems.value(action->action) : 0; if (widget) { #ifndef QT_MAC_USE_COCOA ChangeMenuAttributes(action->menu, kMenuAttrDoNotCacheImage, 0); diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 9348f7b..a5bde7c 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -190,7 +190,7 @@ public: QRect actionRect(QAction *) const; mutable QVector<QRect> actionRects; - mutable QWidgetList widgetItems; + mutable QHash<QAction *, QWidget *> widgetItems; void updateActionRects() const; QRect popupGeometry(const QWidget *widget) const; QRect popupGeometry(int screen = -1) const; diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index bdd3c75..13ee346 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -88,8 +88,6 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo const QRect final_geometry = _final_geometry.isValid() || widget->isWindow() ? _final_geometry : QRect(QPoint(-500 - widget->width(), -500 - widget->height()), widget->size()); - if (r == final_geometry) - return; //the widget is already where it should be #ifndef QT_NO_ANIMATION AnimationMap::const_iterator it = m_animation_map.constFind(widget); if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry) @@ -116,9 +114,4 @@ bool QWidgetAnimator::animating() const return !m_animation_map.isEmpty(); } -bool QWidgetAnimator::animating(QWidget *widget) const -{ - return m_animation_map.contains(widget); -} - QT_END_NAMESPACE diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h index 68d9344..095380f 100644 --- a/src/gui/widgets/qwidgetanimator_p.h +++ b/src/gui/widgets/qwidgetanimator_p.h @@ -70,7 +70,6 @@ public: QWidgetAnimator(QMainWindowLayout *layout); void animate(QWidget *widget, const QRect &final_geometry, bool animate); bool animating() const; - bool animating(QWidget *widget) const; void abort(QWidget *widget); |