Warning, file /office/calligra/libs/odf/KoOdfStylesReader.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) 2004-2006 David Faure <faure@kde.org> 0003 Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net> 0004 Copyright (C) 2008 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 version 2 as published by the Free Software Foundation. 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 "KoOdfStylesReader.h" 0022 0023 #include "KoXmlNS.h" 0024 #include "KoOdfNotesConfiguration.h" 0025 #include "KoOdfNumberDefinition.h" 0026 #include "KoOdfLineNumberingConfiguration.h" 0027 #include "KoOdfBibliographyConfiguration.h" 0028 0029 #include <OdfDebug.h> 0030 0031 class Q_DECL_HIDDEN KoOdfStylesReader::Private 0032 { 0033 public: 0034 0035 Private() 0036 : globalFootnoteConfiguration(KoOdfNotesConfiguration::Footnote) 0037 , globalEndnoteConfiguration(KoOdfNotesConfiguration::Endnote) 0038 { 0039 } 0040 0041 QHash < QString /*family*/, QHash < QString /*name*/, KoXmlElement* > > customStyles; 0042 // auto-styles in content.xml 0043 QHash < QString /*family*/, QHash < QString /*name*/, KoXmlElement* > > contentAutoStyles; 0044 // auto-styles in styles.xml 0045 QHash < QString /*family*/, QHash < QString /*name*/, KoXmlElement* > > stylesAutoStyles; 0046 QHash < QString /*family*/, KoXmlElement* > defaultStyles; 0047 0048 QHash < QString /*name*/, KoXmlElement* > styles; // page-layout, font-face etc. 0049 QHash < QString /*name*/, KoXmlElement* > masterPages; 0050 QHash < QString /*name*/, KoXmlElement* > presentationPageLayouts; 0051 QHash < QString /*drawType*/, QHash< QString /*name*/, KoXmlElement* > > drawStyles; 0052 0053 QList <KoXmlElement* > tableTemplates; 0054 0055 KoXmlElement officeStyle; 0056 KoXmlElement layerSet; 0057 0058 DataFormatsMap dataFormats; 0059 0060 // XXX: there can also be notes configuration objects _per_ section. 0061 KoOdfNotesConfiguration globalFootnoteConfiguration; 0062 KoOdfNotesConfiguration globalEndnoteConfiguration; 0063 0064 KoOdfBibliographyConfiguration globalBibliographyConfiguration; 0065 0066 KoOdfLineNumberingConfiguration lineNumberingConfiguration; 0067 0068 }; 0069 0070 KoOdfStylesReader::KoOdfStylesReader() 0071 : d(new Private) 0072 { 0073 } 0074 0075 KoOdfStylesReader::~KoOdfStylesReader() 0076 { 0077 typedef QHash<QString, KoXmlElement*> AutoStylesMap; 0078 foreach(const AutoStylesMap& map, d->customStyles) 0079 qDeleteAll(map); 0080 foreach(const AutoStylesMap& map, d->contentAutoStyles) 0081 qDeleteAll(map); 0082 foreach(const AutoStylesMap& map, d->stylesAutoStyles) 0083 qDeleteAll(map); 0084 foreach(const DataFormatsMap::mapped_type& dataFormat, d->dataFormats) 0085 delete dataFormat.second; 0086 qDeleteAll(d->defaultStyles); 0087 qDeleteAll(d->styles); 0088 qDeleteAll(d->masterPages); 0089 qDeleteAll(d->presentationPageLayouts); 0090 qDeleteAll(d->tableTemplates); 0091 foreach(const AutoStylesMap& map, d->drawStyles) { 0092 qDeleteAll(map); 0093 } 0094 delete d; 0095 } 0096 0097 void KoOdfStylesReader::createStyleMap(const KoXmlDocument& doc, bool stylesDotXml) 0098 { 0099 const KoXmlElement docElement = doc.documentElement(); 0100 // We used to have the office:version check here, but better let the apps do that 0101 KoXmlElement fontStyles = KoXml::namedItemNS(docElement, KoXmlNS::office, "font-face-decls"); 0102 0103 if (!fontStyles.isNull()) { 0104 //debugOdf <<"Starting reading in font-face-decls..."; 0105 insertStyles(fontStyles, stylesDotXml ? AutomaticInStyles : AutomaticInContent); 0106 }// else 0107 // debugOdf <<"No items found"; 0108 0109 //debugOdf <<"Starting reading in office:automatic-styles. stylesDotXml=" << stylesDotXml; 0110 0111 KoXmlElement autoStyles = KoXml::namedItemNS(docElement, KoXmlNS::office, "automatic-styles"); 0112 if (!autoStyles.isNull()) { 0113 insertStyles(autoStyles, stylesDotXml ? AutomaticInStyles : AutomaticInContent); 0114 }// else 0115 // debugOdf <<"No items found"; 0116 0117 0118 //debugOdf <<"Reading in master styles"; 0119 0120 KoXmlNode masterStyles = KoXml::namedItemNS(docElement, KoXmlNS::office, "master-styles"); 0121 if (!masterStyles.isNull()) { 0122 KoXmlElement master; 0123 forEachElement(master, masterStyles) { 0124 if (master.localName() == "master-page" && 0125 master.namespaceURI() == KoXmlNS::style) { 0126 const QString name = master.attributeNS(KoXmlNS::style, "name", QString()); 0127 debugOdf << "Master style: '" << name << "' loaded"; 0128 d->masterPages.insert(name, new KoXmlElement(master)); 0129 } else if (master.localName() == "layer-set" && master.namespaceURI() == KoXmlNS::draw) { 0130 debugOdf << "Master style: layer-set loaded"; 0131 d->layerSet = master; 0132 } else 0133 // OASIS docu mentions style:handout-master and draw:layer-set here 0134 warnOdf << "Unknown tag " << master.tagName() << " in office:master-styles"; 0135 } 0136 } 0137 0138 0139 debugOdf << "Starting reading in office:styles"; 0140 0141 const KoXmlElement officeStyle = KoXml::namedItemNS(docElement, KoXmlNS::office, "styles"); 0142 0143 if (!officeStyle.isNull()) { 0144 d->officeStyle = officeStyle; 0145 insertOfficeStyles(officeStyle); 0146 } 0147 0148 //debugOdf <<"Styles read in."; 0149 } 0150 0151 QHash<QString, KoXmlElement*> KoOdfStylesReader::customStyles(const QString& family) const 0152 { 0153 if (family.isNull()) 0154 return QHash<QString, KoXmlElement*>(); 0155 return d->customStyles.value(family); 0156 } 0157 0158 QHash<QString, KoXmlElement*> KoOdfStylesReader::autoStyles(const QString& family, bool stylesDotXml) const 0159 { 0160 if (family.isNull()) 0161 return QHash<QString, KoXmlElement*>(); 0162 return stylesDotXml ? d->stylesAutoStyles.value(family) : d->contentAutoStyles.value(family); 0163 } 0164 0165 KoOdfStylesReader::DataFormatsMap KoOdfStylesReader::dataFormats() const 0166 { 0167 return d->dataFormats; 0168 } 0169 0170 KoOdfNotesConfiguration KoOdfStylesReader::globalNotesConfiguration(KoOdfNotesConfiguration::NoteClass noteClass) const 0171 { 0172 switch (noteClass) { 0173 case (KoOdfNotesConfiguration::Endnote): 0174 return d->globalEndnoteConfiguration; 0175 case (KoOdfNotesConfiguration::Footnote): 0176 default: 0177 return d->globalFootnoteConfiguration; 0178 } 0179 } 0180 0181 KoOdfBibliographyConfiguration KoOdfStylesReader::globalBibliographyConfiguration() const 0182 { 0183 return d->globalBibliographyConfiguration; 0184 } 0185 0186 KoOdfLineNumberingConfiguration KoOdfStylesReader::lineNumberingConfiguration() const 0187 { 0188 return d->lineNumberingConfiguration; 0189 } 0190 0191 0192 void KoOdfStylesReader::insertOfficeStyles(const KoXmlElement& styles) 0193 { 0194 KoXmlElement e; 0195 forEachElement(e, styles) { 0196 const QString localName = e.localName(); 0197 const QString ns = e.namespaceURI(); 0198 if ((ns == KoXmlNS::svg && ( 0199 localName == "linearGradient" 0200 || localName == "radialGradient")) 0201 || (ns == KoXmlNS::draw && ( 0202 localName == "gradient" 0203 || localName == "hatch" 0204 || localName == "fill-image" 0205 || localName == "marker" 0206 || localName == "stroke-dash" 0207 || localName == "opacity")) 0208 || (ns == KoXmlNS::calligra && ( 0209 localName == "conicalGradient")) 0210 ) { 0211 QString drawType = localName; 0212 if (drawType.endsWith(QLatin1String("Gradient"))) { 0213 drawType = "gradient"; 0214 } 0215 const QString name = e.attributeNS(KoXmlNS::draw, "name", QString()); 0216 Q_ASSERT(!name.isEmpty()); 0217 KoXmlElement* ep = new KoXmlElement(e); 0218 d->drawStyles[drawType].insert(name, ep); 0219 }else if(ns == KoXmlNS::table && localName == "table-template") { 0220 d->tableTemplates.append(new KoXmlElement(e)); 0221 } else { 0222 insertStyle(e, CustomInStyles); 0223 } 0224 } 0225 } 0226 0227 void KoOdfStylesReader::insertStyles(const KoXmlElement& styles, TypeAndLocation typeAndLocation) 0228 { 0229 //debugOdf <<"Inserting styles from" << styles.tagName(); 0230 KoXmlElement e; 0231 forEachElement(e, styles) 0232 insertStyle(e, typeAndLocation); 0233 } 0234 0235 void KoOdfStylesReader::insertStyle(const KoXmlElement& e, TypeAndLocation typeAndLocation) 0236 { 0237 const QString localName = e.localName(); 0238 const QString ns = e.namespaceURI(); 0239 const QString name = e.attributeNS(KoXmlNS::style, "name", QString()); 0240 0241 if ((ns == KoXmlNS::style && localName == "style") 0242 || (ns == KoXmlNS::text && localName == "list-style")) { 0243 const QString family = localName == "list-style" ? "list" : e.attributeNS(KoXmlNS::style, "family", QString()); 0244 0245 if (typeAndLocation == AutomaticInContent) { 0246 QHash<QString, KoXmlElement*>& dict = d->contentAutoStyles[ family ]; 0247 if (dict.contains(name)) { 0248 debugOdf << "Auto-style: '" << name << "' already exists"; 0249 delete dict.take(name); 0250 } 0251 dict.insert(name, new KoXmlElement(e)); 0252 //debugOdf <<"Style: '" << name <<"' loaded as a style auto style"; 0253 } else if (typeAndLocation == AutomaticInStyles) { 0254 QHash<QString, KoXmlElement*>& dict = d->stylesAutoStyles[ family ]; 0255 if (dict.contains(name)) { 0256 debugOdf << "Auto-style: '" << name << "' already exists"; 0257 delete dict.take(name); 0258 } 0259 dict.insert(name, new KoXmlElement(e)); 0260 //debugOdf <<"Style: '" << name <<"' loaded as a style auto style"; 0261 } else { 0262 QHash<QString, KoXmlElement*>& dict = d->customStyles[ family ]; 0263 if (dict.contains(name)) { 0264 debugOdf << "Style: '" << name << "' already exists"; 0265 delete dict.take(name); 0266 } 0267 dict.insert(name, new KoXmlElement(e)); 0268 //debugOdf <<"Style: '" << name <<"' loaded"; 0269 } 0270 } else if (ns == KoXmlNS::style && ( 0271 localName == "page-layout" 0272 || localName == "font-face")) { 0273 if (d->styles.contains(name)) { 0274 debugOdf << "Style: '" << name << "' already exists"; 0275 delete d->styles.take(name); 0276 } 0277 d->styles.insert(name, new KoXmlElement(e)); 0278 } else if (localName == "presentation-page-layout" && ns == KoXmlNS::style) { 0279 if (d->presentationPageLayouts.contains(name)) { 0280 debugOdf << "Presentation page layout: '" << name << "' already exists"; 0281 delete d->presentationPageLayouts.take(name); 0282 } 0283 d->presentationPageLayouts.insert(name, new KoXmlElement(e)); 0284 } else if (localName == "default-style" && ns == KoXmlNS::style) { 0285 const QString family = e.attributeNS(KoXmlNS::style, "family", QString()); 0286 if (!family.isEmpty()) 0287 d->defaultStyles.insert(family, new KoXmlElement(e)); 0288 } else if (ns == KoXmlNS::number && ( 0289 localName == "number-style" 0290 || localName == "currency-style" 0291 || localName == "percentage-style" 0292 || localName == "boolean-style" 0293 || localName == "text-style" 0294 || localName == "date-style" 0295 || localName == "time-style")) { 0296 QPair<QString, KoOdfNumberStyles::NumericStyleFormat> numberStyle = KoOdfNumberStyles::loadOdfNumberStyle(e); 0297 d->dataFormats.insert(numberStyle.first, qMakePair(numberStyle.second, new KoXmlElement(e))); 0298 } else if (ns == KoXmlNS::text && localName == "notes-configuration") { 0299 if (e.attributeNS(KoXmlNS::text, "note-class", "footnote") == "footnote") { 0300 d->globalFootnoteConfiguration.loadOdf(e); 0301 } else { 0302 d->globalEndnoteConfiguration.loadOdf(e); 0303 } 0304 } else if (ns == KoXmlNS::text && localName == "linenumbering-configuration") { 0305 d->lineNumberingConfiguration.loadOdf(e); 0306 } else if (ns == KoXmlNS::text && localName == "bibliography-configuration") { 0307 KoOdfBibliographyConfiguration bibConfiguration; 0308 bibConfiguration.loadOdf(e); 0309 d->globalBibliographyConfiguration = bibConfiguration; 0310 } 0311 } 0312 0313 KoXmlElement *KoOdfStylesReader::defaultStyle(const QString &family) const 0314 { 0315 return d->defaultStyles[family]; 0316 } 0317 0318 KoXmlElement KoOdfStylesReader::officeStyle() const 0319 { 0320 return d->officeStyle; 0321 } 0322 0323 KoXmlElement KoOdfStylesReader::layerSet() const 0324 { 0325 return d->layerSet; 0326 } 0327 0328 QHash<QString, KoXmlElement*> KoOdfStylesReader::masterPages() const 0329 { 0330 return d->masterPages; 0331 } 0332 0333 QHash<QString, KoXmlElement*> KoOdfStylesReader::presentationPageLayouts() const 0334 { 0335 return d->presentationPageLayouts; 0336 } 0337 0338 QHash<QString, KoXmlElement*> KoOdfStylesReader::drawStyles(const QString &drawType) const 0339 { 0340 return d->drawStyles.value(drawType); 0341 } 0342 0343 const KoXmlElement* KoOdfStylesReader::findStyle(const QString& name) const 0344 { 0345 return d->styles[ name ]; 0346 } 0347 0348 const KoXmlElement* KoOdfStylesReader::findStyle(const QString& styleName, const QString& family) const 0349 { 0350 const KoXmlElement* style = findStyleCustomStyle(styleName, family); 0351 if (!style) 0352 style = findAutoStyleStyle(styleName, family); 0353 if (!style) 0354 style = findContentAutoStyle(styleName, family); 0355 return style; 0356 } 0357 0358 const KoXmlElement* KoOdfStylesReader::findStyle(const QString& styleName, const QString& family, bool stylesDotXml) const 0359 { 0360 const KoXmlElement* style = findStyleCustomStyle(styleName, family); 0361 if (!style && !stylesDotXml) { 0362 style = findContentAutoStyle(styleName, family); 0363 } 0364 if (!style && stylesDotXml) { 0365 style = findAutoStyleStyle(styleName, family); 0366 } 0367 return style; 0368 0369 } 0370 0371 const KoXmlElement* KoOdfStylesReader::findStyleCustomStyle(const QString& styleName, const QString& family) const 0372 { 0373 const KoXmlElement* style = d->customStyles.value(family).value(styleName); 0374 if (style && !family.isEmpty()) { 0375 const QString styleFamily = style->attributeNS(KoXmlNS::style, "family", QString()); 0376 if (styleFamily != family) { 0377 warnOdf << "KoOdfStylesReader: was looking for style " << styleName 0378 << " in family " << family << " but got " << styleFamily << endl; 0379 } 0380 } 0381 return style; 0382 } 0383 0384 const KoXmlElement* KoOdfStylesReader::findAutoStyleStyle(const QString& styleName, const QString& family) const 0385 { 0386 const KoXmlElement* style = d->stylesAutoStyles.value(family).value(styleName); 0387 if (style) { 0388 const QString styleFamily = style->attributeNS(KoXmlNS::style, "family", QString()); 0389 if (styleFamily != family) { 0390 warnOdf << "KoOdfStylesReader: was looking for style " << styleName 0391 << " in family " << family << " but got " << styleFamily << endl; 0392 } 0393 } 0394 return style; 0395 } 0396 0397 const KoXmlElement* KoOdfStylesReader::findContentAutoStyle(const QString& styleName, const QString& family) const 0398 { 0399 const KoXmlElement* style = d->contentAutoStyles.value(family).value(styleName); 0400 if (style) { 0401 const QString styleFamily = style->attributeNS(KoXmlNS::style, "family", QString()); 0402 if (styleFamily != family) { 0403 warnOdf << "KoOdfStylesReader: was looking for style " << styleName 0404 << " in family " << family << " but got " << styleFamily << endl; 0405 } 0406 } 0407 return style; 0408 } 0409 0410 QList<KoXmlElement*> KoOdfStylesReader::tableTemplates() const 0411 { 0412 return d->tableTemplates; 0413 }