File indexing completed on 2024-05-12 15:56:53

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2010 Thomas Zander <zander@kde.org>
0003  * SPDX-FileCopyrightText: 2010 KO GmbH <boud@valdyas.org>
0004  * SPDX-FileCopyrightText: 2010 Thorsten Zachmann <zachmann@kde.org>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.0-or-later
0007  */
0008 
0009 #include "KoTosContainer.h"
0010 
0011 #include "KoTosContainer_p.h"
0012 #include "KoShapeRegistry.h"
0013 #include "KoShapeFactoryBase.h"
0014 #include "KoShapeLoadingContext.h"
0015 #include "KoTextShapeDataBase.h"
0016 #include "KoTosContainerModel.h"
0017 #include "KoXmlNS.h"
0018 
0019 #include <FlakeDebug.h>
0020 
0021 #include <QTextCursor>
0022 #include <QTextDocument>
0023 
0024 KoTosContainer::Private::Private()
0025     : QSharedData()
0026     , resizeBehavior(KoTosContainer::IndependentSizes)
0027 {
0028 }
0029 
0030 KoTosContainer::Private::Private(const Private &rhs)
0031     : QSharedData()
0032     , resizeBehavior(rhs.resizeBehavior)
0033     , preferredTextRect(rhs.preferredTextRect)
0034     , alignment(rhs.alignment)
0035 {
0036 }
0037 
0038 KoTosContainer::Private::~Private()
0039 {
0040 }
0041 
0042 
0043 KoTosContainer::KoTosContainer()
0044     : KoShapeContainer()
0045     , d(new Private)
0046 {
0047 }
0048 
0049 KoTosContainer::KoTosContainer(const KoTosContainer &rhs)
0050     : KoShapeContainer(rhs)
0051     , d(rhs.d)
0052 {
0053 }
0054 
0055 KoTosContainer::~KoTosContainer()
0056 {
0057     delete textShape();
0058 }
0059 
0060 void KoTosContainer::paintComponent(QPainter &) const
0061 {
0062 }
0063 
0064 bool KoTosContainer::loadText(const QDomElement &element)
0065 {
0066     Q_UNUSED(element);
0067     return false;
0068 }
0069 
0070 
0071 void KoTosContainer::setPlainText(const QString &text)
0072 {
0073     KoShape *textShape = this->textShape();
0074     if (textShape == 0) {
0075         warnFlake << "No text shape present in KoTosContainer";
0076         return;
0077     }
0078     KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData());
0079     Q_ASSERT(shapeData->document());
0080     shapeData->document()->setPlainText(text);
0081 }
0082 
0083 void KoTosContainer::setResizeBehavior(ResizeBehavior resizeBehavior)
0084 {
0085     if (d->resizeBehavior == resizeBehavior) {
0086         return;
0087     }
0088     d->resizeBehavior = resizeBehavior;
0089     if (model()) {
0090         model()->containerChanged(this, KoShape::SizeChanged);
0091     }
0092 }
0093 
0094 KoTosContainer::ResizeBehavior KoTosContainer::resizeBehavior() const
0095 {
0096     return d->resizeBehavior;
0097 }
0098 
0099 void KoTosContainer::setTextAlignment(Qt::Alignment alignment)
0100 {
0101     KoShape *textShape = this->textShape();
0102     if (textShape == 0) {
0103         warnFlake << "No text shape present in KoTosContainer";
0104         return;
0105     }
0106 
0107     // vertical
0108     KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData());
0109     shapeData->setVerticalAlignment(alignment);
0110 
0111     // horizontal
0112     Q_ASSERT(shapeData->document());
0113     QTextBlockFormat bf;
0114     bf.setAlignment(alignment & Qt::AlignHorizontal_Mask);
0115 
0116     QTextCursor cursor(shapeData->document());
0117     cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
0118     cursor.mergeBlockFormat(bf);
0119 
0120     d->alignment = alignment;
0121 }
0122 
0123 Qt::Alignment KoTosContainer::textAlignment() const
0124 {
0125     KoShape *textShape = this->textShape();
0126     if (textShape == 0) {
0127         warnFlake << "No text shape present in KoTosContainer";
0128         return Qt::AlignTop;
0129     }
0130 
0131     // vertical
0132     KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData());
0133     // the model makes sure it contains a shape that has a KoTextShapeDataBase set so no need to check that
0134     Qt::Alignment answer = shapeData->verticalAlignment() & Qt::AlignVertical_Mask;
0135 
0136     // horizontal
0137     Q_ASSERT(shapeData->document());
0138     QTextCursor cursor(shapeData->document());
0139     answer = answer | (cursor.blockFormat().alignment() & Qt::AlignHorizontal_Mask);
0140 
0141     return answer;
0142 }
0143 
0144 void KoTosContainer::setPreferredTextRect(const QRectF &rect)
0145 {
0146     d->preferredTextRect = rect;
0147     KoShape *textShape = this->textShape();
0148     //debugFlake << rect << textShape << d->resizeBehavior;
0149     if (d->resizeBehavior == TextFollowsPreferredTextRect && textShape) {
0150         //debugFlake << rect;
0151         textShape->setPosition(rect.topLeft());
0152         textShape->setSize(rect.size());
0153     }
0154 }
0155 
0156 QRectF KoTosContainer::preferredTextRect() const
0157 {
0158     return d->preferredTextRect;
0159 }
0160 
0161 KoShape *KoTosContainer::createTextShape(KoDocumentResourceManager *documentResources)
0162 {
0163     if (!documentResources) {
0164         warnFlake << "KoDocumentResourceManager not found";
0165         return 0;
0166     }
0167 
0168     delete textShape();
0169     delete model();
0170 
0171     setModel(new KoTosContainerModel());
0172 
0173     QSet<KoShape*> delegates;
0174     delegates << this;
0175     KoShape *textShape = 0;
0176     KoShapeFactoryBase *factory = KoShapeRegistry::instance()->get("TextShapeID");
0177     if (factory) { // not installed, that's too bad, but allowed
0178         textShape = factory->createDefaultShape(documentResources);
0179         Q_ASSERT(textShape); // would be a bug in the text shape;
0180         if (d->resizeBehavior == TextFollowsPreferredTextRect) {
0181             textShape->setSize(d->preferredTextRect.size());
0182         } else {
0183             textShape->setSize(size());
0184         }
0185         if (d->resizeBehavior == TextFollowsPreferredTextRect) {
0186             textShape->setPosition(d->preferredTextRect.topLeft());
0187         } else {
0188             textShape->setPosition(QPointF(0, 0));
0189         }
0190         textShape->setSelectable(false);
0191         textShape->setRunThrough(runThrough());
0192         KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData());
0193         Q_ASSERT(shapeData); // would be a bug in kotext
0194         // TODO check if that is correct depending on the resize mode
0195         shapeData->setVerticalAlignment(Qt::AlignVCenter);
0196         addShape(textShape);
0197         // textShape->setZIndex(zIndex() + 1); // not needed as there as the text shape is the only sub shape
0198         delegates << textShape;
0199     } else {
0200         warnFlake << "Text shape factory not found";
0201     }
0202     setToolDelegates(delegates);
0203     return textShape;
0204 }
0205 
0206 KoShape *KoTosContainer::textShape() const
0207 {
0208     const QList<KoShape*> subShapes = shapes();
0209     return subShapes.isEmpty() ? 0 : subShapes.at(0);
0210 }
0211 
0212 void KoTosContainer::shapeChanged(ChangeType type, KoShape *shape)
0213 {
0214     Q_UNUSED(shape);
0215     if (model() == 0) {
0216         return;
0217     }
0218 
0219     if (type == SizeChanged || type == ContentChanged) {
0220         model()->containerChanged(this, type);
0221     }
0222     // TODO is this needed?
0223 #if 0
0224     Q_FOREACH (KoShape *shape, model()->shapes())
0225         shape->notifyChanged();
0226 #endif
0227 }
0228 
0229 void KoTosContainer::setRunThrough(short int runThrough)
0230 {
0231     KoShape::setRunThrough(runThrough);
0232     KoShape *textShape = this->textShape();
0233     if (textShape) {
0234         textShape->setRunThrough(runThrough);
0235     }
0236 }