source: src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp@ 507f3c

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
Last change on this file since 507f3c was 507f3c, checked in by Frederik Heber <heber@…>, 9 years ago

QtObservedBond returns ::ptr instead of ptr from left and right atom.

  • FIX: GLWorldScene crashed on resolving sender() of a reparent..() signal because the object got destroyed in the meantime.
  • Property mode set to 100644
File size: 25.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * GLWorldScene.cpp
26 *
27 * This is based on the Qt3D example "teaservice", specifically parts of teaservice.cpp.
28 *
29 * Created on: Aug 17, 2011
30 * Author: heber
31 */
32
33// include config.h
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "GLWorldScene.hpp"
39#include <Qt3D/qglview.h>
40#include <Qt3D/qglbuilder.h>
41#include <Qt3D/qglscenenode.h>
42#include <Qt3D/qglsphere.h>
43#include <Qt3D/qglcylinder.h>
44
45#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject.hpp"
46#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.hpp"
47#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_bond.hpp"
48#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp"
49#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_shape.hpp"
50
51#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
52
53#include "CodePatterns/MemDebug.hpp"
54
55#include "CodePatterns/Log.hpp"
56
57#include <boost/assign.hpp>
58
59#include "Actions/SelectionAction/Atoms/AtomByIdAction.hpp"
60#include "Actions/SelectionAction/Atoms/NotAtomByIdAction.hpp"
61#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
62#include "Actions/SelectionAction/Molecules/NotMoleculeByIdAction.hpp"
63#include "Atom/atom.hpp"
64#include "Bond/bond.hpp"
65#include "Descriptors/AtomIdDescriptor.hpp"
66#include "Descriptors/MoleculeIdDescriptor.hpp"
67#include "Helpers/helpers.hpp"
68#include "Shapes/ShapeRegistry.hpp"
69#include "molecule.hpp"
70#include "World.hpp"
71
72#include <iostream>
73
74using namespace MoleCuilder;
75
76GLWorldScene::GLWorldScene(
77 QtObservedInstanceBoard * _board,
78 QObject *parent) :
79 QObject(parent),
80 BondNodeParentMaps(std::vector<BondNodeParentMap_t>(2)),
81 selectionMode(SelectAtom),
82 board(_board)
83{
84 qRegisterMetaType<atomId_t>("atomId_t");
85 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
86
87 int sphereDetails[] = {5, 3, 2, 0};
88 int cylinderDetails[] = {16, 8, 6, 3};
89 for (int i=0;i<GLMoleculeObject::DETAILTYPES_MAX;i++){
90 QGLBuilder emptyBuilder;
91 GLMoleculeObject::meshEmpty[i] = emptyBuilder.finalizedSceneNode();
92 QGLBuilder sphereBuilder;
93 sphereBuilder << QGLSphere(2.0, sphereDetails[i]);
94 GLMoleculeObject::meshSphere[i] = sphereBuilder.finalizedSceneNode();
95 GLMoleculeObject::meshSphere[i]->setOption(QGLSceneNode::CullBoundingBox, true);
96 QGLBuilder cylinderBuilder;
97 cylinderBuilder << QGLCylinder(.25,.25,1.0,cylinderDetails[i]);
98 GLMoleculeObject::meshCylinder[i] = cylinderBuilder.finalizedSceneNode();
99 GLMoleculeObject::meshCylinder[i]->setOption(QGLSceneNode::CullBoundingBox, true);
100 }
101 connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)),
102 this, SLOT(insertMolecule(QtObservedMolecule::ptr)));
103 connect(board, SIGNAL(moleculeRemoved(ObservedValue_Index_t)),
104 this, SLOT(removeMolecule(ObservedValue_Index_t)));
105
106 connect(board, SIGNAL(atomInserted(QtObservedAtom::ptr)),
107 this, SLOT(connectAtom(QtObservedAtom::ptr)), Qt::DirectConnection);
108 connect(this, SIGNAL(atomConnected(QtObservedAtom::ptr)),
109 this, SLOT(insertAtom(QtObservedAtom::ptr)));
110 connect(board, SIGNAL(atomRemoved(ObservedValue_Index_t)),
111 this, SLOT(removeAtom(ObservedValue_Index_t)));
112
113 connect(board, SIGNAL(bondInserted(QtObservedBond::ptr)),
114 this, SLOT(connectBond(QtObservedBond::ptr)), Qt::DirectConnection);
115 connect(this, SIGNAL(bondConnected(QtObservedBond::ptr)),
116 this, SLOT(insertBond(QtObservedBond::ptr)));
117 connect(board, SIGNAL(bondRemoved(ObservedValue_Index_t)),
118 this, SLOT(removeBond(ObservedValue_Index_t)));
119
120// connect(this, SIGNAL(updated()), this, SLOT(update()));
121}
122
123GLWorldScene::~GLWorldScene()
124{
125 // remove all elements
126 GLMoleculeObject::cleanMaterialMap();
127}
128
129void GLWorldScene::clickAtom(atomId_t no)
130{
131 LOG(3, "INFO: GLWorldScene - atom " << no << " has been clicked.");
132 const atom * const Walker = const_cast<const World &>(World::getInstance()).
133 getAtom(AtomById(no));
134 ASSERT( Walker != NULL,
135 "GLWorldScene::clickAtom() - clicked atom has disappeared.");
136 if (selectionMode == SelectAtom){
137 if (!World::getInstance().isSelected(Walker))
138 SelectionAtomById(std::vector<atomId_t>(1,no));
139 else
140 SelectionNotAtomById(std::vector<atomId_t>(1,no));
141 }else if (selectionMode == SelectMolecule){
142 const molecule *mol = Walker->getMolecule();
143 ASSERT(mol, "Atom without molecule has been clicked.");
144 molids_t ids(1, mol->getId());
145 if (!World::getInstance().isSelected(mol))
146 SelectionMoleculeById(ids);
147 else
148 SelectionNotMoleculeById(ids);
149 }
150 emit clicked(no);
151}
152
153/** Prepares adding an atom to the scene
154 *
155 * We need to listen to moleculeChanged() in order to properly re-parent()
156 * this QObject
157 *
158 * @param _atom atom to connect
159 */
160void GLWorldScene::connectAtom(QtObservedAtom::ptr _atom)
161{
162 connect(_atom.get(), SIGNAL(moleculeChanged()), this, SLOT(reparentAtom()));
163
164 {
165 const ObservedValue_Index_t atomid = _atom->getIndex();
166 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
167 AtomNodeParentMap.left.insert( std::make_pair(atomid, (ObservedValue_Index_t)NULL) );
168 }
169
170 emit atomConnected(_atom);
171}
172
173/** Adds an atom to the scene.
174 *
175 * @param _atom atom to add
176 */
177void GLWorldScene::insertAtom(QtObservedAtom::ptr _atom)
178{
179 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "
180 << _atom->getAtomIndex());
181
182 const ObservedValue_Index_t atomid = _atom->getIndex();
183 QObject *parent = static_cast<QObject *>(this);
184 GLMoleculeObject_atom *atomObject = NULL;
185 {
186 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
187 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(atomid);
188 ASSERT (parentiter != AtomNodeParentMap.left.end(),
189 "GLWorldScene::insertAtom() - parent to atom id "+toString(atomid)+" unknown?");
190 const ObservedValue_Index_t parentindex = parentiter->second;
191 if (parentindex != (ObservedValue_Index_t)NULL) {
192 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentindex);
193 if (moliter != MoleculesinSceneMap.end())
194 parent = moliter->second;
195 }
196
197 atomObject = new GLMoleculeObject_atom(
198 GLMoleculeObject::meshSphere,
199 parent,
200 _atom);
201 ASSERT( atomObject != NULL,
202 "GLWorldScene::atomInserted - could not create atom object for "
203 +toString(_atom->getAtomIndex()));
204 }
205 AtomNodeMap::iterator iter = AtomsinSceneMap.find(atomid);
206 ASSERT(iter == AtomsinSceneMap.end(),
207 "GLWorldScene::insertAtom - same atom with id "
208 +toString(_atom->getAtomIndex())+" added again.");
209 AtomsinSceneMap.insert( make_pair(atomid, atomObject) );
210
211 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SLOT(clickAtom(atomId_t)));
212 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
213 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
214 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
215
216 emit changed();
217 emit changeOccured();
218}
219
220/** Removes an atom.
221 *
222 * @param _atomid index of the atom that is removed
223 */
224void GLWorldScene::removeAtom(ObservedValue_Index_t _atomid)
225{
226 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+".");
227 // bonds are removed by signal coming from ~bond
228
229 // remove atoms
230 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_atomid);
231 ASSERT(iter != AtomsinSceneMap.end(),
232 "GLWorldScene::removeAtom() - atom "+toString(_atomid)+" not on display.");
233 GLMoleculeObject_atom *atomObject = iter->second;
234 AtomsinSceneMap.erase(iter);
235 delete atomObject;
236 {
237 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
238 AtomNodeParentMap.left.erase(_atomid);
239 }
240 emit changed();
241 emit changeOccured();
242}
243
244/** Prepares adding a bond to the scene
245 *
246 * We need to listen to moleculeChanged() in order to properly re-parent()
247 * this QObject
248 *
249 * @param _bond bond to connect
250 */
251void GLWorldScene::connectBond(QtObservedBond::ptr _bond)
252{
253 connect(_bond.get(), SIGNAL(leftmoleculeChanged()), this, SLOT(reparentBondLeft()));
254 connect(_bond.get(), SIGNAL(rightmoleculeChanged()), this, SLOT(reparentBondRight()));
255
256 {
257 const ObservedValue_Index_t bondid = _bond->getIndex();
258 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
259 if ((_bond->getLeftAtom() != NULL) && (_bond->getLeftAtom()->getMoleculeRef() != NULL))
260 BondNodeParentMaps[0].left.insert(
261 std::make_pair(bondid, _bond->getLeftAtom()->getMoleculeRef()->getIndex()) );
262 else
263 BondNodeParentMaps[0].left.insert(
264 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
265 if ((_bond->getRightAtom() != NULL) && (_bond->getRightAtom()->getMoleculeRef() != NULL))
266 BondNodeParentMaps[1].left.insert(
267 std::make_pair(bondid, _bond->getRightAtom()->getMoleculeRef()->getIndex()) );
268 else
269 BondNodeParentMaps[1].left.insert(
270 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
271 }
272
273 emit bondConnected(_bond);
274}
275
276/** Adds a bond to the scene.
277 *
278 * @param _bond bond to add
279 */
280void GLWorldScene::insertBond(QtObservedBond::ptr _bond)
281{
282 static const std::vector< GLMoleculeObject_bond::SideOfBond > bondsides =
283 boost::assign::list_of<GLMoleculeObject_bond::SideOfBond>
284 (GLMoleculeObject_bond::left)
285 (GLMoleculeObject_bond::right);
286 LOG(3, "INFO: GLWorldScene::insertBond() - Adding bonds " << _bond->getBondIndex());
287
288 const ObservedValue_Index_t bondid = _bond->getIndex();
289#ifdef NDEBUG
290 BondNodeMap::iterator iter = BondsinSceneMap.find(bondid);
291 ASSERT( iter == BondsinSceneMap.end(),
292 "GLWorldScene::insertBond() - bond "+toString(bondid)+" is already known.");
293#endif
294 {
295 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
296 for (size_t i=0;i<2;++i) {
297 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[i].left.find(bondid);
298 ASSERT (parentiter != BondNodeParentMaps[i].left.end(),
299 "GLWorldScene::insertBond() - parent to bond id "+toString(bondid)+" unknown?");
300 QObject *parent = this;
301 if (parentiter->second != (ObservedValue_Index_t)NULL) {
302 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentiter->second);
303 if (moliter != MoleculesinSceneMap.end())
304 parent = moliter->second;
305 }
306
307 GLMoleculeObject_bond *bondObject = new GLMoleculeObject_bond(
308 GLMoleculeObject::meshCylinder,
309 parent,
310 _bond,
311 bondsides[i]);
312 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
313 BondsinSceneMap.insert( std::make_pair(bondid, bondObject) );
314 }
315 }
316
317 emit changed();
318 emit changeOccured();
319}
320
321/** Removes a bond.
322 *
323 * @param _bondid id of bond to remove
324 */
325void GLWorldScene::removeBond(ObservedValue_Index_t _bondid)
326{
327 LOG(3, "INFO: GLWorldScene::removedBond() - Removing bond to id " << _bondid);
328
329 // left bond
330 std::pair<BondNodeMap::iterator, BondNodeMap::iterator> iters =
331 BondsinSceneMap.equal_range(_bondid);
332 ASSERT( iters.first != iters.second,
333 "GLWorldScene::removedBond() - could not find bond to id "+toString(_bondid));
334 for (BondNodeMap::iterator iter = iters.first; iter != iters.second; ++iter) {
335 GLMoleculeObject_bond *bondObject = iter->second;
336 delete bondObject; // is done by signal from bond itself
337 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
338 }
339 BondsinSceneMap.erase(_bondid);
340 {
341 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
342 BondNodeParentMaps[0].left.erase(_bondid);
343 BondNodeParentMaps[1].left.erase(_bondid);
344 }
345
346 emit changed();
347 emit changeOccured();
348}
349
350void GLWorldScene::hoverChangedSignalled(GLMoleculeObject *ob)
351{
352 // Find the atom, ob corresponds to.
353 hoverAtomId = -1;
354 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
355 if (atomObject){
356 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
357 if (iter->second == atomObject)
358 hoverAtomId = iter->second->objectId();
359 }
360
361 // Propagate signal.
362 emit hoverChanged(hoverAtomId);
363 } else {
364 // Find the atom, ob corresponds to.
365 GLMoleculeObject_molecule *moleculeObject = dynamic_cast<GLMoleculeObject_molecule *>(ob);
366 if (moleculeObject){
367 // Propagate signal.
368 emit hoverChanged(moleculeObject->objectId(), 0);
369 }
370 }
371}
372
373void GLWorldScene::clickMolecule(moleculeId_t no)
374{
375 LOG(3, "INFO: GLMoleculeObject_molecule - mol " << no << " has been clicked.");
376 const molecule * const mol= const_cast<const World &>(World::getInstance()).
377 getMolecule(MoleculeById(no));
378 ASSERT(mol, "Atom without molecule has been clicked.");
379 molids_t ids(1, mol->getId());
380 if (!World::getInstance().isSelected(mol))
381 SelectionMoleculeById(ids);
382 else
383 SelectionNotMoleculeById(ids);
384 emit clicked(no);
385}
386
387/** Inserts a molecule into the scene.
388 *
389 * @param _mol molecule to insert
390 */
391void GLWorldScene::insertMolecule(QtObservedMolecule::ptr _mol)
392{
393 const ObservedValue_Index_t molid = _mol->getIndex();
394 LOG(3, "INFO: GLWorldScene: Received signal moleculeInserted for molecule "
395 << _mol->getMolIndex());
396
397 MoleculeNodeMap::const_iterator iter = MoleculesinSceneMap.find(molid);
398 ASSERT( iter == MoleculesinSceneMap.end(),
399 "GLWorldScene::insertMolecule() - molecule's id "+toString(molid)
400 +" already present.");
401
402 // add new object
403 LOG(1, "DEBUG: Adding GLMoleculeObject_molecule to id " << molid);
404 GLMoleculeObject_molecule *molObject =
405 new GLMoleculeObject_molecule(
406 GLMoleculeObject::meshEmpty,
407 this,
408 _mol);
409 ASSERT( molObject != NULL,
410 "GLWorldScene::insertMolecule - could not create molecule object for "
411 +toString(molid));
412#ifndef NDEBUG
413 foreach (QObject *obj, molObject->children()) {
414 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
415 ASSERT( meshobj == NULL,
416 "GLWorldScene::insertMolecule() - there are already atoms or bonds attached to a to molecule.");
417 }
418#endif
419
420 // check all atoms for not yet assigned parents
421 {
422 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
423 std::pair<AtomNodeParentMap_t::right_const_iterator, AtomNodeParentMap_t::right_const_iterator> iters =
424 AtomNodeParentMap.right.equal_range(molid);
425 for (AtomNodeParentMap_t::right_const_iterator iter = iters.first;
426 iter != iters.second; ++iter) {
427 AtomNodeMap::const_iterator atomiter = AtomsinSceneMap.find(iter->second);
428 if (atomiter != AtomsinSceneMap.end())
429 resetParent(atomiter->second, molObject);
430 }
431 }
432 // check all bonds for not yet assigned parents
433 {
434 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
435 for (size_t i=0;i<2;++i) {
436 std::pair<BondNodeParentMap_t::right_const_iterator, BondNodeParentMap_t::right_const_iterator> iters =
437 BondNodeParentMaps[i].right.equal_range(molid);
438 for (BondNodeParentMap_t::right_const_iterator iter = iters.first;
439 iter != iters.second; ++iter) {
440 BondNodeMap::const_iterator bonditer = BondsinSceneMap.find(iter->second);
441 if (bonditer != BondsinSceneMap.end())
442 resetParent(bonditer->second, molObject);
443 }
444 }
445 }
446
447#ifndef NDEBUG
448 std::pair<MoleculeNodeMap::iterator, bool> inserter =
449#endif
450 MoleculesinSceneMap.insert( make_pair(molid, molObject) );
451 ASSERT(inserter.second,
452 "GLWorldScene::insertMolecule() - molecule "+toString(_mol->getMolIndex())
453 +" already present in scene.");
454
455 connect (molObject, SIGNAL(changed()), this, SIGNAL(changed()));
456 connect (molObject, SIGNAL(changeOccured()), this, SIGNAL(changeOccured()));
457
458 emit changed();
459 emit changeOccured();
460}
461
462/** Removes a molecule from the scene.
463 *
464 * @param _molid index of the molecule to remove
465 */
466void GLWorldScene::removeMolecule(ObservedValue_Index_t _molid)
467{
468 LOG(3, "INFO: GLWorldScene: Received signal moleculeRemoved for molecule "+toString(_molid)+".");
469
470 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
471 ASSERT ( iter != MoleculesinSceneMap.end(),
472 "GLWorldScene::removeMolecule() - to be removed molecule "+toString(_molid)
473 +" is already gone.");
474 GLMoleculeObject_molecule *molObject = iter->second;
475 // check for any atoms and bonds still attached to it
476#ifndef NDEBUG
477 foreach (QObject *obj, molObject->children()) {
478 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
479 ASSERT( meshobj == NULL,
480 "GLWorldScene::removeMolecule() - there are still atoms or bonds attached to a to molecule.");
481 }
482#endif
483 // finally, remove molecule
484 delete molObject;
485 MoleculesinSceneMap.erase(iter);
486
487 emit changed();
488 emit changeOccured();
489}
490
491void GLWorldScene::moleculesVisibilityChanged(ObservedValue_Index_t _id, bool _visible)
492{
493 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
494 ASSERT( iter != MoleculesinSceneMap.end(),
495 "GLWorldScene::moleculeInserted() - molecule's id "
496 +toString(board->getMoleculeIdToIndex(_id))+" is unknown.");
497
498 GLMoleculeObject_molecule *molObject = iter->second;
499 molObject->setVisible(_visible);
500
501 emit changed();
502 emit changeOccured();
503}
504
505/** This converts safely index into a GLMoleculeObject_molecule.
506 *
507 * \param _MoleculesinSceneMap all present molecules
508 * \param _molid index to look for
509 * \return MolObject or NULL when not found
510 */
511GLMoleculeObject_molecule *GLWorldScene::getMoleculeObject(
512 const ObservedValue_Index_t _molid) const
513{
514 const MoleculeNodeMap::const_iterator moliter = MoleculesinSceneMap.find(_molid);
515 if (moliter != MoleculesinSceneMap.end())
516 return moliter->second;
517 else
518 return NULL;
519}
520
521/** Changes the parent of an object in the scene.
522 *
523 * \param _id index of the object whose parent to change
524 * \param _ob new parent
525 */
526void GLWorldScene::reparentAtom()
527{
528 QtObservedAtom *walker = dynamic_cast<QtObservedAtom *>(sender());
529 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
530 const ObservedValue_Index_t walkerid = walker->getIndex();
531 LOG(4, "DEBUG: GLWorldScene: Received signal moleculeChanged for atom "+toString(walkerid)+".");
532 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(walkerid);
533 ASSERT( parentiter != AtomNodeParentMap.left.end(),
534 "GLWorldScene::reparentAtom() - could not find object to id "+toString(walkerid));
535
536 // change parent entry
537 AtomNodeParentMap.left.erase(parentiter);
538 if (walker->getMoleculeRef() != NULL)
539 AtomNodeParentMap.left.insert( std::make_pair(walkerid, walker->getMoleculeRef()->getIndex()) );
540 else
541 AtomNodeParentMap.left.insert( std::make_pair(walkerid, (ObservedValue_Index_t)NULL) );
542 parentiter = AtomNodeParentMap.left.find(walkerid);
543
544 const AtomNodeMap::iterator atomiter = AtomsinSceneMap.find(walkerid);
545 if (atomiter != AtomsinSceneMap.end())
546 resetParent(atomiter->second, getMoleculeObject(parentiter->second));
547 // else atom does not yet exist
548}
549
550/** Changes the parent of an left-side bond in the scene.
551 *
552 */
553void GLWorldScene::reparentBondLeft()
554{
555 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
556 QtObservedBond *bond = dynamic_cast<QtObservedBond *>(sender());
557 reparentBond(bond, bond->getLeftAtom(), GLMoleculeObject_bond::left);
558}
559
560/** Changes the parent of an right-side bond in the scene.
561 *
562 */
563void GLWorldScene::reparentBondRight()
564{
565 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
566 QtObservedBond *bond = dynamic_cast<QtObservedBond *>(sender());
567 reparentBond(bond, bond->getRightAtom(), GLMoleculeObject_bond::right);
568}
569
570GLMoleculeObject_bond *GLWorldScene::getBondInScene(
571 const ObservedValue_Index_t _bondid,
572 GLMoleculeObject_bond::SideOfBond _side) const
573{
574 std::pair<GLWorldScene::BondNodeMap::const_iterator, GLWorldScene::BondNodeMap::const_iterator> iters =
575 BondsinSceneMap.equal_range(_bondid);
576 ASSERT( std::distance(iters.first, iters.second) == 2,
577 "GLWorldScene::getBondInScene() - not exactly two bonds of same id "
578 +toString(_bondid)+" present in scene.");
579 for (GLWorldScene::BondNodeMap::const_iterator bonditer = iters.first;
580 bonditer != iters.second; ++bonditer) {
581 if (bonditer->second->BondSide == _side)
582 return bonditer->second;
583 }
584 return NULL;
585}
586
587/** Changes the parent of an object in the scene.
588 *
589 * \param _atom atom of bond whose molecule we are associated to
590 * \param _side side of bond
591 */
592void GLWorldScene::reparentBond(
593 QtObservedBond *_bond,
594 const QtObservedAtom::ptr _atom,
595 const GLMoleculeObject_bond::SideOfBond _side)
596{
597 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
598 const size_t dim = (_side == GLMoleculeObject_bond::left) ? 0 : 1;
599 const ObservedValue_Index_t bondid = _bond->getIndex();
600 LOG(4, "DEBUG: GLWorldScene: Received signal moleculeChanged for bond "+toString(bondid)+".");
601 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[dim].left.find(bondid);
602 ASSERT( parentiter != BondNodeParentMaps[dim].left.end(),
603 "GLWorldScene::reparentBond() - could not find object to id "+toString(bondid));
604
605 // change parent entry
606 BondNodeParentMaps[dim].left.erase(bondid);
607 if ((_atom != NULL) && (_atom->getMoleculeRef() != NULL))
608 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, _atom->getMoleculeRef()->getIndex()));
609 else
610 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, (ObservedValue_Index_t)NULL) );
611 parentiter = BondNodeParentMaps[dim].left.find(bondid);
612
613 // reset parent
614 resetParent(getBondInScene(bondid, _side), getMoleculeObject(parentiter->second));
615}
616
617/** Resets the parent of an GLMoleculeObject.
618 *
619 * \param _obj object to reparent
620 * \param _molid index of parent molecule
621 */
622void GLWorldScene::resetParent(
623 GLMoleculeObject *_obj,
624 GLMoleculeObject_molecule *_molobj)
625{
626 if (_obj != NULL) {
627 QObject *parent = this;
628 if (_molobj != NULL)
629 parent = _molobj;
630 // else: molecule does not yet exist: is done when molecule is instantiated
631 LOG(5, "DEBUG: Resetting parent of " << _obj << " to " << parent);
632 _obj->setParent(parent);
633 ASSERT( _obj->parent() == parent,
634 "GLWorldScene::resetParent() - new parent "+toString(parent)+" was not set.");
635 } else
636 ELOG(1, "Object to reparent was NULL.");
637 // else object does not yet exist
638}
639
640/** Adds a shape to the scene.
641 *
642 */
643void GLWorldScene::addShape(const std::string &_name)
644{
645 Shape * const shape = ShapeRegistry::getInstance().getByName(_name);
646 if (shape != NULL) {
647 GLMoleculeObject_shape *shapeObject = new GLMoleculeObject_shape(*shape, this);
648 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
649 ASSERT(iter == ShapesinSceneMap.end(),
650 "GLWorldScene::addShape() - same shape "+_name+" added again.");
651 ShapesinSceneMap.insert( make_pair(_name, shapeObject) );
652 } else
653 ELOG(2, "GLWorldScene::addShape() - shape disappeared before we could draw it.");
654
655 emit changed();
656}
657
658void GLWorldScene::removeShape(const std::string &_name)
659{
660 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
661 ASSERT(iter != ShapesinSceneMap.end(),
662 "GLWorldScene::removeShape() - shape "+_name+" not in scene.");
663 ShapesinSceneMap.erase(iter);
664 delete(iter->second);
665
666 emit changed();
667}
668
669void GLWorldScene::updateSelectedShapes()
670{
671 foreach (QObject *obj, children()) {
672 GLMoleculeObject_shape *shapeobj = qobject_cast<GLMoleculeObject_shape *>(obj);
673 if (shapeobj){
674 shapeobj->enable(ShapeRegistry::getInstance().isSelected(shapeobj->getShape()));
675 }
676 }
677
678 emit changed();
679}
680
681void GLWorldScene::initialize(QGLView *view, QGLPainter *painter) const
682{
683 // Initialize all of the mesh objects that we have as children.
684 foreach (QObject *obj, children()) {
685 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
686 if (meshobj)
687 meshobj->initialize(view, painter);
688 }
689}
690
691void GLWorldScene::draw(QGLPainter *painter, const QVector4D &cameraPlane) const
692{
693 // Draw all of the mesh objects that we have as children.
694 foreach (QObject *obj, children()) {
695 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
696 if (meshobj)
697 meshobj->draw(painter, cameraPlane);
698 }
699}
700
701void GLWorldScene::setSelectionMode(SelectionModeType mode)
702{
703 selectionMode = mode;
704 // TODO send update to toolbar
705}
706
707void GLWorldScene::setSelectionModeAtom()
708{
709 setSelectionMode(SelectAtom);
710}
711
712void GLWorldScene::setSelectionModeMolecule()
713{
714 setSelectionMode(SelectMolecule);
715}
716
Note: See TracBrowser for help on using the repository browser.