bool Converter::convertList(QTextCursor *cursor, const QDomElement &element) { const QString styleName = element.attribute("style-name"); const ListFormatProperty property = m_StyleInformation->listProperty(styleName); QTextListFormat format; QTextList *list = 0; if (cursor->currentList()) { format = cursor->currentList()->format(); } property.apply(&format); if (!firstTime) list = cursor->insertList(format); else list = cursor->createList(format); firstTime = true; QDomElement itemChild = element.firstChildElement(); while (!itemChild.isNull()) { if (itemChild.tagName() == QLatin1String("list-item")) { QDomElement childElement = itemChild.firstChildElement(); while (!childElement.isNull()) { if (childElement.tagName() == QLatin1String("p")) { if (!convertParagraph(cursor, childElement, QTextBlockFormat(), true)) { return false; } list->add(cursor->block()); } else if (childElement.tagName() == QLatin1String("list")) { if (!convertList(cursor, childElement)) { return false; } list->add(cursor->block()); } childElement = childElement.nextSiblingElement(); } } itemChild = itemChild.nextSiblingElement(); } firstTime = false; return true; }
QTextList *tryReadList(QTextList *list, const QString &line) { QTextList *listOut = list; QRegularExpression exp("^( *)(\\d+\\.|\\*) (.*)$"); QRegularExpressionMatch match = exp.match(line); if (match.hasMatch()) { const int indent = match.captured(1).size() / 2 + 1; const QString contents = match.captured(3); const bool ordered = match.captured(2) != "*"; QTextListFormat fmt; fmt.setStyle(ordered ? QTextListFormat::ListDecimal : QTextListFormat::ListDisc); fmt.setIndent(indent); if (!listOut || fmt != listOut->format()) { listOut = cursor.insertList(fmt); } else { cursor.insertBlock(); } readInlineText(contents); listOut->add(cursor.block()); return listOut; } else { return 0; } }
bool Converter::convertList( QTextCursor *cursor, const QDomElement &element ) { const QString styleName = element.attribute( QStringLiteral("style-name") ); const ListFormatProperty property = mStyleInformation->listProperty( styleName ); QTextListFormat format; if ( cursor->currentList() ) { // we are in a nested list format = cursor->currentList()->format(); format.setIndent( format.indent() + 1 ); } property.apply( &format, 0 ); QTextList *list = cursor->insertList( format ); QDomElement itemChild = element.firstChildElement(); int loop = 0; while ( !itemChild.isNull() ) { if ( itemChild.tagName() == QLatin1String( "list-item" ) ) { loop++; QDomElement childElement = itemChild.firstChildElement(); while ( !childElement.isNull() ) { QTextBlock prevBlock; if ( childElement.tagName() == QLatin1String( "p" ) ) { if ( loop > 1 ) cursor->insertBlock(); prevBlock = cursor->block(); if ( !convertParagraph( cursor, childElement, QTextBlockFormat(), true ) ) return false; } else if ( childElement.tagName() == QLatin1String( "list" ) ) { prevBlock = cursor->block(); if ( !convertList( cursor, childElement ) ) return false; } if( prevBlock.isValid() ) list->add( prevBlock ); childElement = childElement.nextSiblingElement(); } } itemChild = itemChild.nextSiblingElement(); } return true; }
void KoList::add(const QTextBlock &block, int level) { if (!block.isValid()) return; if (level == 0) { // fetch the first proper level we have level = 1; // if nothing works... for (int i = 1; i <= 10; i++) { if (d->style->hasLevelProperties(i)) { level = i; break; } } } remove(block); QTextList *textList = d->textLists.value(level-1).data(); if (!textList) { QTextCursor cursor(block); QTextListFormat format = d->style->listFormat(level); if (continueNumbering(level)) format.setProperty(KListStyle::ContinueNumbering, true); textList = cursor.createList(format); format.setProperty(KListStyle::ListId, (KListStyle::ListIdType)(textList)); textList->setFormat(format); d->textLists[level-1] = textList; d->textListIds[level-1] = (KListStyle::ListIdType)textList; } else { textList->add(block); } QTextCursor cursor(block); QTextBlockFormat blockFormat = cursor.blockFormat(); if (d->style->styleId()) { blockFormat.setProperty(KParagraphStyle::ListStyleId, d->style->styleId()); } else { blockFormat.clearProperty(KParagraphStyle::ListStyleId); } if (d->type == KoList::TextList) { blockFormat.clearProperty(KParagraphStyle::ListLevel); } else { blockFormat.setProperty(KParagraphStyle::ListLevel, level); } cursor.setBlockFormat(blockFormat); d->invalidate(block); }
void QGithubMarkdown::read(const QByteArray &markdown, QTextDocument *target) { doc = target; doc->clear(); cursor = QTextCursor(doc); cursor.beginEditBlock(); const QList<Token> tokens = tokenize(clean(QString::fromUtf8(markdown))); const QList<Paragraph> paragraphs = paragraphize(tokens); const auto paralists = listize(paragraphs); //std::for_each(paragraphs.begin(), paragraphs.end(), [](const Paragraph &item){qDebug() << item;}); bool firstBlock = true; for (const auto paralist : paralists) { auto insertTokens = [&](const QList<Token> &tokens, const QTextCharFormat &format, const bool isCode) { QTextCharFormat fmt(format); QTextCharFormat codeFmt(format); codeFmt.setFontFamily("Monospace"); QListIterator<Token> iterator(tokens); while (iterator.hasNext()) { const Token token = iterator.next(); if (isCode) { cursor.insertText(token.source); } else { if (token.type == Token::Bold) { if (fmt.fontWeight() == QFont::Bold) { fmt.setFontWeight(QFont::Normal); } else { fmt.setFontWeight(QFont::Bold); } } else if (token.type == Token::Italic) { fmt.setFontItalic(!fmt.fontItalic()); } else if (token.type == Token::InlineCodeDelimiter) { while (iterator.hasNext()) { const Token next = iterator.next(); if (next.type == Token::InlineCodeDelimiter) { break; } else { cursor.insertText(token.source, codeFmt); } } } else if (token.type == Token::Character) { cursor.insertText(token.content.toChar(), fmt); } else { cursor.insertText(token.source, fmt); } } } }; if (paralist.second.indent == -1) { const Paragraph paragraph = paralist.first; QTextCharFormat charFmt; QTextBlockFormat blockFmt; blockFmt.setBottomMargin(5.0f); if (Paragraph::FirstHeading <= paragraph.type && paragraph.type <= Paragraph::LastHeading) { charFmt.setFontPointSize(sizeMap[paragraph.type]); } else if (paragraph.type == Paragraph::Quote) { blockFmt.setIndent(1); } else if (paragraph.type == Paragraph::Code) { blockFmt.setNonBreakableLines(true); charFmt.setFontFamily("Monospace"); } if (!firstBlock) { cursor.insertBlock(); } else { firstBlock = false; } cursor.setBlockFormat(blockFmt); cursor.block().setUserState(paragraph.type); insertTokens(paragraph.tokens, charFmt, paragraph.type == Paragraph::Code); } else { const List list = paralist.second; qDebug() << "##########################" << list.indent << list.ordered; std::for_each(list.paragraphs.begin(), list.paragraphs.end(), [](const Paragraph &item){qDebug() << item;}); cursor.setBlockFormat(QTextBlockFormat()); cursor.setBlockCharFormat(QTextCharFormat()); QTextListFormat listFormat; listFormat.setStyle(list.ordered ? QTextListFormat::ListDecimal : QTextListFormat::ListDisc); listFormat.setIndent(list.indent); QTextList *l = cursor.insertList(listFormat); qDebug() << "inserting list" << list.indent; bool firstBlock = true; for (const Paragraph ¶graph : list.paragraphs) { if (firstBlock) { firstBlock = false; } else { cursor.insertBlock(); qDebug() << "inserting block"; } insertTokens(paragraph.tokens, QTextCharFormat(), false); qDebug() << l->count(); l->add(cursor.block()); qDebug() << l->count(); qDebug() << "inserting characters"; } } } cursor.endEditBlock(); qDebug() << doc->toHtml(); }