diff options
author | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-09-17 15:25:08 (GMT) |
---|---|---|
committer | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-09-17 15:25:08 (GMT) |
commit | 1d05c5221ba8ad3f5d3d36ba2025ea45bc3afe88 (patch) | |
tree | 6cba08738ce9fcdb0d1d8d7417b336a8521f36a1 /src/gui | |
parent | b7923d48fb6d755d4563eeed0e7f3cbc774d69d5 (diff) | |
parent | 0db5ca5c733422b28524791b4f292227a61090d2 (diff) | |
download | Qt-1d05c5221ba8ad3f5d3d36ba2025ea45bc3afe88.zip Qt-1d05c5221ba8ad3f5d3d36ba2025ea45bc3afe88.tar.gz Qt-1d05c5221ba8ad3f5d3d36ba2025ea45bc3afe88.tar.bz2 |
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt into 4.6
Conflicts:
tests/auto/qtwidgets/tst_qtwidgets.cpp
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/embedded/directfb.pri | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.cpp | 18 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 396 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.h | 22 | ||||
-rw-r--r-- | src/gui/graphicsview/qsimplex_p.cpp | 9 | ||||
-rw-r--r-- | src/gui/graphicsview/qsimplex_p.h | 2 | ||||
-rw-r--r-- | src/gui/itemviews/qabstractitemview.cpp | 12 | ||||
-rw-r--r-- | src/gui/itemviews/qabstractitemview_p.h | 1 | ||||
-rw-r--r-- | src/gui/itemviews/qtableview.cpp | 28 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 15 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qcursor_s60.cpp | 10 | ||||
-rw-r--r-- | src/gui/kernel/qdnd_s60.cpp | 10 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qtooltip.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/painting.pri | 1 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase_mac.cpp | 31 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 77 |
20 files changed, 451 insertions, 197 deletions
diff --git a/src/gui/embedded/directfb.pri b/src/gui/embedded/directfb.pri index 7dae9d5..43ff0c7 100644 --- a/src/gui/embedded/directfb.pri +++ b/src/gui/embedded/directfb.pri @@ -8,7 +8,7 @@ #DEFINES += QT_DIRECTFB_IMAGECACHE #DEFINES += QT_NO_DIRECTFB_WM #DEFINES += QT_NO_DIRECTFB_LAYER -#DEFINES += QT_NO_DIRECTFB_PALETTE +#DEFINES += QT_DIRECTFB_PALETTE #DEFINES += QT_NO_DIRECTFB_PREALLOCATED #DEFINES += QT_NO_DIRECTFB_MOUSE #DEFINES += QT_NO_DIRECTFB_KEYBOARD diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 5897ae4..12124ab 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -194,7 +194,7 @@ QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { Q_D(QGraphicsAnchorLayout); - QGraphicsAnchor *a = d->anchor(firstItem, firstEdge, secondItem, secondEdge); + QGraphicsAnchor *a = d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); invalidate(); return a; } @@ -246,12 +246,12 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, // Horizontal anchor Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); - d->anchor(firstItem, firstEdge, secondItem, secondEdge); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); // Vertical anchor firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); - d->anchor(firstItem, firstEdge, secondItem, secondEdge); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); invalidate(); } @@ -288,6 +288,18 @@ void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, } /*! + Returns true if there are no arrangement that satisfies all constraints. + Otherwise returns false. + + \sa addAnchor() +*/ +bool QGraphicsAnchorLayout::hasConflicts() const +{ + Q_D(const QGraphicsAnchorLayout); + return d->hasConflicts(); +} + +/*! Sets the default horizontal spacing for the anchor layout to \a spacing. \sa horizontalSpacing(), setVerticalSpacing(), setSpacing() diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index d9a87ba..44074d1 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -93,6 +93,7 @@ public: QGraphicsLayoutItem *secondItem, Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical); + bool hasConflicts() const; void setHorizontalSpacing(qreal spacing); void setVerticalSpacing(qreal spacing); void setSpacing(qreal spacing); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index a37ec96..23601f9 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -59,7 +59,7 @@ QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() { - layoutPrivate->deleteAnchorData(data); + layoutPrivate->removeAnchor(data->from, data->to); } void QGraphicsAnchorPrivate::setSpacing(qreal value) @@ -332,6 +332,7 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() for (int i = 0; i < NOrientations; ++i) { spacings[i] = -1; graphSimplified[i] = false; + graphHasConflicts[i] = false; } } @@ -790,7 +791,7 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() // Horizontal AnchorData *data = new AnchorData(0, 0, QWIDGETSIZE_MAX); - addAnchor(layout, Qt::AnchorLeft, layout, + addAnchor_helper(layout, Qt::AnchorLeft, layout, Qt::AnchorRight, data); data->skipInPreferred = 1; @@ -800,7 +801,7 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() // Vertical data = new AnchorData(0, 0, QWIDGETSIZE_MAX); - addAnchor(layout, Qt::AnchorTop, layout, + addAnchor_helper(layout, Qt::AnchorTop, layout, Qt::AnchorBottom, data); data->skipInPreferred = 1; @@ -816,8 +817,10 @@ void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL); Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL); - removeAnchor(q, Qt::AnchorLeft, q, Qt::AnchorRight); - removeAnchor(q, Qt::AnchorTop, q, Qt::AnchorBottom); + removeAnchor_helper(internalVertex(q, Qt::AnchorLeft), + internalVertex(q, Qt::AnchorRight)); + removeAnchor_helper(internalVertex(q, Qt::AnchorTop), + internalVertex(q, Qt::AnchorBottom)); } void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) @@ -832,7 +835,7 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) int maximumSize = item->maximumWidth(); AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, Qt::AnchorLeft, item, + addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data); // Vertical @@ -841,7 +844,7 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) maximumSize = item->maximumHeight(); data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, Qt::AnchorTop, item, + addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data); } @@ -904,16 +907,16 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( QSimplexConstraint *c = new QSimplexConstraint; AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); c->variables.insert(data, 1.0); - addAnchor(item, firstEdge, item, centerEdge, data); + addAnchor_helper(item, firstEdge, item, centerEdge, data); data = new AnchorData(minimumSize, preferredSize, maximumSize); c->variables.insert(data, -1.0); - addAnchor(item, centerEdge, item, lastEdge, data); + addAnchor_helper(item, centerEdge, item, lastEdge, data); itemCenterConstraints[orientation].append(c); // Remove old one - removeAnchor(item, firstEdge, item, lastEdge); + removeAnchor_helper(first, last); } void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( @@ -976,11 +979,11 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( int maximumSize = oldData->maxSize * 2; AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, firstEdge, item, lastEdge, data); + addAnchor_helper(item, firstEdge, item, lastEdge, data); // Remove old anchors - removeAnchor(item, firstEdge, item, centerEdge); - removeAnchor(item, centerEdge, item, lastEdge); + removeAnchor_helper(first, center); + removeAnchor_helper(center, internalVertex(item, lastEdge)); } else { // this is only called from removeAnchors() @@ -989,13 +992,13 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( for (int i = 0; i < adjacents.count(); ++i) { AnchorVertex *v = adjacents.at(i); if (v->m_item != item) { - removeAnchor(item, centerEdge, v->m_item, v->m_edge); + removeAnchor_helper(center, internalVertex(v->m_item, v->m_edge)); } } // when all non-internal anchors is removed it will automatically merge the // center anchor into a left-right (or top-bottom) anchor. We must also delete that. // by this time, the center vertex is deleted and merged into a non-centered internal anchor - removeAnchor(item, firstEdge, item, lastEdge); + removeAnchor_helper(first, internalVertex(item, lastEdge)); } } @@ -1039,7 +1042,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * * Helper function that is called from the anchor functions in the public API. * If \a spacing is 0, it will pick up the spacing defined by the style. */ -QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, +QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -1112,18 +1115,18 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *first } else { data = new AnchorData(0); // spacing should be 0 } - addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); } else if (*spacing >= 0) { data = new AnchorData(*spacing); - addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); } else { data = new AnchorData(-*spacing); - addAnchor(secondItem, secondEdge, firstItem, firstEdge, data); + addAnchor_helper(secondItem, secondEdge, firstItem, firstEdge, data); } return acquireGraphicsAnchor(data); } -void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, +void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -1142,8 +1145,9 @@ void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, // Remove previous anchor // ### Could we update the existing edgeData rather than creating a new one? - if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) - removeAnchor(firstItem, firstEdge, secondItem, secondEdge); + if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) { + removeAnchor_helper(v1, v2); + } // 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 @@ -1178,15 +1182,82 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *fi return graphicsAnchor; } -void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge) +/*! + * \internal + * + * Implements the high level "removeAnchor" feature. Called by + * the QAnchorData destructor. + */ +void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex, + AnchorVertex *secondVertex) { - removeAnchor_helper(internalVertex(firstItem, firstEdge), - internalVertex(secondItem, secondEdge)); + Q_Q(QGraphicsAnchorLayout); + + // Actually delete the anchor + removeAnchor_helper(firstVertex, secondVertex); + + QGraphicsLayoutItem *firstItem = firstVertex->m_item; + QGraphicsLayoutItem *secondItem = secondVertex->m_item; + + // Checking if the item stays in the layout or not + bool keepFirstItem = false; + bool keepSecondItem = false; + + QPair<AnchorVertex *, int> v; + int refcount = -1; + + if (firstItem != q) { + for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { + v = m_vertexList.value(qMakePair(firstItem, static_cast<Qt::AnchorPoint>(i))); + if (v.first) { + if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) + refcount = 2; + else + refcount = 1; + + if (v.second > refcount) { + keepFirstItem = true; + break; + } + } + } + } else + keepFirstItem = true; + + if (secondItem != q) { + for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { + v = m_vertexList.value(qMakePair(secondItem, static_cast<Qt::AnchorPoint>(i))); + if (v.first) { + if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) + refcount = 2; + else + refcount = 1; + + if (v.second > refcount) { + keepSecondItem = true; + break; + } + } + } + } else + keepSecondItem = true; + + if (!keepFirstItem) + q->removeAt(items.indexOf(firstItem)); + + if (!keepSecondItem) + q->removeAt(items.indexOf(secondItem)); + + // Removing anchors invalidates the layout + q->invalidate(); } +/* + \internal + + Implements the low level "removeAnchor" feature. Called by + private methods. +*/ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2) { Q_ASSERT(v1 && v2); @@ -1207,17 +1278,6 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorV \internal Only called from outside. (calls invalidate()) */ -void QGraphicsAnchorLayoutPrivate::deleteAnchorData(AnchorData *data) -{ - Q_Q(QGraphicsAnchorLayout); - removeAnchor_helper(data->from, data->to); - q->invalidate(); -} - -/*! - \internal - Only called from outside. (calls invalidate()) -*/ void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal *anchorSize) { Q_Q(QGraphicsAnchorLayout); @@ -1225,12 +1285,35 @@ void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal * // search recursively through all composite anchors Q_ASSERT(data); restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); + + QGraphicsLayoutItem *firstItem = data->from->m_item; + QGraphicsLayoutItem *secondItem = data->to->m_item; + Qt::AnchorPoint firstEdge = data->from->m_edge; + Qt::AnchorPoint secondEdge = data->to->m_edge; + + // Use heuristics to find out what the user meant with this anchor. + correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); + if (data->from->m_item != firstItem) + qSwap(data->from, data->to); + if (anchorSize) { - data->setFixedSize(*anchorSize); + // ### The current implementation makes "setAnchorSize" behavior + // dependent on the argument order for cases where we have + // no heuristic. Ie. two widgets, same anchor point. + + // We cannot have negative sizes inside the graph. This would cause + // the simplex solver to fail because all simplex variables are + // positive by definition. + // "negative spacing" is handled by inverting the standard item order. + if (*anchorSize >= 0) { + data->setFixedSize(*anchorSize); + } else { + data->setFixedSize(-*anchorSize); + qSwap(data->from, data->to); + } } else { data->unsetSize(); } - q->invalidate(); } @@ -1360,25 +1443,23 @@ void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&fi { Q_Q(QGraphicsAnchorLayout); - Qt::AnchorPoint effectiveFirst = firstEdge; - Qt::AnchorPoint effectiveSecond = secondEdge; - - if (firstItem == q) - effectiveFirst = QGraphicsAnchorLayoutPrivate::oppositeEdge(firstEdge); - if (secondItem == q) - effectiveSecond = QGraphicsAnchorLayoutPrivate::oppositeEdge(secondEdge); - - if (effectiveFirst < effectiveSecond) { - - // ### DEBUG - /* printf("Swapping Anchor from %s %d --to--> %s %d\n", - firstItem->isLayout() ? "<layout>" : - qPrintable(static_cast<QGraphicsWidget *>(firstItem)->data(0).toString()), - firstEdge, - secondItem->isLayout() ? "<layout>" : - qPrintable(static_cast<QGraphicsWidget *>(secondItem)->data(0).toString()), - secondEdge); - */ + if ((firstItem != q) && (secondItem != q)) { + // If connection is between widgets (not the layout itself) + // Ensure that "right-edges" sit to the left of "left-edges". + if (firstEdge < secondEdge) { + qSwap(firstItem, secondItem); + qSwap(firstEdge, secondEdge); + } + } else if (firstItem == q) { + // If connection involves the right or bottom of a layout, ensure + // the layout is the second item. + if ((firstEdge == Qt::AnchorRight) || (firstEdge == Qt::AnchorBottom)) { + qSwap(firstItem, secondItem); + qSwap(firstEdge, secondEdge); + } + } else if ((secondEdge != Qt::AnchorRight) && (secondEdge != Qt::AnchorBottom)) { + // If connection involves the left, center or top of layout, ensure + // the layout is the first item. qSwap(firstItem, secondItem); qSwap(firstEdge, secondEdge); } @@ -1507,6 +1588,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation)); GraphPath trunkPath = graphPaths[orientation].value(v); + bool feasible = true; if (!trunkConstraints.isEmpty()) { #if 0 qDebug("Simplex used for trunk of %s", @@ -1514,33 +1596,37 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( #endif // Solve min and max size hints for trunk - QPair<qreal, qreal> minMax = solveMinMax(trunkConstraints, trunkPath); - sizeHints[orientation][Qt::MinimumSize] = minMax.first; - sizeHints[orientation][Qt::MaximumSize] = minMax.second; + qreal min, max; + feasible = solveMinMax(trunkConstraints, trunkPath, &min, &max); // Solve for preferred. The objective function is calculated from the constraints // and variables internally. - solvePreferred(trunkConstraints); + feasible &= solvePreferred(trunkConstraints); - // Propagate the new sizes down the simplified graph, ie. tell the - // group anchors to set their children anchors sizes. + if (feasible) { + // Propagate the new sizes down the simplified graph, ie. tell the + // group anchors to set their children anchors sizes. - // ### we calculated variables already a few times, can't we reuse that? - QList<AnchorData *> trunkVariables = getVariables(trunkConstraints); + // ### we calculated variables already a few times, can't we reuse that? + QList<AnchorData *> trunkVariables = getVariables(trunkConstraints); - for (int i = 0; i < trunkVariables.count(); ++i) - trunkVariables.at(i)->updateChildrenSizes(); + for (int i = 0; i < trunkVariables.count(); ++i) + trunkVariables.at(i)->updateChildrenSizes(); + + // Calculate and set the preferred size for the layout from the edge sizes that + // were calculated above. + qreal pref(0.0); + foreach (const AnchorData *ad, trunkPath.positives) { + pref += ad->sizeAtPreferred; + } + foreach (const AnchorData *ad, trunkPath.negatives) { + pref -= ad->sizeAtPreferred; + } + sizeHints[orientation][Qt::MinimumSize] = min; + sizeHints[orientation][Qt::PreferredSize] = pref; + sizeHints[orientation][Qt::MaximumSize] = max; - // Calculate and set the preferred size for the layout from the edge sizes that - // were calculated above. - qreal pref(0.0); - foreach (const AnchorData *ad, trunkPath.positives) { - pref += ad->sizeAtPreferred; - } - foreach (const AnchorData *ad, trunkPath.negatives) { - pref -= ad->sizeAtPreferred; } - sizeHints[orientation][Qt::PreferredSize] = pref; } else { #if 0 qDebug("Simplex NOT used for trunk of %s", @@ -1574,29 +1660,34 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( // layout. // Solve the other only for preferred, skip trunk - for (int i = 1; i < parts.count(); ++i) { - QList<QSimplexConstraint *> partConstraints = parts[i]; - QList<AnchorData *> partVariables = getVariables(partConstraints); - Q_ASSERT(!partVariables.isEmpty()); - - sizeHintConstraints = constraintsFromSizeHints(partVariables); - partConstraints += sizeHintConstraints; - solvePreferred(partConstraints); - - // Propagate size at preferred to other sizes. Semi-floats - // always will be in their sizeAtPreferred. - for (int j = 0; j < partVariables.count(); ++j) { - AnchorData *ad = partVariables[j]; - Q_ASSERT(ad); - ad->sizeAtMinimum = ad->sizeAtPreferred; - ad->sizeAtMaximum = ad->sizeAtPreferred; - ad->updateChildrenSizes(); - } + if (feasible) { + for (int i = 1; i < parts.count(); ++i) { + QList<QSimplexConstraint *> partConstraints = parts[i]; + QList<AnchorData *> partVariables = getVariables(partConstraints); + Q_ASSERT(!partVariables.isEmpty()); + + sizeHintConstraints = constraintsFromSizeHints(partVariables); + partConstraints += sizeHintConstraints; + feasible &= solvePreferred(partConstraints); + if (!feasible) + break; + + // Propagate size at preferred to other sizes. Semi-floats + // always will be in their sizeAtPreferred. + for (int j = 0; j < partVariables.count(); ++j) { + AnchorData *ad = partVariables[j]; + Q_ASSERT(ad); + ad->sizeAtMinimum = ad->sizeAtPreferred; + ad->sizeAtMaximum = ad->sizeAtPreferred; + ad->updateChildrenSizes(); + } - // Delete the constraints, we won't use them anymore. - qDeleteAll(sizeHintConstraints); - sizeHintConstraints.clear(); + // Delete the constraints, we won't use them anymore. + qDeleteAll(sizeHintConstraints); + sizeHintConstraints.clear(); + } } + graphHasConflicts[orientation] = !feasible; // Clean up our data structures. They are not needed anymore since // distribution uses just interpolation. @@ -2061,47 +2152,48 @@ void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges( interpolateEdge(prev, data->m_edges.last(), orientation); } -QPair<qreal, qreal> -QGraphicsAnchorLayoutPrivate::solveMinMax(QList<QSimplexConstraint *> constraints, - GraphPath path) +bool QGraphicsAnchorLayoutPrivate::solveMinMax(QList<QSimplexConstraint *> constraints, + GraphPath path, qreal *min, qreal *max) { QSimplex simplex; - simplex.setConstraints(constraints); - - // Obtain the objective constraint - QSimplexConstraint objective; - QSet<AnchorData *>::const_iterator iter; - for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter) - objective.variables.insert(*iter, 1.0); - - for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter) - objective.variables.insert(*iter, -1.0); - - simplex.setObjective(&objective); - - // Calculate minimum values - qreal min = simplex.solveMin(); - - // Save sizeAtMinimum results - QList<QSimplexVariable *> variables = simplex.constraintsVariables(); - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = static_cast<AnchorData *>(variables[i]); - ad->sizeAtMinimum = ad->result; - } + bool feasible = simplex.setConstraints(constraints); + if (feasible) { + // Obtain the objective constraint + QSimplexConstraint objective; + QSet<AnchorData *>::const_iterator iter; + for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter) + objective.variables.insert(*iter, 1.0); + + for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter) + objective.variables.insert(*iter, -1.0); + + simplex.setObjective(&objective); + + // Calculate minimum values + *min = simplex.solveMin(); + + // Save sizeAtMinimum results + QList<QSimplexVariable *> variables = simplex.constraintsVariables(); + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + Q_ASSERT(ad->result >= ad->minSize || qFuzzyCompare(ad->result, ad->minSize)); + ad->sizeAtMinimum = ad->result; + } - // Calculate maximum values - qreal max = simplex.solveMax(); + // Calculate maximum values + *max = simplex.solveMax(); - // Save sizeAtMaximum results - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = static_cast<AnchorData *>(variables[i]); - ad->sizeAtMaximum = ad->result; + // Save sizeAtMaximum results + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + Q_ASSERT(ad->result <= ad->maxSize || qFuzzyCompare(ad->result, ad->maxSize)); + ad->sizeAtMaximum = ad->result; + } } - - return qMakePair<qreal, qreal>(min, max); + return feasible; } -void QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> constraints) +bool QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> constraints) { QList<AnchorData *> variables = getVariables(constraints); QList<QSimplexConstraint *> preferredConstraints; @@ -2148,25 +2240,35 @@ void QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> co QSimplex *simplex = new QSimplex; - simplex->setConstraints(constraints + preferredConstraints); - simplex->setObjective(&objective); + bool feasible = simplex->setConstraints(constraints + preferredConstraints); + if (feasible) { + simplex->setObjective(&objective); - // Calculate minimum values - simplex->solveMin(); + // Calculate minimum values + simplex->solveMin(); - // Save sizeAtPreferred results - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = static_cast<AnchorData *>(variables[i]); - ad->sizeAtPreferred = ad->result; - } - - // Make sure we delete the simplex solver -before- we delete the - // constraints used by it. - delete simplex; + // Save sizeAtPreferred results + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + ad->sizeAtPreferred = ad->result; + } + // Make sure we delete the simplex solver -before- we delete the + // constraints used by it. + delete simplex; + } // Delete constraints and variables we created. qDeleteAll(preferredConstraints); qDeleteAll(preferredVariables); + + return feasible; +} + +bool QGraphicsAnchorLayoutPrivate::hasConflicts() const +{ + QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate*>(this); + that->calculateGraphs(); + return graphHasConflicts[0] || graphHasConflicts[1]; } #ifdef QT_DEBUG diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index f701c3f..4e1bcd4 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -403,15 +403,15 @@ public: return data->graphicsAnchor; } - // helper function used by the 4 API functions - QGraphicsAnchor *anchor(QGraphicsLayoutItem *firstItem, + // function used by the 4 API functions + QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, qreal *spacing = 0); - // Anchor Manipulation methods - void addAnchor(QGraphicsLayoutItem *firstItem, + // Helper for Anchor Manipulation methods + void addAnchor_helper(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -420,12 +420,8 @@ public: QGraphicsAnchor *getAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - void removeAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge); + void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); - void deleteAnchorData(AnchorData *data); void setAnchorSize(AnchorData *data, const qreal *anchorSize); void anchorSize(const AnchorData *data, qreal *minSize = 0, @@ -482,9 +478,10 @@ public: Orientation orientation); // Linear Programming solver methods - QPair<qreal, qreal> solveMinMax(QList<QSimplexConstraint *> constraints, - GraphPath path); - void solvePreferred(QList<QSimplexConstraint *> constraints); + bool solveMinMax(QList<QSimplexConstraint *> constraints, + GraphPath path, qreal *min, qreal *max); + bool solvePreferred(QList<QSimplexConstraint *> constraints); + bool hasConflicts() const; #ifdef QT_DEBUG void dumpGraph(); @@ -518,6 +515,7 @@ public: // ### bool graphSimplified[2]; + bool graphHasConflicts[2]; uint calculateGraphCacheDirty : 1; }; diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp index 3bd6b5a..e3a991e 100644 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -84,12 +84,12 @@ void QSimplex::clearDataStructures() objective = 0; } -void QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) +bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) { clearDataStructures(); if (newConstraints.isEmpty()) - return; + return true; // we are ok with no constraints constraints = newConstraints; // Set Variables direct mapping @@ -153,7 +153,7 @@ void QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) matrix = (qreal *)malloc(sizeof(qreal) * columns * rows); if (!matrix) { qWarning() << "QSimplex: Unable to allocate memory!"; - return; + return false; } for (int i = columns * rows - 1; i >= 0; --i) matrix[i] = 0.0; @@ -198,11 +198,12 @@ void QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) if (valueAt(0, columns - 1) != 0.0) { qWarning() << "QSimplex: No feasible solution!"; clearDataStructures(); - return; + return false; } // Remove artificial variables clearColumns(firstArtificial, columns - 2); + return true; } void QSimplex::solveMaxHelper() diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h index 805ef4a..54b080d 100644 --- a/src/gui/graphicsview/qsimplex_p.h +++ b/src/gui/graphicsview/qsimplex_p.h @@ -107,7 +107,7 @@ public: qreal solveMax(); QList<QSimplexVariable *> constraintsVariables(); - void setConstraints(const QList<QSimplexConstraint *> constraints); + bool setConstraints(const QList<QSimplexConstraint *> constraints); void setObjective(QSimplexConstraint *objective); void dumpMatrix(); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 9d977a5..757ded9 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -69,6 +69,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() : model(QAbstractItemModelPrivate::staticEmptyModel()), itemDelegate(0), selectionModel(0), + ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate), selectionMode(QAbstractItemView::ExtendedSelection), selectionBehavior(QAbstractItemView::SelectItems), currentlyCommittingEditor(0), @@ -1589,6 +1590,11 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); d->autoScroll = autoScroll; QRect rect(d->pressedPosition - offset, pos); + if (command.testFlag(QItemSelectionModel::Toggle)) { + command &= ~QItemSelectionModel::Toggle; + d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command |= d->ctrlDragSelectionFlag; + } setSelection(rect, command); // signal handlers may change the model @@ -1659,6 +1665,10 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) if ((event->buttons() & Qt::LeftButton) && d->selectionAllowed(index) && d->selectionModel) { setState(DragSelectingState); QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); + if (command.testFlag(QItemSelectionModel::Toggle)) { + command &= ~QItemSelectionModel::Toggle; + command |= d->ctrlDragSelectionFlag; + } // Do the normalize ourselves, since QRect::normalized() is flawed QRect selectionRect = QRect(topLeft, bottomRight); @@ -1699,6 +1709,8 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event) EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers); bool edited = edit(index, trigger, event); + d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate; + //in the case the user presses on no item we might decide to clear the selection if (d->selectionModel && !index.isValid()) d->selectionModel->select(QModelIndex(), selectionCommand(index, event)); diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 725d0a9..6b1ec8e 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -342,6 +342,7 @@ public: QMap<int, QPointer<QAbstractItemDelegate> > rowDelegates; QMap<int, QPointer<QAbstractItemDelegate> > columnDelegates; QPointer<QItemSelectionModel> selectionModel; + QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag; QAbstractItemView::SelectionMode selectionMode; QAbstractItemView::SelectionBehavior selectionBehavior; diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 684da3f..f1ffaa6 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -2519,9 +2519,21 @@ void QTableViewPrivate::selectRow(int row, bool anchor) QModelIndex index = model->index(row, column, root); QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((!(command & QItemSelectionModel::Current) && anchor) + if ((anchor && !(command & QItemSelectionModel::Current)) || (q->selectionMode() == QTableView::SingleSelection)) rowSectionAnchor = row; + + if (q->selectionMode() != QTableView::SingleSelection + && command.testFlag(QItemSelectionModel::Toggle)) { + if (anchor) + ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index) + ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command &= ~QItemSelectionModel::Toggle; + command |= ctrlDragSelectionFlag; + if (!anchor) + command |= QItemSelectionModel::Current; + } + QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root); QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root); if (verticalHeader->sectionsMoved() && tl.row() != br.row()) @@ -2545,9 +2557,21 @@ void QTableViewPrivate::selectColumn(int column, bool anchor) QModelIndex index = model->index(row, column, root); QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((!(command & QItemSelectionModel::Current) && anchor) + if ((anchor && !(command & QItemSelectionModel::Current)) || (q->selectionMode() == QTableView::SingleSelection)) columnSectionAnchor = column; + + if (q->selectionMode() != QTableView::SingleSelection + && command.testFlag(QItemSelectionModel::Toggle)) { + if (anchor) + ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index) + ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command &= ~QItemSelectionModel::Toggle; + command |= ctrlDragSelectionFlag; + if (!anchor) + command |= QItemSelectionModel::Current; + } + QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root); QModelIndex br = model->index(model->rowCount(root) - 1, qMax(columnSectionAnchor, column), root); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index fd889fc..6a381f5 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -439,7 +439,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) } } S60->lastCursorPos = globalPos; -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS +#if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS) if (S60->brokenPointerCursors) qt_symbian_move_cursor_sprite(); #endif @@ -855,7 +855,6 @@ void qt_init(QApplicationPrivate * /* priv */, int) //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this) const TInt KMachineUidSamsungI8510 = 0x2000C51E; - const TInt KMachineUidSamsungI550 = 0x2000A678; TInt machineUID; TInt mouse; TInt touch; @@ -888,6 +887,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; } +#ifndef QT_NO_CURSOR //Check if window server pointer cursors are supported or not #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS //In generic binary, use the HAL and OS version @@ -912,6 +912,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) #endif S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); } +#endif /* ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag @@ -1275,7 +1276,7 @@ int QApplication::s60ProcessEvent(TWsEvent *event) } break; case EEventFocusGained: - RDebug::Printf("focus gained %x", control); +#ifndef QT_NO_CURSOR //re-enable mouse interaction if (S60->mouseInteractionEnabled) { #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS @@ -1285,9 +1286,10 @@ int QApplication::s60ProcessEvent(TWsEvent *event) #endif S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); } +#endif break; case EEventFocusLost: - RDebug::Printf("focus lost %x", control); +#ifndef QT_NO_CURSOR //disable mouse as may be moving to application that does not support it if (S60->mouseInteractionEnabled) { #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS @@ -1297,6 +1299,7 @@ int QApplication::s60ProcessEvent(TWsEvent *event) #endif S60->wsSession().SetPointerCursorMode(EPointerCursorNone); } +#endif break; default: break; @@ -1534,7 +1537,9 @@ void QApplication::restoreOverrideCursor() QListIterator<WId> iter(QWidgetPrivate::mapper->uniqueKeys()); while (iter.hasNext()) { CCoeControl *ctrl = iter.next(); - ctrl->DrawableWindow()->ClearPointerCursor(); + if(ctrl->OwnsWindow()) { + ctrl->DrawableWindow()->ClearPointerCursor(); + } } if (w) qt_symbian_setWindowCursor(w->cursor(), w->effectiveWinId()); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6ecd535..2b1aaf5 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -220,7 +220,7 @@ static void resolveAygLibs() # define FE_FONTSMOOTHINGCLEARTYPE 0x0002 #endif -Q_GUI_EXPORT bool qt_cleartype_enabled; +bool qt_cleartype_enabled; Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL); diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp index 757eaa8..0d8283d 100644 --- a/src/gui/kernel/qcursor_s60.cpp +++ b/src/gui/kernel/qcursor_s60.cpp @@ -52,8 +52,10 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_CURSOR static QCursor cursorSprite; -static int cursorSpriteVisible; +static int cursorSpriteVisible; +#endif //pos and setpos are required whether cursors are configured or not. QPoint QCursor::pos() @@ -520,8 +522,10 @@ void qt_symbian_setGlobalCursor(const QCursor &cursor) while(iter.hasNext()) { CCoeControl *ctrl = iter.next(); - RWindowTreeNode *node = ctrl->DrawableWindow(); - qt_symbian_setWindowGroupCursor(cursor, *node); + if(ctrl->OwnsWindow()) { + RWindowTreeNode *node = ctrl->DrawableWindow(); + qt_symbian_setWindowGroupCursor(cursor, *node); + } } } } diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp index 2456185..3d6ecd2 100644 --- a/src/gui/kernel/qdnd_s60.cpp +++ b/src/gui/kernel/qdnd_s60.cpp @@ -214,11 +214,13 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) case QEvent::MouseButtonRelease: { qApp->removeEventFilter(this); +#ifndef QT_NO_CURSOR if (restoreCursor) { QApplication::restoreOverrideCursor(); willDrop = false; restoreCursor = false; } +#endif if (object && object->target()) { QMouseEvent *me = (QMouseEvent *)e; @@ -267,7 +269,9 @@ Qt::DropAction QDragManager::drag(QDrag *o) updatePixmap(); updateCursor(); +#ifndef QT_NO_CURSOR qt_symbian_set_cursor_visible(true); //force cursor on even for touch phone +#endif object->d_func()->target = 0; @@ -282,10 +286,12 @@ Qt::DropAction QDragManager::drag(QDrag *o) delete eventLoop; eventLoop = 0; +#ifndef QT_NO_CURSOR qt_symbian_set_cursor_visible(false); overrideCursor = QCursor(); //deref the cursor data qt_symbian_dnd_dragging = false; +#endif return global_accepted_action; } @@ -306,10 +312,12 @@ void QDragManager::cancel(bool deleteSource) drag_object = object = 0; } +#ifndef QT_NO_CURSOR if (restoreCursor) { QApplication::restoreOverrideCursor(); restoreCursor = false; } +#endif global_accepted_action = Qt::IgnoreAction; } @@ -317,10 +325,12 @@ void QDragManager::cancel(bool deleteSource) void QDragManager::drop() { +#ifndef QT_NO_CURSOR if (restoreCursor) { QApplication::restoreOverrideCursor(); restoreCursor = false; } +#endif } QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 794d15a..67084c4 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -304,11 +304,13 @@ static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode) return format; } +#ifndef QT_NO_CURSOR void qt_symbian_setWindowCursor(const QCursor &cursor, const CCoeControl* wid); void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &node); void qt_symbian_setGlobalCursor(const QCursor &cursor); void qt_symbian_set_cursor_visible(bool visible); bool qt_symbian_is_cursor_visible(); +#endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index a480195..2d0d209 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -290,8 +290,8 @@ void QTipLabel::timerEvent(QTimerEvent *e) // Fade out tip on mac (makes it invisible). // The tip will not be deleted until a new tip is shown. - // DRSWAT - Cocoa - macWindowFade(qt_mac_window_for(this)); + // DRSWAT - Cocoa + macWindowFade(qt_mac_window_for(this)); QTipLabel::instance->fadingOut = true; // will never be false again. } else @@ -431,7 +431,7 @@ bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o) void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect) { - if (QTipLabel::instance){ // a tip does already exist + if (QTipLabel::instance && QTipLabel::instance->isVisible()){ // a tip does already exist if (text.isEmpty()){ // empty text means hide current tip QTipLabel::instance->hideTip(); return; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 522ce33..3744377 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1222,8 +1222,9 @@ void QWidget::releaseMouse() WId id = effectiveWinId(); id->SetPointerCapture(false); QWidgetPrivate::mouseGrabber = 0; - +#ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); +#endif } } diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 5abac2f..8343cb9 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -22,6 +22,7 @@ HEADERS += \ painting/qpainter_p.h \ painting/qpainterpath.h \ painting/qpainterpath_p.h \ + painting/qvectorpath_p.h \ painting/qpathclipper_p.h \ painting/qpdf_p.h \ painting/qpen.h \ diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index d65910c..2584003 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -308,6 +308,21 @@ void QFontDatabase::load(const QFontPrivate *d, int script) if (familyRef) { fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); goto FamilyFound; + } else { +#if defined(QT_MAC_USE_COCOA) + // ATS and CT disagrees on what the family name should be, + // use CT to look up the font if ATS fails. + QCFString familyName = QString::fromAscii(family_name); + QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL); + QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef); + QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute); + + familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault); + if (familyRef) { + fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault); + goto FamilyFound; + } +#endif } } } @@ -456,11 +471,27 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) return; fnt->families.clear(); +#if defined(QT_MAC_USE_COCOA) + // Make sure that the family name set on the font matches what + // kCTFontFamilyNameAttribute returns in initializeDb(). + // So far the best solution seems find the installed font + // using CoreText and get the family name from it. + // (ATSFontFamilyGetName appears to be the correct API, but also + // returns the font display name.) + for(int i = 0; i < containedFonts.size(); ++i) { + QCFString fontPostScriptName; + ATSFontGetPostScriptName(containedFonts[i], kATSOptionFlagsDefault, &fontPostScriptName); + QCFType<CTFontDescriptorRef> font = CTFontDescriptorCreateWithNameAndSize(fontPostScriptName, 14); + QCFString familyName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); + fnt->families.append(familyName); + } +#else for(int i = 0; i < containedFonts.size(); ++i) { QCFString family; ATSFontGetName(containedFonts[i], kATSOptionFlagsDefault, &family); fnt->families.append(family); } +#endif fnt->handle = handle; } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 8dd01d7..e5a88fc 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -946,48 +946,60 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy if (maps + 8 * numTables > endPtr) return 0; + enum { + Invalid, + Symbol, + AppleRoman, + Unicode11, + Unicode, + MicrosoftUnicode, + MicrosoftUnicodeExtended + }; + + int symbolTable = -1; int tableToUse = -1; - int score = 0; + int score = Invalid; for (int n = 0; n < numTables; ++n) { const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n); const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2); switch (platformId) { case 0: // Unicode - if (score < 4 && + if (score < Unicode && (platformSpecificId == 0 || platformSpecificId == 2 || platformSpecificId == 3)) { tableToUse = n; - score = 4; - } else if (score < 3 && platformSpecificId == 1) { + score = Unicode; + } else if (score < Unicode11 && platformSpecificId == 1) { tableToUse = n; - score = 3; + score = Unicode11; } break; case 1: // Apple - if (score < 2 && platformSpecificId == 0) { // Apple Roman + if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman tableToUse = n; - score = 2; + score = AppleRoman; } break; case 3: // Microsoft switch (platformSpecificId) { case 0: - if (score < 1) { + symbolTable = n; + if (score < Symbol) { tableToUse = n; - score = 1; + score = Symbol; } break; case 1: - if (score < 5) { + if (score < MicrosoftUnicode) { tableToUse = n; - score = 5; + score = MicrosoftUnicode; } break; case 0xa: - if (score < 6) { + if (score < MicrosoftUnicodeExtended) { tableToUse = n; - score = 6; + score = MicrosoftUnicodeExtended; } break; default: @@ -999,7 +1011,9 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy } if(tableToUse < 0) return 0; - *isSymbolFont = (score == 1); + +resolveTable: + *isSymbolFont = (score == Symbol); unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); @@ -1019,6 +1033,41 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy if (table + unicode_table + length > endPtr) return 0; *cmapSize = length; + + // To support symbol fonts that contain a unicode table for the symbol area + // we check the cmap tables and fall back to symbol font unless that would + // involve losing information from the unicode table + if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) { + const uchar *selectedTable = table + unicode_table; + + // Check that none of the latin1 range are in the unicode table + bool unicodeTableHasLatin1 = false; + for (int uc=0x00; uc<0x100; ++uc) { + if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + unicodeTableHasLatin1 = true; + break; + } + } + + // Check that at least one symbol char is in the unicode table + bool unicodeTableHasSymbols = false; + if (!unicodeTableHasLatin1) { + for (int uc=0xf000; uc<0xf100; ++uc) { + if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + unicodeTableHasSymbols = true; + break; + } + } + } + + // Fall back to symbol table + if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) { + tableToUse = symbolTable; + score = Symbol; + goto resolveTable; + } + } + return table + unicode_table; } |