QSharedPointer<RBlock> RClipboardOperation::copyBlock(
    RBlock::Id blockId,
    RDocument& src,
    RDocument& dest,
    bool overwriteBlocks,
    bool toCurrentBlock,
    const QString& blockName,
    RTransaction& transaction) const {

    QSharedPointer<RBlock> srcBlock = src.queryBlock(blockId);
    if (srcBlock.isNull()) {
        qWarning("RClipboardOperation::copyEntityBlock: "
            "block of entity is NULL.");
        return QSharedPointer<RBlock>();
    }
    QString srcBlockName = srcBlock->getName();
    QSharedPointer<RBlock> destBlock;
    if (copiedBlocks.contains(srcBlockName)) {
        destBlock = copiedBlocks.value(srcBlockName);
    }
    else {
        QString destBlockName;
        if (!blockName.isNull()) {
            destBlockName = blockName;
        }
        else {
            if (toCurrentBlock) {
                destBlockName = dest.getBlockName(dest.getCurrentBlockId());
            }
            else {
                destBlockName = srcBlock->getName();
            }
        }
        if (!dest.hasBlock(destBlockName) || (overwriteBlocks && blockName.isNull())) {
            destBlock = QSharedPointer<RBlock> (srcBlock->clone());
            dest.getStorage().setObjectId(*destBlock.data(), RObject::INVALID_ID);
            dest.getStorage().setObjectHandle(*destBlock.data(), RObject::INVALID_HANDLE);
            destBlock->setDocument(&dest);
            if (dest.hasBlock(destBlockName)) {
                if (!transaction.overwriteBlock(destBlock)) {
                    destBlock = dest.queryBlock(destBlockName);
                }
            }
            else {
                transaction.addObject(destBlock);
            }
        } else {
            destBlock = dest.queryBlock(destBlockName);
        }

        copiedBlocks.insert(srcBlockName, destBlock);
    }

    return destBlock;
}
QSharedPointer<RLayer> RClipboardOperation::copyLayer(
        RLayer::Id layerId,
        RDocument& src, RDocument& dest,
        bool overwriteLayers,
        RTransaction& transaction) const {

    bool overwriteLinetypes = false;

    // add layer the entity is on, if the layer exists it is overwritten
    // if overwriteLayers is true:
    QSharedPointer<RLayer> srcLayer = src.queryLayer(layerId);
    if (srcLayer.isNull()) {
        qWarning("RClipboardOperation::copyLayer: "
                 "layer is NULL.");
        return QSharedPointer<RLayer>();
    }

    QSharedPointer<RLinetype> destLinetype = copyLinetype(srcLayer->getLinetypeId(), src, dest, overwriteLinetypes, transaction);

    QString srcLayerName = srcLayer->getName();
    QSharedPointer<RLayer> destLayer;
    if (copiedLayers.contains(srcLayerName)) {
        destLayer = copiedLayers.value(srcLayerName);
        Q_ASSERT(!destLayer.isNull());
    }
    else {
        if (!dest.hasLayer(srcLayerName) || overwriteLayers) {
            destLayer = QSharedPointer<RLayer>(srcLayer->clone());
            destLayer->setDocument(&dest);
            if (destLayer->getDocument()!=srcLayer->getDocument()) {
                dest.getStorage().setObjectId(*destLayer.data(), RObject::INVALID_ID);
                dest.getStorage().setObjectHandle(*destLayer.data(), RObject::INVALID_HANDLE);
            }
            transaction.addObject(destLayer);
        }
        else {
            destLayer = dest.queryLayer(srcLayerName);
            Q_ASSERT(!destLayer.isNull());
        }

        copiedLayers.insert(srcLayerName, destLayer);
    }

    if (!destLinetype.isNull()) {
        destLayer->setLinetypeId(destLinetype->getId());
    }

    return destLayer;
}
Exemple #3
0
RTransaction RMixedOperation::apply(RDocument& document, bool preview) const {
    Q_UNUSED(preview)

    RTransaction transaction(document.getStorage(), text, undoable);
    transaction.setGroup(transactionGroup);

    for (int i = 0; i < list.size(); ++i) {
        if (list[i].first.isNull()) {
            qWarning() << "RMixedOperation::apply: "
                    "list contains NULL object";
            continue;
        }

        if (getMode(list[i].second, RMixedOperation::EndCycle)) {
            transaction.endCycle();
        }
        else if (getMode(list[i].second, RMixedOperation::Delete)) {
            transaction.deleteObject(list[i].first);
        }
        else {
            transaction.addObject(list[i].first,
                getMode(list[i].second, RMixedOperation::UseCurrentAttributes),
                getMode(list[i].second, RMixedOperation::ForceNew));
        }
    }

    transaction.end();
    return transaction;
}
RTransaction RAddObjectsOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), "Adding object(s)", undoable);
    transaction.setRecordAffectedObjects(recordAffectedObjects);
    transaction.setSpatialIndexDisabled(spatialIndexDisabled);

    for (int i = 0; i < addedObjects.size(); ++i) {
        if (limitPreview && preview && i>RSettings::getPreviewEntities()) {
            break;
        }

        if (addedObjects[i].object.isNull()) {
            transaction.endCycle();
            //qWarning() << "RAddObjectsOperation::apply: "
            //        "list contains NULL object";
            continue;
        }

        if (addedObjects[i].deleteIt) {
            transaction.deleteObject(addedObjects[i].object, &document);
            continue;
        }

        transaction.addObject(
            addedObjects[i].object,
            addedObjects[i].useCurrentAttributes,
            addedObjects[i].forceNew);
    }

    transaction.end();
    return transaction;
}
Exemple #5
0
RTransaction RCopyOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), text);
    transaction.setGroup(transactionGroup);

    copy(
        src, document,
        offset,
        1.0, 0.0,             // scale, angle
        false,                // flipHorizontal
        false,                // flipVertical
        false,                // toCurrentLayer
        false,                // toCurrentBlock
        true,                 // overwriteLayers
        false,                // overwriteBlocks
        QString(),            // blockName
        QString(),            // layerName
        transaction,
        true,                 // selectionOnly
        clear,                // clear
        true,                 // toModelSpace (clipboard root is always model space)
        preview
    );

    transaction.end();
    return transaction;
}
RTransaction RMoveReferencePointOperation::apply(RDocument& document, bool preview) const {
    Q_UNUSED(preview)

    RTransaction transaction(document.getStorage(), text);
    transaction.setGroup(transactionGroup);

    QSet<REntity::Id> selectedEntities = document.querySelectedEntities();
    QSet<REntity::Id>::iterator it;
    for (it=selectedEntities.begin(); it!=selectedEntities.end(); it++) {
        QSharedPointer<REntity> entity = document.queryEntity(*it);
        if (entity.isNull()) {
            continue;
        }
        
        // apply operation to cloned entity:
        bool modified = entity->moveReferencePoint(referencePoint, targetPoint);
        
        if (modified) {
            transaction.addObject(entity, false);
        }
    }
        
    transaction.end();

    return transaction;
}
RTransaction RChangePropertyOperation::apply(RDocument& document, bool preview) const {
    Q_UNUSED(preview)
    RTransaction transaction(document.getStorage(), text);

    // always allow property changes (e.g. move entity to hidden layer)
    transaction.setAllowInvisible(true);
    transaction.setGroup(transactionGroup);

    QVariant val = value;

    // optimization: change layer ID instead of changing layer name:
    if (propertyTypeId==REntity::PropertyLayer && value.type() == QVariant::String) {
        val = QVariant(document.getLayerId(value.toString()));
    }

    //RDebug::startTimer();

    //qDebug() << "filter: " << entityTypeFilter;

    QSet<RObject::Id> selectedObjects = document.queryPropertyEditorObjects();
    QSet<RObject::Id>::iterator it;
    for (it = selectedObjects.begin(); it != selectedObjects.end(); it++) {

        QSharedPointer<RObject> obj = document.queryObject(*it);
        if (obj.isNull()) {
            continue;
        }
        if (entityTypeFilter!=RS::EntityAll) {
            // special filter for block references and attributes:
            if (entityTypeFilter==RS::EntityBlockRefAttr) {
                if (obj->getType()!=RS::EntityBlockRef &&
                    obj->getType()!=RS::EntityAttribute) {
                    continue;
                }
            }
            else {
                if (entityTypeFilter!=obj->getType()) {
                    continue;
                }
            }
        }

        // apply operation to object:
        bool modified = obj->setProperty(propertyTypeId, val, &transaction);

        if (modified) {
            transaction.addObject(obj, false, false,
                QSet<RPropertyTypeId>() << propertyTypeId);
        }
    }

    transaction.end();

    //RDebug::stopTimer("RChangePropertyOperation::apply");

    return transaction;
}
QSharedPointer<RLinetype> RClipboardOperation::copyLinetype(
        RLinetype::Id linetypeId,
        RDocument& src, RDocument& dest,
        bool overwriteLinetypes,
        RTransaction& transaction) const {

    // add linetype of entity, if the linetype exists it is overwritten
    // if overwriteLinetypes is true:
    QSharedPointer<RLinetype> srcLinetype = src.queryLinetype(linetypeId);
    if (srcLinetype.isNull()) {
        qWarning("RClipboardOperation::copyLinetype: "
                 "linetype is NULL.");
        return QSharedPointer<RLinetype>();
    }
    QString srcLinetypeName = srcLinetype->getName().toLower();
    QSharedPointer<RLinetype> destLinetype;
    if (copiedLinetypes.contains(srcLinetypeName)) {
        destLinetype = copiedLinetypes.value(srcLinetypeName);
        Q_ASSERT(!destLinetype.isNull());
    }
    else {
        if (!dest.hasLinetype(srcLinetypeName) || overwriteLinetypes) {
            destLinetype = QSharedPointer<RLinetype>(srcLinetype->clone());
            destLinetype->setDocument(&dest);
            if (destLinetype->getDocument()!=srcLinetype->getDocument()) {
                dest.getStorage().setObjectId(*destLinetype.data(), RObject::INVALID_ID);
                dest.getStorage().setObjectHandle(*destLinetype.data(), RObject::INVALID_HANDLE);
            }
            transaction.addObject(destLinetype);
        }
        else {
            destLinetype = dest.queryLinetype(srcLinetypeName);
            Q_ASSERT(!destLinetype.isNull());
        }

        copiedLinetypes.insert(srcLinetypeName, destLinetype);
    }

    return destLinetype;
}
RTransaction RDeleteAllEntitiesOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), "Deleting object(s)", undoable);
    QSet<RObject::Id> ids =
        document.queryAllEntities();

    QSetIterator<RObject::Id> i(ids);
    while (i.hasNext()) {
        transaction.deleteObject(i.next(), &document);
    }

    transaction.end();
    return transaction;
}
RTransaction RDeleteSelectionOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), text);
    transaction.setGroup(transactionGroup);

    QSet<REntity::Id> selectedEntities = document.querySelectedEntities();
    QSet<REntity::Id>::iterator it;
    for (it=selectedEntities.begin(); it!=selectedEntities.end(); it++) {
        transaction.deleteObject(*it);
    }

    transaction.end();
    return transaction;
}
Exemple #11
0
RImporter::RImporter(RDocument& document, RMessageHandler* messageHandler, RProgressHandler* progressHandler) :
    document(&document),
    messageHandler(messageHandler),
    progressHandler(progressHandler),
    transaction(document.getStorage(), "Importing", false),
    blockId(RBlock::INVALID_ID) {

    transaction.setRecordAffectedObjects(false);
    transaction.setAllowAll(true);
    transaction.setSpatialIndexDisabled(true);
    transaction.setExistingLayerDetectionDisabled(true);
    transaction.setExistingBlockDetectionDisabled(true);
    transaction.setBlockRecursionDetectionDisabled(true);
}
RTransaction RDeleteAllEntitiesOperation::apply(RDocument& document, bool preview) const {
    Q_UNUSED(preview)
    RTransaction transaction(document.getStorage(), text, undoable);
    transaction.setGroup(transactionGroup);

    QSet<RObject::Id> ids = document.queryAllEntities();

    QSetIterator<RObject::Id> i(ids);
    while (i.hasNext()) {
        transaction.deleteObject(i.next());
    }

    transaction.end();
    return transaction;
}
RTransaction RChangePropertyOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), "Changing property");

    // 20111110: always allow property changes (e.g. move entity to hidden layer)
    transaction.setAllowInvisible(true);

    QVariant val = value;

    // optimization: change layer ID instead of changing layer name:
    if (propertyTypeId==REntity::PropertyLayer && value.type() == QVariant::String) {
        val = QVariant(document.getLayerId(value.toString()));
    }

    //RDebug::startTimer();

    QSet<REntity::Id> selectedEntities = document.querySelectedEntities();
    QSet<REntity::Id>::iterator it;
    for (it = selectedEntities.begin(); it != selectedEntities.end(); it++) {

        QSharedPointer<REntity> entity = document.queryEntity(*it);
        if (entity.isNull()) {
            continue;
        }
        if (entityTypeFilter!=RS::EntityAll && entityTypeFilter!=entity->getType()) {
            continue;
        }

        // apply operation to entity:
        bool modified = entity->setProperty(propertyTypeId, val);

        if (modified) {
            transaction.addObject(entity, false,
                QSet<RPropertyTypeId>() << propertyTypeId);
        }
    }

    transaction.end();

    //RDebug::stopTimer("RChangePropertyOperation::apply");

    return transaction;
}
Exemple #14
0
RTransaction RDeleteObjectsOperation::apply(RDocument& document, bool preview) const {
    Q_UNUSED(preview)
    RTransaction transaction(document.getStorage(), text, undoable);
    transaction.setRecordAffectedObjects(recordAffectedObjects);
    transaction.setSpatialIndexDisabled(spatialIndexDisabled);
    transaction.setAllowAll(allowAll);
    transaction.setAllowInvisible(allowInvisible);
    transaction.setGroup(transactionGroup);

    for (int i = 0; i < list.size(); ++i) {
        if (list[i].isNull()) {
            qWarning() << "RDeleteObjectsOperation::apply: "
                    "list contains NULL object";
            continue;
        }
        transaction.deleteObject(list[i]);
    }
    transaction.end();
    return transaction;
}
Exemple #15
0
RTransaction RPasteOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), "Inserting object(s)", undoable);

    copy(
        sourceDocument, document,
        offset, scale, rotation, 
        flipHorizontal, flipVertical,
        toCurrentLayer, /*toCurrentBlock=*/ true,
        overwriteLayers, overwriteBlocks,
        blockName,
        transaction,
        false, false,
        false,           // toModelSpace (paste to current block, not model space)
        preview
    );

    transaction.end();

    return transaction;
}
Exemple #16
0
RTransaction RPasteOperation::apply(RDocument& document, bool preview) const {
    RTransaction transaction(document.getStorage(), text, undoable);
    transaction.setGroup(transactionGroup);

    // 20151118: allow also entities on locked / invisible layers to be pasted:
    transaction.setAllowAll(true);

    int iMax = offsets.length();
    if (preview && iMax>10) {
        iMax = 10;
    }

    double rotation = 0.0;
    if (rotations.length()==1) {
        // same rotation for all pasted instances:
        rotation = rotations[0];
    }

    for (int i=0; i<iMax; i++) {
        copy(
            sourceDocument, document,
            offsets[i], scale, i < rotations.length() ? rotations[i] : rotation,
            flipHorizontal, flipVertical,
            toCurrentLayer, /*toCurrentBlock=*/ true,
            overwriteLayers && i==0, overwriteBlocks && i==0,
            blockName,
            layerName,
            transaction,
            false, false,
            false,           // toModelSpace (paste to current block, not model space)
            preview,
            attributes
        );
    }

    transaction.end();

    return transaction;
}
Exemple #17
0
void RViewportEntity::exportEntity(RExporter& e, bool preview, bool forceSelected) const {
    Q_UNUSED(preview);
    Q_UNUSED(forceSelected);

    RDocument* doc = (RDocument*)getDocument();
    if (doc==NULL) {
        return;
    }

    RBox viewportBox(data.position, data.width, data.height);

    // if layer is visible, export viewport frame
    // viewport contents is always exported (unless viewport if off):
    if (isVisible()) {
        // export viewport frame to layer of viewport:
        e.setBrush(Qt::NoBrush);
        QList<RLine> lines = viewportBox.getLines2d();
        for (int i=0; i<lines.length(); i++) {
            e.exportLine(lines[i]);
        }
    }

    // if viewport is off, we're done:
    if (isOff()) {
        return;
    }

    // clip rectangle export
    e.exportClipRectangle(viewportBox);

    RVector offset(0,0);
    offset -= data.viewCenter * data.scale;
    offset -= data.viewTarget * data.scale;

    // create temporary block reference to model space block:
    RBlockReferenceData modelSpaceData(
        doc,
        RBlockReferenceData(
            doc->getModelSpaceBlockId(),
            data.position + offset,
            RVector(data.scale, data.scale),
            0.0
        )
    );
    modelSpaceData.update();

    // start clipping from here:
    e.setClipping(true);

    // render model space block reference into viewport:
    QSet<REntity::Id> ids = doc->queryBlockEntities(doc->getModelSpaceBlockId());
    QList<REntity::Id> list = doc->getStorage().orderBackToFront(ids);
    int i;
    QList<REntity::Id>::iterator it;
    for (it = list.begin(), i = 0; it != list.end(); it++) {
        if (preview && i>RSettings::getPreviewEntities()) {
            break;
        }

        QSharedPointer<REntity> entity = modelSpaceData.queryEntity(*it);
        if (entity.isNull()) {
            continue;
        }

        entity->rotate(data.rotation, data.position);

        // prevent recursions:
        if (entity->getType()==RS::EntityViewport) {
            continue;
        }

        RBox bb = entity->getBoundingBox();
        if (!viewportBox.intersects(bb)) {
            continue;
        }

        entity->scaleVisualProperties(data.scale);

        e.exportEntity(*entity, preview, true);

        i++;
    }

    e.setClipping(false);
}
void RClipboardOperation::copy(
        RDocument& src, RDocument& dest,
        const RVector& offset,
        double scale,
        double rotation,
        bool flipHorizontal,
        bool flipVertical,
        bool toCurrentLayer,
        bool toCurrentBlock,
        bool overwriteLayers,
        bool overwriteBlocks,
        const QString& blockName,
        const QString& layerName,
        RTransaction& transaction,
        bool selectionOnly, bool clear,
        bool toModelSpaceBlock,
        bool preview,
        const RQMapQStringQString& attributes) const {

    bool overwriteLinetypes = false;

    double unitScale;
    if (src.getUnit()==RS::None) {
        unitScale = 1.0;
    }
    else {
        unitScale = RUnit::convert(1.0, src.getUnit(), dest.getUnit());
    }

    if (clear) {
        dest.clear();
    }

    QSet<REntity::Id> entityIdsSet;
    if (selectionOnly) {
        entityIdsSet = src.querySelectedEntities();
    }
    else {
        entityIdsSet = src.queryAllEntities();
    }
    QList<REntity::Id> entityIdsList = src.getStorage().orderBackToFront(entityIdsSet);

    // Non-const offset. reset to 0/0/0 if copying to block
    //    (offset implemented as block reference offset).
    RVector off = offset;

    bool hasBlock = false;

    QSet<REntity::Id> attributeIds;

    // this part is used to insert ('paste') blocks from the part library
    // as new blocks:
    QSharedPointer<RBlockReferenceEntity> refp;
    if (!blockName.isNull()) {
        QSharedPointer<RBlock> block;
        hasBlock = dest.hasBlock(blockName);

        // block does not exist in dest - or -
        // block exists in dest and must be overwritten:
        if (!hasBlock || overwriteBlocks) {
            block = QSharedPointer<RBlock> (new RBlock(&dest, blockName,
                    RVector(0, 0, 0)));
            transaction.overwriteBlock(block);
        }

        // block exists and must not be overwritten:
        else {
            block = dest.queryBlock(blockName);
        }

        Q_ASSERT(!block.isNull());

        // create new block reference that references new, overwritten or existing block
        // (insert later, when block is complete, so we have bounding box for spatial index):
        RBlockReferenceEntity* ref = new RBlockReferenceEntity(&dest,
                RBlockReferenceData(block->getId(), RVector(0,0,0),
                                    RVector(1.0, 1.0, 1.0), 0.0));
        refp = QSharedPointer<RBlockReferenceEntity>(ref);
        refp->setBlockId(dest.getCurrentBlockId());
        off = RVector(0, 0, 0);
        if (flipHorizontal) {
            refp->flipHorizontal();
        }
        if (flipVertical) {
            refp->flipVertical();
        }
        //ref->scale(scale * unitScale);
        refp->scale(scale);
        refp->rotate(rotation);
        refp->move(offset);

        // create attribute for each attribute definition in block with
        // invalid parent ID (fixed later, when block reference ID is known):
        QSet<REntity::Id> ids = src.queryAllEntities();
        QSet<REntity::Id>::iterator it;
        for (it=ids.begin(); it!=ids.end(); it++) {
            REntity::Id id = *it;
            QSharedPointer<RAttributeDefinitionEntity> attDef =
                src.queryEntity(id).dynamicCast<RAttributeDefinitionEntity>();
            if (attDef.isNull()) {
                continue;
            }

            QSharedPointer<RAttributeEntity> att(
                new RAttributeEntity(
                    &dest,
                    RAttributeData(attDef->getData(), REntity::INVALID_ID, attDef->getTag())
                )
            );
            att->scale(unitScale);
            refp->applyTransformationTo(*att);

            // assign values to attributes:
            QString tag = att->getTag();
            if (attributes.contains(tag)) {
                att->setText(attributes[tag]);
            }

            // make sure the attribute has the correct layer ID of the
            // corresponding layer in dest:
            QSharedPointer<RLayer> destLayer = copyEntityLayer(*attDef, src, dest, overwriteLayers, transaction);
            att->setLayerId(destLayer->getId());

            QSharedPointer<RLinetype> destLinetype = copyEntityLinetype(*attDef, src, dest, overwriteLinetypes, transaction);
            att->setLinetypeId(destLinetype->getId());

            transaction.addObject(att, false);
            attributeIds.insert(att->getId());
        }

        scale = 1.0;
        rotation = 0.0;
        flipHorizontal = false;
        flipVertical = false;
        toCurrentLayer = false;
        //toCurrentBlock = false;
    }


    // copy entities from src to dest:
    //     if the block existed already in dest and is not overwritten,
    //     there's nothing to do here:
    if (!hasBlock || overwriteBlocks || preview) {
        copiedLayers.clear();
        copiedLinetypes.clear();
        copiedBlocks.clear();

        int counter = 0;
        QList<REntity::Id>::iterator it;
        for (it=entityIdsList.begin(); it!=entityIdsList.end(); ++it) {
            if (preview && ++counter>RSettings::getPreviewEntities()) {
                break;
            }

            QSharedPointer<REntity> entity = src.queryEntityDirect(*it);
            if (entity.isNull() || entity->isUndone()) {
                continue;
            }

            copyEntity(
                        *entity.data(),
                        src, dest,
                        off, scale, unitScale, rotation,
                        flipHorizontal, flipVertical,
                        toCurrentLayer, toCurrentBlock,
                        overwriteLayers, overwriteBlocks,
                        blockName,
                        transaction,
                        toModelSpaceBlock       // to model space: true for copy
                        // (allow copy from inside any block definition),
                        // false for paste
                        );
        }
    }

    // only overwrite layers:
    else if (overwriteLayers) {
        copiedLayers.clear();

        int counter = 0;
        QList<REntity::Id>::iterator it;
        for (it=entityIdsList.begin(); it!=entityIdsList.end(); ++it) {
            if (preview && ++counter>RSettings::getPreviewEntities()) {
                break;
            }

            QSharedPointer<REntity> entity = src.queryEntityDirect(*it);
            if (entity.isNull() || entity->isUndone()) {
                continue;
            }

            copyEntityLayer(
                        *entity.data(),
                        src, dest,
                        overwriteLayers,
                        transaction
                        );
        }
    }

    // copying of entire block complete, insert block reference now since
    // we now have the bounding box for the spatial index:
    if (!refp.isNull()) {
        bool useCurrentAttributes = true;
        if (!layerName.isEmpty()) {
            useCurrentAttributes = false;
            refp->setLayerId(dest.getLayerId(layerName));
        }
        transaction.addObject(refp, useCurrentAttributes);

        // fix parent ID of attributes created by the new inserted block:
        REntity::Id refId = refp->getId();
        //QSet<REntity::Id> ids = dest.queryAllEntities();
        QSet<REntity::Id>::iterator it;
        for (it=attributeIds.begin(); it!=attributeIds.end(); it++) {
            REntity::Id id = *it;
            QSharedPointer<RAttributeEntity> e =
                dest.queryEntityDirect(id).dynamicCast<RAttributeEntity>();
            if (e.isNull()) {
                continue;
            }

            if (e->getParentId()==REntity::INVALID_ID) {
                e->setParentId(refId);
            }
        }
    }

    transaction.endCycle();
}
/**
 * Adds the given entity (and its layer(s) and block reference(s)) to the
 * given document.
 *
 * \param blockName Name of an existing block in dest
 */
void RClipboardOperation::copyEntity(
        REntity& entity,
        RDocument& src, RDocument& dest,
        const RVector& offset,
        double scale,
        double unitScale,
        double rotation,
        bool flipHorizontal,
        bool flipVertical,
        bool toCurrentLayer,
        bool toCurrentBlock,
        bool overwriteLayers,
        bool overwriteBlocks,
        const QString& blockName,
        RTransaction& transaction,
        bool toModelSpaceBlock) const {

    bool overwriteLinetypes = false;

    QSharedPointer<RLayer> destLayer = copyEntityLayer(entity, src, dest, overwriteLayers, transaction);
    QSharedPointer<RLinetype> destLinetype = copyEntityLinetype(entity, src, dest, overwriteLinetypes, transaction);

    // add block the entity belongs to, if the block exists it is overwritten
    // if 'overwriteBlocks' is true:
    QSharedPointer<RBlock> srcBlock =
        src.queryBlock(entity.getBlockId());
    if (srcBlock.isNull()) {
        qWarning("RClipboardOperation::copyToDocument: "
            "block of entity is NULL.");
        return;
    }
    QString srcBlockName = srcBlock->getName();
    QSharedPointer<RBlock> destBlock;
    if (copiedBlocks.contains(srcBlockName)) {
        destBlock = copiedBlocks.value(srcBlockName);
    }
    else {
        QString destBlockName;
        if (!blockName.isNull()) {
            destBlockName = blockName;
        }
        else {
            if (toCurrentBlock) {
                destBlockName = dest.getBlockName(dest.getCurrentBlockId());
            }
            else {
                destBlockName = srcBlock->getName();
            }
        }
        if (!dest.hasBlock(destBlockName) || (overwriteBlocks && blockName.isNull())) {
            destBlock = QSharedPointer<RBlock> (srcBlock->clone());
            dest.getStorage().setObjectId(*destBlock.data(), RObject::INVALID_ID);
            dest.getStorage().setObjectHandle(*destBlock.data(), RObject::INVALID_HANDLE);
            destBlock->setDocument(&dest);
            if (dest.hasBlock(destBlockName)) {
                if (!transaction.overwriteBlock(destBlock)) {
                    destBlock = dest.queryBlock(destBlockName);
                }
            }
            else {
                transaction.addObject(destBlock);
            }
        } else {
            destBlock = dest.queryBlock(destBlockName);
        }

        copiedBlocks.insert(srcBlockName, destBlock);
    }

    Q_ASSERT(destBlock->getId()!=RBlock::INVALID_ID);

    // entity is a block reference:
    // add entities of the block the block reference refers to (the block
    // definition is then added automatically):
    // if block contents has already been copied, do nothing
    RBlockReferenceEntity* blockRef =
        dynamic_cast<RBlockReferenceEntity*>(&entity);
    if (blockRef!=NULL && !copiedBlockContents.contains(blockRef->getReferencedBlockId())) {
        QSharedPointer<RBlock> refBlock =
            src.queryBlock(blockRef->getReferencedBlockId());
        if (refBlock.isNull()) {
            qWarning("RClipboardOperation::copyToDocument: "
                "entity references a NULL block.");
            return;
        }

        copiedBlockContents.insert(blockRef->getReferencedBlockId());

        // TODO: don't do this twice:
        //qDebug() << "RClipboardOperation::copyToDocument: copying block: " << refBlock->getName();
        // if block exists in dest, it has already been copied or was
        // already there and needs to be overwritten:
        QSharedPointer<RBlock> refBlockDest = dest.queryBlock(refBlock->getName());
        if (refBlockDest.isNull() || overwriteBlocks) {
            QSet<REntity::Id> ids = src.queryBlockEntities(refBlock->getId());
            bool first = true;
            QSet<REntity::Id>::iterator it;
            for (it=ids.begin(); it!=ids.end(); ++it) {
                QSharedPointer<REntity> e = src.queryEntityDirect(*it);
                if (e.isNull()) {
                    continue;
                }

                copyEntity(
                    *e.data(),
                    src, dest,
                    RVector::nullVector,
                    1.0,          // scale from user options not applied to block contents 
                                  // but to block reference
                    unitScale, 
                    0.0,
                    false, false, // no flips
                    false, false, // keep original block and layer
                    overwriteLayers, first && overwriteBlocks,
                    QString(),
                    transaction,
                    false         // not to model space but actual block
                );
                first = false;
            }
        }
    }

    // add entity self:
    QSharedPointer<REntity> destEntity = QSharedPointer<REntity>(entity.clone());
    //dest.getStorage().setObjectId(*destEntity.data(), RObject::INVALID_ID);
    dest.getStorage().setObjectHandle(*destEntity.data(), RObject::INVALID_HANDLE);
    destEntity->setSelected(false);

    // apply transformations:
    if (flipHorizontal) {
        destEntity->flipHorizontal();
    }
    if (flipVertical) {
        destEntity->flipVertical();
    }
    if (blockRef!=NULL) {
        destEntity->scale(scale);
    }
    else {
        destEntity->scale(scale * unitScale);
    }
    destEntity->rotate(rotation);
    // correct block reference offset. necessary for unit conversion:
    if (blockRef!=NULL && src.getUnit()!=dest.getUnit()) {
        destEntity->move(-blockRef->getPosition());
        destEntity->move(blockRef->getPosition() * unitScale);
    }
    destEntity->move(offset);

    destEntity->setDocument(&dest);
    if (toCurrentLayer) {
        // paste to current layer:
        destEntity->setLayerId(dest.getCurrentLayerId());
    }
    else {
        // paste to original layer:
        Q_ASSERT(!destLayer.isNull());
        destEntity->setLayerId(destLayer->getId());
    }

    destEntity->setLinetypeId(destLinetype->getId());

    if (toModelSpaceBlock) {
        destEntity->setBlockId(dest.getModelSpaceBlockId());
    }
    else {
        destEntity->setBlockId(destBlock->getId());
    }

    // correct referenced block id of pasted block reference:
    QSharedPointer<RBlockReferenceEntity> destBlockRef =
        destEntity.dynamicCast<RBlockReferenceEntity>();
    if (!destBlockRef.isNull() && blockRef!=NULL) {
        QString bn = src.getBlockName(blockRef->getReferencedBlockId());
        RBlock::Id blockId = dest.getBlockId(bn);
        destBlockRef->setReferencedBlockId(blockId);
//        qDebug() << "not yet updated block ref: " << *destBlockRef;
//        destBlockRef->update();
//        qDebug() << "updated block ref: " << *destBlockRef;
    }

    transaction.addObject(destEntity, false, true);
}
Exemple #20
0
QSharedPointer<RLayer> RClipboardOperation::copyLayer(
        RLayer::Id layerId,
        RDocument& src, RDocument& dest,
        bool overwriteLayers,
        RTransaction& transaction) const {

    // copy parent layers:
    QString layerName = src.getLayerName(layerId);
    if (layerName.contains(" ... ")) {
        QStringList l = layerName.split(" ... ");
        l.removeLast();
        while (!l.isEmpty()) {
            QString parentLayerName = l.join(" ... ");
            QSharedPointer<RLayer> parentLayer = src.queryLayer(parentLayerName);
            if (!parentLayer.isNull()) {
                copyLayer(parentLayer->getId(), src, dest, overwriteLayers, transaction);
            }
            else {
                qWarning() << "parent layer of layer '" << layerName << "' not found: " << parentLayerName;
            }
            l.removeLast();
        }
    }

    bool overwriteLinetypes = false;

    // add layer the entity is on, if the layer exists it is overwritten
    // if overwriteLayers is true:
    QSharedPointer<RLayer> srcLayer = src.queryLayer(layerId);
    if (srcLayer.isNull()) {
        qWarning("RClipboardOperation::copyLayer: "
                 "layer is NULL.");
        return QSharedPointer<RLayer>();
    }

    QSharedPointer<RLinetype> destLinetype = copyLinetype(srcLayer->getLinetypeId(), src, dest, overwriteLinetypes, transaction);

    QString srcLayerName = srcLayer->getName();
    QSharedPointer<RLayer> destLayer;
    if (copiedLayers.contains(srcLayerName)) {
        destLayer = copiedLayers.value(srcLayerName);
        Q_ASSERT(!destLayer.isNull());
    }
    else {
        if (!dest.hasLayer(srcLayerName) || overwriteLayers) {
            destLayer = QSharedPointer<RLayer>(srcLayer->clone());
            destLayer->setDocument(&dest);
            if (destLayer->getDocument()!=srcLayer->getDocument()) {
                dest.getStorage().setObjectId(*destLayer.data(), RObject::INVALID_ID);
                dest.getStorage().setObjectHandle(*destLayer.data(), RObject::INVALID_HANDLE);
            }
            transaction.addObject(destLayer);
        }
        else {
            destLayer = dest.queryLayer(srcLayerName);
            Q_ASSERT(!destLayer.isNull());
        }

        copiedLayers.insert(srcLayerName, destLayer);
    }

    if (!destLinetype.isNull()) {
        destLayer->setLinetypeId(destLinetype->getId());
    }

    return destLayer;
}