diff --git a/plugins/dockers/layerdocker/NodeDelegate.cpp b/plugins/dockers/layerdocker/NodeDelegate.cpp --- a/plugins/dockers/layerdocker/NodeDelegate.cpp +++ b/plugins/dockers/layerdocker/NodeDelegate.cpp @@ -65,7 +65,16 @@ OptionalProperty findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const; OptionalProperty findVisibilityProperty(KisBaseNode::PropertyList &props) const; - void toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty prop, bool controlPressed, const QModelIndex &index); + void toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty prop, const Qt::KeyboardModifiers modifier, const QModelIndex &index); + void togglePropertyRecursive(const QModelIndex &root, const OptionalProperty &clickedProperty, const QList &items, bool record, bool mode); + + bool stasisIsDirty(const QModelIndex &root, const OptionalProperty &clickedProperty, bool on = false, bool off = false); + void resetPropertyStateRecursive(const QModelIndex &root, const OptionalProperty &clickedProperty); + + void getParentsIndex(QList &items, const QModelIndex &index); + void getChildrenIndex(QList &items, const QModelIndex &index); + void getSiblingsIndex(QList &items, const QModelIndex &index); + }; NodeDelegate::NodeDelegate(NodeView *view, QObject *parent) @@ -480,6 +489,151 @@ return 0; } +void NodeDelegate::Private::toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty clickedProperty, const Qt::KeyboardModifiers modifier, const QModelIndex &index) +{ + QModelIndex root(view->rootIndex()); + + if ((modifier & Qt::ShiftModifier) == Qt::ShiftModifier && clickedProperty->canHaveStasis) { + if(stasisIsDirty(root, clickedProperty)){ // clean inStasis if mixed! + resetPropertyStateRecursive(root, clickedProperty); + } + KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value(); + OptionalProperty prop = findProperty(props, clickedProperty); + + bool mode = true; + bool record = prop->isInStasis; + QList items; + + if(modifier == (Qt::ControlModifier | Qt::ShiftModifier)) { + mode = false; // inverted mode + items.insert(0, index); // important! + getSiblingsIndex(items, index); + } else { + getParentsIndex(items, index); + getChildrenIndex(items, index); + } + togglePropertyRecursive(root, clickedProperty, items, record, mode); + + } else { + resetPropertyStateRecursive(root, clickedProperty); + clickedProperty->state = !clickedProperty->state.toBool(); + view->model()->setData(index, QVariant::fromValue(props), KisNodeModel::PropertiesRole); + } +} + +void NodeDelegate::Private::togglePropertyRecursive(const QModelIndex &root, const OptionalProperty &clickedProperty, const QList &items, bool record, bool mode) +{ + int rowCount = view->model()->rowCount(root); + + for (int i = 0; i < rowCount; i++) { + QModelIndex idx = view->model()->index(i, 0, root); + + // The entire property list has to be altered because model->setData cannot set individual properties + KisBaseNode::PropertyList props = idx.data(KisNodeModel::PropertiesRole).value(); + OptionalProperty prop = findProperty(props, clickedProperty); + + if (!prop) continue; + if (record){ // record + prop->stateInStasis = prop->state.toBool(); + prop->isInStasis = false; + if(mode) { //include mode + prop->state = (items.contains(idx))? QVariant(true) : QVariant(false); + } else { // exclude + prop->state = (!items.contains(idx))? prop->state : + (items.at(0) == idx)? QVariant(true) : QVariant(false); + } + } else { // recover + prop->state = QVariant(prop->stateInStasis); + prop->isInStasis = true; + } + view->model()->setData(idx, QVariant::fromValue(props), KisNodeModel::PropertiesRole); + + togglePropertyRecursive(idx,clickedProperty, items, record, mode); + } +} + +bool NodeDelegate::Private::stasisIsDirty(const QModelIndex &root, const OptionalProperty &clickedProperty, bool on, bool off) +{ + + int rowCount = view->model()->rowCount(root); + bool result = false; + + for (int i = 0; i < rowCount; i++) { + if (result) break; // return on first find + QModelIndex idx = view->model()->index(i, 0, root); + // The entire property list has to be altered because model->setData cannot set individual properties + KisBaseNode::PropertyList props = idx.data(KisNodeModel::PropertiesRole).value(); + OptionalProperty prop = findProperty(props, clickedProperty); + + if (!prop) continue; + if(prop->isInStasis) { + on = true; + } else { + off = true; + } + // stop if both states exist + if (on && off) { + return true; + } + + result = stasisIsDirty(idx,clickedProperty, on, off); + } + return result; +} + +void NodeDelegate::Private::resetPropertyStateRecursive(const QModelIndex &root, const OptionalProperty &clickedProperty) +{ + if (!clickedProperty->canHaveStasis) return; + int rowCount = view->model()->rowCount(root); + + for (int i = 0; i < rowCount; i++) { + QModelIndex idx = view->model()->index(i, 0, root); + // The entire property list has to be altered because model->setData cannot set individual properties + KisBaseNode::PropertyList props = idx.data(KisNodeModel::PropertiesRole).value(); + OptionalProperty prop = findProperty(props, clickedProperty); + + if (!prop) continue; + prop->stateInStasis = prop->state.toBool(); + prop->isInStasis = true; + view->model()->setData(idx, QVariant::fromValue(props), KisNodeModel::PropertiesRole); + + resetPropertyStateRecursive(idx,clickedProperty); + } +} + +void NodeDelegate::Private::getParentsIndex(QList &items, const QModelIndex &index) +{ + if(!index.isValid()) return; + items.append(index); + getParentsIndex(items, index.parent()); +} + +void NodeDelegate::Private::getChildrenIndex(QList &items, const QModelIndex &index) +{ + qint32 childs = view->model()->rowCount(index); + QModelIndex child; + // STEP 1: Go. + for (quint16 i = 0; i < childs; ++i) { + child = view->model()->index(i, 0, index); + items.append(child); + getChildrenIndex(items, child); + } +} + +void NodeDelegate::Private::getSiblingsIndex(QList &items, const QModelIndex &index) +{ + qint32 numberOfLeaves = view->model()->rowCount(index.parent()); + QModelIndex item; + // STEP 1: Go. + for (quint16 i = 0; i < numberOfLeaves; ++i) { + item = view->model()->index(i, 0, index.parent()); + if (item != index) { + items.append(item); + } + } +} + + void NodeDelegate::drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const { KisNodeViewColorScheme scm; @@ -660,58 +814,6 @@ p->drawPixmap(rc.bottomLeft()-QPoint(0, scm.decorationSize()-1), pixmap); } -void NodeDelegate::Private::toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty clickedProperty, bool controlPressed, const QModelIndex &index) -{ - QAbstractItemModel *model = view->model(); - - // Using Ctrl+click to enter stasis - if (controlPressed && clickedProperty->canHaveStasis) { - // STEP 0: Prepare to Enter or Leave control key stasis - quint16 numberOfLeaves = model->rowCount(index.parent()); - QModelIndex eachItem; - // STEP 1: Go. - if (clickedProperty->isInStasis == false) { // Enter - /* Make every leaf of this node go State = False, saving the old property value to stateInStasis */ - for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent()) - eachItem = model->index(i, 1, index.parent()); - // The entire property list has to be altered because model->setData cannot set individual properties - KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value(); - OptionalProperty prop = findProperty(eachPropertyList, clickedProperty); - if (!prop) continue; - prop->stateInStasis = prop->state.toBool(); - prop->state = eachItem == index; - prop->isInStasis = true; - model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole); - - } - - for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent()) - eachItem = model->index(i, 1, index.parent()); - KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value(); - OptionalProperty prop = findProperty(eachPropertyList, clickedProperty); - if (!prop) continue; - } - } else { // Leave - /* Make every leaf of this node go State = stateInStasis */ - for (quint16 i = 0; i < numberOfLeaves; ++i) { - eachItem = model->index(i, 1, index.parent()); - // The entire property list has to be altered because model->setData cannot set individual properties - KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value(); - OptionalProperty prop = findProperty(eachPropertyList, clickedProperty); - if (!prop) continue; - - prop->state = prop->stateInStasis; - prop->isInStasis = false; - model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole); - } - } - } else { - clickedProperty->state = !clickedProperty->state.toBool(); - model->setData(index, QVariant::fromValue(props), KisNodeModel::PropertiesRole); - } -} - - bool NodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { KisNodeViewColorScheme scm; @@ -773,14 +875,16 @@ OptionalProperty clickedProperty = realProps[clickedIcon]; if (!clickedProperty) return false; - d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index); + d->toggleProperty(props, clickedProperty, mouseEvent->modifiers(), index); return true; } } else if (leftButton && visibilityClicked) { KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value(); OptionalProperty clickedProperty = d->findVisibilityProperty(props); if (!clickedProperty) return false; - d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index); + + d->toggleProperty(props, clickedProperty, mouseEvent->modifiers(), index); + return true; } else if (leftButton && decorationClicked) { bool isExpandable = model->hasChildren(index);