1 /* This file is part of the KDE project
2 * Copyright (C) 2008 Girish Ramakrishnan <girish@forwardbias.in>
3 * Copyright (C) 2009 Elvis Stansvik <elvstone@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "KoTextDebug.h"
22
23 #include <QTextDocument>
24 #include <QTextDocumentFragment>
25 #include <QTextFrame>
26 #include <QTextBlock>
27 #include <QTextTable>
28 #include <QTextFragment>
29 #include <QTextList>
30 #include <QTextStream>
31 #include <QTextCursor>
32
33 #include "styles/KoParagraphStyle.h"
34 #include "styles/KoCharacterStyle.h"
35 #include "styles/KoListStyle.h"
36 #include "styles/KoTableStyle.h"
37 #include "styles/KoTableCellStyle.h"
38 #include "styles/KoStyleManager.h"
39 #include "KoTextDocument.h"
40 #include "KoTextBlockData.h"
41 #include <KoInlineTextObjectManager.h>
42 #include <KoInlineNote.h>
43 #include <KoImageData.h>
44
45 #define PARAGRAPH_BORDER_DEBUG
46
47 int KoTextDebug::depth = 0;
48 const int KoTextDebug::INDENT = 2;
49 const QTextDocument *KoTextDebug::document = 0;
50
51 #define dumpIndent(T) { for (int i=0; i<T; ++i) out << ' '; }
52 #define dumpList(T) { foreach (const QString &x, T) out << x << ' '; }
53
Q_DECLARE_METATYPE(QList<KoText::Tab>)54 Q_DECLARE_METATYPE(QList<KoText::Tab>)
55
56 static QString fontProperties(const QTextCharFormat &textFormat)
57 {
58 QMap<int, QVariant> properties = textFormat.properties();
59 QStringList fontProps;
60 // add only font properties here
61 Q_FOREACH (int id, properties.keys()) {
62 QString key, value;
63 switch (id) {
64 case QTextFormat::FontFamily:
65 fontProps.append(properties[id].toString());
66 break;
67 case QTextFormat::FontPointSize:
68 fontProps.append(QString("%1pt").arg(properties[id].toDouble()));
69 break;
70 case QTextFormat::FontSizeAdjustment:
71 fontProps.append(QString("%1adj").arg(properties[id].toDouble()));
72 break;
73 case QTextFormat::FontWeight:
74 fontProps.append(QString("weight %1").arg(properties[id].toInt()));
75 break;
76 case QTextFormat::FontItalic:
77 fontProps.append(properties[id].toBool() ? "italic" : "non-italic");
78 break;
79 case QTextFormat::FontPixelSize:
80 fontProps.append(QString("%1px").arg(properties[id].toDouble()));
81 break;
82 case QTextFormat::FontFixedPitch:
83 fontProps.append(properties[id].toBool() ? "fixedpitch" : "varpitch");
84 break;
85 case QTextFormat::FontCapitalization:
86 fontProps.append(QString("caps %1").arg(properties[id].toInt()));
87 break;
88 case KoCharacterStyle::FontCharset:
89 fontProps.append(properties[id].toString());
90 break;
91 case QTextFormat::FontStyleHint:
92 fontProps.append(QString::number(properties[id].toInt()));
93 break;
94 case QTextFormat::FontKerning:
95 fontProps.append(QString("kerning %1").arg(properties[id].toInt()));
96 break;
97 default:
98 break;
99 }
100 }
101 return fontProps.join(",");
102 }
103
dumpDocument(const QTextDocument * doc,QTextStream & out)104 void KoTextDebug::dumpDocument(const QTextDocument *doc, QTextStream &out)
105 {
106 Q_ASSERT(doc);
107 document = doc;
108 out << QString("<document defaultfont=\"%1\">").arg(doc->defaultFont().toString());
109 dumpFrame(document->rootFrame(), out);
110 out << "</document>";
111 document = 0;
112 }
113
textAttributes(const KoCharacterStyle & style)114 QString KoTextDebug::textAttributes(const KoCharacterStyle &style)
115 {
116 QTextCharFormat format;
117 style.applyStyle(format);
118 return textAttributes(format);
119 }
120
inlineObjectAttributes(const QTextCharFormat & textFormat)121 QString KoTextDebug::inlineObjectAttributes(const QTextCharFormat &textFormat)
122 {
123 QString attrs;
124
125 if (textFormat.objectType() == QTextFormat::UserObject + 1) {
126 KoInlineTextObjectManager *inlineObjectManager = KoTextDocument(document).inlineTextObjectManager();
127 KoInlineObject *inlineObject = inlineObjectManager->inlineTextObject(textFormat);
128 if (KoInlineNote *note = dynamic_cast<KoInlineNote *>(inlineObject)) {
129 attrs.append(QString(" id=\"%1\"").arg(note->id()));
130 if (note->type() == KoInlineNote::Footnote) {
131 attrs.append(" type=\"footnote\"");
132 } else if (note->type() == KoInlineNote::Endnote) {
133 attrs.append(" type=\"endnote\"");
134 }
135 attrs.append(QString(" label=\"%1\"").arg(note->label()));
136 } else {
137 attrs.append(" type=\"inlineobject\">");
138 }
139 }
140
141 return attrs;
142 }
143
textAttributes(const QTextCharFormat & textFormat)144 QString KoTextDebug::textAttributes(const QTextCharFormat &textFormat)
145 {
146 QString attrs;
147
148 QTextImageFormat imageFormat = textFormat.toImageFormat();
149
150 if (imageFormat.isValid()) {
151 attrs.append(" type=\"image\">");
152 return attrs;
153 }
154
155 KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
156 if (styleManager && textFormat.hasProperty(KoCharacterStyle::StyleId)) {
157 int id = textFormat.intProperty(KoCharacterStyle::StyleId);
158 KoCharacterStyle *characterStyle = styleManager->characterStyle(id);
159 attrs.append(" characterStyle=\"id:").append(QString::number(id));
160 if (characterStyle)
161 attrs.append(" name:").append(characterStyle->name());
162 attrs.append("\"");
163 }
164
165 QMap<int, QVariant> properties = textFormat.properties();
166 attrs.append(" type=\"char\"");
167 QString fontProps = fontProperties(textFormat);
168 if (!fontProps.isEmpty())
169 attrs.append(QString(" font=\"%1\"").arg(fontProps));
170
171 if (textFormat.isAnchor()) {
172 attrs.append(QString(" achorHref=\"%1\"").arg(textFormat.anchorHref()));
173 attrs.append(QString(" achorName=\"%1\"").arg(textFormat.anchorName()));
174 }
175
176 Q_FOREACH (int id, properties.keys()) {
177 QString key, value;
178 switch (id) {
179 case QTextFormat::TextOutline: {
180 key = "outline";
181 QPen pen = qvariant_cast<QPen>(properties[id]);
182 if (pen.style() == Qt::NoPen)
183 value = "false";
184 else
185 value = pen.color().name();
186 break;
187 }
188 case KoCharacterStyle::UnderlineStyle:
189 key = "underlinestyle";
190 value = QString::number(properties[id].toInt());
191 break;
192 case QTextFormat::TextUnderlineColor:
193 key = "underlinecolor";
194 value = qvariant_cast<QColor>(properties[id]).name();
195 break;
196 case KoCharacterStyle::UnderlineType:
197 key = "underlinetype";
198 value = QString::number(properties[id].toInt());
199 break;
200 case KoCharacterStyle::UnderlineMode:
201 key = "underlinemode";
202 value = QString::number(properties[id].toInt());
203 break;
204 case KoCharacterStyle::UnderlineWeight:
205 key = "underlineweight";
206 value = QString::number(properties[id].toInt());
207 break;
208 case KoCharacterStyle::UnderlineWidth:
209 key = "underlinewidth";
210 value = QString::number(properties[id].toDouble());
211 break;
212 case KoCharacterStyle::StrikeOutStyle:
213 key = "strikeoutstyle";
214 value = QString::number(properties[id].toInt());
215 break;
216 case KoCharacterStyle::StrikeOutColor:
217 key = "strikeoutcolor";
218 value = qvariant_cast<QColor>(properties[id]).name();
219 break;
220 case KoCharacterStyle::StrikeOutType:
221 key = "strikeouttype";
222 value = QString::number(properties[id].toInt());
223 break;
224 case KoCharacterStyle::StrikeOutMode:
225 key = "strikeoutmode";
226 value = QString::number(properties[id].toInt());
227 break;
228 case KoCharacterStyle::StrikeOutWeight:
229 key = "strikeoutweight";
230 value = QString::number(properties[id].toInt());
231 break;
232 case KoCharacterStyle::StrikeOutWidth:
233 key = "strikeoutwidth";
234 value = QString::number(properties[id].toDouble());
235 break;
236 case QTextFormat::ForegroundBrush:
237 key = "foreground";
238 value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
239 break;
240 case QTextFormat::BackgroundBrush:
241 key = "background";
242 value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
243 break;
244 case QTextFormat::BlockAlignment:
245 key = "align";
246 value = QString::number(properties[id].toInt());
247 break;
248 case QTextFormat::TextIndent:
249 key = "textindent";
250 value = QString::number(properties[id].toInt());
251 break;
252 case QTextFormat::BlockIndent:
253 key = "indent";
254 value = QString::number(properties[id].toInt());
255 break;
256 case KoCharacterStyle::Country:
257 key = "country";
258 value = properties[id].toString();
259 break;
260 case KoCharacterStyle::Language:
261 key = "language";
262 value = properties[id].toString();
263 break;
264 case KoCharacterStyle::HasHyphenation:
265 key = "hyphenation";
266 value = QString::number(properties[id].toBool());
267 break;
268 case KoCharacterStyle::StrikeOutText:
269 key = "strikeout-text";
270 value = properties[id].toString();
271 break;
272 case KoCharacterStyle::FontCharset:
273 key = "font-charset";
274 value = properties[id].toString();
275 break;
276 case KoCharacterStyle::TextRotationAngle:
277 key = "rotation-angle";
278 value = QString::number(properties[id].toInt());
279 break;
280 case KoCharacterStyle::TextRotationScale:
281 key = "text-rotation-scale";
282 value = properties[id].toInt() == KoCharacterStyle::Fixed ? "Fixed" : "LineHeight";
283 break;
284 case KoCharacterStyle::TextScale:
285 key = "text-scale";
286 value = QString::number(properties[id].toInt());
287 break;
288 case KoCharacterStyle::InlineRdf:
289 key = "inline-rdf";
290 value = QString::number(properties[id].toInt());
291 break;
292 default:
293 key = "unknown"+QString::number(id);
294 value = QString::number(properties[id].toInt());
295 break;
296 }
297 if (!key.isEmpty())
298 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
299 }
300 return attrs;
301 }
302
paraAttributes(const KoParagraphStyle & style)303 QString KoTextDebug::paraAttributes(const KoParagraphStyle &style)
304 {
305 QTextBlockFormat format;
306 style.applyStyle(format);
307 return paraAttributes(format);
308 }
309
paraAttributes(const QTextBlockFormat & blockFormat)310 QString KoTextDebug::paraAttributes(const QTextBlockFormat &blockFormat)
311 {
312 QString attrs;
313 KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
314 if (styleManager && blockFormat.hasProperty(KoParagraphStyle::StyleId)) {
315 int id = blockFormat.intProperty(KoParagraphStyle::StyleId);
316 KoParagraphStyle *paragraphStyle = styleManager->paragraphStyle(id);
317 attrs.append(" paragraphStyle=\"id:").append(QString::number(id));
318 if (paragraphStyle)
319 attrs.append(" name:").append(paragraphStyle->name());
320 attrs.append("\"");
321 }
322
323 QMap<int, QVariant> properties = blockFormat.properties();
324 Q_FOREACH (int id, properties.keys()) {
325 QString key, value;
326 switch (id) {
327 // the following are 'todo'
328 case KoParagraphStyle::PercentLineHeight:
329 case KoParagraphStyle::FixedLineHeight:
330 case KoParagraphStyle::MinimumLineHeight:
331 case KoParagraphStyle::LineSpacing:
332 case KoParagraphStyle::LineSpacingFromFont:
333 case KoParagraphStyle::AlignLastLine:
334 case KoParagraphStyle::WidowThreshold:
335 case KoParagraphStyle::OrphanThreshold:
336 case KoParagraphStyle::DropCapsTextStyle:
337 case KoParagraphStyle::FollowDocBaseline:
338 case KoParagraphStyle::HasLeftBorder:
339 case KoParagraphStyle::HasTopBorder:
340 case KoParagraphStyle::HasRightBorder:
341 case KoParagraphStyle::HasBottomBorder:
342 case KoParagraphStyle::BorderLineWidth:
343 case KoParagraphStyle::SecondBorderLineWidth:
344 case KoParagraphStyle::DistanceToSecondBorder:
345 case KoParagraphStyle::LeftPadding:
346 case KoParagraphStyle::TopPadding:
347 case KoParagraphStyle::RightPadding:
348 case KoParagraphStyle::BottomPadding:
349 case KoParagraphStyle::LeftBorderColor:
350 case KoParagraphStyle::TopInnerBorderWidth:
351 case KoParagraphStyle::TopBorderSpacing:
352 case KoParagraphStyle::TopBorderStyle:
353 case KoParagraphStyle::TopBorderColor:
354 case KoParagraphStyle::RightInnerBorderWidth:
355 case KoParagraphStyle::RightBorderSpacing:
356 case KoParagraphStyle::RightBorderStyle:
357 case KoParagraphStyle::RightBorderColor:
358 case KoParagraphStyle::BottomInnerBorderWidth:
359 case KoParagraphStyle::BottomBorderSpacing:
360 case KoParagraphStyle::BottomBorderStyle:
361 case KoParagraphStyle::BottomBorderColor:
362 case KoParagraphStyle::ListStyleId:
363 case KoParagraphStyle::ListStartValue:
364 case KoParagraphStyle::RestartListNumbering:
365 case KoParagraphStyle::TextProgressionDirection:
366 case KoParagraphStyle::MasterPageName:
367 case KoParagraphStyle::OutlineLevel:
368 break;
369 case KoParagraphStyle::AutoTextIndent:
370 key = "autotextindent";
371 value = properties[id].toBool() ? "true" : "false" ;
372 break;
373 #ifdef PARAGRAPH_BORDER_DEBUG // because it tends to get annoyingly long :)
374 case KoParagraphStyle::LeftBorderWidth:
375 key = "border-width-left";
376 value = QString::number(properties[id].toDouble()) ;
377 break;
378 case KoParagraphStyle::TopBorderWidth:
379 key = "border-width-top";
380 value = QString::number(properties[id].toDouble()) ;
381 break;
382 case KoParagraphStyle::RightBorderWidth:
383 key = "border-width-right";
384 value = QString::number(properties[id].toDouble()) ;
385 break;
386 case KoParagraphStyle::BottomBorderWidth:
387 key = "border-width-bottom";
388 value = QString::number(properties[id].toDouble()) ;
389 break;
390 case KoParagraphStyle::LeftBorderStyle:
391 key = "border-style-left";
392 value = QString::number(properties[id].toDouble()) ;
393 break;
394 case KoParagraphStyle::LeftBorderSpacing:
395 key = "inner-border-spacing-left";
396 value = QString::number(properties[id].toDouble()) ;
397 break;
398 case KoParagraphStyle::LeftInnerBorderWidth:
399 key = "inner-border-width-left";
400 value = QString::number(properties[id].toDouble()) ;
401 break;
402 #endif
403 case KoParagraphStyle::TabStopDistance:
404 key = "tab-stop-distance";
405 value = QString::number(properties[id].toDouble());
406 break;
407 case KoParagraphStyle::TabPositions:
408 key = "tab-stops";
409 value.clear();
410 Q_FOREACH (const QVariant & qvtab, qvariant_cast<QList<QVariant> >(properties[id])) {
411 KoText::Tab tab = qvtab.value<KoText::Tab>();
412 value.append("{");
413 value.append(" pos:").append(QString::number(tab.position));
414 value.append(" type:").append(QString::number(tab.type));
415 if (! tab.delimiter.isNull())
416 value.append(" delim:").append(QString(tab.delimiter));
417 value.append(" leadertype:").append(QString::number(tab.leaderType));
418 value.append(" leaderstyle:").append(QString::number(tab.leaderStyle));
419 value.append(" leaderweight:").append(QString::number(tab.leaderWeight));
420 value.append(" leaderwidth:").append(QString().setNum(tab.leaderWidth));
421 value.append(" leadercolor:").append(tab.leaderColor.name());
422 if (! tab.leaderText.isEmpty())
423 value.append(" leadertext:").append(QString(tab.leaderText));
424 value.append("}, ");
425 }
426 break;
427 case KoParagraphStyle::DropCaps:
428 key = "drop-caps";
429 value = QString::number(properties[id].toBool());
430 break;
431 case KoParagraphStyle::DropCapsLines:
432 key = "drop-caps-lines";
433 value = QString::number(properties[id].toInt());
434 break;
435 case KoParagraphStyle::DropCapsLength:
436 key = "drop-caps-length";
437 value = QString::number(properties[id].toInt());
438 break;
439 case KoParagraphStyle::DropCapsDistance:
440 key = "drop-caps-distance";
441 value = QString::number(properties[id].toDouble());
442 break;
443 case QTextFormat::BlockBottomMargin:
444 value = QString::number(properties[id].toDouble());
445 if (value != "0")
446 key = "block-bottom-margin";
447 break;
448 case QTextFormat::BlockTopMargin:
449 value = QString::number(properties[id].toDouble());
450 if (value != "0")
451 key = "block-top-margin";
452 break;
453 case QTextFormat::BlockLeftMargin:
454 value = QString::number(properties[id].toDouble());
455 if (value != "0")
456 key = "block-left-margin";
457 break;
458 case QTextFormat::BlockRightMargin:
459 value = QString::number(properties[id].toDouble());
460 if (value != "0")
461 key = "block-right-margin";
462 break;
463 case KoParagraphStyle::UnnumberedListItem:
464 key = "unnumbered-list-item";
465 value = QString::number(properties[id].toBool());
466 break;
467 case KoParagraphStyle::IsListHeader:
468 key = "list-header";
469 value = '1';
470 break;
471 case KoParagraphStyle::ListLevel:
472 key = "list-level";
473 value = QString::number(properties[id].toInt());
474 break;
475 default:
476 break;
477 }
478 if (!key.isEmpty())
479 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
480 }
481 return attrs;
482 }
483
listAttributes(const QTextListFormat & listFormat)484 QString KoTextDebug::listAttributes(const QTextListFormat &listFormat)
485 {
486 QString attrs;
487 KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
488 if (styleManager && listFormat.hasProperty(KoListStyle::StyleId)) {
489 int id = listFormat.intProperty(KoListStyle::StyleId);
490 KoListStyle *listStyle = styleManager->listStyle(id);
491 attrs.append(" listStyle=\"id:").append(QString::number(id));
492 if (listStyle)
493 attrs.append(" name:").append(listStyle->name());
494 attrs.append("\"");
495 }
496
497 QMap<int, QVariant> properties = listFormat.properties();
498 Q_FOREACH (int id, properties.keys()) {
499 QString key, value;
500 switch (id) {
501 case QTextListFormat::ListStyle:
502 key = "type";
503 value = QString::number(properties[id].toInt());
504 break;
505 case QTextListFormat::ListIndent:
506 key = "indent";
507 value = QString::number(properties[id].toDouble());
508 break;
509 case KoListStyle::ListItemPrefix:
510 key = "prefix";
511 value = properties[id].toString();
512 break;
513 case KoListStyle::ListItemSuffix:
514 key = "suffix";
515 value = properties[id].toString();
516 break;
517 case KoListStyle::StartValue:
518 key = "start-value";
519 value = QString::number(properties[id].toInt());
520 break;
521 case KoListStyle::Level:
522 key = "level";
523 value = QString::number(properties[id].toInt());
524 break;
525 case KoListStyle::DisplayLevel:
526 key = "display-level";
527 value = QString::number(properties[id].toInt());
528 break;
529 case KoListStyle::Alignment:
530 key = "alignment";
531 value = QString::number(properties[id].toInt());
532 break;
533 case KoListStyle::RelativeBulletSize:
534 key = "bullet-size";
535 value = QString::number(properties[id].toInt());
536 break;
537 case KoListStyle::BulletCharacter:
538 key = "bullet-char";
539 value = properties[id].toString();
540 break;
541 case KoListStyle::LetterSynchronization:
542 key = "letter-sync";
543 value = QString::number(properties[id].toInt());
544 break;
545 case KoListStyle::StyleId:
546 key = "styleid";
547 value = QString::number(properties[id].toInt());
548 break;
549 case KoListStyle::MinimumWidth:
550 key = "minimum-width";
551 value = QString::number(properties[id].toDouble());
552 break;
553 case KoListStyle::ListId:
554 key = "list-id";
555 value = QString::number(properties[id].toInt());
556 break;
557 case KoListStyle::IsOutline:
558 key = "is-outline";
559 value = QString::number(properties[id].toBool());
560 break;
561 case KoListStyle::Indent:
562 key = "indent";
563 value = QString::number(properties[id].toInt());
564 break;
565 case KoListStyle::MinimumDistance:
566 key = "minimum-distance";
567 value = QString::number(properties[id].toDouble());
568 break;
569 case KoListStyle::Width:
570 key = "width";
571 value = QString::number(properties[id].toDouble());
572 break;
573 case KoListStyle::Height:
574 key = "height";
575 value = QString::number(properties[id].toDouble());
576 break;
577 case KoListStyle::BulletImage:
578 key = "bullet-image";
579 value = QString::number((quintptr)(properties[id].value<KoImageData*>()));
580 break;
581 case KoListStyle::Margin:
582 key="margin-left";
583 value =QString::number(properties[id].toInt());
584 break;
585 case KoListStyle::TextIndent:
586 key="text-indent";
587 value =QString::number(properties[id].toInt());
588 break;
589 case KoListStyle::AlignmentMode:
590 key="label-alignment";
591 value=QString(properties[id].toBool()? "true":"false");
592 break;
593 case KoListStyle::LabelFollowedBy:
594 key="label-followed-by";
595 value =QString::number(properties[id].toInt());
596 break;
597 case KoListStyle::TabStopPosition:
598 key="tab-stop-position";
599 value =QString::number(properties[id].toInt());
600 break;
601 default:
602 break;
603 }
604 if (!key.isEmpty())
605 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
606 }
607 return attrs;
608 }
609
tableAttributes(const KoTableStyle & tableStyle)610 QString KoTextDebug::tableAttributes(const KoTableStyle &tableStyle)
611 {
612 QTextTableFormat format;
613 tableStyle.applyStyle(format);
614 return tableAttributes(format);
615 }
616
tableAttributes(const QTextTableFormat & tableFormat)617 QString KoTextDebug::tableAttributes(const QTextTableFormat &tableFormat)
618 {
619 QString attrs;
620 KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
621 if (styleManager) {
622 int id = tableFormat.intProperty(KoTableStyle::StyleId);
623 KoTableStyle *tableStyle = styleManager->tableStyle(id);
624 attrs.append(" tableStyle=\"id:").append(QString::number(id));
625 if (tableStyle)
626 attrs.append(" name:").append(tableStyle->name());
627 attrs.append("\"");
628 }
629
630 QMap<int, QVariant> properties = tableFormat.properties();
631 Q_FOREACH (int id, properties.keys()) {
632 QString key, value;
633 switch (id) {
634 case QTextTableFormat::TableColumnWidthConstraints:
635 case QTextFormat::BackgroundBrush:
636 key = "background";
637 value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
638 break;
639 case QTextFormat::BlockAlignment:
640 key = "alignment";
641 switch (properties[id].toInt()) {
642 case Qt::AlignLeft:
643 value = "left";
644 break;
645 case Qt::AlignRight:
646 value = "right";
647 break;
648 case Qt::AlignHCenter:
649 value = "center";
650 break;
651 case Qt::AlignJustify:
652 value = "justify";
653 break;
654 default:
655 value.clear();
656 break;
657 }
658 break;
659 case KoTableStyle::KeepWithNext:
660 key = "keep-with-next";
661 value = properties[id].toBool() ? "true" : "false";
662 break;
663 case KoTableStyle::BreakBefore:
664 key = "break-before";
665 value = properties[id].toBool() ? "true" : "false";
666 break;
667 case KoTableStyle::BreakAfter:
668 key = "break-after";
669 value = properties[id].toBool() ? "true" : "false";
670 break;
671 case KoTableStyle::MayBreakBetweenRows:
672 key = "may-break-between-rows";
673 value = properties[id].toBool() ? "true" : "false";
674 break;
675 case KoTableStyle::MasterPageName:
676 key = "master-page-name";
677 value = properties[id].toString();
678 break;
679 case QTextTableFormat::TableColumns:
680 key = "columns";
681 value = QString::number(properties[id].toInt());
682 break;
683 case QTextTableFormat::TableCellSpacing:
684 key = "cell-spacing";
685 value = QString::number(properties[id].toDouble());
686 break;
687 case QTextTableFormat::TableHeaderRowCount:
688 key = "header-row-count";
689 value = QString::number(properties[id].toInt());
690 break;
691 default:
692 break;
693 }
694 if (!key.isEmpty())
695 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
696 }
697 return attrs;
698 }
699
frameAttributes(const QTextFrameFormat & frameFormat)700 QString KoTextDebug::frameAttributes(const QTextFrameFormat &frameFormat)
701 {
702 QString attrs;
703
704 QMap<int, QVariant> properties = frameFormat.properties();
705 Q_FOREACH (int id, properties.keys()) {
706 QString key, value;
707 switch (id) {
708 case QTextFrameFormat::FrameBorderBrush:
709 break;
710 case QTextFrameFormat::FrameBorderStyle:
711 key = "border-style";
712 // determine border style.
713 switch (properties[id].toInt()) {
714 case QTextFrameFormat::BorderStyle_None:
715 value = "None";
716 break;
717 case QTextFrameFormat::BorderStyle_Dotted:
718 value = "Dotted";
719 break;
720 case QTextFrameFormat::BorderStyle_Dashed:
721 value = "Dashed";
722 break;
723 case QTextFrameFormat::BorderStyle_Solid:
724 value = "Solid";
725 break;
726 case QTextFrameFormat::BorderStyle_Double:
727 value = "Double";
728 break;
729 case QTextFrameFormat::BorderStyle_DotDash:
730 value = "DotDash";
731 break;
732 case QTextFrameFormat::BorderStyle_DotDotDash:
733 value = "DotDotDash";
734 break;
735 case QTextFrameFormat::BorderStyle_Groove:
736 value = "Groove";
737 break;
738 case QTextFrameFormat::BorderStyle_Ridge:
739 value = "Ridge";
740 break;
741 case QTextFrameFormat::BorderStyle_Inset:
742 value = "Inset";
743 break;
744 case QTextFrameFormat::BorderStyle_Outset:
745 value = "Outset";
746 break;
747 default:
748 value = "Unknown";
749 break;
750 }
751 break;
752 case QTextFrameFormat::FrameBorder:
753 key = "border";
754 value = QString::number(properties[id].toDouble());
755 break;
756 case QTextFrameFormat::FrameMargin:
757 key = "margin";
758 value = QString::number(properties[id].toDouble());
759 break;
760 case QTextFrameFormat::FramePadding:
761 key = "padding";
762 value = QString::number(properties[id].toDouble());
763 break;
764 case QTextFrameFormat::FrameWidth:
765 key = "width";
766 value = QString::number(properties[id].toDouble());
767 break;
768 case QTextFrameFormat::FrameHeight:
769 key = "height";
770 value = QString::number(properties[id].toDouble());
771 break;
772 case QTextFrameFormat::FrameTopMargin:
773 key = "top-margin";
774 value = QString::number(properties[id].toDouble());
775 break;
776 case QTextFrameFormat::FrameBottomMargin:
777 key = "bottom-margin";
778 value = QString::number(properties[id].toDouble());
779 break;
780 case QTextFrameFormat::FrameLeftMargin:
781 key = "left-margin";
782 value = QString::number(properties[id].toDouble());
783 break;
784 case QTextFrameFormat::FrameRightMargin:
785 key = "right-margin";
786 value = QString::number(properties[id].toDouble());
787 break;
788 default:
789 break;
790 }
791 if (!key.isEmpty())
792 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
793 }
794 return attrs;
795 }
796
tableCellAttributes(const KoTableCellStyle & tableCellStyle)797 QString KoTextDebug::tableCellAttributes(const KoTableCellStyle &tableCellStyle)
798 {
799 QTextTableCellFormat format;
800 tableCellStyle.applyStyle(format);
801 return tableCellAttributes(format);
802 }
803
tableCellAttributes(const QTextTableCellFormat & tableCellFormat)804 QString KoTextDebug::tableCellAttributes(const QTextTableCellFormat &tableCellFormat)
805 {
806 QString attrs;
807 KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
808 if (styleManager) {
809 int id = tableCellFormat.intProperty(KoTableCellStyle::StyleId);
810 KoTableCellStyle *tableCellStyle = styleManager->tableCellStyle(id);
811 attrs.append(" tableCellStyle=\"id:").append(QString::number(id));
812 if (tableCellStyle)
813 attrs.append(" name:").append(tableCellStyle->name());
814 attrs.append("\"");
815 }
816
817 QMap<int, QVariant> properties = tableCellFormat.properties();
818 Q_FOREACH (int id, properties.keys()) {
819 QString key, value;
820 switch (id) {
821 case QTextTableCellFormat::TableCellRowSpan:
822 key = "row-span";
823 value = QString::number(properties[id].toInt());
824 break;
825 case QTextTableCellFormat::TableCellColumnSpan:
826 key = "column-span";
827 value = QString::number(properties[id].toInt());
828 break;
829 case QTextFormat::TableCellTopPadding:
830 key = "top-padding";
831 value = QString::number(properties[id].toDouble());
832 break;
833 case QTextFormat::TableCellBottomPadding:
834 key = "bottom-padding";
835 value = QString::number(properties[id].toDouble());
836 break;
837 case QTextFormat::TableCellLeftPadding:
838 key = "left-padding";
839 value = QString::number(properties[id].toDouble());
840 break;
841 case QTextFormat::TableCellRightPadding:
842 key = "right-padding";
843 value = QString::number(properties[id].toDouble());
844 break;
845 case KoTableCellStyle::MasterPageName:
846 key = "master-page-name";
847 value = properties[id].toString();
848 break;
849 default:
850 break;
851 }
852 if (!key.isEmpty())
853 attrs.append(" ").append(key).append("=\"").append(value).append("\"");
854 }
855 return attrs;
856 }
857
dumpFrame(const QTextFrame * frame,QTextStream & out)858 void KoTextDebug::dumpFrame(const QTextFrame *frame, QTextStream &out)
859 {
860 depth += INDENT;
861
862 dumpIndent(depth);
863 out << "<frame" << frameAttributes(frame->frameFormat()) << '>' << endl;
864
865 QTextFrame::iterator iterator = frame->begin();
866
867 for (; !iterator.atEnd(); ++iterator) {
868 QTextFrame *childFrame = iterator.currentFrame();
869 QTextBlock textBlock = iterator.currentBlock();
870
871 if (childFrame) {
872 QTextTable *table = qobject_cast<QTextTable *>(childFrame);
873 if (table) {
874 dumpTable(table, out);
875 } else {
876 dumpFrame(frame, out);
877 }
878 } else if (textBlock.isValid()) {
879 dumpBlock(textBlock, out);
880 }
881 }
882
883 dumpIndent(depth);
884 out << "</frame>" << endl;
885 depth -= INDENT;
886 }
887
dumpBlock(const QTextBlock & block,QTextStream & out)888 void KoTextDebug::dumpBlock(const QTextBlock &block, QTextStream &out)
889 {
890 depth += INDENT;
891
892 QString attrs;
893 attrs.append(paraAttributes(block.blockFormat()));
894 //attrs.append(" blockcharformat=\"").append(textAttributes(QTextCursor(block).blockCharFormat())).append('\"');
895 attrs.append(textAttributes(QTextCursor(block).blockCharFormat()));
896
897 QTextList *list = block.textList();
898 if (list) {
899 attrs.append(" list=\"item:").append(QString::number(list->itemNumber(block) + 1)).append('/')
900 .append(QString::number(list->count()));
901 attrs.append('"');
902 attrs.append(listAttributes(list->format()));
903 }
904
905 dumpIndent(depth);
906 out << "<block" << attrs << '>' << endl;
907
908 QTextBlock::Iterator iterator = block.begin();
909 for (; !iterator.atEnd(); ++iterator) {
910 QTextFragment fragment = iterator.fragment();
911 if (fragment.isValid()) {
912 dumpFragment(fragment, out);
913 }
914 }
915 dumpIndent(depth);
916 out << "</block>" << endl;
917 depth -= INDENT;
918 if (block.next().isValid())
919 out << ' ';
920 }
921
dumpTable(const QTextTable * table,QTextStream & out)922 void KoTextDebug::dumpTable(const QTextTable *table, QTextStream &out)
923 {
924 depth += INDENT;
925
926 QString attrs;
927 attrs.append(tableAttributes(table->format()));
928 attrs.append(frameAttributes(table->frameFormat())); // include frame attributes too.
929
930 dumpIndent(depth);
931 out << "<table" << attrs << '>' << endl;
932
933 // loop through all the cells in the table and dump the cells.
934 for (int row = 0; row < table->rows(); ++row) {
935 for (int column = 0; column < table->columns(); ++column) {
936 dumpTableCell(table->cellAt(row, column), out);
937 }
938 }
939
940 dumpIndent(depth);
941 out << "</table>" << endl;
942 depth -= INDENT;
943 }
944
dumpTableCell(const QTextTableCell & cell,QTextStream & out)945 void KoTextDebug::dumpTableCell(const QTextTableCell &cell, QTextStream &out)
946 {
947 depth += INDENT;
948
949 QString attrs;
950 attrs.append(textAttributes(cell.format()));
951 attrs.append(tableCellAttributes(cell.format().toTableCellFormat()));
952
953 dumpIndent(depth);
954 out << "<cell" << attrs << '>' << endl;
955
956 // iterate through the cell content.
957 QTextFrame::iterator cellIter = cell.begin();
958 while (!cellIter.atEnd()) {
959 if (cellIter.currentFrame() != 0) {
960 // content is a frame or table.
961 dumpFrame(cellIter.currentFrame(), out);
962 } else {
963 // content is a block.
964 dumpBlock(cellIter.currentBlock(), out);
965 }
966 ++cellIter;
967 }
968
969 dumpIndent(depth);
970 out << "</cell>\n";
971
972 depth -= INDENT;
973 }
974
dumpFragment(const QTextFragment & fragment,QTextStream & out)975 void KoTextDebug::dumpFragment(const QTextFragment &fragment, QTextStream &out)
976 {
977 depth += INDENT;
978
979 QTextCharFormat charFormat = fragment.charFormat();
980 KoInlineObject *inlineObject = KoTextDocument(document).inlineTextObjectManager()->inlineTextObject(charFormat);
981 if (inlineObject) {
982 QString cf = inlineObjectAttributes(charFormat);
983
984 dumpIndent(depth);
985 out << "<fragment" << cf << ">\n";
986 } else {
987 QString cf = textAttributes(charFormat);
988
989 dumpIndent(depth);
990 out << "<fragment" << cf << ">\n";
991 dumpIndent(depth + INDENT);
992 out << '|' << fragment.text() << "|\n";
993 dumpIndent(depth);
994 out << "</fragment>\n";
995 }
996
997 depth -= INDENT;
998 }
999
1000