KDEGames

kgamesvgdocument.cpp
1 /***************************************************************************
2  * Copyright (C) 2007 Mark A. Taff <[email protected]> *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU Library General Public License *
6  * version 2 as published by the Free Software Foundation *
7  * *
8  * This program is distributed in the hope that it will be useful, *
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11  * GNU Library General Public License for more details. *
12  * *
13  * You should have received a copy of the GNU Library General Public *
14  * License along with this program; if not, write to the *
15  * Free Software Foundation, Inc., *
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
17  ***************************************************************************/
18 
19 #include "kgamesvgdocument.h"
20 #include "kgamesvgdocument_p.h"
21 
22 #include <KFilterDev>
23 
24 #include <QBuffer>
25 #include <QFile>
26 #include <QString>
27 #include <QDomElement>
28 #include <QDomNode>
29 #include <QDebug>
30 
31 #include <math.h>
32 
33 //
34 // Public
35 //
36 
44 class KGameSvgDocumentPrivate
45 {
46  public:
47 
51  KGameSvgDocumentPrivate()
52  {}
53 
54  ~KGameSvgDocumentPrivate()
55  {}
56 
65  QDomNode findElementById(const QString& attributeName, const QString& attributeValue, const QDomNode& node);
66 
71  QDomElement currentElement() const;
72 
78  void setCurrentElement();
79 
84  bool styleHasTrailingSemicolon() const;
85 
92  void setStyleHasTrailingSemicolon(bool hasSemicolon);
93 
97  QDomNode m_currentNode;
98 
102  QDomElement m_currentElement;
103 
111  QStringList m_inkscapeOrder;
112 
118  static const QString SVG_XML_PREPEND;
119 
125  static const QString SVG_XML_APPEND;
126 
130  QString m_svgFilename;
131 
135  bool m_hasSemicolon;
136 
137 
138 };
139 
140 const QString KGameSvgDocumentPrivate::SVG_XML_PREPEND = QStringLiteral("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><svg>");
141 const QString KGameSvgDocumentPrivate::SVG_XML_APPEND = QStringLiteral("</svg>");
142 
144  : QDomDocument(), d(new KGameSvgDocumentPrivate)
145 {}
146 
148  : QDomDocument(), d(new KGameSvgDocumentPrivate(*doc.d))
149 {
150 }
151 
153 {
154  delete d;
155 }
156 
158 {
160  *d = *doc.d;
161  return *this;
162 }
163 
164 QDomNode KGameSvgDocument::elementByUniqueAttributeValue(const QString& attributeName, const QString& attributeValue)
165 {
166  /* DOM is always "live", so there maybe a new root node. We always have to ask for the
167  * root node instead of keeping a pointer to it.
168  */
169  QDomElement docElem = documentElement();
170  QDomNode n = docElem.firstChild();
171 
172  QDomNode node = d->findElementById(attributeName, attributeValue, n);
173  setCurrentNode(node);
174  return node;
175 }
176 
178 {
179  return elementByUniqueAttributeValue(QStringLiteral( "id" ), attributeValue);
180 }
181 
183 {
184  if (d->m_svgFilename.isNull())
185  {
186  qCDebug(GAMES_LIB) << "KGameSvgDocument::load(): Filename not specified.";
187  return;
188  }
189 
190  QFile file(d->m_svgFilename);
191  if (!file.open(QIODevice::ReadOnly))
192  {
193  return;
194  }
195  QByteArray content = file.readAll();
196 
197  // If the file is compressed, decompress the contents before loading it.
198  if (!content.startsWith("<?xml")) // krazy:exclude=strings
199  {
200  QBuffer buf(&content);
201  KCompressionDevice::CompressionType type = KFilterDev::compressionTypeForMimeType(QStringLiteral("application/x-gzip"));
202  KCompressionDevice flt(&buf, false, type);
203  if (!flt.open(QIODevice::ReadOnly))
204  {
205  flt.close();
206  return;
207  }
208  QByteArray ar = flt.readAll();
209  flt.close();
210  content = ar;
211  }
212 
213  if (!setContent(content))
214  {
215  file.close();
216  qCDebug(GAMES_LIB) << "DOM content not set.";
217  return;
218  }
219  file.close();
220 }
221 
223 {
224  setSvgFilename(svgFilename);
225  load();
226 }
227 
228 void KGameSvgDocument::rotate(double degrees, const MatrixOptions& options)
229 {
230  QTransform matrix;
231 
232  if (options == ApplyToCurrentMatrix)
233  {
234  matrix = transformMatrix().QTransform::rotate(degrees);
235  }
236  else
237  {
238  matrix = QTransform();
239  matrix.QTransform::rotate(degrees);
240  }
242 }
243 
244 void KGameSvgDocument::translate(int xPixels, int yPixels, const MatrixOptions& options)
245 {
246  QTransform matrix;
247 
248  if (options == ApplyToCurrentMatrix)
249  {
250  matrix = transformMatrix().QTransform::translate(xPixels, yPixels);
251  }
252  else
253  {
254  matrix = QTransform();
255  matrix.QTransform::translate(xPixels, yPixels);
256  }
258 }
259 
260 void KGameSvgDocument::shear(double xRadians, double yRadians, const MatrixOptions& options)
261 {
262  QTransform matrix;
263 
264  if (options == ApplyToCurrentMatrix)
265  {
266  matrix = transformMatrix().QTransform::shear(xRadians, yRadians);
267  }
268  else
269  {
270  matrix = QTransform();
271  matrix.QTransform::shear(xRadians, yRadians);
272  }
274 }
275 
276 void KGameSvgDocument::skew(double xDegrees, double yDegrees, const MatrixOptions& options)
277 {
278  double xRadians = xDegrees * (M_PI / 180);
279  double yRadians = yDegrees * (M_PI / 180);
280 
281  shear(xRadians, yRadians, options);
282 }
283 
284 void KGameSvgDocument::scale(double xFactor, double yFactor, const MatrixOptions& options)
285 {
286  QTransform matrix;
287  if ((xFactor == 0) || (yFactor == 0))
288  {
289  qWarning () << "KGameSvgDocument::scale: You cannot scale by zero";
290  }
291 
292  if (options == ApplyToCurrentMatrix)
293  {
294  matrix = transformMatrix().QTransform::scale(xFactor, yFactor);
295  }
296  else
297  {
298  matrix = QTransform();
299  matrix.QTransform::scale(xFactor, yFactor);
300  }
302 }
303 
305 {
306  return d->m_currentNode;
307 }
308 
310 {
311  d->m_currentNode = node;
312  d->setCurrentElement();
313 }
314 
316 {
317  return d->m_svgFilename;
318 }
319 
321 {
322  d->m_svgFilename = svgFilename;
323 }
324 
326 {
327  return styleProperties().value(propertyName);
328 }
329 
330 void KGameSvgDocument::setStyleProperty(const QString& propertyName, const QString& propertyValue)
331 {
332  QHash<QString, QString> properties;
333 
334  properties = styleProperties();
335  properties.insert(propertyName, propertyValue);
336 
338 }
339 
341 {
342  QString s, t, xml, defs, pattern;
343  QTextStream str(&s);
344  QTextStream str_t(&t);
345  QStringList defsAdded;
346  int result = 0;
347  QRegExp rx;
348 
349  currentNode().save(str, 1);
350  xml = *str.string();
351 
352  // Find and add any required gradients or patterns
353  pattern = QLatin1String( "url" ) + WSP_ASTERISK + OPEN_PARENS + WSP_ASTERISK + QLatin1String( "#(.*)" ) + WSP_ASTERISK + CLOSE_PARENS;
354  rx.setPattern(pattern);
355  if (rx.indexIn(xml, result) != -1)
356  {
357  QDomNode node, nodeBase;
358  QString baseId;
359  QDomNode n = def();
360 
361  result = 0;
362  while ((result = rx.indexIn(xml, result)) != -1)
363  {
364  // Find the pattern or gradient referenced
365  result += rx.matchedLength();
366  if (!defsAdded.contains(rx.cap(1)))
367  {
368  node = d->findElementById(QStringLiteral( "id" ), rx.cap(1), n);
369  node.save(str_t, 1);
370  defsAdded.append(rx.cap(1));
371  }
372 
373  // Find the gradient the above gradient is based on
374  baseId = node.toElement().attribute(QStringLiteral( "xlink:href" )).mid(1);
375  if (!defsAdded.contains(baseId))
376  {
377  nodeBase = d->findElementById(QStringLiteral( "id" ), baseId, n);
378  nodeBase.save(str_t, 1);
379  defsAdded.append(baseId);
380  }
381  }
382  defs = *str_t.string();
383  defs = QLatin1String( "<defs>" ) + defs + QLatin1String( "</defs>" );
384  }
385 
386  // Need to make node be a real svg document, so prepend and append required tags.
387  xml = d->SVG_XML_PREPEND + defs + xml + d->SVG_XML_APPEND;
388  return xml;
389 }
390 
392 {
393  return nodeToSvg().toUtf8();
394 }
395 
397 {
398  return d->m_currentElement.attribute( QStringLiteral( "style" ), QStringLiteral( "Element has no style attribute." ));
399 }
400 
401 void KGameSvgDocument::setStyle(const QString& styleAttribute)
402 {
403  d->m_currentElement.setAttribute(QStringLiteral( "style" ), styleAttribute);
404 }
405 
407 {
408  return elementsByTagName(QStringLiteral( "pattern" ));
409 }
410 
412 {
413  return elementsByTagName(QStringLiteral( "linearGradient" ));
414 }
415 
417 {
418  return elementsByTagName(QStringLiteral( "radialGradient" ));
419 }
420 
422 {
423  return elementsByTagName(QStringLiteral( "defs" ));
424 }
425 
427 {
428  return defs().at(0);
429 }
430 
432 {
433  return d->m_currentElement.attribute( QStringLiteral( "transform" ), QStringLiteral( "Element has no transform attribute." ) );
434 }
435 
436 void KGameSvgDocument::setTransform(const QString& transformAttribute)
437 {
438  d->m_currentElement.setAttribute(QStringLiteral( "transform" ), transformAttribute);
439 }
440 
442 {
443  QHash<QString, QString> stylePropertiesHash;
444  QStringList styleProperties, keyValuePair;
446 
447  styleProperties = style().split(QLatin1Char( ';' ));
448 
449  /* The style attr may have a trailing semi-colon. If it does, split()
450  * gives us an empty final element. Remove it or we get 'index out of range' errors
451  */
452  if (styleProperties.at((styleProperties.count()-1)).isEmpty())
453  {
454  styleProperties.removeAt((styleProperties.count()-1));
455  d->setStyleHasTrailingSemicolon(true);
456  }
457  else {d->setStyleHasTrailingSemicolon(false);}
458 
459  for (int i = 0; i < styleProperties.size(); i++)
460  {
461  styleProperty = styleProperties.at(i);
462  keyValuePair = styleProperty.split(QLatin1Char( ':' ));
463  stylePropertiesHash.insert(keyValuePair.at(0), keyValuePair.at(1));
464  }
465  return stylePropertiesHash;
466 }
467 
469 {
470  QHash<QString, QString> styleProperties = _styleProperties;
471  QString styleBuffer, property;
472 
473  d->m_inkscapeOrder << QStringLiteral( "fill" ) << QStringLiteral( "fill-opacity" ) << QStringLiteral( "fill-rule" ) << QStringLiteral( "stroke" ) << QStringLiteral( "stroke-width" ) << QStringLiteral( "stroke-linecap" )
474  << QStringLiteral( "stroke-linejoin" ) << QStringLiteral( "stroke-miterlimit" ) << QStringLiteral( "stroke-dasharray" ) << QStringLiteral( "stroke-opacity" );
475 
476  if (options == UseInkscapeOrder)
477  {
478  for (int i = 0; i < d->m_inkscapeOrder.size(); i++)
479  {
480  property = d->m_inkscapeOrder.at(i);
481  if (styleProperties.contains(property))
482  {
483  styleBuffer += property + QLatin1Char( ':' ) + styleProperties.take(property) + QLatin1Char( ';' );
484  }
485  else
486  {
487  // Do Nothing
488  }
489  }
490  }
491 
492  // Append any style properties
493  if (!styleProperties.isEmpty())
494  {
495  QHashIterator<QString, QString> it(styleProperties);
496  while (it.hasNext())
497  {
498  it.next();
499  styleBuffer += it.key() + QLatin1Char( ':' ) + it.value() + QLatin1Char( ';' );
500  }
501  }
502 
503  // Remove trailing semicolon if original didn't have one
504  if (!d->styleHasTrailingSemicolon()) {styleBuffer.chop(1);}
505  setStyle(styleBuffer);
506 }
507 
509 {
510  /*
511  * Transform attributes can be quite complex. Here, we assemble this tangled web of
512  * complexity into an single matrix.
513  *
514  * The regex's that make this bearable live in kgamesvgdocument_p.h. As these regex's
515  * get quite complex, we have some code in tests/kgamesvgdocumenttest.cpp to help verify
516  * they are still correct after being edited.
517  *
518  * Warning: This code depends on the capturing parenthesis in the regex's not changing.
519  *
520  * For all the gory details, see http://www.w3.org/TR/SVG/coords.html#TransformAttribute
521  */
522  QRegExp rx;
523  QString transformAttribute;
524  int result;
525  int i = 0;
526  QTransform baseMatrix = QTransform();
527 
528  transformAttribute = transform();
529  if (transformAttribute == QLatin1String( "Element has no transform attribute." ))
530  {
531  return QTransform();
532  }
533  transformAttribute = transformAttribute.trimmed();
534 
535  rx.setPattern(TRANSFORMS);
536  if (!rx.exactMatch(transformAttribute))
537  {
538  qWarning () << "Transform attribute seems to be invalid. Check your SVG file.";
539  return QTransform();
540  }
541 
542  rx.setPattern(TRANSFORM);
543 
544  while (transformAttribute.size() > 0 && i < 32) // 32 is an arbitrary limit for the number of transforms for a single node
545  {
546  result = rx.indexIn(transformAttribute);
547  if (result != -1) // Found left-most transform
548  {
549  if (rx.cap(1) == QLatin1String( "matrix" ))
550  {
551  // If the first transform found is a matrix, use it as the base,
552  // else we use a null matrix.
553  if (i == 0)
554  {
555  baseMatrix = QTransform(rx.cap(2).toDouble(), rx.cap(3).toDouble(), rx.cap(4).toDouble(),
556  rx.cap(5).toDouble(), rx.cap(6).toDouble(), rx.cap(7).toDouble());
557  }
558  else
559  {
560  baseMatrix = QTransform(rx.cap(2).toDouble(), rx.cap(3).toDouble(), rx.cap(4).toDouble(),
561  rx.cap(5).toDouble(), rx.cap(6).toDouble(), rx.cap(7).toDouble()) * baseMatrix;
562  }
563  }
564 
565  if (rx.cap(8) == QLatin1String( "translate" ))
566  {
567  double x = rx.cap(9).toDouble();
568  double y = rx.cap(10).toDouble();
569  if (rx.cap(10).isEmpty()) // y defaults to zero per SVG standard
570  {
571  y = 0;
572  }
573  baseMatrix = baseMatrix.translate(x, y);
574  }
575 
576  if (rx.cap(11) == QLatin1String( "scale" ))
577  {
578  double x = rx.cap(12).toDouble();
579  double y = rx.cap(12).toDouble();
580  if (rx.cap(13).isEmpty()) // y defaults to x per SVG standard
581  {
582  y = x;
583  }
584  baseMatrix = baseMatrix.scale(x, y);
585  }
586 
587  if (rx.cap(14) == QLatin1String( "rotate" ))
588  {
589  double a = rx.cap(15).toDouble();
590  double cx = rx.cap(16).toDouble();
591  double cy = rx.cap(17).toDouble();
592 
593  if ((cx > 0) || (cy > 0)) // rotate around point (cx, cy)
594  {
595  baseMatrix.translate(cx, cy);
596  baseMatrix.rotate(a);
597  baseMatrix.translate((cx * -1), (cy * -1));
598  }
599  else
600  {
601  baseMatrix = baseMatrix.rotate(a); // rotate around origin
602  }
603  }
604 
605  if (rx.cap(18) == QLatin1String( "skewX" ))
606  {
607  baseMatrix = baseMatrix.shear(rx.cap(19).toDouble() * (M_PI / 180), 0);
608  }
609 
610  if (rx.cap(20) == QLatin1String( "skewY" ))
611  {
612  baseMatrix = baseMatrix.shear(0, rx.cap(21).toDouble() * (M_PI / 180));
613  }
614  }
615  transformAttribute = transformAttribute.mid(rx.matchedLength() + result);
616  i++;
617  }
618 
619  return baseMatrix;
620 }
621 
623 {
624  QString transformBuffer, tmp;
625  QTransform null = QTransform();
626 
627  if (options == ApplyToCurrentMatrix)
628  {
629  matrix = transformMatrix() * matrix;
630  }
631 
632  transformBuffer = QStringLiteral( "matrix(" );
633  transformBuffer += tmp.setNum(matrix.m11(),'g',7) + QLatin1Char( ',' );
634  transformBuffer += tmp.setNum(matrix.m12(),'g',7) + QLatin1Char( ',' );
635  transformBuffer += tmp.setNum(matrix.m21(),'g',7) + QLatin1Char( ',' );
636  transformBuffer += tmp.setNum(matrix.m22(),'g',7) + QLatin1Char( ',' );
637  transformBuffer += tmp.setNum(matrix.dx(),'g',7) + QLatin1Char( ',' );
638  transformBuffer += tmp.setNum(matrix.dy(),'g',7) + QLatin1Char( ')' );
639 
640  if ((transform() == QLatin1String( "Element has no transform attribute." )) && (matrix == null))
641  {
642  // Do not write a meaningless matrix to DOM
643  }
644  else
645  {
646  setTransform(transformBuffer);
647  }
648 }
649 
650 
651 //
652 // Private
653 //
654 
655 QDomNode KGameSvgDocumentPrivate::findElementById(const QString& attributeName, const QString& attributeValue, const QDomNode& node)
656 {
657  QDomElement e = node.toElement(); // try to convert the node to an element.
658  QString value = e.attribute( attributeName, QStringLiteral( "Element has no attribute with that name." ));
659 
660  if (value == attributeValue)
661  {
662  // We found our node. Stop recursion and return it.
663  return node;
664  }
665 
666  if (!node.firstChild().isNull())
667  {
668  QDomNode result = findElementById(attributeName, attributeValue, node.firstChild());
672  if (!result.isNull()) return result; // If we found the node with id, then return it
673  }
674  if (!node.nextSibling().isNull())
675  {
676  QDomNode result = findElementById(attributeName, attributeValue, node.nextSibling());
679  if (!result.isNull()) return result;
680  }
681  if (!node.firstChild().isNull() && !node.nextSibling().isNull())
682  {
683  // Do Nothing
684  //qCDebug(GAMES_LIB) << "No children or siblings.";
685  }
686 
687  // Matching node not found, so return a null node.
688  return QDomNode();
689 }
690 
691 QDomElement KGameSvgDocumentPrivate::currentElement() const
692 {
693  return m_currentElement;
694 }
695 
696 void KGameSvgDocumentPrivate::setCurrentElement()
697 {
698  m_currentElement = m_currentNode.toElement();
699 }
700 
701 bool KGameSvgDocumentPrivate::styleHasTrailingSemicolon() const
702 {
703  return m_hasSemicolon;
704 }
705 
706 void KGameSvgDocumentPrivate::setStyleHasTrailingSemicolon(bool hasSemicolon)
707 {
708  m_hasSemicolon = hasSemicolon;
709 }
710 
QString cap(int nth) const const
QHash::iterator insert(const Key &key, const T &value)
QString svgFilename() const
Returns the name of the SVG file this DOM represents.
void setSvgFilename(const QString &svgFilename)
Sets the current SVG filename.
qreal dx() const const
qreal dy() const const
const Key & key() const const
void setTransform(const QString &transformAttribute)
Sets the transform attribute of the current node.
QString attribute(const QString &name, const QString &defValue) const const
bool hasNext() const const
const T & at(int i) const const
int size() const const
void removeAt(int i)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QString styleProperty(const QString &propertyName) const
Returns the value of the style property given for the current node.
bool startsWith(const QByteArray &ba) const const
QHash< QString, QString > styleProperties() const
Returns a hash of the style properties of the current node.
QString style() const
Returns the style attribute of the current node.
QDomElement documentElement() const const
QDomNodeList defs() const
Returns the defs in the document.
QDomNodeList radialGradients() const
Returns the radialGradients in the document.
void chop(int n)
double toDouble(bool *ok) const const
QTransform transformMatrix() const
Returns the transform attribute of the current node as a matrix.
int size() const const
QDomNode nextSibling() const const
void setPattern(const QString &pattern)
QDomElement toElement() const const
int matchedLength() const const
int indexIn(const QString &str, int offset, QRegExp::CaretMode caretMode) const const
static CompressionType compressionTypeForMimeType(const QString &mimetype)
QTransform & translate(qreal dx, qreal dy)
int count(const T &value) const const
void append(const T &value)
When building a style attribute, sort properties the same way Inkscape does.
QTransform & scale(qreal sx, qreal sy)
void shear(double xRadians, double yRadians, const MatrixOptions &options=ApplyToCurrentMatrix)
Shears the origin of the current node.
qreal m11() const const
qreal m12() const const
qreal m21() const const
qreal m22() const const
QDomNodeList elementsByTagName(const QString &tagname) const const
bool isEmpty() const const
QString trimmed() const const
virtual ~KGameSvgDocument()
Destructor.
QByteArray readAll()
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
A class for manipulating an SVG file using DOM.
QDomNode currentNode() const
Returns the last node found by elementById, or null if node not found.
KGameSvgDocument & operator=(const KGameSvgDocument &doc)
Assignment Operator.
void setStyleProperties(const QHash< QString, QString > &_styleProperties, const StylePropertySortOptions &options=Unsorted)
Sets the style properties of the current node.
virtual bool open(QIODevice::OpenMode mode) override
This file contains the KGameSvgDocument class, used for manipulating an SVG file using DOM...
QString transform() const
Returns the transform attribute of the current node.
QHashIterator::Item next()
void skew(double xDegrees, double yDegrees, const MatrixOptions &options=ApplyToCurrentMatrix)
Skews the origin of the current node.
void load()
Reads the SVG file svgFilename() into DOM.
void scale(double xFactor, double yFactor, const MatrixOptions &options=ApplyToCurrentMatrix)
Scales the origin of the current node.
bool isNull() const const
QTransform & rotate(qreal angle, Qt::Axis axis)
void close() override
Replace the current matrix.
QDomDocument & operator=(const QDomDocument &x)
void translate(int xPixels, int yPixels, const MatrixOptions &options=ApplyToCurrentMatrix)
Moves the origin of the current node.
QString * string() const const
void save(QTextStream &stream, int indent, QDomNode::EncodingPolicy encodingPolicy) const const
QDomNode firstChild() const const
QString mid(int position, int n) const const
T take(const Key &key)
KGameSvgDocument()
Constructor.
bool isEmpty() const const
virtual void close() override
QString & setNum(short n, int base)
QString nodeToSvg() const
Returns the current node and its children as a new xml svg document.
bool open(QIODevice::OpenMode mode) override
bool contains(const Key &key) const const
QDomNode elementByUniqueAttributeValue(const QString &attributeName, const QString &attributeValue)
Returns the node with the given value for the given attribute.
const T & value() const const
QDomNode def() const
Returns the first def in the document.
QDomNodeList patterns() const
Returns the patterns in the document.
QDomNodeList linearGradients() const
Returns the linearGradients in the document.
void setTransformMatrix(QTransform &matrix, const MatrixOptions &options=ApplyToCurrentMatrix)
Sets the transform attribute of the current node.
QByteArray nodeToByteArray() const
Builds a new svg document and returns a QByteArray suitable for passing to QSvgRenderer::load().
QTransform & shear(qreal sh, qreal sv)
void setCurrentNode(const QDomNode &node)
Sets the current node.
QDomNode elementById(const QString &attributeValue)
Returns a node with the given id.
void setStyle(const QString &styleAttribute)
Sets the style attribute of the current node.
void rotate(double degrees, const MatrixOptions &options=ApplyToCurrentMatrix)
Rotates the origin of the current node counterclockwise.
bool exactMatch(const QString &str) const const
void setStyleProperty(const QString &propertyName, const QString &propertyValue)
Sets the value of the style property given for the current node.
QDomNode at(int index) const const
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:36:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.