bool removeKeyframes(KisImageSP image, const FrameItemList &frames) { bool result = false; QScopedPointer<KUndo2Command> cmd( new KUndo2Command(kundo2_i18np("Remove Keyframe", "Remove Keyframes", frames.size()))); // lisp-lovers present ;) foreach (const FrameItem &item, frames) { const int time = item.time; KisNodeSP node = item.node; KisKeyframeChannel *content = node->getKeyframeChannel(KisKeyframeChannel::Content.id()); if (!content) continue; KisKeyframeSP keyframe = content->keyframeAt(time); if (!keyframe) continue; content->deleteKeyframe(keyframe, cmd.data()); result = true; } if (result) { image->postExecutionUndoAdapter()->addCommand(toQShared(cmd.take())); } return result; }
void updateMask(bool isHidden) { /** * Depending on whether the mask is hidden we should either * update it entirely via the setDirty() call, or we can use a * lightweight approach by directly regenerating the * precalculated static image using * KisRecalculateTransformMaskJob. */ if (!isHidden) { KisRecalculateTransformMaskJob updateJob(m_mask); updateJob.run(); } else { m_mask->recaclulateStaticImage(); QRect updateRect = m_mask->extent(); KisNodeSP parent = m_mask->parent(); if (parent && parent->original()) { updateRect |= parent->original()->defaultBounds()->bounds(); } m_mask->setDirty(updateRect); } }
KisNodeSP KisKraLoader::loadNodes(const KoXmlElement& element, KisImageWSP image, KisNodeSP parent) { KoXmlNode node = element.firstChild(); KoXmlNode child; if (!node.isNull()) { if (node.isElement()) { if (node.nodeName().toUpper() == LAYERS.toUpper() || node.nodeName().toUpper() == MASKS.toUpper()) { for (child = node.lastChild(); !child.isNull(); child = child.previousSibling()) { KisNodeSP node = loadNode(child.toElement(), image, parent); if (node) { image->nextLayerName(); // Make sure the nameserver is current with the number of nodes. image->addNode(node, parent); if (node->inherits("KisLayer") && child.childNodesCount() > 0) { loadNodes(child.toElement(), image, node); } } } } } } return parent; }
KisImageLayerRemoveCommand::KisImageLayerRemoveCommand(KisImageSP image, KisNodeSP layer) : KisImageCommand(i18n("Remove Layer"), image) { m_layer = layer; m_prevParent = layer->parent(); m_prevAbove = layer->prevSibling(); }
void refreshLayerMovementAbilities() { layerMeta.clear(); if (layers.count() == 0) return; for(int i = 0; i < layers.count(); ++i) { const KisNodeSP layer = layers.at(i); LayerModelMetaInfo ability; if (i > 0) ability.canMoveUp = true; if (i < layers.count() - 1) ability.canMoveDown = true; KisNodeSP parent = layer; while(parent) { ++ability.depth; parent = parent->parent(); } if (ability.depth > 1) ability.canMoveLeft = true; if (i < layers.count() - 1 && qobject_cast<const KisGroupLayer*>(layers.at(i + 1).constData())) ability.canMoveRight = true; layerMeta[layer] = ability; } }
QRect KisFilterMask::needRect(const QRect& rect, PositionToFilthy pos) const { Q_UNUSED(pos); /** * FIXME: This check of the emptiness should be done * on the higher/lower level */ if(rect.isEmpty()) return rect; KisSafeFilterConfigurationSP filterConfig = filter(); if (!filterConfig) return rect; KisNodeSP parent = this->parent(); const int lod = parent && parent->projection() ? parent->projection()->defaultBounds()->currentLevelOfDetail() : 0; KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); /** * If we need some additional pixels even outside of a selection * for accurate layer filtering, we'll get them! * And no KisMask::needRect will prevent us from doing this! ;) * That's why simply we do not call KisMask::needRect here :) */ return filter->neededRect(rect, filterConfig.data(), lod); }
/** * FIXME: try to cache filter pointer inside a Private block */ QRect KisFilterMask::changeRect(const QRect &rect, PositionToFilthy pos) const { /** * FIXME: This check of the emptiness should be done * on the higher/lower level */ if(rect.isEmpty()) return rect; QRect filteredRect = rect; KisSafeFilterConfigurationSP filterConfig = filter(); if (filterConfig) { KisNodeSP parent = this->parent(); const int lod = parent && parent->projection() ? parent->projection()->defaultBounds()->currentLevelOfDetail() : 0; KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); filteredRect = filter->changedRect(rect, filterConfig.data(), lod); } /** * We can't paint outside a selection, that is why we call * KisMask::changeRect to crop actual change area in the end */ filteredRect = KisMask::changeRect(filteredRect, pos); /** * FIXME: Think over this solution * Union of rects means that changeRect returns NOT the rect * changed by this very layer, but an accumulated rect changed * by all underlying layers. Just take into account and change * documentation accordingly */ return rect | filteredRect; }
KisImageCommand::UpdateTarget::UpdateTarget(KisImageWSP image, KisNodeSP removedNode, const QRect &updateRect) : m_image(image), m_updateRect(updateRect) { m_needsFullRefresh = false; if(!isLayer(removedNode)) { m_node = removedNode->parent(); } else { m_node = removedNode; while((m_node = m_node->nextSibling()) && !isLayer(m_node)); if(!m_node) { m_node = removedNode; while((m_node = m_node->prevSibling()) && !isLayer(m_node)); } if(!m_node) { m_node = removedNode->parent(); m_needsFullRefresh = true; } } }
bool KisNodeFacade::moveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis) { dbgImage << "moveNode " << node << " " << parent << " " << aboveThis; if (!node) { dbgImage << "cannot move null node"; return false; } if (!parent) { dbgImage << "cannot move to null parent"; return false; } if (node == parent) { dbgImage << "cannot move self inside self"; return false; } if (node == aboveThis) { dbgImage << "cannot move self above self"; return false; } if (parent == aboveThis) { dbgImage << "cannot move above parent"; return false; } if (!node->parent()) { dbgImage << "node does not have a parent"; return false; } if (aboveThis && aboveThis->parent() != parent) { dbgImage << "above this parent is not the parent"; return false; } int newIndex = aboveThis ? parent->index(aboveThis) + 1 : 0; return moveNode(node, parent, newIndex); }
KisNodeSP findNode(KisNodeSP node, const QPoint &point, bool wholeGroup, bool editableOnly) { KisNodeSP foundNode = 0; while (node) { KisLayerSP layer = dynamic_cast<KisLayer*>(node.data()); if (!layer || !layer->isEditable()) { node = node->prevSibling(); continue; } KoColor color(layer->projection()->colorSpace()); layer->projection()->pixel(point.x(), point.y(), &color); KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(layer.data()); if ((group && group->passThroughMode()) || color.opacityU8() != OPACITY_TRANSPARENT_U8) { if (layer->inherits("KisGroupLayer") && (!editableOnly || layer->isEditable())) { // if this is a group and the pixel is transparent, don't even enter it foundNode = findNode(node->lastChild(), point, wholeGroup, editableOnly); } else { foundNode = !wholeGroup ? node : node->parent(); } } if (foundNode) break; node = node->prevSibling(); } return foundNode; }
void KisCutCopyActionFactory::run(bool willCut, KisView2 *view) { KisImageSP image = view->image(); bool haveShapesSelected = view->selectionManager()->haveShapesSelected(); if (haveShapesSelected) { #ifdef __GNUC__ #warning "Add saving of XML data for Cut/Copy of shapes" #endif image->barrierLock(); if (willCut) { view->canvasBase()->toolProxy()->cut(); } else { view->canvasBase()->toolProxy()->copy(); } image->unlock(); } else { KisNodeSP node = view->activeNode(); if (!node) return; image->barrierLock(); ActionHelper::copyFromDevice(view, node->paintDevice()); image->unlock(); KUndo2Command *command = 0; if (willCut && node->isEditable()) { struct ClearSelection : public KisTransactionBasedCommand { ClearSelection(KisNodeSP node, KisSelectionSP sel) : m_node(node), m_sel(sel) {} KisNodeSP m_node; KisSelectionSP m_sel; KUndo2Command* paint() { KisTransaction transaction("", m_node->paintDevice()); m_node->paintDevice()->clearSelection(m_sel); m_node->setDirty(m_sel->selectedRect()); return transaction.endAndTake(); } }; command = new ClearSelection(node, view->selection()); } QString actionName = willCut ? i18n("Cut") : i18n("Copy"); KisProcessingApplicator *ap = beginAction(view, actionName); if (command) { ap->applyCommand(command, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); } KisOperationConfiguration config(id()); config.setProperty("will-cut", willCut); endAction(ap, config.toXML()); } }
bool KisNodeFacade::removeNode(KisNodeSP node) { if (!node) return false; if (!node->parent()) return false; return node->parent()->remove(node); }
int deepChildCount(KisNodeSP layer) { quint32 childCount = layer->childCount(); QList<KisNodeSP> children = layer->childNodes(layerClassNames(), KoProperties()); for(quint32 i = 0; i < childCount; ++i) childCount += deepChildCount(children.at(i)); return childCount; }
KisNodeSP KisDummiesFacadeBase::findFirstLayer(KisNodeSP root) { KisNodeSP child = root->firstChild(); while(child && !child->inherits("KisLayer")) { child = child->nextSibling(); } return child; }
bool KisNodeFacade::toTop(KisNodeSP node) { if (!node) return false; if (!node->parent()) return false; if (node == node->parent()->lastChild()) return true; return moveNode(node, node->parent(), node->parent()->lastChild()); }
MoveNodeStruct(KisImageSP _image, KisNodeSP _node, KisNodeSP _parent, KisNodeSP _above) : image(_image), node(_node), newParent(_parent), newAbove(_above), oldParent(_node->parent()), oldAbove(_node->prevSibling()) { }
QImage utils::StrokeTester::doStroke(bool cancelled, bool indirectPainting, bool externalLayer, bool testUpdates, bool needQImage) { KisImageSP image = utils::createImage(0, m_imageSize); KoCanvasResourceManager *manager = utils::createResourceManager(image, 0, m_presetFilename); KisNodeSP currentNode; for (int i = 0; i < m_numIterations; i++) { modifyResourceManager(manager, image, i); KisPainter *painter = new KisPainter(); KisResourcesSnapshotSP resources = new KisResourcesSnapshot(image, image->rootLayer()->firstChild(), image->postExecutionUndoAdapter(), manager); if(externalLayer) { KisNodeSP externalNode = new KisPaintLayer(0, "extlyr", OPACITY_OPAQUE_U8, image->colorSpace()); resources->setCurrentNode(externalNode); Q_ASSERT(resources->currentNode() == externalNode); } initImage(image, resources->currentNode(), i); KisStrokeStrategy *stroke = createStroke(indirectPainting, resources, painter, image); m_strokeId = image->startStroke(stroke); addPaintingJobs(image, resources, painter, i); if(!cancelled) { image->endStroke(m_strokeId); } else { image->cancelStroke(m_strokeId); } image->waitForDone(); currentNode = resources->currentNode(); } QImage resultImage; if(needQImage) { KisPaintDeviceSP device = testUpdates ? image->projection() : currentNode->paintDevice(); resultImage = device->convertToQImage(0, 0, 0, image->width(), image->height()); } image = 0; delete manager; return resultImage; }
void KisDummiesFacadeBase::slotNodeAdded(KisNodeSP node) { emit sigContinueAddNode(node, node->parent(), node->prevSibling()); KisNodeSP childNode = node->firstChild(); while (childNode) { slotNodeAdded(childNode); childNode = childNode->nextSibling(); } }
KisImageLayerMoveCommand::KisImageLayerMoveCommand(KisImageSP image, KisNodeSP layer, KisNodeSP newParent, KisNodeSP newAbove) : KisImageCommand(i18n("Move Layer"), image) { m_layer = layer; m_newParent = newParent; m_newAbove = newAbove; m_prevParent = layer->parent(); m_prevAbove = layer->prevSibling(); m_index = -1; }
KisImageLayerMoveCommand::KisImageLayerMoveCommand(KisImageSP image, KisNodeSP node, KisNodeSP newParent, quint32 index) : KisImageCommand(i18n("Move Layer"), image) { m_layer = node; m_newParent = newParent; m_newAbove = 0; m_prevParent = node->parent(); m_prevAbove = node->prevSibling(); m_index = index; }
void KisDummiesFacadeBase::slotRemoveNode(KisNodeSP node) { KisNodeSP childNode = node->lastChild(); while (childNode) { slotRemoveNode(childNode); childNode = childNode->prevSibling(); } emit sigContinueRemoveNode(node); }
void testObligeSingleChildImpl(bool transpDefaultPixel) { QString id = !transpDefaultPixel ? "single_layer_no_channel_flags_nontransp_def_pixel.kra" : "single_layer_no_channel_flags_transp_def_pixel.kra"; QString fileName = TestUtil::fetchDataFileLazy(id); KisDocument *doc = KisPart::instance()->createDocument(); doc->loadNativeFormat(fileName); KisImageWSP image = doc->image(); QVERIFY(image); QCOMPARE(image->nlayers(), 2); KisNodeSP root = image->root(); KisNodeSP child = root->firstChild(); QVERIFY(child); QCOMPARE(root->original(), root->projection()); if (transpDefaultPixel) { QCOMPARE(root->original(), child->projection()); } else { QVERIFY(root->original() != child->projection()); } delete doc; }
bool moveKeyframes(KisImageSP image, const FrameItemList &srcFrames, const FrameItemList &dstFrames, bool copy) { if (srcFrames.size() != dstFrames.size()) return false; bool result = false; QScopedPointer<KUndo2Command> cmd( new KUndo2Command(!copy ? kundo2_i18np("Move Keyframe", "Move Keyframes", srcFrames.size()) : kundo2_i18np("Copy Keyframe", "Copy Keyframes", srcFrames.size()))); // lisp-lovers present ;) for (int i = 0; i < srcFrames.size(); i++) { const int srcTime = srcFrames[i].time; KisNodeSP srcNode = srcFrames[i].node; const int dstTime = dstFrames[i].time; KisNodeSP dstNode = dstFrames[i].node; if (srcNode != dstNode) continue; KisKeyframeChannel *content = srcNode->getKeyframeChannel(KisKeyframeChannel::Content.id()); if (!content) continue; KisKeyframeSP dstKeyframe = content->keyframeAt(dstTime); if (dstKeyframe) { content->deleteKeyframe(dstKeyframe, cmd.data()); } KisKeyframeSP srcKeyframe = content->keyframeAt(srcTime); if (srcKeyframe) { if (copy) { content->copyKeyframe(srcKeyframe, dstTime, cmd.data()); } else { content->moveKeyframe(srcKeyframe, dstTime, cmd.data()); } } result = true; } if (result) { image->postExecutionUndoAdapter()->addCommand(toQShared(cmd.take())); } return result; }
bool KisNodeFacade::addNode(KisNodeSP node, KisNodeSP parent) { dbgImage << "Add node " << node << " to " << parent; if (!node) return false; if (!parent && !m_d->root) return false; if (parent) return parent->add(node, parent->lastChild()); else return m_d->root->add(node, m_d->root->lastChild()); }
bool KisNodeFacade::lowerNode(KisNodeSP node) { if (!node) return false; if (!node->parent()) return false; if (node->prevSibling()) return raiseNode(node->prevSibling()); else return true; // We're already at bottom, but there's no sense // in complaining }
void KisClearActionFactory::run(KisView2 *view) { #ifdef __GNUC__ #warning "Add saving of XML data for Clear action" #endif KisNodeSP node = view->activeNode(); if (!node || !node->isEditable()) return; view->canvasBase()->toolProxy()->deleteSelection(); }
KisImageLayerMoveCommand::KisImageLayerMoveCommand(KisImageWSP image, KisNodeSP layer, KisNodeSP newParent, KisNodeSP newAbove, bool doUpdates) : KisImageCommand(kundo2_i18n("Move Layer"), image) { m_layer = layer; m_newParent = newParent; m_newAbove = newAbove; m_prevParent = layer->parent(); m_prevAbove = layer->prevSibling(); m_index = -1; m_useIndex = false; m_doUpdates = doUpdates; }
KisImageLayerMoveCommand::KisImageLayerMoveCommand(KisImageWSP image, KisNodeSP node, KisNodeSP newParent, quint32 index) : KisImageCommand(kundo2_i18n("Move Layer"), image) { m_layer = node; m_newParent = newParent; m_newAbove = 0; m_prevParent = node->parent(); m_prevAbove = node->prevSibling(); m_index = index; m_useIndex = true; m_doUpdates = true; }
bool KisNodeFacade::raiseNode(KisNodeSP node) { if (!node) return false; if (!node->parent()) return false; if (node->nextSibling()) return moveNode(node, node->parent(), node->nextSibling()); else return true; // we're already at the top, but there is no // sense in complaining. }
void dumpNodeStack(KisNodeSP node, QString prefix = QString("\t")) { for (uint i = 0; i < node->childCount(); ++i) { if (node->at(i)->parent()) dbgImage << prefix << "\t" << node->at(i) << "node at" << i << " has index from parent:" << node->index(node->at(i)); if (node->at(i)->childCount() > 0) { dumpNodeStack(node->at(i), prefix + "\t"); } } }