libs/flake

KoShapeContainer.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  * Copyright (C) 2006-2009 Thomas Zander <zander@kde.org>
00003  * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 #include "KoShapeContainer.h"
00021 #include "KoShapeContainer_p.h"
00022 #include "KoShapeContainerModel.h"
00023 #include "KoShapeBorderModel.h"
00024 #include "KoChildrenData.h"
00025 
00026 #include <QPointF>
00027 #include <QPainter>
00028 #include <QPainterPath>
00029 
00030 KoShapeContainerPrivate::KoShapeContainerPrivate(KoShapeContainer *q)
00031     : KoShapePrivate(q),
00032     children(0)
00033 {
00034 }
00035 
00036 KoShapeContainerPrivate::~KoShapeContainerPrivate()
00037 {
00038     delete children;
00039 }
00040 
00041 KoShapeContainer::KoShapeContainer()
00042     : KoShape(*(new KoShapeContainerPrivate(this)))
00043 {
00044 }
00045 
00046 KoShapeContainer::KoShapeContainer(KoShapeContainerModel *model)
00047         : KoShape(*(new KoShapeContainerPrivate(this)))
00048 {
00049     Q_D(KoShapeContainer);
00050     d->children = model;
00051 }
00052 
00053 KoShapeContainer::~KoShapeContainer()
00054 {
00055     Q_D(KoShapeContainer);
00056     if (d->children) {
00057         foreach(KoShape *shape, d->children->childShapes())
00058             shape->setParent(0);
00059     }
00060 }
00061 
00062 void KoShapeContainer::addChild(KoShape *shape)
00063 {
00064     Q_D(KoShapeContainer);
00065     Q_ASSERT(shape);
00066     if (shape->parent() == this && childShapes().contains(shape))
00067         return;
00068     if (d->children == 0)
00069         d->children = new KoChildrenData();
00070     if (shape->parent() && shape->parent() != this)
00071         shape->parent()->removeChild(shape);
00072     d->children->add(shape);
00073     shape->setParent(this);
00074     childCountChanged();
00075 }
00076 
00077 void KoShapeContainer::removeChild(KoShape *shape)
00078 {
00079     Q_D(KoShapeContainer);
00080     Q_ASSERT(shape);
00081     if (d->children == 0)
00082         return;
00083     d->children->remove(shape);
00084     shape->setParent(0);
00085     childCountChanged();
00086 
00087     KoShapeContainer * grandparent = parent();
00088     if (grandparent) {
00089         grandparent->model()->childChanged(this, KoShape::ChildChanged);
00090     }
00091 }
00092 
00093 int  KoShapeContainer::childCount() const
00094 {
00095     Q_D(const KoShapeContainer);
00096     if (d->children == 0)
00097         return 0;
00098     return d->children->count();
00099 }
00100 
00101 bool KoShapeContainer::isChildLocked(const KoShape *child) const
00102 {
00103     Q_D(const KoShapeContainer);
00104     if (d->children == 0)
00105         return false;
00106     return d->children->isChildLocked(child);
00107 }
00108 
00109 void KoShapeContainer::setClipping(const KoShape *child, bool clipping)
00110 {
00111     Q_D(KoShapeContainer);
00112     if (d->children == 0)
00113         return;
00114     d->children->setClipping(child, clipping);
00115 }
00116 
00117 void KoShapeContainer::paint(QPainter &painter, const KoViewConverter &converter)
00118 {
00119     Q_D(KoShapeContainer);
00120     painter.save();
00121     paintComponent(painter, converter);
00122     painter.restore();
00123     if (d->children == 0 || d->children->count() == 0)
00124         return;
00125 
00126     QList<KoShape*> sortedObjects = d->children->childShapes();
00127     qSort(sortedObjects.begin(), sortedObjects.end(), KoShape::compareShapeZIndex);
00128 
00129     QMatrix baseMatrix = absoluteTransformation(0).inverted() * painter.matrix();
00130 
00131     // clip the children to the parent outline.
00132     QMatrix m;
00133     qreal zoomX, zoomY;
00134     converter.zoom(&zoomX, &zoomY);
00135     m.scale(zoomX, zoomY);
00136     painter.setClipPath(m.map(outline()));
00137 
00138     foreach(KoShape *shape, sortedObjects) {
00139         //kDebug(30006) <<"KoShapeContainer::painting shape:" << shape->shapeId() <<"," << shape->boundingRect();
00140         if (! shape->isVisible())
00141             continue;
00142         if (! childClipped(shape))  // the shapeManager will have to draw those, or else we can't do clipRects
00143             continue;
00144         if (painter.hasClipping()) {
00145             QRectF rect = converter.viewToDocument(painter.clipRegion().boundingRect());
00146             rect = matrix().mapRect(rect);
00147             // don't try to draw a child shape that is not in the clipping rect of the painter.
00148             if (! rect.intersects(shape->boundingRect()))
00149                 continue;
00150         }
00151 
00152         painter.save();
00153         painter.setMatrix(shape->absoluteTransformation(&converter) * baseMatrix);
00154         shape->paint(painter, converter);
00155         painter.restore();
00156         if (shape->border()) {
00157             painter.save();
00158             painter.setMatrix(shape->absoluteTransformation(&converter) * baseMatrix);
00159             shape->border()->paintBorder(shape, painter, converter);
00160             painter.restore();
00161         }
00162     }
00163 }
00164 
00165 void KoShapeContainer::shapeChanged(ChangeType type, KoShape *shape)
00166 {
00167     Q_D(KoShapeContainer);
00168     Q_UNUSED(shape);
00169     if (d->children == 0)
00170         return;
00171     if (!(type == RotationChanged || type == ScaleChanged || type == ShearChanged
00172             || type == SizeChanged || type == PositionChanged))
00173         return;
00174     d->children->containerChanged(this);
00175     foreach(KoShape *shape, d->children->childShapes())
00176         shape->notifyChanged();
00177 }
00178 
00179 bool KoShapeContainer::childClipped(const KoShape *child) const
00180 {
00181     Q_D(const KoShapeContainer);
00182     if (d->children == 0) // throw exception??
00183         return false;
00184     return d->children->childClipped(child);
00185 }
00186 
00187 void KoShapeContainer::update() const
00188 {
00189     Q_D(const KoShapeContainer);
00190     KoShape::update();
00191     if (d->children)
00192         foreach(KoShape *shape, d->children->childShapes())
00193             shape->update();
00194 }
00195 
00196 QList<KoShape*> KoShapeContainer::childShapes() const
00197 {
00198     Q_D(const KoShapeContainer);
00199     if (d->children == 0)
00200         return QList<KoShape*>();
00201 
00202     return d->children->childShapes();
00203 }
00204 
00205 KoShapeContainerModel *KoShapeContainer::model() const
00206 {
00207     Q_D(const KoShapeContainer);
00208     return d->children;
00209 }
00210