Warning, file /office/calligra/libs/flake/KoTosContainer.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) 2010 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2010 KO GmbH <boud@kogmbh.com> 0004 * Copyright (C) 2010 Thorsten Zachmann <zachmann@kde.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoTosContainer.h" 0023 0024 #include "KoTosContainer_p.h" 0025 #include "KoShapeRegistry.h" 0026 #include "KoShapeFactoryBase.h" 0027 #include "KoShapeLoadingContext.h" 0028 #include "KoTextShapeDataBase.h" 0029 #include "KoTosContainerModel.h" 0030 #include "KoStyleStack.h" 0031 #include "KoOdfLoadingContext.h" 0032 #include "KoXmlNS.h" 0033 #include "KoGenStyle.h" 0034 0035 #include <FlakeDebug.h> 0036 0037 #include <QTextCursor> 0038 #include <QTextDocument> 0039 0040 KoTosContainerPrivate::KoTosContainerPrivate(KoShapeContainer *q) 0041 : KoShapeContainerPrivate(q) 0042 , resizeBehavior(KoTosContainer::IndependentSizes) 0043 { 0044 } 0045 0046 KoTosContainerPrivate::~KoTosContainerPrivate() 0047 { 0048 } 0049 0050 0051 KoTosContainer::KoTosContainer() 0052 : KoShapeContainer(*(new KoTosContainerPrivate(this))) 0053 { 0054 } 0055 0056 KoTosContainer::~KoTosContainer() 0057 { 0058 delete textShape(); 0059 } 0060 0061 KoTosContainer::KoTosContainer(KoTosContainerPrivate &dd) 0062 : KoShapeContainer(dd) 0063 { 0064 } 0065 0066 void KoTosContainer::paintComponent(QPainter &, const KoViewConverter &, KoShapePaintingContext &) 0067 { 0068 } 0069 0070 bool KoTosContainer::loadText(const KoXmlElement &element, KoShapeLoadingContext &context) 0071 { 0072 Q_D(const KoTosContainer); 0073 0074 KoXmlElement child; 0075 forEachElement(child, element) { 0076 // only recreate the text shape if there's something to be loaded 0077 if (child.localName() == "p" || child.localName() == "list") { 0078 0079 KoShape *textShape = createTextShape(context.documentResourceManager()); 0080 if (!textShape) { 0081 return false; 0082 } 0083 //apply the style properties to the loaded text 0084 setTextAlignment(d->alignment); 0085 0086 // In the case of text on shape, we cannot ask the text shape to load 0087 // the odf, since it expects a complete document with style info and 0088 // everything, so we have to use the KoTextShapeData object instead. 0089 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0090 Q_ASSERT(shapeData); 0091 shapeData->loadStyle(element, context); 0092 bool loadOdf = shapeData->loadOdf(element, context); 0093 0094 return loadOdf; 0095 } 0096 } 0097 return true; 0098 } 0099 0100 void KoTosContainer::loadStyle(const KoXmlElement &element, KoShapeLoadingContext &context) 0101 { 0102 Q_D(KoTosContainer); 0103 0104 KoShapeContainer::loadStyle(element, context); 0105 0106 KoStyleStack &styleStack = context.odfLoadingContext().styleStack(); 0107 styleStack.setTypeProperties("graphic"); 0108 0109 QString verticalAlign(styleStack.property(KoXmlNS::draw, "textarea-vertical-align")); 0110 Qt::Alignment vAlignment(Qt::AlignTop); 0111 if (verticalAlign == "bottom") { 0112 vAlignment = Qt::AlignBottom; 0113 } else if (verticalAlign == "justify") { 0114 // not yet supported 0115 vAlignment = Qt::AlignVCenter; 0116 } else if (verticalAlign == "middle") { 0117 vAlignment = Qt::AlignVCenter; 0118 } 0119 0120 QString horizontalAlign(styleStack.property(KoXmlNS::draw, "textarea-horizontal-align")); 0121 Qt::Alignment hAlignment(Qt::AlignLeft); 0122 if (horizontalAlign == "center") { 0123 hAlignment = Qt::AlignCenter; 0124 } else if (horizontalAlign == "justify") { 0125 // not yet supported 0126 hAlignment = Qt::AlignCenter; 0127 } else if (horizontalAlign == "right") { 0128 hAlignment = Qt::AlignRight; 0129 } 0130 0131 d->alignment = vAlignment | hAlignment; 0132 } 0133 0134 QString KoTosContainer::saveStyle(KoGenStyle &style, KoShapeSavingContext &context) const 0135 { 0136 Qt::Alignment alignment = textAlignment(); 0137 QString verticalAlignment = "top"; 0138 Qt::Alignment vAlignment(alignment & Qt::AlignVertical_Mask); 0139 if (vAlignment == Qt::AlignBottom) { 0140 verticalAlignment = "bottom"; 0141 } else if (vAlignment == Qt::AlignVCenter || vAlignment == Qt::AlignCenter) { 0142 verticalAlignment = "middle"; 0143 } 0144 0145 style.addProperty("draw:textarea-vertical-align", verticalAlignment); 0146 0147 QString horizontalAlignment = "left"; 0148 Qt::Alignment hAlignment(alignment & Qt::AlignHorizontal_Mask); 0149 if (hAlignment == Qt::AlignCenter || hAlignment == Qt::AlignHCenter) { 0150 horizontalAlignment = "center"; 0151 } else if (hAlignment == Qt::AlignJustify) { 0152 horizontalAlignment = "justify"; 0153 } else if (hAlignment == Qt::AlignRight) { 0154 horizontalAlignment = "right"; 0155 } 0156 0157 style.addProperty("draw:textarea-horizontal-align", horizontalAlignment); 0158 // FIXME set these dependent on flags 0159 style.addProperty("draw:auto-grow-height", "false"); 0160 style.addProperty("draw:auto-grow-width", "false"); 0161 0162 return KoShapeContainer::saveStyle(style, context); 0163 } 0164 0165 void KoTosContainer::saveText(KoShapeSavingContext &context) const 0166 { 0167 KoShape *textShape = this->textShape(); 0168 if (!textShape) { 0169 return; 0170 } 0171 // In the case of text on shape, we cannot ask the text shape to save 0172 // the odf, since it would save all the frame information as well, which 0173 // is wrong. 0174 // Only save the text shape if it has content. 0175 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0176 if (shapeData && !shapeData->document()->isEmpty()) { 0177 shapeData->saveOdf(context); 0178 } 0179 } 0180 0181 void KoTosContainer::setPlainText(const QString &text) 0182 { 0183 KoShape *textShape = this->textShape(); 0184 if (textShape == 0) { 0185 warnFlake << "No text shape present in KoTosContainer"; 0186 return; 0187 } 0188 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0189 Q_ASSERT(shapeData->document()); 0190 shapeData->document()->setPlainText(text); 0191 } 0192 0193 void KoTosContainer::setResizeBehavior(ResizeBehavior resizeBehavior) 0194 { 0195 Q_D(KoTosContainer); 0196 if (d->resizeBehavior == resizeBehavior) { 0197 return; 0198 } 0199 d->resizeBehavior = resizeBehavior; 0200 if (d->model) { 0201 d->model->containerChanged(this, KoShape::SizeChanged); 0202 } 0203 } 0204 0205 KoTosContainer::ResizeBehavior KoTosContainer::resizeBehavior() const 0206 { 0207 Q_D(const KoTosContainer); 0208 return d->resizeBehavior; 0209 } 0210 0211 void KoTosContainer::setTextAlignment(Qt::Alignment alignment) 0212 { 0213 Q_D(KoTosContainer); 0214 0215 KoShape *textShape = this->textShape(); 0216 if (textShape == 0) { 0217 warnFlake << "No text shape present in KoTosContainer"; 0218 return; 0219 } 0220 0221 // vertical 0222 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0223 shapeData->setVerticalAlignment(alignment); 0224 0225 // horizontal 0226 Q_ASSERT(shapeData->document()); 0227 QTextBlockFormat bf; 0228 bf.setAlignment(alignment & Qt::AlignHorizontal_Mask); 0229 0230 QTextCursor cursor(shapeData->document()); 0231 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); 0232 cursor.mergeBlockFormat(bf); 0233 0234 d->alignment = alignment; 0235 } 0236 0237 Qt::Alignment KoTosContainer::textAlignment() const 0238 { 0239 KoShape *textShape = this->textShape(); 0240 if (textShape == 0) { 0241 warnFlake << "No text shape present in KoTosContainer"; 0242 return Qt::AlignTop; 0243 } 0244 0245 // vertical 0246 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0247 // the model makes sure it contains a shape that has a KoTextShapeDataBase set so no need to check that 0248 Qt::Alignment answer = shapeData->verticalAlignment() & Qt::AlignVertical_Mask; 0249 0250 // horizontal 0251 Q_ASSERT(shapeData->document()); 0252 QTextCursor cursor(shapeData->document()); 0253 answer = answer | (cursor.blockFormat().alignment() & Qt::AlignHorizontal_Mask); 0254 0255 return answer; 0256 } 0257 0258 void KoTosContainer::setPreferredTextRect(const QRectF &rect) 0259 { 0260 Q_D(KoTosContainer); 0261 d->preferredTextRect = rect; 0262 KoShape *textShape = this->textShape(); 0263 //debugFlake << rect << textShape << d->resizeBehavior; 0264 if (d->resizeBehavior == TextFollowsPreferredTextRect && textShape) { 0265 //debugFlake << rect; 0266 textShape->setPosition(rect.topLeft()); 0267 textShape->setSize(rect.size()); 0268 } 0269 } 0270 0271 QRectF KoTosContainer::preferredTextRect() const 0272 { 0273 Q_D(const KoTosContainer); 0274 return d->preferredTextRect; 0275 } 0276 0277 KoShape *KoTosContainer::createTextShape(KoDocumentResourceManager *documentResources) 0278 { 0279 if (!documentResources) { 0280 warnFlake << "KoDocumentResourceManager not found"; 0281 return 0; 0282 } 0283 0284 Q_D(KoTosContainer); 0285 0286 delete textShape(); 0287 delete d->model; 0288 0289 d->model = new KoTosContainerModel(); 0290 0291 QSet<KoShape*> delegates; 0292 delegates << this; 0293 KoShape *textShape = 0; 0294 KoShapeFactoryBase *factory = KoShapeRegistry::instance()->get("TextShapeID"); 0295 if (factory) { // not installed, thats too bad, but allowed 0296 textShape = factory->createDefaultShape(documentResources); 0297 Q_ASSERT(textShape); // would be a bug in the text shape; 0298 if (d->resizeBehavior == TextFollowsPreferredTextRect) { 0299 textShape->setSize(d->preferredTextRect.size()); 0300 } else { 0301 textShape->setSize(size()); 0302 } 0303 if (d->resizeBehavior == TextFollowsPreferredTextRect) { 0304 textShape->setPosition(d->preferredTextRect.topLeft()); 0305 } else { 0306 textShape->setPosition(QPointF(0, 0)); 0307 } 0308 textShape->setSelectable(false); 0309 textShape->setRunThrough(runThrough()); 0310 KoTextShapeDataBase *shapeData = qobject_cast<KoTextShapeDataBase*>(textShape->userData()); 0311 Q_ASSERT(shapeData); // would be a bug in kotext 0312 // TODO check if that is correct depending on the resize mode 0313 shapeData->setVerticalAlignment(Qt::AlignVCenter); 0314 addShape(textShape); 0315 // textShape->setZIndex(zIndex() + 1); // not needed as there as the text shape is the only sub shape 0316 delegates << textShape; 0317 } else { 0318 warnFlake << "Text shape factory not found"; 0319 } 0320 setToolDelegates(delegates); 0321 return textShape; 0322 } 0323 0324 KoShape *KoTosContainer::textShape() const 0325 { 0326 const QList<KoShape*> subShapes = shapes(); 0327 return subShapes.isEmpty() ? 0 : subShapes.at(0); 0328 } 0329 0330 void KoTosContainer::shapeChanged(ChangeType type, KoShape *shape) 0331 { 0332 Q_UNUSED(shape); 0333 Q_D(KoTosContainer); 0334 if (d->model == 0) { 0335 return; 0336 } 0337 0338 if (type == SizeChanged || type == ContentChanged) { 0339 d->model->containerChanged(this, type); 0340 } 0341 // TODO is this needed? 0342 #if 0 0343 foreach(KoShape *shape, d->model->shapes()) 0344 shape->notifyChanged(); 0345 #endif 0346 } 0347 0348 void KoTosContainer::setRunThrough(short int runThrough) 0349 { 0350 KoShape::setRunThrough(runThrough); 0351 KoShape *textShape = this->textShape(); 0352 if (textShape) { 0353 textShape->setRunThrough(runThrough); 0354 } 0355 }