Changeset 59f1bc
- Timestamp:
- Feb 14, 2016, 12:34:29 PM (9 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- 23221f
- Parents:
- 03e69e
- git-author:
- Frederik Heber <heber@…> (01/06/16 08:36:58)
- git-committer:
- Frederik Heber <heber@…> (02/14/16 12:34:29)
- Location:
- src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp
r03e69e r59f1bc 126 126 connect (ObservedMolecule.get(), SIGNAL(indexChanged(const moleculeId_t, const moleculeId_t)), 127 127 this, SLOT(resetIndex(const moleculeId_t, const moleculeId_t))); 128 connect (ObservedMolecule.get(), SIGNAL(atomInserted(QtObservedAtom::ptr)), 129 this, SLOT(atomInserted(QtObservedAtom::ptr)) ); 130 connect (ObservedMolecule.get(), SIGNAL(atomRemoved(const atomId_t)), 131 this, SLOT(atomRemoved(const atomId_t)) ); 128 /// these are channeled through GLWorldScene instead to ensure synchronicity 129 // connect (ObservedMolecule.get(), SIGNAL(atomInserted(QtObservedAtom::ptr)), 130 // this, SLOT(atomInserted(QtObservedAtom::ptr)) ); 131 // connect (ObservedMolecule.get(), SIGNAL(atomRemoved(const atomId_t)), 132 // this, SLOT(atomRemoved(const atomId_t)) ); 132 133 connect (ObservedMolecule.get(), SIGNAL(selectedChanged()), this, SLOT(resetSelected())); 133 134 -
src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp
r03e69e r59f1bc 94 94 } 95 95 connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)), 96 this, SLOT(moleculeSignOn(QtObservedMolecule::ptr)) );96 this, SLOT(moleculeSignOn(QtObservedMolecule::ptr)), Qt::DirectConnection); 97 97 connect(board, SIGNAL(moleculeRemoved(const moleculeId_t)), 98 this, SLOT(moleculeSignOff(const moleculeId_t)) );98 this, SLOT(moleculeSignOff(const moleculeId_t)), Qt::DirectConnection); 99 99 connect(board, SIGNAL(moleculeIndexChanged(const moleculeId_t, const moleculeId_t)), 100 100 this, SLOT(moleculeIndexChanged(const moleculeId_t, const moleculeId_t))); 101 connect(board, SIGNAL(atomInserted(QtObservedAtom::ptr)), 102 this, SLOT(atomInserted(QtObservedAtom::ptr))); 103 connect(board, SIGNAL(atomRemoved(const atomId_t)), 104 this, SLOT(atomRemoved(const atomId_t))); 101 105 connect(this, SIGNAL(insertMolecule(QtObservedMolecule::ptr)), 102 106 this, SLOT(moleculeInserted(QtObservedMolecule::ptr)) ); … … 151 155 } 152 156 153 /** Inserts an atom into the scene before molecule is present. 154 * 155 * @param _molid molecule to insert atom for 156 * @param _atomid atom to insert 157 /** Prepares insertion of a general atom. 158 * 159 * This is called before the insertion into a molecule and thus before the 160 * insertion into the scene. 161 * 162 * @param _atom atom to insert 157 163 */ 158 164 void GLWorldScene::atomInserted(QtObservedAtom::ptr _atom) 159 165 { 160 ASSERT (_atom, 161 "GLWorldScene::moleculeInserted() - received shared_ptr for atom is empty?"); 166 const atomId_t atomid = _atom->getAtomIndex(); 167 ASSERT( QtObservedAtomMap.find(atomid) == QtObservedAtomMap.end(), 168 "GLWorldScene::AtomInserted() - atom with id "+toString(atomid) 169 +" is already present in QtObservedAtomMap."); 170 QtObservedAtomMap[atomid] = _atom; 171 connect(_atom.get(), SIGNAL(indexChanged(const atomId_t,const atomId_t)), 172 this, SLOT(atomIndexChanged(const atomId_t,const atomId_t)) ); 173 } 174 175 /** Removes an general atom. 176 * 177 * This is called when the atom has been removed from the molecule. 178 * 179 * @param _atom atom to remove 180 */ 181 void GLWorldScene::atomRemoved(const atomId_t _atomid) 182 { 183 const QtObservedAtomMap_t::iterator eraseiter = QtObservedAtomMap.find(_atomid); 184 ASSERT( eraseiter != QtObservedAtomMap.end(), 185 "GLWorldScene::AtomRemoved() - atom with id "+toString(_atomid) 186 +" is not present in QtObservedAtomMap."); 187 disconnect(eraseiter->second.get(), SIGNAL(indexChanged(const atomId_t,const atomId_t)), 188 this, SLOT(atomIndexChanged(const atomId_t,const atomId_t)) ); 189 QtObservedAtomMap.erase(eraseiter); 190 } 191 192 /** Inserts an atom into the scene when molecule is present. 193 * 194 * @param _atom atom to insert 195 */ 196 void GLWorldScene::moleculesAtomInserted(QtObservedAtom::ptr _atom) 197 { 162 198 const atomId_t atomid = _atom->getAtomIndex(); 163 199 const atomId_t molid = _atom->getAtomMoleculeIndex(); … … 165 201 166 202 // check of molecule is already present 203 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex); 167 204 MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid); 168 205 if (moliter != MoleculesinSceneMap.end()) { 169 // no action, is also caught via QtObservedMolecule by GLMoleculeObject_molecule 206 LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomInserted for atom "+toString(atomid)+"."); 207 QMetaObject::invokeMethod(moliter->second, // pointer to a QObject 208 "atomInserted", // member name (no parameters here) 209 Qt::QueuedConnection, // connection type 210 Q_ARG(QtObservedAtom::ptr, _atom)); // parameters 170 211 } else { 171 // store signal for when it is instantiated 172 if (MoleculeMissedStateMap.count(molid) == 0) 173 MoleculeMissedStateMap.insert( std::make_pair(molid ,StateChangeMap_t()) ); 174 MoleculeMissedStateMap[molid].insert( std::make_pair(atomid, atomInsertedState) ); 175 QtObservedAtomMap[atomid] = _atom; 176 connect(_atom.get(), SIGNAL(indexChanged(const atomId_t,const atomId_t)), 177 this, SLOT(atomIndexChanged(const atomId_t,const atomId_t)) ); 178 LOG(3, "INFO: GLWorldScene: Placing atomInserted for atom " << atomid 179 << " and molecule " << molid << " into missed state map."); 212 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex); 213 // only record missed state for molecule if (still) present but not instantiated 214 if (QtObservedMoleculeMap.count(molid)) { 215 // store signal for when it is instantiated 216 if (MoleculeMissedStateMap.count(molid) == 0) 217 MoleculeMissedStateMap.insert( std::make_pair(molid ,StateChangeMap_t()) ); 218 MoleculeMissedStateMap[molid].insert( std::make_pair(atomid, atomInsertedState) ); 219 ASSERT( QtObservedAtomMap[atomid] == _atom, 220 "GLWorldScene::moleculesAtomInserted() - atom "+toString(atomid) 221 +" inserted in molecule "+toString(molid) 222 +" which does not match atom in QtObservedAtomMap."); 223 LOG(3, "INFO: GLWorldScene: Placing atomInserted for atom " << atomid 224 << " and molecule " << molid << " into missed state map."); 225 } 180 226 } 181 227 } … … 183 229 /** Removes an atom into the scene before molecule is present. 184 230 * 185 * @param _molid molecule to insert atom for 186 * @param _atomid atom to insert 187 */ 188 void GLWorldScene::atomRemoved(const atomId_t _atomid) 189 { 190 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex); 191 231 * @param _atomid atom to remove 232 */ 233 void GLWorldScene::moleculesAtomRemoved(const atomId_t _atomid) 234 { 192 235 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+"."); 193 236 … … 197 240 const moleculeId_t molid = atom->getAtomMoleculeIndex(); 198 241 // check of molecule is already present 242 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex); 199 243 MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(molid); 200 244 if (moliter != MoleculesinSceneMap.end()) { 201 // no action, is also caught via QtObservedMolecule by GLMoleculeObject_molecule 245 LOG(3, "INFO: GLWorldScene: Sending signal moleculesAtomRemoved for atom "+toString(_atomid)+"."); 246 QMetaObject::invokeMethod(moliter->second, // pointer to a QObject 247 "atomRemoved", // member name (no parameters here) 248 Qt::QueuedConnection, // connection type 249 Q_ARG(const atomId_t, _atomid)); // parameters 202 250 } else { 203 // store signal for when it is instantiated 204 if (MoleculeMissedStateMap.count(molid) == 0) 205 MoleculeMissedStateMap.insert( std::make_pair(molid ,StateChangeMap_t()) ); 206 MoleculeMissedStateMap[molid].insert( std::make_pair(_atomid, atomRemovedState) ); 207 LOG(3, "INFO: GLWorldScene: Placing atomRemoved for atom " << _atomid 208 << " and molecule " << molid << " into missed state map."); 251 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex); 252 // only record missed state for molecule if (still) present but not instantiated 253 if (QtObservedMoleculeMap.count(molid)) { 254 // store signal for when it is instantiated 255 if (MoleculeMissedStateMap.count(molid) == 0) 256 MoleculeMissedStateMap.insert( std::make_pair(molid, StateChangeMap_t()) ); 257 MoleculeMissedStateMap[molid].insert( std::make_pair(_atomid, atomRemovedState) ); 258 LOG(3, "INFO: GLWorldScene: Placing atomRemoved for atom " << _atomid 259 << " and molecule " << molid << " into missed state map."); 260 } 209 261 } 210 262 } … … 216 268 // source as GLMoleculeObject_molecule would 217 269 connect(_mol.get(), SIGNAL(atomInserted(QtObservedAtom::ptr)), 218 this, SLOT( atomInserted(QtObservedAtom::ptr)) );270 this, SLOT(moleculesAtomInserted(QtObservedAtom::ptr)) ); 219 271 connect(_mol.get(), SIGNAL(atomRemoved(const atomId_t)), 220 this, SLOT( atomRemoved(const atomId_t)) );272 this, SLOT(moleculesAtomRemoved(const atomId_t)) ); 221 273 const moleculeId_t molid = _mol->getMolIndex(); 222 QtObservedMoleculeMap.insert( std::make_pair(molid, _mol) ); 274 ASSERT( QtObservedMoleculeMap.find(molid) == QtObservedMoleculeMap.end(), 275 "GLWorldScene::moleculeSignOn() - molecule with id "+toString(molid) 276 +" is already present in QtObservedMoleculeMap."); 277 QtObservedMoleculeMap[molid] = _mol; 278 connect(_mol.get(), SIGNAL(indexChanged(const moleculeId_t,const moleculeId_t)), 279 this, SLOT(moleculeIndexChanged(const moleculeId_t,const moleculeId_t)) ); 223 280 224 281 LOG(3, "INFO: GLWorldScene: Received signal moleculeSignOn for molecule "+toString(molid)+"."); … … 229 286 void GLWorldScene::moleculeSignOff(const moleculeId_t _id) 230 287 { 231 ASSERT( QtObservedMoleculeMap.count(_id), 288 const QtObservedMoleculeMap_t::iterator eraseiter = QtObservedMoleculeMap.find(_id); 289 ASSERT( eraseiter != QtObservedMoleculeMap.end(), 232 290 "GLWorldScene::moleculeSignOff() - cannot find id "+toString(_id)+" in map."); 233 const QtObservedMolecule::ptr mol = QtObservedMoleculeMap[_id];234 mol->disconnect(this);235 QtObservedMoleculeMap.erase( _id);291 disconnect(eraseiter->second.get(), SIGNAL(indexChanged(const moleculeId_t,const moleculeId_t)), 292 this, SLOT(moleculeIndexChanged(const moleculeId_t,const moleculeId_t)) ); 293 QtObservedMoleculeMap.erase(eraseiter); 236 294 237 295 LOG(3, "INFO: GLWorldScene: Received signal moleculeSignOff for molecule "+toString(_id)+"."); … … 256 314 ASSERT( iter == MoleculesinSceneMap.end(), 257 315 "GLWorldScene::moleculeInserted() - molecule's id "+toString(molid)+" already present."); 258 259 // check whether molecule is still present260 if (RemovalMolecules.count(molid) != 0) {261 RemovalMolecules.erase(molid);262 return;263 }264 316 265 317 // add new object … … 325 377 { 326 378 LOG(1, "INFO: invoking atomInserted for atom " << iter->first); 327 const QtObservedAtom::ptr walker = QtObservedAtomMap[iter->first];328 379 QMetaObject::invokeMethod(molObject, // pointer to a QObject 329 380 "atomInserted", // member name (no parameters here) … … 374 425 375 426 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id); 376 if ( iter == MoleculesinSceneMap.end()) { 377 RemovalMolecules.insert(_id); 378 } else { 427 if ( iter != MoleculesinSceneMap.end()) { 379 428 LOG(1, "DEBUG: Removing GLMoleculeObject_molecule to id " << _id); 380 429 GLMoleculeObject_molecule *molObject = iter->second; … … 405 454 void GLWorldScene::moleculeIndexChanged(const moleculeId_t _oldid, const moleculeId_t _newid) 406 455 { 407 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_oldid); 408 if ( iter == MoleculesinSceneMap.end()) { 409 RemovalMolecule_t::iterator removeiter = 410 RemovalMolecules.find(_oldid); 411 ASSERT( removeiter != RemovalMolecules.end(), 412 "GLWorldScene::moleculeIndexChanged() - cannot find id "+toString(_oldid)+" in any map."); 413 RemovalMolecules.erase(removeiter); 414 RemovalMolecules.insert(_newid); 415 if (QtObservedMoleculeMap.count(_oldid)) { 416 const QtObservedMolecule::ptr mol = QtObservedMoleculeMap[_oldid]; 417 QtObservedMoleculeMap.erase(_oldid); 418 QtObservedMoleculeMap.insert( std::make_pair(_newid, mol) ); 456 { 457 QtObservedMoleculeMap_t::iterator const olditer = QtObservedMoleculeMap.find(_oldid); 458 ASSERT ( olditer != QtObservedMoleculeMap.end(), 459 "GLWorldScene::moleculeIndexChanged() - molecule " 460 +toString(_oldid)+" not present in QtObservedMoleculeMap."); 461 #ifndef NDEBUG 462 QtObservedMoleculeMap_t::iterator const newiter = QtObservedMoleculeMap.find(_newid); 463 ASSERT ( newiter == QtObservedMoleculeMap.end(), 464 "GLWorldScene::moleculeIndexChanged() - molecule " 465 +toString(_newid)+" already present in QtObservedMoleculeMap."); 466 #endif 467 const QtObservedMolecule::ptr mol = olditer->second; 468 QtObservedMoleculeMap.erase(olditer); 469 QtObservedMoleculeMap[_newid] = mol; 470 } 471 { 472 MoleculeNodeMap::iterator const olditer = MoleculesinSceneMap.find(_oldid); 473 if ( olditer != MoleculesinSceneMap.end()) { 474 #ifndef NDEBUG 475 MoleculeNodeMap::iterator const newiter = MoleculesinSceneMap.find(_newid); 476 ASSERT ( newiter == MoleculesinSceneMap.end(), 477 "GLWorldScene::moleculeIndexChanged() - molecule " 478 +toString(_newid)+" already present in MoleculesinSceneMap."); 479 #endif 480 LOG(1, "DEBUG: Changing GLMoleculeObject_molecule from " << _oldid << " to id " << _newid); 481 GLMoleculeObject_molecule* const molObject = olditer->second; 482 MoleculesinSceneMap.erase(olditer); 483 MoleculesinSceneMap[_newid] = molObject; 419 484 } 420 } else {421 LOG(1, "DEBUG: Changing GLMoleculeObject_molecule from " << _oldid << " to id " << _newid);422 GLMoleculeObject_molecule* molObject = iter->second;423 MoleculesinSceneMap.erase(iter);424 MoleculesinSceneMap.insert(425 std::make_pair( _newid, molObject) );426 485 } 427 486 } -
src/UIElements/Views/Qt4/Qt3D/GLWorldScene.hpp
r03e69e r59f1bc 95 95 void moleculeSignOn(QtObservedMolecule::ptr); 96 96 void moleculeIndexChanged(const moleculeId_t _oldid, const moleculeId_t _newid); 97 void moleculesAtomRemoved(const atomId_t _atomid); 98 void moleculesAtomInserted(QtObservedAtom::ptr); 97 99 void atomRemoved(const atomId_t _atomid); 98 100 void atomInserted(QtObservedAtom::ptr); … … 109 111 110 112 private: 111 112 typedef std::set<moleculeId_t> RemovalMolecule_t;113 //!> list of molecule ids whose moleculeRemoved we have received but who have not been inserted yet114 RemovalMolecule_t RemovalMolecules;115 113 116 114 typedef std::map< moleculeId_t , GLMoleculeObject_molecule* > MoleculeNodeMap; … … 137 135 //!> map to contain all QtObservedMolecule that have not been instantiated so far 138 136 QtObservedMoleculeMap_t QtObservedMoleculeMap; 137 139 138 //!> flag to indicate whether state map is currently worked on 140 139 boost::recursive_mutex MoleculeMissedStateMap_mutex; -
src/documentation/constructs/qt-gui.dox
r03e69e r59f1bc 59 59 * there is a QTimer that only updates an object in regular intervals, or 60 60 * because of asynchronous threads. Elsewhen, the slot callback for a 61 * certain signal is called directly. For all of these cases we have to61 * certain signal is called directly. All of these cases we have to 62 62 * accommodate. This is especially problematic with the instantiation and 63 * destruction of objects .63 * destruction of objects that represent atoms and molecules in the World. 64 64 * 65 65 * A clarifying example: Imagine an atom is constructed, the AtomObserver … … 70 70 * 71 71 * The only possible way out is to duplicate information. This is the usual 72 * way how to deal withenvironments with multiple threads. I.e. all the72 * way how to proceed in environments with multiple threads. I.e. all the 73 73 * information that the GUI representants of information inside the World 74 74 * needs to be doubled such that when the original information is destroyed 75 * the representant can still be accessed as long as needed. 75 * the representant can still be accessed as long as needed. Here, we use 76 * the ObservedValue construct of CodePatterns. 76 77 * 77 78 * \subsection qt-gui-general-observedvalue Observed Value … … 100 101 * pieces of information that require more computing resources within the 101 102 * updater. Also, the Cacheable's information can only be obtained as long 102 * as the source of information is still alive. 103 * 104 * Both concepts can be used in threaded environments as mutexed are used to 103 * as the source of information is still alive. However, so far Cacheable's 104 * content is marked invalid when an update signal has been received and 105 * update itself only on request, which is no longer possible when the object 106 * to represent is gone. 107 * 108 * Both concepts can be used in threaded environments as mutexes are used to 105 109 * protect read and write accesses. 106 110 * 107 * \subsection qt-gui-general-signalslot Observer/Observable and Signal/Slot 108 * 109 * In the following we refer to Observer/Observable as "O/O" and to Signal/Slot 110 * as "S/S". 111 * 112 * One thing we need to do is to translate between update() or 113 * recieveNotification() calls from an Observable and subsequent signal/slot 114 * calls. The general idea is to use these ObservedValues as translation 115 * points for small pieces of information and Cacheables for larger pieces. 116 * 117 * However, we need more of these translation points: 118 * -# GLWorldView checks for 119 * -# World's MoleculeInserted 120 * -# World's SelectionChanged 121 * -# WorldTime's TimeChanged 122 * -# each molecule's AtomInserted and AtomRemoved 123 * -# AtomObservable's AtomChanged. 124 * -# ShapeRegistry's ShapedAdded, ShapeRemoved, and SelectionChanged 125 * -# GLMoleculeObject_molecule checks for 126 * -# molecule's AtomInserted, AtomRemoved, AtomMoved, IndexChanged 127 * -# World's SelectionChanged 128 * 111 * \subsection qt-gui-general-observedinstance The observed instance board 112 * 113 * The setup is then as follows: We have two distinct realms, the World (with 114 * atoms and molecules) on the one side and the QtGUI (with visual 115 * representations of atoms and molecules) on the other side. 116 * 117 * There is an interface between this world such that the destruction of an 118 * atom does not directly invalidate its visual representation. This interface 119 * between the two realms is contained in the class QtObservedInstanceBoard, 120 * which is a singleton and is similar to the World instance in the World realm 121 * for the QtGui realm. 122 * 123 * All properties, e.g. the position of an element, relevant to the QtGUI are 124 * duplicated as ObservedValues. Properties associated to the same instance in 125 * the World, e.g. the same atom, are combined into a QtObservedAtom instance, 126 * and similarly QtObservedMolecule for molecule. All of these observed 127 * instances are placed into ObservedValuesContainer which are contained in 128 * the interface QtObservedInstanceBoard. 129 * 130 * The sequence of events is then as follows (here exemplified with an atom): 131 * -# an atom is created (World::createAtom()), the World notifies about it 132 * via its World::AtomInserted channel. 133 * -# QtObservedInstanceBoard is signOn()ed to this channel and instantiates 134 * a new QtObservedAtom which is placed into its respective 135 * ObservedValuesContainer. 136 * -# on instantiation of QtObservedAtom a vector of specific ObservedValues is 137 * created, one for each property (position, element, bond count, ...). 138 * Each signOn()s to the respective atom's channel. Also the QtObservedAtom 139 * signOn()s to each of these channels as it converts these notifications 140 * into Qt signals (and the updated value can be accessed via getters from 141 * the QtObservedAtom instance). The QtObservedInstanceBoard is notified 142 * of this with the instance being marked as connected. 143 * -# when the atom is destroyed (World::destroyAtom()), being an Observable 144 * it will call subjectKilled() on all its channels. The 145 * ObservedValue_wCallback announces this subjectKilled() via the callback 146 * function which notifies QtObservedAtom. Once all subjectKilled(), for 147 * each observed value and for QtObservedAtom itself, have been received, 148 * the QtObservedInstanceBoard is notified by the instance now being 149 * marked as disconnected and ready for erase. 150 * -# then the QtObservedInstanceBoard removes the instance from its 151 * ObservedValuesContainer. 152 * 153 * Note however that the instance is a shared_ptr and will continue to exist 154 * and therefore its getters will still deliver the last piece of information 155 * before the atom was destroyed until all shared_ptrs are released. Hence, 156 * the QtGui may safely continue using the pointer. 157 * 158 * As new observed instances may come in immediately having the same id and 159 * as it is difficult to keep track who got its observed instance already 160 * and who not, a soft fail is required. I.e. of the QtObservedInstanceBoard 161 * returns an empty shared_ptr this means that the object -- despite any 162 * received (and probably delayed) signal -- has been destroyed and should 163 * not be displayed, updated by, ... whatsoever. 164 * 165 * \subsection qt-gui-general-signalslot Details on the slot connections 166 * 167 * Qt's event system does not guarantee that events are always processed in 168 * the order they are emitted. This is because connections can be defined 169 * as direct or queued (or both with auto). Direct connections will always 170 * be executed as direct function calls, i.e. immediately. Queued connections 171 * however are inserted into Qt's event queue and may even get processed by 172 * a different thread. 173 * 174 * We have to take care of this. 175 * 176 * Basically what we do in QtObservedInstanceBoard and the observed instances 177 * of type QtObservedAtom and QtObservedMolecule is that we translate between 178 * the Observer/Observable (O/O) system of CodePatterns with its callback 179 * functions and the event system of Qt with its Signal/Slot (S/S). 180 * 181 * That is in the recieveNotification() functions many "emit()"s can be found. 182 * 183 * Furthermore, signals are used in a specific way to ensure synchronicity. 184 * This is only a problem with the visual representation as we there find a 185 * a nested problem: First molecules, then atoms belonging to a certain 186 * molecule. This enforces a certain sequence of events and thus of signals. 187 * 188 * \subsubsection qt-gui-general-signalslot-glworldscene Details on GLWorldScene 189 * 190 * The central place for all events is the GLWorldScene instance. There 191 * signals from QtObservedInstanceBoard for insertion and removal of both atoms 192 * and molecules are caught. Insertion of molecules is dealt with directly, 193 * we sign on to the inserted&removed channels for its atoms, then we emit 194 * a queued signal to actually instantiate the GLMoleculeObject_molecule. 195 * 196 * Until its instantiation we store incoming signals in the 197 * GLWorldScene::MoleculeMissedStateMap, protected by a mutex to enforce atomic 198 * access. After it has been instantiated (and all stored signals have been 199 * processed), they are relayed onto the specific instance. However, we do not 200 * do this via emits but by directly using Qt's invokeMethod() which allows 201 * to trigger queued events. This way it is done in a likewise manner whether 202 * it has been a stored or live signal that was received. 203 * 204 * \subsubsection qt-gui-general-signalslot-other Details on other signals 205 * 206 * All other signals that only change the property of a visual representation, 207 * e.g. the element of an atom, is directly processed by, in this case, the 208 * GLMoleculeObject_atom connected to QtObservedAtom. 209 . * 129 210 * \section qt-gui-qt3d Qt3D and the way to get atoms and bonds displayed 130 211 * … … 146 227 * of an element-specific color at the atom's position. The atom relies 147 228 * on its representants to be contain all required information but it 148 * is also signOn() to the atom itself whose O/O are translated to S/S149 * for processing whenever desired.229 * is also signOn() to the QtObservedAtom itself whose O/O are translated to 230 * S/S for processing whenever desired. 150 231 * 151 232 * Next comes the GLMoleculeObject_bond which displays a cylinder between … … 158 239 * 159 240 * Parallel to these are GLMoleculeObject_shape which display the surface 160 * of a selected shape. A shape in general does not change after instant ation,241 * of a selected shape. A shape in general does not change after instantiation, 161 242 * hence the shape lives with the information it gets on instantiation till 162 243 * it dies. … … 168 249 * molecules. The molecule also needs ObservedValues for its bounding box 169 250 * (used to show when it's selected), the index, the selection status, 170 * and the list of atom ids. As Cacheable we use the tesselation structure.251 * and the list of atom ids. 171 252 * 172 253 * \section qt-gui-cases Sample cases … … 270 351 * they automatically clear the info box. 271 352 * 272 * \date 201 5-07-15353 * \date 2016-01-08 273 354 */
Note:
See TracChangeset
for help on using the changeset viewer.