void NavigatorTreeModel::propagateInvisible(const ModelNode &node, const bool &invisible)
{
    QList <ModelNode> children = node.allDirectSubModelNodes();
    foreach (ModelNode child, children) {
        child.setAuxiliaryData("childOfInvisible",invisible);
        if (!child.auxiliaryData("invisible").toBool())
            propagateInvisible(child,invisible);
    }
void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
{
    if (m_blockItemChangedSignal)
        return;

    uint nodeHash = item->data(Qt::UserRole).toUInt();
    Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
    ModelNode node = nodeForHash(nodeHash);

    ItemRow itemRow = itemRowForNode(node);
    if (item == itemRow.idItem) {
        try {
            node.setId(item->text());
        } catch (InvalidIdException &e) {
            QMessageBox::warning(0, tr("Invalid Id"), e.description());
            item->setText(node.id());
        }
    } else if (item == itemRow.visibilityItem) {
        bool invisible = (item->checkState() == Qt::Unchecked);

        node.setAuxiliaryData("invisible", invisible);
        propagateInvisible(node,isNodeInvisible(node));
    }
}
bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
                  Qt::DropAction action,
                  int row,
                  int column,
                  const QModelIndex &dropIndex)
{
    if (action == Qt::IgnoreAction)
        return true;
    if (action != Qt::LinkAction)
        return false;
    if (!data->hasFormat("application/vnd.modelnode.list"))
        return false;
    if (column > 1)
        return false;
    if (dropIndex.model() != this)
        return false;

    QModelIndex parentIndex, parentItemIndex;
    PropertyName parentPropertyName;
    int targetIndex;

    parentIndex = dropIndex.sibling(dropIndex.row(), 0);
    targetIndex = (row > -1)? row : rowCount(parentIndex);

    if (this->data(parentIndex, NavigatorRole).isValid()) {
        parentItemIndex = parentIndex;
        ModelNode parentNode = nodeForIndex(parentItemIndex);
        if (!parentNode.metaInfo().hasDefaultProperty())
            return false;
        targetIndex -= visibleProperties(parentNode).count();
        parentPropertyName = parentNode.metaInfo().defaultPropertyName();
    } else {
        parentItemIndex = parentIndex.parent();
        parentPropertyName = parentIndex.data(Qt::DisplayRole).toByteArray();
    }

    // Disallow dropping items between properties, which are listed first.
    if (targetIndex < 0)
        return false;

    Q_ASSERT(parentItemIndex.isValid());

    QByteArray encodedData = data->data("application/vnd.modelnode.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    QList<ModelNode> nodeList;
    while (!stream.atEnd()) {
        uint nodeHash;
        stream >> nodeHash;
        if (containsNodeHash(nodeHash)) {
            ModelNode node(nodeForHash(nodeHash));
            nodeList.append(node);
        }
    }

    ModelNode parentNode(nodeForIndex(parentItemIndex));
    NodeAbstractProperty parentProperty = parentNode.nodeAbstractProperty(parentPropertyName);

    if (parentProperty.isNodeProperty() &&
        nodeList.count() > 1) {
        return false;
    }

    moveNodesInteractive(parentProperty, nodeList, targetIndex);
    propagateInvisible(parentNode, isNodeInvisible(parentNode));

    return false; // don't let the view do drag&drop on its own
}
bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
                  Qt::DropAction action,
                  int row,
                  int column,
                  const QModelIndex &parentIndex)
{
    if (action == Qt::IgnoreAction)
        return true;
    if (action != Qt::LinkAction)
        return false;
    if (!data->hasFormat("application/vnd.modelnode.list"))
        return false;
    if (column > 1)
        return false;
    if (parentIndex.model() != this)
        return false;


    QModelIndex parentIdIndex = parentIndex;
    parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);

    Q_ASSERT(parentIdIndex.isValid());

    int targetIndex = 0;
    if (row > -1) {
        targetIndex = row;
    } else {
        targetIndex = rowCount(parentIdIndex);
    }

    QByteArray encodedData = data->data("application/vnd.modelnode.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    ModelNode parentNode(nodeForIndex(parentIdIndex));

    QList<ModelNode> nodeList;

    while (!stream.atEnd()) {
        uint nodeHash;
        stream >> nodeHash;
        ModelNode node(nodeForHash(nodeHash));
        if (!node.isValid() || (parentNode == node) || node.isAncestorOf(parentNode))
            continue;
        nodeList.append(node);
    }

    RewriterTransaction transaction = m_view->beginRewriterTransaction();
    foreach (const ModelNode &node, nodeList) {
        if (!isAnchestorInList(node, nodeList)) {
            if (node.parentProperty().parentModelNode() != parentNode) {
                if (node != parentNode) {
                    reparentModelNode(parentNode, node);
                }
            }

            if (node.parentProperty().isNodeListProperty()) {
                int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
                if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
                    --targetIndex;
                }
                if (index != targetIndex) {
                    node.parentProperty().toNodeListProperty().slide(index, targetIndex);
                }
            }
        }
    }

    propagateInvisible(parentNode, isNodeInvisible(parentNode));

    return false; // don't let the view do drag&drop on its own
}