Warning, file /office/calligra/libs/flake/KoShapeContainer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2006-2010 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 #include "KoShapeContainer.h" 0021 #include "KoShapeContainer_p.h" 0022 #include "KoShapeContainerModel.h" 0023 #include "KoShapeStrokeModel.h" 0024 #include "KoShapeContainerDefaultModel.h" 0025 #include "KoShapeSavingContext.h" 0026 0027 #include <QPointF> 0028 #include <QPainter> 0029 #include <QPainterPath> 0030 0031 #include <algorithm> 0032 0033 KoShapeContainerPrivate::KoShapeContainerPrivate(KoShapeContainer *q) 0034 : KoShapePrivate(q), 0035 model(0) 0036 { 0037 } 0038 0039 KoShapeContainerPrivate::~KoShapeContainerPrivate() 0040 { 0041 delete model; 0042 } 0043 0044 KoShapeContainer::KoShapeContainer(KoShapeContainerModel *model) 0045 : KoShape(*(new KoShapeContainerPrivate(this))) 0046 { 0047 Q_D(KoShapeContainer); 0048 d->model = model; 0049 } 0050 0051 KoShapeContainer::KoShapeContainer(KoShapeContainerPrivate &dd) 0052 : KoShape(dd) 0053 { 0054 } 0055 0056 KoShapeContainer::~KoShapeContainer() 0057 { 0058 Q_D(KoShapeContainer); 0059 if (d->model) { 0060 foreach(KoShape *shape, d->model->shapes()) { 0061 delete shape; 0062 } 0063 } 0064 } 0065 0066 void KoShapeContainer::addShape(KoShape *shape) 0067 { 0068 Q_D(KoShapeContainer); 0069 Q_ASSERT(shape); 0070 if (shape->parent() == this && shapes().contains(shape)) 0071 return; 0072 // TODO add a method to create a default model depending on the shape container 0073 if (d->model == 0) 0074 d->model = new KoShapeContainerDefaultModel(); 0075 if (shape->parent() && shape->parent() != this) 0076 shape->parent()->removeShape(shape); 0077 d->model->add(shape); 0078 shape->setParent(this); 0079 } 0080 0081 void KoShapeContainer::removeShape(KoShape *shape) 0082 { 0083 Q_D(KoShapeContainer); 0084 Q_ASSERT(shape); 0085 if (d->model == 0) 0086 return; 0087 d->model->remove(shape); 0088 shape->setParent(0); 0089 0090 KoShapeContainer * grandparent = parent(); 0091 if (grandparent) { 0092 grandparent->model()->childChanged(this, KoShape::ChildChanged); 0093 } 0094 } 0095 0096 void KoShapeContainer::removeAllShapes() 0097 { 0098 Q_D(KoShapeContainer); 0099 if (d->model == 0) 0100 return; 0101 for(int i = d->model->shapes().count() - 1; i >= 0; --i) { 0102 KoShape *shape = d->model->shapes().at(i); 0103 d->model->remove(shape); 0104 shape->setParent(0); 0105 } 0106 0107 KoShapeContainer * grandparent = parent(); 0108 if (grandparent) { 0109 grandparent->model()->childChanged(this, KoShape::ChildChanged); 0110 } 0111 } 0112 0113 int KoShapeContainer::shapeCount() const 0114 { 0115 Q_D(const KoShapeContainer); 0116 if (d->model == 0) 0117 return 0; 0118 return d->model->count(); 0119 } 0120 0121 bool KoShapeContainer::isChildLocked(const KoShape *child) const 0122 { 0123 Q_D(const KoShapeContainer); 0124 if (d->model == 0) 0125 return false; 0126 return d->model->isChildLocked(child); 0127 } 0128 0129 KoShape::AllowedInteractions KoShapeContainer::allowedInteractions(const KoShape *child) const 0130 { 0131 Q_D(const KoShapeContainer); 0132 KoShape::AllowedInteractions state; 0133 if (!d->model) { 0134 return child->allowedInteractions(false); 0135 } 0136 return d->model->allowedInteractions(child); 0137 } 0138 0139 void KoShapeContainer::setClipped(const KoShape *child, bool clipping) 0140 { 0141 Q_D(KoShapeContainer); 0142 if (d->model == 0) 0143 return; 0144 d->model->setClipped(child, clipping); 0145 } 0146 0147 void KoShapeContainer::setInheritsTransform(const KoShape *shape, bool inherit) 0148 { 0149 Q_D(KoShapeContainer); 0150 if (d->model == 0) 0151 return; 0152 d->model->setInheritsTransform(shape, inherit); 0153 } 0154 0155 bool KoShapeContainer::inheritsTransform(const KoShape *shape) const 0156 { 0157 Q_D(const KoShapeContainer); 0158 if (d->model == 0) 0159 return false; 0160 return d->model->inheritsTransform(shape); 0161 } 0162 0163 void KoShapeContainer::paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintcontext) 0164 { 0165 Q_D(KoShapeContainer); 0166 painter.save(); 0167 paintComponent(painter, converter, paintcontext); 0168 painter.restore(); 0169 if (d->model == 0 || d->model->count() == 0) 0170 return; 0171 0172 QList<KoShape*> sortedObjects = d->model->shapes(); 0173 std::sort(sortedObjects.begin(), sortedObjects.end(), KoShape::compareShapeZIndex); 0174 0175 // Do the following to revert the absolute transformation of the container 0176 // that is re-applied in shape->absoluteTransformation() later on. The transformation matrix 0177 // of the container has already been applied once before this function is called. 0178 QTransform baseMatrix = absoluteTransformation(&converter).inverted() * painter.transform(); 0179 0180 // clip the children to the parent outline. 0181 QTransform m; 0182 qreal zoomX, zoomY; 0183 converter.zoom(&zoomX, &zoomY); 0184 m.scale(zoomX, zoomY); 0185 painter.setClipPath(m.map(outline()), Qt::IntersectClip); 0186 0187 QRectF toPaintRect = converter.viewToDocument(painter.clipRegion().boundingRect()); 0188 toPaintRect = transform().mapRect(toPaintRect); 0189 // We'll use this clipRect to see if our child shapes lie within it. 0190 // Because shape->boundingRect() uses absoluteTransformation(0) we'll 0191 // use that as well to have the same (absolute) reference transformation 0192 // of our and the child's bounding boxes. 0193 QTransform absTrans = absoluteTransformation(0); 0194 QRectF clipRect = absTrans.map(outline()).boundingRect(); 0195 0196 0197 foreach(KoShape *shape, sortedObjects) { 0198 //debugFlake <<"KoShapeContainer::painting shape:" << shape->shapeId() <<"," << shape->boundingRect(); 0199 if (!shape->isVisible()) 0200 continue; 0201 if (!isClipped(shape)) // the shapeManager will have to draw those, or else we can't do clipRects 0202 continue; 0203 // don't try to draw a child shape that is not in the clipping rect of the painter. 0204 if (!clipRect.intersects(shape->boundingRect())) 0205 0206 continue; 0207 0208 painter.save(); 0209 painter.setTransform(shape->absoluteTransformation(&converter) * baseMatrix); 0210 shape->paint(painter, converter, paintcontext); 0211 painter.restore(); 0212 if (shape->stroke()) { 0213 painter.save(); 0214 painter.setTransform(shape->absoluteTransformation(&converter) * baseMatrix); 0215 shape->stroke()->paint(shape, painter, converter); 0216 painter.restore(); 0217 } 0218 } 0219 } 0220 0221 void KoShapeContainer::shapeChanged(ChangeType type, KoShape* shape) 0222 { 0223 Q_UNUSED(shape); 0224 Q_D(KoShapeContainer); 0225 if (d->model == 0) 0226 return; 0227 if (!(type == RotationChanged || type == ScaleChanged || type == ShearChanged 0228 || type == SizeChanged || type == PositionChanged || type == GenericMatrixChange)) 0229 return; 0230 d->model->containerChanged(this, type); 0231 foreach(KoShape *shape, d->model->shapes()) 0232 shape->notifyChanged(); 0233 } 0234 0235 bool KoShapeContainer::isClipped(const KoShape *child) const 0236 { 0237 Q_D(const KoShapeContainer); 0238 if (d->model == 0) // throw exception?? 0239 return false; 0240 return d->model->isClipped(child); 0241 } 0242 0243 void KoShapeContainer::update() const 0244 { 0245 Q_D(const KoShapeContainer); 0246 KoShape::update(); 0247 if (d->model) 0248 foreach(KoShape *shape, d->model->shapes()) 0249 shape->update(); 0250 } 0251 0252 QList<KoShape*> KoShapeContainer::shapes() const 0253 { 0254 Q_D(const KoShapeContainer); 0255 if (d->model == 0) 0256 return QList<KoShape*>(); 0257 0258 return d->model->shapes(); 0259 } 0260 0261 KoShapeContainerModel *KoShapeContainer::model() const 0262 { 0263 Q_D(const KoShapeContainer); 0264 return d->model; 0265 }