summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsanchorlayout.cpp
diff options
context:
space:
mode:
authorJesus Sanchez-Palencia <jesus.palencia@openbossa.org>2009-05-28 18:28:23 (GMT)
committerEduardo M. Fleury <eduardo.fleury@openbossa.org>2009-07-22 18:03:57 (GMT)
commitb1bd07d163d335ab05b878b907965e43124d8da1 (patch)
treefe3cc90839501f138657ba6c892379d857288771 /src/gui/graphicsview/qgraphicsanchorlayout.cpp
parent26a785e3c65a5f60bcf5bb2e07e58bc6b544dc30 (diff)
downloadQt-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.cpp235
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();
+}