Warning, file /office/calligra/braindump/src/Layout.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  Copyright (c) 2009 Cyrille Berger <cberger@cberger.net>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation;
0007  * either version 2, or (at your option) any later version of the License.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public License
0015  * along with this library; see the file COPYING.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "Layout.h"
0021 
0022 #include <QEvent>
0023 #include <QPainter>
0024 #include <QCoreApplication>
0025 
0026 #include <KoShape.h>
0027 #include <KoViewConverter.h>
0028 #include <KoXmlReader.h>
0029 #include <KoShapeLoadingContext.h>
0030 #include <KoShapeSavingContext.h>
0031 
0032 #include <Utils.h>
0033 
0034 struct Layout::Private : public KoShape {
0035     Private() : eventSent(false) {}
0036     Layout* self;
0037     QList<KoShape*> shapes;
0038     QString id;
0039     bool eventSent;
0040     void removeDependees();
0041     void triggerRelayout();
0042 protected:
0043     virtual void shapeChanged(ChangeType type, KoShape * shape);
0044 private:
0045     // Fake
0046     virtual void paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &) {
0047         Q_UNUSED(painter);
0048         Q_UNUSED(converter);
0049         qFatal("Shouldn't be called");
0050     }
0051     virtual bool loadOdf(const KoXmlElement & element, KoShapeLoadingContext &context) {
0052         Q_UNUSED(element);
0053         Q_UNUSED(context);
0054         qFatal("Shouldn't be called");
0055         return false;
0056     }
0057     virtual void saveOdf(KoShapeSavingContext & context) const {
0058         Q_UNUSED(context);
0059         qFatal("Shouldn't be called");
0060     }
0061 
0062 };
0063 
0064 static int event_type_delayed_relayout = QEvent::registerEventType();
0065 
0066 void Layout::Private::removeDependees()
0067 {
0068     foreach(KoShape * shape, shapes) {
0069         shape->removeDependee(this);
0070     }
0071 }
0072 
0073 void Layout::Private::shapeChanged(ChangeType type, KoShape * shape)
0074 {
0075     switch(type) {
0076     case PositionChanged:
0077     case RotationChanged:
0078     case ScaleChanged:
0079     case ShearChanged:
0080     case SizeChanged:
0081     case GenericMatrixChange:
0082         self->shapeGeometryChanged(shape);
0083         triggerRelayout();
0084         break;
0085     default:
0086         break;
0087     }
0088 }
0089 
0090 void Layout::Private::triggerRelayout()
0091 {
0092     if(!eventSent) {
0093         QCoreApplication::postEvent(self, new QEvent(QEvent::Type(event_type_delayed_relayout)));
0094         eventSent = true;
0095     }
0096 }
0097 
0098 
0099 Layout::Layout(const QString& _id) : d(new Private)
0100 {
0101     d->self = this;
0102     d->id = _id;
0103 }
0104 
0105 Layout::~Layout()
0106 {
0107     d->removeDependees();
0108     delete d;
0109 }
0110 
0111 const QString& Layout::id() const
0112 {
0113     return d->id;
0114 }
0115 
0116 void Layout::replaceLayout(Layout* layout)
0117 {
0118     layout->d->removeDependees(); // Avoid both layout to fight for the shapes position
0119     addShapes(layout->d->shapes);
0120     d->triggerRelayout();
0121 }
0122 
0123 void Layout::addShapes(QList<KoShape*> _shapes)
0124 {
0125     foreach(KoShape * shape, _shapes) {
0126         Q_ASSERT(!d->shapes.contains(shape));
0127         d->shapes.push_back(shape);
0128     }
0129     shapesAdded(_shapes);
0130     foreach(KoShape * shape, _shapes) {
0131         shape->addDependee(d);
0132     }
0133     d->triggerRelayout();
0134 }
0135 
0136 void Layout::addShape(KoShape* _shape)
0137 {
0138     Q_ASSERT(!d->shapes.contains(_shape));
0139     d->shapes.push_back(_shape);
0140     shapeAdded(_shape);
0141     _shape->addDependee(d);
0142     d->triggerRelayout();
0143 }
0144 
0145 void Layout::removeShape(KoShape* _shape)
0146 {
0147     _shape->removeDependee(d);
0148     d->shapes.removeAll(_shape);
0149     shapeRemoved(_shape);
0150     d->triggerRelayout();
0151 }
0152 
0153 void Layout::shapesAdded(QList<KoShape*> _shapes)
0154 {
0155     foreach(KoShape * shape, _shapes) {
0156         shapeAdded(shape);
0157     }
0158 }
0159 
0160 
0161 QRectF Layout::boundingBox() const
0162 {
0163     QRectF b;
0164     Utils::containerBoundRec(shapes(), b);
0165     return b;
0166 }
0167 
0168 const QList<KoShape*>& Layout::shapes() const
0169 {
0170     return d->shapes;
0171 }
0172 
0173 bool Layout::event(QEvent * e)
0174 {
0175     if(e->type() == event_type_delayed_relayout) {
0176         Q_ASSERT(d->eventSent);
0177         e->accept();
0178         relayout();
0179         d->eventSent = false;
0180         return true;
0181     } else {
0182         return QObject::event(e);
0183     }
0184 }