Warning, file /office/calligra/libs/odf/KoGenStyles.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-2008 Thorsten Zachmann <zachmann@kde.org>
0004    Copyright (C) 2009 Thomas Zander <zander@kde.org>
0005    Copyright (C) 2008 Girish Ramakrishnan <girish@forwardbias.in>
0006    Copyright (C) 2009 Inge Wallin <inge@lysator.liu.se>
0007    Copyright (C) 2010 KO GmbH <jos.van.den.oever@kogmbh.com>
0008    Copyright (C) 2010 Jarosław Staniek <staniek@kde.org>
0009 
0010    This library is free software; you can redistribute it and/or
0011    modify it under the terms of the GNU Library General Public
0012    License version 2 as published by the Free Software Foundation.
0013 
0014    This library is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    Library General Public License for more details.
0018 
0019    You should have received a copy of the GNU Library General Public License
0020    along with this library; see the file COPYING.LIB.  If not, write to
0021    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022  * Boston, MA 02110-1301, USA.
0023 */
0024 
0025 #include "KoGenStyles.h"
0026 
0027 #include <KoStore.h>
0028 #include <KoStoreDevice.h>
0029 #include <KoXmlWriter.h>
0030 #include "KoOdfWriteStore.h"
0031 #include "KoFontFace.h"
0032 #include <float.h>
0033 #include <OdfDebug.h>
0034 
0035 static const struct {
0036     KoGenStyle::Type m_type;
0037     const char * m_elementName;
0038     const char * m_propertiesElementName;
0039     bool m_drawElement;
0040 } styleData[] = {
0041     { KoGenStyle::TextStyle,            "style:style", "style:text-properties",         false  },
0042     { KoGenStyle::ParagraphStyle,       "style:style", "style:paragraph-properties",    false  },
0043     { KoGenStyle::SectionStyle,         "style:style", "style:section-properties",      false  },
0044     { KoGenStyle::RubyStyle,            "style:style", "style:ruby-properties",         false  },
0045     { KoGenStyle::TableStyle,           "style:style", "style:table-properties",        false  },
0046     { KoGenStyle::TableColumnStyle,     "style:style", "style:table-column-properties", false  },
0047     { KoGenStyle::TableRowStyle,        "style:style", "style:table-row-properties",    false  },
0048     { KoGenStyle::TableCellStyle,       "style:style", "style:table-cell-properties",   false  },
0049     { KoGenStyle::GraphicStyle,         "style:style", "style:graphic-properties",      false  },
0050     { KoGenStyle::PresentationStyle,    "style:style", "style:graphic-properties",      false  },
0051     { KoGenStyle::DrawingPageStyle,     "style:style", "style:drawing-page-properties", false  },
0052     { KoGenStyle::ChartStyle,           "style:style", "style:chart-properties",        false  },
0053     { KoGenStyle::ListStyle,            "text:list-style", 0, false  },
0054     { KoGenStyle::LinearGradientStyle,  "svg:linearGradient", 0, true  },
0055     { KoGenStyle::RadialGradientStyle,  "svg:radialGradient", 0, true  },
0056     { KoGenStyle::ConicalGradientStyle, "calligra:conicalGradient", 0, true  },
0057     { KoGenStyle::StrokeDashStyle,      "draw:stroke-dash", 0, true  },
0058     { KoGenStyle::FillImageStyle,       "draw:fill-image", 0, true  },
0059     { KoGenStyle::HatchStyle,           "draw:hatch", "style:graphic-properties", true  },
0060     { KoGenStyle::GradientStyle,        "draw:gradient", "style:graphic-properties", true  },
0061     { KoGenStyle::MarkerStyle,          "draw:marker", "style:graphic-properties", true  },
0062     { KoGenStyle::PresentationPageLayoutStyle, "style:presentation-page-layout", 0, false  },
0063     { KoGenStyle::OutlineLevelStyle,    "text:outline-style", 0, false }
0064 };
0065 
0066 static const unsigned int numStyleData = sizeof(styleData) / sizeof(*styleData);
0067 
0068 static const struct {
0069     KoGenStyle::Type m_type;
0070     const char * m_elementName;
0071     const char * m_propertiesElementName;
0072     bool m_drawElement;
0073 } autoStyleData[] = {
0074     { KoGenStyle::TextAutoStyle,         "style:style", "style:text-properties",         false  },
0075     { KoGenStyle::ParagraphAutoStyle,    "style:style", "style:paragraph-properties",    false  },
0076     { KoGenStyle::SectionAutoStyle,      "style:style", "style:section-properties",      false  },
0077     { KoGenStyle::RubyAutoStyle,         "style:style", "style:ruby-properties",         false  },
0078     { KoGenStyle::TableAutoStyle,        "style:style", "style:table-properties",        false  },
0079     { KoGenStyle::TableColumnAutoStyle,  "style:style", "style:table-column-properties", false  },
0080     { KoGenStyle::TableRowAutoStyle,     "style:style", "style:table-row-properties",    false  },
0081     { KoGenStyle::TableCellAutoStyle,    "style:style", "style:table-cell-properties",   false  },
0082     { KoGenStyle::GraphicAutoStyle,      "style:style", "style:graphic-properties",      false  },
0083     { KoGenStyle::PresentationAutoStyle, "style:style", "style:graphic-properties",      false  },
0084     { KoGenStyle::DrawingPageAutoStyle,  "style:style", "style:drawing-page-properties", false  },
0085     { KoGenStyle::ChartAutoStyle,        "style:style", "style:chart-properties",        false  },
0086     { KoGenStyle::PageLayoutStyle, "style:page-layout", "style:page-layout-properties",  false  },
0087     { KoGenStyle::ListAutoStyle, "text:list-style", 0, false  },
0088     { KoGenStyle::NumericNumberStyle, "number:number-style", 0, false  },
0089     { KoGenStyle::NumericFractionStyle, "number:number-style", 0, false  },
0090     { KoGenStyle::NumericScientificStyle, "number:number-style", 0, false  },
0091     { KoGenStyle::NumericDateStyle, "number:date-style", 0, false  },
0092     { KoGenStyle::NumericTimeStyle, "number:time-style", 0, false  },
0093     { KoGenStyle::NumericPercentageStyle, "number:percentage-style", 0, false  },
0094     { KoGenStyle::NumericCurrencyStyle, "number:currency-style", 0, false  },
0095     { KoGenStyle::NumericBooleanStyle, "number:boolean-style", 0, false  },
0096     { KoGenStyle::NumericTextStyle, "number:text-style", 0, false  }
0097 };
0098 
0099 static const unsigned int numAutoStyleData = sizeof(autoStyleData) / sizeof(*autoStyleData);
0100 
0101 static void insertRawOdfStyles(const QByteArray& xml, QByteArray& styles)
0102 {
0103     if (xml.isEmpty())
0104         return;
0105     if (!styles.isEmpty() && !styles.endsWith('\n') && !xml.startsWith('\n')) {
0106         styles.append('\n');
0107     }
0108     styles.append(xml);
0109 }
0110 
0111 class Q_DECL_HIDDEN KoGenStyles::Private
0112 {
0113 public:
0114     Private(KoGenStyles *q) : q(q)
0115     {
0116     }
0117 
0118     ~Private()
0119     {
0120     }
0121 
0122     QVector<KoGenStyles::NamedStyle> styles(bool autoStylesInStylesDotXml, KoGenStyle::Type type) const;
0123     void saveOdfAutomaticStyles(KoXmlWriter* xmlWriter, bool autoStylesInStylesDotXml,
0124                                 const QByteArray& rawOdfAutomaticStyles) const;
0125     void saveOdfDocumentStyles(KoXmlWriter* xmlWriter) const;
0126     void saveOdfMasterStyles(KoXmlWriter* xmlWriter) const;
0127     QString makeUniqueName(const QString& base, const QByteArray &family, InsertionFlags flags) const;
0128 
0129     /**
0130      * Save font face declarations
0131      *
0132      * This creates the office:font-face-decls tag containing all font face
0133      * declarations
0134      */
0135     void saveOdfFontFaceDecls(KoXmlWriter* xmlWriter) const;
0136 
0137     /// style definition -> name
0138     StyleMap styleMap;
0139 
0140     /// Map with the style name as key.
0141     /// This map is mainly used to check for name uniqueness
0142     QMap<QByteArray, QSet<QString> > styleNames;
0143     QMap<QByteArray, QSet<QString> > autoStylesInStylesDotXml;
0144 
0145     /// List of styles (used to preserve ordering)
0146     QVector<KoGenStyles::NamedStyle> styleList;
0147 
0148     /// map for saving default styles
0149     QMap<int, KoGenStyle> defaultStyles;
0150 
0151     /// font faces
0152     QMap<QString, KoFontFace> fontFaces;
0153 
0154     StyleMap::iterator insertStyle(const KoGenStyle &style, const QString &name, InsertionFlags flags);
0155 
0156     struct RelationTarget {
0157         QString target; // the style we point to
0158         QString attribute; // the attribute name used for the relation
0159     };
0160     QHash<QString, RelationTarget> relations; // key is the name of the source style
0161 
0162     QByteArray rawOdfDocumentStyles;
0163     QByteArray rawOdfAutomaticStyles_stylesDotXml;
0164     QByteArray rawOdfAutomaticStyles_contentDotXml;
0165     QByteArray rawOdfMasterStyles;
0166     QByteArray rawOdfFontFaceDecls;
0167 
0168     KoGenStyles *q;
0169 };
0170 
0171 QVector<KoGenStyles::NamedStyle> KoGenStyles::Private::styles(bool autoStylesInStylesDotXml, KoGenStyle::Type type) const
0172 {
0173     QVector<KoGenStyles::NamedStyle> lst;
0174     QVector<KoGenStyles::NamedStyle>::const_iterator it = styleList.constBegin();
0175     const QVector<KoGenStyles::NamedStyle>::const_iterator end = styleList.constEnd();
0176     for (; it != end ; ++it) {
0177         if ((*it).style->type() == type && (*it).style->autoStyleInStylesDotXml() == autoStylesInStylesDotXml) {
0178             lst.append(*it);
0179         }
0180     }
0181     return lst;
0182 }
0183 
0184 void KoGenStyles::Private::saveOdfAutomaticStyles(KoXmlWriter* xmlWriter, bool autoStylesInStylesDotXml,
0185                                                   const QByteArray& rawOdfAutomaticStyles) const
0186 {
0187     xmlWriter->startElement("office:automatic-styles");
0188 
0189     for (uint i = 0; i < numAutoStyleData; ++i) {
0190         QVector<KoGenStyles::NamedStyle> stylesList = styles(autoStylesInStylesDotXml, autoStyleData[i].m_type);
0191         QVector<KoGenStyles::NamedStyle>::const_iterator it = stylesList.constBegin();
0192         for (; it != stylesList.constEnd() ; ++it) {
0193             (*it).style->writeStyle(xmlWriter, *q, autoStyleData[i].m_elementName, (*it).name,
0194                                     autoStyleData[i].m_propertiesElementName, true, autoStyleData[i].m_drawElement);
0195         }
0196     }
0197 
0198     if (!rawOdfAutomaticStyles.isEmpty()) {
0199         xmlWriter->addCompleteElement(rawOdfAutomaticStyles.constData());
0200     }
0201 
0202     xmlWriter->endElement(); // office:automatic-styles
0203 }
0204 
0205 void KoGenStyles::Private::saveOdfDocumentStyles(KoXmlWriter* xmlWriter) const
0206 {
0207     xmlWriter->startElement("office:styles");
0208 
0209     for (uint i = 0; i < numStyleData; ++i) {
0210         const QMap<int, KoGenStyle>::const_iterator it(defaultStyles.constFind(styleData[i].m_type));
0211         if (it != defaultStyles.constEnd()) {
0212             it.value().writeStyle(xmlWriter, *q, "style:default-style", "",
0213                                   styleData[i].m_propertiesElementName, true, styleData[i].m_drawElement);
0214         }
0215     }
0216 
0217     for (uint i = 0; i < numStyleData; ++i) {
0218         QVector<KoGenStyles::NamedStyle> stylesList(styles(false, styleData[i].m_type));
0219         QVector<KoGenStyles::NamedStyle>::const_iterator it = stylesList.constBegin();
0220         for (; it != stylesList.constEnd() ; ++it) {
0221             if (relations.contains(it->name)) {
0222                 KoGenStyles::Private::RelationTarget relation = relations.value(it->name);
0223                 KoGenStyle styleCopy = *(*it).style;
0224                 styleCopy.addAttribute(relation.attribute, relation.target);
0225                 styleCopy.writeStyle(xmlWriter, *q, styleData[i].m_elementName, (*it).name,
0226                                     styleData[i].m_propertiesElementName, true, styleData[i].m_drawElement);
0227             } else {
0228                 (*it).style->writeStyle(xmlWriter, *q, styleData[i].m_elementName, (*it).name,
0229                                     styleData[i].m_propertiesElementName, true, styleData[i].m_drawElement);
0230             }
0231         }
0232     }
0233 
0234     if (!rawOdfDocumentStyles.isEmpty()) {
0235         xmlWriter->addCompleteElement(rawOdfDocumentStyles.constData());
0236     }
0237 
0238     xmlWriter->endElement(); // office:styles
0239 }
0240 
0241 void KoGenStyles::Private::saveOdfMasterStyles(KoXmlWriter* xmlWriter) const
0242 {
0243     xmlWriter->startElement("office:master-styles");
0244 
0245     QVector<KoGenStyles::NamedStyle> stylesList = styles(false, KoGenStyle::MasterPageStyle);
0246     QVector<KoGenStyles::NamedStyle>::const_iterator it = stylesList.constBegin();
0247     for (; it != stylesList.constEnd() ; ++it) {
0248         (*it).style->writeStyle(xmlWriter, *q, "style:master-page", (*it).name, 0);
0249     }
0250 
0251     if (!rawOdfMasterStyles.isEmpty()) {
0252         xmlWriter->addCompleteElement(rawOdfMasterStyles.constData());
0253     }
0254 
0255     xmlWriter->endElement(); // office:master-styles
0256 }
0257 
0258 void KoGenStyles::Private::saveOdfFontFaceDecls(KoXmlWriter* xmlWriter) const
0259 {
0260     if (fontFaces.isEmpty())
0261         return;
0262 
0263     xmlWriter->startElement("office:font-face-decls");
0264     for (QMap<QString, KoFontFace>::ConstIterator it(fontFaces.constBegin());
0265          it != fontFaces.constEnd(); ++it)
0266     {
0267         it.value().saveOdf(xmlWriter);
0268     }
0269 
0270     if (!rawOdfFontFaceDecls.isEmpty()) {
0271         xmlWriter->addCompleteElement(rawOdfFontFaceDecls.constData());
0272     }
0273 
0274     xmlWriter->endElement(); // office:font-face-decls
0275 }
0276 
0277 QString KoGenStyles::Private::makeUniqueName(const QString& base, const QByteArray &family, InsertionFlags flags) const
0278 {
0279     // If this name is not used yet, and numbering isn't forced, then the given name is ok.
0280     if ((flags & DontAddNumberToName)
0281             && !autoStylesInStylesDotXml[family].contains(base)
0282             && !styleNames[family].contains(base))
0283         return base;
0284     int num = 1;
0285     QString name;
0286     do {
0287         name = base + QString::number(num++);
0288     } while (autoStylesInStylesDotXml[family].contains(name)
0289              || styleNames[family].contains(name));
0290     return name;
0291 }
0292 
0293 //------------------------
0294 
0295 KoGenStyles::KoGenStyles()
0296         : d(new Private(this))
0297 {
0298 }
0299 
0300 KoGenStyles::~KoGenStyles()
0301 {
0302     delete d;
0303 }
0304 
0305 QString KoGenStyles::insert(const KoGenStyle& style, const QString& baseName, InsertionFlags flags)
0306 {
0307     // if it is a default style it has to be saved differently
0308     if (style.isDefaultStyle()) {
0309         // we can have only one default style per type
0310         Q_ASSERT(!d->defaultStyles.contains(style.type()));
0311         // default style is only possible for style:style in office:style types
0312         Q_ASSERT(style.type() == KoGenStyle::TextStyle ||
0313                  style.type() == KoGenStyle::ParagraphStyle ||
0314                  style.type() == KoGenStyle::SectionStyle ||
0315                  style.type() == KoGenStyle::RubyStyle ||
0316                  style.type() == KoGenStyle::TableStyle ||
0317                  style.type() == KoGenStyle::TableColumnStyle ||
0318                  style.type() == KoGenStyle::TableRowStyle ||
0319                  style.type() == KoGenStyle::TableCellStyle ||
0320                  style.type() == KoGenStyle::GraphicStyle ||
0321                  style.type() == KoGenStyle::PresentationStyle ||
0322                  style.type() == KoGenStyle::DrawingPageStyle ||
0323                  style.type() == KoGenStyle::ChartStyle);
0324 
0325         d->defaultStyles.insert(style.type(), style);
0326         // default styles don't have a name
0327         return QString();
0328     }
0329 
0330     if (flags & AllowDuplicates) {
0331         StyleMap::iterator it = d->insertStyle(style, baseName, flags);
0332         return it.value();
0333     }
0334 
0335     StyleMap::iterator it = d->styleMap.find(style);
0336     if (it == d->styleMap.end()) {
0337         // Not found, try if this style is in fact equal to its parent (the find above
0338         // wouldn't have found it, due to m_parentName being set).
0339         if (!style.parentName().isEmpty()) {
0340             KoGenStyle testStyle(style);
0341             const KoGenStyle* parentStyle = this->style(style.parentName(), style.familyName());   // ## linear search
0342             if (!parentStyle) {
0343                 debugOdf << "baseName=" << baseName << "parent style" << style.parentName()
0344                               << "not found in collection";
0345             } else {
0346                 // TODO remove
0347                 if (testStyle.m_familyName != parentStyle->m_familyName) {
0348                     warnOdf << "baseName=" << baseName << "family=" << testStyle.m_familyName
0349                                     << "parent style" << style.parentName() << "has a different family:"
0350                                     << parentStyle->m_familyName;
0351                 }
0352 
0353                 testStyle.m_parentName = parentStyle->m_parentName;
0354                 // Exclude the type from the comparison. It's ok for an auto style
0355                 // to have a user style as parent; they can still be identical
0356                 testStyle.m_type = parentStyle->m_type;
0357                 // Also it's ok to not have the display name of the parent style
0358                 // in the auto style
0359                 QMap<QString, QString>::const_iterator it = parentStyle->m_attributes.find("style:display-name");
0360                 if (it != parentStyle->m_attributes.end())
0361                     testStyle.addAttribute("style:display-name", *it);
0362 
0363                 if (*parentStyle == testStyle)
0364                     return style.parentName();
0365             }
0366         }
0367 
0368         it = d->insertStyle(style, baseName, flags);
0369     }
0370     return it.value();
0371 }
0372 
0373 KoGenStyles::StyleMap::iterator KoGenStyles::Private::insertStyle(const KoGenStyle &style,
0374                                                                   const QString& baseName, InsertionFlags flags)
0375 {
0376     QString styleName(baseName);
0377     if (styleName.isEmpty()) {
0378         switch (style.type()) {
0379         case KoGenStyle::ParagraphAutoStyle: styleName = 'P'; break;
0380         case KoGenStyle::ListAutoStyle: styleName = 'L'; break;
0381         case KoGenStyle::TextAutoStyle: styleName = 'T'; break;
0382         default:
0383             styleName = 'A'; // for "auto".
0384         }
0385         flags &= ~DontAddNumberToName; // i.e. force numbering
0386     }
0387     styleName = makeUniqueName(styleName, style.m_familyName, flags);
0388     if (style.autoStyleInStylesDotXml())
0389         autoStylesInStylesDotXml[style.m_familyName].insert(styleName);
0390     else
0391         styleNames[style.m_familyName].insert(styleName);
0392     KoGenStyles::StyleMap::iterator it = styleMap.insert(style, styleName);
0393     NamedStyle s;
0394     s.style = &it.key();
0395     s.name = styleName;
0396     styleList.append(s);
0397     return it;
0398 }
0399 
0400 KoGenStyles::StyleMap KoGenStyles::styles() const
0401 {
0402     return d->styleMap;
0403 }
0404 
0405 QVector<KoGenStyles::NamedStyle> KoGenStyles::styles(KoGenStyle::Type type) const
0406 {
0407     return d->styles(false, type);
0408 }
0409 
0410 const KoGenStyle* KoGenStyles::style(const QString &name, const QByteArray &family) const
0411 {
0412     QVector<KoGenStyles::NamedStyle>::const_iterator it = d->styleList.constBegin();
0413     const QVector<KoGenStyles::NamedStyle>::const_iterator end = d->styleList.constEnd();
0414     for (; it != end ; ++it) {
0415         if ((*it).name == name && (*it).style->familyName() == family) {
0416             return (*it).style;
0417         }
0418     }
0419     return 0;
0420 }
0421 
0422 KoGenStyle* KoGenStyles::styleForModification(const QString &name, const QByteArray &family)
0423 {
0424     return const_cast<KoGenStyle *>(style(name, family));
0425 }
0426 
0427 void KoGenStyles::markStyleForStylesXml(const QString &name, const QByteArray &family)
0428 {
0429     Q_ASSERT(d->styleNames[family].contains(name));
0430     d->styleNames[family].remove(name);
0431     d->autoStylesInStylesDotXml[family].insert(name);
0432     styleForModification(name, family)->setAutoStyleInStylesDotXml(true);
0433 }
0434 
0435 void KoGenStyles::insertFontFace(const KoFontFace &face)
0436 {
0437     Q_ASSERT(!face.isNull());
0438     if (face.isNull()) {
0439         warnOdf << "This font face is null and will not be added to styles: set at least the name";
0440         return;
0441     }
0442     d->fontFaces.insert(face.name(), face); // replaces prev item
0443 }
0444 
0445 KoFontFace KoGenStyles::fontFace(const QString& name) const
0446 {
0447     return d->fontFaces.value(name);
0448 }
0449 
0450 bool KoGenStyles::saveOdfStylesDotXml(KoStore* store, KoXmlWriter* manifestWriter) const
0451 {
0452     if (!store->open("styles.xml"))
0453         return false;
0454 
0455     manifestWriter->addManifestEntry("styles.xml",  "text/xml");
0456 
0457     KoStoreDevice stylesDev(store);
0458     KoXmlWriter* stylesWriter = KoOdfWriteStore::createOasisXmlWriter(&stylesDev, "office:document-styles");
0459 
0460     d->saveOdfFontFaceDecls(stylesWriter);
0461     d->saveOdfDocumentStyles(stylesWriter);
0462     d->saveOdfAutomaticStyles(stylesWriter, true, d->rawOdfAutomaticStyles_stylesDotXml);
0463     d->saveOdfMasterStyles(stylesWriter);
0464 
0465     stylesWriter->endElement(); // root element (office:document-styles)
0466     stylesWriter->endDocument();
0467     delete stylesWriter;
0468 
0469     if (!store->close())   // done with styles.xml
0470         return false;
0471 
0472     return true;
0473 }
0474 
0475 void KoGenStyles::saveOdfStyles(StylesPlacement placement, KoXmlWriter* xmlWriter) const
0476 {
0477     switch (placement) {
0478     case DocumentStyles:
0479         d->saveOdfDocumentStyles(xmlWriter);
0480         break;
0481     case MasterStyles:
0482         d->saveOdfMasterStyles(xmlWriter);
0483         break;
0484     case DocumentAutomaticStyles:
0485         d->saveOdfAutomaticStyles(xmlWriter, false, d->rawOdfAutomaticStyles_contentDotXml);
0486         break;
0487     case StylesXmlAutomaticStyles:
0488         d->saveOdfAutomaticStyles(xmlWriter, true, d->rawOdfAutomaticStyles_stylesDotXml);
0489         break;
0490     case FontFaceDecls:
0491         d->saveOdfFontFaceDecls(xmlWriter);
0492         break;
0493     }
0494 }
0495 
0496 void KoGenStyles::insertRawOdfStyles(StylesPlacement placement, const QByteArray& xml)
0497 {
0498     switch (placement) {
0499     case DocumentStyles:
0500         ::insertRawOdfStyles(xml, d->rawOdfDocumentStyles);
0501         break;
0502     case MasterStyles:
0503         ::insertRawOdfStyles(xml, d->rawOdfMasterStyles);
0504         break;
0505     case DocumentAutomaticStyles:
0506         ::insertRawOdfStyles(xml, d->rawOdfAutomaticStyles_contentDotXml);
0507         break;
0508     case StylesXmlAutomaticStyles:
0509         ::insertRawOdfStyles(xml, d->rawOdfAutomaticStyles_stylesDotXml);
0510         break;
0511     case FontFaceDecls:
0512         ::insertRawOdfStyles(xml, d->rawOdfFontFaceDecls);
0513         break;
0514     }
0515 }
0516 
0517 void KoGenStyles::insertStyleRelation(const QString &source, const QString &target, const char *tagName)
0518 {
0519     KoGenStyles::Private::RelationTarget relation;
0520     relation.target = target;
0521     relation.attribute = QString(tagName);
0522     d->relations.insert(source, relation);
0523 }
0524 
0525 QDebug operator<<(QDebug dbg, const KoGenStyles& styles)
0526 {
0527     dbg.nospace() << "KoGenStyles:";
0528     QVector<KoGenStyles::NamedStyle>::const_iterator it = styles.d->styleList.constBegin();
0529     const QVector<KoGenStyles::NamedStyle>::const_iterator end = styles.d->styleList.constEnd();
0530     for (; it != end ; ++it) {
0531         dbg.nospace() << (*it).name;
0532     }
0533     for (QMap<QByteArray, QSet<QString> >::const_iterator familyIt(styles.d->styleNames.constBegin()); familyIt != styles.d->styleNames.constEnd(); ++familyIt) {
0534         for (QSet<QString>::const_iterator it(familyIt.value().constBegin()); it != familyIt.value().constEnd(); ++it) {
0535             dbg.space() << "style:" << *it;
0536         }
0537     }
0538 #ifndef NDEBUG
0539     for (QMap<QByteArray, QSet<QString> >::const_iterator familyIt(styles.d->autoStylesInStylesDotXml.constBegin()); familyIt != styles.d->autoStylesInStylesDotXml.constEnd(); ++familyIt) {
0540         for (QSet<QString>::const_iterator it(familyIt.value().constBegin()); it != familyIt.value().constEnd(); ++it) {
0541             dbg.space() << "auto style for style.xml:" << *it;
0542         }
0543     }
0544 #endif
0545     return dbg.space();
0546 }