File indexing completed on 2025-04-27 04:08:16
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2012 Dan Leinir Turthra Jensen <admin@leinir.dk> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "LayerModel.h" 0008 #include "LayerThumbProvider.h" 0009 #include <PropertyContainer.h> 0010 #include <kis_node_model.h> 0011 #include <KisViewManager.h> 0012 #include <kis_canvas2.h> 0013 #include <kis_node_manager.h> 0014 #include <kis_dummies_facade_base.h> 0015 #include <KisDocument.h> 0016 #include <kis_composite_ops_model.h> 0017 #include <kis_node.h> 0018 #include <kis_image.h> 0019 #include <kis_layer.h> 0020 #include <kis_group_layer.h> 0021 #include <kis_paint_layer.h> 0022 #include <kis_filter_mask.h> 0023 #include <kis_shape_controller.h> 0024 #include <kis_adjustment_layer.h> 0025 #include <kis_selection_manager.h> 0026 #include <filter/kis_filter.h> 0027 #include <filter/kis_filter_configuration.h> 0028 #include <filter/kis_filter_registry.h> 0029 #include <KoShapeControllerBase.h> 0030 #include <KoProperties.h> 0031 #include <QQmlEngine> 0032 #include <kis_base_node.h> 0033 #include "KisSelectionActionsAdapter.h" 0034 #include <KisGlobalResourcesInterface.h> 0035 0036 struct LayerModelMetaInfo { 0037 0038 bool canMoveUp {false}; 0039 bool canMoveRight {false}; 0040 bool canMoveDown {false}; 0041 bool canMoveLeft {false}; 0042 int depth {-1}; 0043 }; 0044 0045 class LayerModel::Private { 0046 public: 0047 Private(LayerModel* qq) 0048 : q(qq) 0049 , nodeModel(new KisNodeModel(qq)) 0050 , updateActiveLayerWithNewFilterConfigTimer(new QTimer(qq)) 0051 , imageChangedTimer(new QTimer(qq)) 0052 { 0053 QList<KisFilterSP> tmpFilters = KisFilterRegistry::instance()->values(); 0054 Q_FOREACH (const KisFilterSP& filter, tmpFilters) 0055 { 0056 filters[filter.data()->id()] = filter.data(); 0057 } 0058 updateActiveLayerWithNewFilterConfigTimer->setInterval(0); 0059 updateActiveLayerWithNewFilterConfigTimer->setSingleShot(true); 0060 connect(updateActiveLayerWithNewFilterConfigTimer, SIGNAL(timeout()), qq, SLOT(updateActiveLayerWithNewFilterConfig())); 0061 0062 imageChangedTimer->setInterval(250); 0063 imageChangedTimer->setSingleShot(true); 0064 connect(imageChangedTimer, SIGNAL(timeout()), qq, SLOT(imageHasChanged())); 0065 } 0066 0067 LayerModel* q {nullptr}; 0068 QList<KisNodeSP> layers; 0069 QHash<const KisNode*, LayerModelMetaInfo> layerMeta; 0070 KisNodeModel* nodeModel {nullptr}; 0071 bool aboutToRemoveRoots {false}; 0072 KisViewManager* view {nullptr}; 0073 KisCanvas2* canvas {nullptr}; 0074 QScopedPointer<KisSelectionActionsAdapter> selectionActionsAdapter; 0075 QPointer<KisNodeManager> nodeManager; 0076 KisImageWSP image; 0077 KisNodeSP activeNode; 0078 QQmlEngine* declarativeEngine {nullptr}; 0079 LayerThumbProvider* thumbProvider {nullptr}; 0080 QHash<QString, const KisFilter*> filters; 0081 0082 KisFilterConfigurationSP newConfig; 0083 QTimer* updateActiveLayerWithNewFilterConfigTimer {nullptr}; 0084 0085 QTimer* imageChangedTimer {nullptr}; 0086 static int counter() 0087 { 0088 static int count = 0; 0089 return count++; 0090 } 0091 0092 static QStringList layerClassNames() 0093 { 0094 QStringList list; 0095 list << "KisGroupLayer"; 0096 list << "KisPaintLayer"; 0097 list << "KisFilterMask"; 0098 list << "KisAdjustmentLayer"; 0099 return list; 0100 } 0101 0102 int deepChildCount(KisNodeSP layer) 0103 { 0104 quint32 childCount = layer->childCount(); 0105 QList<KisNodeSP> children = layer->childNodes(layerClassNames(), KoProperties()); 0106 for(quint32 i = 0; i < childCount; ++i) 0107 childCount += deepChildCount(children.at(i)); 0108 return childCount; 0109 } 0110 0111 void rebuildLayerList(KisNodeSP layer = 0) 0112 { 0113 bool refreshingFromRoot = false; 0114 if (!image) 0115 { 0116 layers.clear(); 0117 return; 0118 } 0119 if (layer == 0) 0120 { 0121 refreshingFromRoot = true; 0122 layers.clear(); 0123 layer = image->rootLayer(); 0124 } 0125 // implementation node: The root node is not a visible node, and so 0126 // is never added to the list of layers 0127 QList<KisNodeSP> children = layer->childNodes(layerClassNames(), KoProperties()); 0128 if (children.count() == 0) 0129 return; 0130 for(quint32 i = children.count(); i > 0; --i) 0131 { 0132 layers << children.at(i-1); 0133 rebuildLayerList(children.at(i-1)); 0134 } 0135 0136 if (refreshingFromRoot) 0137 refreshLayerMovementAbilities(); 0138 } 0139 0140 void refreshLayerMovementAbilities() 0141 { 0142 layerMeta.clear(); 0143 if (layers.count() == 0) 0144 return; 0145 for(int i = 0; i < layers.count(); ++i) 0146 { 0147 const KisNodeSP layer = layers.at(i); 0148 LayerModelMetaInfo ability; 0149 0150 if (i > 0) 0151 ability.canMoveUp = true; 0152 0153 if (i < layers.count() - 1) 0154 ability.canMoveDown = true; 0155 0156 KisNodeSP parent = layer; 0157 while(parent) 0158 { 0159 ++ability.depth; 0160 parent = parent->parent(); 0161 } 0162 0163 if (ability.depth > 1) 0164 ability.canMoveLeft = true; 0165 0166 if (i < layers.count() - 1 && qobject_cast<const KisGroupLayer*>(layers.at(i + 1).constData())) 0167 ability.canMoveRight = true; 0168 0169 layerMeta[layer] = ability; 0170 } 0171 } 0172 }; 0173 0174 LayerModel::LayerModel(QObject* parent) 0175 : QAbstractListModel(parent) 0176 , d(new Private(this)) 0177 { 0178 0179 connect(d->nodeModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), 0180 this, SLOT(source_rowsAboutToBeInserted(QModelIndex,int,int))); 0181 connect(d->nodeModel, SIGNAL(rowsInserted(QModelIndex,int,int)), 0182 this, SLOT(source_rowsInserted(QModelIndex,int,int))); 0183 0184 connect(d->nodeModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), 0185 this, SLOT(source_rowsAboutToBeRemoved(QModelIndex,int,int))); 0186 connect(d->nodeModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), 0187 this, SLOT(source_rowsRemoved(QModelIndex,int,int))); 0188 0189 connect(d->nodeModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0190 this, SLOT(source_dataChanged(QModelIndex,QModelIndex))); 0191 connect(d->nodeModel, SIGNAL(modelReset()), 0192 this, SLOT(source_modelReset())); 0193 0194 connect(d->nodeModel, SIGNAL(layoutAboutToBeChanged()), this, SIGNAL(layoutAboutToBeChanged())); 0195 connect(d->nodeModel, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged())); 0196 } 0197 0198 LayerModel::~LayerModel() 0199 { 0200 delete d; 0201 } 0202 0203 QHash<int, QByteArray> LayerModel::roleNames() const 0204 { 0205 QHash<int, QByteArray> roles; 0206 roles[IconRole] = "icon"; 0207 roles[NameRole] = "name"; 0208 roles[ActiveLayerRole] = "activeLayer"; 0209 roles[OpacityRole] = "opacity"; 0210 roles[PercentOpacityRole] = "percentOpacity"; 0211 roles[VisibleRole] = "visible"; 0212 roles[CompositeDetailsRole] = "compositeDetails"; 0213 roles[FilterRole] = "filter"; 0214 roles[ChildCountRole] = "childCount"; 0215 roles[DeepChildCountRole] = "deepChildCount"; 0216 roles[DepthRole] = "depth"; 0217 roles[PreviousItemDepthRole] = "previousItemDepth"; 0218 roles[NextItemDepthRole] = "nextItemDepth"; 0219 roles[CanMoveDownRole] = "canMoveDown"; 0220 roles[CanMoveLeftRole] = "canMoveLeft"; 0221 roles[CanMoveRightRole] = "canMoveRight"; 0222 roles[CanMoveUpRole] = "canMoveUp"; 0223 0224 return roles; 0225 } 0226 0227 QObject* LayerModel::view() const 0228 { 0229 return d->view; 0230 } 0231 0232 void LayerModel::setView(QObject *newView) 0233 { 0234 KisViewManager* view = qobject_cast<KisViewManager*>(newView); 0235 // This has to happen very early, and we will be filling it back up again soon anyway... 0236 if (d->canvas) { 0237 d->canvas->disconnectCanvasObserver(this); 0238 disconnect(d->image, 0, this, 0); 0239 disconnect(d->nodeManager, 0, this, 0); 0240 disconnect(d->nodeModel, 0, d->nodeManager, 0); 0241 disconnect(d->nodeModel, SIGNAL(nodeActivated(KisNodeSP)), this, SLOT(currentNodeChanged(KisNodeSP))); 0242 d->image = 0; 0243 d->nodeManager = 0; 0244 d->layers.clear(); 0245 d->activeNode.clear(); 0246 d->canvas = 0; 0247 d->nodeModel->setDummiesFacade(0, 0, 0, 0, 0); 0248 d->selectionActionsAdapter.reset(); 0249 0250 } 0251 0252 d->view = view; 0253 if (!d->view) { 0254 return; 0255 } 0256 0257 d->canvas = view->canvasBase(); 0258 d->thumbProvider = new LayerThumbProvider(); 0259 d->thumbProvider->setLayerModel(this); 0260 d->thumbProvider->setLayerID(Private::counter()); 0261 // QT5TODO: results in a crash 0262 d->declarativeEngine->addImageProvider(QString("layerthumb%1").arg(d->thumbProvider->layerID()), d->thumbProvider); 0263 0264 if (d->canvas) { 0265 d->image = d->canvas->imageView()->image(); 0266 d->nodeManager = d->canvas->viewManager()->nodeManager(); 0267 0268 KisDummiesFacadeBase *kritaDummiesFacade = dynamic_cast<KisDummiesFacadeBase*>(d->canvas->imageView()->document()->shapeController()); 0269 KisShapeController *shapeController = dynamic_cast<KisShapeController*>(d->canvas->imageView()->document()->shapeController()); 0270 0271 d->selectionActionsAdapter.reset(new KisSelectionActionsAdapter(d->canvas->viewManager()->selectionManager())); 0272 d->nodeModel->setDummiesFacade(kritaDummiesFacade, 0273 d->image, 0274 shapeController, 0275 d->selectionActionsAdapter.data(), 0276 d->nodeManager); 0277 0278 connect(d->image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted())); 0279 connect(d->image, SIGNAL(sigNodeChanged(KisNodeSP)), SLOT(nodeChanged(KisNodeSP))); 0280 connect(d->image, SIGNAL(sigImageUpdated(QRect)), SLOT(imageChanged())); 0281 connect(d->image, SIGNAL(sigRemoveNodeAsync(KisNodeSP)), SLOT(aboutToRemoveNode(KisNodeSP))); 0282 0283 // cold start 0284 currentNodeChanged(d->nodeManager->activeNode()); 0285 0286 // Connection KisNodeManager -> KisLayerBox 0287 connect(d->nodeManager, SIGNAL(sigUiNeedChangeActiveNode(KisNodeSP)), this, SLOT(currentNodeChanged(KisNodeSP))); 0288 0289 d->rebuildLayerList(); 0290 beginResetModel(); 0291 endResetModel(); 0292 } 0293 } 0294 0295 QObject* LayerModel::engine() const 0296 { 0297 return d->declarativeEngine; 0298 } 0299 0300 void LayerModel::setEngine(QObject* newEngine) 0301 { 0302 d->declarativeEngine = qobject_cast<QQmlEngine*>(newEngine); 0303 emit engineChanged(); 0304 } 0305 0306 QString LayerModel::fullImageThumbUrl() const 0307 { 0308 return QString("image://layerthumb%1/fullimage/%2").arg(d->thumbProvider->layerID()).arg(QDateTime::currentMSecsSinceEpoch()); 0309 } 0310 0311 void LayerModel::currentNodeChanged(KisNodeSP newActiveNode) 0312 { 0313 if (!d->activeNode.isNull()) { 0314 QModelIndex oldIndex = d->nodeModel->indexFromNode(d->activeNode); 0315 source_dataChanged(oldIndex, oldIndex); 0316 } 0317 d->activeNode = newActiveNode; 0318 emitActiveChanges(); 0319 if (!d->activeNode.isNull()) { 0320 QModelIndex oldIndex = d->nodeModel->indexFromNode(d->activeNode); 0321 source_dataChanged(oldIndex, oldIndex); 0322 } 0323 } 0324 0325 QVariant LayerModel::data(const QModelIndex& index, int role) const 0326 { 0327 QVariant data; 0328 if (index.isValid()) { 0329 KisNodeSP node = d->layers.at(index.row()); 0330 if (node.isNull()) 0331 return data; 0332 KisNodeSP parent; 0333 switch(role) 0334 { 0335 case IconRole: 0336 if (dynamic_cast<const KisGroupLayer*>(node.constData())) 0337 data = QLatin1String("../images/svg/icon-layer_group-black.svg"); 0338 else if (dynamic_cast<const KisFilterMask*>(node.constData())) 0339 data = QLatin1String("../images/svg/icon-layer_filter-black.svg"); 0340 else if (dynamic_cast<const KisAdjustmentLayer*>(node.constData())) 0341 data = QLatin1String("../images/svg/icon-layer_filter-black.svg"); 0342 else 0343 // We add the currentMSecsSinceEpoch to ensure we force an update (even with cache turned 0344 // off, we still apparently get some caching behaviour on delegates in QML) 0345 data = QString("image://layerthumb%1/%2/%3").arg(d->thumbProvider->layerID()).arg(index.row()).arg(QDateTime::currentMSecsSinceEpoch()); 0346 break; 0347 case NameRole: 0348 data = node->name(); 0349 break; 0350 case ActiveLayerRole: 0351 data = (node == d->activeNode); 0352 break; 0353 case OpacityRole: 0354 data = node->opacity(); 0355 break; 0356 case PercentOpacityRole: 0357 data = node->percentOpacity(); 0358 break; 0359 case VisibleRole: 0360 data = node->visible(); 0361 break; 0362 case CompositeDetailsRole: 0363 // composite op goes here... 0364 if (node->compositeOp()) 0365 data = node->compositeOp()->description(); 0366 break; 0367 case FilterRole: 0368 break; 0369 case ChildCountRole: 0370 data = node->childNodes(d->layerClassNames(), KoProperties()).count(); 0371 break; 0372 case DeepChildCountRole: 0373 data = d->deepChildCount(d->layers.at(index.row())); 0374 break; 0375 case DepthRole: 0376 data = d->layerMeta[node.data()].depth; 0377 break; 0378 case PreviousItemDepthRole: 0379 if (index.row() == 0) 0380 data = -1; 0381 else 0382 data = d->layerMeta[d->layers[index.row() - 1].data()].depth; 0383 break; 0384 case NextItemDepthRole: 0385 if (index.row() == d->layers.count() - 1) 0386 data = -1; 0387 else 0388 data = d->layerMeta[d->layers[index.row() + 1].data()].depth; 0389 break; 0390 case CanMoveDownRole: 0391 data = (node == d->activeNode) && d->layerMeta[node.data()].canMoveDown; 0392 break; 0393 case CanMoveLeftRole: 0394 data = (node == d->activeNode) && d->layerMeta[node.data()].canMoveLeft; 0395 break; 0396 case CanMoveRightRole: 0397 data = (node == d->activeNode) && d->layerMeta[node.data()].canMoveRight; 0398 break; 0399 case CanMoveUpRole: 0400 data = (node == d->activeNode) && d->layerMeta[node.data()].canMoveUp; 0401 break; 0402 default: 0403 break; 0404 } 0405 } 0406 return data; 0407 } 0408 0409 int LayerModel::rowCount(const QModelIndex& parent) const 0410 { 0411 if ( parent.isValid() ) { 0412 return 0; 0413 } 0414 return d->layers.count(); 0415 } 0416 0417 QVariant LayerModel::headerData(int section, Qt::Orientation orientation, int role) const 0418 { 0419 return QAbstractItemModel::headerData(section, orientation, role); 0420 } 0421 0422 void LayerModel::setActive(int index) 0423 { 0424 if (index > -1 && index < d->layers.count()) { 0425 KisNodeSP newNode = d->layers.at(index); 0426 d->nodeManager->slotUiActivatedNode(newNode); 0427 currentNodeChanged(newNode); 0428 } 0429 } 0430 0431 void LayerModel::moveUp() 0432 { 0433 KisNodeSP node = d->nodeManager->activeNode(); 0434 KisNodeSP parent = node->parent(); 0435 KisNodeSP grandParent = parent->parent(); 0436 0437 if (!d->nodeManager->activeNode()->nextSibling()) { 0438 //dbgKrita << "Active node apparently has no next sibling, however that has happened..."; 0439 if (!grandParent) 0440 return; 0441 //dbgKrita << "Node has grandparent"; 0442 if (!grandParent->parent() && node->inherits("KisMask")) 0443 return; 0444 //dbgKrita << "Node isn't a mask"; 0445 d->nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1); 0446 } 0447 else { 0448 //dbgKrita << "Move node directly"; 0449 d->nodeManager->lowerNode(); 0450 } 0451 } 0452 0453 void LayerModel::moveDown() 0454 { 0455 KisNodeSP node = d->nodeManager->activeNode(); 0456 KisNodeSP parent = node->parent(); 0457 KisNodeSP grandParent = parent->parent(); 0458 0459 if (!d->nodeManager->activeNode()->prevSibling()) { 0460 //dbgKrita << "Active node apparently has no previous sibling, however that has happened..."; 0461 if (!grandParent) 0462 return; 0463 //dbgKrita << "Node has grandparent"; 0464 if (!grandParent->parent() && node->inherits("KisMask")) 0465 return; 0466 //dbgKrita << "Node isn't a mask"; 0467 d->nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent)); 0468 } else 0469 { 0470 //dbgKrita << "Move node directly"; 0471 d->nodeManager->raiseNode(); 0472 } 0473 } 0474 0475 void LayerModel::moveLeft() 0476 { 0477 KisNodeSP node = d->nodeManager->activeNode(); 0478 KisNodeSP parent = node->parent(); 0479 KisNodeSP grandParent = parent->parent(); 0480 quint16 nodeIndex = parent->index(node); 0481 0482 if (!grandParent) 0483 return; 0484 if (!grandParent->parent() && node->inherits("KisMask")) 0485 return; 0486 0487 if (nodeIndex <= parent->childCount() / 2) { 0488 d->nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent)); 0489 } 0490 else { 0491 d->nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1); 0492 } 0493 } 0494 0495 void LayerModel::moveRight() 0496 { 0497 KisNodeSP node = d->nodeManager->activeNode(); 0498 KisNodeSP parent = d->nodeManager->activeNode()->parent(); 0499 KisNodeSP newParent; 0500 int nodeIndex = parent->index(node); 0501 int indexAbove = nodeIndex + 1; 0502 int indexBelow = nodeIndex - 1; 0503 0504 if (parent->at(indexBelow) && parent->at(indexBelow)->allowAsChild(node)) { 0505 newParent = parent->at(indexBelow); 0506 d->nodeManager->moveNodeAt(node, newParent, newParent->childCount()); 0507 } 0508 else if (parent->at(indexAbove) && parent->at(indexAbove)->allowAsChild(node)) { 0509 newParent = parent->at(indexAbove); 0510 d->nodeManager->moveNodeAt(node, newParent, 0); 0511 } 0512 else { 0513 return; 0514 } 0515 } 0516 0517 void LayerModel::clear() 0518 { 0519 d->canvas->viewManager()->selectionManager()->clear(); 0520 } 0521 0522 void LayerModel::clone() 0523 { 0524 d->nodeManager->duplicateActiveNode(); 0525 } 0526 0527 void LayerModel::setLocked(int index, bool newLocked) 0528 { 0529 if (index > -1 && index < d->layers.count()) { 0530 if(d->layers[index]->userLocked() == newLocked) 0531 return; 0532 d->layers[index]->setUserLocked(newLocked); 0533 QModelIndex idx = createIndex(index, 0); 0534 dataChanged(idx, idx); 0535 } 0536 } 0537 0538 void LayerModel::setOpacity(int index, float newOpacity) 0539 { 0540 if (index > -1 && index < d->layers.count()) { 0541 if(qFuzzyCompare(d->layers[index]->opacity() + 1, newOpacity + 1)) 0542 return; 0543 d->layers[index]->setOpacity(newOpacity); 0544 d->layers[index]->setDirty(); 0545 QModelIndex idx = createIndex(index, 0); 0546 dataChanged(idx, idx); 0547 } 0548 } 0549 0550 void LayerModel::setVisible(int index, bool newVisible) 0551 { 0552 if (index > -1 && index < d->layers.count()) { 0553 KisBaseNode::PropertyList props = d->layers[index]->sectionModelProperties(); 0554 if(props[0].state == newVisible) 0555 return; 0556 KisBaseNode::Property prop = props[0]; 0557 prop.state = newVisible; 0558 props[0] = prop; 0559 d->nodeModel->setData( d->nodeModel->indexFromNode(d->layers[index]), QVariant::fromValue<KisBaseNode::PropertyList>(props), KisNodeModel::PropertiesRole ); 0560 d->layers[index]->setDirty(d->layers[index]->extent()); 0561 QModelIndex idx = createIndex(index, 0); 0562 dataChanged(idx, idx); 0563 } 0564 } 0565 0566 QImage LayerModel::layerThumbnail(QString layerID) const 0567 { 0568 // So, yeah, this is a complete cheatery hack. However, it ensures 0569 // we actually get updates when we want them (every time the image is supposed 0570 // to be changed). Had hoped we could avoid it, but apparently not. 0571 int index = layerID.section(QChar('/'), 0, 0).toInt(); 0572 QImage thumb; 0573 if (index > -1 && index < d->layers.count()) { 0574 if (d->thumbProvider) 0575 thumb = d->layers[index]->createThumbnail(120, 120, Qt::KeepAspectRatio); 0576 } 0577 return thumb; 0578 } 0579 0580 void LayerModel::deleteCurrentLayer() 0581 { 0582 d->activeNode.clear(); 0583 d->nodeManager->removeNode(); 0584 } 0585 0586 void LayerModel::deleteLayer(int index) 0587 { 0588 if (index > -1 && index < d->layers.count()) { 0589 if (d->activeNode == d->layers.at(index)) 0590 d->activeNode.clear(); 0591 d->nodeManager->slotUiActivatedNode(d->layers.at(index)); 0592 d->nodeManager->removeNode(); 0593 d->rebuildLayerList(); 0594 beginResetModel(); 0595 endResetModel(); 0596 } 0597 } 0598 0599 void LayerModel::addLayer(int layerType) 0600 { 0601 switch(layerType) { 0602 case 0: 0603 d->nodeManager->createNode("KisPaintLayer"); 0604 break; 0605 case 1: 0606 d->nodeManager->createNode("KisGroupLayer"); 0607 break; 0608 case 2: 0609 d->nodeManager->createNode("KisFilterMask", true); 0610 break; 0611 default: 0612 break; 0613 } 0614 } 0615 0616 void LayerModel::source_rowsAboutToBeInserted(QModelIndex /*p*/, int /*from*/, int /*to*/) 0617 { 0618 beginResetModel(); 0619 } 0620 0621 void LayerModel::source_rowsInserted(QModelIndex /*p*/, int, int) 0622 { 0623 d->rebuildLayerList(); 0624 emit countChanged(); 0625 endResetModel(); 0626 } 0627 0628 void LayerModel::source_rowsAboutToBeRemoved(QModelIndex /*p*/, int /*from*/, int /*to*/) 0629 { 0630 beginResetModel(); 0631 } 0632 0633 void LayerModel::source_rowsRemoved(QModelIndex, int, int) 0634 { 0635 d->rebuildLayerList(); 0636 emit countChanged(); 0637 endResetModel(); 0638 } 0639 0640 void LayerModel::source_dataChanged(QModelIndex /*tl*/, QModelIndex /*br*/) 0641 { 0642 QModelIndex top = createIndex(0, 0); 0643 QModelIndex bottom = createIndex(d->layers.count() - 1, 0); 0644 dataChanged(top, bottom); 0645 } 0646 0647 void LayerModel::source_modelReset() 0648 { 0649 beginResetModel(); 0650 d->rebuildLayerList(); 0651 d->activeNode.clear(); 0652 if (d->layers.count() > 0) 0653 { 0654 d->nodeManager->slotUiActivatedNode(d->layers.at(0)); 0655 currentNodeChanged(d->layers.at(0)); 0656 } 0657 emit countChanged(); 0658 endResetModel(); 0659 } 0660 0661 void LayerModel::notifyImageDeleted() 0662 { 0663 } 0664 0665 void LayerModel::nodeChanged(KisNodeSP node) 0666 { 0667 QModelIndex index = createIndex(d->layers.indexOf(node), 0); 0668 dataChanged(index, index); 0669 } 0670 0671 void LayerModel::imageChanged() 0672 { 0673 d->imageChangedTimer->start(); 0674 } 0675 0676 void LayerModel::imageHasChanged() 0677 { 0678 QModelIndex top = createIndex(0, 0); 0679 QModelIndex bottom = createIndex(d->layers.count() - 1, 0); 0680 dataChanged(top, bottom); 0681 } 0682 0683 void LayerModel::aboutToRemoveNode(KisNodeSP node) 0684 { 0685 Q_UNUSED(node); 0686 QTimer::singleShot(0, this, SLOT(source_modelReset())); 0687 } 0688 0689 void LayerModel::emitActiveChanges() 0690 { 0691 emit activeFilterConfigChanged(); 0692 emit activeNameChanged(); 0693 emit activeTypeChanged(); 0694 emit activeCompositeOpChanged(); 0695 emit activeOpacityChanged(); 0696 emit activeVisibleChanged(); 0697 emit activeLockedChanged(); 0698 emit activeRChannelActiveChanged(); 0699 emit activeGChannelActiveChanged(); 0700 emit activeBChannelActiveChanged(); 0701 emit activeAChannelActiveChanged(); 0702 } 0703 0704 QString LayerModel::activeName() const 0705 { 0706 if (d->activeNode.isNull()) 0707 return QString(); 0708 return d->activeNode->name(); 0709 } 0710 0711 void LayerModel::setActiveName(QString newName) 0712 { 0713 if (d->activeNode.isNull()) 0714 return; 0715 d->activeNode->setName(newName); 0716 emit activeNameChanged(); 0717 } 0718 0719 QString LayerModel::activeType() const 0720 { 0721 return d->activeNode->metaObject()->className(); 0722 } 0723 0724 int LayerModel::activeCompositeOp() const 0725 { 0726 if (d->activeNode.isNull()) 0727 return 0; 0728 KoID entry(d->activeNode->compositeOp()->id()); 0729 QModelIndex idx = KisCompositeOpListModel::sharedInstance()->indexOf(entry); 0730 if (idx.isValid()) 0731 return idx.row(); 0732 return 0; 0733 } 0734 0735 void LayerModel::setActiveCompositeOp(int newOp) 0736 { 0737 if (d->activeNode.isNull()) 0738 return; 0739 KoID entry; 0740 if (KisCompositeOpListModel::sharedInstance()->entryAt(entry, KisCompositeOpListModel::sharedInstance()->index(newOp))) 0741 { 0742 d->activeNode->setCompositeOpId(entry.id()); 0743 d->activeNode->setDirty(); 0744 emit activeCompositeOpChanged(); 0745 } 0746 } 0747 0748 int LayerModel::activeOpacity() const 0749 { 0750 if (d->activeNode.isNull()) 0751 return 0; 0752 return d->activeNode->opacity(); 0753 } 0754 0755 void LayerModel::setActiveOpacity(int newOpacity) 0756 { 0757 d->activeNode->setOpacity(newOpacity); 0758 d->activeNode->setDirty(); 0759 emit activeOpacityChanged(); 0760 } 0761 0762 bool LayerModel::activeVisible() const 0763 { if (d->activeNode.isNull()) 0764 return false; 0765 return d->activeNode->visible(); 0766 } 0767 0768 void LayerModel::setActiveVisible(bool newVisible) 0769 { 0770 if (d->activeNode.isNull()) 0771 return; 0772 setVisible(d->layers.indexOf(d->activeNode), newVisible); 0773 emit activeVisibleChanged(); 0774 } 0775 0776 bool LayerModel::activeLocked() const 0777 { 0778 if (d->activeNode.isNull()) 0779 return false; 0780 return d->activeNode->userLocked(); 0781 } 0782 0783 void LayerModel::setActiveLocked(bool newLocked) 0784 { 0785 if (d->activeNode.isNull()) 0786 return; 0787 d->activeNode->setUserLocked(newLocked); 0788 emit activeLockedChanged(); 0789 } 0790 0791 bool LayerModel::activeAChannelActive() const 0792 { 0793 KisLayer* layer = qobject_cast<KisLayer*>(d->activeNode.data()); 0794 bool state = false; 0795 if (layer) 0796 state = !layer->alphaChannelDisabled(); 0797 return state; 0798 } 0799 0800 void LayerModel::setActiveAChannelActive(bool newActive) 0801 { 0802 KisLayer* layer = qobject_cast<KisLayer*>(d->activeNode.data()); 0803 if (layer) 0804 { 0805 layer->disableAlphaChannel(!newActive); 0806 layer->setDirty(); 0807 emit activeAChannelActiveChanged(); 0808 } 0809 } 0810 0811 0812 bool getActiveChannel(KisNodeSP node, int channelIndex) 0813 { 0814 KisLayer* layer = qobject_cast<KisLayer*>(node.data()); 0815 bool flag = false; 0816 if (layer) 0817 { 0818 QBitArray flags = layer->channelFlags(); 0819 if (channelIndex < flags.size()) { 0820 flag = flags[channelIndex]; 0821 } 0822 } 0823 return flag; 0824 } 0825 0826 void setChannelActive(KisNodeSP node, int channelIndex, bool newActive) 0827 { 0828 KisLayer* layer = qobject_cast<KisLayer*>(node.data()); 0829 if (layer) { 0830 QBitArray flags = layer->channelFlags(); 0831 flags.setBit(channelIndex, newActive); 0832 layer->setChannelFlags(flags); 0833 layer->setDirty(); 0834 } 0835 } 0836 0837 bool LayerModel::activeBChannelActive() const 0838 { 0839 return getActiveChannel(d->activeNode, 2); 0840 } 0841 0842 void LayerModel::setActiveBChannelActive(bool newActive) 0843 { 0844 setChannelActive(d->activeNode, 2, newActive); 0845 emit activeBChannelActiveChanged(); 0846 } 0847 0848 bool LayerModel::activeGChannelActive() const 0849 { 0850 return getActiveChannel(d->activeNode, 1); 0851 } 0852 0853 void LayerModel::setActiveGChannelActive(bool newActive) 0854 { 0855 setChannelActive(d->activeNode, 1, newActive); 0856 emit activeGChannelActiveChanged(); 0857 } 0858 0859 bool LayerModel::activeRChannelActive() const 0860 { 0861 return getActiveChannel(d->activeNode, 0); 0862 } 0863 0864 void LayerModel::setActiveRChannelActive(bool newActive) 0865 { 0866 setChannelActive(d->activeNode, 0, newActive); 0867 emit activeRChannelActiveChanged(); 0868 } 0869 0870 QObject* LayerModel::activeFilterConfig() const 0871 { 0872 QMap<QString, QVariant> props; 0873 QString filterId; 0874 KisFilterMask* filterMask = qobject_cast<KisFilterMask*>(d->activeNode.data()); 0875 if (filterMask) { 0876 props = filterMask->filter()->getProperties(); 0877 filterId = filterMask->filter()->name(); 0878 } 0879 else { 0880 KisAdjustmentLayer* adjustmentLayer = qobject_cast<KisAdjustmentLayer*>(d->activeNode.data()); 0881 if (adjustmentLayer) 0882 { 0883 props = adjustmentLayer->filter()->getProperties(); 0884 filterId = adjustmentLayer->filter()->name(); 0885 } 0886 } 0887 PropertyContainer* config = new PropertyContainer(filterId, 0); 0888 QMap<QString, QVariant>::const_iterator i; 0889 for(i = props.constBegin(); i != props.constEnd(); ++i) { 0890 config->setProperty(i.key().toLatin1(), i.value()); 0891 //dbgKrita << "Getting active config..." << i.key() << i.value(); 0892 } 0893 return config; 0894 } 0895 0896 void LayerModel::setActiveFilterConfig(QObject* newConfig) 0897 { 0898 if (d->activeNode.isNull()) 0899 return; 0900 PropertyContainer* config = qobject_cast<PropertyContainer*>(newConfig); 0901 if (!config) 0902 return; 0903 0904 //dbgKrita << "Attempting to set new config" << config->name(); 0905 KisFilterConfigurationSP realConfig = d->filters.value(config->name())->factoryConfiguration(KisGlobalResourcesInterface::instance()); 0906 QMap<QString, QVariant>::const_iterator i; 0907 for(i = realConfig->getProperties().constBegin(); i != realConfig->getProperties().constEnd(); ++i) 0908 { 0909 realConfig->setProperty(i.key(), config->property(i.key().toLatin1())); 0910 //dbgKrita << "Creating config..." << i.key() << i.value(); 0911 } 0912 // The following code causes sporadic crashes, and disabling causes leaks. So, leaks it must be, for now. 0913 // The cause is the lack of a smart pointer interface for passing filter configs around 0914 // Must be remedied, but for now... 0915 // if (d->newConfig) 0916 // delete(d->newConfig); 0917 d->newConfig = realConfig; 0918 //d->updateActiveLayerWithNewFilterConfigTimer->start(); 0919 updateActiveLayerWithNewFilterConfig(); 0920 } 0921 0922 void LayerModel::updateActiveLayerWithNewFilterConfig() 0923 { 0924 if (!d->newConfig) 0925 return; 0926 //dbgKrita << "Setting new config..." << d->newConfig->name(); 0927 KisFilterMask* filterMask = qobject_cast<KisFilterMask*>(d->activeNode.data()); 0928 if (filterMask) 0929 { 0930 //dbgKrita << "Setting filter mask"; 0931 filterMask->setFilter(d->newConfig->cloneWithResourcesSnapshot()); 0932 } 0933 else 0934 { 0935 KisAdjustmentLayer* adjustmentLayer = qobject_cast<KisAdjustmentLayer*>(d->activeNode.data()); 0936 if (adjustmentLayer) 0937 { 0938 //dbgKrita << "Setting filter on adjustment layer"; 0939 adjustmentLayer->setFilter(d->newConfig->cloneWithResourcesSnapshot()); 0940 } 0941 else 0942 { 0943 //dbgKrita << "UNKNOWN, BAIL OUT!"; 0944 } 0945 } 0946 d->newConfig = 0; 0947 d->activeNode->setDirty(d->activeNode->extent()); 0948 d->image->setModifiedWithoutUndo(); 0949 QTimer::singleShot(100, this, SIGNAL(activeFilterConfigChanged())); 0950 } 0951