Esempio n. 1
0
void OdtWriter::writeAutomaticStyles(const QTextDocument* document)
{
	m_xml.writeStartElement(QString::fromLatin1("office:automatic-styles"));

	QVector<QTextFormat> formats = document->allFormats();

	// Find all used styles
	QVector<int> text_styles;
	QVector<int> paragraph_styles;
	int index = 0;
	for (QTextBlock block = document->begin(); block.isValid(); block = block.next()) {
		index = block.blockFormatIndex();
		if (!paragraph_styles.contains(index)) {
			int heading = block.blockFormat().property(QTextFormat::UserProperty).toInt();
			if (!heading) {
				paragraph_styles.append(index);
			} else {
				m_styles.insert(index, QString("Heading-%1").arg(heading));
			}
		}
		for (QTextBlock::iterator iter = block.begin(); !(iter.atEnd()); ++iter) {
			index = iter.fragment().charFormatIndex();
			if (!text_styles.contains(index) && formats.at(index).propertyCount()) {
				text_styles.append(index);
			}
		}
	}

	// Write text styles
	int text_style = 1;
	for (int i = 0; i < text_styles.size(); ++i) {
		int index = text_styles.at(i);
		const QTextFormat& format = formats.at(index);
		QString name = QString::fromLatin1("T") + QString::number(text_style);
		if (writeTextStyle(format.toCharFormat(), name)) {
			m_styles.insert(index, name);
			++text_style;
		}
	}

	// Write paragraph styles
	int paragraph_style = 1;
	for (int i = 0; i < paragraph_styles.size(); ++i) {
		int index = paragraph_styles.at(i);
		const QTextFormat& format = formats.at(index);
		QString name = QString::fromLatin1("P") + QString::number(paragraph_style);
		if (writeParagraphStyle(format.toBlockFormat(), name)) {
			m_styles.insert(index, name);
			++paragraph_style;
		} else {
			m_styles.insert(index, "Normal");
		}
	}

	m_xml.writeEndElement();
}
Esempio n. 2
0
void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &block)
{
    if (block.textList()) { // its a list-item
        const int listLevel = block.textList()->format().indent();
        if (m_listStack.isEmpty() || m_listStack.top() != block.textList()) {
            // not the same list we were in.
            while (m_listStack.count() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) { // we need to close tags
                m_listStack.pop();
                writer.writeEndElement(); // list
                if (m_listStack.count())
                    writer.writeEndElement(); // list-item
            }
            while (m_listStack.count() < listLevel) {
                if (m_listStack.count())
                    writer.writeStartElement(textNS, QString::fromLatin1("list-item"));
                writer.writeStartElement(textNS, QString::fromLatin1("list"));
                if (m_listStack.count() == listLevel - 1) {
                    m_listStack.push(block.textList());
                    writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("L%1")
                            .arg(block.textList()->formatIndex()));
                }
                else {
                    m_listStack.push(0);
                }
            }
        }
        writer.writeStartElement(textNS, QString::fromLatin1("list-item"));
    }
    else {
        while (! m_listStack.isEmpty()) {
            m_listStack.pop();
            writer.writeEndElement(); // list
            if (m_listStack.count())
                writer.writeEndElement(); // list-item
        }
    }

    if (block.length() == 1) { // only a linefeed
        writer.writeEmptyElement(textNS, QString::fromLatin1("p"));
        writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("p%1")
            .arg(block.blockFormatIndex()));
        if (block.textList())
            writer.writeEndElement(); // numbered-paragraph
        return;
    }
    writer.writeStartElement(textNS, QString::fromLatin1("p"));
    writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("p%1")
        .arg(block.blockFormatIndex()));
    for (QTextBlock::Iterator frag= block.begin(); !frag.atEnd(); frag++) {
        writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed in front of it.
        writer.writeStartElement(textNS, QString::fromLatin1("span"));

        QString fragmentText = frag.fragment().text();
        if (fragmentText.length() == 1 && fragmentText[0] == 0xFFFC) { // its an inline character.
            writeInlineCharacter(writer, frag.fragment());
            writer.writeEndElement(); // span
            continue;
        }

        writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("c%1")
            .arg(frag.fragment().charFormatIndex()));
        bool escapeNextSpace = true;
        int precedingSpaces = 0;
        int exportedIndex = 0;
        for (int i=0; i <= fragmentText.count(); ++i) {
            QChar character = fragmentText[i];
            bool isSpace = character.unicode() == ' ';

            // find more than one space. -> <text:s text:c="2" />
            if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
                const bool startParag = exportedIndex == 0 && i == precedingSpaces;
                if (!startParag)
                    writer.writeCharacters(fragmentText.mid(exportedIndex, i - precedingSpaces + 1 - exportedIndex));
                writer.writeEmptyElement(textNS, QString::fromLatin1("s"));
                const int count = precedingSpaces - (startParag?0:1);
                if (count > 1)
                    writer.writeAttribute(textNS, QString::fromLatin1("c"), QString::number(count));
                precedingSpaces = 0;
                exportedIndex = i;
            }

            if (i < fragmentText.count()) {
                if (character.unicode() == 0x2028) { // soft-return
                    //if (exportedIndex < i)
                        writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
                    writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
                    exportedIndex = i+1;
                    continue;
                } else if (character.unicode() == '\t') { // Tab
                    //if (exportedIndex < i)
                        writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
                    writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
                    exportedIndex = i+1;
                    precedingSpaces = 0;
                } else if (isSpace) {
                    ++precedingSpaces;
                    escapeNextSpace = true;
                } else if (!isSpace) {
                    precedingSpaces = 0;
                }
            }
        }

        writer.writeCharacters(fragmentText.mid(exportedIndex));
        writer.writeEndElement(); // span
    }
    writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed behind it.
    writer.writeEndElement(); // p
    if (block.textList())
        writer.writeEndElement(); // list-item
}
Esempio n. 3
0
void OdtWriter::writeBody(const QTextDocument* document)
{
	m_xml.writeStartElement(QString::fromLatin1("office:body"));
	m_xml.writeStartElement(QString::fromLatin1("office:text"));

	for (QTextBlock block = document->begin(); block.isValid(); block = block.next()) {
		int heading = block.blockFormat().property(QTextFormat::UserProperty).toInt();
		if (!heading) {
			m_xml.writeStartElement(QString::fromLatin1("text:p"));
		} else {
			m_xml.writeStartElement(QString::fromLatin1("text:h"));
			m_xml.writeAttribute(QString::fromLatin1("text:outline-level"), QString::number(heading));
		}
		m_xml.writeAttribute(QString::fromLatin1("text:style-name"), m_styles.value(block.blockFormatIndex()));
		m_xml.setAutoFormatting(false);

		for (QTextBlock::iterator iter = block.begin(); !(iter.atEnd()); ++iter) {
			QTextFragment fragment = iter.fragment();
			QString style = m_styles.value(fragment.charFormatIndex());
			if (!style.isEmpty()) {
				m_xml.writeStartElement(QString::fromLatin1("text:span"));
				m_xml.writeAttribute(QString::fromLatin1("text:style-name"), style);
			}

			QString text = fragment.text();
			int start = 0;
			int spaces = -1;
			for (int i = 0; i < text.length(); ++i) {
				QChar c = text.at(i);
				if (c.unicode() == 0x0009) {
					m_xml.writeCharacters(text.mid(start, i - start));
					m_xml.writeEmptyElement(QString::fromLatin1("text:tab"));
					start = i + 1;
				} else if (c.unicode() == 0x2028) {
					m_xml.writeCharacters(text.mid(start, i - start));
					m_xml.writeEmptyElement(QString::fromLatin1("text:line-break"));
					start = i + 1;
				} else if (c.unicode() == 0x0020) {
					++spaces;
				} else if (spaces > 0) {
					m_xml.writeCharacters(text.mid(start, i - spaces - start));
					m_xml.writeEmptyElement(QString::fromLatin1("text:s"));
					m_xml.writeAttribute(QString::fromLatin1("text:c"), QString::number(spaces));
					spaces = -1;
					start = i;
				} else {
					spaces = -1;
				}
			}
			if (spaces > 0) {
				m_xml.writeCharacters(text.mid(start, text.length() - spaces - start));
				m_xml.writeEmptyElement(QString::fromLatin1("text:s"));
				m_xml.writeAttribute(QString::fromLatin1("text:c"), QString::number(spaces));
			} else {
				m_xml.writeCharacters(text.mid(start));
			}

			if (!style.isEmpty()) {
				m_xml.writeEndElement();
			}
		}

		m_xml.writeEndElement();
		m_xml.setAutoFormatting(true);
	}

	m_xml.writeEndElement();
	m_xml.writeEndElement();
}