示例#1
0
void KoTextWriter::saveParagraph(const QTextBlock &block, int from, int to)
{
    QString changeName = QString();

    QTextBlockFormat blockFormat = block.blockFormat();
    int outlineLevel = blockFormat.intProperty(KoParagraphStyle::OutlineLevel);
    if (outlineLevel > 0) {
        d->writer->startElement("text:h", false);
        d->writer->addAttribute("text:outline-level", outlineLevel);
    } else 
        d->writer->startElement("text:p", false);

    QString styleName = saveParagraphStyle(block);
    if (!styleName.isEmpty())
        d->writer->addAttribute("text:style-name", styleName);

    // Write the fragments and their formats
    QTextCursor cursor(block);
    QTextCharFormat blockCharFormat = cursor.blockCharFormat();
    QTextCharFormat previousCharFormat;
    QTextBlock::iterator it;
    for (it = block.begin(); !(it.atEnd()); ++it) {
        QTextFragment currentFragment = it.fragment();
        const int fragmentStart = currentFragment.position();
        const int fragmentEnd = fragmentStart + currentFragment.length();
        if (to != -1 && fragmentStart >= to)
            break;
        if (currentFragment.isValid()) {
            QTextCharFormat charFormat = currentFragment.charFormat();
            QTextCharFormat compFormat = charFormat;
            bool identical;
            previousCharFormat.clearProperty(KoCharacterStyle::ChangeTrackerId);
            compFormat.clearProperty(KoCharacterStyle::ChangeTrackerId);
            if (previousCharFormat == compFormat)
                identical = true;
            else
                identical = false;

            if ( d->changeTracker && d->changeTracker->containsInlineChanges(charFormat) && d->changeTracker->elementById(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt())->isEnabled()) {
                KoGenChange change;
                d->changeTracker->saveInlineChange(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt(), change);
                changeName = d->sharedData->genChanges().insert(change);
                d->writer->startElement("text:change-start", false);
                d->writer->addAttribute("text:change-id", changeName);
                d->writer->endElement();
            }

            KoInlineObject *inlineObject = d->layout->inlineTextObjectManager()->inlineTextObject(charFormat);
            if (currentFragment.length() == 1 && inlineObject
                    && currentFragment.text()[0].unicode() == QChar::ObjectReplacementCharacter) {
                inlineObject->saveOdf(d->context);
            } else {
                QString styleName = saveCharacterStyle(charFormat, blockCharFormat);
                if (charFormat.isAnchor()) {
                    d->writer->startElement("text:a", false);
                    d->writer->addAttribute("xlink:type", "simple");
                    d->writer->addAttribute("xlink:href", charFormat.anchorHref());
                } else if (!styleName.isEmpty() /*&& !identical*/) {
                    d->writer->startElement("text:span", false);
                    d->writer->addAttribute("text:style-name", styleName);
                }

                QString text = currentFragment.text();
                int spanFrom = fragmentStart >= from ? 0 : from;
                int spanTo = to == -1 ? fragmentEnd : (fragmentEnd > to ? to : fragmentEnd);
                if (spanFrom != fragmentStart || spanTo != fragmentEnd) { // avoid mid, if possible
                    d->writer->addTextSpan(text.mid(spanFrom - fragmentStart, spanTo - spanFrom));
                } else {
                    d->writer->addTextSpan(text);
                }

                if ((!styleName.isEmpty() /*&& !identical*/) || charFormat.isAnchor())
                    d->writer->endElement();
            } // if (inlineObject)

            if (!changeName.isEmpty()) {
                d->writer->startElement("text:change-end", false);
                d->writer->addAttribute("text:change-id",changeName);
                d->writer->endElement();
                changeName=QString();
            }
            previousCharFormat = charFormat;
        } // if (fragment.valid())
    } // foeach(fragment)

    d->writer->endElement();
}
示例#2
0
void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode)
{
    beginEditBlock();

    Q_ASSERT(newFormat.isValid());

    int newFormatIdx = -1;
    if (mode == SetFormatAndPreserveObjectIndices) {
        QTextCharFormat cleanFormat = newFormat;
        cleanFormat.clearProperty(QTextFormat::ObjectIndex);
        newFormatIdx = formats.indexForFormat(cleanFormat);
    } else if (mode == SetFormat) {
        newFormatIdx = formats.indexForFormat(newFormat);
    }

    if (pos == -1) {
        if (mode == MergeFormat) {
            QTextFormat format = formats.format(initialBlockCharFormatIndex);
            format.merge(newFormat);
            initialBlockCharFormatIndex = formats.indexForFormat(format);
        } else if (mode == SetFormatAndPreserveObjectIndices
                   && formats.format(initialBlockCharFormatIndex).objectIndex() != -1) {
            QTextCharFormat f = newFormat;
            f.setObjectIndex(formats.format(initialBlockCharFormatIndex).objectIndex());
            initialBlockCharFormatIndex = formats.indexForFormat(f);
        } else {
            initialBlockCharFormatIndex = newFormatIdx;
        }

        ++pos;
        --length;
    }

    const int startPos = pos;
    const int endPos = pos + length;

    split(startPos);
    split(endPos);

    while (pos < endPos) {
        FragmentMap::Iterator it = fragments.find(pos);
        Q_ASSERT(!it.atEnd());

        QTextFragmentData *fragment = it.value();

        Q_ASSERT(formats.format(fragment->format).type() == QTextFormat::CharFormat);

        int offset = pos - it.position();
        int length = qMin(endPos - pos, int(fragment->size - offset));
        int oldFormat = fragment->format;

        if (mode == MergeFormat) {
            QTextFormat format = formats.format(fragment->format);
            format.merge(newFormat);
            fragment->format = formats.indexForFormat(format);
        } else if (mode == SetFormatAndPreserveObjectIndices
                   && formats.format(oldFormat).objectIndex() != -1) {
            QTextCharFormat f = newFormat;
            f.setObjectIndex(formats.format(oldFormat).objectIndex());
            fragment->format = formats.indexForFormat(f);
        } else {
            fragment->format = newFormatIdx;
        }

        QTextUndoCommand c = { QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
                               0, pos, { length }, 0 };
        appendUndoItem(c);

        pos += length;
        Q_ASSERT(pos == (int)(it.position() + fragment->size) || pos >= endPos);
    }

    int n = fragments.findNode(startPos - 1);
    if (n)
        unite(n);

    n = fragments.findNode(endPos);
    if (n)
        unite(n);

    QTextBlock blockIt = blocksFind(startPos);
    QTextBlock endIt = blocksFind(endPos);
    if (endIt.isValid())
        endIt = endIt.next();
    for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())
        QTextDocumentPrivate::block(blockIt)->invalidate();

    documentChange(startPos, length);

    endEditBlock();
}
示例#3
0
void tst_QTextFormat::resolveFont()
{
    QTextDocument doc;

    QTextCharFormat fmt;
    fmt.setProperty(QTextFormat::ForegroundBrush, QColor(Qt::blue));
    QCOMPARE(fmt.property(QTextFormat::ForegroundBrush).userType(), qMetaTypeId<QColor>());
    QCOMPARE(fmt.property(QTextFormat::ForegroundBrush).value<QColor>(), QColor(Qt::blue));
    fmt.setProperty(QTextFormat::FontItalic, true);
    QTextCursor(&doc).insertText("Test", fmt);

    QVector<QTextFormat> formats = doc.allFormats();
    QCOMPARE(formats.count(), 3);

    QVERIFY(formats.at(2).type() == QTextFormat::CharFormat);
    fmt = formats.at(2).toCharFormat();

    QVERIFY(!fmt.font().underline());
    QVERIFY(fmt.hasProperty(QTextFormat::ForegroundBrush));

    QFont f;
    f.setUnderline(true);
    doc.setDefaultFont(f);
    formats = doc.allFormats();
    fmt = formats.at(2).toCharFormat();

    QVERIFY(fmt.font().underline());
    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));

    // verify that deleting a non-existent property does not affect the font resolving

    QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));
    fmt.clearProperty(QTextFormat::BackgroundBrush);
    QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));

    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
    QVERIFY(fmt.font().underline());

    // verify that deleting an existent but font _unrelated_ property does not affect the font resolving

    QVERIFY(fmt.hasProperty(QTextFormat::ForegroundBrush));
    fmt.clearProperty(QTextFormat::ForegroundBrush);
    QVERIFY(!fmt.hasProperty(QTextFormat::ForegroundBrush));

    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
    QVERIFY(fmt.font().underline());

    // verify that removing a font property _does_ clear the resolving

    QVERIFY(fmt.hasProperty(QTextFormat::FontItalic));
    fmt.clearProperty(QTextFormat::FontItalic);
    QVERIFY(!fmt.hasProperty(QTextFormat::FontItalic));

    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
    QVERIFY(!fmt.font().underline());
    QVERIFY(!fmt.font().italic());

    // reset
    fmt = formats.at(2).toCharFormat();

    QVERIFY(fmt.font().underline());
    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));

    // verify that _setting_ an unrelated property does _not_ affect the resolving

    QVERIFY(!fmt.hasProperty(QTextFormat::IsAnchor));
    fmt.setProperty(QTextFormat::IsAnchor, true);
    QVERIFY(fmt.hasProperty(QTextFormat::IsAnchor));

    QVERIFY(fmt.font().underline());
    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));

    // verify that setting a _related_ font property does affect the resolving
    //
    QVERIFY(!fmt.hasProperty(QTextFormat::FontStrikeOut));
    fmt.setProperty(QTextFormat::FontStrikeOut, true);
    QVERIFY(fmt.hasProperty(QTextFormat::FontStrikeOut));

    QVERIFY(!fmt.font().underline());
    QVERIFY(!fmt.hasProperty(QTextFormat::FontUnderline));
    QVERIFY(fmt.font().strikeOut());
}
示例#4
0
QT_BEGIN_NAMESPACE

/*!
    \class QTextTableCell
    \reentrant

    \brief The QTextTableCell class represents the properties of a
    cell in a QTextTable.

    \ingroup text

    Table cells are pieces of document structure that belong to a table.
    The table orders cells into particular rows and columns; cells can
    also span multiple columns and rows.

    Cells are usually created when a table is inserted into a document with
    QTextCursor::insertTable(), but they are also created and destroyed when
    a table is resized.

    Cells contain information about their location in a table; you can
    obtain the row() and column() numbers of a cell, and its rowSpan()
    and columnSpan().

    The format() of a cell describes the default character format of its
    contents. The firstCursorPosition() and lastCursorPosition() functions
    are used to obtain the extent of the cell in the document.

    \sa QTextTable QTextTableFormat
*/

/*!
    \fn QTextTableCell::QTextTableCell()

    Constructs an invalid table cell.

    \sa isValid()
*/

/*!
    \fn QTextTableCell::QTextTableCell(const QTextTableCell &other)

    Copy constructor. Creates a new QTextTableCell object based on the
    \a other cell.
*/

/*!
    \fn QTextTableCell& QTextTableCell::operator=(const QTextTableCell &other)

    Assigns the \a other table cell to this table cell.
*/

/*!
    \since 4.2

    Sets the cell's character format to \a format. This can for example be used to change
    the background color of the entire cell:

    QTextTableCell cell = table->cellAt(2, 3);
    QTextCharFormat format = cell.format();
    format.setBackground(Qt::blue);
    cell.setFormat(format);

    Note that the cell's row or column span cannot be changed through this function. You have
    to use QTextTable::mergeCells and QTextTable::splitCell instead.

    \sa format()
*/
void QTextTableCell::setFormat(const QTextCharFormat &format)
{
    QTextCharFormat fmt = format;
    fmt.clearProperty(QTextFormat::ObjectIndex);
    fmt.setObjectType(QTextFormat::TableCellObject);
    QTextDocumentPrivate *p = table->docHandle();
    QTextDocumentPrivate::FragmentIterator frag(&p->fragmentMap(), fragment);

    QTextFormatCollection *c = p->formatCollection();
    QTextCharFormat oldFormat = c->charFormat(frag->format);
    fmt.setTableCellRowSpan(oldFormat.tableCellRowSpan());
    fmt.setTableCellColumnSpan(oldFormat.tableCellColumnSpan());

    p->setCharFormat(frag.position(), 1, fmt, QTextDocumentPrivate::SetFormatAndPreserveObjectIndices);
}
bool QTextHtmlImporter::appendNodeText()
{
    const int initialCursorPosition = cursor.position();
    QTextCharFormat format = currentNode->charFormat;

    if(wsm == QTextHtmlParserNode::WhiteSpacePre || wsm == QTextHtmlParserNode::WhiteSpacePreWrap)
        compressNextWhitespace = PreserveWhiteSpace;

    QString text = currentNode->text;

    QString textToInsert;
    textToInsert.reserve(text.size());

    for (int i = 0; i < text.length(); ++i) {
        QChar ch = text.at(i);

        if (ch.isSpace()
            && ch != QChar::Nbsp
            && ch != QChar::ParagraphSeparator) {

            if (compressNextWhitespace == CollapseWhiteSpace)
                compressNextWhitespace = RemoveWhiteSpace; // allow this one, and remove the ones coming next.
            else if(compressNextWhitespace == RemoveWhiteSpace)
                continue;

            if (wsm == QTextHtmlParserNode::WhiteSpacePre
                || textEditMode
               ) {
                if (ch == QLatin1Char('\n')) {
                    if (textEditMode)
                        continue;
                } else if (ch == QLatin1Char('\r')) {
                    continue;
                }
            } else if (wsm != QTextHtmlParserNode::WhiteSpacePreWrap) {
                compressNextWhitespace = RemoveWhiteSpace;
                if (wsm == QTextHtmlParserNode::WhiteSpaceNoWrap)
                    ch = QChar::Nbsp;
                else
                    ch = QLatin1Char(' ');
            }
        } else {
            compressNextWhitespace = PreserveWhiteSpace;
        }

        if (ch == QLatin1Char('\n')
            || ch == QChar::ParagraphSeparator) {

            if (!textToInsert.isEmpty()) {
                cursor.insertText(textToInsert, format);
                textToInsert.clear();
            }

            QTextBlockFormat fmt = cursor.blockFormat();

            if (fmt.hasProperty(QTextFormat::BlockBottomMargin)) {
                QTextBlockFormat tmp = fmt;
                tmp.clearProperty(QTextFormat::BlockBottomMargin);
                cursor.setBlockFormat(tmp);
            }

            fmt.clearProperty(QTextFormat::BlockTopMargin);
            appendBlock(fmt, cursor.charFormat());
        } else {
            if (!namedAnchors.isEmpty()) {
                if (!textToInsert.isEmpty()) {
                    cursor.insertText(textToInsert, format);
                    textToInsert.clear();
                }

                format.setAnchor(true);
                format.setAnchorNames(namedAnchors);
                cursor.insertText(ch, format);
                namedAnchors.clear();
                format.clearProperty(QTextFormat::IsAnchor);
                format.clearProperty(QTextFormat::AnchorName);
            } else {
                textToInsert += ch;
            }
        }
    }

    if (!textToInsert.isEmpty()) {
        cursor.insertText(textToInsert, format);
    }

    return cursor.position() != initialCursorPosition;
}