void KoList::setStyle(KListStyle *style) { if (style == 0) { KStyleManager *styleManager = KTextDocument(d->document).styleManager(); Q_ASSERT(styleManager); style = styleManager->defaultListStyle(); } if (style != d->style) { if (d->style) disconnect(d->style, 0, this, 0); d->style = style->clone(this); connect(d->style, SIGNAL(styleChanged(int)), this, SLOT(styleChanged(int))); } for (int i = 0; i < d->textLists.count(); i++) { QTextList *textList = d->textLists.value(i).data(); if (!textList) continue; KListLevelProperties properties = d->style->levelProperties(i+1); if (properties.listId()) d->textListIds[i] = properties.listId(); QTextListFormat format; properties.applyStyle(format); textList->setFormat(format); d->invalidate(textList->item(0)); } }
void TextTools::indentLessClicked() { QTextList* list = cursor()->currentList(); if (list == 0) { QTextBlockFormat format = cursor()->blockFormat(); int indent = format.indent(); if (indent) { indent--; format.setIndent(indent); cursor()->insertBlock(format); updateText(); } return; } QTextCharFormat format = cursor()->blockCharFormat(); QTextListFormat listFormat = list->format(); QTextBlock block = cursor()->block(); if (block.next().isValid()) block = block.next(); else { block = QTextBlock(); } cursor()->insertBlock(block.blockFormat()); cursor()->setCharFormat(block.charFormat()); updateText(); }
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; } }
void MainWindow::highlightListItems() { QTextCursor cursor = editor->textCursor(); QTextList *list = cursor.currentList(); if (!list) return; cursor.beginEditBlock(); //! [0] for (int index = 0; index < list->count(); ++index) { QTextBlock listItem = list->item(index); //! [0] QTextBlockFormat newBlockFormat = listItem.blockFormat(); newBlockFormat.setBackground(Qt::lightGray); QTextCursor itemCursor = cursor; itemCursor.setPosition(listItem.position()); //itemCursor.movePosition(QTextCursor::StartOfBlock); itemCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); itemCursor.setBlockFormat(newBlockFormat); /* //! [1] processListItem(listItem); //! [1] */ //! [2] } //! [2] cursor.endEditBlock(); }
void TextEditWidget::sl_IncreaseListIndent_Triggered() { QTextCursor cursor = this->textField->textCursor(); QTextList *textList = cursor.currentList(); if (!textList) {return;} QTextListFormat format = textList->format(); format.setIndent(format.indent() + 1); textList->setFormat(format); }
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; }
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; }
void KoList::updateStoredList(const QTextBlock &block) { if (block.textList()) { int level = block.textList()->format().property(KListStyle::Level).toInt(); QTextList *textList = block.textList(); QTextListFormat format = textList->format(); format.setProperty(KListStyle::ListId, (KListStyle::ListIdType)(textList)); textList->setFormat(format); d->textLists[level-1] = textList; d->textListIds[level-1] = (KListStyle::ListIdType)textList; } }
void TestChangeTrackedDelete::testListItemDelete() { TextTool *textTool = new TextTool(new MockCanvas); KoTextEditor *textEditor = textTool->textEditor(); QVERIFY(textEditor); QTextDocument *document = textEditor->document(); KTextDocumentLayout *layout = qobject_cast<KTextDocumentLayout*>(document->documentLayout()); QTextCursor *cursor = textEditor->cursor(); insertSampleList(document); cursor->setPosition(46); cursor->setPosition(78, QTextCursor::KeepAnchor); ChangeTrackedDeleteCommand *delCommand = new ChangeTrackedDeleteCommand(ChangeTrackedDeleteCommand::NextChar, textTool); textEditor->addCommand(delCommand); QCOMPARE(document->characterAt(46).unicode(), (ushort)(QChar::ObjectReplacementCharacter)); // This is wierd. Without this loop present the succeeding call to inlineTextObject returs NULL. Why ?????? for (int i=0; i<document->characterCount(); i++) { cursor->setPosition(i); } cursor->setPosition(47); KDeleteChangeMarker *testMarker = dynamic_cast<KDeleteChangeMarker*>(layout->inlineTextObjectManager()->inlineTextObject(*cursor)); QTextDocumentFragment deleteData = KTextDocument(document).changeTracker()->elementById(testMarker->changeId())->deleteData(); QTextDocument deleteDocument; QTextCursor deleteCursor(&deleteDocument); deleteCursor.insertFragment(deleteData); bool listFound = false; for (int i=0; i < deleteDocument.characterCount(); i++) { deleteCursor.setPosition(i); if (deleteCursor.currentList()) { listFound = true; continue; } } QVERIFY(listFound == true); QTextList *deletedList = deleteCursor.currentList(); bool deletedListStatus = deletedList->format().boolProperty(KDeleteChangeMarker::DeletedList); QVERIFY (deletedListStatus == false); bool deletedListItemStatus; deletedListItemStatus = deletedList->item(0).blockFormat().boolProperty(KDeleteChangeMarker::DeletedListItem); QVERIFY(deletedListItemStatus == false); deletedListItemStatus = deletedList->item(1).blockFormat().boolProperty(KDeleteChangeMarker::DeletedListItem); QVERIFY(deletedListItemStatus == true); delete textTool; }
void TextTools::orderedListClicked() { QTextCharFormat format = cursor()->charFormat(); QTextListFormat listFormat; QTextList* list = cursor()->currentList(); if (list) { listFormat = list->format(); int indent = listFormat.indent(); listFormat.setIndent(indent + 1); } listFormat.setStyle(QTextListFormat::ListDecimal); cursor()->insertList(listFormat); cursor()->setCharFormat(format); updateText(); }
void MainWindow::insertList() { QTextCursor cursor = editor->textCursor(); cursor.beginEditBlock(); QTextList *list = cursor.currentList(); QTextListFormat listFormat; if (list) listFormat = list->format(); listFormat.setStyle(QTextListFormat::ListDisc); listFormat.setIndent(listFormat.indent() + 1); cursor.insertList(listFormat); cursor.endEditBlock(); }
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 TextEditWidget::sl_ListButton_Triggered(QAction* action) { if (!action) { WARNING("Null pointer recieved"); return; } QTextListFormat::Style style = (QTextListFormat::Style)action->data().toInt(); QTextCursor cursor = this->textField->textCursor(); QTextList *textList = cursor.currentList(); if (!textList) { WARNING("Wrong button state"); return; } QTextListFormat format = textList->format(); format.setStyle(style); textList->setFormat(format); }
void MainWindow::insertList() { QTextCursor cursor = editor->textCursor(); cursor.beginEditBlock(); QTextList *list = cursor.currentList(); //! [0] listFormat = QTextListFormat() if list: listFormat = list.format() listFormat.setIndent(listFormat.indent() + 1) listFormat.setStyle(QTextListFormat.ListDisc) cursor.insertList(listFormat) //! [0] cursor.endEditBlock(); }
void ParagraphSettingsDialog::slotApply() { emit startMacro(i18n("Paragraph Settings\n")); KoParagraphStyle chosenStyle; m_paragraphGeneral->save(&chosenStyle); QTextBlockFormat format; chosenStyle.applyStyle(format); m_cursor->mergeBlockFormat(format); if (chosenStyle.listStyle()) { ChangeListCommand *cmd = new ChangeListCommand(*m_cursor, chosenStyle.listStyle(), 0, ChangeListCommand::MergeWithAdjacentList); m_tool->addCommand(cmd); } else { QTextList *list = m_cursor->block().textList(); if (list) { // then remove it. list->remove(m_cursor->block()); } } emit stopMacro(); }
void KoList::setContinueNumbering(int level, bool enable) { Q_ASSERT(level > 0 && level <= 10); level = qMax(qMin(level, 10), 1); QBitArray bitArray = d->properties[ContinueNumbering].toBitArray(); if (bitArray.isEmpty()) bitArray.resize(10); bitArray.setBit(level-1, enable); d->properties[ContinueNumbering] = bitArray; QTextList *textList = d->textLists.value(level-1).data(); if (!textList) return; QTextListFormat format = textList->format(); if (enable) { format.setProperty(KListStyle::ContinueNumbering, true); } else { format.clearProperty(KListStyle::ContinueNumbering); } textList->setFormat(format); }
void TextEditWidget::sl_ListButton_Toggled(bool toggle) { QTextCursor cursor = this->textField->textCursor(); if (toggle) { if (cursor.currentList()) { WARNING("Wrong button state"); return; } QTextListFormat format; format.setStyle(QTextListFormat::ListDisc); cursor.createList(format); } else { QTextList *textList = cursor.currentList(); if (!cursor.currentList()) { WARNING("Wrong button state"); return; } QTextBlock block = cursor.block(); textList->remove(block); QTextBlockFormat format = block.blockFormat(); format.setIndent(0); cursor.setBlockFormat(format); } }
void MRichTextEdit::slotCursorPositionChanged() { QTextList *pTextList = f_textedit->textCursor().currentList(); if (m_lastBlockList && (pTextList == m_lastBlockList || (pTextList != 0 && m_lastBlockList != 0 && pTextList->format().style() == m_lastBlockList->format().style()))) { return; } m_lastBlockList = pTextList; if (pTextList) { QTextListFormat lfmt = pTextList->format(); if (lfmt.style() == QTextListFormat::ListDisc) { f_list_bullet->setChecked(true); f_list_ordered->setChecked(false); } else if (lfmt.style() == QTextListFormat::ListDecimal) { f_list_bullet->setChecked(false); f_list_ordered->setChecked(true); } else { f_list_bullet->setChecked(false); f_list_ordered->setChecked(false); } } else { f_list_bullet->setChecked(false); f_list_ordered->setChecked(false); } }
void KoTextWriter::write(const QTextDocument *document, int from, int to) { d->document = const_cast<QTextDocument*>(document); d->styleManager = KoTextDocument(document).styleManager(); QTextBlock fromblock = document->findBlock(from); QTextBlock toblock = document->findBlock(to); QTextCursor fromcursor(fromblock); QTextTable *currentTable = fromcursor.currentTable(); QTextList *currentList = fromcursor.currentList(); // NOTE even better would be if we create a new table/list out of multiple selected // tablecells/listitems that contain only the selected cells/items. But following // at least enables copying a whole list/table while still being able to copy/paste // only parts of the text within a list/table (see also bug 275990). if (currentTable || currentList) { if (from == 0 && to < 0) { // save everything means also save current table and list currentTable = 0; currentList = 0; } else { QTextCursor tocursor(toblock); //fromcursor.setPosition(from, QTextCursor::KeepAnchor); tocursor.setPosition(to, QTextCursor::KeepAnchor); if (!fromcursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor)) { fromcursor = QTextCursor(); } if (!tocursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor)) { tocursor = QTextCursor(); } // save the whole table if all cells are selected if (currentTable) { QTextTableCell fromcell = currentTable->cellAt(from); QTextTableCell tocell = currentTable->cellAt(to); if ((fromcursor.isNull() || fromcursor.currentTable() != currentTable) && (tocursor.isNull() || tocursor.currentTable() != currentTable) && fromcell.column() == 0 && fromcell.row() == 0 && tocell.column() == currentTable->columns()-1 && tocell.row() == currentTable->rows()-1 ) { currentTable = 0; } } // save the whole list if all list-items are selected if (currentList) { int fromindex = currentList->itemNumber(fromblock); int toindex = currentList->itemNumber(toblock); if ((fromcursor.isNull() || fromcursor.currentList() != currentList) && (tocursor.isNull() || tocursor.currentList() != currentList) && fromindex <= 0 && (toindex < 0 || toindex == currentList->count()-1) ) { currentList = 0; } } } } QHash<QTextList *, QString> listStyles = d->saveListStyles(fromblock, to); d->globalFrom = from; d->globalTo = to; d->writeBlocks(const_cast<QTextDocument *>(document), from, to, listStyles, currentTable, currentList); }
void MainWindow::showList() { QTextCursor cursor = editor->textCursor(); QTextFrame *frame = cursor.currentFrame(); if (!frame) return; QTreeWidget *treeWidget = new QTreeWidget; treeWidget->setColumnCount(1); QStringList headerLabels; headerLabels << tr("Lists"); treeWidget->setHeaderLabels(headerLabels); QTreeWidgetItem *parentItem = 0; QTreeWidgetItem *item; QTreeWidgetItem *lastItem = 0; parentItems.clear(); previousItems.clear(); //! [3] QTextFrame::iterator it; for (it = frame->begin(); !(it.atEnd()); ++it) { QTextBlock block = it.currentBlock(); if (block.isValid()) { QTextList *list = block.textList(); if (list) { int index = list->itemNumber(block); //! [3] if (index == 0) { parentItems.append(parentItem); previousItems.append(lastItem); listStructures.append(list); parentItem = lastItem; lastItem = 0; if (parentItem != 0) item = new QTreeWidgetItem(parentItem, lastItem); else item = new QTreeWidgetItem(treeWidget, lastItem); } else { while (parentItem != 0 && listStructures.last() != list) { listStructures.pop_back(); parentItem = parentItems.takeLast(); lastItem = previousItems.takeLast(); } if (parentItem != 0) item = new QTreeWidgetItem(parentItem, lastItem); else item = new QTreeWidgetItem(treeWidget, lastItem); } item->setText(0, block.text()); lastItem = item; /* //! [4] processListItem(list, index); //! [4] */ //! [5] } //! [5] //! [6] } //! [6] //! [7] } //! [7] treeWidget->setWindowTitle(tr("List Contents")); treeWidget->show(); }
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(); }
void TestListStyle::testListStyle() { KListStyle ls; KListLevelProperties llp = ls.levelProperties(2); QCOMPARE(llp.level(), 2); llp.setStyle(KListStyle::AlphaLowerItem); KListLevelProperties llp2 = ls.levelProperties(2); QVERIFY(llp2.style() != llp.style()); ls.setLevelProperties(llp); QCOMPARE(llp.level(), 2); QCOMPARE(llp.style(), KListStyle::AlphaLowerItem); llp = ls.levelProperties(2); QCOMPARE(llp.level(), 2); QCOMPARE(llp.style(), KListStyle::AlphaLowerItem); QTextDocument doc; KTextDocument kodoc(&doc); kodoc.setStyleManager(new KStyleManager); QTextCursor cursor(&doc); cursor.insertText("foo\nbar\nBaz\n"); QTextBlock block = doc.begin(); ls.applyStyle(block, 2); QVERIFY(block.textList()); QTextList *textList = block.textList(); QTextListFormat format = textList->format(); QCOMPARE(format.intProperty(QTextListFormat::ListStyle), (int)(KListStyle::AlphaLowerItem)); block = block.next(); QVERIFY(block.isValid()); ls.applyStyle(block, 2); QVERIFY(block.textList()); QCOMPARE(block.textList(), textList); ls.applyStyle(block, 10); // should set the properties of the only one that is set, level 1 QVERIFY(block.textList()); textList = block.textList(); format = textList->format(); QCOMPARE(format.intProperty(QTextListFormat::ListStyle), (int)(KListStyle::AlphaLowerItem)); // getting a properties without setting it doesn't change the list. KListLevelProperties l4 = ls.levelProperties(4); QCOMPARE(l4.level(), 4); QCOMPARE(l4.displayLevel(), 0); // default l4.setDisplayLevel(3); QCOMPARE(l4.displayLevel(), 3); QCOMPARE(ls.hasLevelProperties(4), false); KListLevelProperties anotherL4 = ls.levelProperties(4); QCOMPARE(anotherL4.level(), 4); QCOMPARE(anotherL4.displayLevel(), 0); // default QCOMPARE(ls.hasLevelProperties(4), false); QCOMPARE(ls.hasLevelProperties(5), false); // new levels are a copy of the existing level. KListLevelProperties l5 = ls.levelProperties(5); QCOMPARE(l5.displayLevel(), 0); QCOMPARE(l5.style(), KListStyle::AlphaLowerItem); QCOMPARE(l5.indent(), 0.); }
void TestDocumentLayout::testNumberedList() { initForNewTest("Base\nListItem1\nListItem2\nListItem3\nListItem4\nListItem5\nListItem6\nListItem6\nListItem7\nListItem8\nListItem9\nListItem10\nListItem11\nListItem12\n"); KoParagraphStyle style; m_styleManager->add(&style); QTextBlock block = m_doc->begin(); style.applyStyle(block); block = block.next(); KoListStyle listStyle; KoListLevelProperties llp; llp.setStyle(KoListStyle::DecimalItem); listStyle.setLevelProperties(llp); style.setListStyle(&listStyle); QTextList *previous = 0; int i; for (i = 1; i <= 9; i++) { QVERIFY(block.isValid()); // qDebug() << "->" << block.text(); style.applyStyle(block); QTextList *textList = block.textList(); QVERIFY(textList); if (previous == 0) { previous = textList; } else { QCOMPARE(textList, previous); } QCOMPARE(textList->format().intProperty(QTextListFormat::ListStyle), (int)(KoListStyle::DecimalItem)); block = block.next(); } m_layout->layout(); QTextLayout *blockLayout = m_block.layout(); QCOMPARE(blockLayout->lineAt(0).x(), 0.0); QTextBlock blok = m_doc->begin().next(); qreal indent = blok.layout()->lineAt(0).x(); QVERIFY(indent > 0.0); for (i = 1; i <= 9; ++i) { // qDebug() << "=>" << blok.text(); QTextList *textList = blok.textList(); QVERIFY(textList); QCOMPARE(blok.layout()->lineAt(0).x(), indent); // all the same indent. blok = blok.next(); } // now make number of listitems be more than 10, so we use 2 digits. for (i = 9; i <= 12; ++i) { QVERIFY(block.isValid()); style.applyStyle(block); // qDebug() << "->" << block.text(); block = block.next(); } m_layout->layout(); blockLayout = m_block.layout(); QCOMPARE(blockLayout->lineAt(0).x(), 0.0); blok = m_doc->begin().next(); qreal indent2 = blok.layout()->lineAt(0).x(); QVERIFY(indent2 > indent); // since it takes an extra digit for (i = 2; i <= 12; ++i) { // qDebug() << "=>" << blok.text(); QCOMPARE(blok.layout()->lineAt(0).x(), indent2); // all the same indent. blok = blok.next(); } // now to make sure the text is actually properly set. block = m_doc->begin().next(); i = 1; while (block.isValid() && i < 13) { KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(data); QCOMPARE(data->counterText(), QString::number(i++)); block = block.next(); } llp.setListItemSuffix("."); llp.setStartValue(4); listStyle.setLevelProperties(llp); QTextCursor cursor(m_doc); cursor.setPosition(10); // listItem1 QTextBlockFormat format = cursor.blockFormat(); format.setProperty(KoParagraphStyle::ListStartValue, 4); cursor.setBlockFormat(format); cursor.setPosition(40); // listItem4 format = cursor.blockFormat(); format.setProperty(KoParagraphStyle::ListStartValue, 12); cursor.setBlockFormat(format); // at this point we start numbering at 4. Have 4, 5, 6, 12, 13, 14, 15 etc m_layout->layout(); // now to make sur the text is actually properly set. block = m_doc->begin().next(); i = 4; while (block.isValid() && i < 22) { if (i == 7) { i = 12; } KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(data); QCOMPARE(data->counterText(), QString::number(i++)); block = block.next(); } }
void HtmlExporter::emitBlock( const QTextBlock &block ) { // save and later restore, in case we 'change' the default format by // emitting block char format information // NOTE the bottom line is commented, to use default charFormat, which can be set from outside. //QTextCharFormat oldDefaultCharFormat = defaultCharFormat; QString blockTag; bool isBlockQuote = false; const QTextBlockFormat blockFormat = block.blockFormat(); if ( blockFormat.hasProperty( BilboTextFormat::IsBlockQuote ) && blockFormat.boolProperty( BilboTextFormat::IsBlockQuote ) ) { isBlockQuote = true; } QTextList *list = block.textList(); if ( list ) { if ( list->itemNumber( block ) == 0 ) { // first item? emit <ul> or appropriate // qDebug() << "first item" << endl; if ( isBlockQuote ) { html += QLatin1String( "<blockquote>" ); } const QTextListFormat format = list->format(); const int style = format.style(); switch ( style ) { case QTextListFormat::ListDecimal: html += QLatin1String( "<ol" ); break; case QTextListFormat::ListDisc: html += QLatin1String( "<ul" ); break; case QTextListFormat::ListCircle: html += QLatin1String( "<ul type=\"circle\"" ); break; case QTextListFormat::ListSquare: html += QLatin1String( "<ul type=\"square\"" ); break; case QTextListFormat::ListLowerAlpha: html += QLatin1String( "<ol type=\"a\"" ); break; case QTextListFormat::ListUpperAlpha: html += QLatin1String( "<ol type=\"A\"" ); break; default: html += QLatin1String( "<ul" ); // ### should not happen //qDebug() << html; } /* if (format.hasProperty(QTextFormat::ListIndent)) { html += QLatin1String(" style=\"-qt-list-indent: "); html += QString::number(format.indent()); html += QLatin1String(";\""); }*/ html += QLatin1Char( '>' ); } blockTag = QLatin1String( "li" ); // html += QLatin1String( "<li " ); } // const QTextBlockFormat blockFormat = block.blockFormat(); if ( blockFormat.hasProperty( QTextFormat::BlockTrailingHorizontalRulerWidth ) ) { if ( ( blockFormat.hasProperty( BilboTextFormat::IsHtmlTagSign ) ) && ( blockFormat.boolProperty( BilboTextFormat::IsHtmlTagSign ) ) ) { html += QLatin1String( "<!--split-->" ); return; } else { html += QLatin1String( "<hr" ); QTextLength width = blockFormat.lengthProperty( QTextFormat::BlockTrailingHorizontalRulerWidth ); if ( width.type() != QTextLength::VariableLength ) { emitTextLength( "width", width ); } else { html += QLatin1Char( ' ' ); } html += QLatin1String( "/>" ); return; } } const bool pre = blockFormat.nonBreakableLines(); if ( pre ) { // qDebug() << "NonBreakable lines" << endl; // if (list) { // html += QLatin1Char('>'); // } // html += QLatin1String( "<pre" ); // emitBlockAttributes( block ); // html += QLatin1Char( '>' ); blockTag = QLatin1String( "pre" ); } else { if (!list) { if ( isBlockQuote ) { html += QLatin1String( "<blockquote>" ); } if ( ( blockFormat.hasProperty( BilboTextFormat::HtmlHeading ) ) && ( blockFormat.intProperty( BilboTextFormat::HtmlHeading ) ) ) { const int index = blockFormat.intProperty( BilboTextFormat::HtmlHeading ); blockTag = QLatin1Char( 'h' ) + QString::number( index ); } else { //html += QLatin1String("<div"); // html += QLatin1String( "<p" ); blockTag = QLatin1String( "p" ); } } } if ( !blockTag.isEmpty() ) { html += QLatin1Char( '<' ) + blockTag; emitBlockAttributes( block ); html += QLatin1Char( '>' ); } QTextBlock::Iterator it = block.begin(); for ( ; !it.atEnd(); ++it ) { emitFragment( it.fragment(), blockFormat ); } if ( !blockTag.isEmpty() ) { html += QLatin1String( "</" ) + blockTag + QLatin1String( ">\n" ); } // if ( pre ) { // html += QLatin1String( "</pre>\n" ); // } else { // if ( list ) { // html += QLatin1String( "</li>\n" ); // } else { // if ( blockFormat::boolProperty( BilboTextFormat::IsHtmlHeading ) ) { // const int index = format.intProperty( QTextFormat::FontSizeAdjustment ); // switch ( index ) { // case -2: // html += QLatin1String( "</h6>" ); // break; // case -1: // html += QLatin1String( "</h5>" ); // break; // case 0: // html += QLatin1String( "</h4>" ); // break; // case 1: // html += QLatin1String( "</h3>" ); // break; // case 2: // html += QLatin1String( "<h2" ); // break; // case 3: // html += QLatin1String( "<h1" ); // break; // } // } else { // html += QLatin1String( "</p>\n" ); // } // } // } // HACK html.replace( QRegExp("<br[\\s]*/>[\\n]*<br[\\s]*/>[\\n]*"),"<br /> <br />" ); if ( list ) { if ( list->itemNumber( block ) == list->count() - 1 ) { // last item? close list if ( isOrderedList( list->format().style() ) ) { html += QLatin1String( "</ol>\n" ); } else { html += QLatin1String( "</ul>\n" ); } if ( isBlockQuote ) { html += QLatin1String( "</blockquote>\n" ); } } } else { if ( isBlockQuote ) { html += QLatin1String( "</blockquote>\n" ); } } // NOTE the bottom line is commented, to use default charFormat, which can be set from outside. //defaultCharFormat = oldDefaultCharFormat; }
void KoTextWriter::write(QTextDocument *document, int from, int to) { d->styleManager = KoTextDocument(document).styleManager(); d->layout = dynamic_cast<KoTextDocumentLayout*>(document->documentLayout()); d->changeTracker = KoTextDocument(document).changeTracker(); // Q_ASSERT(d->changeTracker); Q_ASSERT(d->layout); Q_ASSERT(d->layout->inlineTextObjectManager()); QTextBlock block = document->findBlock(from); KoTextDocument textDocument(document); QHash<QTextList *, QString> listStyles = saveListStyles(block, to); QList<QTextList*> textLists; // Store the current lists being stored. KoList *currentList = 0; while (block.isValid() && ((to == -1) || (block.position() <= to))) { QTextBlockFormat blockFormat = block.blockFormat(); QTextList *textList = block.textList(); int headingLevel = 0, numberedParagraphLevel = 0; if (textList) { headingLevel = blockFormat.intProperty(KoParagraphStyle::OutlineLevel); numberedParagraphLevel = blockFormat.intProperty(KoParagraphStyle::ListLevel); } if (textList && !headingLevel && !numberedParagraphLevel) { if (!textLists.contains(textList)) { KoList *list = textDocument.list(block); if (currentList != list) { while (!textLists.isEmpty()) { textLists.removeLast(); d->writer->endElement(); // </text:list> if (!textLists.isEmpty()) { d->writer->endElement(); // </text:list-element> } } currentList = list; } else if (!textLists.isEmpty()) // sublists should be written within a list-item d->writer->startElement("text:list-item", false); d->writer->startElement("text:list", false); d->writer->addAttribute("text:style-name", listStyles[textList]); if (textList->format().hasProperty(KoListStyle::ContinueNumbering)) d->writer->addAttribute("text:continue-numbering", textList->format().boolProperty(KoListStyle::ContinueNumbering) ? "true" : "false"); textLists.append(textList); } else if (textList != textLists.last()) { while ((!textLists.isEmpty()) && (textList != textLists.last())) { textLists.removeLast(); d->writer->endElement(); // </text:list> d->writer->endElement(); // </text:list-element> } } const bool listHeader = blockFormat.boolProperty(KoParagraphStyle::IsListHeader) || blockFormat.boolProperty(KoParagraphStyle::UnnumberedListItem); d->writer->startElement(listHeader ? "text:list-header" : "text:list-item", false); if (KoListStyle::isNumberingStyle(textList->format().style())) { if (KoTextBlockData *blockData = dynamic_cast<KoTextBlockData *>(block.userData())) { d->writer->startElement("text:number", false); d->writer->addTextSpan(blockData->counterText()); d->writer->endElement(); } } } else { // Close any remaining list... while (!textLists.isEmpty()) { textLists.removeLast(); d->writer->endElement(); // </text:list> if (!textLists.isEmpty()) { d->writer->endElement(); // </text:list-element> } } if (textList && numberedParagraphLevel) { d->writer->startElement("text:numbered-paragraph", false); d->writer->addAttribute("text:level", numberedParagraphLevel); d->writer->addAttribute("text:style-name", listStyles.value(textList)); } } saveParagraph(block, from, to); if (!textLists.isEmpty() || numberedParagraphLevel) { // we are generating a text:list-item. Look forward and generate unnumbered list items. while (true) { QTextBlock nextBlock = block.next(); if (!nextBlock.isValid() || !((to == -1) || (nextBlock.position() < to))) break; if (!nextBlock.textList() || !nextBlock.blockFormat().boolProperty(KoParagraphStyle::UnnumberedListItem)) break; block = nextBlock; saveParagraph(block, from, to); } } // We must check if we need to close a previously-opened text:list node. if ((block.textList() && !headingLevel) || numberedParagraphLevel) d->writer->endElement(); block = block.next(); } // while // Close any remaining lists while (!textLists.isEmpty()) { textLists.removeLast(); d->writer->endElement(); // </text:list> if (!textLists.isEmpty()) { d->writer->endElement(); // </text:list-element> } } }
QString Format::frameToString( QTextFrame *frame ) { QString out; QTextFrame::iterator it; for( it = frame->begin(); it != frame->end(); ++it ) { QTextBlock block = it.currentBlock(); if ( block.isValid() ) { out += "<block"; QTextCursor c( block ); QDateTime dt = TextFormats::lastModified( c ); if ( dt.isValid() ) { out += " lastmodified=\"" + dt.toString( Qt::ISODate ) + "\""; } if ( TextFormats::isTitle( c ) ) { out += " titlestyle=\"title\""; } else if ( TextFormats::isSubTitle( c ) ) { out += " titlestyle=\"subtitle\""; } QTextBlockFormat blockFormat = block.blockFormat(); if ( blockFormat.isValid() ) { QTextList *list = block.textList(); if ( list ) { QTextListFormat f = list->format(); out += " liststyle=\""; switch( f.style() ) { default: case QTextListFormat::ListDisc: out += "disc"; break; case QTextListFormat::ListDecimal: out += "decimal"; break; } out += "\""; out += " listindent=\"" + QString::number( f.indent() ) + "\""; } else { if ( blockFormat.indent() != 0 ) { out += " blockindent=\"" + QString::number( blockFormat.indent() ) + "\""; } } } out += ">\n"; QTextBlock::iterator it2; for( it2 = block.begin(); it2 != block.end(); ++it2 ) { QTextFragment fragment = it2.fragment(); if ( !fragment.isValid() ) continue; QString text = fragment.text(); QString outText; for( int i = 0; i < text.size(); ++i ) { if ( text.at( i ) == 0xfffc ) { outText += "<todo status=\""; QTextImageFormat imageFormat = fragment.charFormat().toImageFormat(); if ( imageFormat.isValid() ) { if ( imageFormat.name().contains( "done" ) ) outText += "done"; else outText += "todo"; } else { dbg() << "NO IMAGE FORMAT" << endl; } outText += "\"/>"; } else { outText += escape( QString( text.at( i ) ) ); } } out += " <fragment"; QTextCharFormat format = fragment.charFormat(); if ( !format.anchorHref().isEmpty() ) { out += " link=\"" + escape( format.anchorHref() ) + "\""; } if ( format.fontWeight() == QFont::Bold ) { out += " bold=\"true\""; } if ( format.fontItalic() ) { out += " italic=\"true\""; } if ( format.hasProperty( QTextFormat::FontPointSize ) && format.fontPointSize() != 10 ) { out += " fontsize=\"" + QString::number( format.fontPointSize() ) + "\""; } if ( outText.trimmed().isEmpty() ) outText.replace( " ", "[FIXME:space]" ); out += ">" + outText + "</fragment>\n"; } out += "</block>"; out += "\n"; } QTextFrame *f = it.currentFrame(); if ( f ) { QTextFrameFormat format = f->frameFormat(); out += "<frame"; if ( format.hasProperty( TextFormats::FrameType ) ) { out += " type="; if ( format.property( TextFormats::FrameType ) == TextFormats::CodeFrame ) { out += "\"code\""; } else { out += "\"undefined\""; } } out += ">\n"; out += frameToString( f ); out += "</frame>\n"; } } return out; }