예제 #1
0
void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlock &to,
				     const QTextBlockFormat &newFormat, FormatChangeMode mode)
{
    beginEditBlock();

    Q_ASSERT(mode != SetFormatAndPreserveObjectIndices); // only implemented for setCharFormat

    Q_ASSERT(newFormat.isValid());

    int newFormatIdx = -1;
    if (mode == SetFormat)
        newFormatIdx = formats.indexForFormat(newFormat);
    QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(newFormat));

    QTextBlock it = from;
    QTextBlock end = to;
    if (end.isValid())
	end = end.next();

    for (; it != end; it = it.next()) {
        int oldFormat = block(it)->format;
        QTextBlockFormat format = formats.blockFormat(oldFormat);
        QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(format));
        if (mode == MergeFormat) {
            format.merge(newFormat);
            newFormatIdx = formats.indexForFormat(format);
            group = qobject_cast<QTextBlockGroup *>(objectForFormat(format));
        }
        block(it)->format = newFormatIdx;

        block(it)->invalidate();

        QTextUndoCommand c = { QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
                               0, it.position(), { 1 }, 0 };
        appendUndoItem(c);

        if (group != oldGroup) {
            if (oldGroup)
                oldGroup->blockRemoved(it);
            if (group)
                group->blockInserted(it);
        } else if (group) {
	    group->blockFormatChanged(it);
	}
    }

    documentChange(from.position(), to.position() + to.length() - from.position());

    endEditBlock();
}
예제 #2
0
/*!
    Appends a custom undo \a item to the undo stack.
*/
void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item)
{
    if (!undoEnabled) {
        delete item;
        return;
    }

    QTextUndoCommand c;
    c.command = QTextUndoCommand::Custom;
    c.block = editBlock != 0;
    c.operation = QTextUndoCommand::MoveCursor;
    c.format = 0;
    c.strPos = 0;
    c.pos = 0;
    c.blockFormat = 0;

    c.custom = item;
    appendUndoItem(c);
}
예제 #3
0
int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,
                                  int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)
{
    Q_ASSERT(formats.format(blockFormat).isBlockFormat());
    Q_ASSERT(formats.format(charFormat).isCharFormat());
    Q_ASSERT(pos >= 0 && (pos < fragments.length() || (pos == 0 && fragments.length() == 0)));
    Q_ASSERT(isValidBlockSeparator(blockSeparator));

    beginEditBlock();

    int strPos = text.length();
    text.append(blockSeparator);
    const int fragment = insert_block(pos, strPos, charFormat, blockFormat, op, QTextUndoCommand::BlockRemoved);

    Q_ASSERT(blocks.length() == fragments.length());

    int b = blocks.findNode(pos);
    QTextBlockData *B = blocks.fragment(b);

    QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true,
                           op, charFormat, strPos, pos, { blockFormat },
                           B->revision };

    appendUndoItem(c);
    Q_ASSERT(undoState == undoStack.size());

    // update revision numbers of the modified blocks. Close to the
    // truth, but we may want to special case breaking a block before
    // the first or behind the last character
    B->revision = undoState;
    b = blocks.next(b);
    if (b) {
        B = blocks.fragment(b);
        B->revision = undoState;
    }

    if (formats.charFormat(charFormat).objectIndex() == -1)
        needsEnsureMaximumBlockCount = true;

    endEditBlock();
    return fragment;
}
예제 #4
0
void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
{
    beginEditBlock();
    int objectIndex = obj->objectIndex();
    int oldFormatIndex = formats.objectFormatIndex(objectIndex);
    formats.setObjectFormatIndex(objectIndex, format);

    QTextBlockGroup *b = qobject_cast<QTextBlockGroup *>(obj);
    if (b) {
        b->d_func()->markBlocksDirty();
    }
    QTextFrame *f = qobject_cast<QTextFrame *>(obj);
    if (f)
        documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());

    QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex,
                           0, 0, { obj->d_func()->objectIndex }, 0 };
    appendUndoItem(c);

    endEditBlock();
}
예제 #5
0
void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format)
{
    if (strLength <= 0)
        return;

    Q_ASSERT(pos >= 0 && pos < fragments.length());
    Q_ASSERT(formats.format(format).isCharFormat());

    insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);

    beginEditBlock();

    int b = blocks.findNode(pos);
    QTextBlockData *B = blocks.fragment(b);

    QTextUndoCommand c = { QTextUndoCommand::Inserted, true,
                           QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength },
                           B->revision };
    appendUndoItem(c);
    B->revision = undoState;
    Q_ASSERT(undoState == undoStack.size());

    endEditBlock();
}
int QTextDocument::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: contentsChange((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break;
        case 1: contentsChanged(); break;
        case 2: undoAvailable((*reinterpret_cast< bool(*)>(_a[1]))); break;
        case 3: redoAvailable((*reinterpret_cast< bool(*)>(_a[1]))); break;
        case 4: undoCommandAdded(); break;
        case 5: modificationChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
        case 6: cursorPositionChanged((*reinterpret_cast< const QTextCursor(*)>(_a[1]))); break;
        case 7: blockCountChanged((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 8: documentLayoutChanged(); break;
        case 9: undo(); break;
        case 10: redo(); break;
        case 11: appendUndoItem((*reinterpret_cast< QAbstractUndoItem*(*)>(_a[1]))); break;
        case 12: setModified((*reinterpret_cast< bool(*)>(_a[1]))); break;
        case 13: setModified(); break;
        }
        _id -= 14;
    }
#ifndef QT_NO_PROPERTIES
      else if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast< bool*>(_v) = isUndoRedoEnabled(); break;
        case 1: *reinterpret_cast< bool*>(_v) = isModified(); break;
        case 2: *reinterpret_cast< QSizeF*>(_v) = pageSize(); break;
        case 3: *reinterpret_cast< QFont*>(_v) = defaultFont(); break;
        case 4: *reinterpret_cast< bool*>(_v) = useDesignMetrics(); break;
        case 5: *reinterpret_cast< QSizeF*>(_v) = size(); break;
        case 6: *reinterpret_cast< qreal*>(_v) = textWidth(); break;
        case 7: *reinterpret_cast< int*>(_v) = blockCount(); break;
        case 8: *reinterpret_cast< qreal*>(_v) = indentWidth(); break;
        case 9: *reinterpret_cast< QString*>(_v) = defaultStyleSheet(); break;
        case 10: *reinterpret_cast< int*>(_v) = maximumBlockCount(); break;
        }
        _id -= 11;
    } else if (_c == QMetaObject::WriteProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: setUndoRedoEnabled(*reinterpret_cast< bool*>(_v)); break;
        case 1: setModified(*reinterpret_cast< bool*>(_v)); break;
        case 2: setPageSize(*reinterpret_cast< QSizeF*>(_v)); break;
        case 3: setDefaultFont(*reinterpret_cast< QFont*>(_v)); break;
        case 4: setUseDesignMetrics(*reinterpret_cast< bool*>(_v)); break;
        case 6: setTextWidth(*reinterpret_cast< qreal*>(_v)); break;
        case 8: setIndentWidth(*reinterpret_cast< qreal*>(_v)); break;
        case 9: setDefaultStyleSheet(*reinterpret_cast< QString*>(_v)); break;
        case 10: setMaximumBlockCount(*reinterpret_cast< int*>(_v)); break;
        }
        _id -= 11;
    } else if (_c == QMetaObject::ResetProperty) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyDesignable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyScriptable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyStored) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyEditable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyUser) {
        _id -= 11;
    }
#endif // QT_NO_PROPERTIES
    return _id;
}
예제 #7
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();
}
예제 #8
0
void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::Operation op)
{
    Q_ASSERT(to <= fragments.length() && to <= pos);
    Q_ASSERT(pos >= 0 && pos+length <= fragments.length());
    Q_ASSERT(blocks.length() == fragments.length());

    if (pos == to)
        return;

    const bool needsInsert = to != -1;

#if !defined(QT_NO_DEBUG)
    const bool startAndEndInSameFrame = (frameAt(pos) == frameAt(pos + length - 1));

    const bool endIsEndOfChildFrame = (isAncestorFrame(frameAt(pos), frameAt(pos + length - 1))
                                       && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame);

    const bool startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent
               = (text.at(find(pos)->stringPosition) == QTextBeginningOfFrame
                  && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame
                  && frameAt(pos)->parentFrame() == frameAt(pos + length - 1)->parentFrame());

    const bool isFirstTableCell = (qobject_cast<QTextTable *>(frameAt(pos + length - 1))
                                  && frameAt(pos + length - 1)->parentFrame() == frameAt(pos));

    Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);
#endif

    beginEditBlock();

    split(pos);
    split(pos+length);

    uint dst = needsInsert ? fragments.findNode(to) : 0;
    uint dstKey = needsInsert ? fragments.position(dst) : 0;

    uint x = fragments.findNode(pos);
    uint end = fragments.findNode(pos+length);

    uint w = 0;
    while (x != end) {
        uint n = fragments.next(x);

        uint key = fragments.position(x);
        uint b = blocks.findNode(key+1);
        QTextBlockData *B = blocks.fragment(b);
        int blockRevision = B->revision;

        QTextFragmentData *X = fragments.fragment(x);
        QTextUndoCommand c = { QTextUndoCommand::Removed, true,
                               op, X->format, X->stringPosition, key, { X->size },
                               blockRevision };
        QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true,
                                     op, X->format, X->stringPosition, dstKey, { X->size },
                                     blockRevision };

        if (key+1 != blocks.position(b)) {
//	    qDebug("remove_string from %d length %d", key, X->size);
            Q_ASSERT(noBlockInString(text.mid(X->stringPosition, X->size)));
            w = remove_string(key, X->size, op);

            if (needsInsert) {
                insert_string(dstKey, X->stringPosition, X->size, X->format, op);
                dstKey += X->size;
            }
        } else {
//	    qDebug("remove_block at %d", key);
            Q_ASSERT(X->size == 1 && isValidBlockSeparator(text.at(X->stringPosition)));
            b = blocks.previous(b);
            B = 0;
            c.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockDeleted : QTextUndoCommand::BlockRemoved;
            w = remove_block(key, &c.blockFormat, QTextUndoCommand::BlockAdded, op);

            if (needsInsert) {
                insert_block(dstKey++, X->stringPosition, X->format, c.blockFormat, op, QTextUndoCommand::BlockRemoved);
                cInsert.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockAdded : QTextUndoCommand::BlockInserted;
                cInsert.blockFormat = c.blockFormat;
            }
        }
        appendUndoItem(c);
        if (B)
            B->revision = undoState;
        x = n;

        if (needsInsert)
            appendUndoItem(cInsert);
    }
    if (w)
        unite(w);

    Q_ASSERT(blocks.length() == fragments.length());

    endEditBlock();
}