File indexing completed on 2024-05-12 16:34:43
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2008 Peter Simonsson <peter.simonsson@gmail.com> 0003 * Copyright (C) 2010-2014 Yue Liu <yue.liu@mail.com> 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 0021 #include "StencilShapeFactory.h" 0022 0023 #include "StencilBoxDebug.h" 0024 0025 #include <KoShape.h> 0026 #include <KoDrag.h> 0027 #include <KoShapeOdfSaveHelper.h> 0028 #include <KoOdf.h> 0029 #include <KoShapeLoadingContext.h> 0030 #include <KoShapeBasedDocumentBase.h> 0031 #include <KoOdfLoadingContext.h> 0032 #include <KoStore.h> 0033 #include <KoOdfReadStore.h> 0034 #include <KoXmlNS.h> 0035 #include <KoShapeRegistry.h> 0036 #include <SvgParser.h> 0037 #include <KoProperties.h> 0038 #include <KoShapeGroup.h> 0039 #include <KoShapeGroupCommand.h> 0040 0041 #include <QMimeData> 0042 #include <QIODevice> 0043 #include <KArchive/kcompressiondevice.h> 0044 0045 StencilShapeFactory:: 0046 StencilShapeFactory(const QString& id, 0047 const QString& name, 0048 const KoProperties* props) 0049 : KoShapeFactoryBase(id, name) 0050 , m_properties(props) 0051 { 0052 // ensures ShapeCollectionDocker ignores the stencil shapes for now, 0053 // exclusively available by StencilBox 0054 setFamily("stencil"); 0055 } 0056 0057 StencilShapeFactory:: 0058 ~StencilShapeFactory() 0059 { 0060 delete m_properties; 0061 } 0062 0063 KoShape* StencilShapeFactory:: 0064 createFromOdf(KoStore* store, KoDocumentResourceManager* documentRes) const 0065 { 0066 KoOdfReadStore odfStore(store); 0067 QString errorMessage; 0068 if (! odfStore.loadAndParse(errorMessage)) { 0069 errorStencilBox << "loading and parsing failed:" << errorMessage << endl; 0070 return 0; 0071 } 0072 0073 KoXmlElement content = odfStore.contentDoc().documentElement(); 0074 KoXmlElement realBody(KoXml::namedItemNS(content, KoXmlNS::office, "body")); 0075 if (realBody.isNull()) { 0076 errorStencilBox << "No body tag found!" << endl; 0077 return 0; 0078 } 0079 0080 KoXmlElement body = KoXml::namedItemNS(realBody, KoXmlNS::office, "drawing"); 0081 if (body.isNull()) { 0082 errorStencilBox << "No office:drawing tag found!" << endl; 0083 return 0; 0084 } 0085 0086 KoXmlElement page = KoXml::namedItemNS(body, KoXmlNS::draw, "page"); 0087 if (page.isNull()) { 0088 errorStencilBox << "No page found!" << endl; 0089 return 0; 0090 } 0091 0092 KoXmlElement shapeElement = KoXml::namedItemNS(page, KoXmlNS::draw, "g"); 0093 if (shapeElement.isNull()) { 0094 shapeElement = KoXml::namedItemNS(page, KoXmlNS::draw, "custom-shape"); 0095 if (shapeElement.isNull()) { 0096 errorStencilBox << "draw:g or draw:custom-shape element not found!" << endl; 0097 return 0; 0098 } 0099 } 0100 0101 KoOdfLoadingContext loadingContext(odfStore.styles(), odfStore.store()); 0102 KoShapeLoadingContext context(loadingContext, documentRes); 0103 0104 KoShapeRegistry* registry = KoShapeRegistry::instance(); 0105 foreach (const QString & id, registry->keys()) { 0106 KoShapeFactoryBase* shapeFactory = registry->value(id); 0107 shapeFactory->newDocumentResourceManager(documentRes); 0108 } 0109 0110 return KoShapeRegistry::instance()->createShapeFromOdf(shapeElement, context); 0111 } 0112 0113 KoShape* StencilShapeFactory:: 0114 createFromSvg(QIODevice* in, KoDocumentResourceManager* documentRes) const 0115 { 0116 if (!in->open(QIODevice::ReadOnly)) { 0117 debugStencilBox << "svg file open error"; 0118 return 0; 0119 } 0120 0121 int line, col; 0122 QString errormessage; 0123 KoXmlDocument inputDoc; 0124 const bool parsed = inputDoc.setContent(in, &errormessage, &line, &col); 0125 in->close(); 0126 0127 if (!parsed) { 0128 debugStencilBox << "Error while parsing file: " 0129 << "at line " << line << " column: " << col 0130 << " message: " << errormessage << endl; 0131 return 0; 0132 } 0133 0134 SvgParser parser(documentRes); 0135 parser.setXmlBaseDir(id()); 0136 QList<KoShape*> shapes = parser.parseSvg(inputDoc.documentElement()); 0137 if (shapes.isEmpty()) 0138 return 0; 0139 if (shapes.count() == 1) 0140 return shapes.first(); 0141 0142 KoShapeGroup *svgGroup = new KoShapeGroup; 0143 KoShapeGroupCommand cmd(svgGroup, shapes); 0144 cmd.redo(); 0145 0146 return svgGroup; 0147 } 0148 0149 KoShape* StencilShapeFactory:: 0150 createDefaultShape(KoDocumentResourceManager* documentResources) const 0151 { 0152 KoShape* shape = 0; 0153 KoStore* store = 0; 0154 QIODevice* in = 0; 0155 QString ext = id().mid(id().lastIndexOf('.')).toLower(); 0156 if (ext == ".odg") { 0157 store = KoStore::createStore(id(), KoStore::Read); 0158 if (!store->bad()) { 0159 shape = createFromOdf(store, documentResources); 0160 } 0161 delete store; 0162 } else if (ext == ".svg") { 0163 in = new KCompressionDevice(id(), KCompressionDevice::None); 0164 shape = createFromSvg(in, documentResources); 0165 delete in; 0166 } else if (ext == ".svgz") { 0167 in = new KCompressionDevice(id(), KCompressionDevice::GZip); 0168 shape = createFromSvg(in, documentResources); 0169 delete in; 0170 } else { 0171 debugStencilBox << "stencil format" << ext << "unsupported"; 0172 } 0173 0174 if (shape) { 0175 if (m_properties->intProperty("keepAspectRatio") == 1) 0176 shape->setKeepAspectRatio(true); 0177 } 0178 0179 return shape; 0180 } 0181 0182 // StencilShapeFactory shouldn't participate element support detection 0183 bool StencilShapeFactory:: 0184 supports(const KoXmlElement& e, KoShapeLoadingContext& context) const 0185 { 0186 Q_UNUSED(e); 0187 Q_UNUSED(context); 0188 return false; 0189 }