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