diff options
author | Jesus Sanchez-Palencia <jesus.palencia@openbossa.org> | 2009-05-28 18:28:23 (GMT) |
---|---|---|
committer | Eduardo M. Fleury <eduardo.fleury@openbossa.org> | 2009-07-22 18:03:57 (GMT) |
commit | b1bd07d163d335ab05b878b907965e43124d8da1 (patch) | |
tree | fe3cc90839501f138657ba6c892379d857288771 /src/gui/graphicsview/qgraphicsanchorlayout.cpp | |
parent | 26a785e3c65a5f60bcf5bb2e07e58bc6b544dc30 (diff) | |
download | Qt-b1bd07d163d335ab05b878b907965e43124d8da1.zip Qt-b1bd07d163d335ab05b878b907965e43124d8da1.tar.gz Qt-b1bd07d163d335ab05b878b907965e43124d8da1.tar.bz2 |
QGraphicsAnchorLayout: Adding QGraphicsAnchorLayout public and private classes
This is a total re-written implementation of QGraphicsAnchorLayout using
a numerical approach. We use QGraph and QSimplex in order to achieve this.
This first commit gives us a just ready-to-use qgraphicslayout, but the
private class still need to inherit from qgraphicslayoutprivate. Optimizations
and documentation are all work in progress.
Signed-off-by: Anselmo Lacerda S. de Melo <anselmo.melo@openbossa.org>
Signed-off-by: Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
Signed-off-by: Eduardo M. Fleury <eduardo.fleury@openbossa.org>
Signed-off-by: Jesus Sanchez-Palencia <jesus.palencia@openbossa.org>
Diffstat (limited to 'src/gui/graphicsview/qgraphicsanchorlayout.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp new file mode 100644 index 0000000..d737e36 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicsanchorlayout_p.h" + +QGraphicsAnchorLayout::QGraphicsAnchorLayout(QGraphicsLayoutItem *parent) + : QGraphicsLayout(parent), d_ptr(new QGraphicsAnchorLayoutPrivate()) +{ + // ### REMOVE THAT + d_ptr->q_ptr = this; + + d_ptr->createLayoutEdges(); +} + +QGraphicsAnchorLayout::~QGraphicsAnchorLayout() +{ + Q_D(QGraphicsAnchorLayout); + + for (int i = count() - 1; i >= 0; --i) { + QGraphicsLayoutItem *item = d->items.at(i); + removeAt(i); + if (item) { + if (item->ownedByLayout()) + delete item; + } + } +} + +void QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, + Edge firstEdge, + QGraphicsLayoutItem *secondItem, + Edge secondEdge, qreal spacing) +{ + Q_D(QGraphicsAnchorLayout); + if ((firstItem == 0) || (secondItem == 0)) { + qWarning("QGraphicsAnchorLayout::anchor: " + "Cannot anchor NULL items"); + return; + } + + if (firstItem == secondItem) { + qWarning("QGraphicsAnchorLayout::anchor: " + "Cannot anchor the item to itself"); + return; + } + + if (d->edgeOrientation(secondEdge) != d->edgeOrientation(firstEdge)) { + qWarning("QGraphicsAnchorLayout::anchor: " + "Cannot anchor edges of different orientations"); + return; + } + + // In QGraphicsAnchorLayout, items are represented in its internal + // graph as four anchors that connect: + // - Left -> HCenter + // - HCenter-> Right + // - Top -> VCenter + // - VCenter -> Bottom + + // Ensure that the internal anchors have been created for both items. + if (firstItem != this && !d->items.contains(firstItem)) { + d->createItemEdges(firstItem); + d->addChildItem(firstItem); + } + if (secondItem != this && !d->items.contains(secondItem)) { + d->createItemEdges(secondItem); + d->addChildItem(secondItem); + } + + // Use heuristics to find out what the user meant with this anchor. + d->correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); + + // Create actual anchor between firstItem and secondItem. + AnchorData *data; + if (spacing >= 0) { + data = new AnchorData(spacing); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + } else { + data = new AnchorData(-spacing); + d->addAnchor(secondItem, secondEdge, firstItem, firstEdge, data); + } + + invalidate(); +} + +void QGraphicsAnchorLayout::removeAnchor(QGraphicsLayoutItem *firstItem, Edge firstEdge, + QGraphicsLayoutItem *secondItem, Edge secondEdge) +{ + Q_D(QGraphicsAnchorLayout); + if ((firstItem == 0) || (secondItem == 0)) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor between NULL items"); + return; + } + + if (firstItem == secondItem) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor from the item to itself"); + return; + } + + if (d->edgeOrientation(secondEdge) != d->edgeOrientation(firstEdge)) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor from edges of different orientations"); + return; + } + + d->removeAnchor(firstItem, firstEdge, secondItem, secondEdge); + + invalidate(); +} + +void QGraphicsAnchorLayout::setGeometry(const QRectF &geom) +{ + Q_D(QGraphicsAnchorLayout); + QGraphicsLayout::setGeometry(geom); + d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Horizontal); + d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Vertical); + d->setItemsGeometries(); +} + +void QGraphicsAnchorLayout::removeAt(int index) +{ + Q_D(QGraphicsAnchorLayout); + QGraphicsLayoutItem *item = d->items.value(index); + + if (item) { + d->items.remove(index); + d->removeAnchors(item); + item->setParentLayoutItem(0); + } +} + +int QGraphicsAnchorLayout::count() const +{ + Q_D(const QGraphicsAnchorLayout); + return d->items.size(); +} + +QGraphicsLayoutItem *QGraphicsAnchorLayout::itemAt(int index) const +{ + Q_D(const QGraphicsAnchorLayout); + return d->items.value(index); +} + +void QGraphicsAnchorLayout::invalidate() +{ + Q_D(QGraphicsAnchorLayout); + QGraphicsLayout::invalidate(); + d->calculateGraphCacheDirty = 1; +} + +QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +{ + Q_UNUSED(which); + Q_UNUSED(constraint); + Q_D(const QGraphicsAnchorLayout); + + // Some setup calculations are delayed until the information is + // actually needed, avoiding unnecessary recalculations when + // adding multiple anchors. + + // sizeHint() / effectiveSizeHint() already have a cache + // mechanism, using invalidate() to force recalculation. However + // sizeHint() is called three times after invalidation (for max, + // min and pref), but we just need do our setup once. + + const_cast<QGraphicsAnchorLayoutPrivate *>(d)->calculateGraphs(); + + // ### apply constraint! + QSizeF engineSizeHint( + d->sizeHints[QGraphicsAnchorLayoutPrivate::Horizontal][which], + d->sizeHints[QGraphicsAnchorLayoutPrivate::Vertical][which]); + + qreal left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + + return engineSizeHint + QSizeF(left + right, top + bottom); +} + +//////// DEBUG ///////// +#include <QFile> +void QGraphicsAnchorLayout::dumpGraph() +{ + Q_D(QGraphicsAnchorLayout); + + QFile file(QString::fromAscii("anchorlayout.dot")); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) + qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData()); + + QString dotContents = d->graph[0].serializeToDot(); + file.write(dotContents.toLocal8Bit()); + dotContents = d->graph[1].serializeToDot(); + file.write(dotContents.toLocal8Bit()); + + file.close(); +} |