Warning, file /office/calligra/libs/text/KoTextDebug.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2008 Girish Ramakrishnan <girish@forwardbias.in>
0003  * Copyright (C) 2009 Elvis Stansvik <elvstone@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "KoTextDebug.h"
0022 
0023 #include <QTextDocument>
0024 #include <QTextDocumentFragment>
0025 #include <QTextFrame>
0026 #include <QTextBlock>
0027 #include <QTextTable>
0028 #include <QTextFragment>
0029 #include <QTextList>
0030 #include <QTextStream>
0031 #include <QTextCursor>
0032 
0033 #include "styles/KoParagraphStyle.h"
0034 #include "styles/KoCharacterStyle.h"
0035 #include "styles/KoListStyle.h"
0036 #include "styles/KoTableStyle.h"
0037 #include "styles/KoTableCellStyle.h"
0038 #include "styles/KoStyleManager.h"
0039 #include "KoTextDocument.h"
0040 #include "KoTextBlockData.h"
0041 #include <KoInlineTextObjectManager.h>
0042 #include <KoInlineNote.h>
0043 #include <KoImageData.h>
0044 
0045 #define PARAGRAPH_BORDER_DEBUG
0046 
0047 int KoTextDebug::depth = 0;
0048 const int KoTextDebug::INDENT = 2;
0049 const QTextDocument *KoTextDebug::document = 0;
0050 
0051 #define dumpIndent(T) { for (int i=0; i<T; ++i) out << ' '; }
0052 #define dumpList(T) { foreach (const QString &x, T) out << x << ' '; }
0053 
0054 Q_DECLARE_METATYPE(QVector<KoText::Tab>)
0055 
0056 static QString fontProperties(const QTextCharFormat &textFormat)
0057 {
0058     QMap<int, QVariant> properties = textFormat.properties();
0059     QStringList fontProps;
0060     // add only font properties here
0061     foreach(int id, properties.keys()) {
0062         switch (id) {
0063         case QTextFormat::FontFamily:
0064             fontProps.append(properties[id].toString());
0065             break;
0066         case QTextFormat::FontPointSize:
0067             fontProps.append(QString("%1pt").arg(properties[id].toDouble()));
0068             break;
0069         case QTextFormat::FontSizeAdjustment:
0070             fontProps.append(QString("%1adj").arg(properties[id].toDouble()));
0071             break;
0072         case QTextFormat::FontWeight:
0073             fontProps.append(QString("weight %1").arg(properties[id].toInt()));
0074             break;
0075         case QTextFormat::FontItalic:
0076             fontProps.append(properties[id].toBool() ? "italic" : "non-italic");
0077             break;
0078         case QTextFormat::FontPixelSize:
0079             fontProps.append(QString("%1px").arg(properties[id].toDouble()));
0080             break;
0081         case QTextFormat::FontFixedPitch:
0082             fontProps.append(properties[id].toBool() ? "fixedpitch" : "varpitch");
0083             break;
0084         case QTextFormat::FontCapitalization:
0085             fontProps.append(QString("caps %1").arg(properties[id].toInt()));
0086             break;
0087         case KoCharacterStyle::FontCharset:
0088             fontProps.append(properties[id].toString());
0089             break;
0090         case QTextFormat::FontStyleHint:
0091             fontProps.append(QString::number(properties[id].toInt()));
0092             break;
0093         case QTextFormat::FontKerning:
0094             fontProps.append(QString("kerning %1").arg(properties[id].toInt()));
0095             break;
0096         default:
0097             break;
0098         }
0099     }
0100     return fontProps.join(",");
0101 }
0102 
0103 void KoTextDebug::dumpDocument(const QTextDocument *doc, QTextStream &out)
0104 {
0105     Q_ASSERT(doc);
0106     document = doc;
0107     out << QString("<document defaultfont=\"%1\">").arg(doc->defaultFont().toString());
0108     dumpFrame(document->rootFrame(), out);
0109     out << "</document>";
0110     document = 0;
0111 }
0112 
0113 QString KoTextDebug::textAttributes(const KoCharacterStyle &style)
0114 {
0115     QTextCharFormat format;
0116     style.applyStyle(format);
0117     return textAttributes(format);
0118 }
0119 
0120 QString KoTextDebug::inlineObjectAttributes(const QTextCharFormat &textFormat)
0121 {
0122     QString attrs;
0123 
0124     if (textFormat.objectType() == QTextFormat::UserObject + 1) {
0125         KoInlineTextObjectManager *inlineObjectManager = KoTextDocument(document).inlineTextObjectManager();
0126         KoInlineObject *inlineObject = inlineObjectManager->inlineTextObject(textFormat);
0127         if (KoInlineNote *note = dynamic_cast<KoInlineNote *>(inlineObject)) {
0128             attrs.append(QString(" id=\"%1\"").arg(note->id()));
0129             if (note->type() == KoInlineNote::Footnote) {
0130                 attrs.append(" type=\"footnote\"");
0131             } else if (note->type() == KoInlineNote::Endnote) {
0132                 attrs.append(" type=\"endnote\"");
0133             }
0134             attrs.append(QString(" label=\"%1\"").arg(note->label()));
0135         } else {
0136             attrs.append(" type=\"inlineobject\">");
0137         }
0138     }
0139 
0140     return attrs;
0141 }
0142 
0143 QString KoTextDebug::textAttributes(const QTextCharFormat &textFormat)
0144 {
0145     QString attrs;
0146 
0147     QTextImageFormat imageFormat = textFormat.toImageFormat();
0148 
0149     if (imageFormat.isValid()) {
0150         attrs.append(" type=\"image\">");
0151         return attrs;
0152     }
0153 
0154     KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
0155     if (styleManager && textFormat.hasProperty(KoCharacterStyle::StyleId)) {
0156         int id = textFormat.intProperty(KoCharacterStyle::StyleId);
0157         KoCharacterStyle *characterStyle = styleManager->characterStyle(id);
0158         attrs.append(" characterStyle=\"id:").append(QString::number(id));
0159         if (characterStyle)
0160             attrs.append(" name:").append(characterStyle->name());
0161         attrs.append("\"");
0162     }
0163 
0164     QMap<int, QVariant> properties = textFormat.properties();
0165     attrs.append(" type=\"char\"");
0166     QString fontProps = fontProperties(textFormat);
0167     if (!fontProps.isEmpty())
0168         attrs.append(QString(" font=\"%1\"").arg(fontProps));
0169 
0170     if (textFormat.isAnchor()) {
0171         attrs.append(QString(" achorHref=\"%1\"").arg(textFormat.anchorHref()));
0172         attrs.append(QString(" achorName=\"%1\"").arg(textFormat.anchorName()));
0173     }
0174 
0175     foreach(int id, properties.keys()) {
0176         QString key, value;
0177         switch (id) {
0178         case QTextFormat::TextOutline: {
0179             key = "outline";
0180             QPen pen = qvariant_cast<QPen>(properties[id]);
0181             if (pen.style() == Qt::NoPen)
0182                 value = "false";
0183             else
0184                 value = pen.color().name();
0185             break;
0186         }
0187         case KoCharacterStyle::UnderlineStyle:
0188             key = "underlinestyle";
0189             value = QString::number(properties[id].toInt());
0190             break;
0191         case QTextFormat::TextUnderlineColor:
0192             key = "underlinecolor";
0193             value = qvariant_cast<QColor>(properties[id]).name();
0194             break;
0195         case KoCharacterStyle::UnderlineType:
0196             key = "underlinetype";
0197             value = QString::number(properties[id].toInt());
0198             break;
0199         case KoCharacterStyle::UnderlineMode:
0200             key = "underlinemode";
0201             value = QString::number(properties[id].toInt());
0202             break;
0203         case KoCharacterStyle::UnderlineWeight:
0204             key = "underlineweight";
0205             value = QString::number(properties[id].toInt());
0206             break;
0207         case KoCharacterStyle::UnderlineWidth:
0208             key = "underlinewidth";
0209             value = QString::number(properties[id].toDouble());
0210             break;
0211         case KoCharacterStyle::StrikeOutStyle:
0212             key = "strikeoutstyle";
0213             value = QString::number(properties[id].toInt());
0214             break;
0215         case KoCharacterStyle::StrikeOutColor:
0216             key = "strikeoutcolor";
0217             value = qvariant_cast<QColor>(properties[id]).name();
0218             break;
0219         case KoCharacterStyle::StrikeOutType:
0220             key = "strikeouttype";
0221             value = QString::number(properties[id].toInt());
0222             break;
0223         case KoCharacterStyle::StrikeOutMode:
0224             key = "strikeoutmode";
0225             value = QString::number(properties[id].toInt());
0226             break;
0227         case KoCharacterStyle::StrikeOutWeight:
0228             key = "strikeoutweight";
0229             value = QString::number(properties[id].toInt());
0230             break;
0231         case KoCharacterStyle::StrikeOutWidth:
0232             key = "strikeoutwidth";
0233             value = QString::number(properties[id].toDouble());
0234             break;
0235         case QTextFormat::ForegroundBrush:
0236             key = "foreground";
0237             value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
0238             break;
0239         case QTextFormat::BackgroundBrush:
0240             key = "background";
0241             value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
0242             break;
0243         case QTextFormat::BlockAlignment:
0244             key = "align";
0245             value = QString::number(properties[id].toInt());
0246             break;
0247         case QTextFormat::TextIndent:
0248             key = "textindent";
0249             value = QString::number(properties[id].toInt());
0250             break;
0251         case QTextFormat::BlockIndent:
0252             key = "indent";
0253             value = QString::number(properties[id].toInt());
0254             break;
0255         case KoCharacterStyle::Country:
0256             key = "country";
0257             value = properties[id].toString();
0258             break;
0259         case KoCharacterStyle::Language:
0260             key = "language";
0261             value = properties[id].toString();
0262             break;
0263         case KoCharacterStyle::HasHyphenation:
0264             key = "hyphenation";
0265             value = properties[id].toBool();
0266             break;
0267         case KoCharacterStyle::StrikeOutText:
0268             key = "strikeout-text";
0269             value = properties[id].toString();
0270             break;
0271         case KoCharacterStyle::FontCharset:
0272             key = "font-charset";
0273             value = properties[id].toString();
0274             break;
0275         case KoCharacterStyle::TextRotationAngle:
0276             key = "rotation-angle";
0277             value = QString::number(properties[id].toInt());
0278             break;
0279         case KoCharacterStyle::TextRotationScale:
0280             key = "text-rotation-scale";
0281             value = properties[id].toInt() == KoCharacterStyle::Fixed ? "Fixed" : "LineHeight";
0282             break;
0283         case KoCharacterStyle::TextScale:
0284             key = "text-scale";
0285             value = QString::number(properties[id].toInt());
0286             break;
0287         case KoCharacterStyle::InlineRdf:
0288             key = "inline-rdf";
0289             value = QString::number(properties[id].toInt());
0290             break;
0291         default:
0292             key = "unknown"+QString::number(id);
0293             value = QString::number(properties[id].toInt());
0294             break;
0295         }
0296         if (!key.isEmpty())
0297             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0298     }
0299     return attrs;
0300 }
0301 
0302 QString KoTextDebug::paraAttributes(const KoParagraphStyle &style)
0303 {
0304     QTextBlockFormat format;
0305     style.applyStyle(format);
0306     return paraAttributes(format);
0307 }
0308 
0309 QString KoTextDebug::paraAttributes(const QTextBlockFormat &blockFormat)
0310 {
0311     QString attrs;
0312     KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
0313     if (styleManager && blockFormat.hasProperty(KoParagraphStyle::StyleId)) {
0314         int id = blockFormat.intProperty(KoParagraphStyle::StyleId);
0315         KoParagraphStyle *paragraphStyle = styleManager->paragraphStyle(id);
0316         attrs.append(" paragraphStyle=\"id:").append(QString::number(id));
0317         if (paragraphStyle)
0318             attrs.append(" name:").append(paragraphStyle->name());
0319         attrs.append("\"");
0320     }
0321 
0322     QMap<int, QVariant> properties = blockFormat.properties();
0323     foreach(int id, properties.keys()) {
0324         QString key, value;
0325         switch (id) {
0326         // the following are 'todo'
0327         case KoParagraphStyle::PercentLineHeight:
0328         case KoParagraphStyle::FixedLineHeight:
0329         case KoParagraphStyle::MinimumLineHeight:
0330         case KoParagraphStyle::LineSpacing:
0331         case KoParagraphStyle::LineSpacingFromFont:
0332         case KoParagraphStyle::AlignLastLine:
0333         case KoParagraphStyle::WidowThreshold:
0334         case KoParagraphStyle::OrphanThreshold:
0335         case KoParagraphStyle::DropCapsTextStyle:
0336         case KoParagraphStyle::FollowDocBaseline:
0337         case KoParagraphStyle::HasLeftBorder:
0338         case KoParagraphStyle::HasTopBorder:
0339         case KoParagraphStyle::HasRightBorder:
0340         case KoParagraphStyle::HasBottomBorder:
0341         case KoParagraphStyle::BorderLineWidth:
0342         case KoParagraphStyle::SecondBorderLineWidth:
0343         case KoParagraphStyle::DistanceToSecondBorder:
0344         case KoParagraphStyle::LeftPadding:
0345         case KoParagraphStyle::TopPadding:
0346         case KoParagraphStyle::RightPadding:
0347         case KoParagraphStyle::BottomPadding:
0348         case KoParagraphStyle::LeftBorderColor:
0349         case KoParagraphStyle::TopInnerBorderWidth:
0350         case KoParagraphStyle::TopBorderSpacing:
0351         case KoParagraphStyle::TopBorderStyle:
0352         case KoParagraphStyle::TopBorderColor:
0353         case KoParagraphStyle::RightInnerBorderWidth:
0354         case KoParagraphStyle::RightBorderSpacing:
0355         case KoParagraphStyle::RightBorderStyle:
0356         case KoParagraphStyle::RightBorderColor:
0357         case KoParagraphStyle::BottomInnerBorderWidth:
0358         case KoParagraphStyle::BottomBorderSpacing:
0359         case KoParagraphStyle::BottomBorderStyle:
0360         case KoParagraphStyle::BottomBorderColor:
0361         case KoParagraphStyle::ListStyleId:
0362         case KoParagraphStyle::ListStartValue:
0363         case KoParagraphStyle::RestartListNumbering:
0364         case KoParagraphStyle::TextProgressionDirection:
0365         case KoParagraphStyle::MasterPageName:
0366         case KoParagraphStyle::OutlineLevel:
0367             break;
0368         case KoParagraphStyle::AutoTextIndent:
0369             key = "autotextindent";
0370             value = properties[id].toBool() ? "true" : "false" ;
0371             break;
0372 #ifdef PARAGRAPH_BORDER_DEBUG // because it tends to get annoyingly long :)
0373         case KoParagraphStyle::LeftBorderWidth:
0374             key = "border-width-left";
0375             value = QString::number(properties[id].toDouble()) ;
0376             break;
0377         case KoParagraphStyle::TopBorderWidth:
0378             key = "border-width-top";
0379             value = QString::number(properties[id].toDouble()) ;
0380             break;
0381         case KoParagraphStyle::RightBorderWidth:
0382             key = "border-width-right";
0383             value = QString::number(properties[id].toDouble()) ;
0384             break;
0385         case KoParagraphStyle::BottomBorderWidth:
0386             key = "border-width-bottom";
0387             value = QString::number(properties[id].toDouble()) ;
0388             break;
0389         case KoParagraphStyle::LeftBorderStyle:
0390             key = "border-style-left";
0391             value = QString::number(properties[id].toDouble()) ;
0392             break;
0393         case KoParagraphStyle::LeftBorderSpacing:
0394             key = "inner-border-spacing-left";
0395             value = QString::number(properties[id].toDouble()) ;
0396             break;
0397         case KoParagraphStyle::LeftInnerBorderWidth:
0398             key = "inner-border-width-left";
0399             value = QString::number(properties[id].toDouble()) ;
0400             break;
0401 #endif
0402         case KoParagraphStyle::TabStopDistance:
0403             key = "tab-stop-distance";
0404             value = QString::number(properties[id].toDouble());
0405             break;
0406         case KoParagraphStyle::TabPositions:
0407             key = "tab-stops";
0408             value.clear();
0409             foreach(const QVariant & qvtab, qvariant_cast<QList<QVariant> >(properties[id])) {
0410                 KoText::Tab tab = qvtab.value<KoText::Tab>();
0411                 value.append("{");
0412                 value.append(" pos:").append(QString::number(tab.position));
0413                 value.append(" type:").append(QString::number(tab.type));
0414                 if (! tab.delimiter.isNull())
0415                     value.append(" delim:").append(QString(tab.delimiter));
0416                 value.append(" leadertype:").append(QString::number(tab.leaderType));
0417                 value.append(" leaderstyle:").append(QString::number(tab.leaderStyle));
0418                 value.append(" leaderweight:").append(QString::number(tab.leaderWeight));
0419                 value.append(" leaderwidth:").append(QString().setNum(tab.leaderWidth));
0420                 value.append(" leadercolor:").append(tab.leaderColor.name());
0421                 if (! tab.leaderText.isEmpty())
0422                     value.append(" leadertext:").append(QString(tab.leaderText));
0423                 value.append("}, ");
0424             }
0425             break;
0426         case KoParagraphStyle::DropCaps:
0427             key = "drop-caps";
0428             value = QString::number(properties[id].toBool());
0429             break;
0430         case KoParagraphStyle::DropCapsLines:
0431             key = "drop-caps-lines";
0432             value = QString::number(properties[id].toInt());
0433             break;
0434         case KoParagraphStyle::DropCapsLength:
0435             key = "drop-caps-length";
0436             value = QString::number(properties[id].toInt());
0437             break;
0438         case KoParagraphStyle::DropCapsDistance:
0439             key = "drop-caps-distance";
0440             value = QString::number(properties[id].toDouble());
0441             break;
0442         case QTextFormat::BlockBottomMargin:
0443             value = QString::number(properties[id].toDouble());
0444             if (value != "0")
0445                 key = "block-bottom-margin";
0446             break;
0447         case QTextFormat::BlockTopMargin:
0448             value = QString::number(properties[id].toDouble());
0449             if (value != "0")
0450                 key = "block-top-margin";
0451             break;
0452         case QTextFormat::BlockLeftMargin:
0453             value = QString::number(properties[id].toDouble());
0454             if (value != "0")
0455                 key = "block-left-margin";
0456             break;
0457         case QTextFormat::BlockRightMargin:
0458             value = QString::number(properties[id].toDouble());
0459             if (value != "0")
0460                 key = "block-right-margin";
0461             break;
0462         case KoParagraphStyle::UnnumberedListItem:
0463             key = "unnumbered-list-item";
0464             value = QString::number(properties[id].toBool());
0465             break;
0466         case KoParagraphStyle::IsListHeader:
0467             key = "list-header";
0468             value = '1';
0469             break;
0470         case KoParagraphStyle::ListLevel:
0471             key = "list-level";
0472             value = QString::number(properties[id].toInt());
0473             break;
0474         default:
0475             break;
0476         }
0477         if (!key.isEmpty())
0478             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0479     }
0480     return attrs;
0481 }
0482 
0483 QString KoTextDebug::listAttributes(const QTextListFormat &listFormat)
0484 {
0485     QString attrs;
0486     KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
0487     if (styleManager && listFormat.hasProperty(KoListStyle::StyleId)) {
0488         int id = listFormat.intProperty(KoListStyle::StyleId);
0489         KoListStyle *listStyle = styleManager->listStyle(id);
0490         attrs.append(" listStyle=\"id:").append(QString::number(id));
0491         if (listStyle)
0492             attrs.append(" name:").append(listStyle->name());
0493         attrs.append("\"");
0494     }
0495 
0496     QMap<int, QVariant> properties = listFormat.properties();
0497     foreach(int id, properties.keys()) {
0498         QString key, value;
0499         switch (id) {
0500         case QTextListFormat::ListStyle:
0501             key = "type";
0502             value = QString::number(properties[id].toInt());
0503             break;
0504         case QTextListFormat::ListIndent:
0505             key = "indent";
0506             value = QString::number(properties[id].toDouble());
0507             break;
0508         case KoListStyle::ListItemPrefix:
0509             key = "prefix";
0510             value = properties[id].toString();
0511             break;
0512         case KoListStyle::ListItemSuffix:
0513             key = "suffix";
0514             value = properties[id].toString();
0515             break;
0516         case KoListStyle::StartValue:
0517             key = "start-value";
0518             value = QString::number(properties[id].toInt());
0519             break;
0520         case KoListStyle::Level:
0521             key = "level";
0522             value = QString::number(properties[id].toInt());
0523             break;
0524         case KoListStyle::DisplayLevel:
0525             key = "display-level";
0526             value = QString::number(properties[id].toInt());
0527             break;
0528         case KoListStyle::Alignment:
0529             key = "alignment";
0530             value = QString::number(properties[id].toInt());
0531             break;
0532         case KoListStyle::RelativeBulletSize:
0533             key = "bullet-size";
0534             value = QString::number(properties[id].toInt());
0535             break;
0536         case KoListStyle::BulletCharacter:
0537             key = "bullet-char";
0538             value = properties[id].toString();
0539             break;
0540         case KoListStyle::LetterSynchronization:
0541             key = "letter-sync";
0542             value = QString::number(properties[id].toInt());
0543             break;
0544         case KoListStyle::StyleId:
0545             key = "styleid";
0546             value = QString::number(properties[id].toInt());
0547             break;
0548         case KoListStyle::MinimumWidth:
0549             key = "minimum-width";
0550             value = QString::number(properties[id].toDouble());
0551             break;
0552         case KoListStyle::ListId:
0553             key = "list-id";
0554             value = QString::number(properties[id].toInt());
0555             break;
0556         case KoListStyle::IsOutline:
0557             key = "is-outline";
0558             value = properties[id].toBool();
0559             break;
0560         case KoListStyle::Indent:
0561             key = "indent";
0562             value = QString::number(properties[id].toInt());
0563             break;
0564         case KoListStyle::MinimumDistance:
0565             key = "minimum-distance";
0566             value = QString::number(properties[id].toDouble());
0567             break;
0568         case KoListStyle::Width:
0569             key = "width";
0570             value = QString::number(properties[id].toDouble());
0571             break;
0572         case KoListStyle::Height:
0573             key = "height";
0574             value = QString::number(properties[id].toDouble());
0575             break;
0576         case KoListStyle::BulletImage:
0577             key = "bullet-image";
0578             value = QString::number((quintptr)(properties[id].value<KoImageData*>()));
0579             break;
0580         case KoListStyle::Margin:
0581             key="margin-left";
0582             value =QString::number(properties[id].toInt());
0583             break;
0584         case KoListStyle::TextIndent:
0585             key="text-indent";
0586             value =QString::number(properties[id].toInt());
0587             break;
0588         case KoListStyle::AlignmentMode:
0589             key="label-alignment";
0590             value=QString(properties[id].toBool()? "true":"false");
0591             break;
0592         case KoListStyle::LabelFollowedBy:
0593             key="label-followed-by";
0594             value =QString::number(properties[id].toInt());
0595             break;
0596         case KoListStyle::TabStopPosition:
0597             key="tab-stop-position";
0598             value =QString::number(properties[id].toInt());
0599             break;
0600         default:
0601             break;
0602         }
0603         if (!key.isEmpty())
0604             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0605     }
0606     return attrs;
0607 }
0608 
0609 QString KoTextDebug::tableAttributes(const KoTableStyle &tableStyle)
0610 {
0611     QTextTableFormat format;
0612     tableStyle.applyStyle(format);
0613     return tableAttributes(format);
0614 }
0615 
0616 QString KoTextDebug::tableAttributes(const QTextTableFormat &tableFormat)
0617 {
0618     QString attrs;
0619     KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
0620     if (styleManager) {
0621         int id = tableFormat.intProperty(KoTableStyle::StyleId);
0622         KoTableStyle *tableStyle = styleManager->tableStyle(id);
0623         attrs.append(" tableStyle=\"id:").append(QString::number(id));
0624         if (tableStyle)
0625             attrs.append(" name:").append(tableStyle->name());
0626         attrs.append("\"");
0627     }
0628 
0629     QMap<int, QVariant> properties = tableFormat.properties();
0630     foreach(int id, properties.keys()) {
0631         QString key, value;
0632         switch (id) {
0633         case QTextTableFormat::TableColumnWidthConstraints:
0634         case QTextFormat::BackgroundBrush:
0635             key = "background";
0636             value = qvariant_cast<QBrush>(properties[id]).color().name(); // beware!
0637             break;
0638         case QTextFormat::BlockAlignment:
0639             key = "alignment";
0640             switch (properties[id].toInt()) {
0641                 case Qt::AlignLeft:
0642                     value = "left";
0643                     break;
0644                 case Qt::AlignRight:
0645                     value = "right";
0646                     break;
0647                 case Qt::AlignHCenter:
0648                     value = "center";
0649                     break;
0650                 case Qt::AlignJustify:
0651                     value = "justify";
0652                     break;
0653                 default:
0654                     value.clear();
0655                     break;
0656             }
0657             break;
0658         case KoTableStyle::KeepWithNext:
0659             key = "keep-with-next";
0660             value = properties[id].toBool() ? "true" : "false";
0661             break;
0662         case KoTableStyle::BreakBefore:
0663             key = "break-before";
0664             value = properties[id].toBool() ? "true" : "false";
0665             break;
0666         case KoTableStyle::BreakAfter:
0667             key = "break-after";
0668             value = properties[id].toBool() ? "true" : "false";
0669             break;
0670         case KoTableStyle::MayBreakBetweenRows:
0671             key = "may-break-between-rows";
0672             value = properties[id].toBool() ? "true" : "false";
0673             break;
0674         case KoTableStyle::MasterPageName:
0675             key = "master-page-name";
0676             value = properties[id].toString();
0677             break;
0678         case QTextTableFormat::TableColumns:
0679             key = "columns";
0680             value = QString::number(properties[id].toInt());
0681             break;
0682         case QTextTableFormat::TableCellSpacing:
0683             key = "cell-spacing";
0684             value = QString::number(properties[id].toDouble());
0685             break;
0686         case QTextTableFormat::TableHeaderRowCount:
0687             key = "header-row-count";
0688             value = QString::number(properties[id].toInt());
0689             break;
0690         default:
0691             break;
0692         }
0693         if (!key.isEmpty())
0694             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0695     }
0696     return attrs;
0697 }
0698 
0699 QString KoTextDebug::frameAttributes(const QTextFrameFormat &frameFormat)
0700 {
0701     QString attrs;
0702 
0703     QMap<int, QVariant> properties = frameFormat.properties();
0704     foreach(int id, properties.keys()) {
0705         QString key, value;
0706         switch (id) {
0707         case QTextFrameFormat::FrameBorderBrush:
0708             break;
0709         case QTextFrameFormat::FrameBorderStyle:
0710             key = "border-style";
0711             // determine border style.
0712             switch (properties[id].toInt()) {
0713             case QTextFrameFormat::BorderStyle_None:
0714                 value = "None";
0715                 break;
0716             case QTextFrameFormat::BorderStyle_Dotted:
0717                 value = "Dotted";
0718                 break;
0719             case QTextFrameFormat::BorderStyle_Dashed:
0720                 value = "Dashed";
0721                 break;
0722             case QTextFrameFormat::BorderStyle_Solid:
0723                 value = "Solid";
0724                 break;
0725             case QTextFrameFormat::BorderStyle_Double:
0726                 value = "Double";
0727                 break;
0728             case QTextFrameFormat::BorderStyle_DotDash:
0729                 value = "DotDash";
0730                 break;
0731             case QTextFrameFormat::BorderStyle_DotDotDash:
0732                 value = "DotDotDash";
0733                 break;
0734             case QTextFrameFormat::BorderStyle_Groove:
0735                 value = "Groove";
0736                 break;
0737             case QTextFrameFormat::BorderStyle_Ridge:
0738                 value = "Ridge";
0739                 break;
0740             case QTextFrameFormat::BorderStyle_Inset:
0741                 value = "Inset";
0742                 break;
0743             case QTextFrameFormat::BorderStyle_Outset:
0744                 value = "Outset";
0745                 break;
0746             default:
0747                 value = "Unknown";
0748                 break;
0749             }
0750             break;
0751         case QTextFrameFormat::FrameBorder:
0752             key = "border";
0753             value = QString::number(properties[id].toDouble());
0754             break;
0755         case QTextFrameFormat::FrameMargin:
0756             key = "margin";
0757             value = QString::number(properties[id].toDouble());
0758             break;
0759         case QTextFrameFormat::FramePadding:
0760             key = "padding";
0761             value = QString::number(properties[id].toDouble());
0762             break;
0763         case QTextFrameFormat::FrameWidth:
0764             key = "width";
0765             value = QString::number(properties[id].toDouble());
0766             break;
0767         case QTextFrameFormat::FrameHeight:
0768             key = "height";
0769             value = QString::number(properties[id].toDouble());
0770             break;
0771         case QTextFrameFormat::FrameTopMargin:
0772             key = "top-margin";
0773             value = QString::number(properties[id].toDouble());
0774             break;
0775         case QTextFrameFormat::FrameBottomMargin:
0776             key = "bottom-margin";
0777             value = QString::number(properties[id].toDouble());
0778             break;
0779         case QTextFrameFormat::FrameLeftMargin:
0780             key = "left-margin";
0781             value = QString::number(properties[id].toDouble());
0782             break;
0783         case QTextFrameFormat::FrameRightMargin:
0784             key = "right-margin";
0785             value = QString::number(properties[id].toDouble());
0786             break;
0787         default:
0788             break;
0789         }
0790         if (!key.isEmpty())
0791             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0792     }
0793     return attrs;
0794 }
0795 
0796 QString KoTextDebug::tableCellAttributes(const KoTableCellStyle &tableCellStyle)
0797 {
0798     QTextTableCellFormat format;
0799     tableCellStyle.applyStyle(format);
0800     return tableCellAttributes(format);
0801 }
0802 
0803 QString KoTextDebug::tableCellAttributes(const QTextTableCellFormat &tableCellFormat)
0804 {
0805     QString attrs;
0806     KoStyleManager *styleManager = document ? KoTextDocument(document).styleManager() : 0;
0807     if (styleManager) {
0808         int id = tableCellFormat.intProperty(KoTableCellStyle::StyleId);
0809         KoTableCellStyle *tableCellStyle = styleManager->tableCellStyle(id);
0810         attrs.append(" tableCellStyle=\"id:").append(QString::number(id));
0811         if (tableCellStyle)
0812             attrs.append(" name:").append(tableCellStyle->name());
0813         attrs.append("\"");
0814     }
0815 
0816     QMap<int, QVariant> properties = tableCellFormat.properties();
0817     foreach(int id, properties.keys()) {
0818         QString key, value;
0819         switch (id) {
0820         case QTextTableCellFormat::TableCellRowSpan:
0821             key = "row-span";
0822             value = QString::number(properties[id].toInt());
0823             break;
0824         case QTextTableCellFormat::TableCellColumnSpan:
0825             key = "column-span";
0826             value = QString::number(properties[id].toInt());
0827             break;
0828         case QTextFormat::TableCellTopPadding:
0829             key = "top-padding";
0830             value = QString::number(properties[id].toDouble());
0831             break;
0832         case QTextFormat::TableCellBottomPadding:
0833             key = "bottom-padding";
0834             value = QString::number(properties[id].toDouble());
0835             break;
0836         case QTextFormat::TableCellLeftPadding:
0837             key = "left-padding";
0838             value = QString::number(properties[id].toDouble());
0839             break;
0840         case QTextFormat::TableCellRightPadding:
0841             key = "right-padding";
0842             value = QString::number(properties[id].toDouble());
0843             break;
0844         case KoTableCellStyle::MasterPageName:
0845             key = "master-page-name";
0846             value = properties[id].toString();
0847             break;
0848         default:
0849             break;
0850         }
0851         if (!key.isEmpty())
0852             attrs.append(" ").append(key).append("=\"").append(value).append("\"");
0853     }
0854     return attrs;
0855 }
0856 
0857 void KoTextDebug::dumpFrame(const QTextFrame *frame, QTextStream &out)
0858 {
0859     depth += INDENT;
0860 
0861     dumpIndent(depth);
0862     out << "<frame" << frameAttributes(frame->frameFormat()) << '>' << endl;
0863 
0864     QTextFrame::iterator iterator = frame->begin();
0865 
0866     for (; !iterator.atEnd() && !iterator.atEnd(); ++iterator) {
0867         QTextFrame *childFrame = iterator.currentFrame();
0868         QTextBlock textBlock = iterator.currentBlock();
0869 
0870         if (childFrame) {
0871             QTextTable *table = qobject_cast<QTextTable *>(childFrame);
0872             if (table) {
0873                 dumpTable(table, out);
0874             } else {
0875                 dumpFrame(frame, out);
0876             }
0877         } else if (textBlock.isValid()) {
0878             dumpBlock(textBlock, out);
0879         }
0880     }
0881 
0882     dumpIndent(depth);
0883     out << "</frame>" << endl;
0884     depth -= INDENT;
0885 }
0886 
0887 void KoTextDebug::dumpBlock(const QTextBlock &block, QTextStream &out)
0888 {
0889     depth += INDENT;
0890 
0891     QString attrs;
0892     attrs.append(paraAttributes(block.blockFormat()));
0893     //attrs.append(" blockcharformat=\"").append(textAttributes(QTextCursor(block).blockCharFormat())).append('\"');
0894     attrs.append(textAttributes(QTextCursor(block).blockCharFormat()));
0895 
0896     QTextList *list = block.textList();
0897     if (list) {
0898         attrs.append(" list=\"item:").append(QString::number(list->itemNumber(block) + 1)).append('/')
0899         .append(QString::number(list->count()));
0900         attrs.append('"');
0901         attrs.append(listAttributes(list->format()));
0902     }
0903 
0904     dumpIndent(depth);
0905     out << "<block" << attrs << '>' << endl;
0906 
0907     QTextBlock::Iterator iterator = block.begin();
0908     for (; !iterator.atEnd() && !iterator.atEnd(); ++iterator) {
0909         QTextFragment fragment = iterator.fragment();
0910         if (fragment.isValid()) {
0911             dumpFragment(fragment, out);
0912         }
0913     }
0914     dumpIndent(depth);
0915     out << "</block>" << endl;
0916     depth -= INDENT;
0917     if (block.next().isValid())
0918         out << ' ';
0919 }
0920 
0921 void KoTextDebug::dumpTable(const QTextTable *table, QTextStream &out)
0922 {
0923     depth += INDENT;
0924 
0925     QString attrs;
0926     attrs.append(tableAttributes(table->format()));
0927     attrs.append(frameAttributes(table->frameFormat())); // include frame attributes too.
0928 
0929     dumpIndent(depth);
0930     out << "<table" << attrs << '>' << endl;
0931 
0932     // loop through all the cells in the table and dump the cells.
0933     for (int row = 0; row < table->rows(); ++row) {
0934         for (int column = 0; column < table->columns(); ++column) {
0935             dumpTableCell(table->cellAt(row, column), out);
0936         }
0937     }
0938 
0939     dumpIndent(depth);
0940     out << "</table>" << endl;
0941     depth -= INDENT;
0942 }
0943 
0944 void KoTextDebug::dumpTableCell(const QTextTableCell &cell, QTextStream &out)
0945 {
0946     depth += INDENT;
0947 
0948     QString attrs;
0949     attrs.append(textAttributes(cell.format()));
0950     attrs.append(tableCellAttributes(cell.format().toTableCellFormat()));
0951 
0952     dumpIndent(depth);
0953     out << "<cell" << attrs << '>' << endl;
0954 
0955     // iterate through the cell content.
0956     QTextFrame::iterator cellIter = cell.begin();
0957     while (!cellIter.atEnd()) {
0958         if (cellIter.currentFrame() != 0) {
0959             // content is a frame or table.
0960             dumpFrame(cellIter.currentFrame(), out);
0961         } else {
0962             // content is a block.
0963             dumpBlock(cellIter.currentBlock(), out);
0964         }
0965         ++cellIter;
0966     }
0967 
0968     dumpIndent(depth);
0969     out << "</cell>\n";
0970 
0971     depth -= INDENT;
0972 }
0973 
0974 void KoTextDebug::dumpFragment(const QTextFragment &fragment, QTextStream &out)
0975 {
0976     depth += INDENT;
0977 
0978     QTextCharFormat charFormat = fragment.charFormat();
0979     KoInlineObject *inlineObject = KoTextDocument(document).inlineTextObjectManager()->inlineTextObject(charFormat);
0980     if (inlineObject) {
0981         QString cf = inlineObjectAttributes(charFormat);
0982 
0983         dumpIndent(depth);
0984         out << "<fragment" << cf << ">\n";
0985     } else {
0986         QString cf = textAttributes(charFormat);
0987 
0988         dumpIndent(depth);
0989         out << "<fragment" << cf << ">\n";
0990         dumpIndent(depth + INDENT);
0991         out << '|' << fragment.text() << "|\n";
0992         dumpIndent(depth);
0993         out << "</fragment>\n";
0994     }
0995 
0996     depth -= INDENT;
0997 }
0998