Index: src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp
===================================================================
--- src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp	(revision 95f49f80844c3103ded5d5940874d5342ce246a6)
+++ src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp	(revision 3d5b5bdeb158f9612295a4adbb43add240c21bd9)
@@ -42,4 +42,5 @@
 
 #include <boost/bind.hpp>
+#include <boost/thread/locks.hpp>
 #include <iostream>
 
@@ -63,5 +64,5 @@
   ChangingChildrensVisibility(false),
   update_timer(NULL),
-  callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2))
+  callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2, _3))
 {
   setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
@@ -75,5 +76,5 @@
   //connect(this,SIGNAL(cellChanged(int,int)),this,SLOT(moleculeChanged(int,int)));
 //  connect(selectionModel(),SIGNAL(selectionChanged(QItemSelection, QItemSelection)),this,SLOT(rowsSelected(QItemSelection, QItemSelection)));
-  connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkForVisibilityChange(QStandardItem*)));
+  connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkForVisibilityChange(QStandardItem*)), Qt::DirectConnection);
 }
 
@@ -88,5 +89,5 @@
   if (role == Qt::DisplayRole) {
     if (orientation == Qt::Horizontal) {
-      if (section < QtMoleculeItemFactory::COLUMNTYPES_MAX)
+      if (section < QtMoleculeItem::COLUMNTYPES_MAX)
         return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
     }
@@ -100,16 +101,26 @@
 }
 
-QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(const moleculeId_t _molid) const
-{
+bool QtMoleculeList::isMoleculeItemPresent(const moleculeId_t _molid) const
+{
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
   MoleculeItemBiMap_t::left_const_iterator iter =
       MoleculeItemBiMap.left.find(_molid);
-  if( iter != MoleculeItemBiMap.left.end())
-    return iter->second;
-  else
-    return NULL;
+  return ( iter != MoleculeItemBiMap.left.end());
+}
+
+QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(const moleculeId_t _molid) const
+{
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
+  MoleculeItemBiMap_t::left_const_iterator iter =
+      MoleculeItemBiMap.left.find(_molid);
+  ASSERT( iter != MoleculeItemBiMap.left.end(),
+      "QtMoleculeList::MoleculeIdToItem() - could not find item to id "
+      +toString(_molid));
+  return iter->second;
 }
 
 const moleculeId_t QtMoleculeList::ItemToMoleculeId(const QtMoleculeItem * const _item) const
 {
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
   const MoleculeItemBiMap_t::right_const_iterator iter =
       MoleculeItemBiMap.right.find(const_cast<QtMoleculeItem * const>(_item));
@@ -120,6 +131,56 @@
 }
 
+QtMoleculeItem * QtMoleculeList::getSpecificMoleculeItem(
+    const QtMoleculeItem * const _item,
+    const enum QtMoleculeItem::COLUMNTYPES _type) const
+{
+  QStandardItem *parent_item = _item->parent();
+  ASSERT( parent_item != NULL,
+      "QtMoleculeList::getSpecificMoleculeItem() - parent of molecule item is NULL");
+  return static_cast<QtMoleculeItem *>(parent_item->child(_item->index().row(), _type));
+}
+
+bool QtMoleculeList::isGroupItemPresent(const std::string &_formula) const
+{
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
+  FormulaTreeItemBiMap_t::left_const_iterator iter =
+      FormulaItemBiMap.left.find(_formula);
+  return ( iter != FormulaItemBiMap.left.end());
+}
+
+QStandardItem * QtMoleculeList::FormulaToGroupItem(const std::string &_formula) const
+{
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
+  FormulaTreeItemBiMap_t::left_const_iterator iter =
+      FormulaItemBiMap.left.find(_formula);
+  ASSERT( iter != FormulaItemBiMap.left.end(),
+      "QtMoleculeList::FormulaToGroupItem() - could not find item to formula "
+      +toString(_formula));
+  return iter->second;
+}
+
+const std::string& QtMoleculeList::GroupItemToFormula(const QStandardItem * const _item) const
+{
+  boost::recursive_mutex::scoped_lock lock(map_mutex);
+  static std::string emptystring;
+  const FormulaTreeItemBiMap_t::right_const_iterator iter =
+      FormulaItemBiMap.right.find(const_cast<QStandardItem * const>(_item));
+  if (iter != FormulaItemBiMap.right.end())
+    return iter->second;
+  else
+    return emptystring;
+}
+
+QStandardItem * QtMoleculeList::getSpecificGroupItem(
+    const QStandardItem * const _item,
+    const enum QtMoleculeItem::COLUMNTYPES _type) const
+{
+  return invisibleRootItem()->child(_item->index().row(), _type);
+}
+
+
 const moleculeId_t QtMoleculeList::IndexToMoleculeId(const QModelIndex &_index) const
 {
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   QtMoleculeItem * const item = dynamic_cast<QtMoleculeItem *>(itemFromIndex(_index));
   if (item == NULL)
@@ -136,7 +197,8 @@
       {
         const molecule * const mol = World::getInstance().lastChanged<molecule>();
-        listAccessing_mutex.lock();
-        newItems.push_back( mol );
-        listAccessing_mutex.unlock();
+        boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
+        const moleculeId_t molid = mol->getId();
+        if (molid != (unsigned int )-1)
+          newMolecules.push_back( molid );
         break;
       }
@@ -145,17 +207,8 @@
         const molecule * const mol = World::getInstance().lastChanged<molecule>();
 
-        listAccessing_mutex.lock();
-        toBeRemovedItems.push_back( mol ); // remove in any case, as we also got insert
-        listAccessing_mutex.unlock();
-
-        const QtMoleculeItem *mol_item = MoleculeIdToItem(mol->getId());
-        if (mol_item != NULL) {
-          QStandardItem *parent_item = mol_item->parent();
-          if (parent_item != NULL)
-            addToBeSetOccurrence( parent_item );
-          else
-            ELOG(2, "QtMoleculeList::recieveNotification() - item to molecule "
-                +toString(mol)+" has no parent.");
-        }
+        boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
+        const moleculeId_t molid = mol->getId();
+        if (molid != (unsigned int )-1)
+          removedMolecules.push_back( molid ); // remove in any case, as we also got insert
         break;
       }
@@ -175,14 +228,9 @@
       QtMoleculeItemFactory::getInstance().createGroupItems(_molecule_formula);
   mainitem = groupItems.front();
-  formula.insert( std::make_pair(_molecule_formula, mainitem) );
+  {
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
+    FormulaItemBiMap.left.insert( std::make_pair(_molecule_formula, mainitem) );
+  }
   invisibleRootItem()->appendRow(groupItems);
-}
-
-void QtMoleculeList::addToBeSetOccurrence(
-    QStandardItem *_groupitem)
-{
-  listAccessing_mutex.lock();
-  toBeSetOccurrenceItems.insert( _groupitem );
-  listAccessing_mutex.unlock();
 }
 
@@ -197,24 +245,23 @@
   ASSERT( mol_item != NULL,
       "QtMoleculeList::addMoleculeItem() - item from factory was not a QtMoleculeItem?");
-  MoleculeItemBiMap.left.insert( std::make_pair(_molid, mol_item) );
+  {
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
+    MoleculeItemBiMap.left.insert( std::make_pair(_molid, mol_item) );
+    LOG(1, "Adding" << _molecule_formula << " for " << _molid << " to MoleculeFormulaMap.");
+    MoleculeFormulaMap.insert( std::make_pair( _molid, _molecule_formula) );
+  }
 //  LOG(1, "Inserting molecule " << _mol->getId() << ": " << _mol);
   _groupitem->appendRow(molItems);
-
-  // here update for the occurence will happen "one tick" later, but we don't
-  // have the groupitem any time earlier
-  addToBeSetOccurrence(_groupitem);
-}
-
-void QtMoleculeList::addMolecule(const molecule * const _mol)
+}
+
+std::string QtMoleculeList::addMolecule(const molecule * const _mol)
 {
   // find group if already in list
   QStandardItem *groupItem = NULL;
 
-  const std::string &molecule_formula = _mol->getFormula().toString();
-  FormulaTreeItemMap_t::const_iterator formulaiter =
-      formula.find(molecule_formula);
+  const std::string molecule_formula = _mol->getFormula().toString();
 
   // new molecule type -> create new group
-  if (formulaiter == formula.end()){
+  if (!isGroupItemPresent(molecule_formula)){
     // insert new formula entry into visibility
 #ifndef NDEBUG
@@ -230,29 +277,42 @@
     addGroupItem(groupItem, molecule_formula);
   } else {
-    groupItem = formulaiter->second;
+    groupItem = FormulaToGroupItem(molecule_formula);
   }
   ASSERT( groupItem != NULL,
       "QtMoleculeList::addMolecule() - item with id "+toString(_mol->getId())
-      +" has not parent?");
+      +" has no parent?");
 
   // add molecule
   addMoleculeItem(groupItem, _mol->getId(), molecule_formula);
-}
-
-void QtMoleculeList::removeItem(QtMoleculeItem * const _item)
-{
+
+  return molecule_formula;
+}
+
+void QtMoleculeList::removeMoleculeItem(QtMoleculeItem * const _item)
+{
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   const QModelIndex mol_index = indexFromItem(_item);
   QStandardItem *groupitem = _item->parent();
   const QModelIndex group_index = groupitem->index();
+  {
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
+    MoleculeItemBiMap_t::right_iterator removeiter =
+        MoleculeItemBiMap.right.find(_item);
+    ASSERT( removeiter != MoleculeItemBiMap.right.end(),
+        "QtMoleculeList::removeMoleculeItem() - could not find item in MoleculeBiMap.");
+  //  LOG(1, "Erasing molecule " << (removeiter->second));
+    {
+      MoleculeFormulaMap_t::iterator removeformulaiter =
+          MoleculeFormulaMap.find(removeiter->second);
+      ASSERT( removeformulaiter != MoleculeFormulaMap.end(),
+          "QtMoleculeList::removeMoleculeItem() - could not find id "
+          +toString(removeiter->second)+" in MoleculeFormulaMap.");
+      LOG(1, "Removing " << removeformulaiter->second << " for "
+          << removeformulaiter->first << " from MoleculeFormulaMap.");
+      MoleculeFormulaMap.erase( removeformulaiter );
+    }
+    MoleculeItemBiMap.right.erase(removeiter);
+  }
   removeRows(mol_index.row(), 1, group_index);
-  MoleculeItemBiMap_t::right_iterator removeiter =
-      MoleculeItemBiMap.right.find(_item);
-  ASSERT( removeiter != MoleculeItemBiMap.right.end(),
-      "QtMoleculeList::removeItem() - could not find item in BiMap.");
-  LOG(1, "Erasing molecule " << (removeiter->second));
-  MoleculeItemBiMap.right.erase(removeiter);
-
-  // don't need to, groupitem is already present in toBeSetOccurrenceItems
-//  addToBeSetOccurrence(_groupitem);
 }
 
@@ -266,22 +326,28 @@
     update_timer->stop();
 
-  refill_mutex.lock();
+  {
+    boost::recursive_mutex::scoped_lock refill_lock(refill_mutex);
+    boost::recursive_mutex::scoped_lock listAccessing_lock(listAccessing_mutex);
+
+    //  LOG(1, "Clearing list.");
+
+    clear();
+    FormulaVisibilityCountMap.clear();
+    {
+      boost::recursive_mutex::scoped_lock lock(map_mutex);
+      FormulaItemBiMap.clear();
+      MoleculeFormulaMap.clear();
+      MoleculeItemBiMap.clear();
+    }
+    dirtyMolItems.clear();
+    visibilityMolItems.clear();
+    visibilityGroupItems.clear();
+    newMolecules.clear();
+    removedMolecules.clear();
+    toBeMovedItems.clear();
+  }
 
   const std::vector<const molecule*> &molecules =
       const_cast<const World &>(World::getInstance()).getAllMolecules();
-
-  clear();
-  formula.clear();
-  FormulaVisibilityCountMap.clear();
-//  LOG(1, "Clearing list.");
-  MoleculeItemBiMap.clear();
-  dirtyItems.clear();
-  visibilityItems.clear();
-  toBeMovedItems.clear();
-  newItems.clear();
-  toBeRemovedItems.clear();
-  toBeSetOccurrenceItems.clear();
-  toBeSetVisibilityItems.clear();
-
   for (std::vector<const molecule*>::const_iterator iter = molecules.begin();
       iter != molecules.end();
@@ -289,6 +355,4 @@
     addMolecule(*iter);
 
-  refill_mutex.unlock();
-
   // activate timer
   update_timer->start(1000/update_times_per_second);
@@ -298,13 +362,13 @@
 {
   // get whether any items are dirty
-  listAccessing_mutex.lock();
+  boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
   bool dirty = false;
-  dirty |= !dirtyItems.empty();
-  dirty |= !visibilityItems.empty();
-  dirty |= !newItems.empty();
-  dirty |= !toBeRemovedItems.empty();
-  dirty |= !toBeSetOccurrenceItems.empty();
-  dirty |= !toBeSetVisibilityItems.empty();
-  listAccessing_mutex.unlock();
+  dirty |= !dirtyMolItems.empty();
+  dirty |= !visibilityMolItems.empty();
+  dirty |= !dirtyGroupItems.empty();
+  dirty |= !visibilityGroupItems.empty();
+  dirty |= !newMolecules.empty();
+  dirty |= !removedMolecules.empty();
+  dirty |= !toBeMovedItems.empty();
   return dirty;
 }
@@ -325,12 +389,15 @@
 //  qDebug() << "Item changed called.";
 
-  if (_item->index().column() == QtMoleculeItemFactory::VISIBILITY) {
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
+  if (_item->index().column() == QtMoleculeItem::VISIBILITY) {
 //    qDebug() << "visibilityItem changed: " << (_item->checkState() ? "checked" : "unchecked");
-    listAccessing_mutex.lock();
+    boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
     if ((_item->parent() == NULL) || (_item->parent() == invisibleRootItem()))
-      toBeSetVisibilityItems.insert( _item );
+      visibilityGroupItems.insert( std::make_pair(
+          GroupItemToFormula(_item->parent()), QtMoleculeItem::VISIBILITY) );
     else
-      visibilityItems.insert( dynamic_cast<QtMoleculeItem *>(_item) );
-    listAccessing_mutex.unlock();
+      visibilityMolItems.insert(
+          static_cast<QtMoleculeItem *>(_item)->getMoleculeId()
+          );
   }
 }
@@ -341,18 +408,24 @@
     return;
 
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   const bool visible = _item->checkState();
-  const molecule * const mol = _item->getMolecule();
-  std::string molecule_formula;
-  if (mol != NULL) {
-    molecule_formula = mol->getFormula().toString();
-    ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
+  const moleculeId_t molid = _item->getMoleculeId();
+  std::string molecule_formula("illegal");
+  {
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
+    MoleculeFormulaMap_t::const_iterator formulaiter =
+        MoleculeFormulaMap.find(molid);
+    ASSERT( formulaiter != MoleculeFormulaMap.end(),
+        "QtMoleculeList::setVisibilityForMoleculeItem() - formula of molecule "
+        +toString(molid)+" unknown.");
+    molecule_formula = formulaiter->second;
+  }
+  ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
         "QtMoleculeList::setVisibilityForMoleculeItem() - molecule with formula " +molecule_formula
         +" is not present in FormulaVisibilityCountMap.");
-  }
 
   // get parent
   QStandardItem *groupItem = _item->parent();
-  QStandardItem *visgroupItem =
-      invisibleRootItem()->child(groupItem->index().row(), QtMoleculeItemFactory::VISIBILITY);
+  QStandardItem *visgroupItem = getSpecificGroupItem(groupItem, QtMoleculeItem::VISIBILITY);
   ASSERT( groupItem != NULL,
       "QtMoleculeList::setVisibilityForMoleculeItem() - item with id "
@@ -385,11 +458,11 @@
   ChangingChildrensVisibility = true;
 
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   // go through all children, but don't enter for groupItem once more
   const bool visible = _item->checkState();
-  QStandardItem *groupitem = invisibleRootItem()->child(
-      _item->index().row(), QtMoleculeItemFactory::NAME);
+  QStandardItem *groupitem = getSpecificGroupItem(_item, QtMoleculeItem::NAME);
   for (int i=0;i<groupitem->rowCount();++i) {
     QtMoleculeItem *molItem = dynamic_cast<QtMoleculeItem *>(
-        groupitem->child(i, QtMoleculeItemFactory::VISIBILITY));
+        groupitem->child(i, QtMoleculeItem::VISIBILITY));
     if (molItem->checkState() != visible) {
       molItem->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
@@ -401,5 +474,5 @@
   // set current number of visible children
   const std::string molecule_formula =
-      invisibleRootItem()->child(_item->row(), QtMoleculeItemFactory::NAME)->text().toStdString();
+      GroupItemToFormula( getSpecificGroupItem(_item, QtMoleculeItem::NAME) );
   FormulaVisibilityCountMap_t::iterator countiter =
       FormulaVisibilityCountMap.find(molecule_formula);
@@ -416,10 +489,10 @@
   /*int idx = verticalHeaderItem(row)->data(Qt::UserRole).toInt();
   molecule *mol = molecules->ReturnIndex(idx);
-  string cellValue = item(row,QtMoleculeItemFactory::NAME)->text().toStdString();
+  string cellValue = item(row,QtMoleculeItem::NAME)->text().toStdString();
   if(mol->getName() != cellValue && cellValue !="") {
     mol->setName(cellValue);
   }
   else if(cellValue==""){
-    item(row,QtMoleculeItemFactory::NAME)->setText(QString(mol->getName().c_str()));
+    item(row,QtMoleculeItem::NAME)->setText(QString(mol->getName().c_str()));
   }*/
 }
@@ -428,4 +501,5 @@
 int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
 {
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   QModelIndex modelindex = _groupitem->index();
   ASSERT( modelindex.isValid(),
@@ -437,5 +511,5 @@
       "QtMoleculeList::setOccurrence() - group item at "+toString(index)
       +" does not have a parent?");
-  QStandardItem *occ_item = parent_item->child(index, QtMoleculeItemFactory::OCCURRENCE);
+  QStandardItem *occ_item = parent_item->child(index, QtMoleculeItem::OCCURRENCE);
   ASSERT( occ_item != NULL,
       "QtMoleculeList::setOccurrence() - group item at "+toString(index)
@@ -444,6 +518,7 @@
   if (count == 0) {
     // we have to remove the group item completely
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
     const std::string molecule_formula = _groupitem->text().toStdString();
-    formula.erase(molecule_formula);
+    FormulaItemBiMap.left.erase(molecule_formula);
     FormulaVisibilityCountMap.erase(molecule_formula);
     return index;
@@ -454,6 +529,7 @@
 }
 
-void QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
-{
+std::string QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
+{
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
   // use takeRows of molecule ..
   QStandardItem *groupitem = _molitem->parent();
@@ -461,19 +537,15 @@
       "QtMoleculeList::readdItem() - mol item at "+toString(_molitem->index().row())
       +" does not have a groupitem?");
+  const molecule * const mol = _molitem->getMolecule();
   QList<QStandardItem *> mol_row = _molitem->parent()->takeRow(_molitem->index().row());
-  // call setOccurrence on the old group later, if it's not a removal candidate
-  if (groupitem->rowCount() != 0)
-    addToBeSetOccurrence(groupitem);
   // ..  and re-add where new formula fits
-  const molecule * const mol = _molitem->getMolecule();
   std::string molecule_formula;
   if (mol != NULL) {
     molecule_formula = mol->getFormula().toString();
-    FormulaTreeItemMap_t::iterator iter = formula.find(molecule_formula);
-    if (iter == formula.end()) {
+    if (!isGroupItemPresent(molecule_formula)) {
       // add new group item and formula entry
        addGroupItem(groupitem, molecule_formula);
     } else {
-      groupitem = iter->second;
+      groupitem = FormulaToGroupItem(molecule_formula);
     }
     ASSERT( groupitem != NULL,
@@ -481,28 +553,30 @@
     // finally add again
     groupitem->appendRow(mol_row);
-  }
-  // call setOccurrence on the new group later
-  addToBeSetOccurrence(groupitem);
+  } else {
+    for (QList<QStandardItem *>::iterator iter = mol_row.begin();
+        iter != mol_row.end(); ++iter)
+      delete *iter;
+  }
+
+  return molecule_formula;
 }
 
 void QtMoleculeList::informDirtyState(
-    QtMoleculeItem *_item,
-    const QtMoleculeItem::MoveTypes _type)
+    const moleculeId_t _id,
+    const QtMoleculeItem::COLUMNTYPES _type,
+    const QtMoleculeItem::MoveTypes _movetype)
 {
   listAccessing_mutex.lock();
-  dirtyItems.insert(_item);
+  dirtyMolItems.insert( std::make_pair(_id, _type) );
   listAccessing_mutex.unlock();
 
-  if (_type == QtMoleculeItem::NeedsMove) {
+  if (_movetype == QtMoleculeItem::NeedsMove) {
     // we have to convert whatever item raised the dirty signal to the first
     // item in the row as otherwise multiple items in the row are selected
     // as to be moved, i.e. the same row is moved multiple times
     listAccessing_mutex.lock();
-    toBeMovedItems.insert(_item);
+    toBeMovedItems.insert(_id);
     listAccessing_mutex.unlock();
-//    // add group item, too
-//    toBeSetOccurrenceItems.insert(group_item);
-  }
-
+  }
 }
 
@@ -512,18 +586,18 @@
   // TODO: if we had move semantics ...
   listAccessing_mutex.lock();
-  list_of_items_t dirtyItems_copy = dirtyItems;
-  dirtyItems.clear();
-  list_of_items_t visibilityItems_copy = visibilityItems;
-  visibilityItems.clear();
-  list_of_items_t toBeMovedItems_copy = toBeMovedItems;
+  list_of_molecule_items_t dirtyMolItems_copy = dirtyMolItems;
+  dirtyMolItems.clear();
+  list_of_molecules_t visibilityMolItems_copy = visibilityMolItems;
+  visibilityMolItems.clear();
+  list_of_group_items_t dirtyGroupItems_copy = dirtyGroupItems;
+  dirtyGroupItems.clear();
+  list_of_group_items_t visibilityGroupItems_copy = visibilityGroupItems;
+  visibilityGroupItems.clear();
+  std::vector<moleculeId_t> newMolecules_copy = newMolecules;
+  newMolecules.clear();
+  std::vector<moleculeId_t> removedMolecules_copy = removedMolecules;
+  removedMolecules.clear();
+  list_of_molecules_t toBeMovedItems_copy = toBeMovedItems;
   toBeMovedItems.clear();
-  std::vector<const molecule *> newItems_copy = newItems;
-  newItems.clear();
-  std::vector<const molecule *> toBeRemovedItems_copy = toBeRemovedItems;
-  toBeRemovedItems.clear();
-  std::set<QStandardItem*> toBeSetOccurrenceItems_copy = toBeSetOccurrenceItems;
-  toBeSetOccurrenceItems.clear();
-  std::set<QStandardItem*> toBeSetVisibilityItems_copy = toBeSetVisibilityItems;
-  toBeSetVisibilityItems.clear();
   listAccessing_mutex.unlock();
 
@@ -534,108 +608,150 @@
   /// -# don't add molecule that are also removed
 
-  //  // remove molecules added and removed immediately in both lists
-  std::vector<const molecule *> addedremoved;
-  std::sort(newItems_copy.begin(), newItems_copy.end());
-  std::sort(toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end());
-  std::set_intersection(
-      newItems_copy.begin(), newItems_copy.end(),
-      toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
-      std::back_inserter(addedremoved));
+  // remove molecules added and removed immediately in both lists
+  // note that newMolecules are all those where a moleculeInserted callback
+  // has been received but not action has been taken (i.e. it is not contained
+  // in any other list so far), toBeRemoved is inserted on moleculeRemoved
+  // and other lists (toBeSetOccurrenceItems) are only filled if the molecule
+  // item has already been instantiated.
   {
-    std::vector<const molecule *>::iterator removeiter = std::set_difference(
-        newItems_copy.begin(), newItems_copy.end(),
-        addedremoved.begin(), addedremoved.end(),
-        newItems_copy.begin());
-    newItems_copy.erase(removeiter, newItems_copy.end());
-  }
-  {
-    std::vector<const molecule *>::iterator removeiter = std::set_difference(
-        toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
-        addedremoved.begin(), addedremoved.end(),
-        toBeRemovedItems_copy.begin());
-    toBeRemovedItems_copy.erase(removeiter, toBeRemovedItems_copy.end());
-  }
-  addedremoved.clear();
+    std::vector<moleculeId_t> addedremoved;
+    std::sort(newMolecules_copy.begin(), newMolecules_copy.end());
+    std::sort(removedMolecules_copy.begin(), removedMolecules_copy.end());
+    std::set_intersection(
+        newMolecules_copy.begin(), newMolecules_copy.end(),
+        removedMolecules_copy.begin(), removedMolecules_copy.end(),
+        std::back_inserter(addedremoved));
+    {
+      std::vector<moleculeId_t>::iterator removeiter = std::set_difference(
+          newMolecules_copy.begin(), newMolecules_copy.end(),
+          addedremoved.begin(), addedremoved.end(),
+          newMolecules_copy.begin());
+      newMolecules_copy.erase(removeiter, newMolecules_copy.end());
+    }
+    {
+      std::vector<moleculeId_t>::iterator removeiter = std::set_difference(
+          removedMolecules_copy.begin(), removedMolecules_copy.end(),
+          addedremoved.begin(), addedremoved.end(),
+          removedMolecules_copy.begin());
+      removedMolecules_copy.erase(removeiter, removedMolecules_copy.end());
+    }
+  }
 
   // wait till initial refill has been executed
-  refill_mutex.lock();
-
-  // convert ToBeMoved items from any position to first position item
-  {
-    list_of_items_t toBeMovedItems_copy_fronts;
-    for (list_of_items_t::const_iterator moveiter = toBeMovedItems_copy.begin();
-        moveiter != toBeMovedItems_copy.end(); ++moveiter) {
-      QStandardItem *group_item = (*moveiter)->parent();
-      QtMoleculeItem *mol_item =
-          dynamic_cast<QtMoleculeItem *>(group_item->child((*moveiter)->row(), 0));
-      toBeMovedItems_copy_fronts.insert( mol_item );
-    }
-    toBeMovedItems_copy = toBeMovedItems_copy_fronts;
-  }
-
-  for (std::vector<const molecule *>::iterator removeiter = toBeRemovedItems_copy.begin();
-      removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
-    QtMoleculeItem *item = MoleculeIdToItem((*removeiter)->getId());
-    dirtyItems_copy.erase(item);
-    toBeMovedItems_copy.erase(item);
-  }
-  for (list_of_items_t::iterator visiter = visibilityItems_copy.begin();
-      visiter != visibilityItems_copy.end(); ) {
-    QtMoleculeItem * const _item = dynamic_cast<QtMoleculeItem *>(
-        (*visiter)->parent()->child(
-            (*visiter)->index().row(),
-            QtMoleculeItemFactory::NAME));
-    const moleculeId_t molid = ItemToMoleculeId(_item);
-    const molecule *mol = const_cast<const World &>(World::getInstance()).
-        getMolecule(MoleculeById(molid));
-    if (std::binary_search(
-            toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
-            mol))
-      visibilityItems_copy.erase(visiter++);
-    else
-      ++visiter;
+  boost::recursive_mutex::scoped_lock lock(refill_mutex);
+
+//  LOG(1, "Starting update.");
+
+  // remove removedMolecules from other lists.
+  for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
+      removeiter != removedMolecules_copy.end(); ++removeiter) {
+    for (unsigned int i=0;i< QtMoleculeItem::COLUMNTYPES_MAX; ++i)
+        dirtyMolItems_copy.erase( std::make_pair(*removeiter,(QtMoleculeItem::COLUMNTYPES)i) );
+    toBeMovedItems_copy.erase(*removeiter);
+    visibilityMolItems_copy.erase(*removeiter);
   }
 
   /// 1a. do the update for each dirty item
-  for (list_of_items_t::const_iterator dirtyiter = dirtyItems_copy.begin();
-      dirtyiter != dirtyItems_copy.end(); ++dirtyiter) {
-    LOG(1, "Updating item " << *dirtyiter);
-    (*dirtyiter)->updateState();
+  for (list_of_molecule_items_t::const_iterator dirtyiter = dirtyMolItems_copy.begin();
+      dirtyiter != dirtyMolItems_copy.end(); ++dirtyiter) {
+    if (!isMoleculeItemPresent(dirtyiter->first))
+      continue;
+    QtMoleculeItem * const mol_item =
+        getSpecificMoleculeItem(
+            MoleculeIdToItem(dirtyiter->first),
+            dirtyiter->second);
+//    LOG(1, "Updating item " << mol_item);
+    mol_item->updateState();
   }
 
   /// 1b. do the visibility update for each dirty item
-  for (list_of_items_t::const_iterator visiter = visibilityItems_copy.begin();
-      visiter != visibilityItems_copy.end(); ++visiter) {
-//    LOG(1, "Updating visibility of item " << *visiter);
-    ASSERT(((*visiter)->parent() != NULL) && ((*visiter)->parent() != invisibleRootItem()),
-        "QtMoleculeList::updateItemStates() - a group item ended up in visibilityItems.");
-    setVisibilityForMoleculeItem(*visiter);
+  for (list_of_molecules_t::const_iterator visiter = visibilityMolItems_copy.begin();
+      visiter != visibilityMolItems_copy.end(); ++visiter) {
+    if (!isMoleculeItemPresent(*visiter))
+      continue;
+    QtMoleculeItem * const visitem =
+      getSpecificMoleculeItem(
+          MoleculeIdToItem(*visiter),
+          QtMoleculeItem::VISIBILITY );
+//    LOG(1, "Updating visibility of item " << visitem);
+    setVisibilityForMoleculeItem(visitem);
   }
 
   /// 2. move all items that need to be moved
-  for (list_of_items_t::const_iterator moveiter = toBeMovedItems_copy.begin();
+  typedef std::set<std::string> formulas_t;
+  formulas_t toBeSetOccurrence;
+  for (list_of_molecules_t::const_iterator moveiter = toBeMovedItems_copy.begin();
       moveiter != toBeMovedItems_copy.end(); ++moveiter) {
-//    LOG(1, "Moving item " << *moveiter);
-    readdItem(*moveiter);
-  }
+    boost::recursive_mutex::scoped_lock lock(map_mutex);
+//    LOG(1, "Moving item " << molitem);
+    MoleculeFormulaMap_t::iterator formulaiter =
+        MoleculeFormulaMap.find(*moveiter);
+    ASSERT( formulaiter != MoleculeFormulaMap.end(),
+        "QtMoleculeList::updateItemStates() - formula of molecule "
+        +toString(*moveiter)+" unknown.");
+//    LOG(1, "Adding " << formulaiter->second << " to toBeSetOccurrence.");
+    toBeSetOccurrence.insert( formulaiter->second );
+    if (!isMoleculeItemPresent(*moveiter))
+      continue;
+    QtMoleculeItem *const molitem = MoleculeIdToItem(*moveiter);
+    LOG(1, "Moving item " << molitem);
+    const molecule *mol = molitem->getMolecule();
+    if (mol == NULL) {
+      // removeMolecule will remove also from formula<->molecule bimap
+      removeMoleculeItem(molitem);
+    } else {
+      // remove from formula<->molecule bimap with old formula
+      LOG(1, "Removing " << formulaiter->second << " for " << formulaiter->first << " from MoleculeFormulaMap.");
+      MoleculeFormulaMap.erase( formulaiter );
+      const std::string formula = readdItem(molitem);
+      // and add to formula<->molecule bimap with updated formula
+      LOG(1, "Adding " << formula << " for " << *moveiter << " to MoleculeFormulaMap.");
+      MoleculeFormulaMap.insert( std::make_pair(*moveiter, formula) );
+//      LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
+      toBeSetOccurrence.insert( formula );
+    }
+  }
+
+  // throw out items that we added by an update() while we are in this function
+  listAccessing_mutex.lock();
+  for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
+      removeiter != removedMolecules_copy.end(); ++removeiter) {
+    for (unsigned int i=0;i< QtMoleculeItem::COLUMNTYPES_MAX; ++i)
+        dirtyMolItems.erase( std::make_pair(*removeiter,(QtMoleculeItem::COLUMNTYPES)i) );
+    toBeMovedItems.erase(*removeiter);
+    visibilityMolItems.erase(*removeiter);
+  }
+  listAccessing_mutex.unlock();
+  // after that it is not a problem as items have been removed (hence signOff() was called)
 
   /// 3. remove all items whose molecules have been removed
-  for (std::vector<const molecule *>::const_iterator removeiter = toBeRemovedItems_copy.begin();
-      removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
-//    LOG(1, "Removing molecule " << *removeiter); // cannot access directly, molecule is gone
-    QtMoleculeItem *item = MoleculeIdToItem((*removeiter)->getId());
-    if (item != NULL)
-      removeItem(item);
+  for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
+      removeiter != removedMolecules_copy.end(); ++removeiter) {
+//    LOG(1, "Removing molecule " << *removeiter);
+    if (!isMoleculeItemPresent(*removeiter))
+      continue;
+    QtMoleculeItem *item = MoleculeIdToItem(*removeiter);
+    if (item != NULL) {
+      const std::string formula = item->parent()->text().toStdString();
+//      LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
+      toBeSetOccurrence.insert( formula );
+      removeMoleculeItem(item);
+    }
   }
 
   /// 4. instantiate all new items
-  for (std::vector<const molecule *>::const_iterator moliter = newItems_copy.begin();
-      moliter != newItems_copy.end(); ++moliter) {
-//    LOG(1, "Adding molecule " << (*moliter)->getName());
+  for (std::vector<moleculeId_t>::const_iterator moliter = newMolecules_copy.begin();
+      moliter != newMolecules_copy.end(); ++moliter) {
+//    LOG(1, "Adding molecule " << *moliter);
     // check that World knows the molecule still
     const molecule * const mol = const_cast<const World &>(World::getInstance()).
-        getMolecule(MoleculeById((*moliter)->getId()));
-    if ((mol != NULL) && (mol == *moliter)) {
-      addMolecule(mol);
+        getMolecule(MoleculeById(*moliter));
+    if ((mol != NULL) && (mol->getId() == *moliter)) {
+      const std::string formula = addMolecule(mol);;
+//      LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
+      toBeSetOccurrence.insert( formula );
+    } else {
+      ELOG(2, "Molecule " << *moliter
+          << " disappeared before we could render it in QtMoleculeList.");
     }
   }
@@ -643,26 +759,35 @@
   /// 5a. update the group item's occurrence and visibility
   std::set<int> RowsToRemove;
-  for (std::set<QStandardItem*>::const_iterator groupiter = toBeSetOccurrenceItems_copy.begin();
-      groupiter != toBeSetOccurrenceItems_copy.end(); ++groupiter) {
-//    LOG(1, "Updating group item " << *groupiter);
-    const int index = setOccurrence(*groupiter);
-    if (index != -1)
+  for (std::set<std::string>::const_iterator groupiter = toBeSetOccurrence.begin();
+      groupiter != toBeSetOccurrence.end(); ++groupiter) {
+//    LOG(1, "Updating group item's occurence " << *groupiter);
+    QStandardItem *groupitem = FormulaToGroupItem(*groupiter);
+    const int index = setOccurrence(groupitem);
+    if (index != -1) {
+//      LOG(1, "Removing row of group item " << groupitem);
       RowsToRemove.insert(index);
-  }
+    }
+  }
+  toBeSetOccurrence.clear();
 
   // remove all visibility updates whose row is removed
-  for (std::set<QStandardItem*>::iterator visiter = toBeSetVisibilityItems_copy.begin();
-      visiter != toBeSetVisibilityItems_copy.end(); ) {
-    if (RowsToRemove.count((*visiter)->index().row()) != 0)
-      toBeSetVisibilityItems_copy.erase(visiter++);
-    else
+  for (list_of_group_items_t::iterator visiter = visibilityGroupItems_copy.begin();
+      visiter != visibilityGroupItems_copy.end(); ) {
+      QStandardItem * const groupitem = FormulaToGroupItem(visiter->first);
+    if (RowsToRemove.count(groupitem->index().row()) != 0) {
+//      LOG(1, "Removing vis item " << *visiter << " because of removed group item.");
+      visibilityGroupItems_copy.erase(visiter++);
+    } else
       ++visiter;
   }
 
   // update visibility of all group items
-  for (std::set<QStandardItem*>::iterator visiter = toBeSetVisibilityItems_copy.begin();
-      visiter != toBeSetVisibilityItems_copy.end(); ++visiter) {
+  for (list_of_group_items_t::iterator visiter = visibilityGroupItems_copy.begin();
+      visiter != visibilityGroupItems_copy.end(); ++visiter) {
 //    LOG(1, "Updating visibility of item " << *visiter);
-    setVisibilityForGroupItem(*visiter);
+    QStandardItem * const groupitem =
+        getSpecificGroupItem(FormulaToGroupItem(visiter->first),
+        visiter->second);
+    setVisibilityForGroupItem(groupitem);
   }
 
@@ -675,4 +800,4 @@
 
   // and done
-  refill_mutex.unlock();
-}
+//  LOG(1, "Done with update.");
+}
