Index: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp
===================================================================
--- src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp	(revision 009e2e2d372810a555a452769338209c68591479)
+++ src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp	(revision 6c16a02ecd71315045f7522510b3807789050e4b)
@@ -44,4 +44,6 @@
 
 #include "CodePatterns/MemDebug.hpp"
+
+#include <boost/assign.hpp>
 
 #include "CodePatterns/Assert.hpp"
@@ -65,19 +67,282 @@
 #include "World.hpp"
 
+using namespace boost::assign;
+
 #include "GLMoleculeObject_atom.hpp"
 
-static QGLSceneNode *createMoleculeMesh(const moleculeId_t molid, QObject *parent)
-{
-  const molecule *molref = const_cast<const World &>(World::getInstance()).
-      getMolecule(MoleculeById(molid));
+static Observable::channels_t getAtomsChannels()
+{
+  Observable::channels_t channels;
+  channels += molecule::AtomInserted, molecule::AtomRemoved;
+  return channels;
+}
+
+static Observable::channels_t getAllAtomicChangesChannels()
+{
+  Observable::channels_t channels;
+  channels += molecule::AtomInserted, molecule::AtomRemoved, molecule::AtomMoved;
+  return channels;
+}
+
+// static instances
+const Observable::channels_t GLMoleculeObject_molecule::AtomsChannels(getAtomsChannels());
+const Observable::channels_t GLMoleculeObject_molecule::HullChannels(getAllAtomicChangesChannels());
+const Observable::channels_t GLMoleculeObject_molecule::BoundingBoxChannels(getAllAtomicChangesChannels());
+const Observable::channels_t GLMoleculeObject_molecule::IndexChannels(1, molecule::IndexChanged);
+
+static QGLSceneNode *createMoleculeMesh(const QGeometryData &_geo)
+{
+  // Build a mesh from the geometry.
+  QGLBuilder builder;
+  builder.addTriangles(_geo);
+  QGLSceneNode *mesh = builder.finalizedSceneNode();
+  return mesh;
+}
+
+GLMoleculeObject_molecule::GLMoleculeObject_molecule(QObject *parent, const moleculeId_t _molid) :
+  GLMoleculeObject((QGLSceneNode *)NULL, parent),
+  Observer(std::string("GLMoleculeObject_molecule")+toString(_molid)),
+  owner(NULL),
+  molref(getMolecule(_molid)),
+  /* We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
+   * boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
+   * the class has not been fully constructed yet. "This" itself seems to be working fine.
+   */
+  MolIndexUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateIndex, this)
+      ),
+  TesselationHullUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateTesselationHull, this)
+      ),
+  IsSelectedUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateIsSelected, this)
+      ),
+  BoundingBoxUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateBoundingBox, this)
+      ),
+  PresentAtomsUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateAtoms, this)
+      ),
+  MolIndex(
+      molref,
+      MolIndexUpdater,
+      "MoleculeIndex_"+toString(_molid),
+      _molid,
+      IndexChannels),
+  TesselationHull(
+      molref,
+      TesselationHullUpdater,
+      "MoleculeTesselationHull_"+toString(_molid),
+      HullChannels),
+  isSelected(
+      const_cast<const World * const>(World::getPointer()),
+      IsSelectedUpdater,
+      "MoleculeBoundingBox_"+toString(_molid),
+      updateIsSelected(),
+      BoundingBoxChannels),
+  BoundingBox(
+      molref,
+      BoundingBoxUpdater,
+      "MoleculeBoundingBox_"+toString(_molid),
+      updateBoundingBox(),
+      BoundingBoxChannels),
+  PresentAtoms(
+      molref,
+      PresentAtomsUpdater,
+      "MoleculeAtoms_"+toString(_molid),
+      updateAtoms(),
+      AtomsChannels),
+  hoverAtomId(-1)
+{
+  setObjectId(_molid);
+  setMaterial(getMaterial(1));
+
+  // initially, atoms and bonds should be visible
+  m_visible = false;
+
+  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
+  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
+  connect (this, SIGNAL(TesselationHullChanged()), this, SLOT(resetTesselationHull()), Qt::QueuedConnection);
+  connect (this, SIGNAL(BoundingBoxChanged()), this, SLOT(resetBoundingBox()), Qt::QueuedConnection);
+  connect (this, SIGNAL(IsSelectedChanged()), this, SLOT(resetIsSelected()), Qt::QueuedConnection);
+  connect (this, SIGNAL(IdChanged()), this, SLOT(resetIndex()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(atomInserted(const atomId_t)), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(atomRemoved(const atomId_t)), Qt::QueuedConnection);
+
+  connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
+}
+
+GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const moleculeId_t _molid) :
+  GLMoleculeObject(mesh, parent),
+  Observer(std::string("GLMoleculeObject_molecule")+toString(_molid)),
+  owner(NULL),
+  molref(getMolecule(_molid)),
+  /* We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
+   * boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
+   * the class has not been fully constructed yet. "This" itself seems to be working fine.
+   */
+  MolIndexUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateIndex, this)
+      ),
+  TesselationHullUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateTesselationHull, this)
+      ),
+  IsSelectedUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateIsSelected, this)
+      ),
+  BoundingBoxUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateBoundingBox, this)
+      ),
+  PresentAtomsUpdater(
+      boost::bind(&GLMoleculeObject_molecule::updateAtoms, this)
+      ),
+  MolIndex(
+      molref,
+      MolIndexUpdater,
+      "MoleculeIndex_"+toString(_molid),
+      _molid,
+      IndexChannels),
+  TesselationHull(
+      molref,
+      TesselationHullUpdater,
+      "MoleculeTesselationHull_"+toString(_molid),
+      HullChannels),
+  isSelected(
+      const_cast<const World * const>(World::getPointer()),
+      IsSelectedUpdater,
+      "MoleculeBoundingBox_"+toString(_molid),
+      updateIsSelected(),
+      BoundingBoxChannels),
+  BoundingBox(
+      molref,
+      BoundingBoxUpdater,
+      "MoleculeBoundingBox_"+toString(_molid),
+      updateBoundingBox(),
+      BoundingBoxChannels),
+  PresentAtoms(
+      molref,
+      PresentAtomsUpdater,
+      "MoleculeAtoms_"+toString(_molid),
+      atoms_t(),
+      AtomsChannels),
+  hoverAtomId(-1)
+{
+  setObjectId(_molid);
+  setMaterial(getMaterial(1));
+
+  // initially, atoms and bonds should be visible
+  m_visible = false;
+
+  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
+  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
+  connect (this, SIGNAL(TesselationHullChanged()), this, SLOT(resetTesselationHull()), Qt::QueuedConnection);
+  connect (this, SIGNAL(BoundingBoxChanged()), this, SLOT(resetBoundingBox()), Qt::QueuedConnection);
+  connect (this, SIGNAL(IsSelectedChanged()), this, SLOT(resetIsSelected()), Qt::QueuedConnection);
+  connect (this, SIGNAL(IdChanged()), this, SLOT(resetIndex()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(atomInserted(const atomId_t)), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
+  connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(atomRemoved(const atomId_t)), Qt::QueuedConnection);
+
+  connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
+}
+
+GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
+{
+  deactivateObserver();
+}
+
+void GLMoleculeObject_molecule::deactivateObserver()
+{
+  if (owner != NULL) {
+    owner->signOff(this, molecule::AtomInserted);
+    owner->signOff(this, molecule::AtomRemoved);
+    owner->signOff(this, molecule::AtomMoved);
+    owner->signOff(this, molecule::IndexChanged);
+    /*_atom->signOff(this, AtomObservable::IndexChanged);
+    _atom->signOff(this, AtomObservable::PositionChanged);
+    _atom->signOff(this, AtomObservable::ElementChanged);
+    _atom->signOff(this, AtomObservable::BondsAdded);*/
+    World::getInstance().signOff(this, World::SelectionChanged);
+    owner = NULL;
+  }
+}
+
+void GLMoleculeObject_molecule::activateObserver()
+{
+  // sign on as observer (obtain non-const instance before)
+  const molecule * const _molecule = getMolecule(MolIndex.get());
+  if (_molecule != NULL) {
+    owner = static_cast<const Observable *>(_molecule);
+    owner->signOn(this, molecule::AtomInserted);
+    owner->signOn(this, molecule::AtomRemoved);
+    owner->signOn(this, molecule::AtomMoved);
+    owner->signOn(this, molecule::IndexChanged);
+    /*molref->signOn(this, AtomObservable::IndexChanged);
+    molref->signOn(this, AtomObservable::PositionChanged);
+    molref->signOn(this, AtomObservable::ElementChanged);
+    molref->signOn(this, AtomObservable::BondsAdded);*/
+    World::getInstance().signOn(this, World::SelectionChanged);
+  } else {
+    ELOG(1, "GLMoleculeObject_molecule() - added null object for not present mol id " << MolIndex.get());
+  }
+
+}
+
+void GLMoleculeObject_molecule::addAtomBonds(
+    const bond::ptr &_bond,
+    const GLMoleculeObject_bond::SideOfBond _side
+    )
+{
+  bool bond_present = false;
+  const BondIds ids = getBondIds(_bond, _side);
+  // check whether bond is not present already
+  bond_present = BondsinSceneMap.count(ids);
+  if (!bond_present)
+    bondInserted(ids.first, ids.second, _side);
+  else {
+    BondsinSceneMap[ids]->resetPosition();
+    BondsinSceneMap[ids]->resetWidth();
+  }
+}
+
+void GLMoleculeObject_molecule::addAtomBonds(
+    const atom *_atom)
+{
+  const bool atom_present = AtomsinSceneMap.count(_atom->getId());
+  const BondList &bondlist = _atom->getListOfBonds();
+  for (BondList::const_iterator bonditer = bondlist.begin();
+      (bonditer != bondlist.end()) && atom_present;
+      ++bonditer) {
+    const bond::ptr _bond = *bonditer;
+    // check if OtherAtom's sphere is already present
+    const atom *OtherAtom = _bond->GetOtherAtom(_atom);
+    const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
+    if (otheratom_present && atom_present) {
+      const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
+          GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
+      const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
+          GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
+      addAtomBonds(_bond, side);
+      addAtomBonds(_bond, otherside);
+    }
+  }
+}
+
+QGeometryData GLMoleculeObject_molecule::updateTesselationHull() const
+{
+  QGeometryData geo;
+
+  const molecule * const molref = getMolecule(MolIndex.get());
   if (molref == NULL) {
-    ELOG(1, "Could not createMoleculeMesh, molecule with id " << molid << " already gone.");
-    return NULL;
-  }
-//  Shape shape = molref->getBoundingSphere();
+    ELOG(1, "Could not createMoleculeMesh, molecule with id " << MolIndex.get() << " already gone.");
+    return geo;
+  }
   double minradius = 2.; // TODO: set to maximum bond length value
   LOG(3, "DEBUG: Molecule fits into sphere of radius " << minradius);
   // check minimum bond radius in molecule
-  double minlength = std::numeric_limits<double>::max(); 
+  double minlength = std::numeric_limits<double>::max();
   for (molecule::const_iterator iter = molref->begin();
       iter != molref->end(); ++iter) {
@@ -91,5 +356,4 @@
   minradius = std::max( std::max(minradius, minlength), 1.);
 
-  QGeometryData geo;
   // we need at least three points for tesselation
   if (molref->getAtomCount() >= 3) {
@@ -140,148 +404,98 @@
   }
 
-  // Build a mesh from the geometry.
-  QGLBuilder builder;
-  builder.addTriangles(geo);
-  QGLSceneNode *mesh = builder.finalizedSceneNode();
-  return mesh;
-}
-
-GLMoleculeObject_molecule::GLMoleculeObject_molecule(QObject *parent, const moleculeId_t molid) :
-  GLMoleculeObject(createMoleculeMesh(molid, parent), parent),
-  Observer(std::string("GLMoleculeObject_molecule")+toString(molid)),
-  isBoundingBoxUptodate(true),
-  isSignedOn(false),
-  moleculeid(molid),
-  TesselationHullUptodate(true),
-  hoverAtomId(-1)
-{
-  setMaterial(getMaterial(1));
-  updateBoundingBox();
-
-  // initially, atoms and bonds should be visible
-  m_visible = false;
-
-  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
-  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
-
-  connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
-}
-
-GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const moleculeId_t molid) :
-  GLMoleculeObject(mesh, parent),
-  Observer(std::string("GLMoleculeObject_molecule")+toString(molid)),
-  isBoundingBoxUptodate(true),
-  isSignedOn(false),
-  moleculeid(molid),
-  TesselationHullUptodate(true),
-  hoverAtomId(-1)
-{
-  setMaterial(getMaterial(1));
-  updateBoundingBox();
-
-  // initially, atoms and bonds should be visible
-  m_visible = false;
-
-  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
-  connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
-
-  connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
-}
-
-GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
-{
-  if (isSignedOn) {
-    const molecule *_molecule = const_cast<const World &>(World::getInstance()).
-        getMolecule(MoleculeById(moleculeid));
-    if (_molecule != NULL) {
-      _molecule->signOff(this, molecule::AtomInserted);
-      _molecule->signOff(this, molecule::AtomRemoved);
-      _molecule->signOff(this, molecule::AtomMoved);
-    } else {
-      ELOG(1, "GLMoleculeObject_molecule cannot sign off, molecule with "
-          << moleculeid << " has disappeared.");
-    }
-  }
-  /*_atom->signOff(this, AtomObservable::IndexChanged);
-  _atom->signOff(this, AtomObservable::PositionChanged);
-  _atom->signOff(this, AtomObservable::ElementChanged);
-  _atom->signOff(this, AtomObservable::BondsAdded);*/
-  World::getInstance().signOff(this, World::SelectionChanged);
-}
-
-void GLMoleculeObject_molecule::activateObserver()
-{
-  // sign on as observer (obtain non-const instance before)
-  const molecule *_molecule = const_cast<const World &>(World::getInstance()).
-      getMolecule(MoleculeById(moleculeid));
+  return geo;
+}
+
+bool GLMoleculeObject_molecule::updateIsSelected() const
+{
+  return const_cast<const World &>(World::getInstance()).isMoleculeSelected(MolIndex.get());
+}
+
+GLMoleculeObject_molecule::BoundingBoxInfo GLMoleculeObject_molecule::updateBoundingBox() const
+{
+  BoundingBoxInfo info;
+  const molecule * const _molecule = getMolecule(MolIndex.get());
   if (_molecule != NULL) {
-    _molecule->signOn(this, molecule::AtomInserted);
-    _molecule->signOn(this, molecule::AtomRemoved);
-    _molecule->signOn(this, molecule::AtomMoved);
-    isSignedOn = true;
-  } else {
-    ELOG(1, "GLMoleculeObject_molecule() - added null object for not present mol id " << moleculeid);
-  }
-  /*molref->signOn(this, AtomObservable::IndexChanged);
-  molref->signOn(this, AtomObservable::PositionChanged);
-  molref->signOn(this, AtomObservable::ElementChanged);
-  molref->signOn(this, AtomObservable::BondsAdded);*/
-  World::getInstance().signOn(this, World::SelectionChanged);
-}
-
-void GLMoleculeObject_molecule::addAtomBonds(
-    const bond::ptr &_bond,
-    const GLMoleculeObject_bond::SideOfBond _side
-    )
-{
-  bool bond_present = false;
-  const BondIds ids = getBondIds(_bond, _side);
-  // check whether bond is not present already
-  bond_present = BondsinSceneMap.count(ids);
-  if (!bond_present)
-    bondInserted(_bond, _side);
-  else {
-    BondsinSceneMap[ids]->resetPosition();
-    BondsinSceneMap[ids]->resetWidth();
-  }
-}
-
-void GLMoleculeObject_molecule::addAtomBonds(
-    const atom *_atom)
-{
-  const bool atom_present = AtomsinSceneMap.count(_atom->getId());
-  const BondList &bondlist = _atom->getListOfBonds();
-  for (BondList::const_iterator bonditer = bondlist.begin();
-      (bonditer != bondlist.end()) && atom_present;
-      ++bonditer) {
-    const bond::ptr _bond = *bonditer;
-    // check if OtherAtom's sphere is already present
-    const atom *OtherAtom = _bond->GetOtherAtom(_atom);
-    const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
-    if (otheratom_present && atom_present) {
-      const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
-          GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
-      const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
-          GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
-      addAtomBonds(_bond, side);
-      addAtomBonds(_bond, otherside);
-    }
-  }
-}
-
-void GLMoleculeObject_molecule::updateBoundingBox()
-{
-  isBoundingBoxUptodate = true;
-  const molecule * const _molecule = const_cast<const World &>(World::getInstance()).
-      getMolecule(MoleculeById(moleculeid));
-  if (_molecule == NULL) {
-    ELOG(1, "GLMoleculeObject_molecule cannot updateBoundingBox, molecule with "
-        << moleculeid << " has disappeared.");
-    return;
-  }
-  Shape shape = _molecule->getBoundingSphere();
-  Vector v = shape.getCenter();
-  setPosition(QVector3D(v[0], v[1], v[2]));
-  setScale(shape.getRadius() + 0.3); // getBoundingShape() only sees atoms as points, so make the box a bit bigger
+    Shape shape = _molecule->getBoundingSphere();
+    info.position = shape.getCenter();
+    info.radius = shape.getRadius();
+  } else
+    ELOG(2, "GLMoleculeObject_molecule cannot updateBoundingBox, molecule with "
+        << MolIndex.get() << " has disappeared.");
+  return info;
+}
+
+GLMoleculeObject_molecule::atoms_t GLMoleculeObject_molecule::updateAtoms()
+{
+  const molecule * const mol = getMolecule(MolIndex.get());
+  const atomId_t id = mol->lastChanged()->getId();
+  if (mol->containsAtom(id))
+    DisplayedAtoms.insert(id);
+  else
+    DisplayedAtoms.erase(id);
+  return DisplayedAtoms;
+}
+
+moleculeId_t GLMoleculeObject_molecule::updateIndex() const
+{
+  const molecule * const mol = World::getInstance().lastChanged<molecule>();
+  if (mol != NULL) {
+    return mol->getId();
+  }
+  return (moleculeId_t)-1;
+}
+
+void GLMoleculeObject_molecule::resetTesselationHull()
+{
+  if (!TesselationHull.isValid())
+    updateMesh(createMoleculeMesh(*TesselationHull));
+}
+
+void GLMoleculeObject_molecule::resetIsSelected()
+{
+  setSelected(isSelected.get());
+}
+
+void GLMoleculeObject_molecule::resetBoundingBox()
+{
+  BoundingBoxInfo info = BoundingBox.get();
+  setPosition(QVector3D(info.position[0], info.position[1], info.position[2]));
+  setScale(info.radius + 0.3); // getBoundingSphere() only sees atoms as points, so make the box a bit bigger
+}
+
+void GLMoleculeObject_molecule::resetAtoms()
+{
+  const atoms_t atoms = PresentAtoms.get();
+  std::vector<atomId_t> InsertedAtoms;
+  std::vector<atomId_t> RemovedAtoms;
+  // obtain all newly inserted and removed atoms
+  std::set_difference(
+      atoms.begin(), atoms.end(),
+      DisplayedAtoms.begin(), DisplayedAtoms.end(),
+      std::back_inserter(InsertedAtoms));
+  std::set_difference(
+      DisplayedAtoms.begin(), DisplayedAtoms.end(),
+      atoms.begin(), atoms.end(),
+      std::back_inserter(RemovedAtoms));
+  // remove the atoms
+  std::for_each(RemovedAtoms.begin(), RemovedAtoms.end(),
+      boost::bind(&GLMoleculeObject_molecule::atomRemoved, this, _1));
+  // insert the atoms
+  std::for_each(InsertedAtoms.begin(), InsertedAtoms.end(),
+      boost::bind(&GLMoleculeObject_molecule::atomInserted, this, _1));
+
+  emit changed();
+}
+
+void GLMoleculeObject_molecule::resetIndex()
+{
+  const atomId_t newId = MolIndex.get();
+  const size_t oldId = objectId();
+  ASSERT( newId != oldId,
+      "GLMoleculeObject_molecule::resetIndex() - index "+toString(newId)+" did not change.");
+  LOG(4, "INFO: GLMoleculeObject_molecule: new index is "+toString(newId)+".");
+  setObjectId(newId);
+
+  emit indexChanged(this, oldId, newId);
 }
 
@@ -296,11 +510,10 @@
 void GLMoleculeObject_molecule::subjectKilled(Observable *publisher)
 {
-  isSignedOn = false;
+  deactivateObserver();
 }
 
 void GLMoleculeObject_molecule::recieveNotification(Observable *publisher, Notification_ptr notification)
 {
-  const molecule * const _molecule = const_cast<const World &>(World::getInstance()).
-      getMolecule(MoleculeById(moleculeid));
+  const molecule * const _molecule = getMolecule(MolIndex.get());
   if (publisher == dynamic_cast<const Observable*>(_molecule)){
     // notofication from atom
@@ -317,8 +530,7 @@
         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
   #endif
-        QMetaObject::invokeMethod(this,        // pointer to a QObject
-                                  "atomInserted",       // member name (no parameters here)
-                                  Qt::QueuedConnection,     // connection type
-                                  Q_ARG(atomId_t, _id));     // parameters
+        emit AtomInserted(_id);
+        emit TesselationHullChanged();
+        emit BoundingBoxChanged();
         break;
       }
@@ -329,8 +541,7 @@
         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been removed.";
   #endif
-        QMetaObject::invokeMethod(this,        // pointer to a QObject
-                                  "atomRemoved",       // member name (no parameters here)
-                                  Qt::QueuedConnection,     // connection type
-                                  Q_ARG(const atomId_t, _id));     // parameters
+        emit AtomRemoved(_id);
+        emit TesselationHullChanged();
+        emit BoundingBoxChanged();
         break;
       }
@@ -341,6 +552,15 @@
         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
   #endif
-        TesselationHullUptodate = false;
-        isBoundingBoxUptodate = false;
+        emit TesselationHullChanged();
+        emit BoundingBoxChanged();
+        break;
+      }
+      case molecule::IndexChanged:
+      {
+  #ifdef LOG_OBSERVER
+        const atomId_t _id = _molecule->lastChanged()->getId();
+        observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+"'s index has changed.";
+  #endif
+        emit IdChanged();
         break;
       }
@@ -357,10 +577,5 @@
     switch (notification->getChannelNo()) {
       case World::SelectionChanged:
-        if (_molecule != NULL) {
-          setSelected(World::getInstance().isSelected(_molecule));
-        } else {
-          ELOG(1, "GLMoleculeObject_molecule cannot change selection, molecule with "
-              << moleculeid << " has disappeared.");
-        }
+        emit IsSelectedChanged();
         break;
       default:
@@ -388,5 +603,5 @@
   // draw either molecule's mesh or all atoms and bonds
   if (m_visible) {
-    updateTesselationHull();
+    resetTesselationHull();
 
     painter->modelViewMatrix().push();
@@ -437,6 +652,5 @@
 
     // update bounding box prior to selection
-    if (!isBoundingBoxUptodate)
-      updateBoundingBox();
+    resetBoundingBox();
 
     painter->modelViewMatrix().push();
@@ -463,7 +677,4 @@
 {
   LOG(3, "INFO: GLMoleculeObject_molecule: Received signal atomInserted for atom "+toString(_id)+".");
-
-  TesselationHullUptodate = false;
-  isBoundingBoxUptodate = false;
 
   GLMoleculeObject_atom *atomObject = new GLMoleculeObject_atom(GLMoleculeObject::meshSphere, this, _id);
@@ -483,8 +694,7 @@
   connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
   connect (atomObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
-  connect (atomObject, SIGNAL(BondsInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)));
-  connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, int, int)), this, SLOT(changeAtomId(GLMoleculeObject_atom*, int, int)));
-
-  isBoundingBoxUptodate = false;
+  connect (atomObject, SIGNAL(BondsChanged(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond)));
+  connect (atomObject, SIGNAL(BondsRemoved(const atomId_t, const atomId_t)), this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
+  connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, const atomId_t, const atomId_t)), this, SLOT(changeAtomId(GLMoleculeObject_atom*, const atomId_t, const atomId_t)));
 
   if (m_objectId  == -1)
@@ -512,7 +722,4 @@
   LOG(3, "INFO: GLMoleculeObject_molecule: Received signal atomRemoved for atom "+toString(_id)+".");
   // bonds are removed by signal coming from ~bond
-
-  TesselationHullUptodate = false;
-  isBoundingBoxUptodate = false;
 
   if ((unsigned int)m_objectId == _id)
@@ -528,6 +735,4 @@
   delete atomObject;
 
-  isBoundingBoxUptodate = false;
-
   emit changeOccured();
 }
@@ -551,5 +756,5 @@
     if (moleculeObject == this){
       // Propagate signal.
-      emit hoverChanged(moleculeid, 0);
+      emit hoverChanged(MolIndex.get(), 0);
     }
   }
@@ -582,10 +787,13 @@
  * @param side which side of the bond (left or right)
  */
-void GLMoleculeObject_molecule::bondInserted(const bond::ptr _bond, const enum GLMoleculeObject_bond::SideOfBond _side)
-{
-  LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(*_bond)+".");
+void GLMoleculeObject_molecule::bondInserted(
+    const atomId_t _left, const atomId_t _right,
+    const enum GLMoleculeObject_bond::SideOfBond _side)
+{
+  LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(_left)
+      +toString(_right)+".");
   //LOG(4, "INFO: Currently present bonds " << BondsinSceneMap << ".");
 
-  const BondIds ids = getBondIds(_bond, _side);
+  const BondIds ids( std::make_pair(_left, _right) );
   BondNodeMap::iterator iter = BondsinSceneMap.find(ids);
   if (iter == BondsinSceneMap.end()) {
@@ -638,12 +846,4 @@
 }
 
-void GLMoleculeObject_molecule::updateTesselationHull()
-{
-  if (!TesselationHullUptodate) {
-    updateMesh(createMoleculeMesh(moleculeid, parent()));
-    TesselationHullUptodate = true;
-  }
-}
-
 std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
 {
@@ -654,9 +854,12 @@
 void GLMoleculeObject_molecule::wasClicked()
 {
-  LOG(4, "INFO: GLMoleculeObject_molecule: atom " << moleculeid << " has been clicked");
-  emit moleculeClicked(moleculeid);
-}
-
-void GLMoleculeObject_molecule::changeAtomId(GLMoleculeObject_atom *ob, int oldId, int newId)
+  LOG(4, "INFO: GLMoleculeObject_molecule: atom " << MolIndex.get() << " has been clicked");
+  emit moleculeClicked(MolIndex.get());
+}
+
+void GLMoleculeObject_molecule::changeAtomId(
+    GLMoleculeObject_atom *ob,
+    const atomId_t oldId,
+    const atomId_t newId)
 {
   LOG(3, "INFO: GLMoleculeObject_molecule - change atom id " << oldId << " to " << newId << ".");
@@ -679,2 +882,9 @@
   AtomsinSceneMap.insert( make_pair(newId, ob) );
 }
+
+const molecule * const GLMoleculeObject_molecule::getMolecule(const moleculeId_t _id)
+{
+  const molecule * const mol = const_cast<const World &>(World::getInstance()).
+      getMolecule(MoleculeById(_id));
+  return mol;
+}
Index: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp
===================================================================
--- src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp	(revision 009e2e2d372810a555a452769338209c68591479)
+++ src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp	(revision 6c16a02ecd71315045f7522510b3807789050e4b)
@@ -16,5 +16,9 @@
 #include "GLMoleculeObject.hpp"
 
+#include <Qt3D/qgeometrydata.h>
+
+#include "CodePatterns/Cacheable.hpp"
 #include "CodePatterns/Observer/Observer.hpp"
+#include "CodePatterns/ObservedValue.hpp"
 
 #include "GLMoleculeObject_bond.hpp"
@@ -34,6 +38,4 @@
   virtual ~GLMoleculeObject_molecule();
 
-  void updateBoundingBox();
-
   // Observer functions
   void update(Observable *publisher);
@@ -51,7 +53,4 @@
       const enum GLMoleculeObject_bond::SideOfBond side);
 
-  void selected(const bool _isSelected)
-  { isSelected = _isSelected; }
-
 signals:
   void changed();
@@ -59,6 +58,13 @@
   void hoverChanged(const atomId_t);
   void hoverChanged(const moleculeId_t, int);
+  void indexChanged(GLMoleculeObject_molecule *, const moleculeId_t, const moleculeId_t);
   void atomClicked(atomId_t no);
   void moleculeClicked(moleculeId_t no);
+  void TesselationHullChanged();
+  void BoundingBoxChanged();
+  void IsSelectedChanged();
+  void AtomInserted(const atomId_t _id);
+  void AtomRemoved(const atomId_t _id);
+  void IdChanged();
 
 private slots:
@@ -69,12 +75,22 @@
   void atomInserted(const atomId_t _id);
   void atomRemoved(const atomId_t _id);
-  void bondInserted(const bond::ptr _bond, const GLMoleculeObject_bond::SideOfBond side);
+  void bondInserted(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond side);
   void bondRemoved(const atomId_t leftnr, const atomId_t rightnr);
   void hoverChangedSignalled(GLMoleculeObject *ob);
-  void changeAtomId(GLMoleculeObject_atom *, int, int);
+  void changeAtomId(GLMoleculeObject_atom *, const atomId_t, const atomId_t);
 
   void setVisible(bool value);
 
   void activateObserver();
+  void deactivateObserver();
+
+  void resetTesselationHull();
+  void resetIsSelected();
+  void resetBoundingBox();
+  void resetAtoms();
+  void resetIndex();
+
+private:
+  static const molecule * const getMolecule(const moleculeId_t _id);
 
 private:
@@ -85,16 +101,65 @@
   void addAtomBonds(const atom *_atom);
 
-  void updateTesselationHull();
+  //!> typedef for the internal set of atoms
+  typedef std::set<atomId_t> atoms_t;
 
-  //!> states whether selection box is additionally drawn or not
-  bool isSelected;
-  bool isBoundingBoxUptodate;
+  /** Structure for the required information on the bounding box.
+   *
+   */
+  struct BoundingBoxInfo {
+    //!> position of center
+    Vector position;
+    //!> radius of sphere
+    double radius;
+  };
 
-  //!> whether we are signed on to the associated molecule
-  bool isSignedOn;
+  /** Structure for the required information on the tesselation hull.
+   *
+   */
+  struct TesselationHullInfo {
+  };
 
-  const moleculeId_t moleculeid;
+  QGeometryData updateTesselationHull() const;
+  bool updateIsSelected() const;
+  BoundingBoxInfo updateBoundingBox() const;
+  atoms_t updateAtoms();
+  moleculeId_t updateIndex() const;
 
-  bool TesselationHullUptodate;
+  //!> the Observable we are signed on, also indicates whether we are sign on (not NULL)
+  const Observable * owner;
+
+  //!> internal variable for caching molecule ref in cstor
+  const molecule * const molref;
+
+  //!> list of channels when contained atoms needs to update
+  static const Observable::channels_t AtomsChannels;
+  //!> list of channels when tesselation hull needs to update
+  static const Observable::channels_t HullChannels;
+  //!> list of channels when selection status needs to update
+  static const Observable::channels_t SelectionStatusChannels;
+  //!> list of channels when bounding box needs to update
+  static const Observable::channels_t BoundingBoxChannels;
+  //!> list of channels when the index needs to update
+  static const Observable::channels_t IndexChannels;
+
+  boost::function<moleculeId_t ()> MolIndexUpdater;
+  boost::function<QGeometryData ()> TesselationHullUpdater;
+  boost::function<bool ()> IsSelectedUpdater;
+  boost::function<BoundingBoxInfo ()> BoundingBoxUpdater;
+  boost::function<atoms_t ()> PresentAtomsUpdater;
+
+  //!> contains the current molecule index
+  ObservedValue<moleculeId_t> MolIndex;
+  //!> contains current version of the tesselation hull on request
+  Cacheable<QGeometryData> TesselationHull;
+  //!> contains newest version of the selection status
+  ObservedValue<bool> isSelected;
+  //!> contains newest version of the bounding box on request
+  ObservedValue<BoundingBoxInfo> BoundingBox;
+  //!> contains the current live set of atoms for the molecule
+  ObservedValue<atoms_t> PresentAtoms;
+
+  //!> contains the set of atoms displayed
+  atoms_t DisplayedAtoms;
 
   typedef std::map< atomId_t, GLMoleculeObject_atom* > AtomNodeMap;
