Warning, file /office/calligra/filters/libmsooxml/MsooXmlUtils.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of Office 2007 Filters for Calligra 0003 * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com> 0004 * Copyright (c) 2003 Lukas Tinkl <lukas@kde.org> 0005 * Copyright (C) 2003 David Faure <faure@kde.org> 0006 * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). 0007 * 0008 * Contact: Suresh Chande suresh.chande@nokia.com 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Lesser General Public License 0012 * version 2.1 as published by the Free Software Foundation. 0013 * 0014 * This library is distributed in the hope that it will be useful, but 0015 * WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 * Lesser General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU Lesser General Public 0020 * License along with this library; if not, write to the Free Software 0021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 0022 * 02110-1301 USA 0023 * 0024 */ 0025 0026 #ifndef MSOOXML_UTILS_H 0027 #define MSOOXML_UTILS_H 0028 0029 #include "komsooxml_export.h" 0030 0031 #include <QSize> 0032 #include <QColor> 0033 #include <QBuffer> 0034 #include <KoFilterChain.h> 0035 #include <KoXmlReader.h> 0036 #include "MsooXmlDebug.h" 0037 #include <KoGenStyle.h> 0038 0039 class KZip; 0040 struct KoOdfWriters; 0041 class KoCharacterStyle; 0042 class KoXmlWriter; 0043 class KoGenStyles; 0044 0045 //! Returns from the current block if the result of @a call is not equal to KoFilter::OK 0046 #define RETURN_IF_ERROR( call ) \ 0047 { \ 0048 const KoFilter::ConversionStatus result = call; \ 0049 if (result != KoFilter::OK) \ 0050 return result; \ 0051 } 0052 0053 //! Common utilities for handling MSOOXML formats 0054 namespace MSOOXML 0055 { 0056 0057 class MsooXmlReader; 0058 class MsooXmlReaderContext; 0059 0060 namespace Utils { 0061 0062 enum autoFitStatus { 0063 autoFitUnUsed, autoFitOn, autoFitOff 0064 }; 0065 0066 enum MSOOXMLFilter { 0067 DocxFilter, PptxFilter, XlsxFilter 0068 }; 0069 0070 class KOMSOOXML_EXPORT ParagraphBulletProperties 0071 { 0072 public: 0073 0074 ParagraphBulletProperties(); 0075 0076 void clear(); 0077 0078 QString convertToListProperties(KoGenStyles& mainStyles, MSOOXMLFilter filter = XlsxFilter); 0079 0080 bool isEmpty() const; 0081 0082 void setBulletChar(const QString& bulletChar); 0083 0084 void setPrefix(const QString& prefixChar); 0085 0086 void setSuffix(const QString& suffixChar); 0087 0088 void setAlign(const QString& align); 0089 0090 void setNumFormat(const QString& numFormat); 0091 0092 void setMargin(const qreal margin); 0093 0094 void setIndent(const qreal indent); 0095 0096 void setPicturePath(const QString& picturePath); 0097 0098 void setBulletFont(const QString& font); 0099 0100 void setBulletColor(const QString& bulletColor); 0101 0102 void setStartValue(const QString& value); 0103 0104 void setBulletRelativeSize(const int size); 0105 0106 void setBulletSizePt(const qreal size); 0107 0108 void setFollowingChar(const QString& value); 0109 0110 void setTextStyle(const KoGenStyle& textStyle); 0111 0112 void setStartOverride(const bool startOverride); 0113 0114 QString startValue() const; 0115 0116 QString bulletRelativeSize() const; 0117 0118 QString bulletSizePt() const; 0119 0120 QString bulletColor() const; 0121 0122 QString bulletChar() const; 0123 0124 QString bulletFont() const; 0125 0126 QString indent() const; 0127 0128 QString margin() const; 0129 0130 QString followingChar() const; 0131 0132 KoGenStyle textStyle() const; 0133 0134 bool startOverride() const; 0135 0136 void addInheritedValues(const ParagraphBulletProperties& properties); 0137 0138 int m_level; 0139 0140 enum ParagraphBulletType {BulletType, NumberType, PictureType, DefaultType}; 0141 ParagraphBulletType m_type; 0142 0143 private: 0144 0145 QString m_startValue; 0146 QString m_bulletFont; 0147 QString m_bulletChar; 0148 QString m_numFormat; 0149 QString m_prefix; 0150 QString m_suffix; 0151 QString m_align; 0152 QString m_indent; 0153 QString m_margin; 0154 QString m_picturePath; 0155 QString m_bulletColor; 0156 QString m_followingChar; 0157 QString m_bulletRelativeSize; 0158 QString m_bulletSize; 0159 0160 KoGenStyle m_textStyle; 0161 0162 // MSWord specific: Restart the numbering when this list style is 0163 // used for the 1st time. Otherwise don't restart in case any of the 0164 // styles inheriting from the same abstract numbering definition was 0165 // already used. Let's ignore presence of this attribute in 0166 // addInheritedValues. 0167 bool m_startOverride; 0168 }; 0169 0170 //! Container autodeleter. Works for QList, QHash and QMap. 0171 //! @todo move to more generic place 0172 template <typename T> 0173 class ContainerDeleter 0174 { 0175 public: 0176 ContainerDeleter(T& container) : m_container(&container) {} 0177 ~ContainerDeleter() { 0178 qDeleteAll(*m_container); m_container->clear(); 0179 } 0180 private: 0181 T* const m_container; 0182 }; 0183 0184 //! Helper that sets given variable to specified value on destruction 0185 //! Object of type Setter are supposed to be created on the stack. 0186 //! @todo Copied from calligra/kexi/kexiutils/utils.h; replace with a shared code 0187 template <typename T> 0188 class Setter 0189 { 0190 public: 0191 //! Creates a new setter object for variable @a var, 0192 //! which will be set to value @a val on setter's destruction. 0193 Setter(T* var, const T& val) 0194 : m_var(var), m_value(val) { 0195 } 0196 ~Setter() { 0197 if (m_var) 0198 *m_var = m_value; 0199 } 0200 //! Clears the assignment, so the setter 0201 //! will not alter the variable on destruction 0202 void clear() { 0203 m_var = 0; 0204 } 0205 private: 0206 T* m_var; 0207 const T m_value; 0208 }; 0209 0210 //! Helper that works like the @ref Setter class but also has behaviour of std::auto_ptr. 0211 //! When std::auto_ptr is used, the pointer of type T* is not set back to 0 on destruction. 0212 //! @todo replace with a shared code 0213 template <typename T> 0214 class AutoPtrSetter 0215 { 0216 public: 0217 //! Creates a new auto-ptr setter object for variable pointer of type T* @a ptr, 0218 //! which will be set to 0 setter's destruction, unless release() was called. 0219 explicit AutoPtrSetter(T* ptr) 0220 : m_pptr(&ptr) { 0221 } 0222 ~AutoPtrSetter() { 0223 if (m_pptr && *m_pptr) { 0224 delete *m_pptr; 0225 *m_pptr = 0; 0226 } 0227 } 0228 //! Bypasses the smart pointer, and returns it, so on destruction 0229 //! of the AutoPtrSetter object the pointed object will not be deleted 0230 //! (so it is the behaviour like std::auto__ptr::release()) 0231 //! but also the pointer of type T* will not be cleared. 0232 T* release() { 0233 T* p = m_pptr ? *m_pptr : 0; 0234 m_pptr = 0; 0235 return p; 0236 } 0237 private: 0238 T** m_pptr; 0239 }; 0240 0241 //! Decodes boolean attribute @a value. If unspecified returns @a defaultValue. 0242 //! @return true unless @a value is equal to "false", "off" or "0". 0243 KOMSOOXML_EXPORT bool convertBooleanAttr(const QString& value, bool defaultValue = false); 0244 0245 //! Loads content types from "[Content_Types].xml" 0246 /*! Based on information from ECMA-376, Part 1: "11.2 Package Structure". 0247 @return status: KoFilter::OK on success or KoFilter::WrongFormat when any unexpected and critical incompatibility occurs. 0248 */ 0249 //! @todo create whole class keeping the data 0250 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadContentTypes(const KoXmlDocument& contentTypesXML, 0251 QMultiHash<QByteArray, QByteArray>& contentTypes); 0252 0253 //! Loads content types from "docProps/app.xml" 0254 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadDocumentProperties(const KoXmlDocument& appXML, QMap<QString, QVariant>& properties); 0255 0256 //! @return device for file @a fileName of @a zip archive. Status @a status is written on error. 0257 //! The device is already opened for reading and should be deleted after use. 0258 KOMSOOXML_EXPORT QIODevice* openDeviceForFile(const KZip* zip, 0259 QString& errorMessage, 0260 const QString& fileName, 0261 KoFilter::ConversionStatus& status); 0262 0263 //! QXmlStreamReader-based generic loading/parsing into @a doc KoXmlDocument 0264 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadAndParse(QIODevice* io, KoXmlDocument& doc, 0265 QString& errorMessage, const QString & fileName); 0266 0267 //! @see KoOdfReadStore::loadAndParse(QIODevice* fileDevice, KoXmlDocument& doc, QString& errorMessage, const QString& fileName) 0268 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadAndParse(KoXmlDocument& doc, 0269 const KZip* zip, 0270 QString& errorMessage, 0271 const QString& fileName); 0272 0273 //! QXmlStreamReader-based loading/parsing for document.xml 0274 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadAndParseDocument(MsooXmlReader* reader, 0275 const KZip* zip, 0276 KoOdfWriters* writers, 0277 QString& errorMessage, 0278 const QString& fileName, 0279 MsooXmlReaderContext* context = 0); 0280 0281 /*! Copies file @a sourceName from zip archive @a zip to @a outputStore store 0282 under @a destinationName name. If @a size is not 0, *size is set to size of the image 0283 @return KoFilter::OK on success. 0284 On failure @a errorMessage is set. */ 0285 KoFilter::ConversionStatus copyFile(const KZip* zip, QString& errorMessage, 0286 const QString& sourceName, KoStore *outputStore, 0287 const QString& destinationName, bool oleType=false); 0288 0289 /*! Creates a file */ 0290 KoFilter::ConversionStatus createImage(QString& errorMessage, 0291 const QImage& source, KoStore *outputStore, 0292 const QString& destinationName); 0293 0294 /*! @return size of image file @a sourceName read from zip archive @a zip. 0295 Size of the image is returned in @a size. 0296 @return KoFilter::OK on success. 0297 On failure @a errorMessage is set. */ 0298 KoFilter::ConversionStatus imageSize(const KZip* zip, QString& errorMessage, 0299 const QString& sourceName, QSize* size); 0300 0301 //! Loads a thumbnail. 0302 /*! @return conversion status 0303 @todo Thumbnails are apparently used only by PowerPoint or templates for now. 0304 Implement it, for now this feature is not needed for docx. */ 0305 KOMSOOXML_EXPORT KoFilter::ConversionStatus loadThumbnail(QImage& thumbnail, KZip* zip); 0306 0307 // -- conversions --- 0308 0309 //! Handles ST_Lang value @a value (Language Reference) (SharedML, 22.9.2.6) 0310 /*! The value specifies that its contents contains a language identifier as defined by RFC 4646/BCP 47. 0311 Sets up @a language and @a country based on @a value that is of format {langugage}-{country} 0312 @return true on success. */ 0313 KOMSOOXML_EXPORT bool ST_Lang_to_languageAndCountry(const QString& value, QString& language, QString& country); 0314 0315 //! @return QColor value for ST_HexColorRGB (Hexadecimal Color Value) (SharedML, 22.9.2.5) 0316 //! or invalid QColor if @a color is not in the expected format. 0317 //! @par val color value in RRGGBB hexadecimal format 0318 inline QColor ST_HexColorRGB_to_QColor(const QString& color) 0319 { 0320 if (color.length() != 6) 0321 return QColor(); 0322 bool ok; 0323 const uint rgb = color.toUInt(&ok, 16); 0324 return ok ? QColor(QRgb(rgb)) : QColor(); // alpha ignored 0325 // return QColor(QRgb(0xff000000 | color.toInt(0, 16))); 0326 } 0327 0328 //! @return QBrush value for ST_HighlightColor 0329 //! The brush is built out of solid color. 0330 //! If colorName is not supported by the standard, QBrush() is returned. 0331 //! @par colorName named text highlight color like "black", "blue" (17.18.40) 0332 KOMSOOXML_EXPORT QBrush ST_HighlightColor_to_QColor(const QString& colorName); 0333 0334 //! Converts value for 22.9.2.9 ST_Percentage (Percentage Value with Sign) from string 0335 //! Sets @arg ok to true on success. 0336 KOMSOOXML_EXPORT qreal ST_Percentage_to_double(const QString& val, bool& ok); 0337 0338 //! Converts value for 22.9.2.9 ST_Percentage (Percentage Value with Sign) from string 0339 //! If "%" suffix is not present (MSOOXML violation of OOXML), the format is expected to be int({ST_Percentage}*1000). 0340 //! Sets @arg ok to true on success. 0341 KOMSOOXML_EXPORT qreal ST_Percentage_withMsooxmlFix_to_double(const QString& val, bool& ok); 0342 0343 struct KOMSOOXML_EXPORT DoubleModifier { 0344 DoubleModifier(qreal v) : value(v), valid(true) {} 0345 DoubleModifier() : value(0.0), valid(false) {} 0346 qreal value; 0347 bool valid; 0348 }; 0349 0350 KOMSOOXML_EXPORT QColor colorForLuminance(const QColor& color, 0351 const DoubleModifier& modulation, const DoubleModifier& offset); 0352 0353 KOMSOOXML_EXPORT void modifyColor(QColor& color, qreal tint, qreal shade, qreal satMod); 0354 0355 //! Converts shape types from ECMA-376 to ODF. 0356 /*! @return "Common Presentation Shape Attribute" value (ODF 1.1., 9.6.1) 0357 for presentation shape converted from ECMA-376 19.7.10 0358 ST_PlaceholderType (Placeholder ID) value, p. 2987. 0359 @param ecmaType ECMA-376 shape type 0360 The conversion is useful e.g. for presentation:class attribute of draw:frame 0361 out of ECMA-376's ph\@type attribute. 0362 By default (and for empty argument), "outline" is returned. 0363 */ 0364 //! @todo or "object"? ST_PlaceholderType docs day the default is "obj". 0365 //! CASE \#P500 0366 KOMSOOXML_EXPORT QString ST_PlaceholderType_to_ODF(const QString& ecmaType); 0367 0368 //! Sets up @p textStyleProperties with underline style matching MSOOXML name @p msooxmlName. 0369 //! Based on 17.18.99 ST_Underline (Underline Patterns), WML ECMA-376 p.1681 0370 //! and on 20.1.10.82 ST_TextUnderlineType (Text Underline Types), DrawingML ECMA-376 p.3450 (merged) 0371 KOMSOOXML_EXPORT void setupUnderLineStyle(const QString& msooxmlName, KoCharacterStyle* textStyleProperties); 0372 0373 //! @return the symbolic name of column @p column (counted from 0) 0374 //! This is similar to the notation of spreadsheet's column, e.g. 0th column is "A", 1st is "B", 26th is "AA". 0375 KOMSOOXML_EXPORT QString columnName(uint column); 0376 0377 //! Splits @a pathAndFile into path and file parts. Path does not end with '/'. 0378 KOMSOOXML_EXPORT void splitPathAndFile(const QString& pathAndFile, QString* path, QString* file); 0379 0380 //! Returns calculated angle and xDiff, yDiff, caller has to apply these to style 0381 KOMSOOXML_EXPORT void rotateString(const qreal rotation, const qreal width, const qreal height, qreal& angle, qreal& xDiff, qreal& yDiff); 0382 0383 //! Marker related utils 0384 KOMSOOXML_EXPORT QString defineMarkerStyle(KoGenStyles& mainStyles, const QString& markerType); 0385 0386 KOMSOOXML_EXPORT qreal defineMarkerWidth(const QString &markerWidth, const qreal lineWidth); 0387 0388 //! A helper allowing to buffer xml streams and writing them back later 0389 /*! This class is useful when information that has to be written in advance is 0390 based on XML elements parsed later. In such case the information cannot be 0391 saved in one pass. Example of this is paragraphs style name: is should be 0392 written to style:name attribute but relevant XML elements (that we use for 0393 building the style) are appearing later. So we first output created XML to 0394 a buffer, then save the parent element with the style name and use 0395 KoXmlWriter::addCompleteElement() to redirect the buffer contents as a 0396 subelement. 0397 0398 Example use: 0399 @code 0400 KoXmlWriter *body = ...; 0401 XmlWriteBuffer buf; 0402 body = buf.setWriter(body); 0403 // ... 0404 // buf.originalWriter() can be used here ... 0405 // ... 0406 // Use the new buffered body writer here, e.g.: 0407 body->startElement("text:span", false); 0408 body->addAttribute("text:style-name", currentTextStyleName); 0409 body->addTextSpan(text); 0410 body->endElement(); 0411 0412 // We are done with the buffered body writer, now release it and restore 0413 // the original body writer. This inserts all the XML buffered by buf 0414 // into the original body writer (using KoXmlWriter::addCompleteElement()). 0415 0416 body = buf.releaseWriter(); 0417 @endcode */ 0418 class KOMSOOXML_EXPORT XmlWriteBuffer 0419 { 0420 public: 0421 //! Constructor; no writer is set initially. 0422 XmlWriteBuffer(); 0423 0424 //! Destructor, releases writer if there is any set. 0425 ~XmlWriteBuffer(); 0426 0427 //! Assigns writer @a writer to this buffer. 0428 /*! From now any output directed to @a writer is written to a buffer instead. 0429 Use releaseWriter() to write the changes back through the original writer. 0430 @return the newly created writer, which usually should be assigned 0431 to the variable passed as @a writer. */ 0432 KoXmlWriter* setWriter(KoXmlWriter* writer); 0433 0434 //! Releases the original writer set before using setWriter(KoXmlWriter*&). 0435 /*! This inserts all the XML buffered by buffer into the original body writer passed in setWriter() 0436 (internally using KoXmlWriter::addCompleteElement()). 0437 @return the original writer set in setWriter(); 0438 this writer usually should be assigned back to the variable 0439 altered by the recent use of setWriter(). */ 0440 KoXmlWriter* releaseWriter(); 0441 0442 //! Releases the original writer set before using setWriter(KoXmlWriter*&). 0443 /*! This inserts all the XML buffered by buffer into @a bkpXmlSnippet 0444 @return the original writer set in setWriter(); 0445 this writer usually should be assigned back to the variable 0446 altered by the recent use of setWriter(). */ 0447 KoXmlWriter* releaseWriter(QString& bkpXmlSnippet); 0448 0449 //! @return the original writer set in setWriter(). Does not change the state of the buffer. 0450 /*! Use this method when you need to access the remembered writer without releasing it. */ 0451 KoXmlWriter* originalWriter() const { 0452 return m_origWriter; 0453 } 0454 0455 //! Clears this buffer without performing any output to the writer. 0456 void clear(); 0457 0458 //! Returns true if the buffer is empty; otherwise returns false. 0459 bool isEmpty() const { 0460 return m_buffer.buffer().isEmpty(); 0461 } 0462 0463 private: 0464 //! Internal, used in releaseWriter() and the destructor; Does not assert when there's nothing to release. 0465 KoXmlWriter* releaseWriterInternal(); 0466 0467 QBuffer m_buffer; 0468 KoXmlWriter* m_origWriter; 0469 KoXmlWriter* m_newWriter; 0470 }; 0471 0472 //! The purpose of this class is to make sure the this->body variable is proper 0473 //! set back to what it was before even if one of the TRY_READ calls lead to 0474 //! us skipping out of this method. In that case we need to make sure to restore 0475 //! the body variable else things may later crash. 0476 //! 0477 //! FIXME refactor the XmlWriteBuffer and merge this hack in so we don't 0478 //! need to work-around at any place where it's used. 0479 template <typename T> 0480 class AutoRestore 0481 { 0482 public: 0483 explicit AutoRestore(T** originalPtr) 0484 : m_originalPtr(originalPtr), m_prevValue(*originalPtr) { 0485 } 0486 ~AutoRestore() { 0487 if (m_originalPtr) { 0488 *m_originalPtr = m_prevValue; 0489 } 0490 } 0491 private: 0492 T** m_originalPtr; 0493 T* m_prevValue; 0494 }; 0495 0496 } // Utils namespace 0497 0498 } // MSOOXML namespace 0499 0500 #endif /* MSOOXML_UTILS_H */