source: src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp@ 7c7c4a

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 7c7c4a was 7c7c4a, checked in by Frederik Heber <heber@…>, 9 years ago

FIX: All ObservedValue's of GLMoleculeObject_atom/bond/molecule wrapped into vector.

  • the idea is that a GLMoleculeObject may only remove itself _after_ each and every contained Observer has gotten the subjectKilled() signal from the Observables. Only then will destroying the Object and its members thereby not cause any signOff() which try to access Observables or their channels which are no longer present. This can be imagined as a graph where we have to start destroying object at the very bottom.
  • This is the avoid the following conflict: A superior object gets note of a molecule to be removed. It sends the visual representation a signal to remove itself, which causes it to use signOff(). On a parallel track (in another thread) we have the observed object calling subjectKilled() to inform any Observer about its immediate destruction. These two tracks collide. Now, we let first pass all subjectKilled() and when the last Observable has gotten its signal, we begin destroying the visual rep.
  • rerouted signal/slots accordingly.
  • Property mode set to 100644
File size: 22.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/Views/Qt4/QtSelectionChangedAgent.hpp"
52
53#include "CodePatterns/MemDebug.hpp"
54
55#include "CodePatterns/Log.hpp"
56
57#include "Actions/SelectionAction/Atoms/AtomByIdAction.hpp"
58#include "Actions/SelectionAction/Atoms/NotAtomByIdAction.hpp"
59#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
60#include "Actions/SelectionAction/Molecules/NotMoleculeByIdAction.hpp"
61#include "Atom/atom.hpp"
62#include "Bond/bond.hpp"
63#include "Descriptors/AtomIdDescriptor.hpp"
64#include "Descriptors/MoleculeIdDescriptor.hpp"
65#include "Helpers/helpers.hpp"
66#include "Shapes/ShapeRegistry.hpp"
67#include "molecule.hpp"
68#include "World.hpp"
69
70#include <iostream>
71
72using namespace MoleCuilder;
73
74GLWorldScene::GLWorldScene(QObject *parent) :
75 QObject(parent),
76 selectionMode(SelectAtom)
77{
78 int sphereDetails[] = {5, 3, 2, 0};
79 int cylinderDetails[] = {16, 8, 6, 3};
80 for (int i=0;i<GLMoleculeObject::DETAILTYPES_MAX;i++){
81 QGLBuilder emptyBuilder;
82 GLMoleculeObject::meshEmpty[i] = emptyBuilder.finalizedSceneNode();
83 QGLBuilder sphereBuilder;
84 sphereBuilder << QGLSphere(2.0, sphereDetails[i]);
85 GLMoleculeObject::meshSphere[i] = sphereBuilder.finalizedSceneNode();
86 GLMoleculeObject::meshSphere[i]->setOption(QGLSceneNode::CullBoundingBox, true);
87 QGLBuilder cylinderBuilder;
88 cylinderBuilder << QGLCylinder(.25,.25,1.0,cylinderDetails[i]);
89 GLMoleculeObject::meshCylinder[i] = cylinderBuilder.finalizedSceneNode();
90 GLMoleculeObject::meshCylinder[i]->setOption(QGLSceneNode::CullBoundingBox, true);
91 }
92 connect(this, SIGNAL(moleculePreparedInserted(const moleculeId_t)), this, SLOT(moleculeInserted(const moleculeId_t)));
93
94// connect(this, SIGNAL(updated()), this, SLOT(update()));
95}
96
97GLWorldScene::~GLWorldScene()
98{
99 // remove all elements
100 GLMoleculeObject::cleanMaterialMap();
101}
102
103///** Update the WorldScene with molecules and atomsfrom World.
104// *
105// * This function should be called after e.g. WorldTime::TimeChanged was
106// * received or after another molecule has been loaded.
107// *
108// */
109//void GLWorldScene::update()
110//{
111// const std::vector<const molecule *> &molecules =
112// const_cast<const World &>(World::getInstance()).getAllMolecules();
113//
114// for (std::vector<const molecule*>::const_iterator moliter = molecules.begin();
115// moliter != molecules.end();
116// moliter++) {
117// boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
118// // check whether molecule already exists
119// const moleculeId_t molid = (*moliter)->getId();
120// const bool mol_present = MoleculesinSceneMap.count(molid);
121// if (!mol_present)
122// moleculeInserted((*moliter)->getId());
123// }
124//
125// boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
126// MoleculeNodeMap::iterator iter = MoleculesinSceneMap.begin();
127// for (;iter != MoleculesinSceneMap.end();) {
128// const moleculeId_t molid = iter->first;
129// const molecule * const mol = const_cast<const World &>(World::getInstance()).
130// getMolecule(MoleculeById(molid));
131// const bool mol_absent = (mol == NULL);
132// // step on to next molecule before possibly removing entry and invalidating iter
133// ++iter;
134// if (mol_absent)
135// moleculeRemoved(molid);
136// }
137//
138//}
139
140void GLWorldScene::atomClicked(atomId_t no)
141{
142 LOG(3, "INFO: GLMoleculeObject_molecule - atom " << no << " has been clicked.");
143 const atom * const Walker = const_cast<const World &>(World::getInstance()).
144 getAtom(AtomById(no));
145 ASSERT( Walker != NULL,
146 "GLWorldScene::atomClicked() - clicked atom has disappeared.");
147 if (selectionMode == SelectAtom){
148 if (!World::getInstance().isSelected(Walker))
149 SelectionAtomById(std::vector<atomId_t>(1,no));
150 else
151 SelectionNotAtomById(std::vector<atomId_t>(1,no));
152 }else if (selectionMode == SelectMolecule){
153 const molecule *mol = Walker->getMolecule();
154 ASSERT(mol, "Atom without molecule has been clicked.");
155 molids_t ids(1, mol->getId());
156 if (!World::getInstance().isSelected(mol))
157 SelectionMoleculeById(ids);
158 else
159 SelectionNotMoleculeById(ids);
160 }
161 emit clicked(no);
162}
163
164void GLWorldScene::moleculeClicked(moleculeId_t no)
165{
166 LOG(3, "INFO: GLMoleculeObject_molecule - mol " << no << " has been clicked.");
167 const molecule * const mol= const_cast<const World &>(World::getInstance()).
168 getMolecule(MoleculeById(no));
169 ASSERT(mol, "Atom without molecule has been clicked.");
170 molids_t ids(1, mol->getId());
171 if (!World::getInstance().isSelected(mol))
172 SelectionMoleculeById(ids);
173 else
174 SelectionNotMoleculeById(ids);
175 emit clicked(no);
176}
177
178/** Inserts an atom into the scene before molecule is present.
179 *
180 * @param _molid molecule to insert atom for
181 * @param _atomid atom to insert
182 */
183void GLWorldScene::atomInserted(const moleculeId_t _molid, const atomId_t _atomid)
184{
185 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
186
187 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "+toString(_atomid)+".");
188
189 // check of molecule is already present
190 if (MoleculesinSceneMap.count(_molid) != 0) {
191 // pass signal through
192 } else {
193 // store signal for when it is instantiated
194 if (MoleculeMissedStateMap.count(_molid) == 0)
195 MoleculeMissedStateMap.insert( std::make_pair(_molid ,StateChangeMap_t()) );
196 MoleculeMissedStateMap[_molid].insert( std::make_pair(_atomid, atomInsertedState) );
197 }
198}
199
200/** Removes an atom into the scene before molecule is present.
201 *
202 * @param _molid molecule to insert atom for
203 * @param _atomid atom to insert
204 */
205void GLWorldScene::atomRemoved(const moleculeId_t _molid, const atomId_t _atomid)
206{
207 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+".");
208
209 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
210
211 // check of molecule is already present
212 if (MoleculesinSceneMap.count(_molid) != 0) {
213 // pass signal through
214 } else {
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, atomRemovedState) );
219 }
220}
221
222/** Prepres insertion of a molecule into the scene.
223 *
224 * This function takes up the insertion information, i.e. a molecule has been
225 * inserted and its id, and takes some immediate action (writing id into a map).
226 * But the request is then transmitted indirectly (i.e. not necessarily being
227 * processed in the same thread). Hence, we first take the request via a direction
228 * connection in the thread where the actual World::createMolecule() was called.
229 * However, the creation of the visual representation must occur in the thread
230 * who also contains GLWorldScene and GLWorldView and all further parents.
231 *
232 * That's the reason why we split here into moleculePrepareInserted and
233 * moleculeInserted.
234 *
235 * @param _mol molecule to insert
236 */
237void GLWorldScene::moleculePrepareInserted(const moleculeId_t _id)
238{
239 LOG(3, "INFO: GLWorldScene: Received signal moleculePrepareInserted for molecule "+toString(_id)+".");
240
241 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
242
243 MoleculeNodeMap::const_iterator iter = MoleculesinSceneMap.find(_id);
244 ASSERT( iter == MoleculesinSceneMap.end(),
245 "GLWorldScene::moleculeInserted() - molecule's id "+toString(_id)+" already present.");
246
247 emit moleculePreparedInserted(_id);
248}
249
250/** Inserts a molecule into the scene.
251 *
252 * \sa moleculePrepareInserted()
253 *
254 * @param _mol molecule to insert
255 */
256void GLWorldScene::moleculeInserted(const moleculeId_t _id)
257{
258 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
259
260 // check whether molecule is still present
261 if (RemovalMolecules.count(_id) != 0) {
262 RemovalMolecules.erase(_id);
263 return;
264 }
265 if (const_cast<const World &>(World::getInstance()).getMolecule(MoleculeById(_id)) == NULL) {
266 ELOG(2, "Molecule with id " << _id << " has disappeared.");
267 return;
268 }
269
270 // add new object
271 LOG(1, "DEBUG: Adding GLMoleculeObject_molecule to id " << _id);
272 GLMoleculeObject_molecule *molObject =
273 new GLMoleculeObject_molecule(GLMoleculeObject::meshEmpty, this, _id);
274 ASSERT( molObject != NULL,
275 "GLWorldScene::moleculeInserted - could not create molecule object for "+toString(_id));
276 MoleculesinSceneMap.insert( make_pair(_id, molObject) );
277
278 // now handle all state changes that came up before the instantiation
279 while (MoleculeMissedStateMap.count(_id) != 0) {
280 ASSERT( !MoleculeMissedStateMap[_id].empty(),
281 "GLWorldScene::moleculeInserted() - we have an empty state change map for molecule with id "
282 +toString(_id));
283 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
284 for (StateChangeMap_t::iterator iter = MoleculeMissedStateMap[_id].begin();
285 !MoleculeMissedStateMap[_id].empty();
286 iter = MoleculeMissedStateMap[_id].begin()) {
287 std::pair<StateChangeMap_t::iterator, StateChangeMap_t::iterator> rangeiter =
288 MoleculeMissedStateMap[_id].equal_range(iter->first);
289 const size_t StateCounts = std::distance(rangeiter.first, rangeiter.second);
290 if (StateCounts > 1) {
291 // more than one state change, have to combine
292 typedef std::map<StateChangeType, size_t> StateChangeAmounts_t;
293 StateChangeAmounts_t StateChangeAmounts;
294 for (StateChangeMap_t::const_iterator stateiter = rangeiter.first;
295 stateiter != rangeiter.second; ++stateiter)
296 ++StateChangeAmounts[stateiter->second];
297 ASSERT( StateChangeAmounts[atomInsertedState] >= StateChangeAmounts[atomRemovedState],
298 "GLWorldScene::moleculeInserted() - more atomRemoved states than atomInserted for atom "
299 +toString(iter->first));
300 if (StateChangeAmounts[atomInsertedState] > StateChangeAmounts[atomRemovedState]) {
301 LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
302 QMetaObject::invokeMethod(molObject, // pointer to a QObject
303 "atomInserted", // member name (no parameters here)
304 Qt::DirectConnection, // connection type
305 Q_ARG(const atomId_t, iter->first)); // parameters
306 } else {
307 LOG(1, "INFO: Atom " << iter->first << " has been inserted and removed already.");
308 }
309 } else {
310 // can only be an insertion
311 switch (rangeiter.first->second) {
312 case atomRemovedState:
313 ASSERT( 0,
314 "GLWorldScene::moleculeInserted() - atomRemoved state without atomInserted for atom "
315 +toString(iter->first));
316 break;
317 case atomInsertedState:
318 LOG(1, "INFO: invoking atomInserted for atom " << iter->first);
319 QMetaObject::invokeMethod(molObject, // pointer to a QObject
320 "atomInserted", // member name (no parameters here)
321 Qt::DirectConnection, // connection type
322 Q_ARG(const atomId_t, iter->first)); // parameters
323 break;
324 default:
325 ASSERT( 0,
326 "GLWorldScene::moleculeInserted() - there are unknown change states.");
327 break;
328 }
329 }
330 // removed state changes for this atom
331 MoleculeMissedStateMap[_id].erase(iter);
332 }
333 // remove state change map for the molecule
334 MoleculeMissedStateMap.erase(_id);
335 }
336
337 // now let the molObject sign on to molecule
338 molObject->activateObserver();
339
340 connect (molObject, SIGNAL(changed()), this, SIGNAL(changed()));
341 connect (molObject, SIGNAL(changeOccured()), this, SIGNAL(changeOccured()));
342 connect (molObject, SIGNAL(atomClicked(atomId_t)), this, SLOT(atomClicked(atomId_t)));
343 connect (molObject, SIGNAL(moleculeClicked(moleculeId_t)), this, SLOT(moleculeClicked(moleculeId_t)));
344 connect (molObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
345 connect (molObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
346 connect (molObject, SIGNAL(hoverChanged(const atomId_t)), this, SIGNAL(hoverChanged(const atomId_t)));
347 connect (molObject, SIGNAL(hoverChanged(const moleculeId_t, int)), this, SIGNAL(hoverChanged(const moleculeId_t, int)));
348 connect (molObject, SIGNAL(hoverChanged(const moleculeId_t, int)), this, SIGNAL(hoverChanged(const moleculeId_t, int)));
349 connect (molObject, SIGNAL(InstanceRemoved(const moleculeId_t)), this, SLOT(moleculeRemoved(const moleculeId_t)));
350
351 emit changed();
352 emit changeOccured();
353}
354
355/** Removes a molecule from the scene.
356 *
357 * * \sa moleculePrepareRemoved()
358 *
359 * @param _id id of molecule to remove
360 */
361void GLWorldScene::moleculeRemoved(const moleculeId_t _id)
362{
363 LOG(3, "INFO: GLWorldScene: Received signal moleculePrepareRemoved for molecule "+toString(_id)+".");
364
365 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
366
367 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
368 if ( iter == MoleculesinSceneMap.end()) {
369 RemovalMolecules.insert(_id);
370 } else {
371 LOG(1, "DEBUG: Removing GLMoleculeObject_molecule to id " << _id);
372 GLMoleculeObject_molecule *molObject = iter->second;
373 molObject->disconnect();
374 MoleculesinSceneMap.erase(iter);
375 delete molObject;
376 }
377
378 // remove any possible state changes left
379 {
380 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
381 MoleculeMissedStateMap.erase(_id);
382 }
383
384 emit changed();
385 emit changeOccured();
386}
387
388void GLWorldScene::moleculesVisibilityChanged(const moleculeId_t _id, bool _visible)
389{
390 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
391 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
392 ASSERT( iter != MoleculesinSceneMap.end(),
393 "GLWorldScene::moleculeInserted() - molecule's id "+toString(_id)+" is unknown.");
394
395 GLMoleculeObject_molecule *molObject = iter->second;
396 molObject->setVisible(_visible);
397
398 emit changed();
399 emit changeOccured();
400}
401
402/** Adds a shape to the scene.
403 *
404 */
405void GLWorldScene::addShape(const std::string &_name)
406{
407 Shape * const shape = ShapeRegistry::getInstance().getByName(_name);
408 if (shape != NULL) {
409 GLMoleculeObject_shape *shapeObject = new GLMoleculeObject_shape(*shape, this);
410 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
411 ASSERT(iter == ShapesinSceneMap.end(),
412 "GLWorldScene::addShape() - same shape "+_name+" added again.");
413 ShapesinSceneMap.insert( make_pair(_name, shapeObject) );
414 } else
415 ELOG(2, "GLWorldScene::addShape() - shape disappeared before we could draw it.");
416
417 emit changed();
418}
419
420void GLWorldScene::removeShape(const std::string &_name)
421{
422 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
423 ASSERT(iter != ShapesinSceneMap.end(),
424 "GLWorldScene::removeShape() - shape "+_name+" not in scene.");
425 ShapesinSceneMap.erase(iter);
426 delete(iter->second);
427
428 emit changed();
429}
430
431void GLWorldScene::updateSelectedShapes()
432{
433 foreach (QObject *obj, children()) {
434 GLMoleculeObject_shape *shapeobj = qobject_cast<GLMoleculeObject_shape *>(obj);
435 if (shapeobj){
436 shapeobj->enable(ShapeRegistry::getInstance().isSelected(shapeobj->getShape()));
437 }
438 }
439
440 emit changed();
441}
442
443void GLWorldScene::initialize(QGLView *view, QGLPainter *painter) const
444{
445 // Initialize all of the mesh objects that we have as children.
446 foreach (QObject *obj, children()) {
447 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
448 if (meshobj)
449 meshobj->initialize(view, painter);
450 }
451}
452
453void GLWorldScene::draw(QGLPainter *painter, const QVector4D &cameraPlane) const
454{
455 // Draw all of the mesh objects that we have as children.
456 foreach (QObject *obj, children()) {
457 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
458 if (meshobj)
459 meshobj->draw(painter, cameraPlane);
460 }
461}
462
463void GLWorldScene::setSelectionMode(SelectionModeType mode)
464{
465 selectionMode = mode;
466 // TODO send update to toolbar
467}
468
469void GLWorldScene::setSelectionChangedAgent(QtSelectionChangedAgent *agent)
470{
471 connect(agent, SIGNAL(atomSelected(const moleculeId_t, const atomId_t)),
472 this, SLOT(AtomSelected(const moleculeId_t, const atomId_t)));
473 connect(agent, SIGNAL(atomUnselected(const moleculeId_t, const atomId_t)),
474 this, SLOT(AtomUnselected(const moleculeId_t, const atomId_t)));
475
476 connect(agent, SIGNAL(moleculeSelected(const moleculeId_t)),
477 this, SLOT(MoleculeSelected(const moleculeId_t)));
478 connect(agent, SIGNAL(moleculeUnselected(const moleculeId_t)),
479 this, SLOT(MoleculeUnselected(const moleculeId_t)));
480}
481
482void GLWorldScene::setSelectionModeAtom()
483{
484 setSelectionMode(SelectAtom);
485}
486
487void GLWorldScene::setSelectionModeMolecule()
488{
489 setSelectionMode(SelectMolecule);
490}
491
492void GLWorldScene::changeMoleculeId(
493 GLMoleculeObject_molecule *ob,
494 const moleculeId_t oldId,
495 const moleculeId_t newId)
496{
497 LOG(3, "INFO: GLWorldScene - change molecule id " << oldId << " to " << newId << ".");
498
499 {
500 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
501 // Remove from map.
502 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(oldId);
503 ASSERT(iter != MoleculesinSceneMap.end(),
504 "GLWorldScene::changeMoleculeId() - molecule with old id "+toString(oldId)+" not on display.");
505 ASSERT(iter->second == ob,
506 "GLWorldScene::changeMoleculeId() - molecule with id "
507 +toString(oldId)+" does not match with object in MoleculesinSceneMap.");
508 MoleculesinSceneMap.erase(iter);
509
510 // Reinsert with new id.
511 {
512 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(newId);
513 ASSERT(iter == MoleculesinSceneMap.end(),
514 "GLWorldScene::changeMoleculeId() - moleculewith new id "+toString(newId)+" already known.");
515 }
516 MoleculesinSceneMap.insert( make_pair(newId, ob) );
517 }
518
519 {
520 boost::recursive_mutex::scoped_lock lock(MoleculeMissedStateMap_mutex);
521 // Remove and re-insert from map if present.
522 MoleculeMissedStateMap_t::iterator iter = MoleculeMissedStateMap.find(oldId);
523 if (iter != MoleculeMissedStateMap.end()) {
524 StateChangeMap_t changemap = iter->second;
525 MoleculeMissedStateMap.erase(iter);
526 MoleculeMissedStateMap.insert( std::make_pair(newId, changemap) );
527 }
528 }
529}
530
531void GLWorldScene::AtomSelected(const moleculeId_t _molid, const atomId_t _id)
532{
533 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
534 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
535 if (iter != MoleculesinSceneMap.end())
536 QMetaObject::invokeMethod(iter->second, // pointer to a QObject
537 "AtomSelected", // member name (no parameters here)
538 Qt::QueuedConnection, // connection type
539 Q_ARG(const atomId_t, _id)); // parameters
540 else
541 ELOG(2, "DEBUG: GLWorldScene::AtomSelected() - molecule " <<
542 _molid << " unknown to GLWorldScene.");
543}
544
545void GLWorldScene::AtomUnselected(const moleculeId_t _molid, const atomId_t _id)
546{
547 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
548 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
549 if (iter != MoleculesinSceneMap.end())
550 QMetaObject::invokeMethod(iter->second, // pointer to a QObject
551 "AtomUnselected", // member name (no parameters here)
552 Qt::QueuedConnection, // connection type
553 Q_ARG(const atomId_t, _id)); // parameters
554 else
555 ELOG(2, "GLWorldScene::AtomUnselected() - molecule "
556 << _molid << " unknown to GLWorldScene.");
557}
558
559void GLWorldScene::MoleculeSelected(const moleculeId_t _molid)
560{
561 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
562MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
563 if (iter != MoleculesinSceneMap.end())
564 QMetaObject::invokeMethod(iter->second, // pointer to a QObject
565 "Selected", // member name (no parameters here)
566 Qt::QueuedConnection); // connection type
567 else
568 ELOG(2, "GLWorldScene::MoleculeSelected() - molecule "
569 << _molid << " unknown to GLWorldScene.");
570}
571
572void GLWorldScene::MoleculeUnselected(const moleculeId_t _molid)
573{
574 boost::recursive_mutex::scoped_lock lock(MoleculeinSceneMap_mutex);
575 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
576 if (iter != MoleculesinSceneMap.end())
577 QMetaObject::invokeMethod(iter->second, // pointer to a QObject
578 "Unselected", // member name (no parameters here)
579 Qt::QueuedConnection); // connection type
580 else
581 ELOG(2, "GLWorldScene::MoleculeUnselected() - molecule "
582 << _molid << " unknown to GLWorldScene.");
583}
Note: See TracBrowser for help on using the repository browser.