Qt 4.8
qtexthtmlparser.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qtexthtmlparser_p.h"
43 
44 #include <qbytearray.h>
45 #include <qtextcodec.h>
46 #include <qapplication.h>
47 #include <qstack.h>
48 #include <qdebug.h>
49 #include <qthread.h>
50 
51 #include "qtextdocument.h"
52 #include "qtextformat_p.h"
53 #include "qtextdocument_p.h"
54 #include "qtextcursor.h"
55 #include "qfont_p.h"
56 #include "private/qfunctions_p.h"
57 
58 #ifndef QT_NO_TEXTHTMLPARSER
59 
61 
62 // see also tst_qtextdocumentfragment.cpp
63 #define MAX_ENTITY 258
64 static const struct QTextHtmlEntity { const char *name; quint16 code; } entities[MAX_ENTITY]= {
65  { "AElig", 0x00c6 },
66  { "AMP", 38 },
67  { "Aacute", 0x00c1 },
68  { "Acirc", 0x00c2 },
69  { "Agrave", 0x00c0 },
70  { "Alpha", 0x0391 },
71  { "Aring", 0x00c5 },
72  { "Atilde", 0x00c3 },
73  { "Auml", 0x00c4 },
74  { "Beta", 0x0392 },
75  { "Ccedil", 0x00c7 },
76  { "Chi", 0x03a7 },
77  { "Dagger", 0x2021 },
78  { "Delta", 0x0394 },
79  { "ETH", 0x00d0 },
80  { "Eacute", 0x00c9 },
81  { "Ecirc", 0x00ca },
82  { "Egrave", 0x00c8 },
83  { "Epsilon", 0x0395 },
84  { "Eta", 0x0397 },
85  { "Euml", 0x00cb },
86  { "GT", 62 },
87  { "Gamma", 0x0393 },
88  { "Iacute", 0x00cd },
89  { "Icirc", 0x00ce },
90  { "Igrave", 0x00cc },
91  { "Iota", 0x0399 },
92  { "Iuml", 0x00cf },
93  { "Kappa", 0x039a },
94  { "LT", 60 },
95  { "Lambda", 0x039b },
96  { "Mu", 0x039c },
97  { "Ntilde", 0x00d1 },
98  { "Nu", 0x039d },
99  { "OElig", 0x0152 },
100  { "Oacute", 0x00d3 },
101  { "Ocirc", 0x00d4 },
102  { "Ograve", 0x00d2 },
103  { "Omega", 0x03a9 },
104  { "Omicron", 0x039f },
105  { "Oslash", 0x00d8 },
106  { "Otilde", 0x00d5 },
107  { "Ouml", 0x00d6 },
108  { "Phi", 0x03a6 },
109  { "Pi", 0x03a0 },
110  { "Prime", 0x2033 },
111  { "Psi", 0x03a8 },
112  { "QUOT", 34 },
113  { "Rho", 0x03a1 },
114  { "Scaron", 0x0160 },
115  { "Sigma", 0x03a3 },
116  { "THORN", 0x00de },
117  { "Tau", 0x03a4 },
118  { "Theta", 0x0398 },
119  { "Uacute", 0x00da },
120  { "Ucirc", 0x00db },
121  { "Ugrave", 0x00d9 },
122  { "Upsilon", 0x03a5 },
123  { "Uuml", 0x00dc },
124  { "Xi", 0x039e },
125  { "Yacute", 0x00dd },
126  { "Yuml", 0x0178 },
127  { "Zeta", 0x0396 },
128  { "aacute", 0x00e1 },
129  { "acirc", 0x00e2 },
130  { "acute", 0x00b4 },
131  { "aelig", 0x00e6 },
132  { "agrave", 0x00e0 },
133  { "alefsym", 0x2135 },
134  { "alpha", 0x03b1 },
135  { "amp", 38 },
136  { "and", 0x22a5 },
137  { "ang", 0x2220 },
138  { "apos", 0x0027 },
139  { "aring", 0x00e5 },
140  { "asymp", 0x2248 },
141  { "atilde", 0x00e3 },
142  { "auml", 0x00e4 },
143  { "bdquo", 0x201e },
144  { "beta", 0x03b2 },
145  { "brvbar", 0x00a6 },
146  { "bull", 0x2022 },
147  { "cap", 0x2229 },
148  { "ccedil", 0x00e7 },
149  { "cedil", 0x00b8 },
150  { "cent", 0x00a2 },
151  { "chi", 0x03c7 },
152  { "circ", 0x02c6 },
153  { "clubs", 0x2663 },
154  { "cong", 0x2245 },
155  { "copy", 0x00a9 },
156  { "crarr", 0x21b5 },
157  { "cup", 0x222a },
158  { "curren", 0x00a4 },
159  { "dArr", 0x21d3 },
160  { "dagger", 0x2020 },
161  { "darr", 0x2193 },
162  { "deg", 0x00b0 },
163  { "delta", 0x03b4 },
164  { "diams", 0x2666 },
165  { "divide", 0x00f7 },
166  { "eacute", 0x00e9 },
167  { "ecirc", 0x00ea },
168  { "egrave", 0x00e8 },
169  { "empty", 0x2205 },
170  { "emsp", 0x2003 },
171  { "ensp", 0x2002 },
172  { "epsilon", 0x03b5 },
173  { "equiv", 0x2261 },
174  { "eta", 0x03b7 },
175  { "eth", 0x00f0 },
176  { "euml", 0x00eb },
177  { "euro", 0x20ac },
178  { "exist", 0x2203 },
179  { "fnof", 0x0192 },
180  { "forall", 0x2200 },
181  { "frac12", 0x00bd },
182  { "frac14", 0x00bc },
183  { "frac34", 0x00be },
184  { "frasl", 0x2044 },
185  { "gamma", 0x03b3 },
186  { "ge", 0x2265 },
187  { "gt", 62 },
188  { "hArr", 0x21d4 },
189  { "harr", 0x2194 },
190  { "hearts", 0x2665 },
191  { "hellip", 0x2026 },
192  { "iacute", 0x00ed },
193  { "icirc", 0x00ee },
194  { "iexcl", 0x00a1 },
195  { "igrave", 0x00ec },
196  { "image", 0x2111 },
197  { "infin", 0x221e },
198  { "int", 0x222b },
199  { "iota", 0x03b9 },
200  { "iquest", 0x00bf },
201  { "isin", 0x2208 },
202  { "iuml", 0x00ef },
203  { "kappa", 0x03ba },
204  { "lArr", 0x21d0 },
205  { "lambda", 0x03bb },
206  { "lang", 0x2329 },
207  { "laquo", 0x00ab },
208  { "larr", 0x2190 },
209  { "lceil", 0x2308 },
210  { "ldquo", 0x201c },
211  { "le", 0x2264 },
212  { "lfloor", 0x230a },
213  { "lowast", 0x2217 },
214  { "loz", 0x25ca },
215  { "lrm", 0x200e },
216  { "lsaquo", 0x2039 },
217  { "lsquo", 0x2018 },
218  { "lt", 60 },
219  { "macr", 0x00af },
220  { "mdash", 0x2014 },
221  { "micro", 0x00b5 },
222  { "middot", 0x00b7 },
223  { "minus", 0x2212 },
224  { "mu", 0x03bc },
225  { "nabla", 0x2207 },
226  { "nbsp", 0x00a0 },
227  { "ndash", 0x2013 },
228  { "ne", 0x2260 },
229  { "ni", 0x220b },
230  { "not", 0x00ac },
231  { "notin", 0x2209 },
232  { "nsub", 0x2284 },
233  { "ntilde", 0x00f1 },
234  { "nu", 0x03bd },
235  { "oacute", 0x00f3 },
236  { "ocirc", 0x00f4 },
237  { "oelig", 0x0153 },
238  { "ograve", 0x00f2 },
239  { "oline", 0x203e },
240  { "omega", 0x03c9 },
241  { "omicron", 0x03bf },
242  { "oplus", 0x2295 },
243  { "or", 0x22a6 },
244  { "ordf", 0x00aa },
245  { "ordm", 0x00ba },
246  { "oslash", 0x00f8 },
247  { "otilde", 0x00f5 },
248  { "otimes", 0x2297 },
249  { "ouml", 0x00f6 },
250  { "para", 0x00b6 },
251  { "part", 0x2202 },
252  { "percnt", 0x0025 },
253  { "permil", 0x2030 },
254  { "perp", 0x22a5 },
255  { "phi", 0x03c6 },
256  { "pi", 0x03c0 },
257  { "piv", 0x03d6 },
258  { "plusmn", 0x00b1 },
259  { "pound", 0x00a3 },
260  { "prime", 0x2032 },
261  { "prod", 0x220f },
262  { "prop", 0x221d },
263  { "psi", 0x03c8 },
264  { "quot", 34 },
265  { "rArr", 0x21d2 },
266  { "radic", 0x221a },
267  { "rang", 0x232a },
268  { "raquo", 0x00bb },
269  { "rarr", 0x2192 },
270  { "rceil", 0x2309 },
271  { "rdquo", 0x201d },
272  { "real", 0x211c },
273  { "reg", 0x00ae },
274  { "rfloor", 0x230b },
275  { "rho", 0x03c1 },
276  { "rlm", 0x200f },
277  { "rsaquo", 0x203a },
278  { "rsquo", 0x2019 },
279  { "sbquo", 0x201a },
280  { "scaron", 0x0161 },
281  { "sdot", 0x22c5 },
282  { "sect", 0x00a7 },
283  { "shy", 0x00ad },
284  { "sigma", 0x03c3 },
285  { "sigmaf", 0x03c2 },
286  { "sim", 0x223c },
287  { "spades", 0x2660 },
288  { "sub", 0x2282 },
289  { "sube", 0x2286 },
290  { "sum", 0x2211 },
291  { "sup", 0x2283 },
292  { "sup1", 0x00b9 },
293  { "sup2", 0x00b2 },
294  { "sup3", 0x00b3 },
295  { "supe", 0x2287 },
296  { "szlig", 0x00df },
297  { "tau", 0x03c4 },
298  { "there4", 0x2234 },
299  { "theta", 0x03b8 },
300  { "thetasym", 0x03d1 },
301  { "thinsp", 0x2009 },
302  { "thorn", 0x00fe },
303  { "tilde", 0x02dc },
304  { "times", 0x00d7 },
305  { "trade", 0x2122 },
306  { "uArr", 0x21d1 },
307  { "uacute", 0x00fa },
308  { "uarr", 0x2191 },
309  { "ucirc", 0x00fb },
310  { "ugrave", 0x00f9 },
311  { "uml", 0x00a8 },
312  { "upsih", 0x03d2 },
313  { "upsilon", 0x03c5 },
314  { "uuml", 0x00fc },
315  { "weierp", 0x2118 },
316  { "xi", 0x03be },
317  { "yacute", 0x00fd },
318  { "yen", 0x00a5 },
319  { "yuml", 0x00ff },
320  { "zeta", 0x03b6 },
321  { "zwj", 0x200d },
322  { "zwnj", 0x200c }
323 };
324 
325 Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &entityStr, const QTextHtmlEntity &entity)
326 {
327  return entityStr < QLatin1String(entity.name);
328 }
329 
330 Q_STATIC_GLOBAL_OPERATOR bool operator<(const QTextHtmlEntity &entity, const QString &entityStr)
331 {
332  return QLatin1String(entity.name) < entityStr;
333 }
334 
335 static QChar resolveEntity(const QString &entity)
336 {
337  const QTextHtmlEntity *start = &entities[0];
339  const QTextHtmlEntity *e = qBinaryFind(start, end, entity);
340  if (e == end)
341  return QChar();
342  return e->code;
343 }
344 
345 static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
346  0x20ac, // 0x80
347  0x0081, // 0x81 direct mapping
348  0x201a, // 0x82
349  0x0192, // 0x83
350  0x201e, // 0x84
351  0x2026, // 0x85
352  0x2020, // 0x86
353  0x2021, // 0x87
354  0x02C6, // 0x88
355  0x2030, // 0x89
356  0x0160, // 0x8A
357  0x2039, // 0x8B
358  0x0152, // 0x8C
359  0x008D, // 0x8D direct mapping
360  0x017D, // 0x8E
361  0x008F, // 0x8F directmapping
362  0x0090, // 0x90 directmapping
363  0x2018, // 0x91
364  0x2019, // 0x92
365  0x201C, // 0x93
366  0X201D, // 0x94
367  0x2022, // 0x95
368  0x2013, // 0x96
369  0x2014, // 0x97
370  0x02DC, // 0x98
371  0x2122, // 0x99
372  0x0161, // 0x9A
373  0x203A, // 0x9B
374  0x0153, // 0x9C
375  0x009D, // 0x9D direct mapping
376  0x017E, // 0x9E
377  0x0178 // 0x9F
378 };
379 
380 // the displayMode value is according to the what are blocks in the piecetable, not
381 // what the w3c defines.
384  { "address", Html_address, QTextHtmlElement::DisplayInline },
385  { "b", Html_b, QTextHtmlElement::DisplayInline },
386  { "big", Html_big, QTextHtmlElement::DisplayInline },
388  { "body", Html_body, QTextHtmlElement::DisplayBlock },
389  { "br", Html_br, QTextHtmlElement::DisplayInline },
390  { "caption", Html_caption, QTextHtmlElement::DisplayBlock },
391  { "center", Html_center, QTextHtmlElement::DisplayBlock },
392  { "cite", Html_cite, QTextHtmlElement::DisplayInline },
393  { "code", Html_code, QTextHtmlElement::DisplayInline },
394  { "dd", Html_dd, QTextHtmlElement::DisplayBlock },
395  { "dfn", Html_dfn, QTextHtmlElement::DisplayInline },
396  { "div", Html_div, QTextHtmlElement::DisplayBlock },
397  { "dl", Html_dl, QTextHtmlElement::DisplayBlock },
398  { "dt", Html_dt, QTextHtmlElement::DisplayBlock },
399  { "em", Html_em, QTextHtmlElement::DisplayInline },
400  { "font", Html_font, QTextHtmlElement::DisplayInline },
401  { "h1", Html_h1, QTextHtmlElement::DisplayBlock },
402  { "h2", Html_h2, QTextHtmlElement::DisplayBlock },
403  { "h3", Html_h3, QTextHtmlElement::DisplayBlock },
404  { "h4", Html_h4, QTextHtmlElement::DisplayBlock },
405  { "h5", Html_h5, QTextHtmlElement::DisplayBlock },
406  { "h6", Html_h6, QTextHtmlElement::DisplayBlock },
408  { "hr", Html_hr, QTextHtmlElement::DisplayBlock },
409  { "html", Html_html, QTextHtmlElement::DisplayInline },
410  { "i", Html_i, QTextHtmlElement::DisplayInline },
411  { "img", Html_img, QTextHtmlElement::DisplayInline },
412  { "kbd", Html_kbd, QTextHtmlElement::DisplayInline },
413  { "li", Html_li, QTextHtmlElement::DisplayBlock },
414  { "link", Html_link, QTextHtmlElement::DisplayNone },
415  { "meta", Html_meta, QTextHtmlElement::DisplayNone },
416  { "nobr", Html_nobr, QTextHtmlElement::DisplayInline },
417  { "ol", Html_ol, QTextHtmlElement::DisplayBlock },
418  { "p", Html_p, QTextHtmlElement::DisplayBlock },
419  { "pre", Html_pre, QTextHtmlElement::DisplayBlock },
420  { "qt", Html_body /*deliberate mapping*/, QTextHtmlElement::DisplayBlock },
421  { "s", Html_s, QTextHtmlElement::DisplayInline },
422  { "samp", Html_samp, QTextHtmlElement::DisplayInline },
423  { "script", Html_script, QTextHtmlElement::DisplayNone },
424  { "small", Html_small, QTextHtmlElement::DisplayInline },
425  { "span", Html_span, QTextHtmlElement::DisplayInline },
426  { "strong", Html_strong, QTextHtmlElement::DisplayInline },
427  { "style", Html_style, QTextHtmlElement::DisplayNone },
428  { "sub", Html_sub, QTextHtmlElement::DisplayInline },
429  { "sup", Html_sup, QTextHtmlElement::DisplayInline },
431  { "tbody", Html_tbody, QTextHtmlElement::DisplayTable },
432  { "td", Html_td, QTextHtmlElement::DisplayBlock },
433  { "tfoot", Html_tfoot, QTextHtmlElement::DisplayTable },
434  { "th", Html_th, QTextHtmlElement::DisplayBlock },
435  { "thead", Html_thead, QTextHtmlElement::DisplayTable },
436  { "title", Html_title, QTextHtmlElement::DisplayNone },
437  { "tr", Html_tr, QTextHtmlElement::DisplayTable },
438  { "tt", Html_tt, QTextHtmlElement::DisplayInline },
439  { "u", Html_u, QTextHtmlElement::DisplayInline },
440  { "ul", Html_ul, QTextHtmlElement::DisplayBlock },
441  { "var", Html_var, QTextHtmlElement::DisplayInline },
442 };
443 
444 
446 {
447  return str < QLatin1String(e.name);
448 }
449 
451 {
452  return QLatin1String(e.name) < str;
453 }
454 
455 static const QTextHtmlElement *lookupElementHelper(const QString &element)
456 {
457  const QTextHtmlElement *start = &elements[0];
458  const QTextHtmlElement *end = &elements[Html_NumElements];
459  const QTextHtmlElement *e = qBinaryFind(start, end, element);
460  if (e == end)
461  return 0;
462  return e;
463 }
464 
466 {
467  const QTextHtmlElement *e = lookupElementHelper(element);
468  if (!e)
469  return -1;
470  return e->id;
471 }
472 
473 // quotes newlines as "\\n"
474 static QString quoteNewline(const QString &s)
475 {
476  QString n = s;
477  n.replace(QLatin1Char('\n'), QLatin1String("\\n"));
478  return n;
479 }
480 
482  : parent(0), id(Html_unknown),
483  cssFloat(QTextFrameFormat::InFlow), hasOwnListStyle(false),
484  hasCssListIndent(false), isEmptyParagraph(false), isTextFrame(false), isRootFrame(false),
485  displayMode(QTextHtmlElement::DisplayInline), hasHref(false),
486  listStyle(QTextListFormat::ListStyleUndefined), imageWidth(-1), imageHeight(-1), tableBorder(0),
487  tableCellRowSpan(1), tableCellColSpan(1), tableCellSpacing(2), tableCellPadding(0),
488  borderBrush(Qt::darkGray), borderStyle(QTextFrameFormat::BorderStyle_Outset),
489  userState(-1), cssListIndent(0), wsm(WhiteSpaceModeUndefined)
490 {
495 }
496 
498 {
499  for (int i = 0; i < count(); ++i) {
500  qDebug().nospace() << qPrintable(QString(depth(i)*4, QLatin1Char(' ')))
501  << qPrintable(at(i).tag) << ':'
502  << quoteNewline(at(i).text);
503  ;
504  }
505 }
506 
508 {
509  QTextHtmlParserNode *lastNode = &nodes.last();
510  QTextHtmlParserNode *newNode = 0;
511 
512  bool reuseLastNode = true;
513 
514  if (nodes.count() == 1) {
515  reuseLastNode = false;
516  } else if (lastNode->tag.isEmpty()) {
517 
518  if (lastNode->text.isEmpty()) {
519  reuseLastNode = true;
520  } else { // last node is a text node (empty tag) with some text
521 
522  if (lastNode->text.length() == 1 && lastNode->text.at(0).isSpace()) {
523 
524  int lastSibling = count() - 2;
525  while (lastSibling
526  && at(lastSibling).parent != lastNode->parent
527  && at(lastSibling).displayMode == QTextHtmlElement::DisplayInline) {
528  lastSibling = at(lastSibling).parent;
529  }
530 
531  if (at(lastSibling).displayMode == QTextHtmlElement::DisplayInline) {
532  reuseLastNode = false;
533  } else {
534  reuseLastNode = true;
535  }
536  } else {
537  // text node with real (non-whitespace) text -> nothing to re-use
538  reuseLastNode = false;
539  }
540 
541  }
542 
543  } else {
544  // last node had a proper tag -> nothing to re-use
545  reuseLastNode = false;
546  }
547 
548  if (reuseLastNode) {
549  newNode = lastNode;
550  newNode->tag.clear();
551  newNode->text.clear();
552  newNode->id = Html_unknown;
553  } else {
554  nodes.resize(nodes.size() + 1);
555  newNode = &nodes.last();
556  }
557 
558  newNode->parent = parent;
559  return newNode;
560 }
561 
562 void QTextHtmlParser::parse(const QString &text, const QTextDocument *_resourceProvider)
563 {
564  nodes.clear();
565  nodes.resize(1);
566  txt = text;
567  pos = 0;
568  len = txt.length();
569  textEditMode = false;
570  resourceProvider = _resourceProvider;
571  parse();
572  //dumpHtml();
573 }
574 
575 int QTextHtmlParser::depth(int i) const
576 {
577  int depth = 0;
578  while (i) {
579  i = at(i).parent;
580  ++depth;
581  }
582  return depth;
583 }
584 
585 int QTextHtmlParser::margin(int i, int mar) const {
586  int m = 0;
587  const QTextHtmlParserNode *node;
588  if (mar == MarginLeft
589  || mar == MarginRight) {
590  while (i) {
591  node = &at(i);
592  if (!node->isBlock() && node->id != Html_table)
593  break;
594  if (node->isTableCell())
595  break;
596  m += node->margin[mar];
597  i = node->parent;
598  }
599  }
600  return m;
601 }
602 
604 {
605  if (!i)
606  return 0;
607  return at(i).margin[MarginTop];
608 }
609 
611 {
612  if (!i)
613  return 0;
614  return at(i).margin[MarginBottom];
615 }
616 
618 {
619  while (pos < len && txt.at(pos).isSpace() && txt.at(pos) != QChar::ParagraphSeparator)
620  pos++;
621 }
622 
624 {
625  while (pos < len) {
626  QChar c = txt.at(pos++);
627  if (c == QLatin1Char('<')) {
628  parseTag();
629  } else if (c == QLatin1Char('&')) {
630  nodes.last().text += parseEntity();
631  } else {
632  nodes.last().text += c;
633  }
634  }
635 }
636 
637 // parses a tag after "<"
639 {
640  eatSpace();
641 
642  // handle comments and other exclamation mark declarations
643  if (hasPrefix(QLatin1Char('!'))) {
644  parseExclamationTag();
645  if (nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePre
646  && nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePreWrap
647  && !textEditMode)
648  eatSpace();
649  return;
650  }
651 
652  // if close tag just close
653  if (hasPrefix(QLatin1Char('/'))) {
654  if (nodes.last().id == Html_style) {
655 #ifndef QT_NO_CSSPARSER
656  QCss::Parser parser(nodes.last().text);
657  QCss::StyleSheet sheet;
659  parser.parse(&sheet, Qt::CaseInsensitive);
660  inlineStyleSheets.append(sheet);
661  resolveStyleSheetImports(sheet);
662 #endif
663  }
664  parseCloseTag();
665  return;
666  }
667 
668  int p = last();
669  while (p && at(p).tag.size() == 0)
670  p = at(p).parent;
671 
672  QTextHtmlParserNode *node = newNode(p);
673 
674  // parse tag name
675  node->tag = parseWord().toLower();
676 
677  const QTextHtmlElement *elem = lookupElementHelper(node->tag);
678  if (elem) {
679  node->id = elem->id;
680  node->displayMode = elem->displayMode;
681  } else {
682  node->id = Html_unknown;
683  }
684 
685  node->attributes.clear();
686  // _need_ at least one space after the tag name, otherwise there can't be attributes
687  if (pos < len && txt.at(pos).isSpace())
688  node->attributes = parseAttributes();
689 
690  // resolveParent() may have to change the order in the tree and
691  // insert intermediate nodes for buggy HTML, so re-initialize the 'node'
692  // pointer through the return value
693  node = resolveParent();
694  resolveNode();
695 
696  const int nodeIndex = nodes.count() - 1; // this new node is always the last
697 #ifndef QT_NO_CSSPARSER
698  node->applyCssDeclarations(declarationsForNode(nodeIndex), resourceProvider);
699 #endif
700  applyAttributes(node->attributes);
701 
702  // finish tag
703  bool tagClosed = false;
704  while (pos < len && txt.at(pos) != QLatin1Char('>')) {
705  if (txt.at(pos) == QLatin1Char('/'))
706  tagClosed = true;
707 
708  pos++;
709  }
710  pos++;
711 
712  // in a white-space preserving environment strip off a initial newline
713  // since the element itself already generates a newline
716  && node->isBlock()) {
717  if (pos < len - 1 && txt.at(pos) == QLatin1Char('\n'))
718  ++pos;
719  }
720 
721  if (node->mayNotHaveChildren() || tagClosed) {
722  newNode(node->parent);
723  resolveNode();
724  }
725 }
726 
727 // parses a tag beginning with "/"
729 {
730  ++pos;
731  QString tag = parseWord().toLower().trimmed();
732  while (pos < len) {
733  QChar c = txt.at(pos++);
734  if (c == QLatin1Char('>'))
735  break;
736  }
737 
738  // find corresponding open node
739  int p = last();
740  if (p > 0
741  && at(p - 1).tag == tag
742  && at(p - 1).mayNotHaveChildren())
743  p--;
744 
745  while (p && at(p).tag != tag)
746  p = at(p).parent;
747 
748  // simply ignore the tag if we can't find
749  // a corresponding open node, for broken
750  // html such as <font>blah</font></font>
751  if (!p)
752  return;
753 
754  // in a white-space preserving environment strip off a trailing newline
755  // since the closing of the opening block element will automatically result
756  // in a new block for elements following the <pre>
757  // ...foo\n</pre><p>blah -> foo</pre><p>blah
760  && at(p).isBlock()) {
761  if (at(last()).text.endsWith(QLatin1Char('\n')))
762  nodes[last()].text.chop(1);
763  }
764 
765  newNode(at(p).parent);
766  resolveNode();
767 }
768 
769 // parses a tag beginning with "!"
771 {
772  ++pos;
773  if (hasPrefix(QLatin1Char('-'),1) && hasPrefix(QLatin1Char('-'),2)) {
774  pos += 3;
775  // eat comments
776  int end = txt.indexOf(QLatin1String("-->"), pos);
777  pos = (end >= 0 ? end + 3 : len);
778  } else {
779  // eat internal tags
780  while (pos < len) {
781  QChar c = txt.at(pos++);
782  if (c == QLatin1Char('>'))
783  break;
784  }
785  }
786 }
787 
788 // parses an entity after "&", and returns it
790 {
791  int recover = pos;
792  QString entity;
793  while (pos < len) {
794  QChar c = txt.at(pos++);
795  if (c.isSpace() || pos - recover > 9) {
796  goto error;
797  }
798  if (c == QLatin1Char(';'))
799  break;
800  entity += c;
801  }
802  {
803  QChar resolved = resolveEntity(entity);
804  if (!resolved.isNull())
805  return QString(resolved);
806  }
807  if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) {
808  entity.remove(0, 1); // removing leading #
809 
810  int base = 10;
811  bool ok = false;
812 
813  if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
814  entity.remove(0, 1);
815  base = 16;
816  }
817 
818  uint uc = entity.toUInt(&ok, base);
819  if (ok) {
820  if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0])))
821  uc = windowsLatin1ExtendedCharacters[uc - 0x80];
822  QString str;
823  if (QChar::requiresSurrogates(uc)) {
824  str += QChar(QChar::highSurrogate(uc));
825  str += QChar(QChar::lowSurrogate(uc));
826  } else {
827  str = QChar(uc);
828  }
829  return str;
830  }
831  }
832 error:
833  pos = recover;
834  return QLatin1String("&");
835 }
836 
837 // parses one word, possibly quoted, and returns it
839 {
840  QString word;
841  if (hasPrefix(QLatin1Char('\"'))) { // double quotes
842  ++pos;
843  while (pos < len) {
844  QChar c = txt.at(pos++);
845  if (c == QLatin1Char('\"'))
846  break;
847  else if (c == QLatin1Char('&'))
848  word += parseEntity();
849  else
850  word += c;
851  }
852  } else if (hasPrefix(QLatin1Char('\''))) { // single quotes
853  ++pos;
854  while (pos < len) {
855  QChar c = txt.at(pos++);
856  if (c == QLatin1Char('\''))
857  break;
858  else
859  word += c;
860  }
861  } else { // normal text
862  while (pos < len) {
863  QChar c = txt.at(pos++);
864  if (c == QLatin1Char('>')
865  || (c == QLatin1Char('/') && hasPrefix(QLatin1Char('>'), 1))
866  || c == QLatin1Char('<')
867  || c == QLatin1Char('=')
868  || c.isSpace()) {
869  --pos;
870  break;
871  }
872  if (c == QLatin1Char('&'))
873  word += parseEntity();
874  else
875  word += c;
876  }
877  }
878  return word;
879 }
880 
881 // gives the new node the right parent
883 {
884  QTextHtmlParserNode *node = &nodes.last();
885 
886  int p = node->parent;
887 
888  // Excel gives us buggy HTML with just tr without surrounding table tags
889  // or with just td tags
890 
891  if (node->id == Html_td) {
892  int n = p;
893  while (n && at(n).id != Html_tr)
894  n = at(n).parent;
895 
896  if (!n) {
897  nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
898  nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
899 
900  QTextHtmlParserNode *table = &nodes[nodes.count() - 3];
901  table->parent = p;
902  table->id = Html_table;
903  table->tag = QLatin1String("table");
904  table->children.append(nodes.count() - 2); // add row as child
905 
906  QTextHtmlParserNode *row = &nodes[nodes.count() - 2];
907  row->parent = nodes.count() - 3; // table as parent
908  row->id = Html_tr;
909  row->tag = QLatin1String("tr");
910 
911  p = nodes.count() - 2;
912  node = &nodes.last(); // re-initialize pointer
913  }
914  }
915 
916  if (node->id == Html_tr) {
917  int n = p;
918  while (n && at(n).id != Html_table)
919  n = at(n).parent;
920 
921  if (!n) {
922  nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
923  QTextHtmlParserNode *table = &nodes[nodes.count() - 2];
924  table->parent = p;
925  table->id = Html_table;
926  table->tag = QLatin1String("table");
927  p = nodes.count() - 2;
928  node = &nodes.last(); // re-initialize pointer
929  }
930  }
931 
932  // permit invalid html by letting block elements be children
933  // of inline elements with the exception of paragraphs:
934  //
935  // a new paragraph closes parent inline elements (while loop),
936  // unless they themselves are children of a non-paragraph block
937  // element (if statement)
938  //
939  // For example:
940  //
941  // <body><p><b>Foo<p>Bar <-- second <p> implicitly closes <b> that
942  // belongs to the first <p>. The self-nesting
943  // check further down prevents the second <p>
944  // from nesting into the first one then.
945  // so Bar is not bold.
946  //
947  // <body><b><p>Foo <-- Foo should be bold.
948  //
949  // <body><b><p>Foo<p>Bar <-- Foo and Bar should be bold.
950  //
951  if (node->id == Html_p) {
952  while (p && !at(p).isBlock())
953  p = at(p).parent;
954 
955  if (!p || at(p).id != Html_p)
956  p = node->parent;
957  }
958 
959  // some elements are not self nesting
960  if (node->id == at(p).id
961  && node->isNotSelfNesting())
962  p = at(p).parent;
963 
964  // some elements are not allowed in certain contexts
965  while ((p && !node->allowedInContext(at(p).id))
966  // ### make new styles aware of empty tags
967  || at(p).mayNotHaveChildren()
968  ) {
969  p = at(p).parent;
970  }
971 
972  node->parent = p;
973 
974  // makes it easier to traverse the tree, later
975  nodes[p].children.append(nodes.count() - 1);
976  return node;
977 }
978 
979 // sets all properties on the new node
981 {
982  QTextHtmlParserNode *node = &nodes.last();
983  const QTextHtmlParserNode *parent = &nodes.at(node->parent);
984  node->initializeProperties(parent, this);
985 }
986 
988 {
989  if (!isListStart())
990  return false;
991 
992  int p = parent;
993  while (p) {
994  if (parser->at(p).isListStart())
995  return true;
996  p = parser->at(p).parent;
997  }
998  return false;
999 }
1000 
1002 {
1003  // inherit properties from parent element
1004  charFormat = parent->charFormat;
1005 
1006  if (id == Html_html)
1010 
1013 
1014  if (parent->id != Html_table || id == Html_caption) {
1017  else
1019  }
1020  // we don't paint per-row background colors, yet. so as an
1021  // exception inherit the background color here
1022  // we also inherit the background between inline elements
1023  if ((parent->id != Html_tr || !isTableCell())
1026  }
1027 
1028  listStyle = parent->listStyle;
1029  // makes no sense to inherit that property, a named anchor is a single point
1030  // in the document, which is set by the DocumentFragment
1032  wsm = parent->wsm;
1033 
1034  // initialize remaining properties
1040 
1041  for (int i = 0; i < 4; ++i)
1042  padding[i] = -1;
1043 
1044  // set element specific attributes
1045  switch (id) {
1046  case Html_a:
1047  charFormat.setAnchor(true);
1048  for (int i = 0; i < attributes.count(); i += 2) {
1049  const QString key = attributes.at(i);
1050  if (key.compare(QLatin1String("href"), Qt::CaseInsensitive) == 0
1051  && !attributes.at(i + 1).isEmpty()) {
1052  hasHref = true;
1055  }
1056  }
1057 
1058  break;
1059  case Html_em:
1060  case Html_i:
1061  case Html_cite:
1062  case Html_address:
1063  case Html_var:
1064  case Html_dfn:
1065  charFormat.setFontItalic(true);
1066  break;
1067  case Html_big:
1069  break;
1070  case Html_small:
1072  break;
1073  case Html_strong:
1074  case Html_b:
1076  break;
1077  case Html_h1:
1082  break;
1083  case Html_h2:
1088  break;
1089  case Html_h3:
1094  break;
1095  case Html_h4:
1100  break;
1101  case Html_h5:
1106  break;
1107  case Html_p:
1110  break;
1111  case Html_center:
1113  break;
1114  case Html_ul:
1116  // nested lists don't have margins, except for the toplevel one
1117  if (!isNestedList(parser)) {
1120  }
1121  // no left margin as we use indenting instead
1122  break;
1123  case Html_ol:
1125  // nested lists don't have margins, except for the toplevel one
1126  if (!isNestedList(parser)) {
1129  }
1130  // no left margin as we use indenting instead
1131  break;
1132  case Html_code:
1133  case Html_tt:
1134  case Html_kbd:
1135  case Html_samp:
1136  charFormat.setFontFamily(QString::fromLatin1("Courier New,courier"));
1137  // <tt> uses a fixed font, so set the property
1139  break;
1140  case Html_br:
1143  break;
1144  // ##### sub / sup
1145  case Html_pre:
1146  charFormat.setFontFamily(QString::fromLatin1("Courier New,courier"));
1147  wsm = WhiteSpacePre;
1150  // <pre> uses a fixed font
1152  break;
1153  case Html_blockquote:
1158  break;
1159  case Html_dl:
1162  break;
1163  case Html_dd:
1165  break;
1166  case Html_u:
1168  break;
1169  case Html_s:
1171  break;
1172  case Html_nobr:
1174  break;
1175  case Html_th:
1178  break;
1179  case Html_td:
1181  break;
1182  case Html_sub:
1184  break;
1185  case Html_sup:
1187  break;
1188  default: break;
1189  }
1190 }
1191 
1192 #ifndef QT_NO_CSSPARSER
1194 {
1195  for (int i = 0; i < cssValues.count(); ++i) {
1196  if (cssValues.at(i).type == QCss::Value::KnownIdentifier) {
1197  switch (static_cast<QCss::KnownValue>(cssValues.at(i).variant.toInt())) {
1206  default: break;
1207  }
1208  }
1209  }
1210  // allow individual list items to override the style
1211  if (id == Html_li && hasOwnListStyle)
1213 }
1214 
1216 {
1217  QCss::ValueExtractor extractor(declarations);
1218  extractor.extractBox(margin, padding);
1219 
1220  for (int i = 0; i < declarations.count(); ++i) {
1221  const QCss::Declaration &decl = declarations.at(i);
1222  if (decl.d->values.isEmpty()) continue;
1223 
1224  QCss::KnownValue identifier = QCss::UnknownValue;
1225  if (decl.d->values.first().type == QCss::Value::KnownIdentifier)
1226  identifier = static_cast<QCss::KnownValue>(decl.d->values.first().variant.toInt());
1227 
1228  switch (decl.d->propertyId) {
1229  case QCss::BorderColor: borderBrush = QBrush(decl.colorValue()); break;
1230  case QCss::BorderStyles:
1232  borderStyle = static_cast<QTextFrameFormat::BorderStyle>(decl.styleValue() - 1);
1233  break;
1234  case QCss::BorderWidth:
1235  tableBorder = extractor.lengthValue(decl);
1236  break;
1237  case QCss::Color: charFormat.setForeground(decl.colorValue()); break;
1238  case QCss::Float:
1240  switch (identifier) {
1243  default: break;
1244  }
1245  break;
1246  case QCss::QtBlockIndent:
1247  blockFormat.setIndent(decl.d->values.first().variant.toInt());
1248  break;
1249  case QCss::LineHeight: {
1250  qreal lineHeight;
1251  if (decl.realValue(&lineHeight, "px")) {
1253  } else {
1254  bool ok;
1255  QString value = decl.d->values.first().toString();
1256  lineHeight = value.toDouble(&ok);
1257  if (ok)
1259  else
1261  }
1262  break; }
1263  case QCss::TextIndent: {
1264  qreal indent = 0;
1265  if (decl.realValue(&indent, "px"))
1266  blockFormat.setTextIndent(indent);
1267  break; }
1268  case QCss::QtListIndent:
1269  if (decl.intValue(&cssListIndent))
1270  hasCssListIndent = true;
1271  break;
1272  case QCss::QtParagraphType:
1273  if (decl.d->values.first().variant.toString().compare(QLatin1String("empty"), Qt::CaseInsensitive) == 0)
1274  isEmptyParagraph = true;
1275  break;
1276  case QCss::QtTableType:
1277  if (decl.d->values.first().variant.toString().compare(QLatin1String("frame"), Qt::CaseInsensitive) == 0)
1278  isTextFrame = true;
1279  else if (decl.d->values.first().variant.toString().compare(QLatin1String("root"), Qt::CaseInsensitive) == 0) {
1280  isTextFrame = true;
1281  isRootFrame = true;
1282  }
1283  break;
1284  case QCss::QtUserState:
1285  userState = decl.d->values.first().variant.toInt();
1286  break;
1287  case QCss::Whitespace:
1288  switch (identifier) {
1293  default: break;
1294  }
1295  break;
1297  switch (identifier) {
1304  }
1305  break;
1306  case QCss::PageBreakBefore:
1307  switch (identifier) {
1309  case QCss::Value_Auto: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() & ~QTextFormat::PageBreak_AlwaysBefore); break;
1310  default: break;
1311  }
1312  break;
1313  case QCss::PageBreakAfter:
1314  switch (identifier) {
1316  case QCss::Value_Auto: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() & ~QTextFormat::PageBreak_AlwaysAfter); break;
1317  default: break;
1318  }
1319  break;
1321  switch (identifier) {
1329  default: break;
1330  }
1331  break;
1332  case QCss::ListStyleType:
1333  case QCss::ListStyle:
1334  setListStyle(decl.d->values);
1335  break;
1337  textListNumberPrefix = decl.d->values.first().variant.toString();
1338  break;
1340  textListNumberSuffix = decl.d->values.first().variant.toString();
1341  break;
1342  default: break;
1343  }
1344  }
1345 
1346  QFont f;
1347  int adjustment = -255;
1348  extractor.extractFont(&f, &adjustment);
1349  if (f.resolve() & QFont::SizeResolved) {
1350  if (f.pointSize() > 0) {
1352  } else if (f.pixelSize() > 0) {
1354  }
1355  }
1356  if (f.resolve() & QFont::StyleResolved)
1358 
1359  if (f.resolve() & QFont::WeightResolved)
1361 
1362  if (f.resolve() & QFont::FamilyResolved)
1364 
1367 
1368  if (f.resolve() & QFont::OverlineResolved)
1370 
1373 
1376 
1377  if (adjustment >= -1)
1379 
1380  {
1381  Qt::Alignment ignoredAlignment;
1382  QCss::Repeat ignoredRepeat;
1383  QString bgImage;
1384  QBrush bgBrush;
1385  QCss::Origin ignoredOrigin, ignoredClip;
1386  QCss::Attachment ignoredAttachment;
1387  extractor.extractBackground(&bgBrush, &bgImage, &ignoredRepeat, &ignoredAlignment,
1388  &ignoredOrigin, &ignoredAttachment, &ignoredClip);
1389 
1390  if (!bgImage.isEmpty() && resourceProvider) {
1391  applyBackgroundImage(bgImage, resourceProvider);
1392  } else if (bgBrush.style() != Qt::NoBrush) {
1393  charFormat.setBackground(bgBrush);
1394  }
1395  }
1396 }
1397 
1398 #endif // QT_NO_CSSPARSER
1399 
1400 void QTextHtmlParserNode::applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider)
1401 {
1402  if (!url.isEmpty() && resourceProvider) {
1403  QVariant val = resourceProvider->resource(QTextDocument::ImageResource, url);
1404 
1405  if (qApp->thread() != QThread::currentThread()) {
1406  // must use images in non-GUI threads
1407  if (val.type() == QVariant::Image) {
1408  QImage image = qvariant_cast<QImage>(val);
1409  charFormat.setBackground(image);
1410  } else if (val.type() == QVariant::ByteArray) {
1411  QImage image;
1412  if (image.loadFromData(val.toByteArray())) {
1413  charFormat.setBackground(image);
1414  }
1415  }
1416  } else {
1417  if (val.type() == QVariant::Image || val.type() == QVariant::Pixmap) {
1418  charFormat.setBackground(qvariant_cast<QPixmap>(val));
1419  } else if (val.type() == QVariant::ByteArray) {
1420  QPixmap pm;
1421  if (pm.loadFromData(val.toByteArray())) {
1423  }
1424  }
1425  }
1426  }
1427  if (!url.isEmpty())
1429 }
1430 
1432 {
1433  for (int i = 0; i < text.count(); ++i)
1434  if (!text.at(i).isSpace() || text.at(i) == QChar::LineSeparator)
1435  return false;
1436  return true;
1437 }
1438 
1439 static bool setIntAttribute(int *destination, const QString &value)
1440 {
1441  bool ok = false;
1442  int val = value.toInt(&ok);
1443  if (ok)
1444  *destination = val;
1445 
1446  return ok;
1447 }
1448 
1449 static bool setFloatAttribute(qreal *destination, const QString &value)
1450 {
1451  bool ok = false;
1452  qreal val = value.toDouble(&ok);
1453  if (ok)
1454  *destination = val;
1455 
1456  return ok;
1457 }
1458 
1460 {
1461  bool ok = false;
1462  qreal realVal = value.toDouble(&ok);
1463  if (ok) {
1464  *width = QTextLength(QTextLength::FixedLength, realVal);
1465  } else {
1466  value = value.trimmed();
1467  if (!value.isEmpty() && value.endsWith(QLatin1Char('%'))) {
1468  value.chop(1);
1469  realVal = value.toDouble(&ok);
1470  if (ok)
1471  *width = QTextLength(QTextLength::PercentageLength, realVal);
1472  }
1473  }
1474 }
1475 
1476 #ifndef QT_NO_CSSPARSER
1477 void QTextHtmlParserNode::parseStyleAttribute(const QString &value, const QTextDocument *resourceProvider)
1478 {
1479  QString css = value;
1480  css.prepend(QLatin1String("* {"));
1481  css.append(QLatin1Char('}'));
1482  QCss::Parser parser(css);
1483  QCss::StyleSheet sheet;
1484  parser.parse(&sheet, Qt::CaseInsensitive);
1485  if (sheet.styleRules.count() != 1) return;
1486  applyCssDeclarations(sheet.styleRules.at(0).declarations, resourceProvider);
1487 }
1488 #endif
1489 
1491 {
1492  QStringList attrs;
1493 
1494  while (pos < len) {
1495  eatSpace();
1496  if (hasPrefix(QLatin1Char('>')) || hasPrefix(QLatin1Char('/')))
1497  break;
1498  QString key = parseWord().toLower();
1499  QString value = QLatin1String("1");
1500  if (key.size() == 0)
1501  break;
1502  eatSpace();
1503  if (hasPrefix(QLatin1Char('='))){
1504  pos++;
1505  eatSpace();
1506  value = parseWord();
1507  }
1508  if (value.size() == 0)
1509  continue;
1510  attrs << key << value;
1511  }
1512 
1513  return attrs;
1514 }
1515 
1517 {
1518  // local state variable for qt3 textedit mode
1519  bool seenQt3Richtext = false;
1520  QString linkHref;
1521  QString linkType;
1522 
1523  if (attributes.count() % 2 == 1)
1524  return;
1525 
1526  QTextHtmlParserNode *node = &nodes.last();
1527 
1528  for (int i = 0; i < attributes.count(); i += 2) {
1529  QString key = attributes.at(i);
1530  QString value = attributes.at(i + 1);
1531 
1532  switch (node->id) {
1533  case Html_font:
1534  // the infamous font tag
1535  if (key == QLatin1String("size") && value.size()) {
1536  int n = value.toInt();
1537  if (value.at(0) != QLatin1Char('+') && value.at(0) != QLatin1Char('-'))
1538  n -= 3;
1540  } else if (key == QLatin1String("face")) {
1541  node->charFormat.setFontFamily(value);
1542  } else if (key == QLatin1String("color")) {
1543  QColor c; c.setNamedColor(value);
1544  if (!c.isValid())
1545  qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1546  node->charFormat.setForeground(c);
1547  }
1548  break;
1549  case Html_ol:
1550  case Html_ul:
1551  if (key == QLatin1String("type")) {
1552  node->hasOwnListStyle = true;
1553  if (value == QLatin1String("1")) {
1555  } else if (value == QLatin1String("a")) {
1557  } else if (value == QLatin1String("A")) {
1559  } else if (value == QLatin1String("i")) {
1561  } else if (value == QLatin1String("I")) {
1563  } else {
1564  value = value.toLower();
1565  if (value == QLatin1String("square"))
1567  else if (value == QLatin1String("disc"))
1569  else if (value == QLatin1String("circle"))
1571  }
1572  }
1573  break;
1574  case Html_a:
1575  if (key == QLatin1String("href"))
1576  node->charFormat.setAnchorHref(value);
1577  else if (key == QLatin1String("name"))
1578  node->charFormat.setAnchorName(value);
1579  break;
1580  case Html_img:
1581  if (key == QLatin1String("src") || key == QLatin1String("source")) {
1582  node->imageName = value;
1583  } else if (key == QLatin1String("width")) {
1584  node->imageWidth = -2; // register that there is a value for it.
1585  setFloatAttribute(&node->imageWidth, value);
1586  } else if (key == QLatin1String("height")) {
1587  node->imageHeight = -2; // register that there is a value for it.
1588  setFloatAttribute(&node->imageHeight, value);
1589  }
1590  break;
1591  case Html_tr:
1592  case Html_body:
1593  if (key == QLatin1String("bgcolor")) {
1594  QColor c; c.setNamedColor(value);
1595  if (!c.isValid())
1596  qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1597  node->charFormat.setBackground(c);
1598  } else if (key == QLatin1String("background")) {
1599  node->applyBackgroundImage(value, resourceProvider);
1600  }
1601  break;
1602  case Html_th:
1603  case Html_td:
1604  if (key == QLatin1String("width")) {
1605  setWidthAttribute(&node->width, value);
1606  } else if (key == QLatin1String("bgcolor")) {
1607  QColor c; c.setNamedColor(value);
1608  if (!c.isValid())
1609  qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1610  node->charFormat.setBackground(c);
1611  } else if (key == QLatin1String("background")) {
1612  node->applyBackgroundImage(value, resourceProvider);
1613  } else if (key == QLatin1String("rowspan")) {
1614  if (setIntAttribute(&node->tableCellRowSpan, value))
1615  node->tableCellRowSpan = qMax(1, node->tableCellRowSpan);
1616  } else if (key == QLatin1String("colspan")) {
1617  if (setIntAttribute(&node->tableCellColSpan, value))
1618  node->tableCellColSpan = qMax(1, node->tableCellColSpan);
1619  }
1620  break;
1621  case Html_table:
1622  if (key == QLatin1String("border")) {
1623  setFloatAttribute(&node->tableBorder, value);
1624  } else if (key == QLatin1String("bgcolor")) {
1625  QColor c; c.setNamedColor(value);
1626  if (!c.isValid())
1627  qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1628  node->charFormat.setBackground(c);
1629  } else if (key == QLatin1String("background")) {
1630  node->applyBackgroundImage(value, resourceProvider);
1631  } else if (key == QLatin1String("cellspacing")) {
1632  setFloatAttribute(&node->tableCellSpacing, value);
1633  } else if (key == QLatin1String("cellpadding")) {
1634  setFloatAttribute(&node->tableCellPadding, value);
1635  } else if (key == QLatin1String("width")) {
1636  setWidthAttribute(&node->width, value);
1637  } else if (key == QLatin1String("height")) {
1638  setWidthAttribute(&node->height, value);
1639  }
1640  break;
1641  case Html_meta:
1642  if (key == QLatin1String("name")
1643  && value == QLatin1String("qrichtext")) {
1644  seenQt3Richtext = true;
1645  }
1646 
1647  if (key == QLatin1String("content")
1648  && value == QLatin1String("1")
1649  && seenQt3Richtext) {
1650 
1651  textEditMode = true;
1652  }
1653  break;
1654  case Html_hr:
1655  if (key == QLatin1String("width"))
1656  setWidthAttribute(&node->width, value);
1657  break;
1658  case Html_link:
1659  if (key == QLatin1String("href"))
1660  linkHref = value;
1661  else if (key == QLatin1String("type"))
1662  linkType = value;
1663  break;
1664  default:
1665  break;
1666  }
1667 
1668  if (key == QLatin1String("style")) {
1669 #ifndef QT_NO_CSSPARSER
1670  node->parseStyleAttribute(value, resourceProvider);
1671 #endif
1672  } else if (key == QLatin1String("align")) {
1673  value = value.toLower();
1674  bool alignmentSet = true;
1675 
1676  if (value == QLatin1String("left"))
1678  else if (value == QLatin1String("right"))
1680  else if (value == QLatin1String("center"))
1682  else if (value == QLatin1String("justify"))
1684  else
1685  alignmentSet = false;
1686 
1687  if (node->id == Html_img) {
1688  // HTML4 compat
1689  if (alignmentSet) {
1690  if (node->blockFormat.alignment() & Qt::AlignLeft)
1692  else if (node->blockFormat.alignment() & Qt::AlignRight)
1694  } else if (value == QLatin1String("middle")) {
1696  } else if (value == QLatin1String("top")) {
1698  }
1699  }
1700  } else if (key == QLatin1String("valign")) {
1701  value = value.toLower();
1702  if (value == QLatin1String("top"))
1704  else if (value == QLatin1String("middle"))
1706  else if (value == QLatin1String("bottom"))
1708  } else if (key == QLatin1String("dir")) {
1709  value = value.toLower();
1710  if (value == QLatin1String("ltr"))
1712  else if (value == QLatin1String("rtl"))
1714  } else if (key == QLatin1String("title")) {
1715  node->charFormat.setToolTip(value);
1716  } else if (key == QLatin1String("id")) {
1717  node->charFormat.setAnchor(true);
1718  node->charFormat.setAnchorName(value);
1719  }
1720  }
1721 
1722 #ifndef QT_NO_CSSPARSER
1723  if (resourceProvider && !linkHref.isEmpty() && linkType == QLatin1String("text/css"))
1724  importStyleSheet(linkHref);
1725 #endif
1726 }
1727 
1728 #ifndef QT_NO_CSSPARSER
1730 {
1731 public:
1733  : parser(parser) { nameCaseSensitivity = Qt::CaseInsensitive; }
1734 
1735  virtual QStringList nodeNames(NodePtr node) const;
1736  virtual QString attribute(NodePtr node, const QString &name) const;
1737  virtual bool hasAttributes(NodePtr node) const;
1738  virtual bool isNullNode(NodePtr node) const;
1739  virtual NodePtr parentNode(NodePtr node) const;
1740  virtual NodePtr previousSiblingNode(NodePtr node) const;
1741  virtual NodePtr duplicateNode(NodePtr node) const;
1742  virtual void freeNode(NodePtr node) const;
1743 
1744 private:
1746 };
1747 
1749 {
1750  return QStringList(parser->at(node.id).tag.toLower());
1751 }
1752 
1753 #endif // QT_NO_CSSPARSER
1754 
1755 static inline int findAttribute(const QStringList &attributes, const QString &name)
1756 {
1757  int idx = -1;
1758  do {
1759  idx = attributes.indexOf(name, idx + 1);
1760  } while (idx != -1 && (idx % 2 == 1));
1761  return idx;
1762 }
1763 
1764 #ifndef QT_NO_CSSPARSER
1765 
1767 {
1768  const QStringList &attributes = parser->at(node.id).attributes;
1769  const int idx = findAttribute(attributes, name);
1770  if (idx == -1)
1771  return QString();
1772  return attributes.at(idx + 1);
1773 }
1774 
1776 {
1777  const QStringList &attributes = parser->at(node.id).attributes;
1778  return !attributes.isEmpty();
1779 }
1780 
1782 {
1783  return node.id == 0;
1784 }
1785 
1787 {
1788  NodePtr parent;
1789  parent.id = 0;
1790  if (node.id) {
1791  parent.id = parser->at(node.id).parent;
1792  }
1793  return parent;
1794 }
1795 
1797 {
1798  return node;
1799 }
1800 
1802 {
1803  NodePtr sibling;
1804  sibling.id = 0;
1805  if (!node.id)
1806  return sibling;
1807  int parent = parser->at(node.id).parent;
1808  if (!parent)
1809  return sibling;
1810  const int childIdx = parser->at(parent).children.indexOf(node.id);
1811  if (childIdx <= 0)
1812  return sibling;
1813  sibling.id = parser->at(parent).children.at(childIdx - 1);
1814  return sibling;
1815 }
1816 
1818 {
1819 }
1820 
1822 {
1823  for (int i = 0; i < sheet.importRules.count(); ++i) {
1824  const QCss::ImportRule &rule = sheet.importRules.at(i);
1825  if (rule.media.isEmpty()
1826  || rule.media.contains(QLatin1String("screen"), Qt::CaseInsensitive))
1827  importStyleSheet(rule.href);
1828  }
1829 }
1830 
1832 {
1833  if (!resourceProvider)
1834  return;
1835  for (int i = 0; i < externalStyleSheets.count(); ++i)
1836  if (externalStyleSheets.at(i).url == href)
1837  return;
1838 
1839  QVariant res = resourceProvider->resource(QTextDocument::StyleSheetResource, href);
1840  QString css;
1841  if (res.type() == QVariant::String) {
1842  css = res.toString();
1843  } else if (res.type() == QVariant::ByteArray) {
1844  // #### detect @charset
1845  css = QString::fromUtf8(res.toByteArray());
1846  }
1847  if (!css.isEmpty()) {
1848  QCss::Parser parser(css);
1849  QCss::StyleSheet sheet;
1850  parser.parse(&sheet, Qt::CaseInsensitive);
1851  externalStyleSheets.append(ExternalStyleSheet(href, sheet));
1852  resolveStyleSheetImports(sheet);
1853  }
1854 }
1855 
1857 {
1859 
1860  QTextHtmlStyleSelector selector(this);
1861 
1862  int idx = 0;
1863  selector.styleSheets.resize((resourceProvider ? 1 : 0)
1864  + externalStyleSheets.count()
1865  + inlineStyleSheets.count());
1866  if (resourceProvider)
1867  selector.styleSheets[idx++] = resourceProvider->docHandle()->parsedDefaultStyleSheet;
1868 
1869  for (int i = 0; i < externalStyleSheets.count(); ++i, ++idx)
1870  selector.styleSheets[idx] = externalStyleSheets.at(i).sheet;
1871 
1872  for (int i = 0; i < inlineStyleSheets.count(); ++i, ++idx)
1873  selector.styleSheets[idx] = inlineStyleSheets.at(i);
1874 
1875  selector.medium = QLatin1String("screen");
1876 
1878  n.id = node;
1879 
1880  const char *extraPseudo = 0;
1881  if (nodes.at(node).id == Html_a && nodes.at(node).hasHref)
1882  extraPseudo = "link";
1883  decls = selector.declarationsForNode(n, extraPseudo);
1884 
1885  return decls;
1886 }
1887 
1889 {
1890  while (i) {
1891  if (at(i).id == id)
1892  return true;
1893  i = at(i).parent;
1894  }
1895  return false;
1896 }
1897 
1899 #endif // QT_NO_CSSPARSER
1900 
1901 #endif // QT_NO_TEXTHTMLPARSER
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
static QString quoteNewline(const QString &s)
QColor colorValue(const QPalette &=QPalette()) const
bool mayNotHaveChildren() const
void setFontItalic(bool italic)
If italic is true, sets the text format&#39;s font to be italic; otherwise the font will be non-italic...
Definition: qtextformat.h:415
double qreal
Definition: qglobal.h:1193
The QTextListFormat class provides formatting information for lists in a QTextDocument.
Definition: qtextformat.h:642
void setNamedColor(const QString &name)
Sets the RGB value of this QColor to name, which may be in one of these formats:
Definition: qcolor.cpp:560
static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80]
unsigned char c[8]
Definition: qnumeric_p.h:62
QTextFrameFormat::BorderStyle borderStyle
static const struct QTextHtmlEntity entities[MAX_ENTITY]
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void setLineHeight(qreal height, int heightType)
Sets the line height for the paragraph to the value given by height which is dependent on heightType ...
Definition: qtextformat.h:593
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
int lengthValue(const Declaration &decl)
Definition: qcssparser.cpp:402
void setToolTip(const QString &tip)
Sets the tool tip for a fragment of text to the given text.
Definition: qtextformat.h:494
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
void setFontStrikeOut(bool strikeOut)
If strikeOut is true, sets the text format&#39;s font with strike-out enabled (with a horizontal line thr...
Definition: qtextformat.h:441
virtual NodePtr parentNode(NodePtr node) const
bool isNull() const
Returns true if the character is the Unicode character 0x0000 (&#39;\0&#39;); otherwise returns false...
Definition: qchar.h:262
QVector< int > children
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
bool underline() const
Returns true if underline has been set; otherwise returns false.
Definition: qfont.cpp:1320
void setProperty(int propertyId, const QVariant &value)
Sets the property specified by the propertyId to the given value.
#define error(msg)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
int pixelSize() const
Returns the pixel size of the font if it was set with setPixelSize().
Definition: qfont.cpp:1178
#define at(className, varName)
void setListStyle(const QVector< QCss::Value > &cssValues)
QTextHtmlStyleSelector(const QTextHtmlParser *parser)
static int findAttribute(const QStringList &attributes, const QString &name)
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
PageBreakFlags pageBreakPolicy() const
Returns the currently set page break policy for the paragraph.
Definition: qtextformat.h:608
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
Style style() const
Returns the style of the font.
Definition: qfont.cpp:1223
virtual NodePtr duplicateNode(NodePtr node) const
void setFontOverline(bool overline)
If overline is true, sets the text format&#39;s font to be overlined; otherwise the font is displayed non...
Definition: qtextformat.h:436
void setVerticalAlignment(VerticalAlignment alignment)
Sets the vertical alignment used for the characters with this format to the alignment specified...
Definition: qtextformat.h:484
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
Capitalization capitalization() const
Returns the current capitalization type of the font.
Definition: qfont.cpp:1819
QTextHtmlParserNode * newNode(int parent)
const QTextHtmlParserNode & at(int i) const
const char * name
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:295
void setTextIndent(qreal aindent)
Sets the indent for the first line in the block.
Definition: qtextformat.h:584
void setFontFixedPitch(bool fixedPitch)
If fixedPitch is true, sets the text format&#39;s font to be fixed pitch; otherwise a non-fixed pitch fon...
Definition: qtextformat.h:451
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
static QPalette palette()
Returns the application palette.
QTextHTMLElements id
void setBackground(const QBrush &brush)
Sets the brush use to paint the document&#39;s background to the brush specified.
Definition: qtextformat.h:343
The QString class provides a Unicode character string.
Definition: qstring.h:83
bool hasOnlyWhitespace() const
StyleSheetOrigin origin
Definition: qcssparser_p.h:643
virtual QString attribute(NodePtr node, const QString &name) const
Qt::Alignment alignment() const
Returns the paragraph&#39;s alignment.
Definition: qtextformat.h:561
void parseStyleAttribute(const QString &value, const QTextDocument *resourceProvider)
static const uint base
Definition: qurl.cpp:268
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QTextListFormat::Style listStyle
QVariant variant
Definition: qcssparser_p.h:372
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
const QTextHtmlParser * parser
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
bool isSpace() const
Returns true if the character is a separator character (Separator_* categories); otherwise returns fa...
Definition: qchar.cpp:609
Qt::LayoutDirection layoutDirection() const
Returns the document&#39;s layout direction.
Definition: qtextformat.h:340
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
static ushort highSurrogate(uint ucs4)
Returns the high surrogate value of a ucs4 code point.
Definition: qchar.h:303
void setFontWeight(int weight)
Sets the text format&#39;s font weight to weight.
Definition: qtextformat.h:411
void setAnchorName(const QString &name)
This function is deprecated.
Definition: qtextformat.h:509
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
static ushort lowSurrogate(uint ucs4)
Returns the low surrogate value of a ucs4 code point.
Definition: qchar.h:306
QExplicitlySharedDataPointer< DeclarationData > d
Definition: qcssparser_p.h:430
Q_CORE_EXPORT void qDebug(const char *,...)
bool hasProperty(int propertyId) const
Returns true if the text format has a property with the given propertyId; otherwise returns false...
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition: qfont.cpp:1983
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
QTextCharFormat charFormat
QVector< QCss::Declaration > declarationsForNode(int node) const
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool requiresSurrogates(uint ucs4)
Returns true if the UCS-4-encoded character specified by ucs4 can be split into the high and low part...
Definition: qchar.h:294
static bool setIntAttribute(int *destination, const QString &value)
int margin(int i, int mar) const
bool overline() const
Returns true if overline has been set; otherwise returns false.
Definition: qfont.cpp:1344
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
void setFontCapitalization(QFont::Capitalization capitalization)
Sets the capitalization of the text that apppears in this font to capitalization. ...
Definition: qtextformat.h:419
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
The QTextFormat class provides formatting information for a QTextDocument.
Definition: qtextformat.h:129
int bottomMargin(int i) const
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &entityStr, const QTextHtmlEntity &entity)
void initializeProperties(const QTextHtmlParserNode *parent, const QTextHtmlParser *parser)
QStringList parseAttributes()
static int lookupElement(const QString &element)
bool nodeIsChildOf(int i, QTextHTMLElements id) const
const char * name
#define Q_STATIC_GLOBAL_OPERATOR
Definition: qfunctions_p.h:71
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
void setPageBreakPolicy(PageBreakFlags flags)
Sets the page break policy for the paragraph to policy.
Definition: qtextformat.h:606
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void importStyleSheet(const QString &href)
QTextBlockFormat blockFormat
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
QVector< StyleRule > styleRules
Definition: qcssparser_p.h:639
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
bool intValue(int *i, const char *unit=0) const
static QVector< Declaration > declarations(const QVector< StyleRule > &styleRules, const QString &part, quint64 pseudoClass=PseudoClass_Unspecified)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned int uint
Definition: qglobal.h:996
int topMargin(int i) const
void setFontPointSize(qreal size)
Sets the text format&#39;s font size.
Definition: qtextformat.h:406
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void applyCssDeclarations(const QVector< QCss::Declaration > &declarations, const QTextDocument *resourceProvider)
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
QVector< StyleSheet > styleSheets
Definition: qcssparser_p.h:675
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
void clear()
Removes all items from the list.
Definition: qlist.h:764
Qt::BrushStyle style() const
Returns the brush style.
Definition: qbrush.h:182
QTextHTMLElements id
bool loadFromData(const uchar *buf, uint len, const char *format=0, Qt::ImageConversionFlags flags=Qt::AutoColor)
Loads a pixmap from the len first bytes of the given binary data.
Definition: qpixmap.cpp:979
int count() const
Definition: qstring.h:103
#define MAX_ENTITY
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static QChar resolveEntity(const QString &entity)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
void setAlignment(Qt::Alignment alignment)
Sets the paragraph&#39;s alignment.
Definition: qtextformat.h:619
QTextHtmlParserNode * resolveParent()
QTextHTMLElements
QString & append(QChar c)
Definition: qstring.cpp:1777
int compare(const QString &s) const
Definition: qstring.cpp:5037
void setAnchorHref(const QString &value)
Sets the hypertext link for the text format to the given value.
Definition: qtextformat.h:504
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
unsigned short ushort
Definition: qglobal.h:995
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
QString family() const
Returns the requested font family name, i.e.
Definition: qfont.cpp:906
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
bool extractBox(int *margins, int *paddings, int *spacing=0)
Definition: qcssparser.cpp:492
void applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider)
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
The QTextFrameFormat class provides formatting information for frames in a QTextDocument.
Definition: qtextformat.h:727
double toDouble(bool *ok=0) const
Returns the string converted to a double value.
Definition: qstring.cpp:6227
The QTextLength class encapsulates the different types of length used in a QTextDocument.
Definition: qtextformat.h:84
static const QTextHtmlElement * lookupElementHelper(const QString &element)
void setFontFamily(const QString &family)
Sets the text format&#39;s font family.
Definition: qtextformat.h:401
uint toUInt(bool *ok=0, int base=10) const
Returns the string converted to an unsigned int using base base, which is 10 by default and must be b...
Definition: qstring.cpp:6120
if(void) toggleToolbarShown
Definition: qnamespace.h:54
int weight() const
Returns the weight of the font which is one of the enumerated values from QFont::Weight.
Definition: qfont.cpp:1248
void setIndent(int indent)
Sets the paragraph&#39;s indentation.
Definition: qtextformat.h:622
T qvariant_cast(const QVariant &)
Definition: qvariant.h:571
QVector< Declaration > declarationsForNode(NodePtr node, const char *extraPseudo=0)
enum QTextHtmlElement::DisplayMode displayMode
void resolveStyleSheetImports(const QCss::StyleSheet &sheet)
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
static const QTextHtmlElement elements[Html_NumElements]
void setAnchor(bool anchor)
If anchor is true, text with this format represents an anchor, and is formatted in the appropriate wa...
Definition: qtextformat.h:499
The QTextDocument class holds formatted text that can be viewed and edited using a QTextEdit...
void setForeground(const QBrush &brush)
Sets the foreground brush to the specified brush.
Definition: qtextformat.h:350
bool realValue(qreal *r, const char *unit=0) const
int pointSize() const
Returns the point size of the font.
Definition: qfont.cpp:981
bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity=Qt::CaseSensitive)
int depth(int i) const
virtual bool hasAttributes(NodePtr node) const
void clearProperty(int propertyId)
Clears the value of the property given by propertyId.
static bool setFloatAttribute(qreal *destination, const QString &value)
bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *, QCss::Origin *)
Definition: qcssparser.cpp:990
bool isValid() const
Returns true if the color is valid; otherwise returns false.
Definition: qcolor.h:295
QVariant resource(int type, const QUrl &name) const
Returns data of the specified type from the resource with the given name.
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
bool strikeOut() const
Returns true if strikeout has been set; otherwise returns false.
Definition: qfont.cpp:1367
bool isNestedList(const QTextHtmlParser *parser) const
static const KeyPair *const end
void setLayoutDirection(Qt::LayoutDirection direction)
Sets the document&#39;s layout direction to the specified direction.
Definition: qtextformat.h:338
void setUnderlineStyle(UnderlineStyle style)
Sets the style of underlining the text to style.
#define qPrintable(string)
Definition: qglobal.h:1750
virtual bool isNullNode(NodePtr node) const
void applyAttributes(const QStringList &attributes)
QChar toLower() const
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1239
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool allowedInContext(int parentId) const
virtual void freeNode(NodePtr node) const
BorderStyle styleValue() const
virtual QStringList nodeNames(NodePtr node) const
QVector< ImportRule > importRules
Definition: qcssparser_p.h:642
bool extractFont(QFont *font, int *fontSizeAdjustment)
QStringList media
Definition: qcssparser_p.h:625
bool loadFromData(const uchar *buf, int len, const char *format=0)
Loads an image from the first len bytes of the given binary data.
Definition: qimage.cpp:5275
bool isNotSelfNesting() const
virtual NodePtr previousSiblingNode(NodePtr node) const
static void setWidthAttribute(QTextLength *width, QString value)