Esempio n. 1
0
bool QTextDocumentPrivate::ensureMaximumBlockCount()
{
    if (maximumBlockCount <= 0)
        return false;
    if (blocks.numNodes() <= maximumBlockCount)
        return false;

    beginEditBlock();

    const int blocksToRemove = blocks.numNodes() - maximumBlockCount;
    QTextCursor cursor(this, 0);
    cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, blocksToRemove);

    unreachableCharacterCount += cursor.selectionEnd() - cursor.selectionStart();

    // preserve the char format of the paragraph that is to become the new first one
    QTextCharFormat charFmt = cursor.blockCharFormat();
    cursor.removeSelectedText();
    cursor.setBlockCharFormat(charFmt);

    endEditBlock();

    compressPieceTable();

    return true;
}
Esempio n. 2
0
QTextFrame *QTextDocumentPrivate::insertFrame(int start, int end, const QTextFrameFormat &format)
{
    Q_ASSERT(start >= 0 && start < length());
    Q_ASSERT(end >= 0 && end < length());
    Q_ASSERT(start <= end || end == -1);

    if (start != end && frameAt(start) != frameAt(end))
        return 0;

    beginEditBlock();

    QTextFrame *frame = qobject_cast<QTextFrame *>(createObject(format));
    Q_ASSERT(frame);

    // #### using the default block and char format below might be wrong
    int idx = formats.indexForFormat(QTextBlockFormat());
    QTextCharFormat cfmt;
    cfmt.setObjectIndex(frame->objectIndex());
    int charIdx = formats.indexForFormat(cfmt);

    insertBlock(QTextBeginningOfFrame, start, idx, charIdx, QTextUndoCommand::MoveCursor);
    insertBlock(QTextEndOfFrame, ++end, idx, charIdx, QTextUndoCommand::KeepCursor);

    frame->d_func()->fragment_start = find(start).n;
    frame->d_func()->fragment_end = find(end).n;

    insert_frame(frame);

    endEditBlock();

    return frame;
}
Esempio n. 3
0
	void Text4Edit(
        const QString& _text,
		Ui::TextEditEx& _edit,
		const Text2DocHtmlMode _htmlMode,
		const bool _convertLinks,
        const bool _breakDocument,
		const Text2HtmlUriCallback _uriCallback,
		const Emoji::EmojiSizePx _emojiSize,
        const QTextCharFormat::VerticalAlignment _aligment)
	{
        _edit.blockSignals(true);
        _edit.document()->blockSignals(true);
        _edit.setUpdatesEnabled(false);

		Text2DocConverter converter;
		converter.MakeUniqueResources(true);

        auto cursor = _edit.textCursor();
        cursor.beginEditBlock();

		converter.Convert(_text, cursor, _htmlMode, _convertLinks, _breakDocument, _uriCallback, _emojiSize, _aligment);

        cursor.endEditBlock();

		_edit.mergeResources(converter.GetResources());

        _edit.setUpdatesEnabled(true);
        _edit.document()->blockSignals(false);
        _edit.blockSignals(false);

        emit (_edit.document()->contentsChanged());
	}
Esempio n. 4
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();
}
Esempio n. 5
0
void QTextDocumentPrivate::removeFrame(QTextFrame *frame)
{
    QTextFrame *parent = frame->d_func()->parentFrame;
    if (!parent)
        return;

    int start = frame->firstPosition();
    int end = frame->lastPosition();
    Q_ASSERT(end >= start);

    beginEditBlock();

    // remove already removes the frames from the tree
    remove(end, 1);
    remove(start-1, 1);

    endEditBlock();
}
Esempio n. 6
0
void
CImgFilterPluginHelperBase::changedClip(const OFX::InstanceChangedArgs &args, const std::string &clipName)
{
    if (clipName == kOfxImageEffectSimpleSourceClipName &&
        _srcClip && _srcClip->isConnected() &&
        args.reason == OFX::eChangeUserEdit) {
        beginEditBlock("changedClip");
        if (_defaultUnpremult && !_premultChanged->getValue()) {
            switch (_srcClip->getPreMultiplication()) {
                case OFX::eImageOpaque:
                    _premult->setValue(false);
                    break;
                case OFX::eImagePreMultiplied:
                    _premult->setValue(true);
                    break;
                case OFX::eImageUnPreMultiplied:
                    _premult->setValue(false);
                    break;
            }
        }
        if (_processR) {
            switch (_srcClip->getPixelComponents()) {
                case OFX::ePixelComponentAlpha:
                    _processR->setValue(false);
                    _processG->setValue(false);
                    _processB->setValue(false);
                    _processA->setValue(true);
                    break;
                case OFX::ePixelComponentRGBA:
                case OFX::ePixelComponentRGB:
                    // Alpha is not processed by default on RGBA images
                    _processR->setValue(true);
                    _processG->setValue(true);
                    _processB->setValue(true);
                    _processA->setValue(_defaultProcessAlphaOnRGBA);
                    break;
                default:
                    break;
            }
        }
        endEditBlock();
    }
}
Esempio n. 7
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;
}
Esempio n. 8
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();
}
Esempio n. 9
0
void Text::selectText(const QString &txt, const int index)
{
    regenerate();

    if (!doc) {
        return;
    }

    auto cursor = doc->find(txt, index);

    if (!cursor.isNull()) {
        cursor.beginEditBlock();
        cursor.setPosition(index);
        cursor.setPosition(index + txt.size(), QTextCursor::KeepAnchor);
        cursor.endEditBlock();

        QTextCharFormat format;
        format.setBackground(QBrush(QColor("#ff7626")));
        cursor.mergeCharFormat(format);

        regenerate();
        update();
    }
}
Esempio n. 10
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();
}
Esempio n. 11
0
int QTextDocumentPrivate::undoRedo(bool undo)
{
    PMDEBUG("%s, undoState=%d, undoStack size=%d", undo ? "undo:" : "redo:", undoState, undoStack.size());
    if (!undoEnabled || (undo && undoState == 0) || (!undo && undoState == undoStack.size()))
        return -1;

    undoEnabled = false;
    beginEditBlock();
    while (1) {
        if (undo)
            --undoState;
        QTextUndoCommand &c = undoStack[undoState];
        int resetBlockRevision = c.pos;

	switch(c.command) {
        case QTextUndoCommand::Inserted:
            remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation);
            PMDEBUG("   erase: from %d, length %d", c.pos, c.length);
            c.command = QTextUndoCommand::Removed;
	    break;
        case QTextUndoCommand::Removed:
            PMDEBUG("   insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
            insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
            c.command = QTextUndoCommand::Inserted;
	    break;
	case QTextUndoCommand::BlockInserted:
	case QTextUndoCommand::BlockAdded:
            remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation);
            PMDEBUG("   blockremove: from %d", c.pos);
	    if (c.command == QTextUndoCommand::BlockInserted)
		c.command = QTextUndoCommand::BlockRemoved;
	    else
		c.command = QTextUndoCommand::BlockDeleted;
	    break;
	case QTextUndoCommand::BlockRemoved:
	case QTextUndoCommand::BlockDeleted:
            PMDEBUG("   blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
            insert_block(c.pos, c.strPos, c.format, c.blockFormat, (QTextUndoCommand::Operation)c.operation, c.command);
            resetBlockRevision += 1;
	    if (c.command == QTextUndoCommand::BlockRemoved)
		c.command = QTextUndoCommand::BlockInserted;
	    else
		c.command = QTextUndoCommand::BlockAdded;
	    break;
	case QTextUndoCommand::CharFormatChanged: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
            FragmentIterator it = find(c.pos);
            Q_ASSERT(!it.atEnd());

            int oldFormat = it.value()->format;
            setCharFormat(c.pos, c.length, formats.charFormat(c.format));
            c.format = oldFormat;
	    break;
	}
	case QTextUndoCommand::BlockFormatChanged: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   blockformat: format %d pos %d", c.format, c.pos);
            QTextBlock it = blocksFind(c.pos);
            Q_ASSERT(it.isValid());

            int oldFormat = block(it)->format;
            block(it)->format = c.format;
            QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(oldFormat)));
            QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(c.format)));
            c.format = oldFormat;
            if (group != oldGroup) {
                if (oldGroup)
                    oldGroup->blockRemoved(it);
                if (group)
                    group->blockInserted(it);
            } else if (group) {
                group->blockFormatChanged(it);
            }
            documentChange(it.position(), it.length());
	    break;
	}
	case QTextUndoCommand::GroupFormatChange: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   group format change");
            QTextObject *object = objectForIndex(c.objectIndex);
            int oldFormat = formats.objectFormatIndex(c.objectIndex);
            changeObjectFormat(object, c.format);
            c.format = oldFormat;
	    break;
	}
	case QTextUndoCommand::Custom:
            resetBlockRevision = -1; // ## TODO
            if (undo)
                c.custom->undo();
            else
                c.custom->redo();
	    break;
	default:
	    Q_ASSERT(false);
        }

        if (resetBlockRevision >= 0) {
            int b = blocks.findNode(resetBlockRevision);
            QTextBlockData *B = blocks.fragment(b);
            B->revision = c.revision;
        }

        if (undo) {
            if (undoState == 0 || !undoStack[undoState-1].block)
                break;
        } else {
            ++undoState;
            if (undoState == undoStack.size() || !undoStack[undoState-1].block)
                break;
        }
    }
    undoEnabled = true;
    int editPos = -1;
    if (docChangeFrom >= 0) {
        editPos = qMin(docChangeFrom + docChangeLength, length() - 1);
    }
    endEditBlock();
    emitUndoAvailable(isUndoAvailable());
    emitRedoAvailable(isRedoAvailable());
    return editPos;
}
Esempio n. 12
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();
}
Esempio n. 13
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();
}