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