void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const { writer.writeStartElement(textNS, QString::fromLatin1("list-style")); writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("L%1").arg(formatIndex)); QTextListFormat::Style style = format.style(); if (style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha || style == QTextListFormat::ListUpperAlpha || style == QTextListFormat::ListLowerRoman || style == QTextListFormat::ListUpperRoman) { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number")); writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style)); if (format.hasProperty(QTextFormat::ListNumberSuffix)) writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), format.numberSuffix()); else writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1(".")); if (format.hasProperty(QTextFormat::ListNumberPrefix)) writer.writeAttribute(styleNS, QString::fromLatin1("num-prefix"), format.numberPrefix()); } else { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-bullet")); writer.writeAttribute(textNS, QString::fromLatin1("bullet-char"), bulletChar(style)); } writer.writeAttribute(textNS, QString::fromLatin1("level"), QString::number(format.indent())); writer.writeEmptyElement(styleNS, QString::fromLatin1("list-level-properties")); writer.writeAttribute(foNS, QString::fromLatin1("text-align"), QString::fromLatin1("start")); QString spacing = QString::fromLatin1("%1mm").arg(format.indent() * 8); writer.writeAttribute(textNS, QString::fromLatin1("space-before"), spacing); //writer.writeAttribute(textNS, QString::fromLatin1("min-label-width"), spacing); writer.writeEndElement(); // list-level-style-* writer.writeEndElement(); // list-style }
void ListItemsHelper::recalculate() { //kDebug(32500); const QTextListFormat format = m_textList->format(); const KoListStyle::Style listStyle = static_cast<KoListStyle::Style>(m_textList->format().style()); const QString prefix = format.stringProperty(KoListStyle::ListItemPrefix); const QString suffix = format.stringProperty(KoListStyle::ListItemSuffix); const int level = format.intProperty(KoListStyle::Level); int dp = format.intProperty(KoListStyle::DisplayLevel); if (dp > level) dp = level; const int displayLevel = dp ? dp : 1; int startValue = 1; if (format.hasProperty(KoListStyle::StartValue)) startValue = format.intProperty(KoListStyle::StartValue); if (format.boolProperty(KoListStyle::ContinueNumbering)) { // Look for the index of a previous list of the same numbering style and level for (QTextBlock tb = m_textList->item(0).previous(); tb.isValid(); tb = tb.previous()) { if (!tb.textList() || tb.textList() == m_textList) continue; // no list here or it's the same list; keep looking QTextListFormat otherFormat = tb.textList()->format(); if (otherFormat.intProperty(KoListStyle::Level) != level) break; // found a different list but of a different level if (otherFormat.style() == format.style()) { if (KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(tb.userData())) startValue = data->counterIndex() + 1; // Start from previous list value + 1 } break; } } int index = startValue; QList<QTextList*> sublistsToRecalculate; qreal width = format.doubleProperty(KoListStyle::MinimumWidth); for (int i = 0; i < m_textList->count(); i++) { QTextBlock tb = m_textList->item(i); //kDebug(32500) <<" *" << tb.text(); KoTextBlockData *data = dynamic_cast<KoTextBlockData*>(tb.userData()); if (!data) { data = new KoTextBlockData(); tb.setUserData(data); } QTextBlockFormat blockFormat = tb.blockFormat(); if (blockFormat.boolProperty(KoParagraphStyle::UnnumberedListItem) || blockFormat.boolProperty(KoParagraphStyle::IsListHeader)) { data->setCounterText(QString()); data->setPartialCounterText(QString()); continue; } if (blockFormat.boolProperty(KoParagraphStyle::RestartListNumbering)) index = format.intProperty(KoListStyle::StartValue); const int paragIndex = blockFormat.intProperty(KoParagraphStyle::ListStartValue); if (paragIndex > 0) index = paragIndex; //check if this is the first of this level meaning we should start from startvalue QTextBlock b = tb.previous(); for (;b.isValid(); b = b.previous()) { if (b.textList() == m_textList) break; // all fine if (b.textList() == 0) continue; QTextListFormat otherFormat = b.textList()->format(); if (otherFormat.style() != format.style()) continue; // uninteresting for us if (b.textList()->format().intProperty(KoListStyle::Level) < level) { index = startValue; break; } } QString item; if (displayLevel > 1) { int checkLevel = level; int tmpDisplayLevel = displayLevel; for (QTextBlock b = tb.previous(); tmpDisplayLevel > 1 && b.isValid(); b = b.previous()) { if (b.textList() == 0) continue; QTextListFormat lf = b.textList()->format(); if (lf.style() != format.style()) continue; // uninteresting for us const int otherLevel = lf.intProperty(KoListStyle::Level); if (checkLevel <= otherLevel) continue; /*if(needsRecalc(b->textList())) { TODO } */ KoTextBlockData *otherData = dynamic_cast<KoTextBlockData*>(b.userData()); if (! otherData) { kWarning(32500) << "Missing KoTextBlockData, Skipping textblock"; continue; } if (tmpDisplayLevel - 1 < otherLevel) { // can't just copy it fully since we are // displaying less then the full counter item += otherData->partialCounterText(); tmpDisplayLevel--; checkLevel--; for (int i = otherLevel + 1; i < level; i++) { tmpDisplayLevel--; item += ".1"; // add missing counters. } } else { // just copy previous counter as prefix QString otherPrefix = lf.stringProperty(KoListStyle::ListItemPrefix); QString otherSuffix = lf.stringProperty(KoListStyle::ListItemSuffix); QString pureCounter = otherData->counterText().mid(otherPrefix.size()); pureCounter = pureCounter.left(pureCounter.size() - otherSuffix.size()); item += pureCounter; for (int i = otherLevel + 1; i < level; i++) item += ".1"; // add missing counters. tmpDisplayLevel = 0; break; } } for (int i = 1; i < tmpDisplayLevel; i++) item = "1." + item; // add missing counters. } if ((listStyle == KoListStyle::DecimalItem || listStyle == KoListStyle::AlphaLowerItem || listStyle == KoListStyle::UpperAlphaItem || listStyle == KoListStyle::RomanLowerItem || listStyle == KoListStyle::UpperRomanItem) && !(item.isEmpty() || item.endsWith('.') || item.endsWith(' '))) { item += '.'; } bool calcWidth = true; QString partialCounterText; switch (listStyle) { case KoListStyle::DecimalItem: partialCounterText = QString::number(index); break; case KoListStyle::AlphaLowerItem: partialCounterText = intToAlpha(index, Lowercase, m_textList->format().boolProperty(KoListStyle::LetterSynchronization)); break; case KoListStyle::UpperAlphaItem: partialCounterText = intToAlpha(index, Uppercase, m_textList->format().boolProperty(KoListStyle::LetterSynchronization)); break; case KoListStyle::RomanLowerItem: partialCounterText = intToRoman(index); break; case KoListStyle::UpperRomanItem: partialCounterText = intToRoman(index).toUpper(); break; case KoListStyle::SquareItem: case KoListStyle::DiscItem: case KoListStyle::CircleItem: case KoListStyle::HeavyCheckMarkItem: case KoListStyle::BallotXItem: case KoListStyle::RightArrowItem: case KoListStyle::RightArrowHeadItem: case KoListStyle::RhombusItem: case KoListStyle::BoxItem: { calcWidth = false; item = ' '; width = m_displayFont.pointSizeF(); int percent = format.intProperty(KoListStyle::BulletSize); if (percent > 0) width = width * (percent / 100.0); break; } case KoListStyle::CustomCharItem: calcWidth = false; if (format.intProperty(KoListStyle::BulletCharacter)) item = QString(QChar(format.intProperty(KoListStyle::BulletCharacter))); width = m_fm.width(item); break; case KoListStyle::None: calcWidth = false; width = 10.0; // simple indenting break; case KoListStyle::Bengali: case KoListStyle::Gujarati: case KoListStyle::Gurumukhi: case KoListStyle::Kannada: case KoListStyle::Malayalam: case KoListStyle::Oriya: case KoListStyle::Tamil: case KoListStyle::Telugu: case KoListStyle::Tibetan: case KoListStyle::Thai: partialCounterText = intToScript(index, listStyle); break; case KoListStyle::Abjad: case KoListStyle::ArabicAlphabet: case KoListStyle::AbjadMinor: partialCounterText = intToScriptList(index, listStyle); break; case KoListStyle::ImageItem: calcWidth = false; width = qMax(format.doubleProperty(KoListStyle::Width), (qreal)1.0); break; default: // others we ignore. calcWidth = false; } data->setCounterIsImage(listStyle == KoListStyle::ImageItem); data->setPartialCounterText(partialCounterText); data->setCounterIndex(index); item += partialCounterText; if (calcWidth) width = qMax(width, m_fm.width(item)); data->setCounterText(prefix + item + suffix); index++; // have to recalculate any sublists under this element too QTextBlock nb = tb.next(); while (nb.isValid() && nb.textList() == 0) nb = nb.next(); if (nb.isValid()) { QTextListFormat lf = nb.textList()->format(); if ((lf.style() == format.style()) && nb.textList()->format().intProperty(KoListStyle::Level) > level) { // this is a sublist // have to remember to recalculate this list after the current level is done // cant do it right away since the sublist's prefix text is dependant on this level sublistsToRecalculate.append(nb.textList()); } } } for (int i = 0; i < sublistsToRecalculate.count(); i++) { ListItemsHelper lih(sublistsToRecalculate.at(i), m_displayFont); lih.recalculate(); } qreal counterSpacing = m_fm.width(' '); counterSpacing = qMax(format.doubleProperty(KoListStyle::MinimumDistance), counterSpacing); width += m_fm.width(prefix + suffix); // same for all width = qMax(format.doubleProperty(KoListStyle::MinimumWidth), width); for (int i = 0; i < m_textList->count(); i++) { QTextBlock tb = m_textList->item(i); KoTextBlockData *data = dynamic_cast<KoTextBlockData*>(tb.userData()); Q_ASSERT(data); data->setCounterWidth(width); data->setCounterSpacing(counterSpacing); //kDebug(32500) << data->counterText() <<"" << tb.text(); //kDebug(32500) <<" setCounterWidth:" << width; } //kDebug(32500); }