kpimidentities/richtextbuilders
kmarkupdirector.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kmarkupdirector.h"
00024 #include "kmarkupdirector_p.h"
00025
00026 #include <kdebug.h>
00027
00028 #include <QFlags>
00029 #include <QTextDocument>
00030 #include <QTextDocumentFragment>
00031 #include <QString>
00032 #include <QStack>
00033 #include <QTextFrame>
00034 #include <QTextTable>
00035 #include <QTextList>
00036 #include <QTextCursor>
00037 #include <QTextCharFormat>
00038 #include <QMap>
00039 #include <QColor>
00040 #include <QBrush>
00041
00042 #include "kabstractmarkupbuilder.h"
00043
00044 KMarkupDirector::KMarkupDirector(KAbstractMarkupBuilder* builder) :
00045 d(new Private(this))
00046 {
00047 d->builder = builder;
00048 }
00049
00050 KMarkupDirector::~KMarkupDirector()
00051 {
00052 delete d;
00053 }
00054
00055 void KMarkupDirector::processDocumentContents(QTextFrame::iterator start, QTextFrame::iterator end)
00056 {
00057 for (QTextFrame::iterator it = start; ((!it.atEnd()) && (it != end)); ++it) {
00058 QTextFrame *frame = it.currentFrame();
00059 if (frame) {
00060 QTextTable *table = dynamic_cast<QTextTable*>(frame);
00061 if (table) {
00062 processTable(table);
00063 } else {
00064 processFrame(frame);
00065 }
00066 } else {
00067 processBlock(it.currentBlock());
00068 }
00069 }
00070 }
00071
00072 void KMarkupDirector::processFrame(QTextFrame* frame)
00073 {
00074 processDocumentContents(frame->begin(), frame->end());
00075 }
00076
00077 void KMarkupDirector::processBlock(const QTextBlock &block)
00078 {
00079 if (block.isValid()) {
00080 QTextList *list = block.textList();
00081 if (list) {
00082
00083
00084 if ((list->item(0) == block) && (!block.previous().textList())) {
00085 processList(block);
00086 }
00087 } else {
00088 processBlockContents(block);
00089 }
00090 }
00091 }
00092
00093 void KMarkupDirector::processTable(QTextTable *table)
00094 {
00095 QTextTableFormat format = table->format();
00096 QVector<QTextLength> colLengths = format.columnWidthConstraints();
00097
00098 QTextLength tableWidth = format.width();
00099 QString sWidth;
00100
00101 if (tableWidth.type() == QTextLength::PercentageLength) {
00102 sWidth = "%1%";
00103 sWidth = sWidth.arg(tableWidth.rawValue());
00104 } else if (tableWidth.type() == QTextLength::FixedLength) {
00105 sWidth = "%1";
00106 sWidth = sWidth.arg(tableWidth.rawValue());
00107 }
00108
00109 d->builder->beginTable(format.cellPadding(), format.cellSpacing(), sWidth);
00110
00111 int headerRowCount = format.headerRowCount();
00112
00113 QList<QTextTableCell> alreadyProcessedCells;
00114
00115 for (int row = 0; row < table->rows(); ++row) {
00116
00117
00118
00119
00120
00121
00122 d->builder->beginTableRow();
00123
00124
00125
00126
00127
00128 for (int column = 0; column < table->columns(); ++column) {
00129
00130 QTextTableCell tableCell = table->cellAt(row, column);
00131
00132 int columnSpan = tableCell.columnSpan();
00133 int rowSpan = tableCell.rowSpan();
00134 if ((rowSpan > 1) || (columnSpan > 1)) {
00135 if (alreadyProcessedCells.contains(tableCell)) {
00136
00137 continue;
00138 } else {
00139 alreadyProcessedCells.append(tableCell);
00140 }
00141 }
00142
00143 QTextLength cellWidth = colLengths.at(column);
00144
00145 QString sCellWidth;
00146
00147 if (cellWidth.type() == QTextLength::PercentageLength) {
00148 sCellWidth = "%1%";
00149 sCellWidth = sCellWidth.arg(cellWidth.rawValue());
00150 } else if (cellWidth.type() == QTextLength::FixedLength) {
00151 sCellWidth = "%1";
00152 sCellWidth = sCellWidth.arg(cellWidth.rawValue());
00153 }
00154
00155
00156 if (row < headerRowCount) {
00157 d->builder->beginTableHeaderCell(sCellWidth, columnSpan, rowSpan);
00158 } else {
00159 d->builder->beginTableCell(sCellWidth, columnSpan, rowSpan);
00160 }
00161
00162 processTableCell(tableCell);
00163
00164 if (row < headerRowCount) {
00165 d->builder->endTableHeaderCell();
00166 } else {
00167 d->builder->endTableCell();
00168 }
00169 }
00170 d->builder->endTableRow();
00171 }
00172 d->builder->endTable();
00173 }
00174
00175 void KMarkupDirector::processTableCell(const QTextTableCell &cell)
00176 {
00177 processDocumentContents(cell.begin(), cell.end());
00178 }
00179
00180 void KMarkupDirector::processList(const QTextBlock &ablock)
00181 {
00182 QTextBlock block(ablock);
00183
00184 QTextList *list = block.textList();
00185 if (!list) {
00186 return;
00187 }
00188
00189 QList<QTextList*> lists;
00190
00191 while (block.isValid() && block.textList()) {
00192 if (list->item(0) == block) {
00193
00194 QTextListFormat::Style style = list->format().style();
00195 d->builder->beginList(style);
00196
00197 lists.append(list);
00198 }
00199
00200 d->builder->beginListItem();
00201 processBlockContents(block);
00202 d->builder->endListItem();
00203
00204 block = block.next();
00205
00206 if (block.isValid()) {
00207 QTextList *newList = block.textList();
00208
00209 if (!newList) {
00210 while (!lists.isEmpty()) {
00211 lists.removeLast();
00212 d->builder->endList();
00213 }
00214 } else if (newList == list) {
00215
00216 continue;
00217 } else if (newList != list) {
00218 if (newList->item(0) == block) {
00219 list = newList;
00220 continue;
00221 } else {
00222 while (!lists.isEmpty()) {
00223 if (block.textList() != lists.last()) {
00224 lists.removeLast();
00225 d->builder->endList();
00226 } else {
00227 break;
00228 }
00229 }
00230 continue;
00231 }
00232 }
00233 } else {
00234
00235
00236 while (!lists.isEmpty()) {
00237 lists.removeLast();
00238 d->builder->endList();
00239 }
00240 }
00241 }
00242 }
00243
00244 void KMarkupDirector::processBlockContents(const QTextBlock &block)
00245 {
00246 QTextBlockFormat blockFormat = block.blockFormat();
00247 Qt::Alignment blockAlignment = blockFormat.alignment();
00248
00249
00250
00251 if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
00252 d->builder->insertHorizontalRule();
00253 return;
00254 }
00255
00256 QTextBlock::iterator it;
00257 it = block.begin();
00258
00259
00260
00261 if (it.atEnd()) {
00262
00263 d->builder->addNewline();
00264 return;
00265 }
00266
00267 QTextFragment fragment = it.fragment();
00268
00269
00270
00271 if (fragment.isValid()) {
00272 QTextCharFormat fragmentFormat = fragment.charFormat();
00273
00274 if (!fragmentFormat.isImageFormat() && fragment.text().at(0).category() == QChar::Separator_Line) {
00275
00276
00277 foreach(QChar c, fragment.text()) {
00278
00279 if (c.category() == QChar::Separator_Line) {
00280 d->builder->addNewline();
00281 }
00282 }
00283 return;
00284 }
00285 }
00286
00287
00288 if (!block.textList())
00289 {
00290
00291
00292 d->builder->beginParagraph(blockAlignment
00293
00294
00295
00296
00297 );
00298 }
00299 while (!it.atEnd()) {
00300 fragment = it.fragment();
00301 if (fragment.isValid()) {
00302 QTextCharFormat fragmentFormat = fragment.charFormat();
00303
00304 if (fragmentFormat.isImageFormat()) {
00305
00306 QTextImageFormat imageFormat = fragmentFormat.toImageFormat();
00307 d->builder->insertImage(imageFormat.name(), imageFormat.width(), imageFormat.height());
00308 ++it;
00309 continue;
00310 } else {
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 d->processOpeningElements(it);
00334
00335
00336
00337 QStringList sl = fragment.text().split(QChar( QChar::LineSeparator ) );
00338 QStringListIterator i(sl);
00339 bool paraClosed = false;
00340 while (i.hasNext())
00341 {
00342 d->builder->appendLiteralText(i.next());
00343 if (i.hasNext())
00344 {
00345 if (i.peekNext().isEmpty())
00346 {
00347 if (!paraClosed)
00348 {
00349 d->builder->endParagraph();
00350 paraClosed = true;
00351 }
00352 d->builder->addNewline();
00353 } else if (paraClosed) {
00354 d->builder->beginParagraph(blockAlignment);
00355 paraClosed = false;
00356 }
00357 }
00358 }
00359
00360 ++it;
00361 d->processClosingElements(it);
00362 }
00363 }
00364 }
00365
00366
00367 if (!block.textList())
00368 {
00369 d->builder->endParagraph();
00370 }
00371
00372 }
00373
00374 void KMarkupDirector::constructContent(QTextDocument* doc)
00375 {
00376 QTextFrame *rootFrame = doc->rootFrame();
00377 processFrame(rootFrame);
00378 }