From c78bb13f7b9d6704938ac761bf76f0279f8f3d9a Mon Sep 17 00:00:00 2001
From: David Li <dawei.li@gmx.net>
Date: Mon, 21 Mar 2016 14:27:19 +0100
Subject: [PATCH] fix distributed particle

---
 GUI/coregui/Models/GroupProperty.cpp          |  5 ++
 GUI/coregui/Models/GroupProperty.h            |  2 +
 GUI/coregui/Models/ModelMapper.cpp            | 73 ++++++++++++++-----
 GUI/coregui/Models/ModelMapper.h              |  7 ++
 GUI/coregui/Models/ModelPath.cpp              | 46 ++++++++----
 .../Models/ParticleDistributionItem.cpp       | 15 ++--
 6 files changed, 106 insertions(+), 42 deletions(-)

diff --git a/GUI/coregui/Models/GroupProperty.cpp b/GUI/coregui/Models/GroupProperty.cpp
index af65a88b89e..4ee9ca673a2 100644
--- a/GUI/coregui/Models/GroupProperty.cpp
+++ b/GUI/coregui/Models/GroupProperty.cpp
@@ -149,6 +149,11 @@ QString GroupProperty::toString(int index) const
     return name_list[index];
 }
 
+bool GroupProperty::isFixed() const
+{
+    return m_group_type == GroupProperty::FIXED;
+}
+
 void GroupProperty::setGroupMap(std::map<QString, QString> group_map)
 {
     m_type_label_map = std::move(group_map);
diff --git a/GUI/coregui/Models/GroupProperty.h b/GUI/coregui/Models/GroupProperty.h
index 7d9245cb7cc..5a09a01873f 100644
--- a/GUI/coregui/Models/GroupProperty.h
+++ b/GUI/coregui/Models/GroupProperty.h
@@ -57,6 +57,8 @@ public:
     int toIndex(const QString &type) const;
     QString toString(int index) const;
 
+    bool isFixed() const;
+
     friend class GroupPropertyRegistry;
 private:
     GroupProperty(QString group_name);
diff --git a/GUI/coregui/Models/ModelMapper.cpp b/GUI/coregui/Models/ModelMapper.cpp
index d35f291be5a..8a11e5d8517 100644
--- a/GUI/coregui/Models/ModelMapper.cpp
+++ b/GUI/coregui/Models/ModelMapper.cpp
@@ -65,6 +65,11 @@ void ModelMapper::setOnSiblingsChange(std::function<void ()> f)
     m_onSiblingsChange.push_back(f);
 }
 
+void ModelMapper::setOnAnyChildChange(std::function<void (SessionItem *)> f)
+{
+    m_onAnyChildChange.push_back(f);
+}
+
 void ModelMapper::setModel(SessionModel *model)
 {
     if (m_model) {
@@ -74,6 +79,8 @@ void ModelMapper::setModel(SessionModel *model)
                    this, SLOT(onRowsInserted(QModelIndex,int,int)));
         disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
                 this, SLOT(onBeginRemoveRows(QModelIndex,int,int)));
+        disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                this, SLOT(onRowRemoved(QModelIndex,int,int)));
     }
     if (model) {
         m_model = model;
@@ -83,6 +90,8 @@ void ModelMapper::setModel(SessionModel *model)
                    this, SLOT(onRowsInserted(QModelIndex,int,int)));
         connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
                 this, SLOT(onBeginRemoveRows(QModelIndex,int,int)));
+        connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                this, SLOT(onRowRemoved(QModelIndex,int,int)));
     }
 }
 
@@ -150,6 +159,15 @@ void ModelMapper::callOnSiblingsChange()
     }
 }
 
+void ModelMapper::callOnAnyChildChange(SessionItem *item)
+{
+    if (m_active && m_onAnyChildChange.size() > 0) {
+        for (auto f : m_onAnyChildChange) {
+            f(item);
+        }
+    }
+}
+
 void ModelMapper::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
                                 const QVector<int> &/*roles*/)
 {
@@ -180,20 +198,25 @@ void ModelMapper::onDataChanged(const QModelIndex &topLeft, const QModelIndex &b
             }
         }
     }
+    if (nestling > 0) {
+        callOnAnyChildChange(item);
+    }
 }
 
-void ModelMapper::onRowsInserted(const QModelIndex &parent, int first, int last)
+void ModelMapper::onRowsInserted(const QModelIndex &parent, int first, int /*last*/)
 {
-    if(!parent.isValid()) return;
+    SessionItem *newChild = m_model->itemForIndex(parent.child(first, 0));
 
-    if (SessionItem *newChild = m_model->itemForIndex(parent.child(first, 0))) {
+    int nestling = nestlingDepth(newChild);
+
+    if (newChild) {
         if (m_item == newChild) {
             callOnParentChange(m_model->itemForIndex(parent));
         }
+    }
+    if (nestling == 1) {
 
-        else if(m_item == newChild->parent()) {
-            callOnChildrenChange();
-        }
+        callOnChildrenChange();
 
         // inform siblings about the change
         // FIXME SessionItems with invalid parent index (i.e. IView's located on top of graphics scene like ParticleView) should be also notified to update the label
@@ -204,34 +227,46 @@ void ModelMapper::onRowsInserted(const QModelIndex &parent, int first, int last)
                 if(m_item == sibling) callOnSiblingsChange();
             }
         }
+    }
 
+    if (nestling > 0) {
+        callOnAnyChildChange(newChild);
     }
 
 }
 
-void ModelMapper::onBeginRemoveRows(const QModelIndex &parent, int first, int last)
+void ModelMapper::onBeginRemoveRows(const QModelIndex &parent, int first, int /*last*/)
 {
-    if(!parent.isValid()) return;
+    SessionItem *oldChild = m_model->itemForIndex(parent.child(first, 0));
 
-    if (SessionItem *newChild = m_model->itemForIndex(parent.child(first, 0))) {
-        if (m_item == newChild) {
-            callOnParentChange(nullptr);
+    int nestling = nestlingDepth(m_model->itemForIndex(parent));
+
+    if (oldChild) {
+        if (m_item == oldChild) {
+            callOnParentChange(m_model->itemForIndex(parent));
         }
+        if (nestling == 0) {
 
-        else if(m_item == newChild->parent()) {
             callOnChildrenChange();
-        }
 
-        // inform siblings about the change
-        if(SessionItem *parent = newChild->parent()) {
-//            QVector<SessionItem *> items = parent->getItems(parent->tagFromItem(newChild));
-            QVector<SessionItem *> items = parent->getChildrenOfType(newChild->modelType());
-            foreach(SessionItem *sibling, items) {
-                if(m_item == sibling) callOnSiblingsChange();
+            // inform siblings about the change
+            if(SessionItem *parent = oldChild->parent()) {
+    //            QVector<SessionItem *> items = parent->getItems(parent->tagFromItem(newChild));
+                QVector<SessionItem *> items = parent->getChildrenOfType(oldChild->modelType());
+                foreach(SessionItem *sibling, items) {
+                    if(m_item == sibling) callOnSiblingsChange();
+                }
             }
         }
+    }
 
+}
 
+void ModelMapper::onRowRemoved(const QModelIndex &parent, int /*first*/, int /*last*/)
+{
+    int nestling = nestlingDepth(m_model->itemForIndex(parent));
 
+    if (nestling >= 0 || m_model->itemForIndex(parent) == m_item->parent()) {
+        callOnAnyChildChange(nullptr);
     }
 }
diff --git a/GUI/coregui/Models/ModelMapper.h b/GUI/coregui/Models/ModelMapper.h
index 76fffb2f7d6..3612fe7da6a 100644
--- a/GUI/coregui/Models/ModelMapper.h
+++ b/GUI/coregui/Models/ModelMapper.h
@@ -47,6 +47,8 @@ public:
 
     void setOnSiblingsChange(std::function<void(void)> f);
 
+    void setOnAnyChildChange(std::function<void(SessionItem*)> f);
+
     void setActive(bool state) {m_active = state;}
 
 public slots:
@@ -57,6 +59,8 @@ public slots:
 
     void onBeginRemoveRows(const QModelIndex & parent, int first, int last);
 
+    void onRowRemoved(const QModelIndex & parent, int first, int last);
+
 private:
     void setModel(SessionModel *model);
     int nestlingDepth(SessionItem* item, int level = 0);
@@ -67,6 +71,8 @@ private:
     void callOnParentChange(SessionItem *new_parent);
     void callOnChildrenChange();
     void callOnSiblingsChange();
+    void callOnAnyChildChange(SessionItem *item);
+
 
     bool m_active;
     SessionModel *m_model;
@@ -77,6 +83,7 @@ private:
     std::vector<std::function<void(SessionItem*)>> m_onParentChange;
     std::vector<std::function<void(void)>> m_onChildrenChange;
     std::vector<std::function<void(void)>> m_onSiblingsChange;
+    std::vector<std::function<void(SessionItem*)>> m_onAnyChildChange;
 };
 
 #endif
diff --git a/GUI/coregui/Models/ModelPath.cpp b/GUI/coregui/Models/ModelPath.cpp
index 70cf5363818..1b966d0fca0 100644
--- a/GUI/coregui/Models/ModelPath.cpp
+++ b/GUI/coregui/Models/ModelPath.cpp
@@ -17,6 +17,7 @@
 #include "SessionItem.h"
 #include "GroupProperty.h"
 #include "GroupItem.h"
+#include "ParticleItem.h"
 #include <QModelIndex>
 #include <QStringList>
 #include <sstream>
@@ -28,26 +29,32 @@ QStringList ModelPath::getParameterTreeList(const SessionItem *item, QString pre
 {
     QStringList result;
     if (item->modelType() ==  Constants::PropertyType
-            && item->value().type() == QVariant::Double) {
+            && item->value().type() == QVariant::Double && item->itemName() != ParticleItem::P_ABUNDANCE) {
+        if (prefix.endsWith("/"))
+            prefix = prefix.mid(0, prefix.size()-1);
         result << prefix;
     }
-
-//    else if (item->modelType() ==  Constants::GroupItemType) {
-//        if (const GroupItem *groupItem = dynamic_cast<const GroupItem*>(item)) {
-//            if (const SessionItem *subItem = groupItem->group()->getCurrentItem()) {
-//                QString child_prefix = prefix + subItem->itemName() + QString("/");
-//                result << getParameterTreeList(subItem, child_prefix);
-//            }
-//        }
-//    }
-
     else {
         if (item->hasChildren()) {
             for (auto p_child : item->childItems()) {
                 if(p_child->isVisible()) {
-                    QString child_name = p_child->itemName();
-                    QString child_prefix = prefix + child_name + QString("/");
-                    result << getParameterTreeList(p_child, child_prefix);
+                    if (p_child->modelType() ==  Constants::GroupItemType) {
+                        if (const GroupItem *groupItem = dynamic_cast<const GroupItem*>(p_child)) {
+                            if (const SessionItem *subItem = groupItem->group()->getCurrentItem()) {
+                                if (groupItem->group()->isFixed()) {
+                                    QString child_prefix = prefix + groupItem->itemName() + QString("/");
+                                    result << getParameterTreeList(subItem, child_prefix);
+                                } else {
+                                    QString child_prefix = prefix + subItem->itemName() + QString("/");
+                                    result << getParameterTreeList(subItem, child_prefix);
+                                }
+                            }
+                        }
+                    } else {
+                        QString child_name = p_child->itemName();
+                        QString child_prefix = prefix + child_name + QString("/");
+                        result << getParameterTreeList(p_child, child_prefix);
+                    }
                 }
             }
         }
@@ -81,6 +88,17 @@ std::string ModelPath::translateParameterName(const SessionItem *item, const QSt
     if (list.size() > 1) {
         auto remainder = list[1];
         auto p_child = item->getChildByName(first_field);
+        if (!p_child) { //search through group items
+            auto groupItems = item->getChildrenOfType(Constants::GroupItemType);
+            for (auto groupItem : groupItems) {
+                if (GroupItem *gItem = dynamic_cast<GroupItem*>(groupItem)) {
+                    if (gItem->group()->getCurrentType() == first_field) {
+                        p_child = gItem->group()->getCurrentItem();
+                        break;
+                    }
+                }
+            }
+        }
         if (p_child) {
             result << translateParameterName(p_child, remainder);
         }
diff --git a/GUI/coregui/Models/ParticleDistributionItem.cpp b/GUI/coregui/Models/ParticleDistributionItem.cpp
index b5a90c141b3..11bee691a8d 100644
--- a/GUI/coregui/Models/ParticleDistributionItem.cpp
+++ b/GUI/coregui/Models/ParticleDistributionItem.cpp
@@ -50,15 +50,12 @@ ParticleDistributionItem::ParticleDistributionItem()
     ComboProperty par_prop;
     addProperty(P_DISTRIBUTED_PARAMETER, par_prop.getVariant());
     updateParameterList();
-    mapper()->setOnChildPropertyChange(
-                [this](SessionItem*,QString)
-    {
-        updateParameterList();
-    });
-
-    mapper()->setOnChildrenChange(
-                [this]()
+    mapper()->setOnAnyChildChange(
+                [this] (SessionItem* item)
     {
+        // prevent infinit loop when item changes its own properties
+        if (item && item->modelType()== Constants::PropertyType && item->parent() == this)
+            return;
         updateParameterList();
     });
 
@@ -74,7 +71,7 @@ std::unique_ptr<ParticleDistribution> ParticleDistributionItem::createParticleDi
     if (children.size() == 0) {
         return nullptr;
     }
-    std::unique_ptr<IParticle> P_particle = TransformToDomain::createIParticle(*children[0]);
+    std::unique_ptr<IParticle> P_particle = TransformToDomain::createIParticle(*getItem());
     if (!P_particle) {
         throw GUIHelpers::Error("DomainObjectBuilder::buildParticleDistribution()"
                                 " -> Error! No correct particle defined");
-- 
GitLab