summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/qaccessible.h7
-rw-r--r--src/gui/accessible/qaccessible2.cpp12
-rw-r--r--src/gui/accessible/qaccessible2.h13
-rw-r--r--src/gui/effects/qgraphicseffect.cpp5
-rw-r--r--src/gui/effects/qgraphicseffect_p.h2
-rw-r--r--src/gui/graphicsview/qgraph_p.h16
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.cpp21
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp937
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h198
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp107
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h8
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h13
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp78
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h11
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp26
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp27
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h4
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp2
-rw-r--r--src/gui/graphicsview/qsimplex_p.h2
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_p.h9
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp43
-rw-r--r--src/gui/itemviews/qlistview.cpp10
-rw-r--r--src/gui/itemviews/qtreeview.cpp6
-rw-r--r--src/gui/itemviews/qtreeview_p.h2
-rw-r--r--src/gui/kernel/qaction.cpp2
-rw-r--r--src/gui/kernel/qapplication_p.h2
-rw-r--r--src/gui/kernel/qapplication_s60.cpp12
-rw-r--r--src/gui/kernel/qgesturemanager.cpp2
-rw-r--r--src/gui/kernel/qsoftkeymanager.cpp12
-rw-r--r--src/gui/kernel/qt_s60_p.h23
-rw-r--r--src/gui/kernel/qwidget.cpp2
-rw-r--r--src/gui/kernel/qwidget_s60.cpp4
-rw-r--r--src/gui/kernel/qwidget_win.cpp21
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp16
-rw-r--r--src/gui/styles/qs60style.cpp38
-rw-r--r--src/gui/styles/qs60style_p.h1
-rw-r--r--src/gui/styles/qs60style_s60.cpp14
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp68
-rw-r--r--src/gui/styles/qstylesheetstyle_default.cpp43
-rw-r--r--src/gui/styles/qwindowsmobilestyle.cpp21
-rw-r--r--src/gui/styles/qwindowsmobilestyle_p.h4
-rw-r--r--src/gui/styles/qwindowsstyle.cpp39
-rw-r--r--src/gui/styles/qwindowsstyle_p.h10
-rw-r--r--src/gui/text/qcssparser.cpp7
-rw-r--r--src/gui/text/qtextcontrol.cpp28
-rw-r--r--src/gui/text/qtextcontrol_p_p.h4
-rw-r--r--src/gui/widgets/qcombobox.cpp37
-rw-r--r--src/gui/widgets/qcombobox.h1
-rw-r--r--src/gui/widgets/qcombobox_p.h2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp23
-rw-r--r--src/gui/widgets/qmenu.cpp43
-rw-r--r--src/gui/widgets/qmenu_mac.mm2
-rw-r--r--src/gui/widgets/qmenu_p.h2
-rw-r--r--src/gui/widgets/qwidgetanimator.cpp7
-rw-r--r--src/gui/widgets/qwidgetanimator_p.h1
56 files changed, 1364 insertions, 687 deletions
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 8f6d9d9..c493054 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -311,7 +311,8 @@ namespace QAccessible2
EditableTextInterface,
ValueInterface,
TableInterface,
- ActionInterface
+ ActionInterface,
+ ImageInterface
};
}
@@ -321,6 +322,7 @@ class QAccessibleEditableTextInterface;
class QAccessibleValueInterface;
class QAccessibleTableInterface;
class QAccessibleActionInterface;
+class QAccessibleImageInterface;
class Q_GUI_EXPORT QAccessibleInterface : public QAccessible
{
@@ -381,6 +383,9 @@ public:
inline QAccessibleActionInterface *actionInterface()
{ return reinterpret_cast<QAccessibleActionInterface *>(cast_helper(QAccessible2::ActionInterface)); }
+ inline QAccessibleImageInterface *imageInterface()
+ { return reinterpret_cast<QAccessibleImageInterface *>(cast_helper(QAccessible2::ImageInterface)); }
+
private:
QAccessible2Interface *cast_helper(QAccessible2::InterfaceType);
};
diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp
index 0867368..b878cf1 100644
--- a/src/gui/accessible/qaccessible2.cpp
+++ b/src/gui/accessible/qaccessible2.cpp
@@ -120,6 +120,18 @@ QT_BEGIN_NAMESPACE
\link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
*/
+/*!
+ \class QAccessibleImageInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleImageInterface class implements support for
+ the IAccessibleImage interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
QAccessibleSimpleEditableTextInterface::QAccessibleSimpleEditableTextInterface(
QAccessibleInterface *accessibleInterface)
: iface(accessibleInterface)
diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h
index 435c640..ba12a7c 100644
--- a/src/gui/accessible/qaccessible2.h
+++ b/src/gui/accessible/qaccessible2.h
@@ -82,6 +82,7 @@ inline QAccessible2Interface *qAccessibleTextCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleTableCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; }
#define Q_ACCESSIBLE_OBJECT \
public: \
@@ -98,6 +99,8 @@ inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; }
return qAccessibleTableCastHelper(); \
case QAccessible2::ActionInterface: \
return qAccessibleActionCastHelper(); \
+ case QAccessible2::ImageInterface: \
+ return qAccessibleImageCastHelper(); \
} \
return 0; \
} \
@@ -224,6 +227,16 @@ public:
virtual QStringList keyBindings(int actionIndex) = 0;
};
+class Q_GUI_EXPORT QAccessibleImageInterface : public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleImageCastHelper() { return this; }
+
+ virtual QString imageDescription() = 0;
+ virtual QSize imageSize() = 0;
+ virtual QRect imagePosition(QAccessible2::CoordinateType coordType) = 0;
+};
+
#endif // QT_NO_ACCESSIBILITY
QT_END_NAMESPACE
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index 7f83063..568ff73 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -320,6 +320,11 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse
return pm;
}
+QGraphicsEffectSourcePrivate::~QGraphicsEffectSourcePrivate()
+{
+ invalidateCache();
+}
+
void QGraphicsEffectSourcePrivate::invalidateCache(bool effectRectChanged) const
{
if (effectRectChanged && m_cachedMode != QGraphicsEffectSource::ExpandToEffectRectPadMode)
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
index 9a46a24..d94d08d 100644
--- a/src/gui/effects/qgraphicseffect_p.h
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -73,7 +73,7 @@ public:
, m_cachedMode(QGraphicsEffectSource::ExpandToTransparentBorderPadMode)
{}
- virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); }
+ virtual ~QGraphicsEffectSourcePrivate();
virtual void detach() = 0;
virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0;
virtual QRect deviceRect() const = 0;
diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h
index f1fa185..0a2bf27 100644
--- a/src/gui/graphicsview/qgraph_p.h
+++ b/src/gui/graphicsview/qgraph_p.h
@@ -201,11 +201,6 @@ public:
return l;
}
- void setRootVertex(Vertex *vertex)
- {
- userVertex = vertex;
- }
-
QSet<Vertex*> vertices() const {
QSet<Vertex *> setOfVertices;
for (const_iterator it = constBegin(); it != constEnd(); ++it) {
@@ -241,7 +236,7 @@ public:
EdgeData *data = edgeData(v, v1);
bool forward = data->from == v;
if (forward) {
- edges += QString::fromAscii("%1->%2 [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n")
+ edges += QString::fromAscii("\"%1\"->\"%2\" [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n")
.arg(v->toString())
.arg(v1->toString())
.arg(data->minSize)
@@ -250,17 +245,12 @@ public:
;
}
}
- strVertices += QString::fromAscii("%1 [label=\"%2\"]\n").arg(v->toString()).arg(v->toString());
+ strVertices += QString::fromAscii("\"%1\" [label=\"%2\"]\n").arg(v->toString()).arg(v->toString());
}
return QString::fromAscii("%1\n%2\n").arg(strVertices).arg(edges);
}
#endif
- Vertex *rootVertex() const
- {
- return userVertex;
- }
-
protected:
void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data)
{
@@ -286,8 +276,6 @@ protected:
}
private:
- Vertex *userVertex;
-
QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph;
};
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
index 56d70e1..872ec3c 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
@@ -83,10 +83,8 @@
\clearfloat
\section1 Size Hints and Size Policies in an Anchor Layout
- QGraphicsAnchorLayout respects each item's size hints and size policies. However it does
- not currently respect their stretch factors. This might change in the future, so avoid
- using stretch factors in anchor layouts if you want to avoid any future regressions in
- behavior.
+ QGraphicsAnchorLayout respects each item's size hints and size policies.
+ Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}.
\section1 Spacing within an Anchor Layout
@@ -101,6 +99,21 @@
If the spacing is negative, the items will overlap to some extent.
+
+ \section1 Known issues
+ There are some features that QGraphicsAnchorLayout currently does not support.
+ This might change in the future, so avoid using these features if you want to
+ avoid any future regressions in behaviour:
+ \list
+
+ \o Stretch factors are not respected.
+
+ \o QSizePolicy::ExpandFlag is not respected.
+
+ \o Height for width is not respected.
+
+ \endlist
+
\sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout
*/
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index 41aa8aa..182594e 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -61,6 +61,8 @@ QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version)
QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate()
{
+ // ###
+ layoutPrivate->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Orientation(data->orientation));
layoutPrivate->removeAnchor(data->from, data->to);
}
@@ -105,7 +107,7 @@ qreal QGraphicsAnchorPrivate::spacing() const
static void internalSizeHints(QSizePolicy::Policy policy,
qreal minSizeHint, qreal prefSizeHint, qreal maxSizeHint,
qreal *minSize, qreal *prefSize,
- qreal *expSize, qreal *maxSize)
+ qreal *maxSize)
{
// minSize, prefSize and maxSize are initialized
// with item's preferred Size: this is QSizePolicy::Fixed.
@@ -135,11 +137,6 @@ static void internalSizeHints(QSizePolicy::Policy policy,
*prefSize = *minSize;
else
*prefSize = prefSizeHint;
-
- if (policy & QSizePolicy::ExpandFlag)
- *expSize = *maxSize;
- else
- *expSize = *prefSize;
}
bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
@@ -154,7 +151,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
if (isLayoutAnchor) {
minSize = 0;
prefSize = 0;
- expSize = 0;
maxSize = QWIDGETSIZE_MAX;
if (isCenterAnchor)
maxSize /= 2;
@@ -205,8 +201,8 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
}
maxSizeHint = QWIDGETSIZE_MAX;
}
- internalSizeHints(policy, minSizeHint, prefSizeHint, maxSizeHint,
- &minSize, &prefSize, &expSize, &maxSize);
+ internalSizeHints(policy, minSizeHint, prefSizeHint, maxSizeHint,
+ &minSize, &prefSize, &maxSize);
// Set the anchor effective sizes to preferred.
//
@@ -217,7 +213,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
// recalculate and override the values we set here.
sizeAtMinimum = prefSize;
sizeAtPreferred = prefSize;
- sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
return true;
@@ -225,10 +220,20 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
void ParallelAnchorData::updateChildrenSizes()
{
- firstEdge->sizeAtMinimum = secondEdge->sizeAtMinimum = sizeAtMinimum;
- firstEdge->sizeAtPreferred = secondEdge->sizeAtPreferred = sizeAtPreferred;
- firstEdge->sizeAtExpanding = secondEdge->sizeAtExpanding = sizeAtExpanding;
- firstEdge->sizeAtMaximum = secondEdge->sizeAtMaximum = sizeAtMaximum;
+ firstEdge->sizeAtMinimum = sizeAtMinimum;
+ firstEdge->sizeAtPreferred = sizeAtPreferred;
+ firstEdge->sizeAtMaximum = sizeAtMaximum;
+
+ const bool secondFwd = (secondEdge->from == from);
+ if (secondFwd) {
+ secondEdge->sizeAtMinimum = sizeAtMinimum;
+ secondEdge->sizeAtPreferred = sizeAtPreferred;
+ secondEdge->sizeAtMaximum = sizeAtMaximum;
+ } else {
+ secondEdge->sizeAtMinimum = -sizeAtMinimum;
+ secondEdge->sizeAtPreferred = -sizeAtPreferred;
+ secondEdge->sizeAtMaximum = -sizeAtMaximum;
+ }
firstEdge->updateChildrenSizes();
secondEdge->updateChildrenSizes();
@@ -247,8 +252,16 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn
return false;
}
- minSize = qMax(firstEdge->minSize, secondEdge->minSize);
- maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize);
+ // Account for parallel anchors where the second edge is backwards.
+ // We rely on the fact that a forward anchor of sizes min, pref, max is equivalent
+ // to a backwards anchor of size (-max, -pref, -min)
+ const bool secondFwd = (secondEdge->from == from);
+ const qreal secondMin = secondFwd ? secondEdge->minSize : -secondEdge->maxSize;
+ const qreal secondPref = secondFwd ? secondEdge->prefSize : -secondEdge->prefSize;
+ const qreal secondMax = secondFwd ? secondEdge->maxSize : -secondEdge->minSize;
+
+ minSize = qMax(firstEdge->minSize, secondMin);
+ maxSize = qMin(firstEdge->maxSize, secondMax);
// This condition means that the maximum size of one anchor being simplified is smaller than
// the minimum size of the other anchor. The consequence is that there won't be a valid size
@@ -257,16 +270,27 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn
return false;
}
- expSize = qMax(firstEdge->expSize, secondEdge->expSize);
- expSize = qMin(expSize, maxSize);
+ // The equivalent preferred Size of a parallel anchor is calculated as to
+ // reduce the deviation from the original preferred sizes _and_ to avoid shrinking
+ // items below their preferred sizes, unless strictly needed.
- prefSize = qMax(firstEdge->prefSize, secondEdge->prefSize);
- prefSize = qMin(prefSize, expSize);
+ // ### This logic only holds if all anchors in the layout are "well-behaved" in the
+ // following terms:
+ //
+ // - There are no negative-sized anchors
+ // - All sequential anchors are composed of children in the same direction as the
+ // sequential anchor itself
+ //
+ // With these assumptions we can grow a child knowing that no hidden items will
+ // have to shrink as the result of that.
+ // If any of these does not hold, we have a situation where the ParallelAnchor
+ // does not have enough information to calculate its equivalent prefSize.
+ prefSize = qMax(firstEdge->prefSize, secondPref);
+ prefSize = qMin(prefSize, maxSize);
// See comment in AnchorData::refreshSizeHints() about sizeAt* values
sizeAtMinimum = prefSize;
sizeAtPreferred = prefSize;
- sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
return true;
@@ -280,8 +304,7 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn
1 is at Maximum
*/
static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal value, qreal min,
- qreal pref, qreal exp,
- qreal max)
+ qreal pref, qreal max)
{
QGraphicsAnchorLayoutPrivate::Interval interval;
qreal lower;
@@ -291,13 +314,9 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu
interval = QGraphicsAnchorLayoutPrivate::MinToPreferred;
lower = min;
upper = pref;
- } else if (value < exp) {
- interval = QGraphicsAnchorLayoutPrivate::PreferredToExpanding;
- lower = pref;
- upper = exp;
} else {
- interval = QGraphicsAnchorLayoutPrivate::ExpandingToMax;
- lower = exp;
+ interval = QGraphicsAnchorLayoutPrivate::PreferredToMax;
+ lower = pref;
upper = max;
}
@@ -313,7 +332,7 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu
static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor,
qreal min, qreal pref,
- qreal exp, qreal max)
+ qreal max)
{
qreal lower;
qreal upper;
@@ -323,12 +342,8 @@ static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qre
lower = min;
upper = pref;
break;
- case QGraphicsAnchorLayoutPrivate::PreferredToExpanding:
+ case QGraphicsAnchorLayoutPrivate::PreferredToMax:
lower = pref;
- upper = exp;
- break;
- case QGraphicsAnchorLayoutPrivate::ExpandingToMax:
- lower = exp;
upper = max;
break;
}
@@ -341,34 +356,31 @@ void SequentialAnchorData::updateChildrenSizes()
// ### REMOVE ME
// ### check whether we are guarantee to get those or we need to warn stuff at this
// point.
- Q_ASSERT(sizeAtMinimum > minSize || qFuzzyCompare(sizeAtMinimum, minSize));
- Q_ASSERT(sizeAtMinimum < maxSize || qFuzzyCompare(sizeAtMinimum, maxSize));
- Q_ASSERT(sizeAtPreferred > minSize || qFuzzyCompare(sizeAtPreferred, minSize));
- Q_ASSERT(sizeAtPreferred < maxSize || qFuzzyCompare(sizeAtPreferred, maxSize));
- Q_ASSERT(sizeAtExpanding > minSize || qFuzzyCompare(sizeAtExpanding, minSize));
- Q_ASSERT(sizeAtExpanding < maxSize || qFuzzyCompare(sizeAtExpanding, maxSize));
- Q_ASSERT(sizeAtMaximum > minSize || qFuzzyCompare(sizeAtMaximum, minSize));
- Q_ASSERT(sizeAtMaximum < maxSize || qFuzzyCompare(sizeAtMaximum, maxSize));
+ Q_ASSERT(sizeAtMinimum > minSize || qAbs(sizeAtMinimum - minSize) < 0.00000001);
+ Q_ASSERT(sizeAtPreferred > minSize || qAbs(sizeAtPreferred - minSize) < 0.00000001);
+ Q_ASSERT(sizeAtMaximum > minSize || qAbs(sizeAtMaximum - minSize) < 0.00000001);
+
+ // These may be false if this anchor was in parallel with the layout stucture
+ // Q_ASSERT(sizeAtMinimum < maxSize || qAbs(sizeAtMinimum - maxSize) < 0.00000001);
+ // Q_ASSERT(sizeAtPreferred < maxSize || qAbs(sizeAtPreferred - maxSize) < 0.00000001);
+ // Q_ASSERT(sizeAtMaximum < maxSize || qAbs(sizeAtMaximum - maxSize) < 0.00000001);
// Band here refers if the value is in the Minimum To Preferred
// band (the lower band) or the Preferred To Maximum (the upper band).
const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> minFactor =
- getFactor(sizeAtMinimum, minSize, prefSize, expSize, maxSize);
+ getFactor(sizeAtMinimum, minSize, prefSize, maxSize);
const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> prefFactor =
- getFactor(sizeAtPreferred, minSize, prefSize, expSize, maxSize);
- const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> expFactor =
- getFactor(sizeAtExpanding, minSize, prefSize, expSize, maxSize);
+ getFactor(sizeAtPreferred, minSize, prefSize, maxSize);
const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> maxFactor =
- getFactor(sizeAtMaximum, minSize, prefSize, expSize, maxSize);
+ getFactor(sizeAtMaximum, minSize, prefSize, maxSize);
for (int i = 0; i < m_edges.count(); ++i) {
AnchorData *e = m_edges.at(i);
- e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->prefSize, e->expSize, e->maxSize);
- e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->prefSize, e->expSize, e->maxSize);
- e->sizeAtExpanding = interpolate(expFactor, e->minSize, e->prefSize, e->expSize, e->maxSize);
- e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->prefSize, e->expSize, e->maxSize);
+ e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->prefSize, e->maxSize);
+ e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->prefSize, e->maxSize);
+ e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->prefSize, e->maxSize);
e->updateChildrenSizes();
}
@@ -384,7 +396,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style
{
minSize = 0;
prefSize = 0;
- expSize = 0;
maxSize = 0;
for (int i = 0; i < m_edges.count(); ++i) {
@@ -396,14 +407,12 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style
minSize += edge->minSize;
prefSize += edge->prefSize;
- expSize += edge->expSize;
maxSize += edge->maxSize;
}
// See comment in AnchorData::refreshSizeHints() about sizeAt* values
sizeAtMinimum = prefSize;
sizeAtPreferred = prefSize;
- sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
return true;
@@ -478,12 +487,15 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate()
for (int j = 0; j < 3; ++j) {
sizeHints[i][j] = -1;
}
- sizeAtExpanding[i] = -1;
interpolationProgress[i] = -1;
spacings[i] = -1;
graphSimplified[i] = false;
graphHasConflicts[i] = false;
+
+ layoutFirstVertex[i] = 0;
+ layoutCentralVertex[i] = 0;
+ layoutLastVertex[i] = 0;
}
}
@@ -526,33 +538,67 @@ inline static qreal checkAdd(qreal a, qreal b)
/*!
\internal
- Adds \a newAnchor to the graph \a g.
+ Adds \a newAnchor to the graph.
Returns the newAnchor itself if it could be added without further changes to the graph. If a
- new parallel anchor had to be created, then returns the new parallel anchor. In case the
- addition is unfeasible -- because a parallel setup is not possible, returns 0.
+ new parallel anchor had to be created, then returns the new parallel anchor. If a parallel anchor
+ had to be created and it results in an unfeasible setup, \a feasible is set to false, otherwise
+ true.
+
+ Note that in the case a new parallel anchor is created, it might also take over some constraints
+ from its children anchors.
*/
-static AnchorData *addAnchorMaybeParallel(Graph<AnchorVertex, AnchorData> *g,
- AnchorData *newAnchor)
+AnchorData *QGraphicsAnchorLayoutPrivate::addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible)
{
- bool feasible = true;
+ Orientation orientation = Orientation(newAnchor->orientation);
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+ *feasible = true;
// If already exists one anchor where newAnchor is supposed to be, we create a parallel
// anchor.
- if (AnchorData *oldAnchor = g->takeEdge(newAnchor->from, newAnchor->to)) {
+ if (AnchorData *oldAnchor = g.takeEdge(newAnchor->from, newAnchor->to)) {
ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, newAnchor);
+ // The parallel anchor will "replace" its children anchors in
+ // every center constraint that they appear.
+
+ // ### If the dependent (center) anchors had reference(s) to their constraints, we
+ // could avoid traversing all the itemCenterConstraints.
+ QList<QSimplexConstraint *> &constraints = itemCenterConstraints[orientation];
+
+ AnchorData *children[2] = { oldAnchor, newAnchor };
+ QList<QSimplexConstraint *> *childrenConstraints[2] = { &parallel->m_firstConstraints,
+ &parallel->m_secondConstraints };
+
+ for (int i = 0; i < 2; ++i) {
+ AnchorData *child = children[i];
+ QList<QSimplexConstraint *> *childConstraints = childrenConstraints[i];
+
+ if (!child->isCenterAnchor)
+ continue;
+
+ parallel->isCenterAnchor = true;
+
+ for (int i = 0; i < constraints.count(); ++i) {
+ QSimplexConstraint *c = constraints[i];
+ if (c->variables.contains(child)) {
+ childConstraints->append(c);
+ qreal v = c->variables.take(child);
+ c->variables.insert(parallel, v);
+ }
+ }
+ }
+
// At this point we can identify that the parallel anchor is not feasible, e.g. one
// anchor minimum size is bigger than the other anchor maximum size.
- feasible = parallel->refreshSizeHints_helper(0, false);
+ *feasible = parallel->refreshSizeHints_helper(0, false);
newAnchor = parallel;
}
- g->createEdge(newAnchor->from, newAnchor->to, newAnchor);
- return feasible ? newAnchor : 0;
+ g.createEdge(newAnchor->from, newAnchor->to, newAnchor);
+ return newAnchor;
}
-
/*!
\internal
@@ -656,30 +702,185 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
if (graphSimplified[orientation])
return true;
- graphSimplified[orientation] = true;
#if 0
qDebug("Simplifying Graph for %s",
orientation == Horizontal ? "Horizontal" : "Vertical");
#endif
- if (!graph[orientation].rootVertex())
- return true;
+ // Vertex simplification
+ if (!simplifyVertices(orientation)) {
+ restoreVertices(orientation);
+ return false;
+ }
+ // Anchor simplification
bool dirty;
bool feasible = true;
do {
dirty = simplifyGraphIteration(orientation, &feasible);
} while (dirty && feasible);
- if (!feasible)
- graphSimplified[orientation] = false;
+ // Note that if we are not feasible, we fallback and make sure that the graph is fully restored
+ if (!feasible) {
+ graphSimplified[orientation] = true;
+ restoreSimplifiedGraph(orientation);
+ restoreVertices(orientation);
+ return false;
+ }
+
+ graphSimplified[orientation] = true;
+ return true;
+}
+
+static AnchorVertex *replaceVertex_helper(AnchorData *data, AnchorVertex *oldV, AnchorVertex *newV)
+{
+ AnchorVertex *other;
+ if (data->from == oldV) {
+ data->from = newV;
+ other = data->to;
+ } else {
+ data->to = newV;
+ other = data->from;
+ }
+ return other;
+}
+
+bool QGraphicsAnchorLayoutPrivate::replaceVertex(Orientation orientation, AnchorVertex *oldV,
+ AnchorVertex *newV, const QList<AnchorData *> &edges)
+{
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+ bool feasible = true;
+
+ for (int i = 0; i < edges.count(); ++i) {
+ AnchorData *ad = edges[i];
+ AnchorVertex *otherV = replaceVertex_helper(ad, oldV, newV);
+
+#if defined(QT_DEBUG)
+ ad->name = QString::fromAscii("%1 --to--> %2").arg(ad->from->toString()).arg(ad->to->toString());
+#endif
+
+ bool newFeasible;
+ AnchorData *newAnchor = addAnchorMaybeParallel(ad, &newFeasible);
+ feasible &= newFeasible;
+
+ if (newAnchor != ad) {
+ // A parallel was created, we mark that in the list of anchors created by vertex
+ // simplification. This is needed because we want to restore them in a separate step
+ // from the restoration of anchor simplification.
+ anchorsFromSimplifiedVertices[orientation].append(newAnchor);
+ }
+
+ g.takeEdge(oldV, otherV);
+ }
return feasible;
}
/*!
\internal
+*/
+bool QGraphicsAnchorLayoutPrivate::simplifyVertices(Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+
+ // We'll walk through vertices
+ QStack<AnchorVertex *> stack;
+ stack.push(layoutFirstVertex[orientation]);
+ QSet<AnchorVertex *> visited;
+
+ while (!stack.isEmpty()) {
+ AnchorVertex *v = stack.pop();
+ visited.insert(v);
+
+ // Each adjacent of 'v' is a possible vertex to be merged. So we traverse all of
+ // them. Since once a merge is made, we might add new adjacents, and we don't want to
+ // pass two times through one adjacent. The 'index' is used to track our position.
+ QList<AnchorVertex *> adjacents = g.adjacentVertices(v);
+ int index = 0;
+
+ while (index < adjacents.count()) {
+ AnchorVertex *next = adjacents.at(index);
+ index++;
+
+ AnchorData *data = g.edgeData(v, next);
+ const bool bothLayoutVertices = v->m_item == q && next->m_item == q;
+ const bool zeroSized = !data->minSize && !data->maxSize;
+
+ if (!bothLayoutVertices && zeroSized) {
+
+ // Create a new vertex pair, note that we keep a list of those vertices so we can
+ // easily process them when restoring the graph.
+ AnchorVertexPair *newV = new AnchorVertexPair(v, next, data);
+ simplifiedVertices[orientation].append(newV);
+
+ // Collect the anchors of both vertices, the new vertex pair will take their place
+ // in those anchors
+ const QList<AnchorVertex *> &vAdjacents = g.adjacentVertices(v);
+ const QList<AnchorVertex *> &nextAdjacents = g.adjacentVertices(next);
+
+ for (int i = 0; i < vAdjacents.count(); ++i) {
+ AnchorVertex *adjacent = vAdjacents.at(i);
+ if (adjacent != next) {
+ AnchorData *ad = g.edgeData(v, adjacent);
+ newV->m_firstAnchors.append(ad);
+ }
+ }
+
+ for (int i = 0; i < nextAdjacents.count(); ++i) {
+ AnchorVertex *adjacent = nextAdjacents.at(i);
+ if (adjacent != v) {
+ AnchorData *ad = g.edgeData(next, adjacent);
+ newV->m_secondAnchors.append(ad);
+
+ // We'll also add new vertices to the adjacent list of the new 'v', to be
+ // created as a vertex pair and replace the current one.
+ if (!adjacents.contains(adjacent))
+ adjacents.append(adjacent);
+ }
+ }
+
+ // ### merge this loop into the ones that calculated m_firstAnchors/m_secondAnchors?
+ // Make newV take the place of v and next
+ bool feasible = replaceVertex(orientation, v, newV, newV->m_firstAnchors);
+ feasible &= replaceVertex(orientation, next, newV, newV->m_secondAnchors);
+
+ // Update the layout vertex information if one of the vertices is a layout vertex.
+ AnchorVertex *layoutVertex = 0;
+ if (v->m_item == q)
+ layoutVertex = v;
+ else if (next->m_item == q)
+ layoutVertex = next;
+
+ if (layoutVertex) {
+ // Layout vertices always have m_item == q...
+ newV->m_item = q;
+ changeLayoutVertex(orientation, layoutVertex, newV);
+ }
+
+ g.takeEdge(v, next);
+
+ // If a non-feasibility is found, we leave early and cancel the simplification
+ if (!feasible)
+ return false;
+
+ v = newV;
+ visited.insert(newV);
+
+ } else if (!visited.contains(next) && !stack.contains(next)) {
+ // If the adjacent is not fit for merge and it wasn't visited by the outermost
+ // loop, we add it to the stack.
+ stack.push(next);
+ }
+ }
+ }
+
+ return true;
+}
+
+/*!
+ \internal
One iteration of the simplification algorithm. Returns true if another iteration is needed.
@@ -700,7 +901,7 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
QSet<AnchorVertex *> visited;
QStack<QPair<AnchorVertex *, AnchorVertex *> > stack;
- stack.push(qMakePair(static_cast<AnchorVertex *>(0), g.rootVertex()));
+ stack.push(qMakePair(static_cast<AnchorVertex *>(0), layoutFirstVertex[orientation]));
QVector<AnchorVertex*> candidates;
bool candidatesForward;
@@ -719,7 +920,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
// (a) it is a layout vertex, we don't simplify away the layout vertices;
// (b) it does not have exactly 2 adjacents;
// (c) it will change the direction of the sequence;
- // (d) its next adjacent is already visited (a cycle in the graph).
+ // (d) its next adjacent is already visited (a cycle in the graph);
+ // (e) the next anchor is a center anchor.
const QList<AnchorVertex *> &adjacents = g.adjacentVertices(v);
const bool isLayoutVertex = v->m_item == q;
@@ -742,13 +944,14 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
candidatesForward = (beforeSequence == data->from);
}
- // This is a tricky part. We peek at the next vertex to find out
+ // This is a tricky part. We peek at the next vertex to find out whether
//
- // - whether the edge from this vertex to the next vertex has the same direction;
- // - whether we already visited the next vertex.
+ // - the edge from this vertex to the next vertex has the same direction;
+ // - we already visited the next vertex;
+ // - the next anchor is a center.
//
- // Those are needed to identify (c) and (d). Note that unlike (a) and (b), we preempt
- // the end of sequence by looking into the next vertex.
+ // Those are needed to identify the remaining end of sequence cases. Note that unlike
+ // (a) and (b), we preempt the end of sequence by looking into the next vertex.
// Peek at the next vertex
AnchorVertex *after;
@@ -766,8 +969,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
const bool willChangeDirection = (candidatesForward != (v == data->from));
const bool cycleFound = visited.contains(after);
- // Now cases (c) and (d)...
- endOfSequence = willChangeDirection || cycleFound;
+ // Now cases (c), (d) and (e)...
+ endOfSequence = willChangeDirection || cycleFound || data->isCenterAnchor;
if (endOfSequence) {
if (!willChangeDirection) {
@@ -839,9 +1042,10 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
// If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll
// create a parallel anchor between the new sequence and the old anchor.
- AnchorData *newAnchor = addAnchorMaybeParallel(&g, sequence);
+ bool newFeasible;
+ AnchorData *newAnchor = addAnchorMaybeParallel(sequence, &newFeasible);
- if (!newAnchor) {
+ if (!newFeasible) {
*feasible = false;
return false;
}
@@ -861,48 +1065,70 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
return false;
}
-static void restoreSimplifiedAnchor(Graph<AnchorVertex, AnchorData> &g,
- AnchorData *edge,
- AnchorVertex *before,
- AnchorVertex *after)
+void QGraphicsAnchorLayoutPrivate::restoreSimplifiedAnchor(AnchorData *edge)
{
- Q_ASSERT(edge->type != AnchorData::Normal);
#if 0
static const char *anchortypes[] = {"Normal",
"Sequential",
"Parallel"};
qDebug("Restoring %s edge.", anchortypes[int(edge->type)]);
#endif
- if (edge->type == AnchorData::Sequential) {
- SequentialAnchorData* seqEdge = static_cast<SequentialAnchorData*>(edge);
- // restore the sequential anchor
- AnchorVertex *prev = before;
- AnchorVertex *last = after;
- if (edge->from != prev)
- qSwap(last, prev);
-
- for (int i = 0; i < seqEdge->m_edges.count(); ++i) {
- AnchorVertex *v1 = (i < seqEdge->m_children.count()) ? seqEdge->m_children.at(i) : last;
- AnchorData *data = seqEdge->m_edges.at(i);
- if (data->type != AnchorData::Normal) {
- restoreSimplifiedAnchor(g, data, prev, v1);
- } else {
- g.createEdge(prev, v1, data);
- }
- prev = v1;
+
+ Graph<AnchorVertex, AnchorData> &g = graph[edge->orientation];
+
+ if (edge->type == AnchorData::Normal) {
+ g.createEdge(edge->from, edge->to, edge);
+
+ } else if (edge->type == AnchorData::Sequential) {
+ SequentialAnchorData *sequence = static_cast<SequentialAnchorData *>(edge);
+
+ for (int i = 0; i < sequence->m_edges.count(); ++i) {
+ AnchorData *data = sequence->m_edges.at(i);
+ restoreSimplifiedAnchor(data);
}
+
+ delete sequence;
+
} else if (edge->type == AnchorData::Parallel) {
- ParallelAnchorData* parallelEdge = static_cast<ParallelAnchorData*>(edge);
- AnchorData *parallelEdges[2] = {parallelEdge->firstEdge,
- parallelEdge->secondEdge};
- for (int i = 0; i < 2; ++i) {
- AnchorData *data = parallelEdges[i];
- if (data->type == AnchorData::Normal) {
- g.createEdge(before, after, data);
- } else {
- restoreSimplifiedAnchor(g, data, before, after);
- }
- }
+
+ // Skip parallel anchors that were created by vertex simplification, they will be processed
+ // later, when restoring vertex simplification.
+ // ### we could improve this check bit having a bit inside 'edge'
+ if (anchorsFromSimplifiedVertices[edge->orientation].contains(edge))
+ return;
+
+ ParallelAnchorData* parallel = static_cast<ParallelAnchorData*>(edge);
+ restoreSimplifiedConstraints(parallel);
+
+ // ### Because of the way parallel anchors are created in the anchor simplification
+ // algorithm, we know that one of these will be a sequence, so it'll be safe if the other
+ // anchor create an edge between the same vertices as the parallel.
+ Q_ASSERT(parallel->firstEdge->type == AnchorData::Sequential
+ || parallel->secondEdge->type == AnchorData::Sequential);
+ restoreSimplifiedAnchor(parallel->firstEdge);
+ restoreSimplifiedAnchor(parallel->secondEdge);
+
+ delete parallel;
+ }
+}
+
+void QGraphicsAnchorLayoutPrivate::restoreSimplifiedConstraints(ParallelAnchorData *parallel)
+{
+ if (!parallel->isCenterAnchor)
+ return;
+
+ for (int i = 0; i < parallel->m_firstConstraints.count(); ++i) {
+ QSimplexConstraint *c = parallel->m_firstConstraints.at(i);
+ qreal v = c->variables[parallel];
+ c->variables.remove(parallel);
+ c->variables.insert(parallel->firstEdge, v);
+ }
+
+ for (int i = 0; i < parallel->m_secondConstraints.count(); ++i) {
+ QSimplexConstraint *c = parallel->m_secondConstraints.at(i);
+ qreal v = c->variables[parallel];
+ c->variables.remove(parallel);
+ c->variables.insert(parallel->secondEdge, v);
}
}
@@ -917,19 +1143,93 @@ void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientatio
orientation == Horizontal ? "Horizontal" : "Vertical");
#endif
+ // Restore anchor simplification
Graph<AnchorVertex, AnchorData> &g = graph[orientation];
-
QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections();
for (int i = 0; i < connections.count(); ++i) {
AnchorVertex *v1 = connections.at(i).first;
AnchorVertex *v2 = connections.at(i).second;
AnchorData *edge = g.edgeData(v1, v2);
- if (edge->type != AnchorData::Normal) {
- AnchorData *oldEdge = g.takeEdge(v1, v2);
- restoreSimplifiedAnchor(g, edge, v1, v2);
- delete oldEdge;
+
+ // We restore only sequential anchors and parallels that were not created by
+ // vertex simplification.
+ if (edge->type == AnchorData::Sequential
+ || (edge->type == AnchorData::Parallel &&
+ !anchorsFromSimplifiedVertices[orientation].contains(edge))) {
+
+ g.takeEdge(v1, v2);
+ restoreSimplifiedAnchor(edge);
}
}
+
+ restoreVertices(orientation);
+}
+
+void QGraphicsAnchorLayoutPrivate::restoreVertices(Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+ QList<AnchorVertexPair *> &toRestore = simplifiedVertices[orientation];
+
+ // We will restore the vertices in the inverse order of creation, this way we ensure that
+ // the vertex being restored was not wrapped by another simplification.
+ for (int i = toRestore.count() - 1; i >= 0; --i) {
+ AnchorVertexPair *pair = toRestore.at(i);
+ QList<AnchorVertex *> adjacents = g.adjacentVertices(pair);
+
+ // Restore the removed edge, this will also restore both vertices 'first' and 'second' to
+ // the graph structure.
+ AnchorVertex *first = pair->m_first;
+ AnchorVertex *second = pair->m_second;
+ g.createEdge(first, second, pair->m_removedAnchor);
+
+ // Restore the anchors for the first child vertex
+ for (int j = 0; j < pair->m_firstAnchors.count(); ++j) {
+ AnchorData *ad = pair->m_firstAnchors.at(j);
+ Q_ASSERT(ad->from == pair || ad->to == pair);
+
+ replaceVertex_helper(ad, pair, first);
+ g.createEdge(ad->from, ad->to, ad);
+ }
+
+ // Restore the anchors for the second child vertex
+ for (int j = 0; j < pair->m_secondAnchors.count(); ++j) {
+ AnchorData *ad = pair->m_secondAnchors.at(j);
+ Q_ASSERT(ad->from == pair || ad->to == pair);
+
+ replaceVertex_helper(ad, pair, second);
+ g.createEdge(ad->from, ad->to, ad);
+ }
+
+ for (int j = 0; j < adjacents.count(); ++j) {
+ g.takeEdge(pair, adjacents.at(j));
+ }
+
+ // The pair simplified a layout vertex, so place back the correct vertex in the variable
+ // that track layout vertices
+ if (pair->m_item == q) {
+ AnchorVertex *layoutVertex = first->m_item == q ? first : second;
+ Q_ASSERT(layoutVertex->m_item == q);
+ changeLayoutVertex(orientation, pair, layoutVertex);
+ }
+
+ delete pair;
+ }
+ toRestore.clear();
+
+ // The restoration process for vertex simplification also restored the effect of the
+ // parallel anchors created during vertex simplification, so we just need to restore
+ // the constraints in case of parallels that contain center anchors. For the same
+ // reason as above, order matters here.
+ QList<AnchorData *> &parallelAnchors = anchorsFromSimplifiedVertices[orientation];
+
+ for (int i = parallelAnchors.count() - 1; i >= 0; --i) {
+ ParallelAnchorData *parallel = static_cast<ParallelAnchorData *>(parallelAnchors.at(i));
+ restoreSimplifiedConstraints(parallel);
+ delete parallel;
+ }
+ parallelAnchors.clear();
}
QGraphicsAnchorLayoutPrivate::Orientation
@@ -959,9 +1259,10 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges()
data->maxSize = QWIDGETSIZE_MAX;
data->skipInPreferred = 1;
- // Set the Layout Left edge as the root of the horizontal graph.
- AnchorVertex *v = internalVertex(layout, Qt::AnchorLeft);
- graph[Horizontal].setRootVertex(v);
+ // Save a reference to layout vertices
+ layoutFirstVertex[Horizontal] = internalVertex(layout, Qt::AnchorLeft);
+ layoutCentralVertex[Horizontal] = 0;
+ layoutLastVertex[Horizontal] = internalVertex(layout, Qt::AnchorRight);
// Vertical
data = new AnchorData;
@@ -970,17 +1271,18 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges()
data->maxSize = QWIDGETSIZE_MAX;
data->skipInPreferred = 1;
- // Set the Layout Top edge as the root of the vertical graph.
- v = internalVertex(layout, Qt::AnchorTop);
- graph[Vertical].setRootVertex(v);
+ // Save a reference to layout vertices
+ layoutFirstVertex[Vertical] = internalVertex(layout, Qt::AnchorTop);
+ layoutCentralVertex[Vertical] = 0;
+ layoutLastVertex[Vertical] = internalVertex(layout, Qt::AnchorBottom);
}
void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges()
{
Q_Q(QGraphicsAnchorLayout);
- Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL);
- Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL);
+ Q_ASSERT(!internalVertex(q, Qt::AnchorHorizontalCenter));
+ Q_ASSERT(!internalVertex(q, Qt::AnchorVerticalCenter));
removeAnchor_helper(internalVertex(q, Qt::AnchorLeft),
internalVertex(q, Qt::AnchorRight));
@@ -1019,6 +1321,8 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item)
void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge)
{
+ Q_Q(QGraphicsAnchorLayout);
+
Orientation orientation;
switch (centerEdge) {
case Qt::AnchorHorizontalCenter:
@@ -1061,24 +1365,32 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
c->variables.insert(data, 1.0);
addAnchor_helper(item, firstEdge, item, centerEdge, data);
data->isCenterAnchor = true;
+ data->dependency = AnchorData::Master;
data->refreshSizeHints(0);
data = new AnchorData;
c->variables.insert(data, -1.0);
addAnchor_helper(item, centerEdge, item, lastEdge, data);
data->isCenterAnchor = true;
+ data->dependency = AnchorData::Slave;
data->refreshSizeHints(0);
itemCenterConstraints[orientation].append(c);
// Remove old one
removeAnchor_helper(first, last);
+
+ if (item == q) {
+ layoutCentralVertex[orientation] = internalVertex(q, centerEdge);
+ }
}
void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge,
bool substitute)
{
+ Q_Q(QGraphicsAnchorLayout);
+
Orientation orientation;
switch (centerEdge) {
case Qt::AnchorHorizontalCenter:
@@ -1120,7 +1432,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
AnchorData *oldData = g.edgeData(first, center);
// Remove center constraint
for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) {
- if (itemCenterConstraints[orientation][i]->variables.contains(oldData)) {
+ if (itemCenterConstraints[orientation].at(i)->variables.contains(oldData)) {
delete itemCenterConstraints[orientation].takeAt(i);
break;
}
@@ -1151,6 +1463,10 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
// by this time, the center vertex is deleted and merged into a non-centered internal anchor
removeAnchor_helper(first, internalVertex(item, lastEdge));
}
+
+ if (item == q) {
+ layoutCentralVertex[orientation] = 0;
+ }
}
@@ -1180,7 +1496,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *
// Look for our anchor in all item center constraints, then remove it
for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) {
- if (itemCenterConstraints[orientation][i]->variables.contains(internalAnchor)) {
+ if (itemCenterConstraints[orientation].at(i)->variables.contains(internalAnchor)) {
delete itemCenterConstraints[orientation].takeAt(i);
break;
}
@@ -1690,7 +2006,7 @@ QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
{
QSet<AnchorData *> variableSet;
for (int i = 0; i < constraints.count(); ++i) {
- const QSimplexConstraint *c = constraints[i];
+ const QSimplexConstraint *c = constraints.at(i);
foreach (QSimplexVariable *var, c->variables.keys()) {
variableSet += static_cast<AnchorData *>(var);
}
@@ -1724,12 +2040,19 @@ QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
void QGraphicsAnchorLayoutPrivate::calculateGraphs(
QGraphicsAnchorLayoutPrivate::Orientation orientation)
{
- Q_Q(QGraphicsAnchorLayout);
-
#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT)
lastCalculationUsedSimplex[orientation] = false;
#endif
+ // ### This is necessary because now we do vertex simplification, we still don't know
+ // differentiate between invalidate()s that doesn't need resimplification and those which
+ // need. For example, when size hint of an item changes, this may cause an anchor to reach 0 or to
+ // leave 0 and get a size. In both cases we need resimplify.
+ //
+ // ### one possible solution would be tracking all the 0-sized anchors, if this set change, we need
+ // resimplify.
+ restoreSimplifiedGraph(orientation);
+
// Reset the nominal sizes of each anchor based on the current item sizes. This function
// works with both simplified and non-simplified graphs, so it'll work when the
// simplification is going to be reused.
@@ -1768,12 +2091,12 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs(
// Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes
// of the "trunk" set of constraints and variables.
// ### does trunk always exist? empty = trunk is the layout left->center->right
- QList<QSimplexConstraint *> trunkConstraints = parts[0];
+ QList<QSimplexConstraint *> trunkConstraints = parts.at(0);
QList<AnchorData *> trunkVariables = getVariables(trunkConstraints);
// For minimum and maximum, use the path between the two layout sides as the
// objective function.
- AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
+ AnchorVertex *v = layoutLastVertex[orientation];
GraphPath trunkPath = graphPaths[orientation].value(v);
bool feasible = calculateTrunk(orientation, trunkPath, trunkConstraints, trunkVariables);
@@ -1787,7 +2110,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs(
if (!feasible)
break;
- QList<QSimplexConstraint *> partConstraints = parts[i];
+ QList<QSimplexConstraint *> partConstraints = parts.at(i);
QList<AnchorData *> partVariables = getVariables(partConstraints);
Q_ASSERT(!partVariables.isEmpty());
feasible &= calculateNonTrunk(partConstraints, partVariables);
@@ -1836,27 +2159,19 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const
if (feasible) {
solvePreferred(allConstraints, variables);
- // Note that we don't include the sizeHintConstraints, since they
- // have a different logic for solveExpanding().
- solveExpanding(constraints, variables);
-
- // Calculate and set the preferred and expanding sizes for the layout,
+ // Calculate and set the preferred size for the layout,
// from the edge sizes that were calculated above.
qreal pref(0.0);
- qreal expanding(0.0);
foreach (const AnchorData *ad, path.positives) {
pref += ad->sizeAtPreferred;
- expanding += ad->sizeAtExpanding;
}
foreach (const AnchorData *ad, path.negatives) {
pref -= ad->sizeAtPreferred;
- expanding -= ad->sizeAtExpanding;
}
sizeHints[orientation][Qt::MinimumSize] = min;
sizeHints[orientation][Qt::PreferredSize] = pref;
sizeHints[orientation][Qt::MaximumSize] = max;
- sizeAtExpanding[orientation] = expanding;
}
qDeleteAll(sizeHintConstraints);
@@ -1870,13 +2185,11 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const
AnchorData *ad = path.positives.toList()[0];
ad->sizeAtMinimum = ad->minSize;
ad->sizeAtPreferred = ad->prefSize;
- ad->sizeAtExpanding = ad->expSize;
ad->sizeAtMaximum = ad->maxSize;
sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum;
sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred;
sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum;
- sizeAtExpanding[orientation] = ad->sizeAtExpanding;
}
#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT)
@@ -1899,10 +2212,9 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra
// Propagate size at preferred to other sizes. Semi-floats always will be
// in their sizeAtPreferred.
for (int j = 0; j < variables.count(); ++j) {
- AnchorData *ad = variables[j];
+ AnchorData *ad = variables.at(j);
Q_ASSERT(ad);
ad->sizeAtMinimum = ad->sizeAtPreferred;
- ad->sizeAtExpanding = ad->sizeAtPreferred;
ad->sizeAtMaximum = ad->sizeAtPreferred;
}
}
@@ -1955,7 +2267,7 @@ void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation)
QSet<AnchorData *> visited;
- AnchorVertex *root = graph[orientation].rootVertex();
+ AnchorVertex *root = layoutFirstVertex[orientation];
graphPaths[orientation].insert(root, GraphPath());
@@ -2013,7 +2325,7 @@ void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation)
QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex);
for (int i = 1; i < valueCount; ++i) {
constraints[orientation] += \
- pathsToVertex[0].constraint(pathsToVertex[i]);
+ pathsToVertex[0].constraint(pathsToVertex.at(i));
}
}
}
@@ -2041,9 +2353,37 @@ void QGraphicsAnchorLayoutPrivate::updateAnchorSizes(Orientation orientation)
QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints(
const QList<AnchorData *> &anchors)
{
+ if (anchors.isEmpty())
+ return QList<QSimplexConstraint *>();
+
+ // Look for the layout edge. That can be either the first half in case the
+ // layout is split in two, or the whole layout anchor.
+ Orientation orient = Orientation(anchors.first()->orientation);
+ AnchorData *layoutEdge = 0;
+ if (layoutCentralVertex[orient]) {
+ layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutCentralVertex[orient]);
+ } else {
+ layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutLastVertex[orient]);
+
+ // If maxSize is less then "infinite", that means there are other anchors
+ // grouped together with this one. We can't ignore its maximum value so we
+ // set back the variable to NULL to prevent the continue condition from being
+ // satisfied in the loop below.
+ if (layoutEdge->maxSize < QWIDGETSIZE_MAX)
+ layoutEdge = 0;
+ }
+
+ // For each variable, create constraints based on size hints
QList<QSimplexConstraint *> anchorConstraints;
+ bool unboundedProblem = true;
for (int i = 0; i < anchors.size(); ++i) {
- AnchorData *ad = anchors[i];
+ AnchorData *ad = anchors.at(i);
+
+ // Anchors that have their size directly linked to another one don't need constraints
+ // For exammple, the second half of an item has exactly the same size as the first half
+ // thus constraining the latter is enough.
+ if (ad->dependency == AnchorData::Slave)
+ continue;
if ((ad->minSize == ad->maxSize) || qFuzzyCompare(ad->minSize, ad->maxSize)) {
QSimplexConstraint *c = new QSimplexConstraint;
@@ -2051,6 +2391,7 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin
c->constant = ad->minSize;
c->ratio = QSimplexConstraint::Equal;
anchorConstraints += c;
+ unboundedProblem = false;
} else {
QSimplexConstraint *c = new QSimplexConstraint;
c->variables.insert(ad, 1.0);
@@ -2058,14 +2399,30 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin
c->ratio = QSimplexConstraint::MoreOrEqual;
anchorConstraints += c;
+ // We avoid adding restrictions to the layout internal anchors. That's
+ // to prevent unnecessary fair distribution from happening due to this
+ // artificial restriction.
+ if (ad == layoutEdge)
+ continue;
+
c = new QSimplexConstraint;
c->variables.insert(ad, 1.0);
c->constant = ad->maxSize;
c->ratio = QSimplexConstraint::LessOrEqual;
anchorConstraints += c;
+ unboundedProblem = false;
}
}
+ // If no upper boundary restriction was added, add one to avoid unbounded problem
+ if (unboundedProblem) {
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->variables.insert(layoutEdge, 1.0);
+ c->constant = QWIDGETSIZE_MAX;
+ c->ratio = QSimplexConstraint::LessOrEqual;
+ anchorConstraints += c;
+ }
+
return anchorConstraints;
}
@@ -2075,38 +2432,26 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin
QList< QList<QSimplexConstraint *> >
QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation)
{
- Q_Q(QGraphicsAnchorLayout);
+ Q_ASSERT(layoutFirstVertex[orientation] && layoutLastVertex[orientation]);
- // Find layout vertices and edges for the current orientation.
- AnchorVertex *layoutFirstVertex = \
- internalVertex(q, pickEdge(Qt::AnchorLeft, orientation));
-
- AnchorVertex *layoutCentralVertex = \
- internalVertex(q, pickEdge(Qt::AnchorHorizontalCenter, orientation));
-
- AnchorVertex *layoutLastVertex = \
- internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
-
- Q_ASSERT(layoutFirstVertex && layoutLastVertex);
-
- AnchorData *edgeL1 = NULL;
- AnchorData *edgeL2 = NULL;
+ AnchorData *edgeL1 = 0;
+ AnchorData *edgeL2 = 0;
// The layout may have a single anchor between Left and Right or two half anchors
// passing through the center
- if (layoutCentralVertex) {
- edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutCentralVertex);
- edgeL2 = graph[orientation].edgeData(layoutCentralVertex, layoutLastVertex);
+ if (layoutCentralVertex[orientation]) {
+ edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutCentralVertex[orientation]);
+ edgeL2 = graph[orientation].edgeData(layoutCentralVertex[orientation], layoutLastVertex[orientation]);
} else {
- edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutLastVertex);
+ edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutLastVertex[orientation]);
}
QLinkedList<QSimplexConstraint *> remainingConstraints;
for (int i = 0; i < constraints[orientation].count(); ++i) {
- remainingConstraints += constraints[orientation][i];
+ remainingConstraints += constraints[orientation].at(i);
}
for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) {
- remainingConstraints += itemCenterConstraints[orientation][i];
+ remainingConstraints += itemCenterConstraints[orientation].at(i);
}
QList<QSimplexConstraint *> trunkConstraints;
@@ -2276,6 +2621,21 @@ void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom)
}
/*!
+ \internal
+
+ Fill the distance in the vertex and in the sub-vertices if its a combined vertex.
+*/
+static void setVertexDistance(AnchorVertex *v, qreal distance)
+{
+ v->distance = distance;
+ if (v->m_type == AnchorVertex::Pair) {
+ AnchorVertexPair *pair = static_cast<AnchorVertexPair *>(v);
+ setVertexDistance(pair->m_first, distance);
+ setVertexDistance(pair->m_second, distance);
+ }
+}
+
+/*!
\internal
Calculate the position of each vertex based on the paths to each of
@@ -2288,9 +2648,9 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions(
QSet<AnchorVertex *> visited;
// Get root vertex
- AnchorVertex *root = graph[orientation].rootVertex();
+ AnchorVertex *root = layoutFirstVertex[orientation];
- root->distance = 0;
+ setVertexDistance(root, 0);
visited.insert(root);
// Add initial edges to the queue
@@ -2314,7 +2674,7 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions(
continue;
visited.insert(pair.second);
- interpolateEdge(pair.first, edge, orientation);
+ interpolateEdge(pair.first, edge);
QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second);
for (int i = 0; i < adjacents.count(); ++i) {
@@ -2343,7 +2703,6 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
result = getFactor(current,
sizeHints[orientation][Qt::MinimumSize],
sizeHints[orientation][Qt::PreferredSize],
- sizeAtExpanding[orientation],
sizeHints[orientation][Qt::MaximumSize]);
interpolationInterval[orientation] = result.first;
@@ -2358,7 +2717,6 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
- minimum size,
- preferred size,
- - size when all expanding anchors are expanded,
- maximum size.
These three key values are calculated in advance using linear
@@ -2370,36 +2728,32 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
vertices to be initalized, so it calls specialized functions that
will recurse back to interpolateEdge().
*/
-void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base,
- AnchorData *edge,
- Orientation orientation)
+void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorData *edge)
{
+ const Orientation orientation = Orientation(edge->orientation);
const QPair<Interval, qreal> factor(interpolationInterval[orientation],
interpolationProgress[orientation]);
qreal edgeDistance = interpolate(factor, edge->sizeAtMinimum, edge->sizeAtPreferred,
- edge->sizeAtExpanding, edge->sizeAtMaximum);
+ edge->sizeAtMaximum);
Q_ASSERT(edge->from == base || edge->to == base);
- if (edge->from == base)
- edge->to->distance = base->distance + edgeDistance;
- else
- edge->from->distance = base->distance - edgeDistance;
+ // Calculate the distance for the vertex opposite to the base
+ if (edge->from == base) {
+ setVertexDistance(edge->to, base->distance + edgeDistance);
+ } else {
+ setVertexDistance(edge->from, base->distance - edgeDistance);
+ }
// Process child anchors
if (edge->type == AnchorData::Sequential)
- interpolateSequentialEdges(edge->from,
- static_cast<SequentialAnchorData *>(edge),
- orientation);
+ interpolateSequentialEdges(static_cast<SequentialAnchorData *>(edge));
else if (edge->type == AnchorData::Parallel)
- interpolateParallelEdges(edge->from,
- static_cast<ParallelAnchorData *>(edge),
- orientation);
+ interpolateParallelEdges(static_cast<ParallelAnchorData *>(edge));
}
-void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(
- AnchorVertex *base, ParallelAnchorData *data, Orientation orientation)
+void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(ParallelAnchorData *data)
{
// In parallels the boundary vertices are already calculate, we
// just need to look for sequential groups inside, because only
@@ -2407,46 +2761,44 @@ void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(
// First edge
if (data->firstEdge->type == AnchorData::Sequential)
- interpolateSequentialEdges(base,
- static_cast<SequentialAnchorData *>(data->firstEdge),
- orientation);
+ interpolateSequentialEdges(static_cast<SequentialAnchorData *>(data->firstEdge));
else if (data->firstEdge->type == AnchorData::Parallel)
- interpolateParallelEdges(base,
- static_cast<ParallelAnchorData *>(data->firstEdge),
- orientation);
+ interpolateParallelEdges(static_cast<ParallelAnchorData *>(data->firstEdge));
// Second edge
if (data->secondEdge->type == AnchorData::Sequential)
- interpolateSequentialEdges(base,
- static_cast<SequentialAnchorData *>(data->secondEdge),
- orientation);
+ interpolateSequentialEdges(static_cast<SequentialAnchorData *>(data->secondEdge));
else if (data->secondEdge->type == AnchorData::Parallel)
- interpolateParallelEdges(base,
- static_cast<ParallelAnchorData *>(data->secondEdge),
- orientation);
+ interpolateParallelEdges(static_cast<ParallelAnchorData *>(data->secondEdge));
}
-void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(
- AnchorVertex *base, SequentialAnchorData *data, Orientation orientation)
+void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(SequentialAnchorData *data)
{
- AnchorVertex *prev = base;
+ // This method is supposed to handle any sequential anchor, even out-of-order
+ // ones. However, in the current QGAL implementation we should get only the
+ // well behaved ones.
+ Q_ASSERT(data->m_edges.first()->from == data->from);
+ Q_ASSERT(data->m_edges.last()->to == data->to);
- // ### I'm not sure whether this assumption is safe. If not,
- // consider that m_edges.last() could be used instead (so
- // at(0) would be the one to be treated specially).
- Q_ASSERT(base == data->m_edges.at(0)->to || base == data->m_edges.at(0)->from);
+ // At this point, the two outter vertices already have their distance
+ // calculated.
+ // We use the first as the base to calculate the internal ones
+
+ AnchorVertex *prev = data->from;
- // Skip the last
for (int i = 0; i < data->m_edges.count() - 1; ++i) {
- AnchorData *child = data->m_edges.at(i);
- interpolateEdge(prev, child, orientation);
- prev = child->to;
+ AnchorData *edge = data->m_edges.at(i);
+ interpolateEdge(prev, edge);
+
+ // Use the recently calculated vertex as the base for the next one
+ const bool edgeIsForward = (edge->from == prev);
+ prev = edgeIsForward ? edge->to : edge->from;
}
// Treat the last specially, since we already calculated it's end
// vertex, so it's only interesting if it's a complex one
if (data->m_edges.last()->type != AnchorData::Normal)
- interpolateEdge(prev, data->m_edges.last(), orientation);
+ interpolateEdge(prev, data->m_edges.last());
}
bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> &constraints,
@@ -2472,9 +2824,10 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *>
// Save sizeAtMinimum results
QList<AnchorData *> variables = getVariables(constraints);
for (int i = 0; i < variables.size(); ++i) {
- AnchorData *ad = static_cast<AnchorData *>(variables[i]);
- Q_ASSERT(ad->result >= ad->minSize || qFuzzyCompare(ad->result, ad->minSize));
+ AnchorData *ad = static_cast<AnchorData *>(variables.at(i));
ad->sizeAtMinimum = ad->result;
+ Q_ASSERT(ad->sizeAtMinimum >= ad->minSize ||
+ qAbs(ad->sizeAtMinimum - ad->minSize) < 0.00000001);
}
// Calculate maximum values
@@ -2482,9 +2835,10 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *>
// Save sizeAtMaximum results
for (int i = 0; i < variables.size(); ++i) {
- AnchorData *ad = static_cast<AnchorData *>(variables[i]);
- Q_ASSERT(ad->result <= ad->maxSize || qFuzzyCompare(ad->result, ad->maxSize));
+ AnchorData *ad = static_cast<AnchorData *>(variables.at(i));
ad->sizeAtMaximum = ad->result;
+ // Q_ASSERT(ad->sizeAtMaximum <= ad->maxSize ||
+ // qAbs(ad->sizeAtMaximum - ad->maxSize) < 0.00000001);
}
}
return feasible;
@@ -2515,7 +2869,7 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint
// A + A_shrinker - A_grower = A_pref
//
for (int i = 0; i < variables.size(); ++i) {
- AnchorData *ad = variables[i];
+ AnchorData *ad = variables.at(i);
if (ad->skipInPreferred)
continue;
@@ -2546,7 +2900,7 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint
// Save sizeAtPreferred results
for (int i = 0; i < variables.size(); ++i) {
- AnchorData *ad = variables[i];
+ AnchorData *ad = variables.at(i);
ad->sizeAtPreferred = ad->result;
}
@@ -2563,139 +2917,6 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint
/*!
\internal
- Calculate the "expanding" keyframe
-
- This new keyframe sits between the already existing sizeAtPreferred and
- sizeAtMaximum keyframes. Its goal is to modify the interpolation between
- the latter as to respect the "expanding" size policy of some anchors.
-
- Previously all items would be subject to a linear interpolation between
- sizeAtPreferred and sizeAtMaximum values. This will change now, the
- expanding anchors will change their size before the others. To calculate
- this keyframe we use the following logic:
-
- 1) Ask each anchor for their desired expanding size (ad->expSize), this
- value depends on the anchor expanding property in the following way:
-
- - Expanding normal anchors want to grow towards their maximum size
- - Non-expanding normal anchors want to remain at their preferred size.
- - Sequential anchors wants to grow towards a size that is calculated by:
- summarizing it's child anchors, where it will use preferred size for non-expanding anchors
- and maximum size for expanding anchors.
- - Parallel anchors want to grow towards the smallest maximum size of all the expanding anchors.
-
- 2) Clamp their desired values to the value they assume in the neighbour
- keyframes (sizeAtPreferred and sizeAtExpanding)
-
- 3) Run simplex with a setup that ensures the following:
-
- a. Anchors will change their value from their sizeAtPreferred towards
- their sizeAtMaximum as much as required to ensure that ALL anchors
- reach their respective "desired" expanding sizes.
-
- b. No anchors will change their value beyond what is NEEDED to satisfy
- the requirement above.
-
- The final result is that, at the "expanding" keyframe expanding anchors
- will grow and take with them all anchors that are parallel to them.
- However, non-expanding anchors will remain at their preferred size unless
- they are forced to grow by a parallel expanding anchor.
-
- Note: For anchors where the sizeAtPreferred is bigger than sizeAtMaximum,
- the visual effect when the layout grows from its preferred size is
- the following: Expanding anchors will keep their size while non
- expanding ones will shrink. Only after non-expanding anchors have
- shrinked all the way, the expanding anchors will start to shrink too.
-*/
-void QGraphicsAnchorLayoutPrivate::solveExpanding(const QList<QSimplexConstraint *> &constraints,
- const QList<AnchorData *> &variables)
-{
- QList<QSimplexConstraint *> itemConstraints;
- QSimplexConstraint *objective = new QSimplexConstraint;
- bool hasExpanding = false;
-
- // Construct the simplex constraints and objective
- for (int i = 0; i < variables.size(); ++i) {
- // For each anchor
- AnchorData *ad = variables[i];
-
- // Clamp the desired expanding size
- qreal upperBoundary = qMax(ad->sizeAtPreferred, ad->sizeAtMaximum);
- qreal lowerBoundary = qMin(ad->sizeAtPreferred, ad->sizeAtMaximum);
- qreal boundedExpSize = qBound(lowerBoundary, ad->expSize, upperBoundary);
-
- // Expanding anchors are those that want to move from their preferred size
- if (boundedExpSize != ad->sizeAtPreferred)
- hasExpanding = true;
-
- // Lock anchor between boundedExpSize and sizeAtMaximum (ensure 3.a)
- if (boundedExpSize == ad->sizeAtMaximum || qFuzzyCompare(boundedExpSize, ad->sizeAtMaximum)) {
- // The interval has only one possible value, we can use an "Equal"
- // constraint and don't need to add this variable to the objective.
- QSimplexConstraint *itemC = new QSimplexConstraint;
- itemC->ratio = QSimplexConstraint::Equal;
- itemC->variables.insert(ad, 1.0);
- itemC->constant = boundedExpSize;
- itemConstraints << itemC;
- } else {
- // Add MoreOrEqual and LessOrEqual constraints.
- QSimplexConstraint *itemC = new QSimplexConstraint;
- itemC->ratio = QSimplexConstraint::MoreOrEqual;
- itemC->variables.insert(ad, 1.0);
- itemC->constant = qMin(boundedExpSize, ad->sizeAtMaximum);
- itemConstraints << itemC;
-
- itemC = new QSimplexConstraint;
- itemC->ratio = QSimplexConstraint::LessOrEqual;
- itemC->variables.insert(ad, 1.0);
- itemC->constant = qMax(boundedExpSize, ad->sizeAtMaximum);
- itemConstraints << itemC;
-
- // Create objective to avoid the anchors from moving away from
- // the preferred size more than the needed amount. (ensure 3.b)
- // The objective function is the distance between sizeAtPreferred
- // and sizeAtExpanding, it will be minimized.
- if (ad->sizeAtExpanding < ad->sizeAtMaximum) {
- // Try to shrink this variable towards its sizeAtPreferred value
- objective->variables.insert(ad, 1.0);
- } else {
- // Try to grow this variable towards its sizeAtPreferred value
- objective->variables.insert(ad, -1.0);
- }
- }
- }
-
- // Solve
- if (hasExpanding == false) {
- // If no anchors are expanding, we don't need to run the simplex
- // Set all variables to their preferred size
- for (int i = 0; i < variables.size(); ++i) {
- variables[i]->sizeAtExpanding = variables[i]->sizeAtPreferred;
- }
- } else {
- // Run simplex
- QSimplex simplex;
-
- // Satisfy expanding (3.a)
- bool feasible = simplex.setConstraints(constraints + itemConstraints);
- Q_ASSERT(feasible);
-
- // Reduce damage (3.b)
- simplex.setObjective(objective);
- simplex.solveMin();
-
- // Collect results
- for (int i = 0; i < variables.size(); ++i) {
- variables[i]->sizeAtExpanding = variables[i]->result;
- }
- }
-
- delete objective;
- qDeleteAll(itemConstraints);
-}
-
-/*!
- \internal
Returns true if there are no arrangement that satisfies all constraints.
Otherwise returns false.
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
index 7dd0d65..3ef37f9 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
@@ -78,66 +78,30 @@ QT_BEGIN_NAMESPACE
Represents a vertex (anchorage point) in the internal graph
*/
struct AnchorVertex {
+ enum Type {
+ Normal = 0,
+ Pair
+ };
+
AnchorVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge)
- : m_item(item), m_edge(edge) {}
+ : m_item(item), m_edge(edge), m_type(Normal) {}
AnchorVertex()
- : m_item(0), m_edge(Qt::AnchorPoint(0)) {}
+ : m_item(0), m_edge(Qt::AnchorPoint(0)), m_type(Normal) {}
#ifdef QT_DEBUG
inline QString toString() const;
#endif
+
QGraphicsLayoutItem *m_item;
Qt::AnchorPoint m_edge;
+ uint m_type : 1;
// Current distance from this vertex to the layout edge (Left or Top)
// Value is calculated from the current anchors sizes.
qreal distance;
};
-#ifdef QT_DEBUG
-inline QString AnchorVertex::toString() const
-{
- if (!this || !m_item) {
- return QLatin1String("NULL");
- }
- QString edge;
- switch (m_edge) {
- case Qt::AnchorLeft:
- edge = QLatin1String("Left");
- break;
- case Qt::AnchorHorizontalCenter:
- edge = QLatin1String("HorizontalCenter");
- break;
- case Qt::AnchorRight:
- edge = QLatin1String("Right");
- break;
- case Qt::AnchorTop:
- edge = QLatin1String("Top");
- break;
- case Qt::AnchorVerticalCenter:
- edge = QLatin1String("VerticalCenter");
- break;
- case Qt::AnchorBottom:
- edge = QLatin1String("Bottom");
- break;
- default:
- edge = QLatin1String("None");
- break;
- }
- QString itemName;
- if (m_item->isLayout()) {
- itemName = QLatin1String("layout");
- } else {
- if (QGraphicsItem *item = m_item->graphicsItem()) {
- itemName = item->data(0).toString();
- }
- }
- edge.insert(0, QLatin1String("%1_"));
- return edge.arg(itemName);
-}
-#endif
-
/*!
\internal
@@ -150,14 +114,21 @@ struct AnchorData : public QSimplexVariable {
Parallel
};
+ enum Dependency {
+ Independent = 0,
+ Master,
+ Slave
+ };
+
AnchorData()
: QSimplexVariable(), item(0), from(0), to(0),
- minSize(0), prefSize(0), expSize(0), maxSize(0),
+ minSize(0), prefSize(0), maxSize(0),
sizeAtMinimum(0), sizeAtPreferred(0),
- sizeAtExpanding(0), sizeAtMaximum(0),
+ sizeAtMaximum(0),
graphicsAnchor(0), skipInPreferred(0),
type(Normal), hasSize(true), isLayoutAnchor(false),
- isCenterAnchor(false), orientation(0) {}
+ isCenterAnchor(false), orientation(0),
+ dependency(Independent) {}
virtual void updateChildrenSizes() {}
virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo);
@@ -194,7 +165,6 @@ struct AnchorData : public QSimplexVariable {
// size.
qreal minSize;
qreal prefSize;
- qreal expSize;
qreal maxSize;
// These attributes define which sizes should that anchor be in when the
@@ -202,7 +172,6 @@ struct AnchorData : public QSimplexVariable {
// calculated by the Simplex solver based on the current layout setup.
qreal sizeAtMinimum;
qreal sizeAtPreferred;
- qreal sizeAtExpanding;
qreal sizeAtMaximum;
QGraphicsAnchor *graphicsAnchor;
@@ -212,6 +181,7 @@ struct AnchorData : public QSimplexVariable {
uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor
uint isCenterAnchor : 1;
uint orientation : 1;
+ uint dependency : 2; // either Independent, Master or Slave
};
#ifdef QT_DEBUG
@@ -250,10 +220,11 @@ struct ParallelAnchorData : public AnchorData
type = AnchorData::Parallel;
orientation = first->orientation;
- // ### Those asserts force that both child anchors have the same direction,
- // but can't we simplify a pair of anchors in opposite directions?
- Q_ASSERT(first->from == second->from);
- Q_ASSERT(first->to == second->to);
+ // This assert whether the child anchors share their vertices
+ Q_ASSERT(((first->from == second->from) && (first->to == second->to)) ||
+ ((first->from == second->to) && (first->to == second->from)));
+
+ // We arbitrarily choose the direction of the first child as "our" direction
from = first->from;
to = first->to;
#ifdef QT_DEBUG
@@ -268,8 +239,73 @@ struct ParallelAnchorData : public AnchorData
AnchorData* firstEdge;
AnchorData* secondEdge;
+
+ QList<QSimplexConstraint *> m_firstConstraints;
+ QList<QSimplexConstraint *> m_secondConstraints;
};
+struct AnchorVertexPair : public AnchorVertex {
+ AnchorVertexPair(AnchorVertex *v1, AnchorVertex *v2, AnchorData *data)
+ : AnchorVertex(), m_first(v1), m_second(v2), m_removedAnchor(data) {
+ m_type = AnchorVertex::Pair;
+ }
+
+ AnchorVertex *m_first;
+ AnchorVertex *m_second;
+
+ AnchorData *m_removedAnchor;
+ QList<AnchorData *> m_firstAnchors;
+ QList<AnchorData *> m_secondAnchors;
+};
+
+#ifdef QT_DEBUG
+inline QString AnchorVertex::toString() const
+{
+ if (!this) {
+ return QLatin1String("NULL");
+ } else if (m_type == Pair) {
+ const AnchorVertexPair *vp = static_cast<const AnchorVertexPair *>(this);
+ return QString::fromAscii("(%1, %2)").arg(vp->m_first->toString()).arg(vp->m_second->toString());
+ } else if (!m_item) {
+ return QString::fromAscii("NULL_%1").arg(int(this));
+ }
+ QString edge;
+ switch (m_edge) {
+ case Qt::AnchorLeft:
+ edge = QLatin1String("Left");
+ break;
+ case Qt::AnchorHorizontalCenter:
+ edge = QLatin1String("HorizontalCenter");
+ break;
+ case Qt::AnchorRight:
+ edge = QLatin1String("Right");
+ break;
+ case Qt::AnchorTop:
+ edge = QLatin1String("Top");
+ break;
+ case Qt::AnchorVerticalCenter:
+ edge = QLatin1String("VerticalCenter");
+ break;
+ case Qt::AnchorBottom:
+ edge = QLatin1String("Bottom");
+ break;
+ default:
+ edge = QLatin1String("None");
+ break;
+ }
+ QString itemName;
+ if (m_item->isLayout()) {
+ itemName = QLatin1String("layout");
+ } else {
+ if (QGraphicsItem *item = m_item->graphicsItem()) {
+ itemName = item->data(0).toString();
+ }
+ }
+ edge.insert(0, QLatin1String("%1_"));
+ return edge.arg(itemName);
+}
+#endif
+
/*!
\internal
@@ -337,8 +373,7 @@ public:
// Interval represents which interpolation interval are we operating in.
enum Interval {
MinToPreferred = 0,
- PreferredToExpanding,
- ExpandingToMax
+ PreferredToMax
};
// Several structures internal to the layout are duplicated to handle
@@ -427,20 +462,33 @@ public:
QLayoutStyleInfo &styleInfo() const;
- // Activation methods
- bool simplifyGraph(Orientation orientation);
- bool simplifyGraphIteration(Orientation orientation, bool *feasible);
- void restoreSimplifiedGraph(Orientation orientation);
+ AnchorData *addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible);
+ // Activation
void calculateGraphs();
void calculateGraphs(Orientation orientation);
+ // Simplification
+ bool simplifyGraph(Orientation orientation);
+ bool simplifyVertices(Orientation orientation);
+ bool simplifyGraphIteration(Orientation orientation, bool *feasible);
+
+ bool replaceVertex(Orientation orientation, AnchorVertex *oldV,
+ AnchorVertex *newV, const QList<AnchorData *> &edges);
+
+
+ void restoreSimplifiedGraph(Orientation orientation);
+ void restoreSimplifiedAnchor(AnchorData *edge);
+ void restoreSimplifiedConstraints(ParallelAnchorData *parallel);
+ void restoreVertices(Orientation orientation);
+
bool calculateTrunk(Orientation orientation, const GraphPath &trunkPath,
const QList<QSimplexConstraint *> &constraints,
const QList<AnchorData *> &variables);
bool calculateNonTrunk(const QList<QSimplexConstraint *> &constraints,
const QList<AnchorData *> &variables);
+ // Support functions for calculateGraph()
bool refreshAllSizeHints(Orientation orientation);
void findPaths(Orientation orientation);
void constraintsFromPaths(Orientation orientation);
@@ -460,6 +508,17 @@ public:
return internalVertex(qMakePair(const_cast<QGraphicsLayoutItem *>(item), edge));
}
+ inline void changeLayoutVertex(Orientation orientation, AnchorVertex *oldV, AnchorVertex *newV)
+ {
+ if (layoutFirstVertex[orientation] == oldV)
+ layoutFirstVertex[orientation] = newV;
+ else if (layoutCentralVertex[orientation] == oldV)
+ layoutCentralVertex[orientation] = newV;
+ else if (layoutLastVertex[orientation] == oldV)
+ layoutLastVertex[orientation] = newV;
+ }
+
+
AnchorVertex *addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge);
void removeInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge);
@@ -468,19 +527,15 @@ public:
void calculateVertexPositions(Orientation orientation);
void setupEdgesInterpolation(Orientation orientation);
- void interpolateEdge(AnchorVertex *base, AnchorData *edge, Orientation orientation);
- void interpolateSequentialEdges(AnchorVertex *base, SequentialAnchorData *edge,
- Orientation orientation);
- void interpolateParallelEdges(AnchorVertex *base, ParallelAnchorData *edge,
- Orientation orientation);
+ void interpolateEdge(AnchorVertex *base, AnchorData *edge);
+ void interpolateSequentialEdges(SequentialAnchorData *edge);
+ void interpolateParallelEdges(ParallelAnchorData *edge);
// Linear Programming solver methods
bool solveMinMax(const QList<QSimplexConstraint *> &constraints,
GraphPath path, qreal *min, qreal *max);
bool solvePreferred(const QList<QSimplexConstraint *> &constraints,
const QList<AnchorData *> &variables);
- void solveExpanding(const QList<QSimplexConstraint *> &constraints,
- const QList<AnchorData *> &variables);
bool hasConflicts() const;
#ifdef QT_DEBUG
@@ -491,7 +546,6 @@ public:
qreal spacings[NOrientations];
// Size hints from simplex engine
qreal sizeHints[2][3];
- qreal sizeAtExpanding[2];
// Items
QVector<QGraphicsLayoutItem *> items;
@@ -504,6 +558,14 @@ public:
// Internal graph of anchorage points and anchors, for both orientations
Graph<AnchorVertex, AnchorData> graph[2];
+ AnchorVertex *layoutFirstVertex[2];
+ AnchorVertex *layoutCentralVertex[2];
+ AnchorVertex *layoutLastVertex[2];
+
+ // Combined anchors in order of creation
+ QList<AnchorVertexPair *> simplifiedVertices[2];
+ QList<AnchorData *> anchorsFromSimplifiedVertices[2];
+
// Graph paths and constraints, for both orientations
QMultiHash<AnchorVertex *, GraphPath> graphPaths[2];
QList<QSimplexConstraint *> constraints[2];
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 2fd499d..723e496 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -386,6 +386,12 @@
introduced in Qt 4.6.
\omitvalue ItemIsFocusScope Internal only (for now).
+
+ \value ItemSendsScenePositionChanges The item enables itemChange()
+ notifications for ItemScenePositionHasChanged. For performance reasons,
+ these notifications are disabled by default. You must enable this flag
+ to receive notifications for scene position changes. This flag was
+ introduced in Qt 4.6.
*/
/*!
@@ -562,6 +568,14 @@
\value ItemOpacityHasChanged The item's opacity has changed. The value
argument is the new opacity (i.e., a double). Do not call setOpacity() as
this notification is delivered. The return value is ignored.
+
+ \value ItemScenePositionHasChanged The item's scene position has changed.
+ This notification is sent if the ItemSendsScenePositionChanges flag is
+ enabled, and after the item's scene position has changed (i.e., the
+ position or transformation of the item itself or the position or
+ transformation of any ancestor has changed). The value argument is the
+ new scene position (the same as scenePos()), and QGraphicsItem ignores
+ the return value for this notification (i.e., a read-only notification).
*/
/*!
@@ -990,6 +1004,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
if (scene) {
// Deliver the change to the index
scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
+
+ // Disable scene pos notifications for old ancestors
+ if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
+ scene->d_func()->setScenePosItemEnabled(q, false);
}
if (subFocusItem && parent) {
@@ -1084,10 +1102,15 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
parent->d_ptr->addChild(q);
parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
- if (!implicitUpdate && scene) {
- scene->d_func()->markDirty(q_ptr, QRect(),
- /*invalidateChildren=*/false,
- /*maybeDirtyClipPath=*/true);
+ if (scene) {
+ if (!implicitUpdate)
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+
+ // Re-enable scene pos notifications for new ancestors
+ if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
+ scene->d_func()->setScenePosItemEnabled(q, true);
}
// Inherit ancestor flags from the new parent.
@@ -1336,7 +1359,9 @@ QGraphicsItem::~QGraphicsItem()
d_ptr->setParentItemHelper(0);
}
+#ifndef QT_NO_GRAPHICSEFFECT
delete d_ptr->graphicsEffect;
+#endif //QT_NO_GRAPHICSEFFECT
if (d_ptr->transformData) {
for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
@@ -1746,6 +1771,12 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
}
if (d_ptr->scene) {
+ if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) {
+ if (flags & ItemSendsScenePositionChanges)
+ d_ptr->scene->d_func()->registerScenePosItem(this);
+ else
+ d_ptr->scene->d_func()->unregisterScenePosItem(this);
+ }
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*maybeDirtyClipPath*/true);
@@ -2506,7 +2537,9 @@ void QGraphicsItem::setOpacity(qreal opacity)
// Update.
if (d_ptr->scene) {
+#ifndef QT_NO_GRAPHICSEFFECT
d_ptr->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*maybeDirtyClipPath=*/false,
@@ -2523,6 +2556,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
\since 4.6
*/
+#ifndef QT_NO_GRAPHICSEFFECT
QGraphicsEffect *QGraphicsItem::graphicsEffect() const
{
return d_ptr->graphicsEffect;
@@ -2569,6 +2603,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
prepareGeometryChange();
}
+#endif //QT_NO_GRAPHICSEFFECT
/*!
\internal
@@ -2582,6 +2617,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
*/
QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
{
+#ifndef QT_NO_GRAPHICSEFFECT
QGraphicsEffect *effect = graphicsEffect;
QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : q_ptr->boundingRect();
if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
@@ -2598,6 +2634,10 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
}
return brect;
+#else //QT_NO_GRAPHICSEFFECT
+ return q_ptr->boundingRect();
+#endif //QT_NO_GRAPHICSEFFECT
+
}
/*!
@@ -2951,7 +2991,7 @@ bool QGraphicsItem::hasFocus() const
{
if (d_ptr->focusProxy)
return d_ptr->focusProxy->hasFocus();
- return (d_ptr->scene && d_ptr->scene->focusItem() == this);
+ return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this);
}
/*!
@@ -3309,6 +3349,9 @@ QPointF QGraphicsItem::pos() const
*/
void QGraphicsItem::setX(qreal x)
{
+ if (d_ptr->inDestructor)
+ return;
+
d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
}
@@ -3330,6 +3373,9 @@ void QGraphicsItem::setX(qreal x)
*/
void QGraphicsItem::setY(qreal y)
{
+ if (d_ptr->inDestructor)
+ return;
+
d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
}
@@ -3395,6 +3441,9 @@ void QGraphicsItem::setPos(const QPointF &pos)
if (d_ptr->pos == pos)
return;
+ if (d_ptr->inDestructor)
+ return;
+
// Update and repositition.
if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
d_ptr->setPosHelper(pos);
@@ -3412,6 +3461,7 @@ void QGraphicsItem::setPos(const QPointF &pos)
// Send post-notification.
itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
+ d_ptr->sendScenePosChange();
}
/*!
@@ -4022,6 +4072,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
// Send post-notification.
itemChange(ItemTransformHasChanged, newTransformVariant);
+ d_ptr->sendScenePosChange();
}
/*!
@@ -4246,6 +4297,24 @@ void QGraphicsItemPrivate::ensureSequentialSiblingIndex()
}
/*!
+ \internal
+*/
+inline void QGraphicsItemPrivate::sendScenePosChange()
+{
+ Q_Q(QGraphicsItem);
+ if (scene) {
+ if (flags & QGraphicsItem::ItemSendsScenePositionChanges)
+ q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos());
+ if (scenePosDescendants) {
+ foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) {
+ if (q->isAncestorOf(item))
+ item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos());
+ }
+ }
+ }
+}
+
+/*!
\since 4.6
Stacks this item before \a sibling, which must be a sibling item (i.e., the
@@ -4296,6 +4365,12 @@ void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
++index;
}
d_ptr->siblingIndex = siblingIndex;
+ for (int i = 0; i < siblings->size(); ++i) {
+ int &index = siblings->at(i)->d_ptr->siblingIndex;
+ if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
+ siblings->at(i)->d_ptr->siblingOrderChange();
+ }
+ d_ptr->siblingOrderChange();
}
}
@@ -4977,6 +5052,7 @@ int QGraphicsItemPrivate::depth() const
/*!
\internal
*/
+#ifndef QT_NO_GRAPHICSEFFECT
void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
{
QGraphicsItemPrivate *itemPrivate = this;
@@ -4989,6 +5065,7 @@ void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
}
} while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
}
+#endif //QT_NO_GRAPHICSEFFECT
/*!
\internal
@@ -5293,6 +5370,16 @@ void QGraphicsItemPrivate::subFocusItemChange()
/*!
\internal
+ Subclasses can reimplement this function to be notified when its
+ siblingIndex order is changed.
+*/
+void QGraphicsItemPrivate::siblingOrderChange()
+{
+}
+
+/*!
+ \internal
+
Tells us if it is a proxy widget
*/
bool QGraphicsItemPrivate::isProxyWidget() const
@@ -5324,7 +5411,9 @@ void QGraphicsItem::update(const QRectF &rect)
return;
// Make sure we notify effects about invalidated source.
+#ifndef QT_NO_GRAPHICSEFFECT
d_ptr->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
if (CacheMode(d_ptr->cacheMode) != NoCache) {
// Invalidate cache.
@@ -10678,6 +10767,7 @@ int QGraphicsItemGroup::type() const
return Type;
}
+#ifndef QT_NO_GRAPHICSEFFECT
QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
{
const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
@@ -10817,6 +10907,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
return pixmap;
}
+#endif //QT_NO_GRAPHICSEFFECT
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, QGraphicsItem *item)
@@ -10940,6 +11031,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change)
case QGraphicsItem::ItemOpacityHasChanged:
str = "ItemOpacityHasChanged";
break;
+ case QGraphicsItem::ItemScenePositionHasChanged:
+ str = "ItemScenePositionHasChanged";
+ break;
}
debug << str;
return debug;
@@ -10997,6 +11091,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemIsFocusScope:
str = "ItemIsFocusScope";
break;
+ case QGraphicsItem::ItemSendsScenePositionChanges:
+ str = "ItemSendsScenePositionChanges";
+ break;
}
debug << str;
return debug;
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index f091e34..8bbe9f1 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -105,7 +105,8 @@ public:
ItemAcceptsInputMethod = 0x1000,
ItemNegativeZStacksBehindParent = 0x2000,
ItemIsPanel = 0x4000,
- ItemIsFocusScope = 0x8000 // internal
+ ItemIsFocusScope = 0x8000, // internal
+ ItemSendsScenePositionChanges = 0x10000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
@@ -137,7 +138,8 @@ public:
ItemZValueChange,
ItemZValueHasChanged,
ItemOpacityChange,
- ItemOpacityHasChanged
+ ItemOpacityHasChanged,
+ ItemScenePositionHasChanged
};
enum CacheMode {
@@ -225,9 +227,11 @@ public:
qreal effectiveOpacity() const;
void setOpacity(qreal opacity);
+#ifndef QT_NO_GRAPHICSEFFECT
// Effect
QGraphicsEffect *graphicsEffect() const;
void setGraphicsEffect(QGraphicsEffect *effect);
+#endif //QT_NO_GRAPHICSEFFECT
Qt::MouseButtons acceptedMouseButtons() const;
void setAcceptedMouseButtons(Qt::MouseButtons buttons);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 51d2ffd..afc2198 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -179,6 +179,7 @@ public:
holesInSiblingIndex(0),
sequentialOrdering(1),
updateDueToGraphicsEffect(0),
+ scenePosDescendants(0),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -223,7 +224,9 @@ public:
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
int depth() const;
+#ifndef QT_NO_GRAPHICSEFFECT
void invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
void invalidateDepthRecursively();
void resolveDepth();
void addChild(QGraphicsItem *child);
@@ -429,6 +432,8 @@ public:
inline void ensureSortedChildren();
static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
void ensureSequentialSiblingIndex();
+ inline void sendScenePosChange();
+ virtual void siblingOrderChange();
QPainterPath cachedClipPath;
QRectF childrenBoundingRect;
@@ -483,7 +488,7 @@ public:
// Packed 32 bits
quint32 fullUpdatePending : 1;
- quint32 flags : 16;
+ quint32 flags : 17;
quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
@@ -498,14 +503,15 @@ public:
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
quint32 notifyInvalidated : 1;
- quint32 mouseSetsFocus : 1;
// New 32 bits
+ quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
quint32 holesInSiblingIndex : 1;
quint32 sequentialOrdering : 1;
quint32 updateDueToGraphicsEffect : 1;
+ quint32 scenePosDescendants : 1;
// Optional stacking order
int globalStackingOrder;
@@ -577,6 +583,7 @@ struct QGraphicsItemPaintInfo
quint32 drawItem : 1;
};
+#ifndef QT_NO_GRAPHICSEFFECT
class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
{
public:
@@ -632,7 +639,7 @@ public:
QGraphicsItemPaintInfo *info;
QTransform lastEffectTransform;
};
-
+#endif //QT_NO_GRAPHICSEFFECT
/*!
Returns true if \a item1 is on top of \a item2.
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index dc036f8..d1845c2 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -294,6 +294,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
needSortTopLevelItems(true),
holesInTopLevelSiblingIndex(false),
topLevelSequentialOrdering(true),
+ scenePosDescendantsUpdatePending(false),
stickyFocus(false),
hasFocus(false),
focusItem(0),
@@ -488,6 +489,55 @@ void QGraphicsScenePrivate::_q_processDirtyItems()
/*!
\internal
+*/
+void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled)
+{
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ p->d_ptr->scenePosDescendants = enabled;
+ p = p->d_ptr->parent;
+ }
+ if (!enabled && !scenePosDescendantsUpdatePending) {
+ scenePosDescendantsUpdatePending = true;
+ QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection);
+ }
+}
+
+/*!
+ \internal
+*/
+void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item)
+{
+ scenePosItems.insert(item);
+ setScenePosItemEnabled(item, true);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item)
+{
+ scenePosItems.remove(item);
+ setScenePosItemEnabled(item, false);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsScenePrivate::_q_updateScenePosDescendants()
+{
+ foreach (QGraphicsItem *item, scenePosItems) {
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ p->d_ptr->scenePosDescendants = 1;
+ p = p->d_ptr->parent;
+ }
+ }
+ scenePosDescendantsUpdatePending = false;
+}
+
+/*!
+ \internal
Schedules an item for removal. This function leaves some stale indexes
around in the BSP tree if called from the item's destructor; these will
@@ -523,6 +573,9 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
}
+ if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
+ unregisterScenePosItem(item);
+
item->d_func()->scene = 0;
//We need to remove all children first because they might use their parent
@@ -2293,8 +2346,9 @@ void QGraphicsScene::clear()
// NB! We have to clear the index before deleting items; otherwise the
// index might try to access dangling item pointers.
d->index->clear();
- const QList<QGraphicsItem *> items = d->topLevelItems;
- qDeleteAll(items);
+ // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items
+ while (!d->topLevelItems.isEmpty())
+ delete d->topLevelItems.first();
Q_ASSERT(d->topLevelItems.isEmpty());
d->lastItemCount = 0;
d->allItemsIgnoreHoverEvents = true;
@@ -2540,6 +2594,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
}
}
+ if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
+ d->registerScenePosItem(item);
+
// Ensure that newly added items that have subfocus set, gain
// focus automatically if there isn't a focus item already.
if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
@@ -2826,18 +2883,20 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
}
/*!
- Returns the scene's current focus item, or 0 if no item currently has
- focus.
+ When the scene is active, this functions returns the scene's current focus
+ item, or 0 if no item currently has focus. When the scene is inactive, this
+ functions returns the item that will gain input focus when the scene becomes
+ active.
The focus item receives keyboard input when the scene receives a
key event.
- \sa setFocusItem(), QGraphicsItem::hasFocus()
+ \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive()
*/
QGraphicsItem *QGraphicsScene::focusItem() const
{
Q_D(const QGraphicsScene);
- return d->focusItem;
+ return isActive() ? d->focusItem : d->lastFocusItem;
}
/*!
@@ -4577,6 +4636,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (itemHasChildren && itemClipsChildrenToShape)
ENSURE_TRANSFORM_PTR;
+#ifndef QT_NO_GRAPHICSEFFECT
if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
ENSURE_TRANSFORM_PTR;
QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
@@ -4599,7 +4659,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
item->d_ptr->graphicsEffect->draw(painter, source);
painter->setWorldTransform(restoreTransform);
sourced->info = 0;
- } else {
+ } else
+#endif //QT_NO_GRAPHICSEFFECT
+ {
draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
effectTransform, wasDirtyParentSceneTransform, drawItem);
}
@@ -4768,10 +4830,12 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
QGraphicsItem *p = item->d_ptr->parent;
while (p) {
p->d_ptr->dirtyChildren = 1;
+#ifndef QT_NO_GRAPHICSEFFECT
if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
p->d_ptr->dirty = 1;
p->d_ptr->fullUpdatePending = 1;
}
+#endif //QT_NO_GRAPHICSEFFECT
p = p->d_ptr->parent;
}
}
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index d6d48d7..a47574e 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -299,6 +299,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated())
Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants())
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
friend class QGraphicsView;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index f8db084..fdec466 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -122,6 +122,13 @@ public:
void _q_processDirtyItems();
+ QSet<QGraphicsItem *> scenePosItems;
+ bool scenePosDescendantsUpdatePending;
+ void setScenePosItemEnabled(QGraphicsItem *item, bool enabled);
+ void registerScenePosItem(QGraphicsItem *item);
+ void unregisterScenePosItem(QGraphicsItem *item);
+ void _q_updateScenePosDescendants();
+
void removeItemHelper(QGraphicsItem *item);
QBrush backgroundBrush;
@@ -234,6 +241,7 @@ public:
item->d_ptr->fullUpdatePending = 0;
item->d_ptr->ignoreVisible = 0;
item->d_ptr->ignoreOpacity = 0;
+#ifndef QT_NO_GRAPHICSEFFECT
QGraphicsEffect::ChangeFlags flags;
if (item->d_ptr->notifyBoundingRectChanged) {
flags |= QGraphicsEffect::SourceBoundingRectChanged;
@@ -243,12 +251,15 @@ public:
flags |= QGraphicsEffect::SourceInvalidated;
item->d_ptr->notifyInvalidated = 0;
}
+#endif //QT_NO_GRAPHICSEFFECT
if (recursive) {
for (int i = 0; i < item->d_ptr->children.size(); ++i)
resetDirtyItem(item->d_ptr->children.at(i), recursive);
}
+#ifndef QT_NO_GRAPHICSEFFECT
if (flags && item->d_ptr->graphicsEffect)
item->d_ptr->graphicsEffect->sourceChanged(flags);
+#endif //QT_NO_GRAPHICSEFFECT
}
inline void ensureSortedTopLevelItems()
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index c88f678..87585a2 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -1512,6 +1512,11 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
this, SLOT(updateSceneRect(QRectF)));
d->scene->d_func()->removeView(this);
d->connectedToScene = false;
+
+ if (isActiveWindow() && isVisible()) {
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+ QApplication::sendEvent(d->scene, &windowDeactivate);
+ }
}
// Assign the new scene and update the contents (scrollbars, etc.)).
@@ -1533,6 +1538,11 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
// enable touch events if any items is interested in them
if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
+
+ if (isActiveWindow() && isVisible()) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ QApplication::sendEvent(d->scene, &windowActivate);
+ }
} else {
d->recalculateContentSize();
}
@@ -2638,6 +2648,19 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
QApplication::sendEvent(d->scene, event);
break;
+ case QEvent::Show:
+ if (d->scene && isActiveWindow()) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ QApplication::sendEvent(d->scene, &windowActivate);
+ }
+ break;
+ case QEvent::Hide:
+ // spontaneous event will generate a WindowDeactivate.
+ if (!event->spontaneous() && d->scene && isActiveWindow()) {
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+ QApplication::sendEvent(d->scene, &windowDeactivate);
+ }
+ break;
case QEvent::Leave:
// ### This is a temporary fix for until we get proper mouse grab
// events. activeMouseGrabberItem should be set to 0 if we lose the
@@ -3252,10 +3275,13 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Determine the exposed region
d->exposedRegion = event->region();
+ if (d->exposedRegion.isEmpty())
+ d->exposedRegion = viewport()->rect();
QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
QPainter painter(viewport());
+ painter.setClipRect(event->rect(), Qt::IntersectClip);
#ifndef QT_NO_RUBBERBAND
if (d->rubberBanding && !d->rubberBandRect.isEmpty())
painter.save();
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index d70a281..d9c65bb 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -318,6 +318,12 @@ void QGraphicsWidget::resize(const QSizeF &size)
*/
/*!
+ \property QGraphicsWidget::sizePolicy
+ \brief the size policy for the widget
+ \sa sizePolicy(), setSizePolicy(), QWidget::sizePolicy()
+*/
+
+/*!
\property QGraphicsWidget::geometry
\brief the geometry of the widget
@@ -410,6 +416,27 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
*/
/*!
+ \property QGraphicsWidget::minimumSize
+ \brief the minimum size of the widget
+
+ \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize
+*/
+
+/*!
+ \property QGraphicsWidget::preferredSize
+ \brief the preferred size of the widget
+
+ \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize
+*/
+
+/*!
+ \property QGraphicsWidget::maximumSize
+ \brief the maximum size of the widget
+
+ \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize
+*/
+
+/*!
Sets the widget's contents margins to \a left, \a top, \a right and \a
bottom.
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 9c71140..05d3a49 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -74,6 +74,10 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
Q_PROPERTY(QSizeF size READ size WRITE resize)
+ Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize)
+ Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize)
+ Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize)
+ Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy)
Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp
index 86b10b4..cd40f9e 100644
--- a/src/gui/graphicsview/qsimplex_p.cpp
+++ b/src/gui/graphicsview/qsimplex_p.cpp
@@ -288,7 +288,7 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
// original problem.
// Otherwise, we clean up our structures and report there is
// no feasible solution.
- if (valueAt(0, columns - 1) != 0.0) {
+ if ((valueAt(0, columns - 1) != 0.0) && (qAbs(valueAt(0, columns - 1)) > 0.00001)) {
qWarning() << "QSimplex: No feasible solution!";
clearDataStructures();
return false;
diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h
index 084ad7f..a5816d1 100644
--- a/src/gui/graphicsview/qsimplex_p.h
+++ b/src/gui/graphicsview/qsimplex_p.h
@@ -107,7 +107,7 @@ struct QSimplexConstraint
Q_ASSERT(constant > 0 || qFuzzyCompare(1, 1 + constant));
- if ((leftHandSide == constant) || qFuzzyCompare(1000 + leftHandSide, 1000 + constant))
+ if ((leftHandSide == constant) || qAbs(leftHandSide - constant) < 0.00000001)
return true;
switch (ratio) {
diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h
index 1531036..452aa75 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_p.h
+++ b/src/gui/inputmethod/qcoefepinputcontext_p.h
@@ -65,10 +65,10 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QCoeFepInputContext : public QInputContext,
- public MCoeFepAwareTextEditor,
- public MCoeFepAwareTextEditor_Extension1,
- public MObjectProvider
+class QCoeFepInputContext : public QInputContext,
+ public MCoeFepAwareTextEditor,
+ public MCoeFepAwareTextEditor_Extension1,
+ public MObjectProvider
{
Q_OBJECT
@@ -97,6 +97,7 @@ private:
void applyHints(Qt::InputMethodHints hints);
void applyFormat(QList<QInputMethodEvent::Attribute> *attributes);
void queueInputCapabilitiesChanged();
+ bool needsInputPanel();
private Q_SLOTS:
void ensureInputCapabilitiesChanged();
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
index 3f21bc3..25b2313 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -47,6 +47,7 @@
#include <private/qcore_symbian_p.h>
#include <fepitfr.h>
+#include <hal.h>
#include <limits.h>
// You only find these enumerations on SDK 5 onwards, so we need to provide our own
@@ -153,6 +154,44 @@ QString QCoeFepInputContext::language()
}
}
+bool QCoeFepInputContext::needsInputPanel()
+{
+ switch (QSysInfo::s60Version()) {
+ case QSysInfo::SV_S60_3_1:
+ case QSysInfo::SV_S60_3_2:
+ // There are no touch phones for pre-5.0 SDKs.
+ return false;
+#ifdef Q_CC_NOKIAX86
+ default:
+ // For emulator we assume that we need an input panel, since we can't
+ // separate between phone types.
+ return true;
+#else
+ case QSysInfo::SV_S60_5_0: {
+ // For SDK == 5.0, we need phone specific detection, since the HAL API
+ // is no good on most phones. However, all phones at the time of writing use the
+ // input panel, except N97 in landscape mode, but in this mode it refuses to bring
+ // up the panel anyway, so we don't have to care.
+ return true;
+ }
+ default:
+ // For unknown/newer types, we try to use the HAL API.
+ int keyboardEnabled;
+ int keyboardType;
+ int err[2];
+ err[0] = HAL::Get(HAL::EKeyboard, keyboardType);
+ err[1] = HAL::Get(HAL::EKeyboardState, keyboardEnabled);
+ if (err[0] == KErrNone && err[1] == KErrNone
+ && keyboardType != 0 && keyboardEnabled)
+ // Means that we have some sort of keyboard.
+ return false;
+
+ // Fall back to using the input panel.
+ return true;
+#endif // !Q_CC_NOKIAX86
+ }
+}
+
bool QCoeFepInputContext::filterEvent(const QEvent *event)
{
// The CloseSoftwareInputPanel event is not handled here, because the VK will automatically
@@ -174,10 +213,8 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
}
}
- // For pre-5.0 SDKs, we don't launch the keyboard.
- if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
+ if (!needsInputPanel())
return false;
- }
if (event->type() == QEvent::RequestSoftwareInputPanel) {
// Notify S60 that we want the virtual keyboard to show up.
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index d680af8..15db9a6 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -357,7 +357,7 @@ QListView::LayoutMode QListView::layoutMode() const
/*!
\property QListView::spacing
- \brief the space between items in the layout
+ \brief the space around the items in the layout
This property is the size of the empty space that is padded around
an item in the layout.
@@ -972,9 +972,9 @@ void QListView::paintEvent(QPaintEvent *e)
option.rect = visualRect(*it);
if (flow() == TopToBottom)
- option.rect.setWidth(qMin(viewport()->size().width(), option.rect.width()));
+ option.rect.setWidth(qMin(viewport()->size().width() - 2 * d->spacing(), option.rect.width()));
else
- option.rect.setHeight(qMin(viewport()->size().height(), option.rect.height()));
+ option.rect.setHeight(qMin(viewport()->size().height() - 2 * d->spacing(), option.rect.height()));
option.state = state;
if (selections && selections->isSelected(*it))
@@ -1837,14 +1837,14 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
{
horizontalScrollBar()->setSingleStep(step.width() + spacing());
horizontalScrollBar()->setPageStep(viewport()->width());
- horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width());
+ horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width() - 2 * spacing());
}
void QCommonListViewBase::updateVerticalScrollBar(const QSize &step)
{
verticalScrollBar()->setSingleStep(step.height() + spacing());
verticalScrollBar()->setPageStep(viewport()->height());
- verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height());
+ verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height() - 2 * spacing());
}
void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 3856293..a3cbc0d 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -2113,6 +2113,12 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
if (vi < 0)
vi = qMax(0, d->viewIndex(current));
+ if (isRightToLeft()) {
+ if (cursorAction == MoveRight)
+ cursorAction = MoveLeft;
+ else if (cursorAction == MoveLeft)
+ cursorAction = MoveRight;
+ }
switch (cursorAction) {
case MoveNext:
case MoveDown:
diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h
index aad5837..d58dea3 100644
--- a/src/gui/itemviews/qtreeview_p.h
+++ b/src/gui/itemviews/qtreeview_p.h
@@ -105,7 +105,7 @@ public:
int top() const { return startValue().toInt(); }
QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(top()); return rect; }
void updateCurrentValue(const QVariant &) { viewport->update(rect()); }
- void updateState(State, State state) { if (state == Stopped) before = after = QPixmap(); }
+ void updateState(State state, State) { if (state == Stopped) before = after = QPixmap(); }
} animatedOperation;
void prepareAnimatedOperation(int item, QVariantAnimation::Direction d);
void beginAnimatedOperation();
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 5f5650f..6f3cbaf 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -286,7 +286,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
Actions with a softkey role defined are only visible in the softkey bar when the widget containing
the action has focus. If no widget currently has focus, the softkey framework will traverse up the
- widget parent heirarchy looking for a widget containing softkey actions.
+ widget parent hierarchy looking for a widget containing softkey actions.
*/
/*!
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 8df4d08..992e4be 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -72,7 +72,7 @@
#include <private/qgraphicssystem_qws_p.h>
#endif
#ifdef Q_OS_SYMBIAN
-#include <w32std.h>
+#include <w32std.h>
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 1b0659a..5578a72 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -357,6 +357,9 @@ QSymbianControl::~QSymbianControl()
setFocusSafely(false);
S60->appUi()->RemoveFromStack(this);
delete m_longTapDetector;
+
+ if(m_previousEventLongTap)
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
}
void QSymbianControl::setWidget(QWidget *w)
@@ -866,6 +869,11 @@ void QSymbianControl::SizeChanged()
tlwExtra->inTopLevelResize = false;
}
}
+
+ // CCoeControl::SetExtent calls SizeChanged, but does not call
+ // PositionChanged, so we call it here to ensure that the widget's
+ // position is updated.
+ PositionChanged();
}
void QSymbianControl::PositionChanged()
@@ -1255,7 +1263,7 @@ bool QApplicationPrivate::modalState()
void QApplicationPrivate::enterModal_sys(QWidget *widget)
{
if (widget) {
- widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue);
+ static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
// Modal partial screen dialogs (like queries) capture pointer events.
// ### FixMe: Add specialized behaviour for fullscreen modal dialogs
widget->effectiveWinId()->SetGloballyCapturing(ETrue);
@@ -1270,7 +1278,7 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget)
void QApplicationPrivate::leaveModal_sys(QWidget *widget)
{
if (widget) {
- widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse);
+ static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
// ### FixMe: Add specialized behaviour for fullscreen modal dialogs
widget->effectiveWinId()->SetGloballyCapturing(EFalse);
widget->effectiveWinId()->SetPointerCapture(EFalse);
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 2a6e286..3d4bb8c 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -181,8 +181,10 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni
return 0;
} else if (QGesture *g = qobject_cast<QGesture *>(object)) {
return g;
+#ifndef QT_NO_GRAPHICSVIEW
} else {
Q_ASSERT(qobject_cast<QGraphicsObject *>(object));
+#endif
}
QList<QGesture *> states =
diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp
index 21795b4..ecad72f 100644
--- a/src/gui/kernel/qsoftkeymanager.cpp
+++ b/src/gui/kernel/qsoftkeymanager.cpp
@@ -137,12 +137,14 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act
*/
QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget)
{
+#ifndef QT_NO_ACTION
QScopedPointer<QAction> action(createAction(standardKey, actionWidget));
connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent()));
connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*)));
QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key);
return action.take();
+#endif //QT_NO_ACTION
}
void QSoftKeyManager::cleanupHash(QObject* obj)
@@ -175,6 +177,7 @@ void QSoftKeyManager::updateSoftKeys()
bool QSoftKeyManager::event(QEvent *e)
{
+#ifndef QT_NO_ACTION
if (e->type() == QEvent::UpdateSoftKeys) {
QList<QAction*> softKeys;
QWidget *source = QApplication::focusWidget();
@@ -197,10 +200,10 @@ bool QSoftKeyManager::event(QEvent *e)
} while (source);
QSoftKeyManagerPrivate::softKeySource = source;
- if (source)
- QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys);
+ QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys);
return true;
}
+#endif //QT_NO_ACTION
return false;
}
@@ -247,7 +250,10 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys)
}
}
- Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource->window()->windowType();
+ const Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource
+ ? QSoftKeyManagerPrivate::softKeySource->window()->windowType()
+ : Qt::Widget;
+
if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup)
QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit"))));
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index 789d89e..3405bcf 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -73,6 +73,7 @@
#include <akntitle.h> // CAknTitlePane
#include <akncontext.h> // CAknContextPane
#include <eikspane.h> // CEikStatusPane
+#include <aknpopupfader.h> // MAknFadedComponent and TAknPopupFader
#endif
QT_BEGIN_NAMESPACE
@@ -114,7 +115,7 @@ public:
int supportsPremultipliedAlpha : 1;
QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
static inline void updateScreenSize();
- static inline RWsSession& wsSession();
+ static inline RWsSession& wsSession();
static inline RWindowGroup& windowGroup();
static inline CWsScreenDevice* screenDevice();
static inline CCoeAppUi* appUi();
@@ -140,7 +141,11 @@ public:
};
class QLongTapTimer;
+
class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver
+#ifdef Q_WS_S60
+, public MAknFadedComponent
+#endif
{
public:
DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII.
@@ -165,6 +170,17 @@ public:
void setFocusSafely(bool focus);
+#ifdef Q_WS_S60
+ void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); }
+
+protected: // from MAknFadedComponent
+ TInt CountFadedComponents() {return 1;}
+ CCoeControl* FadedComponent(TInt aIndex) {return this;}
+#else
+ #warning No fallback implementation for QSymbianControl::FadeBehindPopup
+ void FadeBehindPopup(bool /*fade*/){ }
+#endif
+
protected:
void Draw(const TRect& aRect) const;
void SizeChanged();
@@ -189,6 +205,11 @@ private:
bool m_ignoreFocusChanged;
QLongTapTimer* m_longTapDetector;
bool m_previousEventLongTap;
+
+#ifdef Q_WS_S60
+ // Fader object used to fade everything except this menu and the CBA.
+ TAknPopupFader popupFader;
+#endif
};
inline QS60Data::QS60Data()
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 271b939..f856b13 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -900,7 +900,7 @@ void QWidget::setAutoFillBackground(bool enabled)
passing a \c QAction with a softkey role set on it. When the widget
containing the softkey actions has focus, its softkeys should appear in
the user interface. Softkeys are discovered by traversing the widget
- heirarchy so it is possible to define a single set of softkeys that are
+ hierarchy so it is possible to define a single set of softkeys that are
present at all times by calling addAction() for a given top level widget.
On some platforms, this concept overlaps with \c QMenuBar such that if no
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index a6d8ed7..88cd63d 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -434,8 +434,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
drawableWindow->PointerFilter(EPointerFilterEnterExit
| EPointerFilterMove | EPointerFilterDrag, 0);
- if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) {
activateSymbianWindow(control.data());
+ control->MakeVisible(true);
+ }
// We wait until the control is fully constructed before calling setWinId, because
// this generates a WinIdChanged event.
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 87f1cad..566e18c 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -677,7 +677,11 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const
QWidget *parentWindow = window();
QWExtra *extra = parentWindow->d_func()->extra;
if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
- || (extra && extra->proxyWidget)) {
+ || (extra
+#ifndef QT_NO_GRAPHICSVIEW
+ && extra->proxyWidget
+#endif //QT_NO_GRAPHICSVIEW
+ )) {
if (extra && extra->topextra && extra->topextra->embedded) {
QPoint pt = mapTo(parentWindow, pos);
POINT p = {pt.x(), pt.y()};
@@ -704,7 +708,11 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const
QWidget *parentWindow = window();
QWExtra *extra = parentWindow->d_func()->extra;
if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
- || (extra && extra->proxyWidget)) {
+ || (extra
+#ifndef QT_NO_GRAPHICSVIEW
+ && extra->proxyWidget
+#endif //QT_NO_GRAPHICSVIEW
+ )) {
if (extra && extra->topextra && extra->topextra->embedded) {
POINT p = {pos.x(), pos.y()};
ScreenToClient(parentWindow->effectiveWinId(), &p);
@@ -1331,8 +1339,15 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
ValidateRgn(q->internalWinId(), 0);
+#ifdef Q_WS_WINCE
+ // On Windows CE we can't just fiddle around with the window state.
+ // Too much magic in setWindowState.
+ if (isResize && q->isMaximized())
+ q->setWindowState(q->windowState() & ~Qt::WindowMaximized);
+#else
if (isResize)
data.window_state &= ~Qt::WindowMaximized;
+#endif
if (data.window_state & Qt::WindowFullScreen) {
QTLWExtra *top = topData();
@@ -2046,6 +2061,7 @@ void QWidgetPrivate::winSetupGestures()
bool needv = false;
bool singleFingerPanEnabled = false;
+#ifndef QT_NO_SCROLLAREA
if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) {
QScrollBar *hbar = asa->horizontalScrollBar();
QScrollBar *vbar = asa->verticalScrollBar();
@@ -2061,6 +2077,7 @@ void QWidgetPrivate::winSetupGestures()
winid = q->winId(); // enforces the native winid on the viewport
}
}
+#endif //QT_NO_SCROLLAREA
if (winid) {
GESTURECONFIG gc[1];
memset(gc, 0, sizeof(gc));
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
index 1de5ffa..4f7806f 100644
--- a/src/gui/statemachine/qguistatemachine.cpp
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -106,8 +106,10 @@ static QEvent *cloneEvent(QEvent *e)
return new QEvent(*e);
case QEvent::HideToParent:
return new QEvent(*e);
+#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
return new QWheelEvent(*static_cast<QWheelEvent*>(e));
+#endif //QT_NO_WHEELEVENT
case QEvent::WindowTitleChange:
return new QEvent(*e);
case QEvent::WindowIconChange:
@@ -190,8 +192,10 @@ static QEvent *cloneEvent(QEvent *e)
return new QInputMethodEvent(*static_cast<QInputMethodEvent*>(e));
case QEvent::AccessibilityPrepare:
return new QEvent(*e);
+#ifndef QT_NO_TABLETEVENT
case QEvent::TabletMove:
return new QTabletEvent(*static_cast<QTabletEvent*>(e));
+#endif //QT_NO_TABLETEVENT
case QEvent::LocaleChange:
return new QEvent(*e);
case QEvent::LanguageChange:
@@ -200,10 +204,12 @@ static QEvent *cloneEvent(QEvent *e)
return new QEvent(*e);
case QEvent::Style:
return new QEvent(*e);
+#ifndef QT_NO_TABLETEVENT
case QEvent::TabletPress:
return new QTabletEvent(*static_cast<QTabletEvent*>(e));
case QEvent::TabletRelease:
return new QTabletEvent(*static_cast<QTabletEvent*>(e));
+#endif //QT_NO_TABLETEVENT
case QEvent::OkRequest:
return new QEvent(*e);
case QEvent::HelpRequest:
@@ -238,8 +244,10 @@ static QEvent *cloneEvent(QEvent *e)
return new QHelpEvent(*static_cast<QHelpEvent*>(e));
case QEvent::WhatsThis:
return new QHelpEvent(*static_cast<QHelpEvent*>(e));
+#ifndef QT_NO_STATUSTIP
case QEvent::StatusTip:
return new QStatusTipEvent(*static_cast<QStatusTipEvent*>(e));
+#endif //QT_NO_STATUSTIP
#ifndef QT_NO_ACTION
case QEvent::ActionChanged:
case QEvent::ActionAdded:
@@ -249,8 +257,10 @@ static QEvent *cloneEvent(QEvent *e)
case QEvent::FileOpen:
return new QFileOpenEvent(*static_cast<QFileOpenEvent*>(e));
+#ifndef QT_NO_SHORTCUT
case QEvent::Shortcut:
return new QShortcutEvent(*static_cast<QShortcutEvent*>(e));
+#endif //QT_NO_SHORTCUT
case QEvent::ShortcutOverride:
return new QKeyEvent(*static_cast<QKeyEvent*>(e));
@@ -263,11 +273,15 @@ static QEvent *cloneEvent(QEvent *e)
break;
#endif
+#ifndef QT_NO_WHATSTHIS
case QEvent::WhatsThisClicked:
return new QWhatsThisClickedEvent(*static_cast<QWhatsThisClickedEvent*>(e));
+#endif //QT_NO_WHATSTHIS
+#ifndef QT_NO_TOOLBAR
case QEvent::ToolBarChange:
return new QToolBarChangeEvent(*static_cast<QToolBarChangeEvent*>(e));
+#endif //QT_NO_TOOLBAR
case QEvent::ApplicationActivate:
return new QEvent(*e);
@@ -397,9 +411,11 @@ static QEvent *cloneEvent(QEvent *e)
case QEvent::DynamicPropertyChange:
return new QDynamicPropertyChangeEvent(*static_cast<QDynamicPropertyChangeEvent*>(e));
+#ifndef QT_NO_TABLETEVENT
case QEvent::TabletEnterProximity:
case QEvent::TabletLeaveProximity:
return new QTabletEvent(*static_cast<QTabletEvent*>(e));
+#endif //QT_NO_TABLETEVENT
case QEvent::NonClientAreaMouseMove:
case QEvent::NonClientAreaMouseButtonPress:
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index 350a8e6..e0fcb92 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -281,7 +281,7 @@ void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth);
break;
case SE_Editor:
- drawFrame(SF_Editor, painter, rect, flags | SF_PointNorth);
+ drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth);
break;
default:
break;
@@ -831,6 +831,11 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag
pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio);
break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
+ result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ break;
+
case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
@@ -1676,18 +1681,18 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
text_flags |= Qt::TextHideMnemonic;
- QRect iconRect =
- subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
- QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
-
if ((option->state & State_Selected) && (option->state & State_Enabled))
QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
+ QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
+ QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
+
//todo: move the vertical spacing stuff into subElementRect
const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing);
if (checkable){
+ const int hSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
QStyleOptionMenuItem optionCheckBox;
- optionCheckBox.QStyleOption::operator=(*menuItem);
+ optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem);
optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
const int moveByX = optionCheckBox.rect.width()+vSpacing;
@@ -1696,6 +1701,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
iconRect.translate(moveByX, 0);
iconRect.setWidth(iconRect.width()+vSpacing);
textRect.setWidth(textRect.width()-moveByX-vSpacing);
+ optionCheckBox.rect.translate(vSpacing/2, hSpacing/2);
} else {
textRect.setWidth(textRect.width()-moveByX);
iconRect.setWidth(iconRect.width()+vSpacing);
@@ -2292,8 +2298,18 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
{
QSize sz(csz);
switch (ct) {
+ case CT_ToolButton:
+ sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ //FIXME properly - style should calculate the location of border frame-part
+ sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin));
+ if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(opt))
+ if (toolBtn->subControls & SC_ToolButtonMenu)
+ sz += QSize(pixelMetric(PM_MenuButtonIndicator),0);
+ break;
case CT_PushButton:
sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ //FIXME properly - style should calculate the location of border frame-part
+ sz += QSize(2*pixelMetric(PM_ButtonMargin), 2*pixelMetric(PM_ButtonMargin));
if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget)))
if (buttonWidget->isCheckable())
sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0);
@@ -2572,8 +2588,8 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
break;
case CC_ToolButton:
if (const QStyleOptionToolButton *toolButton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
- const int indicatorRect = pixelMetric(PM_MenuButtonIndicator, toolButton, widget) +
- 2*pixelMetric(PM_ButtonMargin, toolButton, widget);
+ const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2*pixelMetric(PM_ButtonMargin);
+ const int border = pixelMetric(PM_ButtonMargin) + pixelMetric(PM_DefaultFrameWidth);
ret = toolButton->rect;
const bool popup = (toolButton->features &
(QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
@@ -2585,7 +2601,7 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
break;
case SC_ToolButtonMenu:
if (popup)
- ret.adjust(ret.width() - indicatorRect, ret.height() - indicatorRect, 0, 0);
+ ret.adjust(ret.width() - indicatorRect, border, -pixelMetric(PM_ButtonMargin), -border);
break;
default:
break;
@@ -2607,8 +2623,8 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
QRect ret;
switch (element) {
case SE_LineEditContents: {
- // in S60 the input text box doesn't start from line Edit's TL, but
- // a bit indented.
+ // in S60 the input text box doesn't start from line Edit's TL, but
+ // a bit indented.
QRect lineEditRect = opt->rect;
const int adjustment = opt->rect.height()>>2;
lineEditRect.adjust(adjustment,0,0,0);
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
index 54af757..46547bf 100644
--- a/src/gui/styles/qs60style_p.h
+++ b/src/gui/styles/qs60style_p.h
@@ -361,7 +361,6 @@ public:
SF_ToolBarButtonPressed,
SF_PanelBackground,
SF_ButtonInactive,
- SF_Editor,
};
enum SkinElementFlag {
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 0cd87bd..c2a207c 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -319,16 +319,6 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = {
/* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b8},
/* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b9},
- /* SP_QsnFrNotepadCornerTl */ {KAknsIIDQsnFrNotepadContCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadCornerTr */ {KAknsIIDQsnFrNotepadContCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadCornerBl */ {KAknsIIDQsnFrNotepadCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadCornerBr */ {KAknsIIDQsnFrNotepadCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadSideT */ {KAknsIIDQsnFrNotepadContSideT, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadSideB */ {KAknsIIDQsnFrNotepadSideB, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadSideL */ {KAknsIIDQsnFrNotepadSideL, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadSideR */ {KAknsIIDQsnFrNotepadSideR, ENoDraw, ES60_AllReleases, -1,-1},
- /* SP_QsnFrNotepadCenter */ {KAknsIIDQsnFrNotepadCenter, EDrawIcon, ES60_AllReleases, -1,-1},
-
};
QPixmap QS60StyleModeSpecifics::skinnedGraphics(
@@ -852,10 +842,6 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme
centerId.Set(KAknsIIDNone);
frameId.Set(KAknsIIDQsnFrSetOpt);
break;
- case QS60StylePrivate::SF_Editor:
- centerId.Set(KAknsIIDQsnFrNotepadCenter);
- frameId.Set(KAknsIIDQsnFrNotepadCont);
- break;
default:
// center should be correct here
frameId.iMinor = centerId.iMinor - 9;
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index ae1d33a..ce73fd8 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -3325,9 +3325,14 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
break;
case CE_PushButton:
- ParentStyle::drawControl(ce, opt, p, w);
- return;
-
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
+ if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() ||
+ ((btn->features & QStyleOptionButton::HasMenu) && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator))) {
+ ParentStyle::drawControl(ce, opt, p, w);
+ return;
+ }
+ }
+ break;
case CE_PushButtonBevel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QStyleOptionButton btnOpt(*btn);
@@ -3370,7 +3375,9 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (rule.hasPosition() && rule.position()->textAlignment != 0) {
Qt::Alignment textAlignment = rule.position()->textAlignment;
QRect textRect = button->rect;
- uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
+ uint tf = Qt::TextShowMnemonic;
+ const uint verticalAlignMask = Qt::AlignVCenter | Qt::AlignTop | Qt::AlignLeft;
+ tf |= (textAlignment & verticalAlignMask) ? (textAlignment & verticalAlignMask) : Qt::AlignVCenter;
if (!styleHint(SH_UnderlineShortcut, button, w))
tf |= Qt::TextHideMnemonic;
if (!button->icon.isNull()) {
@@ -3599,6 +3606,27 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
}
} else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
QWindowsStyle::drawControl(ce, &mi, p, w);
+ if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) {
+ // We have a style defined, but QWindowsStyle won't draw anything if not checked.
+ // So we mimick what QWindowsStyle would do.
+ int checkcol = qMax<int>(mi.maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth);
+ QRect vCheckRect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x(), mi.rect.y(), checkcol, mi.rect.height()));
+ if (mi.state.testFlag(State_Enabled) && mi.state.testFlag(State_Selected)) {
+ qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &mi.palette.brush(QPalette::Button));
+ } else {
+ QBrush fill(mi.palette.light().color(), Qt::Dense4Pattern);
+ qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &fill);
+ }
+ QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ if (subSubRule.hasDrawable()) {
+ QStyleOptionMenuItem newMi(mi);
+ newMi.rect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x() + QWindowsStylePrivate::windowsItemFrame,
+ mi.rect.y() + QWindowsStylePrivate::windowsItemFrame,
+ checkcol - 2 * QWindowsStylePrivate::windowsItemFrame,
+ mi.rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame));
+ drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
+ }
+ }
} else {
if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
mi.palette.setColor(QPalette::Window, Qt::transparent);
@@ -3668,7 +3696,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
}
if (!cb->currentText.isEmpty() && !cb->editable) {
drawItemText(p, editRect.adjusted(0, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->palette,
- cb->state & State_Enabled, cb->currentText);
+ cb->state & State_Enabled, cb->currentText, QPalette::Text);
}
p->restore();
return;
@@ -4275,23 +4303,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
p->fillRect(v2->rect, v2->palette.alternateBase());
subRule.drawRule(p, opt->rect);
} else {
- QStyleOptionViewItemV2 v2Copy(*v2);
- if (v2->showDecorationSelected) {
- QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ViewItem);
- if (v2->state & QStyle::State_Selected) {
- subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::Highlight);
- } else if (v2->features & QStyleOptionViewItemV2::Alternate) {
- subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase);
- } else if (subRule2.hasBackground()) {
- p->fillRect(v2->rect, subRule2.background()->brush);
- }
- } else if (v2->features & QStyleOptionViewItemV2::Alternate) {
- quint64 pc = v2->state & QStyle::State_Enabled ? PseudoClass_Enabled : PseudoClass_Disabled;
- pc |= PseudoClass_Alternate;
- QRenderRule subRule2 = renderRule(w, PseudoElement_ViewItem, pc);
- subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase);
- }
- baseStyle()->drawPrimitive(pe, &v2Copy, p, w);
+ baseStyle()->drawPrimitive(pe, v2, p, w);
}
}
return;
@@ -4356,18 +4368,6 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
break;
case PE_PanelItemViewItem:
- if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) {
- rect = subElementRect(QStyle::SE_ItemViewItemText, opt, w)
- | subElementRect(QStyle::SE_ItemViewItemDecoration, opt, w)
- | subElementRect(QStyle::SE_ItemViewItemCheckIndicator, opt, w);
- }
- pseudoElement = PseudoElement_ViewItem;
- break;
-
- case PE_PanelItemViewRow:
- ParentStyle::drawPrimitive(pe, opt, p, w);
- if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w))
- return;
pseudoElement = PseudoElement_ViewItem;
break;
diff --git a/src/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp
index 406633e..f79f8e0 100644
--- a/src/gui/styles/qstylesheetstyle_default.cpp
+++ b/src/gui/styles/qstylesheetstyle_default.cpp
@@ -203,49 +203,6 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
ADD_STYLE_RULE;
}
- /*QLineEdit[style="QCleanlooksStyle"] {
- padding-top: 2px;
- padding-bottom: 2px;
- }*/
- if (baseStyle()->inherits("QCleanlooksStyle"))
- {
- SET_ELEMENT_NAME(QLatin1String("QLineEdit"));
- ADD_BASIC_SELECTOR;
- ADD_SELECTOR;
-
-
- SET_PROPERTY(QLatin1String("padding-top"), PaddingTop);
- ADD_VALUE(Value::Identifier, QString::fromLatin1("2px"));
- ADD_DECLARATION;
-
- SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom);
- ADD_VALUE(Value::Identifier, QString::fromLatin1("2px"));
- ADD_DECLARATION;
-
- ADD_STYLE_RULE;
- }
-
- /*QLineEdit[style="QWindowsXPStyle"],
- QLineEdit[style="QWindowsVistaStyle"],
- QLineEdit[style="QGtkStyle"] {
- padding-top: 1px;
- padding-bottom: 1px;
- }*/
- if (baseStyle()->inherits("QWindowsXPStyle") || baseStyle()->inherits("QGtkStyle"))
- {
- SET_ELEMENT_NAME(QLatin1String("QLineEdit"));
-
- SET_PROPERTY(QLatin1String("padding-top"), PaddingTop);
- ADD_VALUE(Value::Identifier, QString::fromLatin1("1px"));
- ADD_DECLARATION;
-
- SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom);
- ADD_VALUE(Value::Identifier, QString::fromLatin1("1px"));
- ADD_DECLARATION;
-
- ADD_STYLE_RULE;
- }
-
/*QFrame {
border: native;
}*/
diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp
index 7ed187f..86ba947 100644
--- a/src/gui/styles/qwindowsmobilestyle.cpp
+++ b/src/gui/styles/qwindowsmobilestyle.cpp
@@ -4121,6 +4121,7 @@ void QWindowsMobileStylePrivate::setupWindowsMobileStyle65()
void QWindowsMobileStylePrivate::drawTabBarTab(QPainter *painter, const QStyleOptionTab *tab)
{
+#ifndef QT_NO_TABBAR
#ifdef Q_WS_WINCE_WM
if (wm65) {
tintImagesButton(tab->palette.button().color());
@@ -4207,6 +4208,7 @@ void QWindowsMobileStylePrivate::drawTabBarTab(QPainter *painter, const QStyleOp
}
}
painter->restore();
+#endif //QT_NO_TABBAR
}
void QWindowsMobileStylePrivate::drawPanelItemViewSelected(QPainter *painter, const QStyleOptionViewItemV4 *option, QRect rect)
@@ -4412,7 +4414,7 @@ void QWindowsMobileStylePrivate::drawScrollbarHandleUp(QPainter *p, QStyleOption
void QWindowsMobileStylePrivate::drawScrollbarHandleDown(QPainter *p, QStyleOptionSlider *opt, bool completeFrame, bool secondScrollBar)
{
-
+#ifndef QT_NO_SCROLLBAR
#ifdef Q_WS_WINCE_WM
if (wm65) {
tintImagesHigh(opt->palette.highlight().color());
@@ -4469,10 +4471,12 @@ void QWindowsMobileStylePrivate::drawScrollbarHandleDown(QPainter *p, QStyleOpti
arrowOpt.rect.adjust(1, 0, 1, 0);
q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p, 0);
}
+#endif //QT_NO_SCROLLBAR
}
void QWindowsMobileStylePrivate::drawScrollbarGroove(QPainter *p,const QStyleOptionSlider *opt)
{
+#ifndef QT_NO_SCROLLBAR
#ifdef Q_OS_WINCE_WM
if (wm65) {
p->fillRect(opt->rect, QColor(231, 231, 231));
@@ -4498,6 +4502,7 @@ void QWindowsMobileStylePrivate::drawScrollbarGroove(QPainter *p,const QStyleOpt
fill = opt->palette.light();
}
p->fillRect(opt->rect, fill);
+#endif //QT_NO_SCROLLBAR
}
QWindowsMobileStyle::QWindowsMobileStyle(QWindowsMobileStylePrivate &dd) : QWindowsStyle(dd) {
@@ -6325,16 +6330,20 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
switch (type) {
case CT_PushButton:
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- newSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
+ newSize = QCommonStyle::sizeFromContents(type, option, size, widget);
int w = newSize.width(),
h = newSize.height();
int defwidth = 0;
if (button->features & QStyleOptionButton::AutoDefaultButton)
defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, button, widget);
- if (w < 75 + defwidth && button->icon.isNull())
- w = 75 + defwidth;
- if (h < 23 + defwidth)
- h = 23 + defwidth;
+
+ int minwidth = int(QStyleHelper::dpiScaled(55.0f));
+ int minheight = int(QStyleHelper::dpiScaled(19.0f));
+
+ if (w < minwidth + defwidth && button->icon.isNull())
+ w = minwidth + defwidth;
+ if (h < minheight + defwidth)
+ h = minheight + defwidth;
newSize = QSize(w + 4, h + 4);
}
break;
diff --git a/src/gui/styles/qwindowsmobilestyle_p.h b/src/gui/styles/qwindowsmobilestyle_p.h
index 1e8c7ff..139a4ab 100644
--- a/src/gui/styles/qwindowsmobilestyle_p.h
+++ b/src/gui/styles/qwindowsmobilestyle_p.h
@@ -60,6 +60,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_STYLE_WINDOWSMOBILE
+class QStyleOptionTab;
+class QStyleOptionSlider;
+class QStyleOptionViewItemV4;
+
class QWindowsMobileStylePrivate : public QWindowsStylePrivate
{
Q_DECLARE_PUBLIC(QWindowsMobileStyle)
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 5cf738e..f894b82 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -115,14 +115,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include <limits.h>
QT_END_INCLUDE_NAMESPACE
-static const int windowsItemFrame = 2; // menu item frame width
-static const int windowsSepHeight = 9; // separator item height
-static const int windowsItemHMargin = 3; // menu item hor text margin
-static const int windowsItemVMargin = 2; // menu item ver text margin
-static const int windowsArrowHMargin = 6; // arrow horizontal margin
-static const int windowsRightBorder = 15; // right border on windows
-static const int windowsCheckMarkWidth = 12; // checkmarks width on windows
-
enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight };
/*
@@ -1847,7 +1839,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
bool act = menuitem->state & State_Selected;
// windows always has a check column, regardless whether we have an icon or not
- int checkcol = qMax(menuitem->maxIconWidth, windowsCheckMarkWidth);
+ int checkcol = qMax<int>(menuitem->maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth);
QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button);
p->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill);
@@ -1903,8 +1895,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
newMi.state |= State_Enabled;
if (act)
newMi.state |= State_On;
- newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame,
- checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame));
+ newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + QWindowsStylePrivate::windowsItemFrame,
+ menuitem->rect.y() + QWindowsStylePrivate::windowsItemFrame,
+ checkcol - 2 * QWindowsStylePrivate::windowsItemFrame,
+ menuitem->rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame));
proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
}
p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
@@ -1915,9 +1909,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setPen(discol);
}
- int xm = windowsItemFrame + checkcol + windowsItemHMargin;
+ int xm = QWindowsStylePrivate::windowsItemFrame + checkcol + QWindowsStylePrivate::windowsItemHMargin;
int xpos = menuitem->rect.x() + xm;
- QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
+ QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin,
+ w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin);
QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
QString s = menuitem->text;
if (!s.isEmpty()) { // draw text
@@ -1951,10 +1946,10 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->restore();
}
if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
- int dim = (h - 2 * windowsItemFrame) / 2;
+ int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2;
PrimitiveElement arrow;
arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
- xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim;
+ xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim;
QRect vSubMenuRect = visualRect(opt->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
QStyleOptionMenuItem newMI = *menuitem;
newMI.rect = vSubMenuRect;
@@ -2994,6 +2989,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
#ifndef QT_NO_COMBOBOX
case CC_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
+ p->save();
QBrush editBrush = cmb->palette.brush(QPalette::Base);
if ((cmb->subControls & SC_ComboBoxFrame)) {
if (cmb->frame) {
@@ -3063,6 +3059,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
}
}
+ p->restore();
}
break;
#endif // QT_NO_COMBOBOX
@@ -3191,7 +3188,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget);
if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
- sz = QSize(10, windowsSepHeight);
+ sz = QSize(10, QWindowsStylePrivate::windowsSepHeight);
}
else if (mi->icon.isNull()) {
sz.setHeight(sz.height() - 2);
@@ -3202,14 +3199,14 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
sz.setHeight(qMax(sz.height(),
mi->icon.actualSize(QSize(iconExtent, iconExtent)).height()
- + 2 * windowsItemFrame));
+ + 2 * QWindowsStylePrivate::windowsItemFrame));
}
int maxpmw = mi->maxIconWidth;
int tabSpacing = 20;
if (mi->text.contains(QLatin1Char('\t')))
w += tabSpacing;
else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
- w += 2 * windowsArrowHMargin;
+ w += 2 * QWindowsStylePrivate::windowsArrowHMargin;
else if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem) {
// adjust the font and add the difference in size.
// it would be better if the font could be adjusted in the initStyleOption qmenu func!!
@@ -3220,9 +3217,9 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
w += fmBold.width(mi->text) - fm.width(mi->text);
}
- int checkcol = qMax(maxpmw, windowsCheckMarkWidth); // Windows always shows a check column
+ int checkcol = qMax<int>(maxpmw, QWindowsStylePrivate::windowsCheckMarkWidth); // Windows always shows a check column
w += checkcol;
- w += windowsRightBorder + 10;
+ w += QWindowsStylePrivate::windowsRightBorder + 10;
sz.setWidth(w);
}
break;
@@ -3230,7 +3227,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#ifndef QT_NO_MENUBAR
case CT_MenuBarItem:
if (!sz.isEmpty())
- sz += QSize(windowsItemHMargin * 4, windowsItemVMargin * 2);
+ sz += QSize(QWindowsStylePrivate::windowsItemHMargin * 4, QWindowsStylePrivate::windowsItemVMargin * 2);
break;
#endif
// Otherwise, fall through
diff --git a/src/gui/styles/qwindowsstyle_p.h b/src/gui/styles/qwindowsstyle_p.h
index fb84dce..d81c82b 100644
--- a/src/gui/styles/qwindowsstyle_p.h
+++ b/src/gui/styles/qwindowsstyle_p.h
@@ -87,7 +87,17 @@ public:
QColor activeGradientCaptionColor;
QColor inactiveCaptionColor;
QColor inactiveGradientCaptionColor;
+
+ enum {
+ windowsItemFrame = 2, // menu item frame width
+ windowsSepHeight = 9, // separator item height
+ windowsItemHMargin = 3, // menu item hor text margin
+ windowsItemVMargin = 2, // menu item ver text margin
+ windowsArrowHMargin = 6, // arrow horizontal margin
+ windowsRightBorder = 15, // right border on windows
+ windowsCheckMarkWidth = 12 // checkmarks width on windows
};
+};
QT_END_NAMESPACE
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 6db86bd..93b9fc6 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -1129,19 +1129,22 @@ static bool setFontWeightFromValue(const Value &value, QFont *font)
static bool setFontFamilyFromValues(const QVector<Value> &values, QFont *font, int start = 0)
{
QString family;
+ bool shouldAddSpace = false;
for (int i = start; i < values.count(); ++i) {
const Value &v = values.at(i);
if (v.type == Value::TermOperatorComma) {
family += QLatin1Char(',');
+ shouldAddSpace = false;
continue;
}
const QString str = v.variant.toString();
if (str.isEmpty())
break;
+ if (shouldAddSpace)
+ family += QLatin1Char(' ');
family += str;
- family += QLatin1Char(' ');
+ shouldAddSpace = true;
}
- family = family.simplified();
if (family.isEmpty())
return false;
font->setFamily(family);
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 9497b6f..2bfe33c 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -911,7 +911,7 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte
break;
case QEvent::MouseButtonPress: {
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
- d->mousePressEvent(ev->button(), matrix.map(ev->pos()), ev->modifiers(),
+ d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(),
ev->buttons(), ev->globalPos());
break; }
case QEvent::MouseMove: {
@@ -979,7 +979,7 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte
#ifndef QT_NO_GRAPHICSVIEW
case QEvent::GraphicsSceneMousePress: {
QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e);
- d->mousePressEvent(ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
+ d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
ev->screenPos());
break; }
case QEvent::GraphicsSceneMouseMove: {
@@ -1296,7 +1296,9 @@ QVariant QTextControl::loadResource(int type, const QUrl &name)
void QTextControlPrivate::_q_updateBlock(const QTextBlock &block)
{
Q_Q(QTextControl);
- emit q->updateRequest(q->blockBoundingRect(block));
+ QRectF br = q->blockBoundingRect(block);
+ br.setRight(qreal(INT_MAX)); // the block might have shrunk
+ emit q->updateRequest(br);
}
QRectF QTextControlPrivate::rectForPosition(int position) const
@@ -1465,7 +1467,7 @@ QRectF QTextControl::selectionRect() const
return selectionRect(d->cursor);
}
-void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers,
+void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers,
Qt::MouseButtons buttons, const QPoint &globalPos)
{
Q_Q(QTextControl);
@@ -1479,11 +1481,11 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF
cursor.clearSelection();
}
}
- if (!(button & Qt::LeftButton))
- return;
-
- if (!((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable)))
- return;
+ if (!(button & Qt::LeftButton) ||
+ !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
+ e->ignore();
+ return;
+ }
cursorIsFocusIndicator = false;
const QTextCursor oldSelection = cursor;
@@ -1507,8 +1509,10 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF
trippleClickTimer.stop();
} else {
int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
- if (cursorPos == -1)
+ if (cursorPos == -1) {
+ e->ignore();
return;
+ }
#if !defined(QT_NO_IM)
QTextLayout *layout = cursor.block().layout();
@@ -1519,8 +1523,10 @@ void QTextControlPrivate::mousePressEvent(Qt::MouseButton button, const QPointF
button, buttons, modifiers);
ctx->mouseHandler(cursorPos - cursor.position(), &ev);
}
- if (!layout->preeditAreaText().isEmpty())
+ if (!layout->preeditAreaText().isEmpty()) {
+ e->ignore();
return;
+ }
}
#endif
if (modifiers == Qt::ShiftModifier) {
diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h
index ca9db9f..66459f6 100644
--- a/src/gui/text/qtextcontrol_p_p.h
+++ b/src/gui/text/qtextcontrol_p_p.h
@@ -131,10 +131,10 @@ public:
QString anchorForCursor(const QTextCursor &anchor) const;
void keyPressEvent(QKeyEvent *e);
- void mousePressEvent(Qt::MouseButton button, const QPointF &pos,
+ void mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos,
Qt::KeyboardModifiers modifiers,
Qt::MouseButtons buttons,
- const QPoint &globalPos = QPoint());
+ const QPoint &globalPos);
void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos);
void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos);
void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos);
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 1879db4..bd1d8ba 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -1111,6 +1111,32 @@ void QComboBoxPrivate::updateLineEditGeometry()
lineEdit->setGeometry(editRect);
}
+Qt::MatchFlags QComboBoxPrivate::matchFlags() const
+{
+ // Base how duplicates are determined on the autocompletion case sensitivity
+ Qt::MatchFlags flags = Qt::MatchFixedString;
+#ifndef QT_NO_COMPLETER
+ if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive)
+#endif
+ flags |= Qt::MatchCaseSensitive;
+ return flags;
+}
+
+
+void QComboBoxPrivate::_q_editingFinished()
+{
+ Q_Q(QComboBox);
+ if (lineEdit && !lineEdit->text().isEmpty()) {
+ //here we just check if the current item was entered
+ const int index = q_func()->findText(lineEdit->text(), matchFlags());
+ if (index != -1 && itemText(currentIndex) != lineEdit->text()) {
+ q->setCurrentIndex(index);
+ emitActivated(currentIndex);
+ }
+ }
+
+}
+
void QComboBoxPrivate::_q_returnPressed()
{
Q_Q(QComboBox);
@@ -1123,13 +1149,7 @@ void QComboBoxPrivate::_q_returnPressed()
// check for duplicates (if not enabled) and quit
int index = -1;
if (!duplicatesEnabled) {
- // Base how duplicates are determined on the autocompletion case sensitivity
- Qt::MatchFlags flags = Qt::MatchFixedString;
-#ifndef QT_NO_COMPLETER
- if (!lineEdit->completer() || lineEdit->completer()->caseSensitivity() == Qt::CaseSensitive)
-#endif
- flags |= Qt::MatchCaseSensitive;
- index = q->findText(text, flags);
+ index = q->findText(text, matchFlags());
if (index != -1) {
q->setCurrentIndex(index);
emitActivated(currentIndex);
@@ -1664,6 +1684,7 @@ void QComboBox::setLineEdit(QLineEdit *edit)
if (d->lineEdit->parent() != this)
d->lineEdit->setParent(this);
connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed()));
+ connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
#ifdef QT3_SUPPORT
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString)));
@@ -1960,7 +1981,7 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
if (lineEdit) {
QString newText = q->itemText(currentIndex.row());
if (lineEdit->text() != newText)
- lineEdit->setText(q->itemText(currentIndex.row()));
+ lineEdit->setText(newText);
updateLineEditGeometry();
}
if (indexChanged) {
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index 0652594..5d5ea21 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -304,6 +304,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_itemSelected(const QModelIndex &item))
Q_PRIVATE_SLOT(d_func(), void _q_emitHighlighted(const QModelIndex &))
Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentIndexChanged(const QModelIndex &index))
+ Q_PRIVATE_SLOT(d_func(), void _q_editingFinished())
Q_PRIVATE_SLOT(d_func(), void _q_returnPressed())
Q_PRIVATE_SLOT(d_func(), void _q_resetButton())
Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &, const QModelIndex &))
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index fe42c47..f6ba57c 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -342,6 +342,8 @@ public:
void init();
QComboBoxPrivateContainer* viewContainer();
void updateLineEditGeometry();
+ Qt::MatchFlags matchFlags() const;
+ void _q_editingFinished();
void _q_returnPressed();
void _q_complete();
void _q_itemSelected(const QModelIndex &item);
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 0fc94c9..2914164 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -1511,6 +1511,18 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
}
#endif // QT_NO_COMPLETER
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
+ if (hasAcceptableInput() || fixup()) {
+ emit accepted();
+ emit editingFinished();
+ }
+ if (inlineCompletionAccepted)
+ event->accept();
+ else
+ event->ignore();
+ return;
+ }
+
if (echoMode() == QLineEdit::PasswordEchoOnEdit
&& !passwordEchoEditing()
&& !isReadOnly()
@@ -1531,17 +1543,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
clear();
}
- if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
- if (hasAcceptableInput() || fixup()) {
- emit accepted();
- emit editingFinished();
- }
- if (inlineCompletionAccepted)
- event->accept();
- else
- event->ignore();
- return;
- }
bool unknown = false;
if (false) {
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 1b5d1cd..cc39b7f 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -273,7 +273,7 @@ void QMenuPrivate::updateActionRects() const
for (int i = 0; i < actions.count(); ++i) {
QAction *action = actions.at(i);
- if (action->isSeparator() || !action->isVisible() || widgetItems.at(i))
+ if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action))
continue;
//..and some members
hasCheckableItems |= action->isCheckable();
@@ -301,7 +301,7 @@ void QMenuPrivate::updateActionRects() const
const QFontMetrics &fm = opt.fontMetrics;
QSize sz;
- if (QWidget *w = widgetItems.at(i)) {
+ if (QWidget *w = widgetItems.value(action)) {
sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
} else {
//calc what I think the size is..
@@ -370,7 +370,7 @@ void QMenuPrivate::updateActionRects() const
rect.setWidth(max_column_width); //uniform width
//we need to update the widgets geometry
- if (QWidget *widget = widgetItems.at(i)) {
+ if (QWidget *widget = widgetItems.value(actions.at(i))) {
widget->setGeometry(rect);
widget->setVisible(actions.at(i)->isVisible());
}
@@ -583,8 +583,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
q->update(actionRect(action));
if (reason == SelectedFromKeyboard) {
- const int actionIndex = actions.indexOf(action);
- QWidget *widget = widgetItems.at(actionIndex);
+ QWidget *widget = widgetItems.value(action);
if (widget) {
if (widget->focusPolicy() != Qt::NoFocus)
widget->setFocus(Qt::TabFocusReason);
@@ -800,7 +799,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
current.moveTop(current.top() + delta);
//we need to update the widgets geometry
- if (QWidget *w = widgetItems.at(i))
+ if (QWidget *w = widgetItems.value(actions.at(i)))
w->setGeometry(current);
}
}
@@ -1392,11 +1391,12 @@ QMenu::QMenu(QMenuPrivate &dd, QWidget *parent)
QMenu::~QMenu()
{
Q_D(QMenu);
- for (int i = 0; i < d->widgetItems.count(); ++i) {
- if (QWidget *widget = d->widgetItems.at(i)) {
- QWidgetAction *action = static_cast<QWidgetAction *>(d->actions.at(i));
+ QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin();
+ for (; it != d->widgetItems.end(); ++it) {
+ if (QWidget *widget = it.value()) {
+ QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
action->releaseWidget(widget);
- d->widgetItems[i] = 0;
+ *it = 0;
}
}
@@ -1878,9 +1878,11 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if(snapToMouse) //position flowing left from the mouse
pos.setX(mouse.x()-size.width());
+#ifndef QT_NO_MENUBAR
//if in a menubar, it should be right-aligned
if (qobject_cast<QMenuBar*>(d->causedPopup.widget))
pos.rx() -= size.width();
+#endif //QT_NO_MENUBAR
if (pos.x() < screen.left()+desktopFrame)
pos.setX(qMax(p.x(), screen.left()+desktopFrame));
@@ -2151,7 +2153,7 @@ void QMenu::paintEvent(QPaintEvent *e)
QAction *action = d->actions.at(i);
QRect adjustedActionRect = d->actionRects.at(i);
if (!e->rect().intersects(adjustedActionRect)
- || d->widgetItems.at(i))
+ || d->widgetItems.value(action))
continue;
//set the clip region to be extra safe (and adjust for the scrollers)
QRegion adjustedActionReg(adjustedActionRect);
@@ -2862,25 +2864,20 @@ void QMenu::actionEvent(QActionEvent *e)
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
}
- QWidget *widget = 0;
- if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action()))
- widget = wa->requestWidget(this);
-
- int index = d->actions.indexOf(e->action());
- Q_ASSERT(index != -1);
- d->widgetItems.insert(index, widget);
-
+ if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
+ QWidget *widget = wa->requestWidget(this);
+ if (widget)
+ d->widgetItems.insert(wa, widget);
+ }
} else if (e->type() == QEvent::ActionRemoved) {
e->action()->disconnect(this);
if (e->action() == d->currentAction)
d->currentAction = 0;
- int index = d->actions.indexOf(e->before()) + 1;
if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
- if (QWidget *widget = d->widgetItems.at(index))
+ if (QWidget *widget = d->widgetItems.value(wa))
wa->releaseWidget(widget);
}
- Q_ASSERT(index != -1);
- d->widgetItems.removeAt(index);
+ d->widgetItems.remove(e->action());
}
#ifdef Q_WS_MAC
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index b238faf..9510cc6 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -1191,7 +1191,7 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
#endif
}
- QWidget *widget = qmenu ? qmenu->widgetItems.value(qmenu->actions.indexOf(action->action)) : 0;
+ QWidget *widget = qmenu ? qmenu->widgetItems.value(action->action) : 0;
if (widget) {
#ifndef QT_MAC_USE_COCOA
ChangeMenuAttributes(action->menu, kMenuAttrDoNotCacheImage, 0);
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index 9348f7b..a5bde7c 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -190,7 +190,7 @@ public:
QRect actionRect(QAction *) const;
mutable QVector<QRect> actionRects;
- mutable QWidgetList widgetItems;
+ mutable QHash<QAction *, QWidget *> widgetItems;
void updateActionRects() const;
QRect popupGeometry(const QWidget *widget) const;
QRect popupGeometry(int screen = -1) const;
diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp
index bdd3c75..13ee346 100644
--- a/src/gui/widgets/qwidgetanimator.cpp
+++ b/src/gui/widgets/qwidgetanimator.cpp
@@ -88,8 +88,6 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
const QRect final_geometry = _final_geometry.isValid() || widget->isWindow() ? _final_geometry :
QRect(QPoint(-500 - widget->width(), -500 - widget->height()), widget->size());
- if (r == final_geometry)
- return; //the widget is already where it should be
#ifndef QT_NO_ANIMATION
AnimationMap::const_iterator it = m_animation_map.constFind(widget);
if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry)
@@ -116,9 +114,4 @@ bool QWidgetAnimator::animating() const
return !m_animation_map.isEmpty();
}
-bool QWidgetAnimator::animating(QWidget *widget) const
-{
- return m_animation_map.contains(widget);
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h
index 68d9344..095380f 100644
--- a/src/gui/widgets/qwidgetanimator_p.h
+++ b/src/gui/widgets/qwidgetanimator_p.h
@@ -70,7 +70,6 @@ public:
QWidgetAnimator(QMainWindowLayout *layout);
void animate(QWidget *widget, const QRect &final_geometry, bool animate);
bool animating() const;
- bool animating(QWidget *widget) const;
void abort(QWidget *widget);