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 }