summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-10-26 10:41:56 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-10-26 10:41:56 (GMT)
commit968f7c0e65a293a7d7b9a87601e853894d9794ed (patch)
tree3a86b71dd69cf4b759bb20b62c18cfeb02a28ef0 /src/gui
parent3481db791c3b48e28f1a9531b247adf6562edb71 (diff)
parente2ef97128c006ac2a5c99c67bb54eebaa3b45720 (diff)
downloadQt-968f7c0e65a293a7d7b9a87601e853894d9794ed.zip
Qt-968f7c0e65a293a7d7b9a87601e853894d9794ed.tar.gz
Qt-968f7c0e65a293a7d7b9a87601e853894d9794ed.tar.bz2
Merge branch '4.6' into 4.6-platform
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/animation/qguivariantanimation.cpp8
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm4
-rw-r--r--src/gui/dialogs/qwizard.cpp2
-rw-r--r--src/gui/dialogs/qwizard_win.cpp2
-rw-r--r--src/gui/effects/qgraphicseffect.cpp19
-rw-r--r--src/gui/effects/qgraphicseffect.h1
-rw-r--r--src/gui/effects/qgraphicseffect_p.h12
-rw-r--r--src/gui/embedded/qdecorationdefault_qws.cpp2
-rw-r--r--src/gui/embedded/qdecorationwindows_qws.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.cpp147
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp52
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h80
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp15
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp258
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h7
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp68
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicstransform.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp13
-rw-r--r--src/gui/image/qimage.cpp23
-rw-r--r--src/gui/image/qpixmap.cpp12
-rw-r--r--src/gui/itemviews/qheaderview.cpp2
-rw-r--r--src/gui/itemviews/qlistview.cpp44
-rw-r--r--src/gui/itemviews/qlistview_p.h1
-rw-r--r--src/gui/itemviews/qtreeview.cpp12
-rw-r--r--src/gui/kernel/kernel.pri1
-rw-r--r--src/gui/kernel/qapplication.cpp41
-rw-r--r--src/gui/kernel/qapplication_win.cpp2
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm7
-rw-r--r--src/gui/kernel/qdesktopwidget.cpp67
-rw-r--r--src/gui/kernel/qdesktopwidget.h6
-rw-r--r--src/gui/kernel/qevent.cpp78
-rw-r--r--src/gui/kernel/qevent.h13
-rw-r--r--src/gui/kernel/qevent_p.h14
-rw-r--r--src/gui/kernel/qgesture.cpp26
-rw-r--r--src/gui/kernel/qgesture.h22
-rw-r--r--src/gui/kernel/qgesture_p.h9
-rw-r--r--src/gui/kernel/qgesturemanager.cpp414
-rw-r--r--src/gui/kernel/qgesturemanager_p.h18
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp2
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac.mm8
-rw-r--r--src/gui/kernel/qstandardgestures.cpp12
-rw-r--r--src/gui/kernel/qwidget.cpp50
-rw-r--r--src/gui/kernel/qwidget_mac.mm2
-rw-r--r--src/gui/kernel/qwidget_p.h66
-rw-r--r--src/gui/kernel/qwidget_win.cpp4
-rw-r--r--src/gui/kernel/qwidget_x11.cpp2
-rw-r--r--src/gui/kernel/qwinnativepangesturerecognizer_win.cpp8
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp130
-rw-r--r--src/gui/math3d/qmatrix4x4.h7
-rw-r--r--src/gui/painting/qbackingstore.cpp5
-rw-r--r--src/gui/painting/qbackingstore_p.h11
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp2
-rw-r--r--src/gui/styles/qcommonstyle.cpp6
-rw-r--r--src/gui/styles/qmotifstyle.cpp4
-rw-r--r--src/gui/styles/qplastiquestyle.cpp8
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp2
-rw-r--r--src/gui/styles/qwindowsmobilestyle.cpp31
-rw-r--r--src/gui/text/qfont.cpp2
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/text/qfontdatabase.cpp2
-rw-r--r--src/gui/text/qfontdatabase_win.cpp12
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp16
-rw-r--r--src/gui/text/qfontengine_ft.cpp10
-rw-r--r--src/gui/text/qfontengine_qpf.cpp2
-rw-r--r--src/gui/text/qfontengine_win.cpp95
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp5
-rw-r--r--src/gui/text/qtextengine.cpp22
-rw-r--r--src/gui/text/qtextengine_mac.cpp2
-rw-r--r--src/gui/text/qtextengine_p.h17
-rw-r--r--src/gui/text/qtextlayout.cpp76
-rw-r--r--src/gui/text/qtextlayout.h4
-rw-r--r--src/gui/text/text.pri1
-rw-r--r--src/gui/widgets/qcombobox.cpp2
-rw-r--r--src/gui/widgets/qdockwidget.cpp2
-rw-r--r--src/gui/widgets/qfontcombobox.cpp2
-rw-r--r--src/gui/widgets/qlineedit.cpp2
-rw-r--r--src/gui/widgets/qmenu.cpp45
-rw-r--r--src/gui/widgets/qmenu_p.h5
-rw-r--r--src/gui/widgets/qplaintextedit.cpp5
-rw-r--r--src/gui/widgets/qpushbutton.cpp4
-rw-r--r--src/gui/widgets/qtextedit.cpp2
84 files changed, 1559 insertions, 654 deletions
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
index 0ae79b6..1e9c166 100644
--- a/src/gui/animation/qguivariantanimation.cpp
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -54,10 +54,10 @@ QT_BEGIN_NAMESPACE
template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress)
{
- return QColor(_q_interpolate(f.red(), t.red(), progress),
- _q_interpolate(f.green(), t.green(), progress),
- _q_interpolate(f.blue(), t.blue(), progress),
- _q_interpolate(f.alpha(), t.alpha(), progress));
+ return QColor(qBound(0,_q_interpolate(f.red(), t.red(), progress),255),
+ qBound(0,_q_interpolate(f.green(), t.green(), progress),255),
+ qBound(0,_q_interpolate(f.blue(), t.blue(), progress),255),
+ qBound(0,_q_interpolate(f.alpha(), t.alpha(), progress),255));
}
template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress)
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index 8e4c461..d9bec27 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -280,6 +280,10 @@ QT_USE_NAMESPACE
- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
{
Q_UNUSED(sender);
+
+ if ([filename length] == 0)
+ return NO;
+
QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename);
QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
QString path = info.absolutePath();
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index 0102e25..db1c9e9 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -1537,7 +1537,9 @@ void QWizardPrivate::handleAeroStyleChange()
vistaHelper->backButton()->show();
} else {
q->setMouseTracking(true); // ### original value possibly different
+#ifndef QT_NO_CURSOR
q->unsetCursor(); // ### ditto
+#endif
antiFlickerWidget->move(0, 0);
vistaHelper->hideBackButton();
vistaHelper->setTitleBarIconAndCaptionVisible(true);
diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp
index aa38ddc..f3f3a4e 100644
--- a/src/gui/dialogs/qwizard_win.cpp
+++ b/src/gui/dialogs/qwizard_win.cpp
@@ -387,10 +387,12 @@ bool QVistaHelper::winEvent(MSG* msg, long* result)
void QVistaHelper::setMouseCursor(QPoint pos)
{
+#ifndef QT_NO_CURSOR
if (rtTop.contains(pos))
wizard->setCursor(Qt::SizeVerCursor);
else
wizard->setCursor(Qt::ArrowCursor);
+#endif
}
void QVistaHelper::mouseEvent(QEvent *event)
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index 91641b0..96d35b0 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -253,7 +253,24 @@ bool QGraphicsEffectSource::isPixmap() const
*/
QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
{
- return d_func()->pixmap(system, offset);
+ Q_D(const QGraphicsEffectSource);
+
+ QPixmap pm;
+ if (d->m_cachedSystem == system)
+ QPixmapCache::find(d->m_cacheKey, &pm);
+
+ if (pm.isNull()) {
+ pm = d->pixmap(system, &d->m_cachedOffset);
+ d->m_cachedSystem = system;
+
+ d->invalidateCache();
+ d->m_cacheKey = QPixmapCache::insert(pm);
+ }
+
+ if (offset)
+ *offset = d->m_cachedOffset;
+
+ return pm;
}
/*!
diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h
index c5d3ede..c89851e 100644
--- a/src/gui/effects/qgraphicseffect.h
+++ b/src/gui/effects/qgraphicseffect.h
@@ -87,6 +87,7 @@ private:
friend class QGraphicsEffectPrivate;
friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
friend class QWidget;
friend class QWidgetPrivate;
};
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
index ff2fb85..fc925f2 100644
--- a/src/gui/effects/qgraphicseffect_p.h
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -55,6 +55,8 @@
#include "qgraphicseffect.h"
+#include <QPixmapCache>
+
#include <private/qobject_p.h>
#include <private/qpixmapfilter_p.h>
@@ -65,7 +67,7 @@ class QGraphicsEffectSourcePrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QGraphicsEffectSource)
public:
QGraphicsEffectSourcePrivate() : QObjectPrivate() {}
- virtual ~QGraphicsEffectSourcePrivate() {}
+ virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); }
virtual void detach() = 0;
virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0;
virtual QRect deviceRect() const = 0;
@@ -77,9 +79,16 @@ public:
virtual bool isPixmap() const = 0;
virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0;
virtual void effectBoundingRectChanged() = 0;
+ void invalidateCache() const { QPixmapCache::remove(m_cacheKey); }
+
friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
+
+private:
+ mutable Qt::CoordinateSystem m_cachedSystem;
+ mutable QPoint m_cachedOffset;
+ mutable QPixmapCache::Key m_cacheKey;
};
class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate
@@ -93,6 +102,7 @@ public:
QGraphicsEffect::ChangeFlags flags;
if (source) {
flags |= QGraphicsEffect::SourceDetached;
+ source->d_func()->invalidateCache();
source->d_func()->detach();
delete source;
}
diff --git a/src/gui/embedded/qdecorationdefault_qws.cpp b/src/gui/embedded/qdecorationdefault_qws.cpp
index 5bc8826..70389d3 100644
--- a/src/gui/embedded/qdecorationdefault_qws.cpp
+++ b/src/gui/embedded/qdecorationdefault_qws.cpp
@@ -394,7 +394,7 @@ QPixmap QDecorationDefault::pixmapFor(const QWidget *widget,
*/
int QDecorationDefault::titleBarHeight(const QWidget *)
{
- return qMax(20, QApplication::fontMetrics().lineSpacing() + BORDER_WIDTH);
+ return qMax(20, QApplication::fontMetrics().height() + BORDER_WIDTH);
}
/*!
diff --git a/src/gui/embedded/qdecorationwindows_qws.cpp b/src/gui/embedded/qdecorationwindows_qws.cpp
index 77393cf..7764ca5 100644
--- a/src/gui/embedded/qdecorationwindows_qws.cpp
+++ b/src/gui/embedded/qdecorationwindows_qws.cpp
@@ -216,7 +216,7 @@ QRegion QDecorationWindows::region(const QWidget *widget, const QRect &rect, int
bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
const QFontMetrics fontMetrics = QApplication::fontMetrics();
- int titleHeight = hasTitle ? qMax(20, fontMetrics.lineSpacing()) : 0;
+ int titleHeight = hasTitle ? qMax(20, fontMetrics.height()) : 0;
int state = widget->windowState();
bool isMinimized = state & Qt::WindowMinimized;
bool isMaximized = state & Qt::WindowMaximized;
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
index c39e8a6..e21cd99 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
@@ -48,36 +48,60 @@
\ingroup geomanagement
\ingroup graphicsview-api
- The anchor layout is a layout where one can specify how widgets should be placed relative to
- each other. The specification is called an anchor, and it is set up by calling anchor().
+ The anchor layout allows developers to specify how widgets should be placed relative to
+ each other, and to the layout itself. The specification is made by adding anchors to the
+ layout by calling addAnchor(), addAnchors() or addCornerAnchors().
+
+ Existing anchors in the layout can be accessed with the anchor() function.
+ Items that are anchored are automatically added to the layout, and if items
+ are removed, all their anchors will be automatically removed.
+
+ \beginfloatleft
+ \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets.
+ \endfloat
+
Anchors are always set up between edges of an item, where the "center" is also considered to
- be an edge. Considering this example:
- \code
- QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
- QGraphicsWidget *a = new QGraphicsWidget;
- QGraphicsWidget *b = new QGraphicsWidget;
- l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
- \endcode
-
- Here is the right edge of item A anchored to the left edge of item B, with the result that
- item B will be placed to the right of item A, with a spacing between A and B. If the
- spacing is negative, the items will overlap to some extent. Items that are anchored are
- automatically added to the layout, and if items are removed, all their anchors will be
- automatically removed
-
- \section1 Size Hints and Size Policies in QGraphicsAnchorLayout
+ be an edge. Consider the following example:
+
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors
+
+ Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom
+ edge of item \c a is anchored to the top edge of item \c b, with the result that
+ item \c b will be placed diagonally to the right and below item \c b.
+
+ The addCornerAnchors() function provides a simpler way of anchoring the corners
+ of two widgets than the two individual calls to addAnchor() shown in the code
+ above. Here, we see how a widget can be anchored to the top-left corner of the enclosing
+ layout:
+
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
+
+ In cases where anchors are used to match the widths or heights of widgets, it is
+ convenient to use the addAnchors() function. As with the other functions for specifying
+ anchors, it can also be used to anchor a widget to a layout.
+
+ \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 respect stretch factors currently. This might change in the future, so please refrain
- from using stretch factors in anchor layout to avoid any future regressions.
+ 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.
+
+ \section1 Spacing within an Anchor Layout
+
+ The layout may distribute some space between the items. If the spacing has not been
+ explicitly specified, the actual amount of space will usually be 0.
- \section1 Spacing within QGraphicsAnchorLayout
+ However, if the first edge is the \e opposite of the second edge (e.g., the right edge
+ of the first widget is anchored to the left edge of the second widget), the size of the
+ anchor will be queried from the style through a pixel metric:
+ \l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and
+ \l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors.
- Between the items, the layout can distribute some space. If the spacing has not been
- explicitly specified, the actual amount of space will usually be 0, but if the first edge
- is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the
- size of the anchor will be queried from the style through the pixelMetric
- PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors).
+ If the spacing is negative, the items will overlap to some extent.
+
+ \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout
*/
/*!
@@ -118,16 +142,26 @@ QGraphicsAnchor::~QGraphicsAnchor()
}
/*!
- Sets the size policy of the anchor to \a policy.
+ \property QGraphicsAnchor::sizePolicy
+ \brief the size policy for the QGraphicsAnchor.
+
+ By setting the size policy on an anchor you can configure how the item can resize itself
+ from its preferred spacing. For instance, if the anchor has the size policy
+ QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size
+ can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed,
+ the anchor can neither grow or shrink, which means that the only size the anchor can have
+ is the spacing. QSizePolicy::Fixed is the default size policy.
+ QGraphicsAnchor always has a minimum spacing of 0 and a very large maximum spacing.
+
+ \sa QGraphicsAnchor::spacing
*/
+
void QGraphicsAnchor::setSizePolicy(QSizePolicy::Policy policy)
{
Q_D(QGraphicsAnchor);
d->setSizePolicy(policy);
}
-/*!
- Returns the size policy of the anchor. The default size policy is QSizePolicy::Fixed
-*/
+
QSizePolicy::Policy QGraphicsAnchor::sizePolicy() const
{
Q_D(const QGraphicsAnchor);
@@ -136,12 +170,12 @@ QSizePolicy::Policy QGraphicsAnchor::sizePolicy() const
/*!
\property QGraphicsAnchor::spacing
- \brief the space between items in the QGraphicsAnchorLayout.
+ \brief the preferred space between items in the QGraphicsAnchorLayout.
Depending on the anchor type, the default spacing is either
0 or a value returned from the style.
- \sa QGraphicsAnchorLayout::anchor()
+ \sa QGraphicsAnchorLayout::addAnchor()
*/
void QGraphicsAnchor::setSpacing(qreal spacing)
{
@@ -205,7 +239,7 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout()
If there is already an anchor between the edges, the the new anchor will replace the old one.
\a firstItem and \a secondItem are automatically added to the layout if they are not part
- of the layout. This means that count() can increase with up to 2.
+ of the layout. This means that count() can increase by up to 2.
The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
Right edge of one item to the Left edge of another (or vice versa) will use the default
@@ -215,7 +249,10 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout()
The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method.
- \sa addCornerAnchors(), addAnchors()
+ Calling this function where \a firstItem or \a secondItem are ancestors of the layout have
+ undefined behaviour.
+
+ \sa addAnchors(), addCornerAnchors()
*/
QGraphicsAnchor *
QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
@@ -240,29 +277,26 @@ QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint fi
}
/*!
- Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal
- edge and another one for the vertical edge that the corners \a firstCorner and \a
- secondCorner specifies.
- The magnitude of the anchors is picked up from the style.
+ Creates two anchors between \a firstItem and \a secondItem specified by the corners,
+ \a firstCorner and \a secondCorner, where one is for the horizontal edge and another
+ one for the vertical edge.
+
+ This is a convenience function, since anchoring corners can be expressed as anchoring
+ two edges. For instance:
- This is a convenience function, since anchoring corners can be expressed as anchoring two edges.
- For instance,
- \code
- layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop);
- layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft);
- \endcode
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps
- has the same effect as
+ This can also be achieved with the following line of code:
- \code
- layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft);
- \endcode
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
If there is already an anchor between the edge pairs, it will be replaced by the anchors that
this function specifies.
\a firstItem and \a secondItem are automatically added to the layout if they are not part of the
- layout. This means that count() can increase with up to 2.
+ layout. This means that count() can increase by up to 2.
+
+ \sa addAnchor(), addAnchors()
*/
void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
Qt::Corner firstCorner,
@@ -289,17 +323,16 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
edges of \a secondItem, so that \a firstItem has the same size as
\a secondItem in the dimensions specified by \a orientations.
- Calling this convenience function with the following arguments
- \code
- l->addAnchors(firstItem, secondItem, Qt::Horizontal)
- \endcode
+ For example, the following example anchors the left and right edges of two items
+ to match their widths:
+
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps
+
+ This can also be achieved using the following line of code:
- is the same as
+ \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes
- \code
- l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft);
- l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
- \endcode
+ \sa addAnchor(), addCornerAnchors()
*/
void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem,
QGraphicsLayoutItem *secondItem,
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h
index f09ac43..01c3a86 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.h
@@ -62,12 +62,13 @@ class Q_GUI_EXPORT QGraphicsAnchor : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing RESET unsetSpacing)
+ Q_PROPERTY(QSizePolicy::Policy sizePolicy READ sizePolicy WRITE setSizePolicy)
public:
void setSpacing(qreal spacing);
void unsetSpacing();
+ qreal spacing() const;
void setSizePolicy(QSizePolicy::Policy policy);
QSizePolicy::Policy sizePolicy() const;
- qreal spacing() const;
~QGraphicsAnchor();
private:
QGraphicsAnchor(QGraphicsAnchorLayout *parent);
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 45627f6..f892bb4 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1228,7 +1228,7 @@ void QGraphicsItemCache::purge()
}
/*!
- Constructs a QGraphicsItem with the given \a parent.
+ Constructs a QGraphicsItem, passing \a item to QGraphicsItem's constructor. It does not modify \fn QObject::parent().
If \a parent is 0, you can add the item to a scene by calling
QGraphicsScene::addItem(). The item will then become a top-level item.
@@ -1511,6 +1511,8 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
the parent. You should not \l{QGraphicsScene::addItem()}{add} the
item to the scene yourself.
+ Calling this function on an item that is an ancestor of \a parent have undefined behaviour.
+
\sa parentItem(), childItems()
*/
void QGraphicsItem::setParentItem(QGraphicsItem *parent)
@@ -2482,12 +2484,14 @@ void QGraphicsItem::setOpacity(qreal opacity)
itemChange(ItemOpacityHasChanged, newOpacityVariant);
// Update.
- if (d_ptr->scene)
+ if (d_ptr->scene) {
+ d_ptr->invalidateGraphicsEffectsRecursively();
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*maybeDirtyClipPath=*/false,
/*force=*/false,
/*ignoreOpacity=*/true);
+ }
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->opacityChanged();
@@ -4735,7 +4739,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const
{
if (!item)
return false;
- return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this)
+ return qt_closestItemFirst(item, this)
&& qt_QGraphicsItem_isObscured(this, item, boundingRect());
}
@@ -4949,6 +4953,22 @@ int QGraphicsItemPrivate::depth() const
/*!
\internal
*/
+void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
+{
+ QGraphicsItemPrivate *itemPrivate = this;
+ do {
+ if (itemPrivate->graphicsEffect) {
+ itemPrivate->notifyInvalidated = 1;
+
+ if (!itemPrivate->updateDueToGraphicsEffect)
+ static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
+ }
+ } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
+}
+
+/*!
+ \internal
+*/
void QGraphicsItemPrivate::invalidateDepthRecursively()
{
if (itemDepth == -1)
@@ -5280,11 +5300,7 @@ void QGraphicsItem::update(const QRectF &rect)
return;
// Make sure we notify effects about invalidated source.
- QGraphicsItem *item = this;
- do {
- if (item->d_ptr->graphicsEffect)
- item->d_ptr->notifyInvalidated = 1;
- } while ((item = item->d_ptr->parent));
+ d_ptr->invalidateGraphicsEffectsRecursively();
if (CacheMode(d_ptr->cacheMode) != NoCache) {
// Invalidate cache.
@@ -7302,7 +7318,7 @@ void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureContext co
/*!
\property QGraphicsObject::parent
- \brief the parent of the item
+ \brief the parent of the item. It is independent from \fn QObject::parent.
\sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
*/
@@ -10721,6 +10737,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
}
pixmapPainter.end();
+
return pixmap;
}
@@ -10740,6 +10757,23 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item)
return debug;
}
+QDebug operator<<(QDebug debug, QGraphicsObject *item)
+{
+ if (!item) {
+ debug << "QGraphicsObject(0)";
+ return debug;
+ }
+
+ debug.nospace() << item->metaObject()->className() << '(' << (void*)item;
+ if (!item->objectName().isEmpty())
+ debug << ", name = " << item->objectName();
+ debug.nospace() << ", parent = " << ((void*)item->parentItem())
+ << ", pos = " << item->pos()
+ << ", z = " << item->zValue() << ", flags = "
+ << item->flags() << ')';
+ return debug.space();
+}
+
QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change)
{
const char *str = "UnknownChange";
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 2665235..f3fe99c 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -555,7 +555,7 @@ public:
using QObject::children;
#endif
- void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::WidgetWithChildrenGesture);
+ void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::ItemWithChildrenGesture);
Q_SIGNALS:
void parentChanged();
@@ -1120,6 +1120,7 @@ template <class T> inline T qgraphicsitem_cast(const QGraphicsItem *item)
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem *item);
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsObject *item);
Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change);
Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag);
Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 8696324..7c3c4f0 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -177,6 +177,7 @@ public:
wantsActive(0),
holesInSiblingIndex(0),
sequentialOrdering(1),
+ updateDueToGraphicsEffect(0),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -221,6 +222,7 @@ public:
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
int depth() const;
+ void invalidateGraphicsEffectsRecursively();
void invalidateDepthRecursively();
void resolveDepth();
void addChild(QGraphicsItem *child);
@@ -502,6 +504,7 @@ public:
quint32 wantsActive : 1;
quint32 holesInSiblingIndex : 1;
quint32 sequentialOrdering : 1;
+ quint32 updateDueToGraphicsEffect : 1;
// Optional stacking order
int globalStackingOrder;
@@ -539,7 +542,7 @@ struct QGraphicsItemPrivate::TransformData
QMatrix4x4 m;
for (int i = 0; i < graphicsTransforms.size(); ++i)
graphicsTransforms.at(i)->applyTo(&m);
- x *= m.toTransform(0);
+ x *= m.toTransform();
}
x.translate(xOrigin, yOrigin);
x.rotate(rotation);
@@ -589,8 +592,11 @@ public:
inline const QWidget *widget() const
{ return 0; }
- inline void update()
- { item->update(); }
+ inline void update() {
+ item->d_ptr->updateDueToGraphicsEffect = true;
+ item->update();
+ item->d_ptr->updateDueToGraphicsEffect = false;
+ }
inline void effectBoundingRectChanged()
{ item->prepareGeometryChange(); }
@@ -619,10 +625,76 @@ public:
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
+ QTransform lastEffectTransform;
};
/*!
+ Returns true if \a item1 is on top of \a item2.
+ The items dont need to be siblings.
+
+ \internal
+*/
+inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ // Siblings? Just check their z-values.
+ const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
+ const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
+ if (d1->parent == d2->parent)
+ return qt_closestLeaf(item1, item2);
+
+ // Find common ancestor, and each item's ancestor closest to the common
+ // ancestor.
+ int item1Depth = d1->depth();
+ int item2Depth = d2->depth();
+ const QGraphicsItem *p = item1;
+ const QGraphicsItem *t1 = item1;
+ while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
+ if (p == item2) {
+ // item2 is one of item1's ancestors; item1 is on top
+ return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
+ }
+ t1 = p;
+ --item1Depth;
+ }
+ p = item2;
+ const QGraphicsItem *t2 = item2;
+ while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
+ if (p == item1) {
+ // item1 is one of item2's ancestors; item1 is not on top
+ return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
+ }
+ t2 = p;
+ --item2Depth;
+ }
+
+ // item1Ancestor is now at the same level as item2Ancestor, but not the same.
+ const QGraphicsItem *p1 = t1;
+ const QGraphicsItem *p2 = t2;
+ while (t1 && t1 != t2) {
+ p1 = t1;
+ p2 = t2;
+ t1 = t1->d_ptr->parent;
+ t2 = t2->d_ptr->parent;
+ }
+
+ // in case we have a common ancestor, we compare the immediate children in the ancestor's path.
+ // otherwise we compare the respective items' topLevelItems directly.
+ return qt_closestLeaf(p1, p2);
+}
+
+/*!
+ Returns true if \a item2 is on top of \a item1.
+ The items dont need to be siblings.
+
+ \internal
+*/
+inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ return qt_closestItemFirst(item2, item1);
+}
+
+/*!
\internal
*/
inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
@@ -642,7 +714,7 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item
/*!
\internal
*/
-static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
{ return qt_closestLeaf(item2, item1); }
/*
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index b7a3962..64c51ad 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -57,6 +57,9 @@
#include <QtGui/qpainter.h>
#include <QtGui/qstyleoption.h>
#include <QtGui/qgraphicsview.h>
+#include <QtGui/qlistview.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qtextedit.h>
QT_BEGIN_NAMESPACE
@@ -86,7 +89,9 @@ QT_BEGIN_NAMESPACE
of embedded widgets through creating a child proxy for each popup. This
means that when an embedded QComboBox shows its popup list, a new
QGraphicsProxyWidget is created automatically, embedding the popup, and
- positioning it correctly.
+ positioning it correctly. This only works if the popup is child of the
+ embedded widget (for example QToolButton::setMenu() requires the QMenu instance
+ to be child of the QToolButton).
\section1 Embedding a Widget with QGraphicsProxyWidget
@@ -184,6 +189,7 @@ QT_BEGIN_NAMESPACE
*/
extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
+extern bool qt_tab_all_widgets;
/*!
\internal
@@ -369,6 +375,7 @@ QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuer
/*!
\internal
+ Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
*/
QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
{
@@ -382,14 +389,16 @@ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next)
child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
return 0;
- }
+ }
}
QWidget *oldChild = child;
+ uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
do {
if (child->isEnabled()
&& child->isVisibleTo(widget)
- && (child->focusPolicy() & Qt::TabFocus)) {
+ && (child->focusPolicy() & focus_flag == focus_flag)
+ && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
return child;
}
child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index a624b10..c459d21 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -242,7 +242,6 @@
#include <QtGui/qstyleoption.h>
#include <QtGui/qtooltip.h>
#include <QtGui/qtransform.h>
-#include <QtGui/qgesture.h>
#include <QtGui/qinputcontext.h>
#include <QtGui/qgraphicseffect.h>
#include <private/qapplication_p.h>
@@ -251,6 +250,14 @@
#include <private/qt_x11_p.h>
#endif
#include <private/qgraphicseffect_p.h>
+#include <private/qgesturemanager_p.h>
+
+// #define GESTURE_DEBUG
+#ifndef GESTURE_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
QT_BEGIN_NAMESPACE
@@ -1052,6 +1059,14 @@ bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event)
*/
bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
{
+ if (QGraphicsObject *object = item->toGraphicsObject()) {
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ if (qAppPriv->gestureManager) {
+ if (qAppPriv->gestureManager->filterEvent(object, event))
+ return true;
+ }
+ }
+
if (filterEvent(item, event))
return false;
if (filterDescendantEvent(item, event))
@@ -3365,6 +3380,10 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::TouchEnd:
d->touchEventHandler(static_cast<QTouchEvent *>(event));
break;
+ case QEvent::Gesture:
+ case QEvent::GestureOverride:
+ d->gestureEventHandler(static_cast<QGestureEvent *>(event));
+ break;
default:
return QObject::event(event);
}
@@ -4569,6 +4588,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
else
painter->setWorldTransform(*transformPtr);
painter->setOpacity(opacity);
+
+ if (sourced->lastEffectTransform != painter->worldTransform()) {
+ sourced->lastEffectTransform = painter->worldTransform();
+ sourced->invalidateCache();
+ }
item->d_ptr->graphicsEffect->draw(painter, source);
painter->setWorldTransform(restoreTransform);
sourced->info = 0;
@@ -5699,6 +5723,238 @@ void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
dispatchHoverEvent(&hoverEvent);
}
+void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
+ QWidget *viewport,
+ QMap<Qt::GestureType, QGesture *> *conflictedGestures,
+ QList<QList<QGraphicsObject *> > *conflictedItems,
+ QHash<QGesture *, QGraphicsObject *> *normalGestures)
+{
+ foreach (QGesture *gesture, gestures) {
+ Qt::GestureType gestureType = gesture->gestureType();
+ if (gesture->hasHotSpot()) {
+ QPoint screenPos = gesture->hotSpot().toPoint();
+ QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
+ QList<QGraphicsObject *> result;
+ for (int j = 0; j < items.size(); ++j) {
+ QGraphicsObject *item = items.at(j)->toGraphicsObject();
+ if (!item)
+ continue;
+ QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
+ if (d->gestureContext.contains(gestureType)) {
+ result.append(item);
+ }
+ }
+ DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
+ << gesture << result;
+ if (result.size() == 1) {
+ normalGestures->insert(gesture, result.first());
+ } else if (!result.isEmpty()) {
+ conflictedGestures->insert(gestureType, gesture);
+ conflictedItems->append(result);
+ }
+ }
+ }
+}
+
+void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
+{
+ QWidget *viewport = event->widget();
+ if (!viewport)
+ return;
+ QList<QGesture *> allGestures = event->allGestures();
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "Delivering gestures:" << allGestures;
+
+ typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
+ GesturesPerItem gesturesPerItem;
+
+ QSet<QGesture *> startedGestures;
+ foreach (QGesture *gesture, allGestures) {
+ QGraphicsObject *target = gestureTargets.value(gesture, 0);
+ if (!target) {
+ // when we are not in started mode but don't have a target
+ // then the only one interested in gesture is the view/scene
+ if (gesture->state() == Qt::GestureStarted)
+ startedGestures.insert(gesture);
+ } else {
+ gesturesPerItem[target].append(gesture);
+ }
+ }
+
+ QMap<Qt::GestureType, QGesture *> conflictedGestures;
+ QList<QList<QGraphicsObject *> > conflictedItems;
+ QHash<QGesture *, QGraphicsObject *> normalGestures;
+ getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
+ &normalGestures);
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "Conflicting gestures:" << conflictedGestures.values() << conflictedItems;
+ Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
+ (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
+
+ // gestures that were sent as override events, but no one accepted them
+ QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
+
+ // deliver conflicted gestures as override events first
+ while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
+ // get the topmost item to deliver the override event
+ Q_ASSERT(!conflictedItems.isEmpty());
+ Q_ASSERT(!conflictedItems.first().isEmpty());
+ QGraphicsObject *topmost = conflictedItems.first().first();
+ for (int i = 1; i < conflictedItems.size(); ++i) {
+ QGraphicsObject *item = conflictedItems.at(i).first();
+ if (qt_closestItemFirst(item, topmost)) {
+ topmost = item;
+ }
+ }
+ // get a list of gestures to send to the item
+ QList<Qt::GestureType> grabbedGestures =
+ topmost->QGraphicsItem::d_func()->gestureContext.keys();
+ QList<QGesture *> gestures;
+ for (int i = 0; i < grabbedGestures.size(); ++i) {
+ if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
+ gestures.append(g);
+ if (!ignoredConflictedGestures.contains(g))
+ ignoredConflictedGestures.insert(g, topmost);
+ }
+ }
+
+ // send gesture override to the topmost item
+ QGestureEvent ev(gestures);
+ ev.t = QEvent::GestureOverride;
+ ev.setWidget(event->widget());
+ // mark event and individual gestures as ignored
+ ev.ignore();
+ foreach(QGesture *g, gestures)
+ ev.setAccepted(g, false);
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "delivering override to"
+ << topmost << gestures;
+ sendEvent(topmost, &ev);
+ // mark all accepted gestures to deliver them as normal gesture events
+ foreach (QGesture *g, gestures) {
+ if (ev.isAccepted() || ev.isAccepted(g)) {
+ conflictedGestures.remove(g->gestureType());
+ gestureTargets.remove(g);
+ // add the gesture to the list of normal delivered gestures
+ normalGestures.insert(g, topmost);
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "override was accepted:"
+ << g << topmost;
+ ignoredConflictedGestures.remove(g);
+ }
+ }
+ // remove the item that we've already delivered from the list
+ for (int i = 0; i < conflictedItems.size(); ) {
+ QList<QGraphicsObject *> &items = conflictedItems[i];
+ if (items.first() == topmost) {
+ items.removeFirst();
+ if (items.isEmpty()) {
+ conflictedItems.removeAt(i);
+ continue;
+ }
+ }
+ ++i;
+ }
+ }
+
+ // put back those started gestures that are not in the conflicted state
+ // and remember their targets
+ QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
+ e = normalGestures.end();
+ for (; it != e; ++it) {
+ QGesture *g = it.key();
+ QGraphicsObject *receiver = it.value();
+ Q_ASSERT(!gestureTargets.contains(g));
+ gestureTargets.insert(g, receiver);
+ gesturesPerItem[receiver].append(g);
+ }
+ it = ignoredConflictedGestures.begin();
+ e = ignoredConflictedGestures.end();
+ for (; it != e; ++it) {
+ QGesture *g = it.key();
+ QGraphicsObject *receiver = it.value();
+ Q_ASSERT(!gestureTargets.contains(g));
+ gestureTargets.insert(g, receiver);
+ gesturesPerItem[receiver].append(g);
+ }
+
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "Started gestures:" << normalGestures.keys()
+ << "All gestures:" << gesturesPerItem.values();
+
+ // deliver all events
+ QList<QGesture *> alreadyIgnoredGestures;
+ QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
+ QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
+ qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
+ for (int i = 0; i < targetItems.size(); ++i) {
+ QGraphicsObject *item = targetItems.at(i);
+ QList<QGesture *> gestures = gesturesPerItem.value(item);
+ // remove gestures that were already delivered once and were ignored
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "already ignored gestures for item"
+ << item << ":" << itemIgnoredGestures.value(item);
+
+ if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
+ continue;
+
+ QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
+ foreach(QGesture *g, alreadyIgnoredGestures) {
+ if (gid->gestureContext.contains(g->gestureType()))
+ gestures += g;
+ }
+ if (gestures.isEmpty())
+ continue;
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "delivering to"
+ << item << gestures;
+ QGestureEvent ev(gestures);
+ ev.setWidget(event->widget());
+ sendEvent(item, &ev);
+ QSet<QGesture *> ignoredGestures;
+ foreach (QGesture *g, gestures) {
+ if (!ev.isAccepted() && !ev.isAccepted(g))
+ ignoredGestures.insert(g);
+ }
+ if (!ignoredGestures.isEmpty()) {
+ // get a list of items under the (current) hotspot of each ignored
+ // gesture and start delivery again from the beginning
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "item has ignored the event, will propagate."
+ << item << ignoredGestures;
+ itemIgnoredGestures[item] += ignoredGestures;
+ QMap<Qt::GestureType, QGesture *> conflictedGestures;
+ QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
+ QHash<QGesture *, QGraphicsObject *> normalGestures;
+ getGestureTargets(ignoredGestures, viewport,
+ &conflictedGestures, &itemsForConflictedGestures,
+ &normalGestures);
+ QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
+ for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
+ itemsSet += itemsForConflictedGestures.at(k).toSet();
+ targetItems = itemsSet.toList();
+ qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
+ alreadyIgnoredGestures = conflictedGestures.values();
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "new targets:" << targetItems;
+ i = -1; // start delivery again
+ continue;
+ }
+ }
+
+ // forget about targets for gestures that have ended
+ foreach (QGesture *g, allGestures) {
+ switch (g->state()) {
+ case Qt::GestureFinished:
+ case Qt::GestureCanceled:
+ gestureTargets.remove(g);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsscene.cpp"
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 8073695..cd20fd0 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -282,6 +282,13 @@ public:
bool allItemsIgnoreTouchEvents;
void enableTouchEventsOnViews();
+ QHash<QGesture *, QGraphicsObject *> gestureTargets;
+ void gestureEventHandler(QGestureEvent *event);
+ void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport,
+ QMap<Qt::GestureType, QGesture *> *conflictedGestures,
+ QList<QList<QGraphicsObject *> > *conflictedItems,
+ QHash<QGesture *, QGraphicsObject *> *normalGestures);
+
void updateInputMethodSensitivityInViews();
QList<QGraphicsItem *> modalPanels;
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
index e21183a..47ae3f1 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -405,70 +405,6 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QR
}
/*!
- Returns true if \a item1 is on top of \a item2.
-
- \internal
-*/
-bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- // Siblings? Just check their z-values.
- const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
- const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
- if (d1->parent == d2->parent)
- return qt_closestLeaf(item1, item2);
-
- // Find common ancestor, and each item's ancestor closest to the common
- // ancestor.
- int item1Depth = d1->depth();
- int item2Depth = d2->depth();
- const QGraphicsItem *p = item1;
- const QGraphicsItem *t1 = item1;
- while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
- if (p == item2) {
- // item2 is one of item1's ancestors; item1 is on top
- return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
- }
- t1 = p;
- --item1Depth;
- }
- p = item2;
- const QGraphicsItem *t2 = item2;
- while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
- if (p == item1) {
- // item1 is one of item2's ancestors; item1 is not on top
- return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
- }
- t2 = p;
- --item2Depth;
- }
-
- // item1Ancestor is now at the same level as item2Ancestor, but not the same.
- const QGraphicsItem *a1 = t1;
- const QGraphicsItem *a2 = t2;
- while (a1) {
- const QGraphicsItem *p1 = a1;
- const QGraphicsItem *p2 = a2;
- a1 = a1->parentItem();
- a2 = a2->parentItem();
- if (a1 && a1 == a2)
- return qt_closestLeaf(p1, p2);
- }
-
- // No common ancestor? Then just compare the items' toplevels directly.
- return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem());
-}
-
-/*!
- Returns true if \a item2 is on top of \a item1.
-
- \internal
-*/
-bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- return closestItemFirst_withoutCache(item2, item1);
-}
-
-/*!
Sort a list of \a itemList in a specific \a order and use the cache if requested.
\internal
@@ -495,9 +431,9 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList<QGraphicsItem *> *itemLi
}
} else {
if (order == Qt::DescendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache);
+ qSort(itemList->begin(), itemList->end(), qt_closestItemFirst);
} else if (order == Qt::AscendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache);
+ qSort(itemList->begin(), itemList->end(), qt_closestItemLast);
}
}
}
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
index 0a86bb7..c130190 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
@@ -145,8 +145,6 @@ public:
QList<QGraphicsItem *> estimateItems(const QRectF &, Qt::SortOrder, bool b = false);
static void climbTree(QGraphicsItem *item, int *stackingOrder);
- static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
- static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
{
diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp
index 49d8999..93dc196 100644
--- a/src/gui/graphicsview/qgraphicstransform.cpp
+++ b/src/gui/graphicsview/qgraphicstransform.cpp
@@ -547,9 +547,7 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const
return;
matrix->translate(d->origin);
- QMatrix4x4 m;
- m.rotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z());
- *matrix *= m.toTransform();
+ matrix->projectedRotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z());
matrix->translate(-d->origin);
}
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 32747cc..710c745 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2701,6 +2701,19 @@ bool QGraphicsView::viewportEvent(QEvent *event)
return true;
}
+ case QEvent::Gesture:
+ case QEvent::GestureOverride:
+ {
+ if (!isEnabled())
+ return false;
+
+ if (d->scene && d->sceneInteractionAllowed) {
+ QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);
+ gestureEvent->setWidget(viewport());
+ (void) QApplication::sendEvent(d->scene, gestureEvent);
+ }
+ return true;
+ }
default:
break;
}
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 21ab40c..571ef9d 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -546,11 +546,7 @@ bool QImageData::checkForAlphaPixels() const
Each pixel stored in a QImage is represented by an integer. The
size of the integer varies depending on the format. QImage
supports several image formats described by the \l Format
- enum. The monochrome (1-bit), 8-bit and 32-bit images are
- available in all versions of Qt. In addition Qt for Embedded Linux
- also supports 2-bit, 4-bit, and 16-bit images. For more information
- about the Qt Extended specific formats, see the documentation of the \l
- Format enum.
+ enum.
Monochrome images are stored using 1-bit indexes into a color table
with at most two colors. There are two different types of
@@ -707,9 +703,20 @@ bool QImageData::checkForAlphaPixels() const
packed with the most significant bit (MSB) first.
\value Format_MonoLSB The image is stored using 1-bit per pixel. Bytes are
packed with the less significant bit (LSB) first.
- \value Format_Indexed8 The image is stored using 8-bit indexes into a colormap.
+
+ \value Format_Indexed8 The image is stored using 8-bit indexes
+ into a colormap. \warning Drawing into a
+ QImage with Indexed8 format is not
+ supported.
+
\value Format_RGB32 The image is stored using a 32-bit RGB format (0xffRRGGBB).
- \value Format_ARGB32 The image is stored using a 32-bit ARGB format (0xAARRGGBB).
+
+ \value Format_ARGB32 The image is stored using a 32-bit ARGB
+ format (0xAARRGGBB). \warning Do not
+ render into ARGB32 images using
+ QPainter. Format_ARGB32_Premultiplied is
+ significantly faster.
+
\value Format_ARGB32_Premultiplied The image is stored using a premultiplied 32-bit
ARGB format (0xAARRGGBB), i.e. the red,
green, and blue channels are multiplied
@@ -718,7 +725,9 @@ bool QImageData::checkForAlphaPixels() const
undefined.) Certain operations (such as image composition
using alpha blending) are faster using premultiplied ARGB32
than with plain ARGB32.
+
\value Format_RGB16 The image is stored using a 16-bit RGB format (5-6-5).
+
\value Format_ARGB8565_Premultiplied The image is stored using a
premultiplied 24-bit ARGB format (8-5-6-5).
\value Format_RGB666 The image is stored using a 24-bit RGB format (6-6-6).
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index f94552d..a3b7516 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -470,9 +470,11 @@ QPixmap::operator QVariant() const
conversion fails.
If the pixmap has 1-bit depth, the returned image will also be 1
- bit deep. If the pixmap has 2- to 8-bit depth, the returned image
- has 8-bit depth. If the pixmap has greater than 8-bit depth, the
- returned image has 32-bit depth.
+ bit deep. Images with more bits will be returned in a format
+ closely represents the underlying system. Usually this will be
+ QImage::Format_ARGB32_Premultiplied for pixmaps with an alpha and
+ QImage::Format_RGB32 or QImage::Format_RGB16 for pixmaps without
+ alpha.
Note that for the moment, alpha masks on monochrome images are
ignored.
@@ -1704,8 +1706,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
In addition, on Symbian, the QPixmap class supports conversion to
and from CFbsBitmap: the toSymbianCFbsBitmap() function creates
- CFbsBitmap equivalent to the QPixmap, based on given mode and returns
- a CFbsBitmap object. The fromSymbianCFbsBitmap() function returns a
+ CFbsBitmap equivalent to the QPixmap, based on given mode and returns
+ a CFbsBitmap object. The fromSymbianCFbsBitmap() function returns a
QPixmap that is equivalent to the given bitmap and given mode.
\section1 Pixmap Transformations
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index fc9820f..3bd9a19 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -1419,7 +1419,7 @@ int QHeaderView::minimumSectionSize() const
int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this);
if (d->orientation == Qt::Horizontal)
return qMax(strut.width(), (fontMetrics().maxWidth() + margin));
- return qMax(strut.height(), (fontMetrics().lineSpacing() + margin));
+ return qMax(strut.height(), (fontMetrics().height() + margin));
}
return d->minimumSectionSize;
}
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 1d9b6e0..f58f458 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -1900,7 +1900,7 @@ void QListModeViewBase::updateVerticalScrollBar(const QSize &step)
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem
&& ((flow() == QListView::TopToBottom && !isWrapping())
|| (flow() == QListView::LeftToRight && isWrapping()))) {
- const int steps = (flow() == QListView::TopToBottom ? flowPositions : segmentPositions).count() - 1;
+ const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).count() - 1;
if (steps > 0) {
const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping());
verticalScrollBar()->setSingleStep(1);
@@ -1921,7 +1921,7 @@ void QListModeViewBase::updateHorizontalScrollBar(const QSize &step)
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem
&& ((flow() == QListView::TopToBottom && isWrapping())
|| (flow() == QListView::LeftToRight && !isWrapping()))) {
- int steps = (flow() == QListView::TopToBottom ? segmentPositions : flowPositions).count() - 1;
+ int steps = (flow() == QListView::TopToBottom ? segmentPositions : scrollValueMap).count() - 1;
if (steps > 0) {
const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping());
horizontalScrollBar()->setSingleStep(1);
@@ -1939,7 +1939,11 @@ int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hi
bool above, bool below, const QRect &area, const QRect &rect) const
{
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int value = qBound(0, verticalScrollBar()->value(), flowPositions.count() - 1);
+ int value;
+ if (scrollValueMap.isEmpty())
+ value = 0;
+ else
+ value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()), flowPositions.count() - 1);
if (above)
hint = QListView::PositionAtTop;
else if (below)
@@ -1966,8 +1970,8 @@ int QListModeViewBase::horizontalOffset() const
return (isRightToLeft() ? maximum - position : position);
}
} else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) {
- int position = flowPositions.at(horizontalScrollBar()->value());
- int maximum = flowPositions.at(horizontalScrollBar()->maximum());
+ int position = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->value()));
+ int maximum = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->maximum()));
return (isRightToLeft() ? maximum - position : position);
}
}
@@ -1986,9 +1990,9 @@ int QListModeViewBase::verticalOffset() const
}
} else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
int value = verticalScrollBar()->value();
- if (value > flowPositions.count())
+ if (value > scrollValueMap.count())
return 0;
- return flowPositions.at(value) - spacing();
+ return flowPositions.at(scrollValueMap.at(value)) - spacing();
}
}
return QCommonListViewBase::verticalOffset();
@@ -2000,7 +2004,11 @@ int QListModeViewBase::horizontalScrollToValue(int index, QListView::ScrollHint
if (horizontalScrollMode() != QAbstractItemView::ScrollPerItem)
return QCommonListViewBase::horizontalScrollToValue(index, hint, leftOf, rightOf, area, rect);
- int value = qBound(0, horizontalScrollBar()->value(), flowPositions.count() - 1);
+ int value;
+ if (scrollValueMap.isEmpty())
+ value = 0;
+ else
+ value = qBound(0, scrollValueMap.at(horizontalScrollBar()->value()), flowPositions.count() - 1);
if (leftOf)
hint = QListView::PositionAtTop;
else if (rightOf)
@@ -2043,14 +2051,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
if (vertical && flow() == QListView::TopToBottom && dy != 0) {
int currentValue = qBound(0, verticalValue, max);
int previousValue = qBound(0, currentValue + dy, max);
- int currentCoordinate = flowPositions.at(currentValue);
- int previousCoordinate = flowPositions.at(previousValue);
+ int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
+ int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
dy = previousCoordinate - currentCoordinate;
} else if (horizontal && flow() == QListView::LeftToRight && dx != 0) {
int currentValue = qBound(0, horizontalValue, max);
int previousValue = qBound(0, currentValue + dx, max);
- int currentCoordinate = flowPositions.at(currentValue);
- int previousCoordinate = flowPositions.at(previousValue);
+ int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
+ int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
dx = previousCoordinate - currentCoordinate;
}
}
@@ -2113,6 +2121,7 @@ QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info)
segmentPositions.clear();
segmentStartRows.clear();
segmentExtents.clear();
+ scrollValueMap.clear();
x = info.bounds.left() + info.spacing;
y = info.bounds.top() + info.spacing;
segmentPositions.append(info.flow == QListView::LeftToRight ? y : x);
@@ -2204,6 +2213,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
deltaSegPosition = 0;
}
// save the flow position of this item
+ scrollValueMap.append(flowPositions.count());
flowPositions.append(flowPosition);
// prepare for the next item
deltaSegPosition = qMax(deltaSegHint, deltaSegPosition);
@@ -2229,6 +2239,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
// if it is the last batch, save the end of the segments
if (info.last == info.max) {
segmentExtents.append(flowPosition);
+ scrollValueMap.append(flowPositions.count());
flowPositions.append(flowPosition);
segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX);
}
@@ -2306,7 +2317,14 @@ QRect QListModeViewBase::mapToViewport(const QRect &rect) const
int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
{
- const QVector<int> positions = (wrap ? segmentPositions : flowPositions);
+ QVector<int> positions;
+ if (wrap)
+ positions = segmentPositions;
+ else if (!flowPositions.isEmpty()) {
+ positions.reserve(scrollValueMap.size());
+ foreach (int itemShown, scrollValueMap)
+ positions.append(flowPositions.at(itemShown));
+ }
if (positions.isEmpty() || bounds <= length)
return positions.count();
if (uniformItemSizes()) {
diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h
index b6785da..de4c7f3 100644
--- a/src/gui/itemviews/qlistview_p.h
+++ b/src/gui/itemviews/qlistview_p.h
@@ -205,6 +205,7 @@ public:
QVector<int> segmentPositions;
QVector<int> segmentStartRows;
QVector<int> segmentExtents;
+ QVector<int> scrollValueMap;
// used when laying out in batches
int batchSavedPosition;
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 210534e..f37d8c7 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -2908,6 +2908,8 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
layout(item);
q->setState(oldState);
+ if (model->canFetchMore(index))
+ model->fetchMore(index);
if (emitSignal) {
emit q->expanded(index);
#ifndef QT_NO_ANIMATION
@@ -2915,8 +2917,6 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
beginAnimatedOperation();
#endif //QT_NO_ANIMATION
}
- if (model->canFetchMore(index))
- model->fetchMore(index);
}
void QTreeViewPrivate::collapse(int item, bool emitSignal)
@@ -3005,10 +3005,12 @@ void QTreeViewPrivate::beginAnimatedOperation()
animatedOperation.setEndValue(animatedOperation.top() + h);
}
- animatedOperation.after = renderTreeToPixmapForAnimation(rect);
+ if (!rect.isEmpty()) {
+ animatedOperation.after = renderTreeToPixmapForAnimation(rect);
- q->setState(QAbstractItemView::AnimatingState);
- animatedOperation.start(); //let's start the animation
+ q->setState(QAbstractItemView::AnimatingState);
+ animatedOperation.start(); //let's start the animation
+ }
}
void QTreeViewPrivate::drawAnimatedOperation(QPainter *painter) const
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 53c2611..8859358 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -84,6 +84,7 @@ SOURCES += \
kernel/qgesturerecognizer.cpp \
kernel/qgesturemanager.cpp \
kernel/qsoftkeymanager.cpp \
+ kernel/qdesktopwidget.cpp \
kernel/qguiplatformplugin.cpp
win32 {
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 9658f5e..202d450 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -2492,6 +2492,7 @@ void QApplication::setActiveWindow(QWidget* act)
/*!internal
* Helper function that returns the new focus widget, but does not set the focus reason.
* Returns 0 if a new focus widget could not be found.
+ * Shared with QGraphicsProxyWidgetPrivate::findFocusChild()
*/
QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next)
{
@@ -3635,8 +3636,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
// walk through parents and check for gestures
if (d->gestureManager) {
- if (d->gestureManager->filterEvent(receiver, e))
- return true;
+ if (receiver->isWidgetType()) {
+ if (d->gestureManager->filterEvent(static_cast<QWidget *>(receiver), e))
+ return true;
+ } else if (QGesture *gesture = qobject_cast<QGesture *>(receiver)) {
+ if (d->gestureManager->filterEvent(gesture, e))
+ return true;
+ }
}
@@ -4161,40 +4167,41 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
if (wd->gestureContext.contains(type)) {
allGestures.removeAt(i);
gestures.append(g);
- gestureEvent->setAccepted(g, false);
} else {
++i;
}
}
- if (!gestures.isEmpty()) {
+ if (!gestures.isEmpty()) { // we have gestures for this w
QGestureEvent ge(gestures);
ge.t = gestureEvent->t;
ge.spont = gestureEvent->spont;
ge.m_accept = wasAccepted;
+ ge.d_func()->accepted = gestureEvent->d_func()->accepted;
res = d->notify_helper(w, &ge);
gestureEvent->spont = false;
eventAccepted = ge.isAccepted();
- if (res && eventAccepted)
- break;
- if (!eventAccepted) {
- // ### two ways to ignore the event/gesture
-
- // if the whole event wasn't accepted, put back those
- // gestures that were not accepted.
- for (int i = 0; i < gestures.size(); ++i) {
- QGesture *g = gestures.at(i);
- if (!ge.isAccepted(g))
- allGestures.append(g);
+ for (int i = 0; i < gestures.size(); ++i) {
+ QGesture *g = gestures.at(i);
+ if ((res && eventAccepted) || (!eventAccepted && ge.isAccepted(g))) {
+ // if the gesture was accepted, mark the target widget for it
+ gestureEvent->d_func()->targetWidgets[g->gestureType()] = w;
+ gestureEvent->setAccepted(g, true);
+ } else if (!eventAccepted && !ge.isAccepted(g)) {
+ // if the gesture was explicitly ignored by the application,
+ // put it back so a parent can get it
+ allGestures.append(g);
}
}
}
- if (allGestures.isEmpty())
+ if (allGestures.isEmpty()) // everything delivered
break;
if (w->isWindow())
break;
w = w->parentWidget();
}
- gestureEvent->m_accept = eventAccepted;
+ foreach (QGesture *g, allGestures)
+ gestureEvent->setAccepted(g, false);
+ gestureEvent->m_accept = false; // to make sure we check individual gestures
} else {
res = d->notify_helper(receiver, e);
}
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 522f1ac..d98ecbb 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -615,6 +615,8 @@ static void qt_set_windows_font_resources()
if (qt_wince_is_mobile()) {
smallerFont.setPointSize(systemFont.pointSize()-1);
QApplication::setFont(smallerFont, "QTabBar");
+ smallerFont.setBold(true);
+ QApplication::setFont(smallerFont, "QAbstractButton");
}
#endif// Q_WS_WINCE
}
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 4c2a14a..d49c150 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -51,6 +51,7 @@
#include <private/qmacinputcontext_p.h>
#include <private/qmultitouch_mac_p.h>
#include <private/qevent_p.h>
+#include <private/qbackingstore_p.h>
#include <qscrollarea.h>
#include <qhash.h>
@@ -503,6 +504,12 @@ extern "C" {
- (void)drawRect:(NSRect)aRect
{
+ if (QApplicationPrivate::graphicsSystem() != 0) {
+ if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore())
+ bs->markDirty(qwidget->rect(), qwidget);
+ qwidgetprivate->syncBackingStore(qwidget->rect());
+ return;
+ }
CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
qwidgetprivate->hd = cg;
CGContextSaveGState(cg);
diff --git a/src/gui/kernel/qdesktopwidget.cpp b/src/gui/kernel/qdesktopwidget.cpp
new file mode 100644
index 0000000..b1e1008
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+#include "qdesktopwidget.h"
+#include "qwidget_p.h"
+
+const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
+{
+ QRect rect = QWidgetPrivate::screenGeometry(widget);
+ if (rect.isNull())
+ return screenGeometry(screenNumber(widget));
+ else return rect;
+}
+
+const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
+{
+ QRect rect = QWidgetPrivate::screenGeometry(widget);
+ if (rect.isNull())
+ return availableGeometry(screenNumber(widget));
+ else
+ return rect;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h
index 85f479e..6e3447c 100644
--- a/src/gui/kernel/qdesktopwidget.h
+++ b/src/gui/kernel/qdesktopwidget.h
@@ -75,14 +75,12 @@ public:
QWidget *screen(int screen = -1);
const QRect screenGeometry(int screen = -1) const;
- const QRect screenGeometry(const QWidget *widget) const
- { return screenGeometry(screenNumber(widget)); }
+ const QRect screenGeometry(const QWidget *widget) const;
const QRect screenGeometry(const QPoint &point) const
{ return screenGeometry(screenNumber(point)); }
const QRect availableGeometry(int screen = -1) const;
- const QRect availableGeometry(const QWidget *widget) const
- { return availableGeometry(screenNumber(widget)); }
+ const QRect availableGeometry(const QWidget *widget) const;
const QRect availableGeometry(const QPoint &point) const
{ return availableGeometry(screenNumber(point)); }
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 2ff6d65..065bd09 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -45,6 +45,7 @@
#include "private/qapplication_p.h"
#include "private/qkeysequence_p.h"
#include "qwidget.h"
+#include "qgraphicsview.h"
#include "qdebug.h"
#include "qmime.h"
#include "qdnd_p.h"
@@ -4223,8 +4224,17 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T
Creates new QGestureEvent containing a list of \a gestures.
*/
QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures)
- : QEvent(QEvent::Gesture), gestures_(gestures)
+ : QEvent(QEvent::Gesture)
{
+ d = reinterpret_cast<QEventPrivate *>(new QGestureEventPrivate(gestures));
+}
+
+/*!
+ Destroys QGestureEvent.
+*/
+QGestureEvent::~QGestureEvent()
+{
+ delete reinterpret_cast<QGestureEventPrivate *>(d);
}
/*!
@@ -4232,7 +4242,7 @@ QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures)
*/
QList<QGesture *> QGestureEvent::allGestures() const
{
- return gestures_;
+ return d_func()->gestures;
}
/*!
@@ -4240,9 +4250,10 @@ QList<QGesture *> QGestureEvent::allGestures() const
*/
QGesture *QGestureEvent::gesture(Qt::GestureType type) const
{
- for(int i = 0; i < gestures_.size(); ++i)
- if (gestures_.at(i)->gestureType() == type)
- return gestures_.at(i);
+ const QGestureEventPrivate *d = d_func();
+ for(int i = 0; i < d->gestures.size(); ++i)
+ if (d->gestures.at(i)->gestureType() == type)
+ return d->gestures.at(i);
return 0;
}
@@ -4251,7 +4262,7 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const
*/
QList<QGesture *> QGestureEvent::activeGestures() const
{
- return gestures_;
+ return d_func()->gestures;
}
/*!
@@ -4259,7 +4270,7 @@ QList<QGesture *> QGestureEvent::activeGestures() const
*/
QList<QGesture *> QGestureEvent::canceledGestures() const
{
- return gestures_;
+ return d_func()->gestures;
}
/*!
@@ -4279,7 +4290,7 @@ void QGestureEvent::setAccepted(QGesture *gesture, bool value)
{
setAccepted(false);
if (gesture)
- gesture->d_func()->accept = value;
+ d_func()->accepted[gesture->gestureType()] = value;
}
/*!
@@ -4315,7 +4326,56 @@ void QGestureEvent::ignore(QGesture *gesture)
*/
bool QGestureEvent::isAccepted(QGesture *gesture) const
{
- return gesture ? gesture->d_func()->accept : false;
+ return gesture ? d_func()->accepted.value(gesture->gestureType(), true) : false;
+}
+
+/*!
+ Sets the widget for this event.
+*/
+void QGestureEvent::setWidget(QWidget *widget)
+{
+ d_func()->widget = widget;
+}
+
+/*!
+ Returns the widget on which the event occurred.
+*/
+QWidget *QGestureEvent::widget() const
+{
+ return d_func()->widget;
+}
+
+/*!
+ Returns the scene-local coordinates if the \a gesturePoint is inside a graphics view.
+
+ \sa QPointF::isNull().
+*/
+QPointF QGestureEvent::mapToScene(const QPointF &gesturePoint) const
+{
+ QWidget *w = widget();
+ if (w) // we get the viewport as widget, not the graphics view
+ w = w->parentWidget();
+ QGraphicsView *view = qobject_cast<QGraphicsView*>(w);
+ if (view) {
+ return view->mapToScene(view->mapFromGlobal(gesturePoint.toPoint()));
+ }
+ return QPointF();
+}
+
+/*!
+ \internal
+*/
+QGestureEventPrivate *QGestureEvent::d_func()
+{
+ return reinterpret_cast<QGestureEventPrivate *>(d);
+}
+
+/*!
+ \internal
+*/
+const QGestureEventPrivate *QGestureEvent::d_func() const
+{
+ return reinterpret_cast<const QGestureEventPrivate *>(d);
}
#ifdef Q_NO_USING_KEYWORD
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 3516222..b7370fd 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -820,10 +820,12 @@ protected:
};
class QGesture;
+class QGestureEventPrivate;
class Q_GUI_EXPORT QGestureEvent : public QEvent
{
public:
QGestureEvent(const QList<QGesture *> &gestures);
+ ~QGestureEvent();
QList<QGesture *> allGestures() const;
QGesture *gesture(Qt::GestureType type) const;
@@ -849,8 +851,17 @@ public:
void ignore(QGesture *);
bool isAccepted(QGesture *) const;
+ void setWidget(QWidget *widget);
+ QWidget *widget() const;
+
+ QPointF mapToScene(const QPointF &gesturePoint) const;
+
private:
- QList<QGesture *> gestures_;
+ QGestureEventPrivate *d_func();
+ const QGestureEventPrivate *d_func() const;
+
+ friend class QApplication;
+ friend class QGestureManager;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index c7a4975..6e6ab01 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -150,6 +150,20 @@ public:
#endif
};
+class QGestureEventPrivate
+{
+public:
+ inline QGestureEventPrivate(const QList<QGesture *> &list)
+ : gestures(list), widget(0)
+ {
+ }
+
+ QList<QGesture *> gestures;
+ QWidget *widget;
+ QMap<Qt::GestureType, bool> accepted;
+ QMap<Qt::GestureType, QWidget *> targetWidgets;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
index fc8df49..ecdd661 100644
--- a/src/gui/kernel/qgesture.cpp
+++ b/src/gui/kernel/qgesture.cpp
@@ -129,6 +129,10 @@ QGesture::~QGesture()
\brief The point that is used to find the receiver for the gesture event.
+ The hot-spot is a point in the global coordinate system, use
+ QWidget::mapFromGlobal() or QGestureEvent::mapToScene() to get a
+ local hot-spot.
+
If the hot-spot is not set, the targetObject is used as the receiver of the
gesture event.
*/
@@ -154,16 +158,6 @@ Qt::GestureState QGesture::state() const
return d_func()->state;
}
-QObject *QGesture::targetObject() const
-{
- return d_func()->targetObject;
-}
-
-void QGesture::setTargetObject(QObject *value)
-{
- d_func()->targetObject = value;
-}
-
QPointF QGesture::hotSpot() const
{
return d_func()->hotSpot;
@@ -241,17 +235,17 @@ QPanGesture::QPanGesture(QObject *parent)
d_func()->gestureType = Qt::PanGesture;
}
-QSizeF QPanGesture::totalOffset() const
+QPointF QPanGesture::totalOffset() const
{
return d_func()->totalOffset;
}
-QSizeF QPanGesture::lastOffset() const
+QPointF QPanGesture::lastOffset() const
{
return d_func()->lastOffset;
}
-QSizeF QPanGesture::offset() const
+QPointF QPanGesture::offset() const
{
return d_func()->offset;
}
@@ -262,17 +256,17 @@ qreal QPanGesture::acceleration() const
}
-void QPanGesture::setTotalOffset(const QSizeF &value)
+void QPanGesture::setTotalOffset(const QPointF &value)
{
d_func()->totalOffset = value;
}
-void QPanGesture::setLastOffset(const QSizeF &value)
+void QPanGesture::setLastOffset(const QPointF &value)
{
d_func()->lastOffset = value;
}
-void QPanGesture::setOffset(const QSizeF &value)
+void QPanGesture::setOffset(const QPointF &value)
{
d_func()->offset = value;
}
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
index 02eb526..6469959 100644
--- a/src/gui/kernel/qgesture.h
+++ b/src/gui/kernel/qgesture.h
@@ -67,7 +67,6 @@ class Q_GUI_EXPORT QGesture : public QObject
Q_PROPERTY(Qt::GestureType gestureType READ gestureType)
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot RESET unsetHotSpot)
Q_PROPERTY(bool hasHotSpot READ hasHotSpot)
- Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
public:
explicit QGesture(QObject *parent = 0);
@@ -77,9 +76,6 @@ public:
Qt::GestureState state() const;
- QObject *targetObject() const;
- void setTargetObject(QObject *value);
-
QPointF hotSpot() const;
void setHotSpot(const QPointF &value);
bool hasHotSpot() const;
@@ -100,22 +96,22 @@ class Q_GUI_EXPORT QPanGesture : public QGesture
Q_OBJECT
Q_DECLARE_PRIVATE(QPanGesture)
- Q_PROPERTY(QSizeF totalOffset READ totalOffset WRITE setTotalOffset)
- Q_PROPERTY(QSizeF lastOffset READ lastOffset WRITE setLastOffset)
- Q_PROPERTY(QSizeF offset READ offset WRITE setOffset)
+ Q_PROPERTY(QPointF totalOffset READ totalOffset WRITE setTotalOffset)
+ Q_PROPERTY(QPointF lastOffset READ lastOffset WRITE setLastOffset)
+ Q_PROPERTY(QPointF offset READ offset WRITE setOffset)
Q_PROPERTY(qreal acceleration READ acceleration WRITE setAcceleration)
public:
QPanGesture(QObject *parent = 0);
- QSizeF totalOffset() const;
- QSizeF lastOffset() const;
- QSizeF offset() const;
+ QPointF totalOffset() const;
+ QPointF lastOffset() const;
+ QPointF offset() const;
qreal acceleration() const;
- void setTotalOffset(const QSizeF &value);
- void setLastOffset(const QSizeF &value);
- void setOffset(const QSizeF &value);
+ void setTotalOffset(const QPointF &value);
+ void setLastOffset(const QPointF &value);
+ void setOffset(const QPointF &value);
void setAcceleration(qreal value);
friend class QPanGestureRecognizer;
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index 7f69a4e..975c0c9 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -68,7 +68,7 @@ class QGesturePrivate : public QObjectPrivate
public:
QGesturePrivate()
: gestureType(Qt::CustomGesture), state(Qt::NoGesture), isHotSpotSet(false),
- targetObject(0), accept(true)
+ targetObject(0)
{
}
@@ -77,7 +77,6 @@ public:
QPointF hotSpot;
bool isHotSpotSet;
QObject *targetObject;
- bool accept;
};
class QPanGesturePrivate : public QGesturePrivate
@@ -90,9 +89,9 @@ public:
{
}
- QSizeF totalOffset;
- QSizeF lastOffset;
- QSizeF offset;
+ QPointF totalOffset;
+ QPointF lastOffset;
+ QPointF offset;
QPoint lastPosition;
qreal acceleration;
};
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 0f0aef2..ed8e744 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -44,6 +44,7 @@
#include "private/qwidget_p.h"
#include "private/qgesture_p.h"
#include "private/qgraphicsitem_p.h"
+#include "private/qevent_p.h"
#include "qgesture.h"
#include "qevent.h"
#include "qgraphicsitem.h"
@@ -88,7 +89,8 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
{
QGesture *dummy = recognizer->createGesture(0);
if (!dummy) {
- qWarning("QGestureManager::registerGestureRecognizer: the recognizer doesn't provide gesture object");
+ qWarning("QGestureManager::registerGestureRecognizer: "
+ "the recognizer fails to create a gesture object, skipping registration.");
return Qt::GestureType(0);
}
Qt::GestureType type = dummy->gestureType();
@@ -107,7 +109,7 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType)
}
-QGesture* QGestureManager::getState(QObject *object, Qt::GestureType type)
+QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type)
{
// if the widget is being deleted we should be carefull and not to
// create a new state, as it will create QWeakPointer which doesnt work
@@ -115,28 +117,39 @@ QGesture* QGestureManager::getState(QObject *object, Qt::GestureType type)
if (object->isWidgetType()) {
if (static_cast<QWidget *>(object)->d_func()->data.in_destructor)
return 0;
+ } else if (QGesture *g = qobject_cast<QGesture *>(object)) {
+ return g;
+ } else {
+ Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
}
- QWeakPointer<QGesture> state = objectGestures.value(QGestureManager::ObjectGesture(object, type));
+ QGesture *state =
+ objectGestures.value(QGestureManager::ObjectGesture(object, type));
if (!state) {
QGestureRecognizer *recognizer = recognizers.value(type);
if (recognizer) {
state = recognizer->createGesture(object);
if (!state)
return 0;
- if (state.data()->gestureType() == Qt::CustomGesture) {
+ if (state->gestureType() == Qt::CustomGesture) {
// if the recognizer didn't fill in the gesture type, then this
// is a custom gesture with autogenerated it and we fill it.
- state.data()->d_func()->gestureType = type;
+ state->d_func()->gestureType = type;
+#if defined(GESTURE_DEBUG)
+ state->setObjectName(QString::number((int)type));
+#endif
}
objectGestures.insert(QGestureManager::ObjectGesture(object, type), state);
- gestureToRecognizer[state.data()] = recognizer;
+ gestureToRecognizer[state] = recognizer;
+ gestureOwners[state] = object;
}
}
- return state.data();
+ return state;
}
-bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
+bool QGestureManager::filterEventThroughContexts(const QMap<QObject *,
+ Qt::GestureType> &contexts,
+ QEvent *event)
{
QSet<QGesture *> triggeredGestures;
QSet<QGesture *> finishedGestures;
@@ -144,93 +157,23 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
QSet<QGesture *> canceledGestures;
QSet<QGesture *> notGestures;
- QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(receiver);
- if (receiver->isWidgetType() || graphicsObject) {
- QMap<QObject *, Qt::GestureType> contexts;
- if (receiver->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(receiver);
- if (!w->d_func()->gestureContext.isEmpty()) {
- typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
- for(ContextIterator it = w->d_func()->gestureContext.begin(),
- e = w->d_func()->gestureContext.end(); it != e; ++it) {
- contexts.insertMulti(w, it.key());
- }
- }
- // find all gesture contexts for the widget tree
- w = w->parentWidget();
- while (w)
- {
- typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
- for (ContextIterator it = w->d_func()->gestureContext.begin(),
- e = w->d_func()->gestureContext.end(); it != e; ++it) {
- if (it.value() == Qt::WidgetWithChildrenGesture)
- contexts.insertMulti(w, it.key());
- }
- w = w->parentWidget();
- }
- } else {
- QGraphicsObject *item = graphicsObject;
- if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
- typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
- for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
- e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
- contexts.insertMulti(item, it.key());
- }
- }
- // find all gesture contexts for the widget tree
- item = item->parentObject();
- while (item)
- {
- typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
- for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
- e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
- if (it.value() == Qt::WidgetWithChildrenGesture)
- contexts.insertMulti(item, it.key());
- }
- item = item->parentObject();
- }
- }
- // filter the event through recognizers
- typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
- for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
- Qt::GestureType gestureType = cit.value();
- QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
- rit = recognizers.lowerBound(gestureType),
- re = recognizers.upperBound(gestureType);
- for (; rit != re; ++rit) {
- QGestureRecognizer *recognizer = rit.value();
- QObject *target = cit.key();
- QGesture *state = getState(target, gestureType);
- if (!state)
- continue;
- QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event);
- QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
- if (type == QGestureRecognizer::GestureTriggered) {
- DEBUG() << "QGestureManager: gesture triggered: " << state;
- triggeredGestures << state;
- } else if (type == QGestureRecognizer::GestureFinished) {
- DEBUG() << "QGestureManager: gesture finished: " << state;
- finishedGestures << state;
- } else if (type == QGestureRecognizer::MaybeGesture) {
- DEBUG() << "QGestureManager: maybe gesture: " << state;
- newMaybeGestures << state;
- } else if (type == QGestureRecognizer::NotGesture) {
- DEBUG() << "QGestureManager: not gesture: " << state;
- notGestures << state;
- } else if (type == QGestureRecognizer::Ignore) {
- DEBUG() << "QGestureManager: gesture ignored the event: " << state;
- } else {
- DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state;
- }
- if (result & QGestureRecognizer::ConsumeEventHint) {
- DEBUG() << "QGestureManager: we were asked to consume the event: " << state;
- //TODO: consume events if asked
- }
- }
- }
- } else if (QGesture *state = qobject_cast<QGesture*>(receiver)) {
- if (QGestureRecognizer *recognizer = gestureToRecognizer.value(state)) {
- QGestureRecognizer::Result result = recognizer->filterEvent(state, state, event);
+ // TODO: sort contexts by the gesture type and check if one of the contexts
+ // is already active.
+
+ // filter the event through recognizers
+ typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
+ for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
+ Qt::GestureType gestureType = cit.value();
+ QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
+ rit = recognizers.lowerBound(gestureType),
+ re = recognizers.upperBound(gestureType);
+ for (; rit != re; ++rit) {
+ QGestureRecognizer *recognizer = rit.value();
+ QObject *target = cit.key();
+ QGesture *state = getState(target, gestureType);
+ if (!state)
+ continue;
+ QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event);
QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
if (type == QGestureRecognizer::GestureTriggered) {
DEBUG() << "QGestureManager: gesture triggered: " << state;
@@ -247,11 +190,15 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
} else if (type == QGestureRecognizer::Ignore) {
DEBUG() << "QGestureManager: gesture ignored the event: " << state;
} else {
- DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state;
+ DEBUG() << "QGestureManager: hm, lets assume the recognizer"
+ << "ignored the event: " << state;
+ }
+ if (result & QGestureRecognizer::ConsumeEventHint) {
+ DEBUG() << "QGestureManager: we were asked to consume the event: "
+ << state;
+ //TODO: consume events if asked
}
}
- } else {
- return false;
}
QSet<QGesture *> startedGestures = triggeredGestures - activeGestures;
@@ -260,7 +207,8 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
// check if a running gesture switched back to maybe state
QSet<QGesture *> activeToMaybeGestures = activeGestures & newMaybeGestures;
- // check if a running gesture switched back to not gesture state, i.e. were canceled
+ // check if a running gesture switched back to not gesture state,
+ // i.e. were canceled
QSet<QGesture *> activeToCancelGestures = activeGestures & notGestures;
canceledGestures += activeToCancelGestures;
@@ -271,7 +219,9 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
timer.start(3000, this);
}
// kill timers for gestures that were in maybe state
- QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures | finishedGestures | canceledGestures | notGestures);
+ QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures
+ | finishedGestures | canceledGestures
+ | notGestures);
foreach(QGesture *gesture, notMaybeGestures) {
QMap<QGesture *, QBasicTimer>::iterator it =
maybeGestures.find(gesture);
@@ -294,7 +244,9 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
// probably those are "singleshot" gestures so we'll fake the started state.
foreach (QGesture *gesture, notStarted)
gesture->d_func()->state = Qt::GestureStarted;
- deliverEvents(notStarted, receiver);
+ QSet<QGesture *> undeliveredGestures;
+ deliverEvents(notStarted, &undeliveredGestures);
+ finishedGestures -= undeliveredGestures;
}
activeGestures += startedGestures;
@@ -328,10 +280,15 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
<< "\n\tcanceled:" << canceledGestures;
}
- deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, receiver);
+ QSet<QGesture *> undeliveredGestures;
+ deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
+ &undeliveredGestures);
+
+ activeGestures -= undeliveredGestures;
// reset gestures that ended
- QSet<QGesture *> endedGestures = finishedGestures + canceledGestures;
+ QSet<QGesture *> endedGestures =
+ finishedGestures + canceledGestures + undeliveredGestures;
foreach (QGesture *gesture, endedGestures) {
if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) {
recognizer->reset(gesture);
@@ -341,100 +298,218 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
return false;
}
-void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, QObject *lastReceiver)
+bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
+{
+ QSet<Qt::GestureType> types;
+ QMap<QObject *, Qt::GestureType> contexts;
+ QWidget *w = receiver;
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ if (!w->d_func()->gestureContext.isEmpty()) {
+ for(ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ types.insert(it.key());
+ contexts.insertMulti(w, it.key());
+ }
+ }
+ // find all gesture contexts for the widget tree
+ w = w->isWindow() ? 0 : w->parentWidget();
+ while (w)
+ {
+ for (ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ if (it.value() == Qt::WidgetWithChildrenGesture) {
+ if (!types.contains(it.key())) {
+ types.insert(it.key());
+ contexts.insertMulti(w, it.key());
+ }
+ }
+ }
+ if (w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ return filterEventThroughContexts(contexts, event);
+}
+
+bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
+{
+ QSet<Qt::GestureType> types;
+ QMap<QObject *, Qt::GestureType> contexts;
+ QGraphicsObject *item = receiver;
+ if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ types.insert(it.key());
+ contexts.insertMulti(item, it.key());
+ }
+ }
+ // find all gesture contexts for the graphics object tree
+ item = item->parentObject();
+ while (item)
+ {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ if (it.value() == Qt::ItemWithChildrenGesture) {
+ if (!types.contains(it.key()))
+ contexts.insertMulti(item, it.key());
+ }
+ }
+ item = item->parentObject();
+ }
+ return filterEventThroughContexts(contexts, event);
+}
+
+bool QGestureManager::filterEvent(QGesture *state, QEvent *event)
+{
+ QMap<QObject *, Qt::GestureType> contexts;
+ contexts.insert(state, state->gestureType());
+ return filterEventThroughContexts(contexts, event);
+}
+
+void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
+ QMap<QWidget *, QList<QGesture *> > *conflicts,
+ QMap<QWidget *, QList<QGesture *> > *normal)
+{
+ typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes;
+ GestureByTypes gestureByTypes;
+
+ // sort gestures by types
+ foreach (QGesture *gesture, gestures) {
+ QWidget *receiver = gestureTargets.value(gesture, 0);
+ Q_ASSERT(receiver);
+ gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
+ }
+
+ // for each gesture type
+ foreach (Qt::GestureType type, gestureByTypes.keys()) {
+ QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type);
+ foreach (QWidget *widget, gestures.keys()) {
+ QWidget *w = widget->parentWidget();
+ while (w) {
+ QMap<Qt::GestureType, Qt::GestureContext>::const_iterator it
+ = w->d_func()->gestureContext.find(type);
+ if (it != w->d_func()->gestureContext.end()) {
+ // i.e. 'w' listens to gesture 'type'
+ Qt::GestureContext context = it.value();
+ if (context == Qt::WidgetWithChildrenGesture && w != widget) {
+ // conflicting gesture!
+ (*conflicts)[widget].append(gestures[widget]);
+ break;
+ }
+ }
+ if (w->isWindow()) {
+ w = 0;
+ break;
+ }
+ w = w->parentWidget();
+ }
+ if (!w)
+ (*normal)[widget].append(gestures[widget]);
+ }
+ }
+}
+
+void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
+ QSet<QGesture *> *undeliveredGestures)
{
if (gestures.isEmpty())
return;
- // group gestures by widgets
- typedef QMap<QObject *, QList<QGesture *> > GesturesPerReceiver;
- GesturesPerReceiver groupedGestures;
- // for conflicted gestures the key is always the innermost widget (i.e. the child)
- GesturesPerReceiver conflictedGestures;
- QMultiHash<QObject *, QGesture *> objectGestures;
+ typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget;
+ GesturesPerWidget conflictedGestures;
+ GesturesPerWidget normalStartedGestures;
- foreach (QGesture *gesture, gestures) {
- QObject *target = gestureTargets.value(gesture, 0);
+ QSet<QGesture *> startedGestures;
+ // first figure out the initial receivers of gestures
+ for (QSet<QGesture *>::const_iterator it = gestures.begin(),
+ e = gestures.end(); it != e; ++it) {
+ QGesture *gesture = *it;
+ QWidget *target = gestureTargets.value(gesture, 0);
if (!target) {
+ // the gesture has just started and doesn't have a target yet.
Q_ASSERT(gesture->state() == Qt::GestureStarted);
if (gesture->hasHotSpot()) {
- // guess the target using the hotspot of the gesture
+ // guess the target widget using the hotspot of the gesture
QPoint pt = gesture->hotSpot().toPoint();
- if (!pt.isNull()) {
- if (QWidget *w = qApp->topLevelAt(pt))
- target = w->childAt(w->mapFromGlobal(pt));
+ if (QWidget *w = qApp->topLevelAt(pt)) {
+ target = w->childAt(w->mapFromGlobal(pt));
}
+ } else {
+ // or use the context of the gesture
+ QObject *context = gestureOwners.value(gesture, 0);
+ if (context->isWidgetType())
+ target = static_cast<QWidget *>(context);
}
- if (!target) {
- target = gesture->targetObject();
- if (!target)
- target = lastReceiver;
- }
+ if (target)
+ gestureTargets.insert(gesture, target);
}
+
+ Qt::GestureType gestureType = gesture->gestureType();
+ Q_ASSERT(gestureType != Qt::CustomGesture);
+
if (target) {
- gestureTargets.insert(gesture, target);
- if (target->isWidgetType())
- objectGestures.insert(target, gesture);
- groupedGestures[target].append(gesture);
+ if (gesture->state() == Qt::GestureStarted) {
+ startedGestures.insert(gesture);
+ } else {
+ normalStartedGestures[target].append(gesture);
+ }
} else {
- qWarning() << "QGestureManager::deliverEvent: could not find the target for gesture"
+ DEBUG() << "QGestureManager::deliverEvent: could not find the target for gesture"
<< gesture->gestureType();
+ qWarning("QGestureManager::deliverEvent: could not find the target for gesture");
+ undeliveredGestures->insert(gesture);
}
}
- typedef QMultiHash<QObject *, QGesture *>::const_iterator ObjectGesturesIterator;
- for (ObjectGesturesIterator it = objectGestures.begin(), e = objectGestures.end(); it != e; ++it) {
- QObject *object1 = it.key();
- QWidget *widget1 = qobject_cast<QWidget *>(object1);
- QGraphicsObject *item1 = qobject_cast<QGraphicsObject *>(object1);
- QGesture *gesture1 = it.value();
- ObjectGesturesIterator cit = it;
- for (++cit; cit != e; ++cit) {
- QObject *object2 = cit.key();
- QWidget *widget2 = qobject_cast<QWidget *>(object2);
- QGraphicsObject *item2 = qobject_cast<QGraphicsObject *>(object2);
- QGesture *gesture2 = cit.value();
- // TODO: ugly, rewrite this.
- if ((widget1 && widget2 && widget2->isAncestorOf(widget1)) ||
- (item1 && item2 && item2->isAncestorOf(item1))) {
- groupedGestures[object2].removeOne(gesture2);
- groupedGestures[object1].removeOne(gesture1);
- conflictedGestures[object1].append(gesture1);
- } else if ((widget1 && widget2 && widget1->isAncestorOf(widget2)) ||
- (item1 && item2 && item1->isAncestorOf(item2))) {
- groupedGestures[object2].removeOne(gesture2);
- groupedGestures[object1].removeOne(gesture1);
- conflictedGestures[object2].append(gesture2);
- }
- }
- }
-
- DEBUG() << "deliverEvents: conflicted =" << conflictedGestures.values()
- << " grouped =" << groupedGestures.values();
+ getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures);
+ DEBUG() << "QGestureManager::deliverEvents:"
+ << "\nstarted: " << startedGestures
+ << "\nconflicted: " << conflictedGestures
+ << "\nnormal: " << normalStartedGestures
+ << "\n";
// if there are conflicting gestures, send the GestureOverride event
- for (GesturesPerReceiver::const_iterator it = conflictedGestures.begin(),
+ for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(),
e = conflictedGestures.end(); it != e; ++it) {
+ QWidget *receiver = it.key();
+ QList<QGesture *> gestures = it.value();
DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to"
- << it.key()
- << " gestures:" << it.value();
- QGestureEvent event(it.value());
+ << receiver
+ << "gestures:" << gestures;
+ QGestureEvent event(gestures);
event.t = QEvent::GestureOverride;
+ // mark event and individual gestures as ignored
event.ignore();
- QApplication::sendEvent(it.key(), &event);
- if (!event.isAccepted()) {
- // nobody accepted the GestureOverride, put it back to deliver to
- // the closest context (i.e. to the inner-most widget).
- DEBUG() <<" override was not accepted";
- groupedGestures[it.key()].append(it.value());
+ foreach(QGesture *g, gestures)
+ event.setAccepted(g, false);
+
+ QApplication::sendEvent(receiver, &event);
+ bool eventAccepted = event.isAccepted();
+ foreach(QGesture *gesture, event.allGestures()) {
+ if (eventAccepted || event.isAccepted(gesture)) {
+ QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
+ Q_ASSERT(w);
+ DEBUG() << "override event: gesture was accepted:" << gesture << w;
+ QList<QGesture *> &gestures = normalStartedGestures[w];
+ gestures.append(gesture);
+ // override the target
+ gestureTargets[gesture] = w;
+ } else {
+ DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture;
+ QList<QGesture *> &gestures = normalStartedGestures[receiver];
+ gestures.append(gesture);
+ }
}
}
- for (GesturesPerReceiver::const_iterator it = groupedGestures.begin(),
- e = groupedGestures.end(); it != e; ++it) {
+ // delivering gestures that are not in conflicted state
+ for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(),
+ e = normalStartedGestures.end(); it != e; ++it) {
if (!it.value().isEmpty()) {
DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key()
- << " gestures:" << it.value();
+ << "gestures:" << it.value();
QGestureEvent event(it.value());
QApplication::sendEvent(it.key(), &event);
}
@@ -452,7 +527,8 @@ void QGestureManager::timerEvent(QTimerEvent *event)
timer.stop();
QGesture *gesture = it.key();
it = maybeGestures.erase(it);
- DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" << gesture;
+ DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:"
+ << gesture;
QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0);
if (recognizer)
recognizer->reset(gesture);
diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h
index c61819f..f0e7225 100644
--- a/src/gui/kernel/qgesturemanager_p.h
+++ b/src/gui/kernel/qgesturemanager_p.h
@@ -61,6 +61,7 @@
QT_BEGIN_NAMESPACE
class QBasicTimer;
+class QGraphicsObject;
class QGestureManager : public QObject
{
Q_OBJECT
@@ -71,13 +72,17 @@ public:
Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer);
void unregisterGestureRecognizer(Qt::GestureType type);
- bool filterEvent(QObject *receiver, QEvent *event);
+ bool filterEvent(QWidget *receiver, QEvent *event);
+ bool filterEvent(QGesture *receiver, QEvent *event);
+ bool filterEvent(QGraphicsObject *receiver, QEvent *event);
// declared in qapplication.cpp
static QGestureManager* instance();
protected:
void timerEvent(QTimerEvent *event);
+ bool filterEventThroughContexts(const QMap<QObject *, Qt::GestureType> &contexts,
+ QEvent *event);
private:
QMultiMap<Qt::GestureType, QGestureRecognizer *> recognizers;
@@ -109,15 +114,20 @@ private:
}
};
- QMap<ObjectGesture, QWeakPointer<QGesture> > objectGestures;
+ QMap<ObjectGesture, QGesture *> objectGestures;
QMap<QGesture *, QGestureRecognizer *> gestureToRecognizer;
+ QHash<QGesture *, QObject *> gestureOwners;
- QHash<QGesture *, QObject *> gestureTargets;
+ QHash<QGesture *, QWidget *> gestureTargets;
int lastCustomGestureId;
QGesture *getState(QObject *widget, Qt::GestureType gesture);
- void deliverEvents(const QSet<QGesture *> &gestures, QObject *lastReceiver);
+ void deliverEvents(const QSet<QGesture *> &gestures,
+ QSet<QGesture *> *undeliveredGestures);
+ void getGestureTargets(const QSet<QGesture*> &gestures,
+ QMap<QWidget *, QList<QGesture *> > *conflicts,
+ QMap<QWidget *, QList<QGesture *> > *normal);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index 9de3bcc..ba3a750 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -186,7 +186,7 @@ void QGestureRecognizer::reset(QGesture *gesture)
\fn QGestureRecognizer::filterEvent(QGesture *gesture, QObject *watched, QEvent *event)
Handles the given \a event for the \a watched object, updating the state of the \a gesture
- object as required, and returns a suitable Result for the current recognition step.
+ object as required, and returns a suitable result for the current recognition step.
This function is called by the framework to allow the recognizer to filter input events
dispatched to QWidget or QGraphicsObject instances that it is monitoring.
diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm
index 7b19a54..7019580 100644
--- a/src/gui/kernel/qmacgesturerecognizer_mac.mm
+++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm
@@ -218,7 +218,7 @@ QMacPanGestureRecognizer::filterEvent(QGesture *gesture, QObject *target, QEvent
const QPointF p = QCursor::pos();
const QPointF posOffset = p - _lastPos;
g->setLastOffset(g->offset());
- g->setOffset(QSizeF(posOffset.x(), posOffset.y()));
+ g->setOffset(QPointF(posOffset.x(), posOffset.y()));
g->setTotalOffset(g->lastOffset() + g->offset());
_lastPos = p;
return QGestureRecognizer::GestureTriggered;
@@ -256,9 +256,9 @@ void QMacPanGestureRecognizer::reset(QGesture *gesture)
_startPos = QPointF();
_lastPos = QPointF();
_panCanceled = true;
- g->setOffset(QSizeF(0, 0));
- g->setLastOffset(QSizeF(0, 0));
- g->setTotalOffset(QSizeF(0, 0));
+ g->setOffset(QPointF(0, 0));
+ g->setLastOffset(QPointF(0, 0));
+ g->setTotalOffset(QPointF(0, 0));
g->setAcceleration(qreal(1));
QGestureRecognizer::reset(gesture);
}
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index dfc3499..a136379 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -73,7 +73,7 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q
result = QGestureRecognizer::MaybeGesture;
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastPosition = p.pos().toPoint();
- d->lastOffset = d->totalOffset = d->offset = QSize();
+ d->lastOffset = d->totalOffset = d->offset = QPointF();
break;
}
case QEvent::TouchEnd: {
@@ -83,7 +83,7 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
d->lastOffset = d->offset;
d->offset =
- QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
+ QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
d->totalOffset += d->offset;
}
@@ -99,11 +99,11 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
d->lastOffset = d->offset;
d->offset =
- QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
+ QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
d->totalOffset += d->offset;
- if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 ||
- d->totalOffset.width() < -10 || d->totalOffset.height() < -10) {
+ if (d->totalOffset.x() > 10 || d->totalOffset.y() > 10 ||
+ d->totalOffset.x() < -10 || d->totalOffset.y() < -10) {
result = QGestureRecognizer::GestureTriggered;
} else {
result = QGestureRecognizer::MaybeGesture;
@@ -128,7 +128,7 @@ void QPanGestureRecognizer::reset(QGesture *state)
QPanGesture *pan = static_cast<QPanGesture*>(state);
QPanGesturePrivate *d = pan->d_func();
- d->totalOffset = d->lastOffset = d->offset = QSizeF();
+ d->totalOffset = d->lastOffset = d->offset = QPointF();
d->lastPosition = QPoint();
d->acceleration = 0;
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index de08312..5fa9a92 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -93,6 +93,7 @@
# include "qx11info_x11.h"
#endif
+#include <private/qgraphicseffect_p.h>
#include <private/qwindowsurface_p.h>
#include <private/qbackingstore_p.h>
#ifdef Q_WS_MAC
@@ -149,24 +150,6 @@ static inline bool hasBackingStoreSupport()
#endif
}
-/*!
- \internal
-
- Returns true if \a p or any of its parents enable the
- Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and
- QWidget::setParent() to determine whether it's necessary to embed the
- widget into a QGraphicsProxyWidget or not.
-*/
-static inline bool bypassGraphicsProxyWidget(QWidget *p)
-{
- while (p) {
- if (p->windowFlags() & Qt::BypassGraphicsProxyWidget)
- return true;
- p = p->parentWidget();
- }
- return false;
-}
-
#ifdef Q_WS_MAC
# define QT_NO_PAINT_DEBUG
#endif
@@ -1806,12 +1789,29 @@ QRegion QWidgetPrivate::clipRegion() const
return r;
}
+void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
+{
+ Q_Q(QWidget);
+ QWidget *w = q;
+ do {
+ if (w->graphicsEffect()) {
+ QWidgetEffectSourcePrivate *sourced =
+ static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
+ if (!sourced->updateDueToGraphicsEffect)
+ w->graphicsEffect()->source()->d_func()->invalidateCache();
+ }
+ w = w->parentWidget();
+ } while (w);
+}
+
void QWidgetPrivate::setDirtyOpaqueRegion()
{
Q_Q(QWidget);
dirtyOpaqueChildren = true;
+ invalidateGraphicsEffectsRecursively();
+
if (q->isWindow())
return;
@@ -5215,6 +5215,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
paintEngine->d_func()->systemClip = QRegion();
} else {
context.painter = sharedPainter;
+ if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
+ sourced->invalidateCache();
+ sourced->lastEffectTransform = sharedPainter->worldTransform();
+ }
sharedPainter->save();
sharedPainter->translate(offset);
graphicsEffect->draw(sharedPainter, source);
@@ -5487,6 +5491,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
return pixmap;
}
+#ifndef QT_NO_GRAPHICSVIEW
/*!
\internal
@@ -5495,7 +5500,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
If successful, the function returns the proxy that embeds the widget, or 0 if no embedded
widget was found.
*/
-QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(QWidget *origin)
+QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
{
if (origin) {
QWExtra *extra = origin->d_func()->extra;
@@ -5505,6 +5510,7 @@ QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(QWidget *origi
}
return 0;
}
+#endif
/*!
\property QWidget::locale
@@ -7314,7 +7320,7 @@ void QWidget::setVisible(bool visible)
break;
parent = parent->parentWidget();
}
- if (parent && !d->getOpaqueRegion().isEmpty())
+ if (parent)
parent->d_func()->setDirtyOpaqueRegion();
}
@@ -7739,6 +7745,10 @@ void QWidget::adjustSize()
Q_D(QWidget);
ensurePolished();
QSize s = d->adjustedSize();
+
+ if (d->layout)
+ d->layout->activate();
+
if (s.isValid())
resize(s);
}
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 05c6a5b..d08f8a9 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -3048,6 +3048,7 @@ void QWidget::grabMouse()
}
}
+#ifndef QT_NO_CURSOR
void QWidget::grabMouse(const QCursor &)
{
if(isVisible() && !qt_nograb()) {
@@ -3056,6 +3057,7 @@ void QWidget::grabMouse(const QCursor &)
mac_mouse_grabber=this;
}
}
+#endif
void QWidget::releaseMouse()
{
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index f7c2712..159a3f2 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -63,7 +63,9 @@
#include "QtGui/qstyle.h"
#include "QtGui/qapplication.h"
#include <private/qgraphicseffect_p.h>
-
+#include "QtGui/qgraphicsproxywidget.h"
+#include "QtGui/qgraphicsscene.h"
+#include "QtGui/qgraphicsview.h"
#include <private/qgesture_p.h>
#ifdef Q_WS_WIN
@@ -180,7 +182,9 @@ struct QWExtra {
// Regular pointers (keep them together to avoid gaps on 64 bits architectures).
void *glContext; // if the widget is hijacked by QGLWindowSurface
QTLWExtra *topextra; // only useful for TLWs
+#ifndef QT_NO_GRAPHICSVIEW
QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
+#endif
#ifndef QT_NO_CURSOR
QCursor *curs;
#endif
@@ -235,6 +239,24 @@ struct QWExtra {
#endif
};
+/*!
+ \internal
+
+ Returns true if \a p or any of its parents enable the
+ Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and
+ QWidget::setParent() to determine whether it's necessary to embed the
+ widget into a QGraphicsProxyWidget or not.
+*/
+static inline bool bypassGraphicsProxyWidget(const QWidget *p)
+{
+ while (p) {
+ if (p->windowFlags() & Qt::BypassGraphicsProxyWidget)
+ return true;
+ p = p->parentWidget();
+ }
+ return false;
+}
+
class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QWidget)
@@ -345,7 +367,9 @@ public:
QPainter *beginSharedPainter();
bool endSharedPainter();
- static QGraphicsProxyWidget * nearestGraphicsProxyWidget(QWidget *origin);
+#ifndef QT_NO_GRAPHICSVIEW
+ static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin);
+#endif
QWindowSurface *createDefaultWindowSurface();
QWindowSurface *createDefaultWindowSurface_sys();
void repaint_sys(const QRegion &rgn);
@@ -360,6 +384,7 @@ public:
void setOpaque(bool opaque);
void updateIsTranslucent();
bool paintOnScreen() const;
+ void invalidateGraphicsEffectsRecursively();
QRegion getOpaqueRegion() const;
const QRegion &getOpaqueChildren() const;
@@ -442,6 +467,31 @@ public:
void setModal_sys();
+ // This is an helper function that return the available geometry for
+ // a widget and takes care is this one is in QGraphicsView.
+ // If the widget is not embed in a scene then the geometry available is
+ // null, we let QDesktopWidget decide for us.
+ static QRect screenGeometry(const QWidget *widget)
+ {
+ QRect screen;
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
+ //It's embedded if it has an ancestor
+ if (ancestorProxy) {
+ if (!bypassGraphicsProxyWidget(widget)) {
+ // One view, let be smart and return the viewport rect then the popup is aligned
+ if (ancestorProxy->scene()->views().size() == 1) {
+ QGraphicsView *view = ancestorProxy->scene()->views().at(0);
+ screen = view->mapToScene(view->viewport()->rect()).boundingRect().toRect();
+ } else {
+ screen = ancestorProxy->scene()->sceneRect().toRect();
+ }
+ }
+ }
+#endif
+ return screen;
+ }
+
inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
{
Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
@@ -729,7 +779,7 @@ class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
{
public:
QWidgetEffectSourcePrivate(QWidget *widget)
- : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0)
+ : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0), updateDueToGraphicsEffect(false)
{}
inline void detach()
@@ -742,7 +792,11 @@ public:
{ return m_widget; }
inline void update()
- { m_widget->update(); }
+ {
+ updateDueToGraphicsEffect = true;
+ m_widget->update();
+ updateDueToGraphicsEffect = false;
+ }
inline bool isPixmap() const
{ return false; }
@@ -754,7 +808,7 @@ public:
if (QWidget *parent = m_widget->parentWidget())
parent->update();
else
- m_widget->update();
+ update();
}
inline const QStyleOption *styleOption() const
@@ -769,6 +823,8 @@ public:
QWidget *m_widget;
QWidgetPaintContext *context;
+ QTransform lastEffectTransform;
+ bool updateDueToGraphicsEffect;
};
inline QWExtra *QWidgetPrivate::extraData() const
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 0672fee..5bf7649 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -854,10 +854,13 @@ void QWidget::grabMouse()
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
SetCapture(effectiveWinId());
mouseGrb = this;
+#ifndef QT_NO_CURSOR
mouseGrbCur = new QCursor(mouseGrb->cursor());
+#endif
}
}
+#ifndef QT_NO_CURSOR
void QWidget::grabMouse(const QCursor &cursor)
{
if (!qt_nograb()) {
@@ -871,6 +874,7 @@ void QWidget::grabMouse(const QCursor &cursor)
mouseGrb = this;
}
}
+#endif
void QWidget::releaseMouse()
{
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 663178f..28676da 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -950,7 +950,7 @@ static void qt_x11_recreateWidget(QWidget *widget)
static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
{
- if (widget->testAttribute(Qt::WA_NativeWindow))
+ if (widget->internalWinId())
qt_x11_recreateWidget(widget);
const QObjectList &children = widget->children();
diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp
index 4619594..12d3058 100644
--- a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp
+++ b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp
@@ -97,11 +97,11 @@ QGestureRecognizer::Result QWinNativePanGestureRecognizer::filterEvent(QGesture
return QGestureRecognizer::Ignore;
}
if (q->state() == Qt::NoGesture) {
- d->lastOffset = d->totalOffset = d->offset = QSize();
+ d->lastOffset = d->totalOffset = d->offset = QPointF();
} else {
d->lastOffset = d->offset;
- d->offset = QSize(ev->position.x() - d->lastPosition.x(),
- ev->position.y() - d->lastPosition.y());
+ d->offset = QPointF(ev->position.x() - d->lastPosition.x(),
+ ev->position.y() - d->lastPosition.y());
d->totalOffset += d->offset;
}
d->lastPosition = ev->position;
@@ -114,7 +114,7 @@ void QWinNativePanGestureRecognizer::reset(QGesture *state)
QPanGesture *pan = static_cast<QPanGesture*>(state);
QPanGesturePrivate *d = pan->d_func();
- d->totalOffset = d->lastOffset = d->offset = QSizeF();
+ d->totalOffset = d->lastOffset = d->offset = QPointF();
d->lastPosition = QPoint();
d->acceleration = 0;
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index ed1b13d..5d624d8 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE
\sa QVector3D, QGenericMatrix
*/
+static const qreal inv_dist_to_plane = 1. / 1024.;
+
/*!
\fn QMatrix4x4::QMatrix4x4()
@@ -1103,7 +1105,111 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
return *this;
}
-#ifndef QT_NO_VECTOR4D
+/*!
+ \internal
+*/
+QMatrix4x4& QMatrix4x4::projectedRotate(qreal angle, qreal x, qreal y, qreal z)
+{
+ // Used by QGraphicsRotation::applyTo() to perform a rotation
+ // and projection back to 2D in a single step.
+ if (angle == 0.0f)
+ return *this;
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ qreal c, s, ic;
+ if (angle == 90.0f || angle == -270.0f) {
+ s = 1.0f;
+ c = 0.0f;
+ } else if (angle == -90.0f || angle == 270.0f) {
+ s = -1.0f;
+ c = 0.0f;
+ } else if (angle == 180.0f || angle == -180.0f) {
+ s = 0.0f;
+ c = -1.0f;
+ } else {
+ qreal a = angle * M_PI / 180.0f;
+ c = qCos(a);
+ s = qSin(a);
+ }
+ bool quick = false;
+ if (x == 0.0f) {
+ if (y == 0.0f) {
+ if (z != 0.0f) {
+ // Rotate around the Z axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[1][1] = c;
+ if (z < 0.0f) {
+ m.m[1][0] = s;
+ m.m[0][1] = -s;
+ } else {
+ m.m[1][0] = -s;
+ m.m[0][1] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (z == 0.0f) {
+ // Rotate around the Y axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[2][2] = 1.0f;
+ if (y < 0.0f) {
+ m.m[0][3] = -s * inv_dist_to_plane;
+ } else {
+ m.m[0][3] = s * inv_dist_to_plane;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (y == 0.0f && z == 0.0f) {
+ // Rotate around the X axis.
+ m.setIdentity();
+ m.m[1][1] = c;
+ m.m[2][2] = 1.0f;
+ if (x < 0.0f) {
+ m.m[1][3] = s * inv_dist_to_plane;
+ } else {
+ m.m[1][3] = -s * inv_dist_to_plane;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ if (!quick) {
+ qreal len = x * x + y * y + z * z;
+ if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
+ len = qSqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+ ic = 1.0f - c;
+ m.m[0][0] = x * x * ic + c;
+ m.m[1][0] = x * y * ic - z * s;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = y * x * ic + z * s;
+ m.m[1][1] = y * y * ic + c;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = 1.0f;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane;
+ m.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ }
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#ifndef QT_NO_QUATERNION
/*!
Multiples this matrix by another that rotates coordinates according
@@ -1430,15 +1536,31 @@ QMatrix QMatrix4x4::toAffine() const
m[3][0], m[3][1]);
}
-static const qreal inv_dist_to_plane = 1. / 1024.;
+/*!
+ Returns the conventional Qt 2D transformation matrix that
+ corresponds to this matrix.
+
+ The returned QTransform is formed by simply dropping the
+ third row and third column of the QMatrix4x4. This is suitable
+ for implementing orthographic projections where the z co-ordinate
+ should be dropped rather than projected.
+
+ \sa toAffine()
+*/
+QTransform QMatrix4x4::toTransform() const
+{
+ return QTransform(m[0][0], m[0][1], m[0][3],
+ m[1][0], m[1][1], m[1][3],
+ m[3][0], m[3][1], m[3][3]);
+}
/*!
Returns the conventional Qt 2D transformation matrix that
corresponds to this matrix.
If \a distanceToPlane is non-zero, it indicates a projection
- factor to use to adjust for the z co-ordinate. The default
- value of 1024 corresponds to the projection factor used
+ factor to use to adjust for the z co-ordinate. The value of
+ 1024 corresponds to the projection factor used
by QTransform::rotate() for the x and y axes.
If \a distanceToPlane is zero, then the returned QTransform
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index b32e00a..ba74b89 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -159,7 +159,8 @@ public:
void toValueArray(qreal *values) const;
QMatrix toAffine() const;
- QTransform toTransform(qreal distanceToPlane = 1024.0f) const;
+ QTransform toTransform() const;
+ QTransform toTransform(qreal distanceToPlane) const;
QPoint map(const QPoint& point) const;
QPointF map(const QPointF& point) const;
@@ -206,6 +207,10 @@ private:
QMatrix4x4(int) { flagBits = General; }
QMatrix4x4 orthonormalInverse() const;
+
+ QMatrix4x4& projectedRotate(qreal angle, qreal x, qreal y, qreal z);
+
+ friend class QGraphicsRotation;
};
inline QMatrix4x4::QMatrix4x4
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 7facd91..00966d6 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -56,6 +56,7 @@
#include <private/qwindowsurface_raster_p.h>
#include <private/qapplication_p.h>
#include <private/qpaintengine_raster_p.h>
+#include <private/qgraphicseffect_p.h>
#include "qgraphicssystem_p.h"
@@ -528,6 +529,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
Q_ASSERT(widget->window() == tlw);
Q_ASSERT(!rgn.isEmpty());
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+
if (widget->d_func()->paintOnScreen()) {
if (widget->d_func()->dirty.isEmpty()) {
widget->d_func()->dirty = rgn;
@@ -603,6 +606,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
Q_ASSERT(widget->window() == tlw);
Q_ASSERT(!rect.isEmpty());
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+
if (widget->d_func()->paintOnScreen()) {
if (widget->d_func()->dirty.isEmpty()) {
widget->d_func()->dirty = QRegion(rect);
diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h
index 94d756e..3288dae 100644
--- a/src/gui/painting/qbackingstore_p.h
+++ b/src/gui/painting/qbackingstore_p.h
@@ -97,6 +97,12 @@ public:
);
}
+ // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+ void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false,
+ bool invalidateBuffer = false);
+ void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false,
+ bool invalidateBuffer = false);
+
private:
QWidget *tlw;
QRegion dirtyOnScreen; // needsFlush
@@ -126,11 +132,6 @@ private:
QRegion dirtyRegion(QWidget *widget = 0) const;
QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const;
- // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
- void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false,
- bool invalidateBuffer = false);
- void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false,
- bool invalidateBuffer = false);
void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset);
void removeDirtyWidget(QWidget *w);
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index fabd7ca..fc12cfe 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -3866,7 +3866,7 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption *
if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
if (!menuItem->text.isEmpty()) {
- newSize.setHeight(menuItem->fontMetrics.lineSpacing());
+ newSize.setHeight(menuItem->fontMetrics.height());
}
}
#ifndef QT_NO_COMBOBOX
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 5886512..70d130a 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -4396,13 +4396,13 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_TitleBarHeight: {
if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) {
- ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 16);
+ ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16);
#ifndef QT_NO_DOCKWIDGET
} else if (qobject_cast<const QDockWidget*>(widget)) {
- ret = qMax(widget->fontMetrics().lineSpacing(), int(QStyleHelper::dpiScaled(13)));
+ ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13)));
#endif
} else {
- ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 18);
+ ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18);
}
} else {
ret = int(QStyleHelper::dpiScaled(18.));
diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp
index e6c60cf..b65d45c 100644
--- a/src/gui/styles/qmotifstyle.cpp
+++ b/src/gui/styles/qmotifstyle.cpp
@@ -1154,7 +1154,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
menuitem->palette, menuitem->state & State_Enabled, menuitem->text,
QPalette::Text);
textWidth = menuitem->fontMetrics.width(menuitem->text) + 10;
- y += menuitem->fontMetrics.lineSpacing() / 2;
+ y += menuitem->fontMetrics.height() / 2;
p->setFont(oldFont);
}
p->setPen(opt->palette.dark().color());
@@ -2056,7 +2056,7 @@ QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
w = 10;
- h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.lineSpacing();
+ h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.height();
}
// a little bit of border can never harm
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index ce2109a..09f5d36 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -5027,7 +5027,7 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o
case CT_MenuItem:
if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator)
- newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.lineSpacing());
+ newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.height());
}
break;
case CT_MenuBarItem:
@@ -5607,11 +5607,11 @@ int QPlastiqueStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
#ifdef QT3_SUPPORT
if (widget && widget->inherits("Q3DockWindowTitleBar")) {
// Q3DockWindow has smaller title bars than QDockWidget
- ret = qMax(widget->fontMetrics().lineSpacing(), 20);
+ ret = qMax(widget->fontMetrics().height(), 20);
} else
#endif
- ret = qMax(widget ? widget->fontMetrics().lineSpacing() :
- (option ? option->fontMetrics.lineSpacing() : 0), 30);
+ ret = qMax(widget ? widget->fontMetrics().height() :
+ (option ? option->fontMetrics.height() : 0), 30);
break;
case PM_MaximumDragDistance:
return -1;
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 707b05e..2d90aa1 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -4722,7 +4722,7 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const
return subRule.size().height();
else if (subRule.hasBox() || subRule.hasBorder()) {
QFontMetrics fm = opt ? opt->fontMetrics : w->fontMetrics();
- return subRule.size(QSize(0, fm.lineSpacing())).height();
+ return subRule.size(QSize(0, fm.height())).height();
}
break;
}
diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp
index 5fa6251..7ed187f 100644
--- a/src/gui/styles/qwindowsmobilestyle.cpp
+++ b/src/gui/styles/qwindowsmobilestyle.cpp
@@ -5347,10 +5347,8 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
painter->drawLines(a);
break; }
case PE_Frame:
- if (d->doubleControls)
- qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),2,&option->palette.light());
- else
- qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),1,&option->palette.light());
+ qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),
+ d->doubleControls ? 2 : 1, &option->palette.background());
break;
case PE_FrameLineEdit:
case PE_FrameMenu:
@@ -6840,34 +6838,11 @@ void QWindowsMobileStyle::polish(QWidget *widget) {
else
#endif //QT_NO_TOOLBAR
-#ifndef QT_NO_PROPERTIES
- if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) {
- QVariant oldFont = widget->property("_q_styleWindowsMobileFont");
- if (!oldFont.isValid()) {
- QFont f = pushButton->font();
- widget->setProperty("_q_styleWindowsMobileFont", f);
- f.setBold(true);
- int p = f.pointSize();
- if (p > 2)
- f.setPointSize(p-1);
- pushButton->setFont(f);
- }
- }
-#endif
- QWindowsStyle::polish(widget);
+ QWindowsStyle::polish(widget);
}
void QWindowsMobileStyle::unpolish(QWidget *widget)
{
-#ifndef QT_NO_PROPERTIES
- if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) {
- QVariant oldFont = widget->property("_q_styleWindowsMobileFont");
- if (oldFont.isValid()) {
- widget->setFont(qVariantValue<QFont>(oldFont));
- widget->setProperty("_q_styleWindowsMobileFont", QVariant());
- }
- }
-#endif
QWindowsStyle::unpolish(widget);
}
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 1285935..1b4c380 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2632,7 +2632,7 @@ QFontCache::~QFontCache()
while (it != end) {
if (--it.value().data->cache_count == 0) {
if (it.value().data->ref == 0) {
- FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %d %d %d %d)",
+ FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %g %d %d %d)",
it.value().data, it.key().script, it.key().def.pointSize,
it.key().def.pixelSize, it.key().def.weight, it.key().def.style,
it.key().def.fixedPitch);
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index d74f0b4..144a82d 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -86,7 +86,7 @@ struct QFontDef
#endif // Q_WS_X11
qreal pointSize;
- int pixelSize;
+ qreal pixelSize;
uint styleStrategy : 16;
uint styleHint : 8;
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 738e36a..fb8444e 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -1331,7 +1331,7 @@ static void match(int script, const QFontDef &request,
" family: %s [%s], script: %d\n"
" weight: %d, style: %d\n"
" stretch: %d\n"
- " pixelSize: %d\n"
+ " pixelSize: %g\n"
" pitch: %c",
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index ae26dab..6cde9ed 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qt_windows.h"
+#include <qmath.h>
#include <private/qapplication_p.h>
#include "qfont_p.h"
#include "qfontengine_p.h"
@@ -670,7 +671,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
break;
}
- lf.lfHeight = -request.pixelSize;
+ lf.lfHeight = -qRound(request.pixelSize);
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
@@ -899,7 +900,6 @@ static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &r
return fe;
}
-
void QFontDatabase::load(const QFontPrivate *d, int script)
{
// sanity checks
@@ -910,8 +910,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// normalize the request to get better caching
QFontDef req = d->request;
if (req.pixelSize <= 0)
- req.pixelSize = qMax(1, qRound(req.pointSize * d->dpi / 72.));
- req.pointSize = 0;
+ req.pixelSize = qreal((req.pointSize * d->dpi) / 72.);
+ if (req.pixelSize < 1)
+ req.pixelSize = 1;
if (req.weight == 0)
req.weight = QFont::Normal;
if (req.stretch == 0)
@@ -928,7 +929,8 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
QFontEngine *fe = QFontCache::instance()->findEngine(key);
// set it to the actual pointsize, so QFontInfo will do the right thing
- req.pointSize = req.pixelSize*72./d->dpi;
+ if (req.pointSize < 0)
+ req.pointSize = req.pixelSize*72./d->dpi;
if (!fe) {
if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 382c4fe..f184811 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -51,6 +51,7 @@
#include <qfile.h>
#include <qtemporaryfile.h>
#include <qabstractfileengine.h>
+#include <qmath.h>
#include <ctype.h>
#include <stdlib.h>
@@ -752,12 +753,12 @@ QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
if (X11->display)
dpi = QX11Info::appDpiY();
else
- dpi = 96; // ####
+ dpi = qt_defaultDpiY();
}
double size;
if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
- fontDef.pixelSize = qRound(size);
+ fontDef.pixelSize = size;
else
fontDef.pixelSize = 12;
@@ -1455,7 +1456,7 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD
slant_value = FC_SLANT_OBLIQUE;
FcPatternAddInteger(pattern, FC_SLANT, slant_value);
- double size_value = qMax(1, request.pixelSize);
+ double size_value = qMax(qreal(1.), request.pixelSize);
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
int stretch = request.stretch;
@@ -1893,8 +1894,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// normalize the request to get better caching
QFontDef req = d->request;
if (req.pixelSize <= 0)
- req.pixelSize = qRound(qt_pixelSize(req.pointSize, d->dpi));
- req.pointSize = 0;
+ req.pixelSize = floor(qt_pixelSize(req.pointSize, d->dpi) * 100 + 0.5) / 100;
+ if (req.pixelSize < 1)
+ req.pixelSize = 1;
if (req.weight == 0)
req.weight = QFont::Normal;
if (req.stretch == 0)
@@ -1909,7 +1911,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
return;
// set it to the actual pointsize, so QFontInfo will do the right thing
- req.pointSize = qt_pointSize(req.pixelSize, d->dpi);
+ if (req.pointSize < 0)
+ req.pointSize = qt_pointSize(req.pixelSize, d->dpi);
+
QFontEngine *fe = QFontCache::instance()->findEngine(key);
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 3da1593..4041717 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -327,7 +327,7 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
{
- *ysize = fontDef.pixelSize << 6;
+ *ysize = qRound(fontDef.pixelSize * 64);
*xsize = *ysize * fontDef.stretch / 100;
*outline_drawing = false;
@@ -387,7 +387,9 @@ QFontEngine::Properties QFreetypeFace::properties() const
p.descent = QFixed::fromFixed(-face->size->metrics.descender);
p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender);
p.emSquare = face->size->metrics.y_ppem;
- p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.);
+// p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.);
+ p.boundingBox = QRectF(0, -p.ascent.toReal(),
+ face->size->metrics.max_advance/64, (p.ascent + p.descent).toReal() );
}
p.italicAngle = 0;
p.capHeight = p.ascent;
@@ -709,6 +711,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
hbFace = freetype->hbFace;
metrics = face->size->metrics;
+
#if defined(Q_WS_QWS)
/*
TrueType fonts with embedded bitmaps may have a bitmap font specific
@@ -1219,7 +1222,8 @@ QFixed QFontEngineFT::ascent() const
QFixed QFontEngineFT::descent() const
{
- return QFixed::fromFixed(-metrics.descender);
+ // subtract a pixel to work around QFontMetrics's built-in + 1
+ return QFixed::fromFixed(-metrics.descender - 64);
}
QFixed QFontEngineFT::leading() const
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index ef3f2ae..6ff0fbd 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -819,7 +819,7 @@ FT_Face QFontEngineQPF::lockFace() const
FT_Face face = freetype->face;
// ### not perfect
- const int ysize = fontDef.pixelSize << 6;
+ const int ysize = int(fontDef.pixelSize) << 6;
const int xsize = ysize;
if (freetype->xsize != xsize || freetype->ysize != ysize) {
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index cc555a3..fd34d0f 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -125,6 +125,7 @@ HDC shared_dc()
}
#endif
+#ifndef Q_WS_WINCE
typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT);
static PtrGetCharWidthI ptrGetCharWidthI = 0;
static bool resolvedGetCharWidthI = false;
@@ -136,6 +137,7 @@ static void resolveGetCharWidthI()
resolvedGetCharWidthI = true;
ptrGetCharWidthI = (PtrGetCharWidthI)QLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI");
}
+#endif // !defined(Q_WS_WINCE)
// defined in qtextengine_win.cpp
typedef void *SCRIPT_CACHE;
@@ -340,8 +342,10 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont
designAdvances = 0;
designAdvancesSize = 0;
+#ifndef Q_WS_WINCE
if (!resolvedGetCharWidthI)
resolveGetCharWidthI();
+#endif
}
QFontEngineWin::~QFontEngineWin()
@@ -381,80 +385,18 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
if (flags & QTextEngine::GlyphIndicesOnly)
return true;
-#if defined(Q_WS_WINCE)
- HDC hdc = shared_dc();
- if (flags & QTextEngine::DesignMetrics) {
- HGDIOBJ oldFont = 0;
- int glyph_pos = 0;
- for(register int i = 0; i < len; i++) {
- bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1
- && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000);
- unsigned int glyph = glyphs->glyphs[glyph_pos];
- if(int(glyph) >= designAdvancesSize) {
- int newSize = (glyph + 256) >> 8 << 8;
- designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, newSize*sizeof(QFixed)));
- for(int i = designAdvancesSize; i < newSize; ++i)
- designAdvances[i] = -1000000;
- designAdvancesSize = newSize;
- }
- if(designAdvances[glyph] < -999999) {
- if(!oldFont)
- oldFont = selectDesignFont();
- SIZE size = {0, 0};
- GetTextExtentPoint32(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size);
- designAdvances[glyph] = QFixed((int)size.cx)/designToDevice;
- }
- glyphs->advances_x[glyph_pos] = designAdvances[glyph];
- glyphs->advances_y[glyph_pos] = 0;
- if (surrogate)
- ++i;
- ++glyph_pos;
- }
- if(oldFont)
- DeleteObject(SelectObject(hdc, oldFont));
- } else {
- int glyph_pos = 0;
- HGDIOBJ oldFont = 0;
-
- for(register int i = 0; i < len; i++) {
- bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1
- && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000);
- unsigned int glyph = glyphs->glyphs[glyph_pos];
-
- glyphs->advances_y[glyph_pos] = 0;
-
- if (glyph >= widthCacheSize) {
- int newSize = (glyph + 256) >> 8 << 8;
- widthCache = q_check_ptr((unsigned char *)realloc(widthCache,
- newSize*sizeof(QFixed)));
- memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize);
- widthCacheSize = newSize;
- }
- glyphs->advances_x[glyph_pos] = widthCache[glyph];
- // font-width cache failed
- if (glyphs->advances_x[glyph_pos] == 0) {
- SIZE size = {0, 0};
- if (!oldFont)
- oldFont = SelectObject(hdc, hfont);
- GetTextExtentPoint32(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size);
- glyphs->advances_x[glyph_pos] = size.cx;
- // if glyph's within cache range, store it for later
- if (size.cx > 0 && size.cx < 0x100)
- widthCache[glyph] = size.cx;
- }
-
- if (surrogate)
- ++i;
- ++glyph_pos;
- }
+ recalcAdvances(glyphs, flags);
+ return true;
+}
- if (oldFont)
- SelectObject(hdc, oldFont);
- }
+inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
+{
+#if defined(Q_WS_WINCE)
+ GetCharWidth32(hdc, glyph, glyph, &width);
#else
- recalcAdvances(glyphs, flags);
+ if (ptrGetCharWidthI)
+ ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
#endif
- return true;
}
void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
@@ -477,8 +419,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
oldFont = selectDesignFont();
int width = 0;
- if (ptrGetCharWidthI)
- ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
+ calculateTTFGlyphWidth(hdc, glyph, width);
designAdvances[glyph] = QFixed(width) / designToDevice;
}
glyphs->advances_x[i] = designAdvances[glyph];
@@ -517,8 +458,8 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
SIZE size = {0, 0};
GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size);
width = size.cx;
- } else if (ptrGetCharWidthI) {
- ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
+ } else {
+ calculateTTFGlyphWidth(hdc, glyph, width);
}
glyphs->advances_x[i] = width;
// if glyph's within cache range, store it for later
@@ -636,7 +577,9 @@ QFixed QFontEngineWin::ascent() const
QFixed QFontEngineWin::descent() const
{
- return tm.tmDescent;
+ // ### we substract 1 to even out the historical +1 in QFontMetrics's
+ // ### height=asc+desc+1 equation. Fix in Qt5.
+ return tm.tmDescent - 1;
}
QFixed QFontEngineWin::leading() const
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index de83d39..73434b1 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -1437,7 +1437,9 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
option.setTextDirection(dir);
layout.setTextOption(option);
layout.beginLayout();
- layout.createLine();
+ QTextLine line = layout.createLine();
+ if (line.isValid())
+ line.setLeadingIncluded(true);
layout.endLayout();
layout.draw(painter, QPointF(r.left(), pos.y()));
break;
@@ -2579,6 +2581,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLine line = tl->createLine();
if (!line.isValid())
break;
+ line.setLeadingIncluded(true);
QFixed left, right;
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 81c9142..a91408f 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1042,7 +1042,7 @@ void QTextEngine::shapeTextWithCE(int item) const
QScriptItem &si = layoutData->items[item];
si.glyph_data_offset = layoutData->used;
- QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent);
+ QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent, &si.leading);
QTextEngine::ShaperFlags flags;
if (si.analysis.bidiLevel % 2)
@@ -1119,7 +1119,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
si.glyph_data_offset = layoutData->used;
- QFontEngine *font = fontEngine(si, &si.ascent, &si.descent);
+ QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
bool kerningEnabled = this->font(si).d->kerning;
@@ -1350,8 +1350,11 @@ void QTextEngine::shape(int item) const
layoutData->items[item].position + block.position(), format);
}
} else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) {
- // set up at least the ascent/descent of the script item for the tab
- fontEngine(layoutData->items[item], &layoutData->items[item].ascent, &layoutData->items[item].descent);
+ // set up at least the ascent/descent/leading of the script item for the tab
+ fontEngine(layoutData->items[item],
+ &layoutData->items[item].ascent,
+ &layoutData->items[item].descent,
+ &layoutData->items[item].leading);
} else {
shapeText(item);
}
@@ -1737,7 +1740,7 @@ QFont QTextEngine::font(const QScriptItem &si) const
return font;
}
-QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent) const
+QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const
{
QFontEngine *engine = 0;
QFontEngine *scaledEngine = 0;
@@ -1777,6 +1780,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
if (ascent) {
*ascent = engine->ascent();
*descent = engine->descent();
+ *leading = engine->leading();
}
if (scaledEngine)
@@ -2009,8 +2013,12 @@ void QScriptLine::setDefaultHeight(QTextEngine *eng)
e = eng->fnt.d->engineForScript(QUnicodeTables::Common);
}
- ascent = qMax(ascent, e->ascent());
- descent = qMax(descent, e->descent());
+ QFixed other_ascent = e->ascent();
+ QFixed other_descent = e->descent();
+ QFixed other_leading = e->leading();
+ leading = qMax(leading + ascent, other_leading + other_ascent) - qMax(ascent, other_ascent);
+ ascent = qMax(ascent, other_ascent);
+ descent = qMax(descent, other_descent);
}
QTextEngine::LayoutData::LayoutData()
diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp
index e101830..eeccc72 100644
--- a/src/gui/text/qtextengine_mac.cpp
+++ b/src/gui/text/qtextengine_mac.cpp
@@ -557,7 +557,7 @@ void QTextEngine::shapeTextMac(int item) const
si.glyph_data_offset = layoutData->used;
- QFontEngine *font = fontEngine(si, &si.ascent, &si.descent);
+ QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
if (font->type() != QFontEngine::Multi) {
shapeTextWithHarfbuzz(item);
return;
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 85c6928..a1d363b 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -345,11 +345,11 @@ struct Q_AUTOTEST_EXPORT QScriptItem
{
inline QScriptItem()
: position(0),
- num_glyphs(0), descent(-1), ascent(-1), width(-1),
+ num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
inline QScriptItem(int p, const QScriptAnalysis &a)
: position(p), analysis(a),
- num_glyphs(0), descent(-1), ascent(-1), width(-1),
+ num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
int position;
@@ -357,6 +357,7 @@ struct Q_AUTOTEST_EXPORT QScriptItem
unsigned short num_glyphs;
QFixed descent;
QFixed ascent;
+ QFixed leading;
QFixed width;
int glyph_data_offset;
QFixed height() const { return ascent + descent + 1; }
@@ -373,9 +374,10 @@ struct Q_AUTOTEST_EXPORT QScriptLine
QScriptLine()
: from(0), length(0),
justified(0), gridfitted(0),
- hasTrailingSpaces(0) {}
+ hasTrailingSpaces(0), leadingIncluded(0) {}
QFixed descent;
QFixed ascent;
+ QFixed leading;
QFixed x;
QFixed y;
QFixed width;
@@ -385,7 +387,11 @@ struct Q_AUTOTEST_EXPORT QScriptLine
mutable uint justified : 1;
mutable uint gridfitted : 1;
uint hasTrailingSpaces : 1;
- QFixed height() const { return ascent + descent + 1; }
+ uint leadingIncluded : 1;
+ QFixed height() const { return ascent + descent + 1
+ + (leadingIncluded? qMax(QFixed(),leading) : QFixed()); }
+ QFixed base() const { return ascent
+ + (leadingIncluded ? qMax(QFixed(),leading) : QFixed()); }
void setDefaultHeight(QTextEngine *eng);
void operator+=(const QScriptLine &other);
};
@@ -394,6 +400,7 @@ Q_DECLARE_TYPEINFO(QScriptLine, Q_PRIMITIVE_TYPE);
inline void QScriptLine::operator+=(const QScriptLine &other)
{
+ leading= qMax(leading + ascent, other.leading + other.ascent) - qMax(ascent, other.ascent);
descent = qMax(descent, other.descent);
ascent = qMax(ascent, other.ascent);
textWidth += other.textWidth;
@@ -476,7 +483,7 @@ public:
return end - si->position;
}
- QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0) const;
+ QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0, QFixed *leading = 0) const;
QFont font(const QScriptItem &si) const;
inline QFont font() const { return fnt; }
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index c5f0e35..4600a29 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -860,7 +860,7 @@ QRectF QTextLayout::boundingRect() const
ymin = qMin(ymin, si.y);
xmax = qMax(xmax, si.x+qMax(si.width, si.textWidth));
// ### shouldn't the ascent be used in ymin???
- ymax = qMax(ymax, si.y+si.ascent+si.descent+1);
+ ymax = qMax(ymax, si.y+si.height());
}
return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal());
}
@@ -1071,10 +1071,10 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo
QTextLineItemIterator iterator(eng, lineNumber, pos, selection);
- const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent;
+
+ const qreal selectionY = pos.y() + line.y.toReal();
const qreal lineHeight = line.height().toReal();
- const qreal selectionY = (y - line.ascent).toReal();
QFixed lastSelectionX = iterator.x;
QFixed lastSelectionWidth;
@@ -1334,23 +1334,23 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
const qreal x = position.x() + l.cursorToX(cursorPosition);
int itm = d->findItem(cursorPosition - 1);
- QFixed ascent = sl.ascent;
+ QFixed base = sl.base();
QFixed descent = sl.descent;
bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft);
if (itm >= 0) {
const QScriptItem &si = d->layoutData->items.at(itm);
if (si.ascent > 0)
- ascent = si.ascent;
+ base = si.ascent;
if (si.descent > 0)
descent = si.descent;
rightToLeft = si.analysis.bidiLevel % 2;
}
- qreal y = position.y() + (sl.y + sl.ascent - ascent).toReal();
+ qreal y = position.y() + (sl.y + sl.base() - base).toReal();
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
&& (p->transform().type() > QTransform::TxTranslate);
if (toggleAntialiasing)
p->setRenderHint(QPainter::Antialiasing);
- p->fillRect(QRectF(x, y, qreal(width), (ascent + descent).toReal()), p->pen().brush());
+ p->fillRect(QRectF(x, y, qreal(width), (base + descent + 1).toReal()), p->pen().brush());
if (toggleAntialiasing)
p->setRenderHint(QPainter::Antialiasing, false);
if (d->layoutData->hasBidi) {
@@ -1500,9 +1500,11 @@ qreal QTextLine::descent() const
}
/*!
- Returns the line's height. This is equal to ascent() + descent() + 1.
+ Returns the line's height. This is equal to ascent() + descent() + 1
+ if leading is not included. If leading is included, this equals to
+ ascent() + descent() + leading() + 1.
- \sa ascent() descent()
+ \sa ascent() descent() leading() setLeadingIncluded()
*/
qreal QTextLine::height() const
{
@@ -1510,6 +1512,51 @@ qreal QTextLine::height() const
}
/*!
+ \since 4.6
+
+ Returns the line's leading.
+
+ \sa ascent() descent() height()
+*/
+qreal QTextLine::leading() const
+{
+ return eng->lines[i].leading.toReal();
+}
+
+/*! \since 4.6
+
+ Includes positive leading into the line's height if \a included is true;
+ otherwise does not include leading.
+
+ By default, leading is not included.
+
+ Note that negative leading is ignored, it must be handled
+ in the code using the text lines by letting the lines overlap.
+
+ \sa leadingIncluded()
+
+*/
+void QTextLine::setLeadingIncluded(bool included)
+{
+ eng->lines[i].leadingIncluded= included;
+
+}
+
+/*! \since 4.6
+
+ Returns true if positive leading is included into the line's height; otherwise returns false.
+
+ By default, leading is not included.
+
+ \sa setLeadingIncluded()
+*/
+bool QTextLine::leadingIncluded() const
+{
+ return eng->lines[i].leadingIncluded;
+}
+
+
+/*!
Returns the width of the line that is occupied by text. This is
always \<= to width(), and is the minimum width that could be used
by layout() without changing the line break position.
@@ -1712,6 +1759,9 @@ void QTextLine::layout_helper(int maxGlyphs)
}
const QScriptItem &current = eng->layoutData->items[item];
+ lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
+ current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
+ current.ascent);
lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);
lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);
@@ -2042,7 +2092,9 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
QTextLineItemIterator iterator(eng, i, pos, selection);
- const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent;
+ QFixed lineBase = line.base();
+
+ const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;
bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);
while (!iterator.atEnd()) {
@@ -2065,7 +2117,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
if (selection)
format.merge(selection->format);
- setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - line.ascent).toReal(),
+ setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),
iterator.itemWidth.toReal(), line.height().toReal()));
QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();
@@ -2086,7 +2138,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
if (si.analysis.flags == QScriptAnalysis::Object && eng->block.docHandle()) {
QFixed itemY = y - si.ascent;
if (format.verticalAlignment() == QTextCharFormat::AlignTop) {
- itemY = y - line.ascent;
+ itemY = y - lineBase;
}
QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 90afac8..9f170f5 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -196,6 +196,10 @@ public:
qreal ascent() const;
qreal descent() const;
qreal height() const;
+ qreal leading() const;
+
+ void setLeadingIncluded(bool included);
+ bool leadingIncluded() const;
qreal naturalTextWidth() const;
QRectF naturalTextRect() const;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index b28ecd7..b7615a4 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -78,6 +78,7 @@ win32 {
unix:x11 {
HEADERS += \
text/qfontengine_x11_p.h \
+ text/qfontdatabase_x11.cpp \
text/qfontengine_ft_p.h
SOURCES += \
text/qfont_x11.cpp \
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 0e888d6..05e1e74 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -314,7 +314,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
// height
- sh.setHeight(qMax(fm.lineSpacing(), 14) + 2);
+ sh.setHeight(qMax(fm.height(), 14) + 2);
if (hasIcon) {
sh.setHeight(qMax(sh.height(), iconSize.height() + 2));
}
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index a574262f..6710275 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -456,7 +456,7 @@ int QDockWidgetLayout::titleHeight() const
int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q);
- return qMax(buttonHeight + 2, titleFontMetrics.lineSpacing() + 2*mw);
+ return qMax(buttonHeight + 2, titleFontMetrics.height() + 2*mw);
}
void QDockWidgetLayout::setGeometry(const QRect &geometry)
diff --git a/src/gui/widgets/qfontcombobox.cpp b/src/gui/widgets/qfontcombobox.cpp
index 7b39823..806db59 100644
--- a/src/gui/widgets/qfontcombobox.cpp
+++ b/src/gui/widgets/qfontcombobox.cpp
@@ -194,7 +194,7 @@ QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,
// font.setFamily(text);
font.setPointSize(QFontInfo(font).pointSize() * 3/2);
QFontMetrics fontMetrics(font);
- return QSize(fontMetrics.width(text), fontMetrics.lineSpacing());
+ return QSize(fontMetrics.width(text), fontMetrics.height());
}
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 629e839..e4252b5 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -624,7 +624,7 @@ QSize QLineEdit::sizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm(font());
- int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin
+ int h = qMax(fm.height(), 14) + 2*d->verticalMargin
+ d->topTextMargin + d->bottomTextMargin
+ d->topmargin + d->bottommargin;
int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 687e1bc..ea25901 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -180,6 +180,21 @@ int QMenuPrivate::scrollerHeight() const
}
//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
+QRect QMenuPrivate::popupGeometry(const QWidget *widget) const
+{
+#ifdef Q_WS_WIN
+ return QApplication::desktop()->screenGeometry(widget);
+#elif defined Q_WS_X11
+ if (X11->desktopEnvironment == DE_KDE)
+ return QApplication::desktop()->screenGeometry(widget);
+ else
+ return QApplication::desktop()->availableGeometry(widget);
+#else
+ return QApplication::desktop()->availableGeometry(widget);
+#endif
+}
+
+//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
QRect QMenuPrivate::popupGeometry(int screen) const
{
#ifdef Q_WS_WIN
@@ -234,7 +249,7 @@ void QMenuPrivate::updateActionRects() const
}
int max_column_width = 0,
- dh = popupGeometry(QApplication::desktop()->screenNumber(q)).height(),
+ dh = popupGeometry(q).height(),
y = 0;
QStyle *style = q->style();
QStyleOption opt;
@@ -744,7 +759,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
if (newScrollFlags & QMenuScroller::ScrollUp)
newOffset -= vmargin;
- QRect screen = popupGeometry(QApplication::desktop()->screenNumber(q));
+ QRect screen = popupGeometry(q);
const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q);
if (q->height() < screen.height()-(desktopFrame*2)-1) {
QRect geom = q->geometry();
@@ -960,10 +975,19 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
return false;
}
+class ExceptionGuard
+{
+public:
+ inline ExceptionGuard(bool *w = 0) : watched(w) { Q_ASSERT(!(*watched)); *watched = true; }
+ inline ~ExceptionGuard() { *watched = false; }
+ inline operator bool() { return *watched; }
+private:
+ bool *watched;
+};
+
void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self)
{
- Q_ASSERT(!activationRecursionGuard);
- activationRecursionGuard = true;
+ ExceptionGuard guard(&activationRecursionGuard);
#ifdef QT3_SUPPORT
const int actionId = q_func()->findIdForAction(action);
#endif
@@ -1008,7 +1032,6 @@ void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedSt
#endif
}
}
- activationRecursionGuard = false;
}
void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e, bool self)
@@ -1789,7 +1812,15 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
d->updateActionRects();
QPoint pos = p;
QSize size = sizeHint();
- QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
+ QRect screen;
+#ifndef QT_NO_GRAPHICSVIEW
+ bool isEmbedded = d->nearestGraphicsProxyWidget(this);
+ if (isEmbedded)
+ screen = d->popupGeometry(this);
+ else
+#endif
+ screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
+
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
#ifdef QT_KEYPAD_NAVIGATION
@@ -2927,7 +2958,7 @@ void QMenu::internalDelayedPopup()
QPoint pos(rightPos);
QMenu *caused = qobject_cast<QMenu*>(d->activeMenu->d_func()->causedPopup.widget);
- const QRect availGeometry(d->popupGeometry(QApplication::desktop()->screenNumber(caused)));
+ const QRect availGeometry(d->popupGeometry(caused));
if (isRightToLeft()) {
pos = leftPos;
if ((caused && caused->x() < x()) || pos.x() < availGeometry.left()) {
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index 9c4f260..9348f7b 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -192,11 +192,12 @@ public:
mutable QVector<QRect> actionRects;
mutable QWidgetList widgetItems;
void updateActionRects() const;
- QRect popupGeometry(int screen=-1) const;
+ QRect popupGeometry(const QWidget *widget) const;
+ QRect popupGeometry(int screen = -1) const;
mutable uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
- uint activationRecursionGuard : 1;
+ bool activationRecursionGuard;
//selection
static QPointer<QMenu> mouseDown;
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 22438bf..fc61889 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -357,10 +357,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
Q_D(QPlainTextDocumentLayout);
QTextDocument *doc = document();
qreal margin = doc->documentMargin();
- QFontMetrics fm(doc->defaultFont());
qreal blockMaximumWidth = 0;
- int leading = qMax(0, fm.leading());
qreal height = 0;
QTextLayout *tl = block.layout();
QTextOption option = doc->defaultTextOption();
@@ -381,9 +379,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
QTextLine line = tl->createLine();
if (!line.isValid())
break;
+ line.setLeadingIncluded(true);
line.setLineWidth(availableWidth);
-
- height += leading;
line.setPosition(QPointF(margin, height));
height += line.height();
blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp
index 1352e1b..eb34336 100644
--- a/src/gui/widgets/qpushbutton.cpp
+++ b/src/gui/widgets/qpushbutton.cpp
@@ -590,7 +590,7 @@ void QPushButtonPrivate::_q_popupPressed()
int x = globalPos.x();
int y = globalPos.y();
if (horizontal) {
- if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->height()) {
+ if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->availableGeometry(q).height()) {
y += rect.height();
} else {
y -= menuSize.height();
@@ -598,7 +598,7 @@ void QPushButtonPrivate::_q_popupPressed()
if (q->layoutDirection() == Qt::RightToLeft)
x += rect.width() - menuSize.width();
} else {
- if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->width())
+ if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->availableGeometry(q).width())
x += rect.width();
else
x -= menuSize.width();
diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp
index b894aa8..f477fee 100644
--- a/src/gui/widgets/qtextedit.cpp
+++ b/src/gui/widgets/qtextedit.cpp
@@ -2079,8 +2079,8 @@ void QTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
}
/*!