Index: src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp
===================================================================
--- src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp	(revision f91ef6007a43260154696025a6213300e1067126)
+++ src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp	(revision 96f14ae4f021b1976486ad5658a68c30645c7467)
@@ -101,4 +101,8 @@
   connect(board, SIGNAL(atomRemoved(ObservedValue_Index_t)),
       this, SLOT(atomRemoved(ObservedValue_Index_t)));
+  connect(board, SIGNAL(bondInserted(QtObservedBond::ptr)),
+      this, SLOT(bondInserted(QtObservedBond::ptr)));
+  connect(board, SIGNAL(bondRemoved(ObservedValue_Index_t)),
+      this, SLOT(bondRemoved(ObservedValue_Index_t)));
   connect(this, SIGNAL(insertMolecule(QtObservedMolecule::ptr)),
       this, SLOT(moleculeInserted(QtObservedMolecule::ptr)) );
@@ -182,4 +186,78 @@
       +" is not present in QtObservedAtomMap.");
   QtObservedAtomMap.erase(eraseiter);
+}
+
+/** Prepares insertion of a bond.
+ *
+ * This is called before the insertion into a molecule and thus before the
+ * insertion into the scene.
+ *
+ * @param _bond bond to insert
+ */
+void GLWorldScene::bondInserted(QtObservedBond::ptr _bond)
+{
+  const ObservedValue_Index_t bondid = _bond->getIndex();
+  ASSERT( QtObservedBondMap.find(bondid) == QtObservedBondMap.end(),
+      "GLWorldScene::BondInserted() - bond with id "+toString(_bond->getBondIndex())
+      +" is already present in QtObservedBondMap.");
+  QtObservedBondMap[bondid] = _bond;
+
+  // assign to its molecule if present
+  const moleculeId_t molid = _bond->getMoleculeIndex();
+  if (molid != (moleculeId_t)-1) {
+    QtObservedMolecule::ptr mol = board->getObservedMolecule(molid);
+    emit moleculesBondInserted(_bond, mol.get());
+  } else {
+    // watch bond till it has a molecule
+    connect( _bond.get(), SIGNAL(moleculeIndexChanged(moleculeId_t,moleculeId_t)),
+        this, SLOT(bondsMoleculeChanged(moleculeId_t, moleculeId_t)));
+  }
+}
+
+/** Handle change of molecule from initial none.
+ *
+ */
+void GLWorldScene::bondsMoleculeChanged(moleculeId_t _oldid, moleculeId_t _newid)
+{
+  ASSERT( _oldid == (moleculeId_t)-1,
+      "GLWorldScene::bondsMoleculeChanged() - got true index change from "
+      +toString(_oldid)+" to "+toString(_newid)+" and not just added to mol.");
+  QtObservedBond* bondref = static_cast<QtObservedBond*>(sender());
+
+  // disconnect from further molecule changes
+  disconnect( bondref, SIGNAL(moleculeIndexChanged(moleculeId_t,moleculeId_t)),
+      this, SLOT(bondsMoleculeChanged(moleculeId_t, moleculeId_t)));
+
+  // add it to its molecule
+  QtObservedMolecule::ptr mol = board->getObservedMolecule(_newid);
+  emit moleculesBondInserted(bondref->getRef(), mol.get());
+}
+
+
+/** Removes an general bond.
+ *
+ * This is called when the bond has been removed from the molecule.
+ *
+ * @param _bond bond to remove
+ */
+void GLWorldScene::bondRemoved(ObservedValue_Index_t _bondid)
+{
+  const QtObservedBondMap_t::iterator eraseiter = QtObservedBondMap.find(_bondid);
+  ASSERT( eraseiter != QtObservedBondMap.end(),
+      "GLWorldScene::BondRemoved() - bond with id "+toString(_bondid)
+      +" is not present in QtObservedBondMap.");
+  QtObservedBond::ptr bondref = eraseiter->second;
+
+  // tell its assigned molecule if present
+  const moleculeId_t molid = bondref->getMoleculeIndex();
+  if (molid != (moleculeId_t)-1) {
+    QtObservedMolecule::ptr mol = board->getObservedMolecule(molid);
+    emit moleculesBondRemoved(_bondid, mol.get());
+  } else {
+    // it might have still been waiting for a molecule assignment
+    disconnect( bondref.get(), SIGNAL(moleculeIndexChanged(moleculeId_t,moleculeId_t)),
+        this, SLOT(bondsMoleculeChanged(moleculeId_t, moleculeId_t)));
+  }
+  QtObservedBondMap.erase(eraseiter);
 }
 
@@ -329,4 +407,123 @@
 }
 
+/** Inserts an bond into the scene when molecule is present.
+ *
+ * @param _bond bond to insert
+ */
+void GLWorldScene::moleculesBondInserted(QtObservedBond::ptr _bond, QtObservedMolecule * _mol)
+{
+  const ObservedValue_Index_t bondid = _bond->getIndex();
+  LOG(3, "INFO: GLWorldScene: Received signal bondInserted for bond " << _bond->getBondIndex());
+  const ObservedValue_Index_t molid = _mol->getIndex();
+
+  // check of molecule is already present
+  boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
+  const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid);
+  if (moliter != MoleculesinSceneMap.end()) {
+    // check that it is the right molecule
+    QtObservedMolecule::ptr &checkmol = moliter->second->ObservedMolecule;
+    ASSERT( checkmol.get() == _mol,
+        "GLWorldScene::moleculesBondInserted() - claimed and present molecule differ.");
+    LOG(3, "INFO: GLWorldScene: Sending signal moleculesBondInserted for bond "
+        << _bond->getBondIndex());
+    QMetaObject::invokeMethod(moliter->second,        // pointer to a QObject
+                              "bondInserted",       // member name (no parameters here)
+                              Qt::QueuedConnection,     // connection type
+                              Q_ARG(QtObservedBond::ptr, _bond));     // parameters
+  } else {
+#ifndef NDEBUG
+    const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
+    ASSERT( removedmoliter != RemovedMolecules.end(),
+          "GLWorldScene::moleculesBondInserted() - would need to send bondInserted to already removed molecule.");
+#endif
+    boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
+    // only record missed state for molecule if (still) present but not instantiated
+    if (QtObservedMoleculeMap.count(molid)) {
+      // store signal for when it is instantiated
+      if (MoleculeMissedStateMap.count(molid) == 0)
+        MoleculeMissedStateMap.insert( std::make_pair(molid ,StateChangeMap_t()) );
+      MoleculeMissedStateMap[molid].insert( std::make_pair(bondid, bondInsertedState) );
+      ASSERT( QtObservedBondMap[bondid] == _bond,
+          "GLWorldScene::moleculesBondInserted() - bond "+toString(bondid)
+          +" inserted in molecule "+toString(_mol->getMolIndex())
+          +" which does not match bond in QtObservedBondMap.");
+      LOG(3, "INFO: GLWorldScene: Placing bondInserted for bond " << _bond->getBondIndex()
+           << " and molecule " << _mol->getMolIndex() << " into missed state map.");
+    }
+  }
+}
+
+/** Removes an bond into the scene before molecule is present.
+ *
+ * @param _bondid bond to remove
+ */
+void GLWorldScene::moleculesBondRemoved(ObservedValue_Index_t _bondid, QtObservedMolecule * _mol)
+{
+  LOG(3, "INFO: GLWorldScene: Received signal bondRemoved for bond "+toString(_bondid)+".");
+
+  const ObservedValue_Index_t molid = _mol->getIndex();
+  // check of molecule is already present
+  boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
+  const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid);
+  if (moliter != MoleculesinSceneMap.end()) {
+    const QtObservedMolecule::ptr &checkmol = moliter->second->ObservedMolecule;
+    if (checkmol.get() == _mol) {
+      LOG(3, "INFO: GLWorldScene: Sending signal moleculesBondRemoved for bond "+toString(_bondid)+".");
+      QMetaObject::invokeMethod(moliter->second,        // pointer to a QObject
+                                "bondRemoved",       // member name (no parameters here)
+                                Qt::QueuedConnection,     // connection type
+                                Q_ARG(ObservedValue_Index_t, _bondid));     // parameters
+    } else {
+      // relay bondRemoved to GLMoleculeObject_molecule in RemovedMolecules
+      LOG(3, "INFO: GLWorldScene: Sending signal moleculesBondRemoved for bond "+toString(_bondid)
+          +" to molecule in RemovedMolecules.");
+      const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
+      ASSERT( removedmoliter != RemovedMolecules.end(),
+          "GLWorldScene::moleculesBondRemoved() - signal from old molecule "
+          +toString(molid)+", but not present in RemovedMolecules");
+#ifndef NDEBUG
+      const QtObservedMolecule::ptr &othercheckmol = removedmoliter->second->ObservedMolecule;
+      ASSERT( othercheckmol.get() == _mol,
+          "GLWorldScene::moleculesBondRemoved() - signal from old molecule "
+          +toString(molid)+", but different one "+toString(othercheckmol)
+          +" present in RemovedMolecules.");
+#endif
+      QMetaObject::invokeMethod(removedmoliter->second,        // pointer to a QObject
+                                "bondRemoved",       // member name (no parameters here)
+                                Qt::QueuedConnection,     // connection type
+                                Q_ARG(ObservedValue_Index_t, _bondid));     // parameters
+    }
+  } else {
+    const RemovedMoleculesMap_t::iterator removedmoliter = RemovedMolecules.find(_mol);
+    if (removedmoliter != RemovedMolecules.end()) {
+      ASSERT( removedmoliter != RemovedMolecules.end(),
+          "GLWorldScene::moleculesBondRemoved() - signal from old molecule "
+          +toString(molid)+", but not present in RemovedMolecules");
+#ifndef NDEBUG
+      const QtObservedMolecule::ptr &othercheckmol = removedmoliter->second->ObservedMolecule;
+      ASSERT( othercheckmol.get() == _mol,
+          "GLWorldScene::moleculesBondRemoved() - signal from old molecule "
+          +toString(molid)+", but different one "+toString(othercheckmol)
+          +" present in RemovedMolecules.");
+#endif
+      QMetaObject::invokeMethod(removedmoliter->second,        // pointer to a QObject
+                                "bondRemoved",       // member name (no parameters here)
+                                Qt::QueuedConnection,     // connection type
+                                Q_ARG(ObservedValue_Index_t, _bondid));     // parameters
+    } else {
+      boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
+      // only record missed state for molecule if (still) present but not instantiated
+      if (QtObservedMoleculeMap.count(molid)) {
+        // store signal for when it is instantiated
+        if (MoleculeMissedStateMap.count(molid) == 0)
+          MoleculeMissedStateMap.insert( std::make_pair(molid, StateChangeMap_t()) );
+        MoleculeMissedStateMap[molid].insert( std::make_pair(_bondid, bondRemovedState) );
+        LOG(3, "INFO: GLWorldScene: Placing bondRemoved for bond " << _bondid
+             << " and molecule " << molid << " into missed state map.");
+      }
+    }
+  }
+}
+
 void GLWorldScene::moleculeSignOn(QtObservedMolecule::ptr _mol)
 {
@@ -418,18 +615,40 @@
             stateiter != rangeiter.second; ++stateiter)
           ++StateChangeAmounts[stateiter->second];
-        ASSERT( StateChangeAmounts[atomInsertedState] >= StateChangeAmounts[atomRemovedState],
-            "GLWorldScene::moleculeInserted() - more atomRemoved states "
-            +toString(StateChangeAmounts[atomRemovedState])+" than atomInserted "
-            +toString(StateChangeAmounts[atomInsertedState])+" for atom "+toString(iter->first));
-        if (StateChangeAmounts[atomInsertedState] > StateChangeAmounts[atomRemovedState]) {
-          LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
-          QMetaObject::invokeMethod(molObject,        // pointer to a QObject
-                                    "atomInserted",       // member name (no parameters here)
-                                    Qt::QueuedConnection,     // connection type
-                                    Q_ARG(QtObservedAtom::ptr, QtObservedAtomMap[iter->first]));     // parameters
-        } else {
-          LOG(1, "INFO: Atom " << iter->first << " has been inserted and removed already.");
+        // is it an atom?
+        if ((StateChangeAmounts[atomInsertedState] + StateChangeAmounts[atomRemovedState]) != 0) {
+          ASSERT( StateChangeAmounts[atomInsertedState] >= StateChangeAmounts[atomRemovedState],
+              "GLWorldScene::moleculeInserted() - more atomRemoved states "
+              +toString(StateChangeAmounts[atomRemovedState])+" than atomInserted "
+              +toString(StateChangeAmounts[atomInsertedState])+" for atom "+toString(iter->first));
+          if (StateChangeAmounts[atomInsertedState] > StateChangeAmounts[atomRemovedState]) {
+            LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
+            QMetaObject::invokeMethod(molObject,        // pointer to a QObject
+                                      "atomInserted",       // member name (no parameters here)
+                                      Qt::QueuedConnection,     // connection type
+                                      Q_ARG(QtObservedAtom::ptr, QtObservedAtomMap[iter->first]));     // parameters
+          } else {
+            LOG(1, "INFO: Atom " << iter->first << " has been inserted and removed already.");
+          }
         }
-        // removed all state changes for this atom
+        // or is it a bond?
+        if ((StateChangeAmounts[bondInsertedState] + StateChangeAmounts[bondInsertedState]) != 0) {
+          ASSERT( StateChangeAmounts[bondInsertedState] >= StateChangeAmounts[bondRemovedState],
+              "GLWorldScene::moleculeInserted() - more bondRemoved states "
+              +toString(StateChangeAmounts[bondRemovedState])+" than bondInserted "
+              +toString(StateChangeAmounts[bondInsertedState])+" for bond "+toString(iter->first));
+          if (StateChangeAmounts[bondInsertedState] > StateChangeAmounts[bondRemovedState]) {
+            LOG(1, "INFO: invoking bondInserted for bond " << iter->first);
+            QMetaObject::invokeMethod(molObject,        // pointer to a QObject
+                                      "bondInserted",       // member name (no parameters here)
+                                      Qt::QueuedConnection,     // connection type
+                                      Q_ARG(QtObservedBond::ptr, QtObservedBondMap[iter->first]));     // parameters
+          } else {
+            LOG(1, "INFO: Bond " << iter->first << " has been inserted and removed already.");
+          }
+        }
+        ASSERT( (StateChangeAmounts[bondInsertedState] + StateChangeAmounts[bondInsertedState]
+            + StateChangeAmounts[atomInsertedState] + StateChangeAmounts[atomRemovedState]) != 0,
+            "GLWorldScene::moleculeInserted() - state with no changes for "+toString(iter->first));
+        // removed all state changes for this atom/bond
         MoleculeMissedStateMap[molid].erase(rangeiter.first, rangeiter.second);
       } else {
@@ -450,4 +669,18 @@
             break;
           }
+          case bondRemovedState:
+            ASSERT( 0,
+                "GLWorldScene::moleculeInserted() - bondRemoved state without bondInserted for bond "
+                +toString(iter->first));
+            break;
+          case bondInsertedState:
+          {
+            LOG(1, "INFO: invoking bondInserted for bond " << iter->first);
+            QMetaObject::invokeMethod(molObject,        // pointer to a QObject
+                                      "bondInserted",       // member name (no parameters here)
+                                      Qt::QueuedConnection,     // connection type
+                                      Q_ARG(QtObservedBond::ptr, QtObservedBondMap[iter->first]));     // parameters
+            break;
+          }
           default:
             ASSERT( 0,
@@ -455,5 +688,5 @@
             break;
         }
-        // removed state changes for this atom
+        // removed state changes for this atom/bond
         MoleculeMissedStateMap[molid].erase(iter);
       }
