KoGenStyle.h 25.9 KB
Newer Older
Casper Boemann's avatar
Casper Boemann committed
1 2
/* This file is part of the KDE project
   Copyright (C) 2004-2006 David Faure <faure@kde.org>
3
   Copyright (C) 2007-2008 Thorsten Zachmann <zachmann@kde.org>
Inge Wallin's avatar
Inge Wallin committed
4
   Copyright (C) 2009 Inge Wallin <inge@lysator.liu.se>
5
   Copyright (C) 2010 KO GmbH <jos.van.den.oever@kogmbh.com>
Jarosław Staniek's avatar
Jarosław Staniek committed
6
   Copyright (C) 2010 Jarosław Staniek <staniek@kde.org>
7
   Copyright (C) 2011 Pierre Ducroquet <pinaraf@pinaraf.info>
Casper Boemann's avatar
Casper Boemann committed
8 9 10

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
11 12
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
Casper Boemann's avatar
Casper Boemann committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef KOGENSTYLE_H
#define KOGENSTYLE_H

28 29 30
#include <QList>
#include <QMap>
#include <QString>
31
#include "kritaodf_export.h"
Casper Boemann's avatar
Casper Boemann committed
32

33
class QTextLength;
Casper Boemann's avatar
Casper Boemann committed
34 35 36 37 38 39
class KoGenStyles;
class KoXmlWriter;

/**
 * A generic style, i.e. basically a collection of properties and a name.
 * Instances of KoGenStyle can either be held in the KoGenStyles collection,
Jarosław Staniek's avatar
Jarosław Staniek committed
40
 * or created (e.g. on the stack) and given to KoGenStyles::insert().
Casper Boemann's avatar
Casper Boemann committed
41 42 43
 *
 * @author David Faure <faure@kde.org>
 */
44
class KRITAODF_EXPORT KoGenStyle
Casper Boemann's avatar
Casper Boemann committed
45 46 47 48
{
public:
    /**
     * Possible values for the "type" argument of the KoGenStyle constructor.
49 50
     * @note If there is still something missing, add it here so that it is possible to use the same
     *       saving code in all applications.
Casper Boemann's avatar
Casper Boemann committed
51
     */
52
    enum Type {
Jarosław Staniek's avatar
Jarosław Staniek committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        PageLayoutStyle,             ///< style:page-layout as in odf 14.3 Page Layout
        TextStyle,                   ///< style:style from family "text" as in odf 14.8.1 Text Styles
                                     ///<  (office:styles)
        TextAutoStyle,               ///< style:style from family "text" as in odf 14.8.1 Text Styles
                                     ///<  (office:automatic-styles)
        ParagraphStyle,              ///< style:style from family "paragraph" as in odf 14.1 Style Element
                                     ///<  (office:styles)
        ParagraphAutoStyle,          ///< style:style from family "paragraph" as in odf 14.1 Style Element
                                     ///<  (office:automatic-styles)
        SectionStyle,                ///< style:style from family "section" as in odf 14.8.3 Section Styles
                                     ///<  (office:styles)
        SectionAutoStyle,            ///< style:style from family "section" as in odf 14.8.3 Section Styles
                                     ///<  (office:automatic-styles)
        RubyStyle,                   ///< style:style from family "ruby" as in odf 14.8.4 Ruby Style
                                     ///<  (office:styles)
        RubyAutoStyle,               ///< style:style from family "ruby" as in odf 14.8.4 Ruby Style
                                     ///<  (office:automatic-styles)
        TableStyle,                  ///< style:style from family "table" as in odf 14.12 Table Formatting
                                     ///<  Properties (office:styles)
        TableAutoStyle,              ///< style:style from family "table" as in odf 14.12 Table Formatting Properties
                                     ///<  (office:automatic-styles)
        TableColumnStyle,            ///< style:style from family "table-column" as in odf 15.9 Column Formatting
                                     ///<  Properties (office:styles)
        TableColumnAutoStyle,        ///< style:style from family "table-column" as in odf 15.9 Column Formatting
                                     ///<  Properties (office:automatic-styles)
        TableRowStyle,               ///< style:style from family "table-row" as in odf 15.10 Table Row Formatting
                                     ///<  Properties (office:styles)
        TableRowAutoStyle,           ///< style:style from family "table-row" as in odf 15.10 Table Row Formatting
                                     ///<  Properties (office:automatic-styles)
        TableCellStyle,              ///< style:style from family "table-cell" as in odf 15.11 Table Cell Formatting
                                     ///<  Properties (office:styles)
        TableCellAutoStyle,          ///< style:style from family "table-cell" as in odf 15.11 Table Cell Formatting
                                     ///<  Properties (office:automatic-styles)
        GraphicStyle,                ///< style:style from family "graphic" as in 14.13.1 Graphic and Presentation
                                     ///<  Styles (office:automatic-styles)
        GraphicAutoStyle,            ///< style:style from family "graphic" as in 14.13.1 Graphic and Presentation
                                     ///<  Styles (office:automatic-styles)
        PresentationStyle,           ///< style:style from family "presentation" as in 14.13.1 Graphic and
                                     ///<  Presentation Styles (office:styles)
        PresentationAutoStyle,       ///< style:style from family "presentation" as in 14.13.1 Graphic and
                                     ///<  Presentation Styles (office:automatic-styles)
        DrawingPageStyle,            ///< style:style from family "drawing-page" as in odf 14.13.2 Drawing Page Style
                                     ///<  (office:styles)
        DrawingPageAutoStyle,        ///< style:style from family "drawing-page" as in odf 14.13.2 Drawing Page Style
                                     ///<  (office:automatic-styles)
        ChartStyle,                  ///< style:style from family "chart" as in odf 14.16 Chart Styles
                                     ///<  (office:styles)
        ChartAutoStyle,              ///< style:style from family "chart" as in odf 14.16 Chart Styles
                                     ///<  (office:automatic-styles)

        ListStyle,                   ///< text:list-style as in odf 14.10 List Style (office:styles)
        ListAutoStyle,               ///< text:list-style as in odf 14.10 List Style (office:automatic-styles)
        NumericNumberStyle,          ///< number:number-style as in odf 14.7.1 Number Style
        NumericDateStyle,            ///< number:date-style as in odf 14.7.4 Date Style
        NumericTimeStyle,            ///< number:time-style as in odf 14.7.5 Time Style
        NumericFractionStyle,        ///< number:number-style as in odf 14.7.1 Number Style
        NumericPercentageStyle,      ///< number:percentage-style as in odf 14.7.3 Percentage Style
        NumericScientificStyle,      ///< number:number-style as in odf 14.7.1 Number Style
        NumericCurrencyStyle,        ///< number:currency-style as in odf 14.7.2 Currency Style
        NumericTextStyle,            ///< number:text-style 14.7.7 Text Style
                                     ///<  @note unused
        HatchStyle,                  ///< draw:hatch as in odf 14.14.3 Hatch (office:styles)
        StrokeDashStyle,             ///< draw:stroke-dash as in odf 14.14.7 Stroke Dash (office:styles)
        GradientStyle,               ///< draw:gradient as in odf 14.14.1 Gradient (office:styles)
        LinearGradientStyle,         ///< svg:linearGradient as in odf 14.14.2 SVG Gradients (office:styles)
        RadialGradientStyle,         ///< svg:radialGradient as in odf 14.14.2 SVG Gradients (office:styles)
Halla Rempt's avatar
Halla Rempt committed
119
        ConicalGradientStyle,        ///< calligra:conicalGradient calligra extension for conical gradients
Jarosław Staniek's avatar
Jarosław Staniek committed
120 121 122 123 124 125 126
        FillImageStyle,              ///< draw:fill-image as in odf 14.14.4 Fill Image (office:styles)
        NumericBooleanStyle,         ///< number:boolean 14.7.6 Boolean Style
                                     ///<  @note unused
        OpacityStyle,                ///< draw:opacity as in odf 14.14.5 Opacity Gradient
                                     ///<  @note unused
        MarkerStyle,                 ///< draw:marker as in odf 14.14.6 Marker
        PresentationPageLayoutStyle, ///< style:presentation-page-layout as in odf 14.15 Presentation Page Layouts
127
        OutlineLevelStyle,           ///< text:outline-style as in odf 1.2 section 16.34
128
        //   TODO differently
Jarosław Staniek's avatar
Jarosław Staniek committed
129 130 131 132 133
        MasterPageStyle,             ///< style:master-page as in odf 14.4 14.4 Master Pages (office:master-styles)
        // style:default-style as in odf 14.2 Default Styles
        // 14.5 Table Templates
        /// @internal @note always update when adding values to this enum
        LastStyle = MasterPageStyle
134
    };
Casper Boemann's avatar
Casper Boemann committed
135 136

    /**
Jarosław Staniek's avatar
Jarosław Staniek committed
137
     * Start the definition of a new style. Its name will be set later by KoGenStyles::insert(),
Casper Boemann's avatar
Casper Boemann committed
138 139 140
     * but first you must define its properties and attributes.
     *
     * @param type this is a hook for the application to categorize styles
141
     * See the Style* enum. Ignored when writing out the style.
Casper Boemann's avatar
Casper Boemann committed
142 143 144 145 146 147
     *
     * @param familyName The value for style:family, e.g. text, paragraph, graphic etc.
     * The family is for style:style elements only; number styles and list styles don't have one.
     *
     * @param parentName If set, name of the parent style from which this one inherits.
     */
Thomas Zander's avatar
Thomas Zander committed
148 149
    explicit KoGenStyle(Type type = PageLayoutStyle, const char *familyName = 0,
                        const QString &parentName = QString());
Casper Boemann's avatar
Casper Boemann committed
150 151
    ~KoGenStyle();

152
    /**
Casper Boemann's avatar
Casper Boemann committed
153 154 155 156 157 158 159
     * setAutoStyleInStylesDotXml(true) marks a given automatic style as being needed in styles.xml.
     * For instance styles used by headers and footers need to go there, since
     * they are saved in styles.xml, and styles.xml must be independent from content.xml.
     *
     * The application should use KoGenStyles::styles( type, true ) in order to retrieve
     * those styles and save them separately.
     */
160 161 162
    void setAutoStyleInStylesDotXml(bool b) {
        m_autoStyleInStylesDotXml = b;
    }
Casper Boemann's avatar
Casper Boemann committed
163
    /// @return the value passed to setAutoStyleInStylesDotXml; false by default
164 165 166
    bool autoStyleInStylesDotXml() const {
        return m_autoStyleInStylesDotXml;
    }
Casper Boemann's avatar
Casper Boemann committed
167

168
    /**
Casper Boemann's avatar
Casper Boemann committed
169 170
     * setDefaultStyle(true) marks a given style as being the default style.
     * This means we expect that you will call writeStyle( ...,"style:default-style"),
luz paz's avatar
luz paz committed
171
     * and its name will be omitted in the output.
Casper Boemann's avatar
Casper Boemann committed
172
     */
173 174 175
    void setDefaultStyle(bool b) {
        m_defaultStyle = b;
    }
Casper Boemann's avatar
Casper Boemann committed
176
    /// @return the value passed to setDefaultStyle; false by default
177 178 179
    bool isDefaultStyle() const {
        return m_defaultStyle;
    }
Casper Boemann's avatar
Casper Boemann committed
180 181

    /// Return the type of this style, as set in the constructor
182 183 184
    Type type() const {
        return m_type;
    }
Casper Boemann's avatar
Casper Boemann committed
185 186

    /// Return the family name
187 188 189
    const char* familyName() const {
        return m_familyName.data();
    }
Casper Boemann's avatar
Casper Boemann committed
190

191
    /// Sets the name of style's parent.
Thomas Zander's avatar
Thomas Zander committed
192
    void setParentName(const QString &name) {
193 194 195
        m_parentName = name;
    }

Casper Boemann's avatar
Casper Boemann committed
196
    /// Return the name of style's parent, if set
197 198 199
    QString parentName() const {
        return m_parentName;
    }
Casper Boemann's avatar
Casper Boemann committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

    /**
     *  @brief The types of properties
     *
     *  Simple styles only write one foo-properties tag, in which case they can just use DefaultType.
     *  However a given style might want to write several kinds of properties, in which case it would
     *  need to use other property types than the default one.
     *
     *  For instance this style:
     *  @code
     *  <style:style style:family="chart">
     *    <style:chart-properties .../>
     *    <style:graphic-properties .../>
     *    <style:text-properties .../>
     *  </style:style>
     *  @endcode
     *  would use DefaultType for chart-properties (and would pass "style:chart-properties" to writeStyle(),
     *  and would use GraphicType and TextType.
     */
219
    enum PropertyType {
Casper Boemann's avatar
Casper Boemann committed
220 221 222 223 224
        /**
         *  DefaultType depends on family: e.g. paragraph-properties if family=paragraph
         *  or on the type of style (e.g. page-layout -> page-layout-properties).
         *  (In fact that tag name is the one passed to writeStyle)
         */
Jarosław Staniek's avatar
Jarosław Staniek committed
225
        DefaultType,
Casper Boemann's avatar
Casper Boemann committed
226 227 228 229 230 231
        /// TextType is always text-properties.
        TextType,
        /// ParagraphType is always paragraph-properties.
        ParagraphType,
        /// GraphicType is always graphic-properties.
        GraphicType,
232 233 234 235 236 237 238 239 240 241 242 243 244 245
        /// SectionType is always section-properties.
        SectionType,
        /// RubyType is always ruby-properties.
        RubyType,
        /// TableType is always table-properties.
        TableType,
        /// TableColumnType is always table-column-properties
        TableColumnType,
        /// TableRowType is always table-row-properties.
        TableRowType,
        /// TableCellType is always for table-cell-properties.
        TableCellType,
        /// PresentationType is always for presentation-properties.
        PresentationType,
246
        /// DrawingPageType is always for drawing-page-properties.
247
        DrawingPageType,
248
        /// ChartType is always for chart-properties.
249
        ChartType,
Casper Boemann's avatar
Casper Boemann committed
250
        Reserved1, ///< @internal for binary compatible extensions
251 252
        /// For elements that are children of the style itself, not any of the properties
        StyleChildElement,
Jarosław Staniek's avatar
Jarosław Staniek committed
253
        /// @internal @note always update when adding values to this enum
254
        LastPropertyType = StyleChildElement
Casper Boemann's avatar
Casper Boemann committed
255 256
    };

257
    /// Add a property to the style. Passing DefaultType as property type uses a style-type specific property type.
Thomas Zander's avatar
Thomas Zander committed
258
    void addProperty(const QString &propName, const QString &propValue, PropertyType type = DefaultType) {
259 260 261
        if (type == DefaultType) {
            type = m_propertyType;
        }
262
        m_properties[type].insert(propName, propValue);
Casper Boemann's avatar
Casper Boemann committed
263 264
    }
    /// Overloaded version of addProperty that takes a char*, usually for "..."
Thomas Zander's avatar
Thomas Zander committed
265
    void addProperty(const QString &propName, const char *propValue, PropertyType type = DefaultType) {
266 267 268
        if (type == DefaultType) {
            type = m_propertyType;
        }
269
        m_properties[type].insert(propName, QString::fromUtf8(propValue));
Casper Boemann's avatar
Casper Boemann committed
270 271
    }
    /// Overloaded version of addProperty that converts an int to a string
Thomas Zander's avatar
Thomas Zander committed
272
    void addProperty(const QString &propName, int propValue, PropertyType type = DefaultType) {
273 274 275
        if (type == DefaultType) {
            type = m_propertyType;
        }
276
        m_properties[type].insert(propName, QString::number(propValue));
Casper Boemann's avatar
Casper Boemann committed
277 278
    }
    /// Overloaded version of addProperty that converts a bool to a string (false/true)
Thomas Zander's avatar
Thomas Zander committed
279
    void addProperty(const QString &propName, bool propValue, PropertyType type = DefaultType) {
280 281 282
        if (type == DefaultType) {
            type = m_propertyType;
        }
283
        m_properties[type].insert(propName, propValue ? "true" : "false");
Casper Boemann's avatar
Casper Boemann committed
284 285 286 287 288 289 290 291
    }

    /**
     *  Add a property which represents a distance, measured in pt
     *  The number is written out with the highest possible precision
     *  (unlike QString::number and setNum, which default to 6 digits),
     *  and the unit name ("pt") is appended to it.
     */
Thomas Zander's avatar
Thomas Zander committed
292
    void addPropertyPt(const QString &propName, qreal propValue, PropertyType type = DefaultType);
293 294 295 296 297 298 299 300
    
    /**
     *  Add a property which represents a length, measured in pt, or in percent
     *  The number is written out with the highest possible precision
     *  (unlike QString::number and setNum, which default to 6 digits) or as integer (for percents),
     *  and the unit name ("pt" or "%") is appended to it.
     */
    void addPropertyLength(const QString &propName, const QTextLength &propValue, PropertyType type = DefaultType);
301 302 303 304 305 306 307 308 309 310 311

    /**
     *  Remove a property from the style.  Passing DefaultType as property type
     *  uses a style-type specific property type.
     */
    void removeProperty(const QString &propName, PropertyType type = DefaultType) {
        if (type == DefaultType) {
            type = m_propertyType;
        }
        m_properties[type].remove(propName);
    }
Casper Boemann's avatar
Casper Boemann committed
312

313 314 315 316 317 318 319 320 321 322 323
    /**
     *  Remove properties of defined type from the style.  Passing DefaultType
     *  as property type uses a style-type specific property type.
     */
    void removeAllProperties(PropertyType type = DefaultType) {
        if (type == DefaultType) {
            type = m_propertyType;
        }
        m_properties[type].clear();
    }

Casper Boemann's avatar
Casper Boemann committed
324 325 326 327 328
    /**
     *  Add an attribute to the style
     *  The difference between property and attributes is a bit oasis-format-specific:
     *  attributes are for the style element itself, and properties are in the style:properties child element
     */
Thomas Zander's avatar
Thomas Zander committed
329
    void addAttribute(const QString &attrName, const QString& attrValue) {
330
        m_attributes.insert(attrName, attrValue);
Casper Boemann's avatar
Casper Boemann committed
331 332
    }
    /// Overloaded version of addAttribute that takes a char*, usually for "..."
Thomas Zander's avatar
Thomas Zander committed
333
    void addAttribute(const QString &attrName, const char* attrValue) {
334
        m_attributes.insert(attrName, QString::fromUtf8(attrValue));
Casper Boemann's avatar
Casper Boemann committed
335 336
    }
    /// Overloaded version of addAttribute that converts an int to a string
Thomas Zander's avatar
Thomas Zander committed
337
    void addAttribute(const QString &attrName, int attrValue) {
338
        m_attributes.insert(attrName, QString::number(attrValue));
Casper Boemann's avatar
Casper Boemann committed
339 340 341
    }

    /// Overloaded version of addAttribute that converts a bool to a string
Thomas Zander's avatar
Thomas Zander committed
342
    void addAttribute(const QString &attrName, bool attrValue) {
343
        m_attributes.insert(attrName, attrValue ? "true" : "false");
Casper Boemann's avatar
Casper Boemann committed
344 345 346 347 348 349 350 351
    }

    /**
     *  Add an attribute which represents a distance, measured in pt
     *  The number is written out with the highest possible precision
     *  (unlike QString::number and setNum, which default to 6 digits),
     *  and the unit name ("pt") is appended to it.
     */
352
    void addAttribute(const QString &attrName, qreal attrValue);
Casper Boemann's avatar
Casper Boemann committed
353

354 355 356 357 358 359 360 361 362 363
    /**
     * Add an attribute that represents a percentage value as defined in ODF
     */
    void addAttributePercent(const QString &attrName, qreal value);

    /**
     * Add an attribute that represents a percentage value as defined in ODF
     */
    void addAttributePercent(const QString &attrName, int value);

364 365 366 367 368 369 370
    /**
     *  Remove an attribute from the style.
     */
    void removeAttribute(const QString &attrName) {
        m_attributes.remove(attrName);
    }

371

Casper Boemann's avatar
Casper Boemann committed
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
    /**
     * @brief Add a child element to the style properties.
     *
     * What is meant here is that the contents of the QString
     * will be written out literally. This means you should use
     * KoXmlWriter to generate it:
     * @code
     * QBuffer buffer;
     * buffer.open( QIODevice::WriteOnly );
     * KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
     * elementWriter.startElement( "..." );
     * ...
     * elementWriter.endElement();
     * QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
     * gs.addChildElement( "...", elementContents );
     * @endcode
     *
389
     * The value of @p elementName is only used to set the order on how the child elements are written out.
Casper Boemann's avatar
Casper Boemann committed
390
     */
391 392 393 394 395
    void addChildElement(const QString &elementName, const QString& elementContents, PropertyType type = DefaultType) {
        if (type == DefaultType) {
            type = m_propertyType;
        }
        m_childProperties[type].insert(elementName, elementContents);
Casper Boemann's avatar
Casper Boemann committed
396 397
    }

398 399 400 401
    /**
     * Same like \a addChildElement above but with QByteArray to explicit convert from QByteArray
     * to QString using utf8 to prevent a dirty pitfall.
     */
402 403 404 405 406
    void addChildElement(const QString &elementName, const QByteArray& elementContents, PropertyType type = DefaultType) {
        if (type == DefaultType) {
            type = m_propertyType;
        }
        m_childProperties[type].insert(elementName, QString::fromUtf8(elementContents));
407 408
    }

409 410
    /**
     * Same like \a addChildElement above but adds a child style which is not child of any of the properties
411
     * The value of @p elementName is only used to set the order on how the child elements are written out.
412 413 414 415 416 417 418 419
     */
    void addStyleChildElement(const QString &elementName, const QString& elementContents) {
        m_properties[StyleChildElement].insertMulti(elementName, elementContents);
    }

    /**
     * Same like \a addStyleChildElement above but with QByteArray to explicit convert from QByteArray
     * to QString using utf8 to prevent a dirty pitfall.
420
     * The value of @p elementName is only used to set the order on how the child elements are written out.
421 422 423 424 425
     */
    void addStyleChildElement(const QString &elementName, const QByteArray& elementContents) {
        m_properties[StyleChildElement].insertMulti(elementName, QString::fromUtf8(elementContents));
    }

Casper Boemann's avatar
Casper Boemann committed
426 427 428 429
    /**
     * @brief Add a style:map to the style.
     * @param styleMap the attributes for the map, associated as (name,value).
     */
Thomas Zander's avatar
Thomas Zander committed
430
    void addStyleMap(const QMap<QString, QString> &styleMap);
Casper Boemann's avatar
Casper Boemann committed
431 432 433 434

    /**
     * @return true if the style has no attributes, no properties, no style map etc.
     * This can be used by applications which do not save all attributes unconditionally,
Jarosław Staniek's avatar
Jarosław Staniek committed
435
     * but only those that differ from the parent. But note that KoGenStyles::insert() can't find this out...
Casper Boemann's avatar
Casper Boemann committed
436
     */
Jarosław Staniek's avatar
Jarosław Staniek committed
437
    bool isEmpty() const;
Casper Boemann's avatar
Casper Boemann committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451

    /**
     *  Write the definition of this style to @p writer, using the OASIS format.
     *  @param writer the KoXmlWriter in which @p elementName will be created and filled in
     *  @param styles the styles collection, used to look up the parent style
     *  @param elementName the name of the XML element, e.g. "style:style". Don't forget to
     *  pass style:default-style if isDefaultStyle().
     *  @param name must come from the collection. It will be ignored if isDefaultStyle() is true.
     *  @param propertiesElementName the name of the XML element with the style properties,
     *  e.g. "style:text-properties". Can be 0 in special cases where there should be no such item,
     *  in which case the attributes and elements are added under the style itself.
     *  @param closeElement set it to false to be able to add more child elements to the style element
     *  @param drawElement set it to true to add "draw:name" (used for gradient/hatch style) otherwise add "style:name"
     */
Thomas Zander's avatar
Thomas Zander committed
452 453
    void writeStyle(KoXmlWriter *writer, const KoGenStyles &styles, const char *elementName, const QString &name,
                    const char *propertiesElementName, bool closeElement = true, bool drawElement = false) const;
Casper Boemann's avatar
Casper Boemann committed
454

455 456 457 458 459 460
    /**
     *  Write the definition of these style properties to @p writer, using the OASIS format.
     *  @param writer the KoXmlWriter in which @p elementName will be created and filled in
     *  @param type the type of properties to write
     *  @param parentStyle the parent to this style
     */
Thomas Zander's avatar
Thomas Zander committed
461 462
    void writeStyleProperties(KoXmlWriter *writer, PropertyType type,
                              const KoGenStyle *parentStyle = 0) const;
463

Casper Boemann's avatar
Casper Boemann committed
464 465 466 467 468 469 470
    /**
     *  QMap requires a complete sorting order.
     *  Another solution would have been a qdict and a key() here, a la KoTextFormat,
     *  but the key was difficult to generate.
     *  Solutions with only a hash value (not representative of the whole data)
     *  require us to write a hashtable by hand....
     */
471
    bool operator<(const KoGenStyle &other) const;
Casper Boemann's avatar
Casper Boemann committed
472 473

    /// Not needed for QMap, but can still be useful
474
    bool operator==(const KoGenStyle &other) const;
Casper Boemann's avatar
Casper Boemann committed
475

476 477 478 479 480 481 482 483 484
    /**
     * Returns a property of this style. In prinicpal this class is meant to be write-only, but
     * some exceptional cases having read-support as well is very useful.  Passing DefaultType
     * as property type uses a style-type specific property type.
     */
    QString property(const QString &propName, PropertyType type = DefaultType) const {
        if (type == DefaultType) {
            type = m_propertyType;
        }
Jarosław Staniek's avatar
Jarosław Staniek committed
485 486
        const QMap<QString, QString>::const_iterator it = m_properties[type].constFind(propName);
        if (it != m_properties[type].constEnd())
Casper Boemann's avatar
Casper Boemann committed
487 488 489 490
            return it.value();
        return QString();
    }

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
    /**
     * Returns a property of this style. In prinicpal this class is meant to be write-only, but
     * some exceptional cases having read-support as well is very useful.  Passing DefaultType
     * as property type uses a style-type specific property type.
     */
    QString childProperty(const QString &propName, PropertyType type = DefaultType) const {
        if (type == DefaultType) {
            type = m_propertyType;
        }
        const QMap<QString, QString>::const_iterator it = m_childProperties[type].constFind(propName);
        if (it != m_childProperties[type].constEnd())
            return it.value();
        return QString();
    }

506
    /// Returns an attribute of this style. In prinicpal this class is meant to be write-only, but some exceptional cases having read-support as well is very useful.
Thomas Zander's avatar
Thomas Zander committed
507
    QString attribute(const QString &propName) const {
Jarosław Staniek's avatar
Jarosław Staniek committed
508 509
        const QMap<QString, QString>::const_iterator it = m_attributes.constFind(propName);
        if (it != m_attributes.constEnd())
Casper Boemann's avatar
Casper Boemann committed
510 511 512 513
            return it.value();
        return QString();
    }

514 515 516 517 518 519 520
    /**
     * Copies properties of defined type from a style to another style.
     * This is needed in rare cases where two styles have properties of different types
     * and we want to merge them to one style.
     */
    static void copyPropertiesFromStyle(const KoGenStyle &sourceStyle, KoGenStyle &targetStyle, PropertyType type = DefaultType);

521
private:
Casper Boemann's avatar
Casper Boemann committed
522 523 524 525 526 527 528
#ifndef NDEBUG
    void printDebug() const;
#endif

private:
    // Note that the copy constructor and assignment operator are allowed.
    // Better not use pointers below!
Thomas Zander's avatar
Thomas Zander committed
529
    // TODO turn this into a QSharedData class
530
    PropertyType m_propertyType;
Thorsten Zachmann's avatar
Thorsten Zachmann committed
531
    Type m_type;
Casper Boemann's avatar
Casper Boemann committed
532 533 534 535
    QByteArray m_familyName;
    QString m_parentName;
    /// We use QMaps since they provide automatic sorting on the key (important for unicity!)
    typedef QMap<QString, QString> StyleMap;
Jarosław Staniek's avatar
Jarosław Staniek committed
536
    StyleMap m_properties[LastPropertyType+1];
537
    StyleMap m_childProperties[LastPropertyType+1];
538
    StyleMap m_attributes;
Thorsten Zachmann's avatar
Thorsten Zachmann committed
539
    QList<StyleMap> m_maps; // we can't really sort the maps between themselves...
Casper Boemann's avatar
Casper Boemann committed
540 541 542

    bool m_autoStyleInStylesDotXml;
    bool m_defaultStyle;
Halla Rempt's avatar
Halla Rempt committed
543
    short m_unused2 {0};
Casper Boemann's avatar
Casper Boemann committed
544

Jarosław Staniek's avatar
Jarosław Staniek committed
545
    // For insert()
Casper Boemann's avatar
Casper Boemann committed
546 547 548 549
    friend class KoGenStyles;
};

#endif /* KOGENSTYLE_H */