summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-10-29 04:54:35 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-10-29 04:54:35 (GMT)
commitc06be171d9e9efe91a3612bf0a82fab0d2cff2fa (patch)
tree8c3194e5171125f281f4df53328826138e723719 /src/gui
parentbfbded95056d43a65b2c9ef1fa90bfd40adc6472 (diff)
parent51f1d68addd23516d7e6e252e476feac0a95d0c0 (diff)
downloadQt-c06be171d9e9efe91a3612bf0a82fab0d2cff2fa.zip
Qt-c06be171d9e9efe91a3612bf0a82fab0d2cff2fa.tar.gz
Qt-c06be171d9e9efe91a3612bf0a82fab0d2cff2fa.tar.bz2
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt-widget-team into kinetic-declarativeui
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.cpp7
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp383
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h35
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp43
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.h51
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp16
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp8
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp2
-rw-r--r--src/gui/graphicsview/qgridlayoutengine_p.h25
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp111
-rw-r--r--src/gui/graphicsview/qsimplex_p.h38
-rw-r--r--src/gui/itemviews/qabstractitemview.h1
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h3
-rw-r--r--src/gui/itemviews/qheaderview.cpp2
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp2
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp2
-rw-r--r--src/gui/itemviews/qlistview.cpp109
-rw-r--r--src/gui/itemviews/qlistview_p.h9
-rw-r--r--src/gui/itemviews/qlistwidget.cpp31
-rw-r--r--src/gui/itemviews/qlistwidget_p.h3
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp2
-rw-r--r--src/gui/itemviews/qtableview.cpp47
-rw-r--r--src/gui/itemviews/qtableview_p.h6
-rw-r--r--src/gui/itemviews/qtreeview.cpp53
-rw-r--r--src/gui/itemviews/qtreeview_p.h4
-rw-r--r--src/gui/kernel/qguiplatformplugin.cpp2
-rw-r--r--src/gui/kernel/qwidget.cpp22
-rw-r--r--src/gui/kernel/qwidget_p.h1
-rw-r--r--src/gui/styles/qcommonstyle.cpp2
-rw-r--r--src/gui/styles/qplastiquestyle.cpp3
-rw-r--r--src/gui/styles/qwindowsstyle.cpp3
-rw-r--r--src/gui/styles/qwindowsvistastyle.cpp50
-rw-r--r--src/gui/styles/qwindowsvistastyle_p.h24
-rw-r--r--src/gui/text/qfont.cpp12
-rw-r--r--src/gui/text/qfontinfo.h3
-rw-r--r--src/gui/text/qfontmetrics.cpp49
-rw-r--r--src/gui/text/qfontmetrics.h5
-rw-r--r--src/gui/text/qtextdocument.cpp18
-rw-r--r--src/gui/widgets/qcombobox.cpp27
-rw-r--r--src/gui/widgets/qcombobox.h3
-rw-r--r--src/gui/widgets/qcombobox_p.h3
-rw-r--r--src/gui/widgets/qdockarealayout.cpp14
-rw-r--r--src/gui/widgets/qdockarealayout_p.h1
-rw-r--r--src/gui/widgets/qdockwidget.cpp10
-rw-r--r--src/gui/widgets/qmenu.cpp4
-rw-r--r--src/gui/widgets/qmenubar.cpp29
-rw-r--r--src/gui/widgets/qsplitter.cpp17
-rw-r--r--src/gui/widgets/qtoolbar.cpp16
-rw-r--r--src/gui/widgets/qtoolbar.h1
50 files changed, 899 insertions, 415 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
index e21cd99..22a7cf9 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
@@ -420,7 +420,7 @@ void QGraphicsAnchorLayout::setSpacing(qreal spacing)
qreal QGraphicsAnchorLayout::horizontalSpacing() const
{
Q_D(const QGraphicsAnchorLayout);
- return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal);
+ return d->styleInfo().defaultSpacing(Qt::Horizontal);
}
/*!
@@ -431,7 +431,7 @@ qreal QGraphicsAnchorLayout::horizontalSpacing() const
qreal QGraphicsAnchorLayout::verticalSpacing() const
{
Q_D(const QGraphicsAnchorLayout);
- return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical);
+ return d->styleInfo().defaultSpacing(Qt::Vertical);
}
/*!
@@ -501,7 +501,8 @@ void QGraphicsAnchorLayout::invalidate()
{
Q_D(QGraphicsAnchorLayout);
QGraphicsLayout::invalidate();
- d->calculateGraphCacheDirty = 1;
+ d->calculateGraphCacheDirty = true;
+ d->styleInfoDirty = true;
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index 8c8c303..1d6e29d 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <QtGui/qwidget.h>
+#include <QtGui/qapplication.h>
#include <QtCore/qlinkedlist.h>
#include <QtCore/qstack.h>
@@ -141,34 +142,25 @@ static void internalSizeHints(QSizePolicy::Policy policy,
*expSize = *prefSize;
}
-void AnchorData::refreshSizeHints(qreal effectiveSpacing)
+bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
{
- const bool isInternalAnchor = from->m_item == to->m_item;
-
QSizePolicy::Policy policy;
qreal minSizeHint;
qreal prefSizeHint;
qreal maxSizeHint;
- if (isInternalAnchor) {
- const QGraphicsAnchorLayoutPrivate::Orientation orient =
- QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge);
- const Qt::AnchorPoint centerEdge =
- QGraphicsAnchorLayoutPrivate::pickEdge(Qt::AnchorHorizontalCenter, orient);
- bool hasCenter = (from->m_edge == centerEdge || to->m_edge == centerEdge);
-
+ // It is an internal anchor
+ if (item) {
if (isLayoutAnchor) {
minSize = 0;
prefSize = 0;
expSize = 0;
maxSize = QWIDGETSIZE_MAX;
- if (hasCenter)
+ if (isCenterAnchor)
maxSize /= 2;
- return;
+ return true;
} else {
-
- QGraphicsLayoutItem *item = from->m_item;
- if (orient == QGraphicsAnchorLayoutPrivate::Horizontal) {
+ if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) {
policy = item->sizePolicy().horizontalPolicy();
minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).width();
prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).width();
@@ -180,7 +172,7 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing)
maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).height();
}
- if (hasCenter) {
+ if (isCenterAnchor) {
minSizeHint /= 2;
prefSizeHint /= 2;
maxSizeHint /= 2;
@@ -196,7 +188,20 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing)
// their effective size hints might be narrowed down due to their size policies.
prefSizeHint = prefSize;
} else {
- prefSizeHint = effectiveSpacing;
+ const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1);
+ qreal s = styleInfo->defaultSpacing(orient);
+ if (s < 0) {
+ QSizePolicy::ControlType controlTypeFrom = from->m_item->sizePolicy().controlType();
+ QSizePolicy::ControlType controlTypeTo = to->m_item->sizePolicy().controlType();
+ s = styleInfo->perItemSpacing(controlTypeFrom, controlTypeTo, orient);
+
+ // ### Currently we do not support negative anchors inside the graph.
+ // To avoid those being created by a negative style spacing, we must
+ // make this test.
+ if (s < 0)
+ s = 0;
+ }
+ prefSizeHint = s;
}
maxSizeHint = QWIDGETSIZE_MAX;
}
@@ -214,6 +219,8 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing)
sizeAtPreferred = prefSize;
sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
+
+ return true;
}
void ParallelAnchorData::updateChildrenSizes()
@@ -227,26 +234,29 @@ void ParallelAnchorData::updateChildrenSizes()
secondEdge->updateChildrenSizes();
}
-void ParallelAnchorData::refreshSizeHints(qreal effectiveSpacing)
+bool ParallelAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
{
- refreshSizeHints_helper(effectiveSpacing);
+ return refreshSizeHints_helper(styleInfo);
}
-void ParallelAnchorData::refreshSizeHints_helper(qreal effectiveSpacing,
+bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo,
bool refreshChildren)
{
- if (refreshChildren) {
- firstEdge->refreshSizeHints(effectiveSpacing);
- secondEdge->refreshSizeHints(effectiveSpacing);
+ if (refreshChildren && (!firstEdge->refreshSizeHints(styleInfo)
+ || !secondEdge->refreshSizeHints(styleInfo))) {
+ return false;
}
- // ### should we warn if the parallel connection is invalid?
- // e.g. 1-2-3 with 10-20-30, the minimum of the latter is
- // bigger than the maximum of the former.
-
minSize = qMax(firstEdge->minSize, secondEdge->minSize);
maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize);
+ // 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
+ // for this parallel setup.
+ if (minSize > maxSize) {
+ return false;
+ }
+
expSize = qMax(firstEdge->expSize, secondEdge->expSize);
expSize = qMin(expSize, maxSize);
@@ -258,6 +268,8 @@ void ParallelAnchorData::refreshSizeHints_helper(qreal effectiveSpacing,
sizeAtPreferred = prefSize;
sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
+
+ return true;
}
/*!
@@ -362,12 +374,12 @@ void SequentialAnchorData::updateChildrenSizes()
}
}
-void SequentialAnchorData::refreshSizeHints(qreal effectiveSpacing)
+bool SequentialAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
{
- refreshSizeHints_helper(effectiveSpacing);
+ return refreshSizeHints_helper(styleInfo);
}
-void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing,
+bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo,
bool refreshChildren)
{
minSize = 0;
@@ -379,8 +391,8 @@ void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing,
AnchorData *edge = m_edges.at(i);
// If it's the case refresh children information first
- if (refreshChildren)
- edge->refreshSizeHints(effectiveSpacing);
+ if (refreshChildren && !edge->refreshSizeHints(styleInfo))
+ return false;
minSize += edge->minSize;
prefSize += edge->prefSize;
@@ -393,6 +405,8 @@ void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing,
sizeAtPreferred = prefSize;
sizeAtExpanding = prefSize;
sizeAtMaximum = prefSize;
+
+ return true;
}
#ifdef QT_DEBUG
@@ -458,7 +472,7 @@ QString GraphPath::toString() const
#endif
QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate()
- : calculateGraphCacheDirty(1)
+ : calculateGraphCacheDirty(true), styleInfoDirty(true)
{
for (int i = 0; i < NOrientations; ++i) {
for (int j = 0; j < 3; ++j) {
@@ -510,18 +524,49 @@ inline static qreal checkAdd(qreal a, qreal b)
}
/*!
- * \internal
- *
- * Takes the sequence of vertices described by (\a before, \a vertices, \a after) and replaces
- * all anchors connected to the vertices in \a vertices with one simplified anchor between
- * \a before and \a after. The simplified anchor will be a placeholder for all the previous
- * anchors between \a before and \a after, and can be restored back to the anchors it is a
- * placeholder for.
- */
-static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
- AnchorVertex *before,
- const QVector<AnchorVertex*> &vertices,
- AnchorVertex *after)
+ \internal
+
+ Adds \a newAnchor to the graph \a g.
+
+ Returns the newAnchor itself if it could be added without further changes to the graph. If a
+ new parallel anchor had to be created, then returns the new parallel anchor. In case the
+ addition is unfeasible -- because a parallel setup is not possible, returns 0.
+*/
+static AnchorData *addAnchorMaybeParallel(Graph<AnchorVertex, AnchorData> *g,
+ AnchorData *newAnchor)
+{
+ bool 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)) {
+ ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, newAnchor);
+
+ // 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);
+ newAnchor = parallel;
+ }
+
+ g->createEdge(newAnchor->from, newAnchor->to, newAnchor);
+ return feasible ? newAnchor : 0;
+}
+
+
+/*!
+ \internal
+
+ Takes the sequence of vertices described by (\a before, \a vertices, \a after) and removes
+ all anchors connected to the vertices in \a vertices, returning one simplified anchor between
+ \a before and \a after.
+
+ Note that this function doesn't add the created anchor to the graph. This should be done by
+ the caller.
+*/
+static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph,
+ AnchorVertex *before,
+ const QVector<AnchorVertex*> &vertices,
+ AnchorVertex *after)
{
AnchorData *data = graph->edgeData(before, vertices.first());
Q_ASSERT(data);
@@ -563,24 +608,7 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
sequence->refreshSizeHints_helper(0, false);
- // Note that since layout 'edges' can't be simplified away from
- // the graph, it's safe to assume that if there's a layout
- // 'edge', it'll be in the boundaries of the sequence.
- sequence->isLayoutAnchor = (sequence->m_edges.first()->isLayoutAnchor
- || sequence->m_edges.last()->isLayoutAnchor);
-
- AnchorData *newAnchor = sequence;
- if (AnchorData *oldAnchor = graph->takeEdge(before, after)) {
- ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, sequence);
- parallel->isLayoutAnchor = (oldAnchor->isLayoutAnchor
- || sequence->isLayoutAnchor);
- parallel->refreshSizeHints_helper(0, false);
- newAnchor = parallel;
- }
- graph->createEdge(before, after, newAnchor);
-
- // True if we created a parallel anchor
- return newAnchor != sequence;
+ return sequence;
}
/*!
@@ -617,15 +645,17 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
2. Go to (1)
3. Done
+ When creating the parallel anchors, the algorithm might identify unfeasible situations. In this
+ case the simplification process stops and returns false. Otherwise returns true.
*/
-void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
+bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
{
static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
if (noSimplification || items.isEmpty())
- return;
+ return true;
if (graphSimplified[orientation])
- return;
+ return true;
graphSimplified[orientation] = true;
#if 0
@@ -634,12 +664,18 @@ void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
#endif
if (!graph[orientation].rootVertex())
- return;
+ return true;
bool dirty;
+ bool feasible = true;
do {
- dirty = simplifyGraphIteration(orientation);
- } while (dirty);
+ dirty = simplifyGraphIteration(orientation, &feasible);
+ } while (dirty && feasible);
+
+ if (!feasible)
+ graphSimplified[orientation] = false;
+
+ return feasible;
}
/*!
@@ -656,7 +692,8 @@ void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
Note that there are some catches to this that are not covered by the above explanation, see
the function comments for more details.
*/
-bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation)
+bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation,
+ bool *feasible)
{
Q_Q(QGraphicsAnchorLayout);
Graph<AnchorVertex, AnchorData> &g = graph[orientation];
@@ -667,8 +704,6 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
QVector<AnchorVertex*> candidates;
bool candidatesForward;
- const Qt::AnchorPoint centerEdge = pickEdge(Qt::AnchorHorizontalCenter, orientation);
-
// Walk depth-first, in the stack we store start of the candidate sequence (beforeSequence)
// and the vertex to be visited.
while (!stack.isEmpty()) {
@@ -777,7 +812,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
// One restriction we have is to not simplify half of an anchor and let the other half
// unsimplified. So we remove center edges before and after the sequence.
- if (beforeSequence->m_edge == centerEdge && beforeSequence->m_item == candidates.first()->m_item) {
+ const AnchorData *firstAnchor = g.edgeData(beforeSequence, candidates.first());
+ if (firstAnchor->isCenterAnchor) {
beforeSequence = candidates.first();
candidates.remove(0);
@@ -786,7 +822,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
continue;
}
- if (afterSequence->m_edge == centerEdge && afterSequence->m_item == candidates.last()->m_item) {
+ const AnchorData *lastAnchor = g.edgeData(candidates.last(), afterSequence);
+ if (lastAnchor->isCenterAnchor) {
afterSequence = candidates.last();
candidates.remove(candidates.count() - 1);
@@ -794,11 +831,26 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP
continue;
}
- // This function will remove the candidates from the graph and create one edge between
- // beforeSequence and afterSequence. This function returns true if the sequential
- // simplification also caused a parallel simplification to be created. In this case we end
- // the iteration and start again (since all the visited state we have may be outdated).
- if (simplifySequentialChunk(&g, beforeSequence, candidates, afterSequence))
+ //
+ // Add the sequence to the graph.
+ //
+
+ AnchorData *sequence = createSequence(&g, beforeSequence, candidates, afterSequence);
+
+ // If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll
+ // create a parallel anchor between the new sequence and the old anchor.
+ AnchorData *newAnchor = addAnchorMaybeParallel(&g, sequence);
+
+ if (!newAnchor) {
+ *feasible = false;
+ return false;
+ }
+
+ // When a new parallel anchor is create in the graph, we finish the iteration and return
+ // true to indicate a new iteration is needed. This happens because a parallel anchor
+ // changes the number of adjacents one vertex has, possibly opening up oportunities for
+ // building candidate lists (when adjacents == 2).
+ if (newAnchor != sequence)
return true;
// If there was no parallel simplification, we'll keep walking the graph. So we clear the
@@ -1008,11 +1060,13 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
AnchorData *data = new AnchorData;
c->variables.insert(data, 1.0);
addAnchor_helper(item, firstEdge, item, centerEdge, data);
+ data->isCenterAnchor = true;
data->refreshSizeHints(0);
data = new AnchorData;
c->variables.insert(data, -1.0);
addAnchor_helper(item, centerEdge, item, lastEdge, data);
+ data->isCenterAnchor = true;
data->refreshSizeHints(0);
itemCenterConstraints[orientation].append(c);
@@ -1234,9 +1288,11 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt
{
Q_Q(QGraphicsAnchorLayout);
+ const Orientation orientation = edgeOrientation(firstEdge);
+
// Guarantee that the graph is no simplified when adding this anchor,
// anchor manipulation always happen in the full graph
- restoreSimplifiedGraph(edgeOrientation(firstEdge));
+ restoreSimplifiedGraph(orientation);
// Is the Vertex (firstItem, firstEdge) already represented in our
// internal structure?
@@ -1245,10 +1301,16 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt
// Remove previous anchor
// ### Could we update the existing edgeData rather than creating a new one?
- if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) {
+ if (graph[orientation].edgeData(v1, v2)) {
removeAnchor_helper(v1, v2);
}
+ // If its an internal anchor, set the associated item
+ if (firstItem == secondItem)
+ data->item = firstItem;
+
+ data->orientation = orientation;
+
// Create a bi-directional edge in the sense it can be transversed both
// from v1 or v2. "data" however is shared between the two references
// so we still know that the anchor direction is from 1 to 2.
@@ -1257,10 +1319,11 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt
#ifdef QT_DEBUG
data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString());
#endif
- // Keep track of anchors that are connected to the layout 'edges'
- data->isLayoutAnchor = (v1->m_item == q || v2->m_item == q);
+ // ### bit to track internal anchors, since inside AnchorData methods
+ // we don't have access to the 'q' pointer.
+ data->isLayoutAnchor = (data->item == q);
- graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data);
+ graph[orientation].createEdge(v1, v2, data);
}
QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem,
@@ -1425,7 +1488,7 @@ void QGraphicsAnchorLayoutPrivate::anchorSize(const AnchorData *data,
Q_ASSERT(minSize || prefSize || maxSize);
Q_ASSERT(data);
QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this);
- that->restoreSimplifiedGraph(edgeOrientation(data->from->m_edge));
+ that->restoreSimplifiedGraph(Orientation(data->orientation));
if (minSize)
*minSize = data->minSize;
@@ -1565,34 +1628,32 @@ void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&fi
}
}
-qreal QGraphicsAnchorLayoutPrivate::effectiveSpacing(Orientation orientation) const
+QLayoutStyleInfo &QGraphicsAnchorLayoutPrivate::styleInfo() const
{
- Q_Q(const QGraphicsAnchorLayout);
- qreal s = spacings[orientation];
- if (s < 0) {
- // ### make sure behaviour is the same as in QGraphicsGridLayout
+ if (styleInfoDirty) {
+ Q_Q(const QGraphicsAnchorLayout);
+ //### Fix this if QGV ever gets support for Metal style or different Aqua sizes.
+ QWidget *wid = 0;
+
QGraphicsLayoutItem *parent = q->parentLayoutItem();
while (parent && parent->isLayout()) {
parent = parent->parentLayoutItem();
}
+ QGraphicsWidget *w = 0;
if (parent) {
QGraphicsItem *parentItem = parent->graphicsItem();
- if (parentItem && parentItem->isWidget()) {
- QGraphicsWidget *w = static_cast<QGraphicsWidget*>(parentItem);
- s = w->style()->pixelMetric(orientation == Horizontal
- ? QStyle::PM_LayoutHorizontalSpacing
- : QStyle::PM_LayoutVerticalSpacing);
- }
+ if (parentItem && parentItem->isWidget())
+ w = static_cast<QGraphicsWidget*>(parentItem);
}
- }
- // ### Currently we do not support negative anchors inside the graph.
- // To avoid those being created by a negative style spacing, we must
- // make this test.
- if (s < 0)
- s = 0;
+ QStyle *style = w ? w->style() : QApplication::style();
+ cachedStyleInfo = QLayoutStyleInfo(style, wid);
+ cachedStyleInfo.setDefaultSpacing(Qt::Horizontal, spacings[0]);
+ cachedStyleInfo.setDefaultSpacing(Qt::Vertical, spacings[1]);
- return s;
+ styleInfoDirty = false;
+ }
+ return cachedStyleInfo;
}
/*!
@@ -1620,7 +1681,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs()
dumpGraph(QString::fromAscii("%1-after").arg(count));
#endif
- calculateGraphCacheDirty = 0;
+ calculateGraphCacheDirty = false;
}
// ### Maybe getGraphParts could return the variables when traversing, at least
@@ -1638,38 +1699,52 @@ QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
}
/*!
- \internal
+ \internal
- Calculate graphs is the method that puts together all the helper routines
- so that the AnchorLayout can calculate the sizes of each item.
+ Calculate graphs is the method that puts together all the helper routines
+ so that the AnchorLayout can calculate the sizes of each item.
- In a nutshell it should do:
+ In a nutshell it should do:
- 1) Update anchor nominal sizes, that is, the size that each anchor would
- have if no other restrictions applied. This is done by quering the
- layout style and the sizeHints of the items belonging to the layout.
+ 1) Refresh anchor nominal sizes, that is, the size that each anchor would
+ have if no other restrictions applied. This is done by quering the
+ layout style and the sizeHints of the items belonging to the layout.
- 2) Simplify the graph by grouping together parallel and sequential anchors
- into "group anchors". These have equivalent minimum, preferred and maximum
- sizeHints as the anchors they replace.
+ 2) Simplify the graph by grouping together parallel and sequential anchors
+ into "group anchors". These have equivalent minimum, preferred and maximum
+ sizeHints as the anchors they replace.
- 3) Check if we got to a trivial case. In some cases, the whole graph can be
- simplified into a single anchor. If so, use this information. If not,
- then call the Simplex solver to calculate the anchors sizes.
+ 3) Check if we got to a trivial case. In some cases, the whole graph can be
+ simplified into a single anchor. If so, use this information. If not,
+ then call the Simplex solver to calculate the anchors sizes.
- 4) Once the root anchors had its sizes calculated, propagate that to the
- anchors they represent.
+ 4) Once the root anchors had its sizes calculated, propagate that to the
+ anchors they represent.
*/
void QGraphicsAnchorLayoutPrivate::calculateGraphs(
QGraphicsAnchorLayoutPrivate::Orientation orientation)
{
Q_Q(QGraphicsAnchorLayout);
- // Simplify the graph
- simplifyGraph(orientation);
+#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT)
+ lastCalculationUsedSimplex[orientation] = false;
+#endif
+
+ // 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.
+ if (!refreshAllSizeHints(orientation)) {
+ qWarning("QGraphicsAnchorLayout: anchor setup is not feasible.");
+ graphHasConflicts[orientation] = true;
+ return;
+ }
- // Reset the nominal sizes of each anchor based on the current item sizes
- setAnchorSizeHintsFromItems(orientation);
+ // Simplify the graph
+ if (!simplifyGraph(orientation)) {
+ qWarning("QGraphicsAnchorLayout: anchor setup is not feasible.");
+ graphHasConflicts[orientation] = true;
+ return;
+ }
// Traverse all graph edges and store the possible paths to each vertex
findPaths(orientation);
@@ -1837,23 +1912,31 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra
}
/*!
- \internal
+ \internal
+
+ Traverse the graph refreshing the size hints. Complex anchors will call the
+ refresh method of their children anchors. Simple anchors, if are internal
+ anchors, will query the associated item for their size hints.
- For graph edges ("anchors") that represent items, this method updates their
- intrinsic size restrictions, based on the item size hints.
+ Returns false if some unfeasibility was found in the graph regarding the
+ complex anchors.
*/
-void QGraphicsAnchorLayoutPrivate::setAnchorSizeHintsFromItems(Orientation orientation)
+bool QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation)
{
Graph<AnchorVertex, AnchorData> &g = graph[orientation];
QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections();
- qreal spacing = effectiveSpacing(orientation);
-
+ QLayoutStyleInfo styleInf = styleInfo();
for (int i = 0; i < vertices.count(); ++i) {
AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);;
Q_ASSERT(data->from && data->to);
- data->refreshSizeHints(spacing);
+
+ // During the traversal we check the feasibility of the complex anchors.
+ if (!data->refreshSizeHints(&styleInf))
+ return false;
}
+
+ return true;
}
/*!
@@ -1960,17 +2043,27 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin
{
QList<QSimplexConstraint *> anchorConstraints;
for (int i = 0; i < anchors.size(); ++i) {
- QSimplexConstraint *c = new QSimplexConstraint;
- c->variables.insert(anchors[i], 1.0);
- c->constant = anchors[i]->minSize;
- c->ratio = QSimplexConstraint::MoreOrEqual;
- anchorConstraints += c;
-
- c = new QSimplexConstraint;
- c->variables.insert(anchors[i], 1.0);
- c->constant = anchors[i]->maxSize;
- c->ratio = QSimplexConstraint::LessOrEqual;
- anchorConstraints += c;
+ AnchorData *ad = anchors[i];
+
+ if ((ad->minSize == ad->maxSize) || qFuzzyCompare(ad->minSize, ad->maxSize)) {
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->variables.insert(ad, 1.0);
+ c->constant = ad->minSize;
+ c->ratio = QSimplexConstraint::Equal;
+ anchorConstraints += c;
+ } else {
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->variables.insert(ad, 1.0);
+ c->constant = ad->minSize;
+ c->ratio = QSimplexConstraint::MoreOrEqual;
+ anchorConstraints += c;
+
+ c = new QSimplexConstraint;
+ c->variables.insert(ad, 1.0);
+ c->constant = ad->maxSize;
+ c->ratio = QSimplexConstraint::LessOrEqual;
+ anchorConstraints += c;
+ }
}
return anchorConstraints;
@@ -2110,8 +2203,8 @@ void QGraphicsAnchorLayoutPrivate::identifyNonFloatItems_helper(const AnchorData
switch(ad->type) {
case AnchorData::Normal:
- if (ad->from->m_item == ad->to->m_item && ad->to->m_item != q)
- nonFloatingItemsIdentifiedSoFar->insert(ad->to->m_item);
+ if (ad->item && ad->item != q)
+ nonFloatingItemsIdentifiedSoFar->insert(ad->item);
break;
case AnchorData::Sequential:
foreach (const AnchorData *d, static_cast<const SequentialAnchorData *>(ad)->m_edges)
@@ -2377,7 +2470,7 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *>
*min = simplex.solveMin();
// Save sizeAtMinimum results
- QList<QSimplexVariable *> variables = simplex.constraintsVariables();
+ 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));
@@ -2536,7 +2629,7 @@ void QGraphicsAnchorLayoutPrivate::solveExpanding(const QList<QSimplexConstraint
hasExpanding = true;
// Lock anchor between boundedExpSize and sizeAtMaximum (ensure 3.a)
- if (boundedExpSize == ad->sizeAtMaximum) {
+ 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;
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
index d45c004..99a866b 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
@@ -151,15 +151,16 @@ struct AnchorData : public QSimplexVariable {
};
AnchorData()
- : QSimplexVariable(), from(0), to(0),
+ : QSimplexVariable(), item(0), from(0), to(0),
minSize(0), prefSize(0), expSize(0), maxSize(0),
sizeAtMinimum(0), sizeAtPreferred(0),
sizeAtExpanding(0), sizeAtMaximum(0),
graphicsAnchor(0), skipInPreferred(0),
- type(Normal), hasSize(true), isLayoutAnchor(false) {}
+ type(Normal), hasSize(true), isLayoutAnchor(false),
+ isCenterAnchor(false), orientation(0) {}
virtual void updateChildrenSizes() {}
- virtual void refreshSizeHints(qreal effectiveSpacing);
+ virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo);
virtual ~AnchorData() {}
@@ -180,6 +181,9 @@ struct AnchorData : public QSimplexVariable {
hasSize = false;
}
+ // Internal anchors have associated items
+ QGraphicsLayoutItem *item;
+
// Anchor is semantically directed
AnchorVertex *from;
AnchorVertex *to;
@@ -205,7 +209,9 @@ struct AnchorData : public QSimplexVariable {
uint skipInPreferred : 1;
uint type : 2; // either Normal, Sequential or Parallel
uint hasSize : 1; // if false, get size from style.
- uint isLayoutAnchor : 1; // if this anchor is connected to a layout 'edge'
+ uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor
+ uint isCenterAnchor : 1;
+ uint orientation : 1;
};
#ifdef QT_DEBUG
@@ -226,9 +232,9 @@ struct SequentialAnchorData : public AnchorData
}
virtual void updateChildrenSizes();
- virtual void refreshSizeHints(qreal effectiveSpacing);
+ virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo);
- void refreshSizeHints_helper(qreal effectiveSpacing, bool refreshChildren = true);
+ bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true);
void setVertices(const QVector<AnchorVertex*> &vertices)
{
@@ -261,9 +267,9 @@ struct ParallelAnchorData : public AnchorData
}
virtual void updateChildrenSizes();
- virtual void refreshSizeHints(qreal effectiveSpacing);
+ virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo);
- void refreshSizeHints_helper(qreal effectiveSpacing, bool refreshChildren = true);
+ bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true);
AnchorData* firstEdge;
AnchorData* secondEdge;
@@ -423,13 +429,12 @@ public:
Qt::AnchorPoint &firstEdge,
QGraphicsLayoutItem *&secondItem,
Qt::AnchorPoint &secondEdge);
- // for getting the actual spacing (will query the style if the
- // spacing is not explicitly set).
- qreal effectiveSpacing(Orientation orientation) const;
+
+ QLayoutStyleInfo &styleInfo() const;
// Activation methods
- void simplifyGraph(Orientation orientation);
- bool simplifyGraphIteration(Orientation orientation);
+ bool simplifyGraph(Orientation orientation);
+ bool simplifyGraphIteration(Orientation orientation, bool *feasible);
void restoreSimplifiedGraph(Orientation orientation);
void calculateGraphs();
@@ -441,7 +446,7 @@ public:
bool calculateNonTrunk(const QList<QSimplexConstraint *> &constraints,
const QList<AnchorData *> &variables);
- void setAnchorSizeHintsFromItems(Orientation orientation);
+ bool refreshAllSizeHints(Orientation orientation);
void findPaths(Orientation orientation);
void constraintsFromPaths(Orientation orientation);
void updateAnchorSizes(Orientation orientation);
@@ -524,6 +529,8 @@ public:
#endif
uint calculateGraphCacheDirty : 1;
+ mutable uint styleInfoDirty : 1;
+ mutable QLayoutStyleInfo cachedStyleInfo;
friend class QGraphicsAnchorPrivate;
};
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index f8c627d..759a223 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1039,13 +1039,31 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
}
// Update focus scope item ptr in new scope.
- if (newParent) {
+ QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
+ if (newFocusScopeItem && newParent) {
+ if (subFocusItem) {
+ // Find the subFocusItem's topmost focus scope.
+ QGraphicsItem *ancestorScope = 0;
+ QGraphicsItem *p = subFocusItem->d_ptr->parent;
+ while (p) {
+ if (p->flags() & QGraphicsItem::ItemIsFocusScope)
+ ancestorScope = p;
+ if (p->isPanel())
+ break;
+ p = p->parentItem();
+ }
+ if (ancestorScope)
+ newFocusScopeItem = ancestorScope;
+ }
+
QGraphicsItem *p = newParent;
while (p) {
if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
- p->d_ptr->focusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
- // ### The below line might not make sense...
- if (subFocusItem)
+ p->d_ptr->focusScopeItem = newFocusScopeItem;
+ // Ensure the new item is no longer the subFocusItem. The
+ // only way to set focus on a child of a focus scope is
+ // by setting focus on the scope itself.
+ if (subFocusItem && !p->focusItem())
subFocusItem->d_ptr->clearSubFocus();
break;
}
@@ -1287,6 +1305,8 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
*/
QGraphicsItem::~QGraphicsItem()
{
+ if (d_ptr->isObject)
+ QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true;
d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
@@ -2982,8 +3002,11 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
while (p) {
if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
p->d_ptr->focusScopeItem = q_ptr;
- if (!q_ptr->isActive() || !p->focusItem())
+ if (!p->focusItem()) {
+ // If you call setFocus on a child of a focus scope that
+ // doesn't currently have a focus item, then stop.
return;
+ }
break;
}
p = p->d_ptr->parent;
@@ -4274,7 +4297,7 @@ void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
// Only move items with the same Z value, and that need moving.
int siblingIndex = sibling->d_ptr->siblingIndex;
int myIndex = d_ptr->siblingIndex;
- if (myIndex >= siblingIndex && d_ptr->z == sibling->d_ptr->z) {
+ if (myIndex >= siblingIndex) {
siblings->move(myIndex, siblingIndex);
// Fixup the insertion ordering.
for (int i = 0; i < siblings->size(); ++i) {
@@ -10778,8 +10801,12 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item)
return debug;
}
- debug << "QGraphicsItem(this =" << ((void*)item)
- << ", parent =" << ((void*)item->parentItem())
+ if (QGraphicsObject *o = item->toGraphicsObject())
+ debug << o->metaObject()->className();
+ else
+ debug << "QGraphicsItem";
+ debug << "(this =" << (void*)item
+ << ", parent =" << (void*)item->parentItem()
<< ", pos =" << item->pos()
<< ", z =" << item->zValue() << ", flags = "
<< item->flags() << ")";
diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h
index 59c6dba..4aeae39 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.h
+++ b/src/gui/graphicsview/qgraphicslayout_p.h
@@ -60,6 +60,8 @@
#include "qgraphicslayout.h"
#include "qgraphicslayoutitem_p.h"
#include <QtGui/qstyle.h>
+#include <QtGui/qwidget.h>
+#include <QtGui/qstyleoption.h>
QT_BEGIN_NAMESPACE
@@ -76,6 +78,55 @@ inline bool qt_graphicsLayoutDebug()
}
#endif
+
+class QLayoutStyleInfo
+{
+public:
+ inline QLayoutStyleInfo() { invalidate(); }
+ inline QLayoutStyleInfo(QStyle *style, QWidget *widget)
+ : m_valid(true), m_style(style), m_widget(widget)
+ {
+ Q_ASSERT(style);
+ if (widget) //###
+ m_styleOption.initFrom(widget);
+ m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ }
+
+ inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; }
+
+ inline QStyle *style() const { return m_style; }
+ inline QWidget *widget() const { return m_widget; }
+
+ inline bool operator==(const QLayoutStyleInfo &other)
+ { return m_style == other.m_style && m_widget == other.m_widget; }
+ inline bool operator!=(const QLayoutStyleInfo &other)
+ { return !(*this == other); }
+
+ inline void setDefaultSpacing(Qt::Orientation o, qreal spacing){
+ if (spacing >= 0)
+ m_defaultSpacing[o - 1] = spacing;
+ }
+
+ inline qreal defaultSpacing(Qt::Orientation o) const {
+ return m_defaultSpacing[o - 1];
+ }
+
+ inline qreal perItemSpacing(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation) const
+ {
+ Q_ASSERT(style());
+ return style()->layoutSpacing(control1, control2, orientation, &m_styleOption, widget());
+ }
+private:
+ bool m_valid;
+ QStyle *m_style;
+ QWidget *m_widget;
+ QStyleOption m_styleOption;
+ qreal m_defaultSpacing[2];
+};
+
class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsLayout)
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index 64c51ad..e9173a9 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -397,7 +397,7 @@ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next)
do {
if (child->isEnabled()
&& child->isVisibleTo(widget)
- && (child->focusPolicy() & focus_flag == focus_flag)
+ && ((child->focusPolicy() & focus_flag) == focus_flag)
&& !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
return child;
}
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index c459d21..a62e486 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -525,6 +525,14 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
item->d_func()->scene = 0;
+ //We need to remove all children first because they might use their parent
+ //attributes (e.g. sceneTransform).
+ if (!item->d_ptr->inDestructor) {
+ // Remove all children recursively
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ q->removeItem(item->d_ptr->children.at(i));
+ }
+
// Unregister focus proxy.
item->d_ptr->resetFocusProxy();
@@ -571,12 +579,6 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
++iterator;
}
- if (!item->d_ptr->inDestructor) {
- // Remove all children recursively
- for (int i = 0; i < item->d_ptr->children.size(); ++i)
- q->removeItem(item->d_ptr->children.at(i));
- }
-
if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
leaveModal(item);
@@ -4910,7 +4912,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
continue;
}
- if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) {
+ if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
if (!viewPrivate->updateRect(paintedViewBoundingRect))
paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 710c745..f72aa8a 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -3319,6 +3319,14 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
if (!(d->optimizationFlags & IndirectPainting)) {
d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
&d->exposedRegion, viewport());
+ // Make sure the painter's world transform is restored correctly when
+ // drawing without painter state protection (DontSavePainterState).
+ // We only change the worldTransform() so there's no need to do a full-blown
+ // save() and restore(). Also note that we don't have to do this in case of
+ // IndirectPainting (the else branch), because in that case we always save()
+ // and restore() in QGraphicsScene::drawItems().
+ if (!d->scene->d_func()->painterStateProtection)
+ painter.setWorldTransform(viewTransform);
} else {
// Find all exposed items
bool allItems = false;
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 35a3c13..d70a281 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -1352,6 +1352,8 @@ void QGraphicsWidget::changeEvent(QEvent *event)
case QEvent::StyleChange:
// ### Don't unset if the margins are explicitly set.
unsetWindowFrameMargins();
+ if (d->layout)
+ d->layout->invalidate();
case QEvent::FontChange:
update();
updateGeometry();
diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h
index a42a537..ed335a8 100644
--- a/src/gui/graphicsview/qgridlayoutengine_p.h
+++ b/src/gui/graphicsview/qgridlayoutengine_p.h
@@ -59,7 +59,7 @@
#include "qmap.h"
#include "qpair.h"
#include "qvector.h"
-
+#include "qgraphicslayout_p.h"
#include <float.h>
QT_BEGIN_NAMESPACE
@@ -128,29 +128,6 @@ public:
};
-class QLayoutStyleInfo
-{
-public:
- inline QLayoutStyleInfo() { invalidate(); }
- inline QLayoutStyleInfo(QStyle *style, QWidget *widget)
- : q_valid(true), q_style(style), q_widget(widget) {}
-
- inline void invalidate() { q_valid = false; q_style = 0; q_widget = 0; }
-
- inline QStyle *style() const { return q_style; }
- inline QWidget *widget() const { return q_widget; }
-
- inline bool operator==(const QLayoutStyleInfo &other)
- { return q_style == other.q_style && q_widget == other.q_widget; }
- inline bool operator!=(const QLayoutStyleInfo &other)
- { return !(*this == other); }
-
-private:
- bool q_valid;
- QStyle *q_style;
- QWidget *q_widget;
-};
-
class QGridLayoutBox
{
public:
diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp
index b8f8fb4..86b10b4 100644
--- a/src/gui/graphicsview/qsimplex_p.cpp
+++ b/src/gui/graphicsview/qsimplex_p.cpp
@@ -108,10 +108,8 @@ void QSimplex::clearDataStructures()
// Constraints
for (int i = 0; i < constraints.size(); ++i) {
delete constraints[i]->helper.first;
- constraints[i]->helper.first = 0;
- constraints[i]->helper.second = 0.0;
delete constraints[i]->artificial;
- constraints[i]->artificial = 0;
+ delete constraints[i];
}
constraints.clear();
@@ -137,7 +135,23 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
if (newConstraints.isEmpty())
return true; // we are ok with no constraints
- constraints = newConstraints;
+
+ // Make deep copy of constraints. We need this copy because we may change
+ // them in the simplification method.
+ for (int i = 0; i < newConstraints.size(); ++i) {
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->constant = newConstraints[i]->constant;
+ c->ratio = newConstraints[i]->ratio;
+ c->variables = newConstraints[i]->variables;
+ constraints << c;
+ }
+
+ // Remove constraints of type Var == K and replace them for their value.
+ if (!simplifyConstraints(&constraints)) {
+ qWarning() << "QSimplex: No feasible solution!";
+ clearDataStructures();
+ return false;
+ }
///////////////////////////////////////
// Prepare variables and constraints //
@@ -508,11 +522,21 @@ qreal QSimplex::solver(solverFactor factor)
// Remove old objective
clearRow(0);
- // Set new objective
+ // Set new objective in the first row of the simplex matrix
+ qreal resultOffset = 0;
QHash<QSimplexVariable *, qreal>::const_iterator iter;
for (iter = objective->variables.constBegin();
iter != objective->variables.constEnd();
++iter) {
+
+ // Check if the variable was removed in the simplification process.
+ // If so, we save its offset to the objective function and skip adding
+ // it to the matrix.
+ if (iter.key()->index == -1) {
+ resultOffset += iter.value() * iter.key()->result;
+ continue;
+ }
+
setValueAt(0, iter.key()->index, -1 * factor * iter.value());
}
@@ -525,7 +549,9 @@ qreal QSimplex::solver(solverFactor factor)
}
#endif
- return factor * valueAt(0, columns - 1);
+ // Return the value calculated by the simplex plus the value of the
+ // fixed variables.
+ return (factor * valueAt(0, columns - 1)) + resultOffset;
}
/*!
@@ -571,4 +597,77 @@ void QSimplex::collectResults()
}
}
+/*!
+ \internal
+
+ Looks for single-valued variables and remove them from the constraints list.
+*/
+bool QSimplex::simplifyConstraints(QList<QSimplexConstraint *> *constraints)
+{
+ QHash<QSimplexVariable *, qreal> results; // List of single-valued variables
+ bool modified = true; // Any chance more optimization exists?
+
+ while (modified) {
+ modified = false;
+
+ // For all constraints
+ QList<QSimplexConstraint *>::iterator iter = constraints->begin();
+ while (iter != constraints->end()) {
+ QSimplexConstraint *c = *iter;
+ if ((c->ratio == QSimplexConstraint::Equal) && (c->variables.count() == 1)) {
+ // Check whether this is a constraint of type Var == K
+ // If so, save its value to "results".
+ QSimplexVariable *variable = c->variables.constBegin().key();
+ qreal result = c->constant / c->variables.value(variable);
+
+ results.insert(variable, result);
+ variable->result = result;
+ variable->index = -1;
+ modified = true;
+
+ }
+
+ // Replace known values among their variables
+ QHash<QSimplexVariable *, qreal>::const_iterator r;
+ for (r = results.constBegin(); r != results.constEnd(); ++r) {
+ if (c->variables.contains(r.key())) {
+ c->constant -= r.value() * c->variables.take(r.key());
+ modified = true;
+ }
+ }
+
+ // Keep it normalized
+ if (c->constant < 0)
+ c->invert();
+
+ if (c->variables.isEmpty()) {
+ // If constraint became empty due to substitution, delete it.
+ if (c->isSatisfied() == false)
+ // We must ensure that the constraint soon to be deleted would not
+ // make the problem unfeasible if left behind. If that's the case,
+ // we return false so the simplex solver can properly report that.
+ return false;
+
+ delete c;
+ iter = constraints->erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+ }
+
+ return true;
+}
+
+void QSimplexConstraint::invert()
+{
+ constant = -constant;
+ ratio = Ratio(2 - ratio);
+
+ QHash<QSimplexVariable *, qreal>::iterator iter;
+ for (iter = variables.begin(); iter != variables.end(); ++iter) {
+ iter.value() = -iter.value();
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h
index 51991a9..084ad7f 100644
--- a/src/gui/graphicsview/qsimplex_p.h
+++ b/src/gui/graphicsview/qsimplex_p.h
@@ -63,7 +63,7 @@ struct QSimplexVariable
QSimplexVariable() : result(0), index(0) {}
qreal result;
- uint index;
+ int index;
};
@@ -95,7 +95,8 @@ struct QSimplexConstraint
QPair<QSimplexVariable *, qreal> helper;
QSimplexVariable * artificial;
-#ifdef QT_DEBUG
+ void invert();
+
bool isSatisfied() {
qreal leftHandSide(0);
@@ -106,7 +107,7 @@ struct QSimplexConstraint
Q_ASSERT(constant > 0 || qFuzzyCompare(1, 1 + constant));
- if (qFuzzyCompare(1000 + leftHandSide, 1000 + constant))
+ if ((leftHandSide == constant) || qFuzzyCompare(1000 + leftHandSide, 1000 + constant))
return true;
switch (ratio) {
@@ -118,6 +119,30 @@ struct QSimplexConstraint
return false;
}
}
+
+#ifdef QT_DEBUG
+ QString toString() {
+ QString result;
+ result += QString::fromAscii("-- QSimplexConstraint %1 --").arg(quintptr(this), 0, 16);
+
+ QHash<QSimplexVariable *, qreal>::const_iterator iter;
+ for (iter = variables.constBegin(); iter != variables.constEnd(); ++iter) {
+ result += QString::fromAscii(" %1 x %2").arg(iter.value()).arg(quintptr(iter.key()), 0, 16);
+ }
+
+ switch (ratio) {
+ case LessOrEqual:
+ result += QString::fromAscii(" (less) <= %1").arg(constant);
+ break;
+ case MoreOrEqual:
+ result += QString::fromAscii(" (more) >= %1").arg(constant);
+ break;
+ default:
+ result += QString::fromAscii(" (eqal) == %1").arg(constant);
+ }
+
+ return result;
+ }
#endif
};
@@ -129,7 +154,6 @@ public:
qreal solveMin();
qreal solveMax();
- QList<QSimplexVariable *> constraintsVariables();
bool setConstraints(const QList<QSimplexConstraint *> constraints);
void setObjective(QSimplexConstraint *objective);
@@ -145,6 +169,7 @@ private:
void combineRows(int toIndex, int fromIndex, qreal factor);
// Simplex
+ bool simplifyConstraints(QList<QSimplexConstraint *> *constraints);
int findPivotColumn();
int pivotRowForColumn(int column);
void reducedRowEchelon();
@@ -168,11 +193,6 @@ private:
qreal *matrix;
};
-inline QList<QSimplexVariable *> QSimplex::constraintsVariables()
-{
- return variables;
-}
-
inline qreal QSimplex::valueAt(int rowIndex, int columnIndex)
{
return matrix[rowIndex * columns + columnIndex];
diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h
index b4f0957..f438148 100644
--- a/src/gui/itemviews/qabstractitemview.h
+++ b/src/gui/itemviews/qabstractitemview.h
@@ -361,6 +361,7 @@ private:
friend class QTreeViewPrivate; // needed to compile with MSVC
friend class QAccessibleItemRow;
+ friend class QListModeViewBase;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractItemView::EditTriggers)
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index fcf381a..66b7662 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -164,7 +164,8 @@ public:
}
#ifndef QT_NO_DRAGANDDROP
- QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
+ virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
+
inline bool canDecode(QDropEvent *e) const {
QStringList modelTypes = model->mimeTypes();
const QMimeData *mime = e->mimeData();
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 3bd9a19..6f2cff9 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -2516,6 +2516,8 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const
Q_D(const QHeaderView);
Q_ASSERT(logicalIndex >= 0);
+ ensurePolished();
+
// use SizeHintRole
QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
if (variant.isValid())
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index 871a4b1..3b3036d 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -255,7 +255,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
\row \o \l Qt::BackgroundRole \o QBrush
\row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead)
\row \o \l Qt::CheckStateRole \o Qt::CheckState
- \row \o \l Qt::DecorationRole \o QIcon and QColor
+ \row \o \l Qt::DecorationRole \o QIcon, QPixmap and QColor
\row \o \l Qt::DisplayRole \o QString and types with a string representation
\row \o \l Qt::EditRole \o See QItemEditorFactory for details
\row \o \l Qt::FontRole \o QFont
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index dfebe03..f2ccb6e 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -599,7 +599,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
while (itParent.isValid() && itParent.parent() != parent)
itParent = itParent.parent();
- if (parent.isValid() && start <= itParent.row() && itParent.row() <= end) {
+ if (itParent.isValid() && start <= itParent.row() && itParent.row() <= end) {
deselected.append(*it);
it = ranges.erase(it);
} else {
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index f58f458..109d760 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -853,8 +853,13 @@ void QListView::resizeEvent(QResizeEvent *e)
*/
void QListView::dragMoveEvent(QDragMoveEvent *e)
{
- if (!d_func()->commonListView->filterDragMoveEvent(e))
- QAbstractItemView::dragMoveEvent(e);
+ Q_D(QListView);
+ if (!d->commonListView->filterDragMoveEvent(e)) {
+ if (viewMode() == QListView::ListMode && flow() == QListView::LeftToRight)
+ static_cast<QListModeViewBase *>(d->commonListView)->dragMoveEvent(e);
+ else
+ QAbstractItemView::dragMoveEvent(e);
+ }
}
@@ -1804,6 +1809,16 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const
return selection;
}
+#ifndef QT_NO_DRAGANDDROP
+QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const
+{
+ if (viewMode == QListView::ListMode && flow == QListView::LeftToRight)
+ return static_cast<QListModeViewBase *>(commonListView)->position(pos, rect, idx);
+ else
+ return QAbstractItemViewPrivate::position(pos, rect, idx);
+}
+#endif
+
/*
* Common ListView Implementation
*/
@@ -1893,6 +1908,96 @@ void QListModeViewBase::paintDragDrop(QPainter *painter)
// in IconMode, it makes no sense to show it
dd->paintDropIndicator(painter);
}
+
+QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const
+{
+ QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport;
+ if (!dd->overwrite) {
+ const int margin = 2;
+ if (pos.x() - rect.left() < margin) {
+ r = QAbstractItemView::AboveItem; // Visually, on the left
+ } else if (rect.right() - pos.x() < margin) {
+ r = QAbstractItemView::BelowItem; // Visually, on the right
+ } else if (rect.contains(pos, true)) {
+ r = QAbstractItemView::OnItem;
+ }
+ } else {
+ QRect touchingRect = rect;
+ touchingRect.adjust(-1, -1, 1, 1);
+ if (touchingRect.contains(pos, false)) {
+ r = QAbstractItemView::OnItem;
+ }
+ }
+
+ if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled)))
+ r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem;
+
+ return r;
+}
+
+void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
+{
+ if (qq->dragDropMode() == QAbstractItemView::InternalMove
+ && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction)))
+ return;
+
+ // ignore by default
+ event->ignore();
+
+ QModelIndex index = qq->indexAt(event->pos());
+ dd->hover = index;
+ if (!dd->droppingOnItself(event, index)
+ && dd->canDecode(event)) {
+
+ if (index.isValid() && dd->showDropIndicator) {
+ QRect rect = qq->visualRect(index);
+ dd->dropIndicatorPosition = position(event->pos(), rect, index);
+ switch (dd->dropIndicatorPosition) {
+ case QAbstractItemView::AboveItem:
+ if (dd->isIndexDropEnabled(index.parent())) {
+ dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height());
+ event->accept();
+ } else {
+ dd->dropIndicatorRect = QRect();
+ }
+ break;
+ case QAbstractItemView::BelowItem:
+ if (dd->isIndexDropEnabled(index.parent())) {
+ dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height());
+ event->accept();
+ } else {
+ dd->dropIndicatorRect = QRect();
+ }
+ break;
+ case QAbstractItemView::OnItem:
+ if (dd->isIndexDropEnabled(index)) {
+ dd->dropIndicatorRect = rect;
+ event->accept();
+ } else {
+ dd->dropIndicatorRect = QRect();
+ }
+ break;
+ case QAbstractItemView::OnViewport:
+ dd->dropIndicatorRect = QRect();
+ if (dd->isIndexDropEnabled(qq->rootIndex())) {
+ event->accept(); // allow dropping in empty areas
+ }
+ break;
+ }
+ } else {
+ dd->dropIndicatorRect = QRect();
+ dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
+ if (dd->isIndexDropEnabled(qq->rootIndex())) {
+ event->accept(); // allow dropping in empty areas
+ }
+ }
+ dd->viewport->update();
+ } // can decode
+
+ if (dd->shouldAutoScroll(event->pos()))
+ qq->startAutoScroll();
+}
+
#endif //QT_NO_DRAGANDDROP
void QListModeViewBase::updateVerticalScrollBar(const QSize &step)
diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h
index de4c7f3..3f8f9db 100644
--- a/src/gui/itemviews/qlistview_p.h
+++ b/src/gui/itemviews/qlistview_p.h
@@ -231,6 +231,11 @@ public:
#ifndef QT_NO_DRAGANDDROP
void paintDragDrop(QPainter *painter);
+
+ // The next two methods are to be used on LefToRight flow only.
+ // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}.
+ QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
+ void dragMoveEvent(QDragMoveEvent *e);
#endif
private:
@@ -356,6 +361,10 @@ public:
QItemSelection selection(const QRect &rect) const;
void selectAll(QItemSelectionModel::SelectionFlags command);
+#ifndef QT_NO_DRAGANDDROP
+ virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
+#endif
+
inline void setGridSize(const QSize &size) { grid = size; }
inline QSize gridSize() const { return grid; }
inline void setWrapping(bool b) { wrap = b; }
diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp
index a978d0f..5dd1d76 100644
--- a/src/gui/itemviews/qlistwidget.cpp
+++ b/src/gui/itemviews/qlistwidget.cpp
@@ -169,6 +169,20 @@ QListWidgetItem *QListModel::take(int row)
return item;
}
+void QListModel::move(int srcRow, int dstRow)
+{
+ if (srcRow == dstRow
+ || srcRow < 0 || srcRow >= items.count()
+ || dstRow < 0 || dstRow >= items.count())
+ return;
+
+ beginMoveRows(QModelIndex(), srcRow, srcRow, QModelIndex(), dstRow);
+ if (srcRow < dstRow)
+ --dstRow;
+ items.move(srcRow, dstRow);
+ endMoveRows();
+}
+
int QListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : items.count();
@@ -1804,22 +1818,15 @@ void QListWidget::dropEvent(QDropEvent *event) {
if (persIndexes.contains(topIndex))
return;
+ qSort(persIndexes); // The dropped items will remain in the same visual order.
QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
- QList<QListWidgetItem *> taken;
- for (int i = 0; i < persIndexes.count(); ++i)
- taken.append(takeItem(persIndexes.at(i).row()));
-
- // insert them back in at their new positions
+ int r = row == -1 ? count() : (dropRow.row() >= 0 ? dropRow.row() : row);
for (int i = 0; i < persIndexes.count(); ++i) {
- // Either at a specific point or appended
- if (row == -1) {
- insertItem(count(), taken.takeFirst());
- } else {
- int r = dropRow.row() >= 0 ? dropRow.row() : row;
- insertItem(qMin(r, count()), taken.takeFirst());
- }
+ const QPersistentModelIndex &pIndex = persIndexes.at(i);
+ d->listModel()->move(pIndex.row(), r);
+ r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
}
event->accept();
diff --git a/src/gui/itemviews/qlistwidget_p.h b/src/gui/itemviews/qlistwidget_p.h
index 69cfa26..b5f28e3 100644
--- a/src/gui/itemviews/qlistwidget_p.h
+++ b/src/gui/itemviews/qlistwidget_p.h
@@ -77,7 +77,7 @@ public:
{ return *i2 < *i1; }
};
-class QListModel : public QAbstractListModel
+class Q_AUTOTEST_EXPORT QListModel : public QAbstractListModel
{
Q_OBJECT
public:
@@ -90,6 +90,7 @@ public:
void insert(int row, const QStringList &items);
void remove(QListWidgetItem *item);
QListWidgetItem *take(int row);
+ void move(int srcRow, int dstRow);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index 1c36787..1ca0391 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -148,7 +148,7 @@ public:
\row \o \l Qt::BackgroundRole \o QBrush
\row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead)
\row \o \l Qt::CheckStateRole \o Qt::CheckState
- \row \o \l Qt::DecorationRole \o QIcon and QColor
+ \row \o \l Qt::DecorationRole \o QIcon, QPixmap, QImage and QColor
\row \o \l Qt::DisplayRole \o QString and types with a string representation
\row \o \l Qt::EditRole \o See QItemEditorFactory for details
\row \o \l Qt::FontRole \o QFont
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 2a937f1..02e5fff 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -117,7 +117,7 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
Index::iterator it_y = index.lowerBound(-span->bottom());
Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
while (-it_y.key() <= span->top() + old_height -1) {
- if(-it_y.key() != span->bottom()) {
+ if (-it_y.key() > span->bottom()) {
(*it_y).remove(-span->left());
if (it_y->isEmpty()) {
it_y = index.erase(it_y) - 1;
@@ -544,6 +544,47 @@ void QSpanCollection::updateRemovedColumns(int start, int end)
qDeleteAll(toBeDeleted);
}
+#ifdef QT_BUILD_INTERNAL
+/*!
+ \internal
+ Checks whether the span index structure is self-consistent, and consistent with the spans list.
+*/
+bool QSpanCollection::checkConsistency() const
+{
+ for (Index::const_iterator it_y = index.begin(); it_y != index.end(); ++it_y) {
+ int y = -it_y.key();
+ const SubIndex &subIndex = it_y.value();
+ for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) {
+ int x = -it.key();
+ Span *span = it.value();
+ if (!spans.contains(span) || span->left() != x
+ || y < span->top() || y > span->bottom())
+ return false;
+ }
+ }
+
+ foreach (const Span *span, spans) {
+ if (span->width() < 1 || span->height() < 1
+ || (span->width() == 1 && span->height() == 1))
+ return false;
+ for (int y = span->top(); y <= span->bottom(); ++y) {
+ Index::const_iterator it_y = index.find(-y);
+ if (it_y == index.end()) {
+ if (y == span->top())
+ return false;
+ else
+ continue;
+ }
+ const SubIndex &subIndex = it_y.value();
+ SubIndex::const_iterator it = subIndex.find(-span->left());
+ if (it == subIndex.end() || it.value() != span)
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
class QTableCornerButton : public QAbstractButton
{
Q_OBJECT
@@ -2065,6 +2106,8 @@ int QTableView::sizeHintForRow(int row) const
if (!model())
return -1;
+ ensurePolished();
+
int left = qMax(0, columnAt(0));
int right = columnAt(d->viewport->width());
if (right == -1) // the table don't have enough columns to fill the viewport
@@ -2122,6 +2165,8 @@ int QTableView::sizeHintForColumn(int column) const
if (!model())
return -1;
+ ensurePolished();
+
int top = qMax(0, rowAt(0));
int bottom = rowAt(d->viewport->height());
if (!isVisible() || bottom == -1) // the table don't have enough rows to fill the viewport
diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h
index 9fa14c2..6b19ded 100644
--- a/src/gui/itemviews/qtableview_p.h
+++ b/src/gui/itemviews/qtableview_p.h
@@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE
* The key of the first map is the row where the subspan starts, the value of the first map is
* a list (map) of all subspans that starts at the same row. It is indexed with its row
*/
-class QSpanCollection
+class Q_AUTOTEST_EXPORT QSpanCollection
{
public:
struct Span
@@ -112,6 +112,10 @@ public:
void updateRemovedRows(int start, int end);
void updateRemovedColumns(int start, int end);
+#ifdef QT_BUILD_INTERNAL
+ bool checkConsistency() const;
+#endif
+
typedef QLinkedList<Span *> SpanList;
SpanList spans; //lists of all spans
private:
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index f37d8c7..bad9dfe 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -1226,8 +1226,12 @@ bool QTreeView::viewportEvent(QEvent *event)
if (oldIndex != newIndex) {
QRect oldRect = visualRect(oldIndex);
QRect newRect = visualRect(newIndex);
- viewport()->update(oldRect.left() - d->indent, oldRect.top(), d->indent, oldRect.height());
- viewport()->update(newRect.left() - d->indent, newRect.top(), d->indent, newRect.height());
+ oldRect.rLeft() -= d->indent;
+ newRect.rLeft() -= d->indent;
+ //we need to paint the whole items (including the decoration) so that when the user
+ //moves the mouse over those elements they are updated
+ viewport()->update(oldRect);
+ viewport()->update(newRect);
}
}
if (selectionBehavior() == QAbstractItemView::SelectRows) {
@@ -1422,8 +1426,9 @@ void QTreeView::drawTree(QPainter *painter, const QRegion &region) const
for (; i < viewItems.count() && y <= area.bottom(); ++i) {
const int itemHeight = d->itemHeight(i);
option.rect.setRect(0, y, viewportWidth, itemHeight);
- option.state = state | (viewItems.at(i).expanded
- ? QStyle::State_Open : QStyle::State_None);
+ option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None)
+ | (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None)
+ | (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None);
d->current = i;
d->spanning = viewItems.at(i).spanning;
if (!multipleRects || !drawn.contains(i)) {
@@ -1748,14 +1753,8 @@ void QTreeView::drawBranches(QPainter *painter, const QRect &rect,
opt.rect = primitive;
const bool expanded = viewItem.expanded;
- const bool children = (((expanded && viewItem.total > 0)) // already laid out and has children
- || d->hasVisibleChildren(index)); // not laid out yet, so we don't know
- bool moreSiblings = false;
- if (d->hiddenIndexes.isEmpty())
- moreSiblings = (d->model->rowCount(parent) - 1 > index.row());
- else
- moreSiblings = ((d->viewItems.size() > item +1)
- && (d->viewItems.at(item + 1).index.parent() == parent));
+ const bool children = viewItem.hasChildren;
+ bool moreSiblings = viewItem.hasMoreSiblings;
opt.state = QStyle::State_Item | extraFlags
| (moreSiblings ? QStyle::State_Sibling : QStyle::State_None)
@@ -1845,9 +1844,7 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
return; // user clicked outside the items
const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
-
- int column = d->header->logicalIndexAt(event->x());
- QPersistentModelIndex persistent = firstColumnIndex.sibling(firstColumnIndex.row(), column);
+ const QPersistentModelIndex persistent = indexAt(event->pos());
if (d->pressedIndex != persistent) {
mousePressEvent(event);
@@ -3127,7 +3124,7 @@ void QTreeViewPrivate::layout(int i)
int hidden = 0;
int last = 0;
int children = 0;
-
+ QTreeViewItem *item = 0;
for (int j = first; j < first + count; ++j) {
current = model->index(j - first, 0, parent);
if (isRowHidden(current)) {
@@ -3135,17 +3132,25 @@ void QTreeViewPrivate::layout(int i)
last = j - hidden + children;
} else {
last = j - hidden + children;
- viewItems[last].index = current;
- viewItems[last].level = level;
- viewItems[last].height = 0;
- viewItems[last].spanning = q->isFirstColumnSpanned(current.row(), parent);
- viewItems[last].expanded = false;
- viewItems[last].total = 0;
+ if (item)
+ item->hasMoreSiblings = true;
+ item = &viewItems[last];
+ item->index = current;
+ item->level = level;
+ item->height = 0;
+ item->spanning = q->isFirstColumnSpanned(current.row(), parent);
+ item->expanded = false;
+ item->total = 0;
+ item->hasMoreSiblings = false;
if (isIndexExpanded(current)) {
- viewItems[last].expanded = true;
+ item->expanded = true;
layout(last);
- children += viewItems[last].total;
+ item = &viewItems[last];
+ children += item->total;
+ item->hasChildren = item->total > 0;
last = j - hidden + children;
+ } else {
+ item->hasChildren = hasVisibleChildren(current);
}
}
}
diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h
index def8253..62676d8 100644
--- a/src/gui/itemviews/qtreeview_p.h
+++ b/src/gui/itemviews/qtreeview_p.h
@@ -66,7 +66,9 @@ struct QTreeViewItem
QModelIndex index; // we remove items whenever the indexes are invalidated
uint expanded : 1;
uint spanning : 1;
- uint total : 30; // total number of children visible
+ uint hasChildren : 1; // if the item has visible children (even if collapsed)
+ uint hasMoreSiblings : 1;
+ uint total : 28; // total number of children visible
uint level : 16; // indentation
int height : 16; // row height
};
diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp
index 6e074a1..b01d40f 100644
--- a/src/gui/kernel/qguiplatformplugin.cpp
+++ b/src/gui/kernel/qguiplatformplugin.cpp
@@ -288,6 +288,8 @@ int QGuiPlatformPlugin::platformHint(PlatformHint hint)
#endif
//by default keep ret = 0 so QCommonStyle will use the style default
break;
+ default:
+ break;
}
return ret;
}
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 5fa9a92..1951ab2 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1825,18 +1825,6 @@ void QWidgetPrivate::setDirtyOpaqueRegion()
pd->setDirtyOpaqueRegion();
}
-QRegion QWidgetPrivate::getOpaqueRegion() const
-{
- Q_Q(const QWidget);
-
- QRegion r = isOpaque ? q->rect() : getOpaqueChildren();
- if (extra && extra->hasMask)
- r &= extra->mask;
- if (r.isEmpty())
- return r;
- return r & clipRect();
-}
-
const QRegion &QWidgetPrivate::getOpaqueChildren() const
{
if (!dirtyOpaqueChildren)
@@ -1851,9 +1839,17 @@ const QRegion &QWidgetPrivate::getOpaqueChildren() const
continue;
const QPoint offset = child->geometry().topLeft();
- that->opaqueChildren += child->d_func()->getOpaqueRegion().translated(offset);
+ QWidgetPrivate *childd = child->d_func();
+ QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
+ if (childd->extra && childd->extra->hasMask)
+ r &= childd->extra->mask;
+ if (r.isEmpty())
+ continue;
+ r.translate(offset);
+ that->opaqueChildren += r;
}
+ that->opaqueChildren &= q_func()->rect();
that->dirtyOpaqueChildren = false;
return that->opaqueChildren;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 159a3f2..5cea641 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -386,7 +386,6 @@ public:
bool paintOnScreen() const;
void invalidateGraphicsEffectsRecursively();
- QRegion getOpaqueRegion() const;
const QRegion &getOpaqueChildren() const;
void setDirtyOpaqueRegion();
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 70d130a..fbd461f 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -4661,7 +4661,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_ToolBarIconSize:
ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolBarIconSize);
if (!ret)
- ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
+ ret = int(QStyleHelper::dpiScaled(24.));
break;
case PM_TabBarIconSize:
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 09f5d36..f880351 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -5514,9 +5514,6 @@ int QPlastiqueStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_MenuHMargin:
ret = 0;
break;
- case PM_ToolBarIconSize:
- ret = 24;
- break;
case PM_ButtonShiftHorizontal:
case PM_ButtonShiftVertical:
ret = 1;
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 0f72440..5cf738e 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -454,9 +454,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
- case PM_ToolBarIconSize:
- ret = int(QStyleHelper::dpiScaled(24.));
- break;
case PM_DockWidgetTitleMargin:
ret = int(QStyleHelper::dpiScaled(2.));
break;
diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp
index 6cb8b40..aafd087 100644
--- a/src/gui/styles/qwindowsvistastyle.cpp
+++ b/src/gui/styles/qwindowsvistastyle.cpp
@@ -159,7 +159,7 @@ QWindowsVistaStyle::QWindowsVistaStyle()
}
//convert Qt state flags to uxtheme button states
-int buttonStateId(int flags, int partId)
+static int buttonStateId(int flags, int partId)
{
int stateId = 0;
if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) {
@@ -190,7 +190,7 @@ int buttonStateId(int flags, int partId)
return stateId;
}
-void Animation::paint(QPainter *painter, const QStyleOption *option)
+void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option)
{
Q_UNUSED(option);
Q_UNUSED(painter);
@@ -205,7 +205,7 @@ void Animation::paint(QPainter *painter, const QStyleOption *option)
+ ((1-alpha)*_secondaryImage)
*/
-void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
+void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
if (_secondaryImage.isNull() || _primaryImage.isNull())
return;
@@ -251,7 +251,7 @@ void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
initial and final state of the transition, depending on the time
difference between _startTime and current time.
*/
-void Transition::paint(QPainter *painter, const QStyleOption *option)
+void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
{
float alpha = 1.0;
if (_duration > 0) {
@@ -278,7 +278,7 @@ void Transition::paint(QPainter *painter, const QStyleOption *option)
secondary pulse images depending on the time difference between
_startTime and current time.
*/
-void Pulse::paint(QPainter *painter, const QStyleOption *option)
+void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
{
float alpha = 1.0;
if (_duration > 0) {
@@ -393,8 +393,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
startImage.fill(0);
QPainter startPainter(&startImage);
- Animation *anim = d->widgetAnimation(widget);
- Transition *t = new Transition;
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+ QWindowsVistaTransition *t = new QWindowsVistaTransition;
t->setWidget(w);
// If we have a running animation on the widget already, we will use that to paint the initial
@@ -531,7 +531,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
case PE_IndicatorCheckBox:
case PE_IndicatorRadioButton:
{
- if (Animation *a = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
a->paint(painter, option);
} else {
QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
@@ -644,7 +644,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
break;
case PE_FrameLineEdit:
- if (Animation *anim = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
anim->paint(painter, option);
} else {
QPainter *p = painter;
@@ -929,13 +929,13 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (doTransition) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
- Animation *anim = d->widgetAnimation(widget);
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
QStyleOptionButton opt = *button;
opt.state = (QStyle::State)oldState;
startImage.fill(0);
- Transition *t = new Transition;
+ QWindowsVistaTransition *t = new QWindowsVistaTransition;
t->setWidget(w);
QPainter startPainter(&startImage);
@@ -972,7 +972,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
{
- if (Animation *anim = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
anim->paint(painter, option);
} else {
name = QLatin1String("BUTTON");
@@ -999,14 +999,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
!(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
(state & State_Enabled) && (state & State_Active))
{
- Animation *anim = d->widgetAnimation(widget);
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
if (!anim && widget) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
alternateImage.fill(0);
- Pulse *pulse = new Pulse;
+ QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
pulse->setWidget(const_cast<QWidget*>(widget));
QPainter startPainter(&startImage);
@@ -1079,7 +1079,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) {
if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) {
- Animation *a = new Animation;
+ QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
a->setWidget(const_cast<QWidget*>(widget));
a->setStartTime(QTime::currentTime());
d->startAnimation(a);
@@ -1095,7 +1095,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QTime current = QTime::currentTime();
if (isIndeterminate) {
- if (Animation *a = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
int glowSize = 120;
int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
int animOffset = a->startTime().msecsTo(current) / 4;
@@ -1165,7 +1165,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
d->drawBackground(theme);
- if (Animation *a = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
int glowSize = 140;
int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
int animOffset = a->startTime().msecsTo(current) / 4;
@@ -1603,8 +1603,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (doTransition) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
- Animation *anim = d->widgetAnimation(widget);
- Transition *t = new Transition;
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+ QWindowsVistaTransition *t = new QWindowsVistaTransition;
t->setWidget(w);
if (!anim) {
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
@@ -1651,7 +1651,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
t->setDuration(500);
}
- if (Animation *anim = d->widgetAnimation(widget)) {
+ if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
anim->paint(painter, option);
return;
}
@@ -2533,7 +2533,7 @@ void QWindowsVistaStylePrivate::timerEvent()
!animations[i]->running() ||
!QWindowsVistaStylePrivate::useVista())
{
- Animation *a = animations.takeAt(i);
+ QWindowsVistaAnimation *a = animations.takeAt(i);
delete a;
}
}
@@ -2546,14 +2546,14 @@ void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
{
for (int i = animations.size() - 1 ; i >= 0 ; --i) {
if (animations[i]->widget() == w) {
- Animation *a = animations.takeAt(i);
+ QWindowsVistaAnimation *a = animations.takeAt(i);
delete a;
break;
}
}
}
-void QWindowsVistaStylePrivate::startAnimation(Animation *t)
+void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
{
Q_Q(QWindowsVistaStyle);
stopAnimation(t->widget());
@@ -2575,11 +2575,11 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const
}
-Animation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
+QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
{
if (!widget)
return 0;
- foreach (Animation *a, animations) {
+ foreach (QWindowsVistaAnimation *a, animations) {
if (a->widget() == widget)
return a;
}
diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h
index e9bbb77..04823c1 100644
--- a/src/gui/styles/qwindowsvistastyle_p.h
+++ b/src/gui/styles/qwindowsvistastyle_p.h
@@ -136,11 +136,11 @@ QT_BEGIN_NAMESPACE
#define TDLG_SECONDARYPANEL 8
#endif
-class Animation
+class QWindowsVistaAnimation
{
public :
- Animation() : _running(true) { }
- virtual ~Animation() { }
+ QWindowsVistaAnimation() : _running(true) { }
+ virtual ~QWindowsVistaAnimation() { }
QWidget * widget() const { return _widget; }
bool running() const { return _running; }
const QTime &startTime() const { return _startTime; }
@@ -161,11 +161,11 @@ protected:
// Handles state transition animations
-class Transition : public Animation
+class QWindowsVistaTransition : public QWindowsVistaAnimation
{
public :
- Transition() : Animation() {}
- virtual ~Transition() { }
+ QWindowsVistaTransition() : QWindowsVistaAnimation() {}
+ virtual ~QWindowsVistaTransition() { }
void setDuration(int duration) { _duration = duration; }
void setStartImage(const QImage &image) { _primaryImage = image; }
void setEndImage(const QImage &image) { _secondaryImage = image; }
@@ -176,11 +176,11 @@ public :
// Handles pulse animations (default buttons)
-class Pulse: public Animation
+class QWindowsVistaPulse: public QWindowsVistaAnimation
{
public :
- Pulse() : Animation() {}
- virtual ~Pulse() { }
+ QWindowsVistaPulse() : QWindowsVistaAnimation() {}
+ virtual ~QWindowsVistaPulse() { }
void setDuration(int duration) { _duration = duration; }
void setPrimaryImage(const QImage &image) { _primaryImage = image; }
void setAlternateImage(const QImage &image) { _secondaryImage = image; }
@@ -199,15 +199,15 @@ public:
~QWindowsVistaStylePrivate();
static bool resolveSymbols();
static inline bool useVista();
- void startAnimation(Animation *);
+ void startAnimation(QWindowsVistaAnimation *);
void stopAnimation(const QWidget *);
- Animation* widgetAnimation(const QWidget *) const;
+ QWindowsVistaAnimation* widgetAnimation(const QWidget *) const;
void timerEvent();
bool transitionsEnabled() const;
QWidget *treeViewHelper();
private:
- QList <Animation*> animations;
+ QList <QWindowsVistaAnimation*> animations;
QBasicTimer animationTimer;
QWidget *m_treeViewHelper;
};
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 1b4c380..447087c 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2324,22 +2324,22 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
*/
QFontInfo::QFontInfo(const QFont &font)
: d(font.d.data())
-{ d->ref.ref(); }
+{
+}
/*!
Constructs a copy of \a fi.
*/
QFontInfo::QFontInfo(const QFontInfo &fi)
- : d(fi.d)
-{ d->ref.ref(); }
+ : d(fi.d.data())
+{
+}
/*!
Destroys the font info object.
*/
QFontInfo::~QFontInfo()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -2347,7 +2347,7 @@ QFontInfo::~QFontInfo()
*/
QFontInfo &QFontInfo::operator=(const QFontInfo &fi)
{
- qAtomicAssign(d, fi.d);
+ d = fi.d.data();
return *this;
}
diff --git a/src/gui/text/qfontinfo.h b/src/gui/text/qfontinfo.h
index 335d761..0998949 100644
--- a/src/gui/text/qfontinfo.h
+++ b/src/gui/text/qfontinfo.h
@@ -43,6 +43,7 @@
#define QFONTINFO_H
#include <QtGui/qfont.h>
+#include <QtCore/qsharedpointer.h>
QT_BEGIN_HEADER
@@ -77,7 +78,7 @@ public:
bool exactMatch() const;
private:
- QFontPrivate *d;
+ QExplicitlySharedDataPointer<QFontPrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index ce122aa..b8c1b33 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -165,7 +165,6 @@ extern int qt_defaultDpi();
QFontMetrics::QFontMetrics(const QFont &font)
: d(font.d.data())
{
- d->ref.ref();
}
/*!
@@ -196,7 +195,6 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
d->screen = screen;
} else {
d = font.d.data();
- d->ref.ref();
}
}
@@ -205,8 +203,9 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
Constructs a copy of \a fm.
*/
QFontMetrics::QFontMetrics(const QFontMetrics &fm)
- : d(fm.d)
-{ d->ref.ref(); }
+ : d(fm.d.data())
+{
+}
/*!
Destroys the font metrics object and frees all allocated
@@ -214,8 +213,6 @@ QFontMetrics::QFontMetrics(const QFontMetrics &fm)
*/
QFontMetrics::~QFontMetrics()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -223,7 +220,7 @@ QFontMetrics::~QFontMetrics()
*/
QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm)
{
- qAtomicAssign(d, fm.d);
+ d = fm.d.data();
return *this;
}
@@ -536,7 +533,7 @@ int QFontMetrics::width(const QString &text, int len) const
if (len == 0)
return 0;
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -612,7 +609,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
int from = qMax(0, pos - 8);
int to = qMin(text.length(), pos + 8);
QString cstr = QString::fromRawData(text.unicode() + from, to - from);
- QTextEngine layout(cstr, d);
+ QTextEngine layout(cstr, d.data());
layout.ignoreBidi = true;
layout.itemize();
width = qRound(layout.width(pos-from, 1));
@@ -661,7 +658,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
@@ -770,7 +767,7 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te
QRectF rb;
QRectF rr(rect);
- qt_format_text(QFont(d), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
+ qt_format_text(QFont(d.data()), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
tabArrayLen, 0);
return rb.toAlignedRect();
@@ -831,7 +828,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -876,7 +873,7 @@ QString QFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, in
}
_text = _text.mid(posA);
}
- QStackTextEngine engine(_text, QFont(d));
+ QStackTextEngine engine(_text, QFont(d.data()));
return engine.elidedText(mode, width, flags);
}
@@ -989,9 +986,8 @@ int QFontMetrics::lineWidth() const
from the given \a fontMetrics object.
*/
QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics)
- : d(fontMetrics.d)
+ : d(fontMetrics.d.data())
{
- d->ref.ref();
}
/*!
@@ -1001,7 +997,7 @@ QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics)
*/
QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
{
- qAtomicAssign(d, other.d);
+ d = other.d.data();
return *this;
}
@@ -1021,7 +1017,6 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
QFontMetricsF::QFontMetricsF(const QFont &font)
: d(font.d.data())
{
- d->ref.ref();
}
/*!
@@ -1052,7 +1047,6 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
d->screen = screen;
} else {
d = font.d.data();
- d->ref.ref();
}
}
@@ -1061,8 +1055,9 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
Constructs a copy of \a fm.
*/
QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm)
- : d(fm.d)
-{ d->ref.ref(); }
+ : d(fm.d.data())
+{
+}
/*!
Destroys the font metrics object and frees all allocated
@@ -1070,8 +1065,6 @@ QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm)
*/
QFontMetricsF::~QFontMetricsF()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -1079,7 +1072,7 @@ QFontMetricsF::~QFontMetricsF()
*/
QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm)
{
- qAtomicAssign(d, fm.d);
+ d = fm.d.data();
return *this;
}
@@ -1374,7 +1367,7 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
*/
qreal QFontMetricsF::width(const QString &text) const
{
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, text.length()).toReal();
@@ -1451,7 +1444,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
if (len == 0)
return QRectF();
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
@@ -1559,7 +1552,7 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString&
tabArrayLen++;
QRectF rb;
- qt_format_text(QFont(d), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
+ qt_format_text(QFont(d.data()), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
tabArrayLen, 0);
return rb;
}
@@ -1624,7 +1617,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d);
+ QTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -1649,7 +1642,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
*/
QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const
{
- QStackTextEngine engine(text, QFont(d));
+ QStackTextEngine engine(text, QFont(d.data()));
return engine.elidedText(mode, QFixed::fromReal(width), flags);
}
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index 1147e3a..23200c5 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -43,6 +43,7 @@
#define QFONTMETRICS_H
#include <QtGui/qfont.h>
+#include <QtCore/qsharedpointer.h>
#ifndef QT_INCLUDE_COMPAT
#include <QtCore/qrect.h>
#endif
@@ -131,7 +132,7 @@ private:
friend class QFontMetricsF;
friend class QStackTextEngine;
- QFontPrivate *d;
+ QExplicitlySharedDataPointer<QFontPrivate> d;
};
@@ -187,7 +188,7 @@ public:
inline bool operator !=(const QFontMetricsF &other) const { return !operator==(other); }
private:
- QFontPrivate *d;
+ QExplicitlySharedDataPointer<QFontPrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index a8956b8..6978b6c 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -140,7 +140,7 @@ bool Qt::mightBeRichText(const QString& text)
/*!
Converts the plain text string \a plain to a HTML string with
- HTML metacharacters \c{<}, \c{>}, and \c{&} replaced by HTML
+ HTML metacharacters \c{<}, \c{>}, \c{&}, and \c{"} replaced by HTML
entities.
Example:
@@ -162,6 +162,8 @@ QString Qt::escape(const QString& plain)
rich += QLatin1String("&gt;");
else if (plain.at(i) == QLatin1Char('&'))
rich += QLatin1String("&amp;");
+ else if (plain.at(i) == QLatin1Char('"'))
+ rich += QLatin1String("&quot;");
else
rich += plain.at(i);
}
@@ -2038,7 +2040,7 @@ void QTextHtmlExporter::emitAttribute(const char *attribute, const QString &valu
html += QLatin1Char(' ');
html += QLatin1String(attribute);
html += QLatin1String("=\"");
- html += value;
+ html += Qt::escape(value);
html += QLatin1Char('"');
}
@@ -2302,12 +2304,12 @@ void QTextHtmlExporter::emitFontFamily(const QString &family)
{
html += QLatin1String(" font-family:");
- QLatin1Char quote('\'');
- if (family.contains(quote))
- quote = QLatin1Char('\"');
+ QLatin1String quote("\'");
+ if (family.contains(QLatin1Char('\'')))
+ quote = QLatin1String("&quot;");
html += quote;
- html += family;
+ html += Qt::escape(family);
html += quote;
html += QLatin1Char(';');
}
@@ -2341,13 +2343,13 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
const QString name = format.anchorName();
if (!name.isEmpty()) {
html += QLatin1String("<a name=\"");
- html += name;
+ html += Qt::escape(name);
html += QLatin1String("\"></a>");
}
const QString href = format.anchorHref();
if (!href.isEmpty()) {
html += QLatin1String("<a href=\"");
- html += href;
+ html += Qt::escape(href);
html += QLatin1String("\">");
closeAnchor = true;
}
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index ae56d36..6dbf15a 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -192,6 +192,8 @@ void QComboBoxPrivate::_q_modelReset()
lineEdit->setText(QString());
updateLineEditGeometry();
}
+ if (currentIndex.row() != indexBeforeChange)
+ _q_emitCurrentIndexChanged(currentIndex);
q->update();
}
@@ -992,14 +994,6 @@ void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIn
}
}
-void QComboBoxPrivate::_q_rowsAboutToBeInserted(const QModelIndex & parent,
- int /*start*/, int /*end*/)
-{
- if (parent != root)
- return;
- indexBeforeChange = currentIndex.row();
-}
-
void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
{
Q_Q(QComboBox);
@@ -1022,11 +1016,8 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int
}
}
-void QComboBoxPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
+void QComboBoxPrivate::_q_updateIndexBeforeChange()
{
- if (parent != root)
- return;
-
indexBeforeChange = currentIndex.row();
}
@@ -1868,15 +1859,17 @@ void QComboBox::setModel(QAbstractItemModel *model)
disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
+ this, SLOT(_q_updateIndexBeforeChange()));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ this, SLOT(_q_updateIndexBeforeChange()));
disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
+ disconnect(d->model, SIGNAL(modelAboutToBeReset()),
+ this, SLOT(_q_updateIndexBeforeChange()));
disconnect(d->model, SIGNAL(modelReset()),
this, SLOT(_q_modelReset()));
if (d->model->QObject::parent() == this)
@@ -1888,15 +1881,17 @@ void QComboBox::setModel(QAbstractItemModel *model)
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
+ this, SLOT(_q_updateIndexBeforeChange()));
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ this, SLOT(_q_updateIndexBeforeChange()));
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
connect(model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
+ connect(model, SIGNAL(modelAboutToBeReset()),
+ this, SLOT(_q_updateIndexBeforeChange()));
connect(model, SIGNAL(modelReset()),
this, SLOT(_q_modelReset()));
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index 6a85096..4089a09 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -308,9 +308,8 @@ private:
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 &))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_updateIndexBeforeChange())
Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end))
Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end))
Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
Q_PRIVATE_SLOT(d_func(), void _q_modelReset())
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index f7458c4..06e51e4 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -357,9 +357,8 @@ public:
#endif
void _q_resetButton();
void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
- void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end);
+ void _q_updateIndexBeforeChange();
void _q_rowsInserted(const QModelIndex & parent, int start, int end);
- void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end);
void _q_rowsRemoved(const QModelIndex & parent, int start, int end);
void updateArrow(QStyle::StateFlag state);
bool updateHoverControl(const QPoint &pos);
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 5a0a9d4..df131ee 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -2259,7 +2259,7 @@ QRect QDockAreaLayoutInfo::tabContentRect() const
** QDockAreaLayout
*/
-QDockAreaLayout::QDockAreaLayout(QMainWindow *win)
+QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : have_central(false)
{
mainWindow = win;
sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, win);
@@ -2582,7 +2582,9 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
{
QSize center_hint(0, 0);
QSize center_min(0, 0);
- bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
+ const bool old_have_central = have_central;
+ have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
+ const bool fallbackToSizeHints = !old_have_central && have_central;
if (have_central) {
center_hint = centralWidgetRect.size();
if (!center_hint.isValid())
@@ -2601,28 +2603,28 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
QSize left_hint = docks[QInternal::LeftDock].size();
- if (left_hint.isNull())
+ if (left_hint.isNull() || fallbackToSizeHints)
left_hint = docks[QInternal::LeftDock].sizeHint();
QSize left_min = docks[QInternal::LeftDock].minimumSize();
QSize left_max = docks[QInternal::LeftDock].maximumSize();
left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
QSize right_hint = docks[QInternal::RightDock].size();
- if (right_hint.isNull())
+ if (right_hint.isNull() || fallbackToSizeHints)
right_hint = docks[QInternal::RightDock].sizeHint();
QSize right_min = docks[QInternal::RightDock].minimumSize();
QSize right_max = docks[QInternal::RightDock].maximumSize();
right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
QSize top_hint = docks[QInternal::TopDock].size();
- if (top_hint.isNull())
+ if (top_hint.isNull() || fallbackToSizeHints)
top_hint = docks[QInternal::TopDock].sizeHint();
QSize top_min = docks[QInternal::TopDock].minimumSize();
QSize top_max = docks[QInternal::TopDock].maximumSize();
top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
QSize bottom_hint = docks[QInternal::BottomDock].size();
- if (bottom_hint.isNull())
+ if (bottom_hint.isNull() || fallbackToSizeHints)
bottom_hint = docks[QInternal::BottomDock].sizeHint();
QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 99a9dbb..1ed14ce 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -233,6 +233,7 @@ public:
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
int sep; // separator extent
+ bool have_central;
mutable QVector<QWidget*> separatorWidgets;
bool isValid() const;
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index 6710275..a8e2a37 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -685,8 +685,6 @@ void QDockWidgetPrivate::_q_toggleTopLevel()
void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
{
- Q_Q(QDockWidget);
-
if (state != 0)
return;
@@ -694,8 +692,6 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
- if (layout->layoutState.indexOf(q).isEmpty()) //The dock widget has not been added into the main window
- return;
if (layout->pluggingWidget != 0) // the main window is animating a docking operation
return;
@@ -1012,6 +1008,12 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
{
Q_Q(QDockWidget);
+ if (!floating && parent) {
+ QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
+ if (!mwlayout || mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea)
+ return; // this dockwidget can't be redocked
+ }
+
bool wasFloating = q->isFloating();
bool hidden = q->isHidden();
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index ea25901..1b5d1cd 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -1878,6 +1878,10 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if(snapToMouse) //position flowing left from the mouse
pos.setX(mouse.x()-size.width());
+ //if in a menubar, it should be right-aligned
+ if (qobject_cast<QMenuBar*>(d->causedPopup.widget))
+ pos.rx() -= size.width();
+
if (pos.x() < screen.left()+desktopFrame)
pos.setX(qMax(p.x(), screen.left()+desktopFrame));
if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index f2f0722..689d2e1 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -336,30 +336,25 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
const bool fitUp = (q->mapToGlobal(adjustedActionRect.topLeft()).y() >= popup_size.height());
const bool fitDown = (pos.y() + popup_size.height() <= screenRect.bottom());
+ const bool rtl = q->isRightToLeft();
const int actionWidth = adjustedActionRect.width();
if (!fitUp && !fitDown) { //we should shift the menu
- bool shouldShiftToRight = !q->isRightToLeft();
- if (q->isRightToLeft() && popup_size.width() > pos.x())
+ bool shouldShiftToRight = !rtl;
+ if (rtl && popup_size.width() > pos.x())
shouldShiftToRight = true;
else if (actionWidth + popup_size.width() + pos.x() > screenRect.right())
shouldShiftToRight = false;
- if (shouldShiftToRight)
- pos.rx() += actionWidth;
- else
- pos.rx() -= popup_size.width();
- } else if (q->isRightToLeft()) {
- pos.setX(pos.x()-(popup_size.width() - actionWidth));
- }
-
- if(pos.x() < screenRect.x()) {
- pos.setX(screenRect.x());
- } else {
- const int off = pos.x()+popup_size.width() - screenRect.right();
- if(off > 0)
- pos.setX(qMax(screenRect.x(), pos.x()-off));
-
+ if (shouldShiftToRight) {
+ pos.rx() += actionWidth + (rtl ? popup_size.width() : 0);
+ } else {
+ //shift to left
+ if (!rtl)
+ pos.rx() -= popup_size.width();
+ }
+ } else if (rtl) {
+ pos.rx() += actionWidth;
}
if(!defaultPopDown || (fitUp && !fitDown))
diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp
index e3121ae..520a802 100644
--- a/src/gui/widgets/qsplitter.cpp
+++ b/src/gui/widgets/qsplitter.cpp
@@ -360,13 +360,26 @@ void QSplitterPrivate::recalc(bool update)
before a hidden widget must be hidden.
*/
bool first = true;
+ bool allInvisible = n != 0;
for (int i = 0; i < n ; ++i) {
QSplitterLayoutStruct *s = list.at(i);
- s->handle->setHidden(first || s->widget->isHidden());
- if (!s->widget->isHidden())
+ bool widgetHidden = s->widget->isHidden();
+ if (allInvisible && !widgetHidden && !s->collapsed)
+ allInvisible = false;
+ s->handle->setHidden(first || widgetHidden);
+ if (!widgetHidden)
first = false;
}
+ if (allInvisible)
+ for (int i = 0; i < n ; ++i) {
+ QSplitterLayoutStruct *s = list.at(i);
+ if (!s->widget->isHidden()) {
+ s->collapsed = false;
+ break;
+ }
+ }
+
int fi = 2 * q->frameWidth();
int maxl = fi;
int minl = fi;
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 40c0b02..5596ca4 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -183,6 +183,9 @@ void QToolBarPrivate::setWindowState(bool floating, bool unplug, const QRect &re
if (visible)
q->show();
+
+ if (floating != wasFloating)
+ emit q->topLevelChanged(floating);
}
void QToolBarPrivate::initDrag(const QPoint &pos)
@@ -518,6 +521,19 @@ void QToolBarPrivate::plug(const QRect &r)
*/
/*!
+ \since 4.6
+
+ \fn void QToolBar::topLevelChanged(bool topLevel)
+
+ This signal is emitted when the \l floating property changes.
+ The \a topLevel parameter is true if the toolbar is now floating;
+ otherwise it is false.
+
+ \sa isWindow()
+*/
+
+
+/*!
Constructs a QToolBar with the given \a parent.
*/
QToolBar::QToolBar(QWidget *parent)
diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h
index a084673..a1a24f0 100644
--- a/src/gui/widgets/qtoolbar.h
+++ b/src/gui/widgets/qtoolbar.h
@@ -142,6 +142,7 @@ Q_SIGNALS:
void orientationChanged(Qt::Orientation orientation);
void iconSizeChanged(const QSize &iconSize);
void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle);
+ void topLevelChanged(bool topLevel);
protected:
void actionEvent(QActionEvent *event);