source: src/UIElements/Qt4/InstanceBoard/QtObservedBond.cpp@ 7f185f9

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

QtObservedBond also offers direct access to stored QtObservedAtoms as const refs.

  • leftatom and rightatom are const throughout the lifetime of the bond. Hence, there is no need to update them and we simply store the refs directly. This will be different for the atom, where the molecule ref may change over the lifetime!
  • Property mode set to 100644
File size: 13.0 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2016 Frederik Heber. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * QtObservedBond.cpp
25 *
26 * Created on: Mar 03, 2016
27 * Author: heber
28 */
29
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "QtObservedBond.hpp"
37
38#include <QtCore/QMetaType>
39
40#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
41
42#include "CodePatterns/MemDebug.hpp"
43
44#include <boost/assign.hpp>
45
46#include "Atom/atom.hpp"
47#include "Bond/bond.hpp"
48#include "World.hpp"
49
50#include "UIElements/Qt4/InstanceBoard/ObservedValue_wCallback.hpp"
51
52using namespace boost::assign;
53
54static const Observable::channels_t getAllObservedAtomChannels()
55{
56 Observable::channels_t channels;
57 channels +=
58 AtomObservable::IndexChanged,
59 AtomObservable::ElementChanged,
60 AtomObservable::PositionChanged;
61 return channels;
62}
63
64static const molecule * getMolecule(const bond::ptr _bond)
65{
66 ASSERT( _bond->leftatom->getMolecule() == _bond->rightatom->getMolecule(),
67 "getMolecule() - leftatom and rightatom belong to different molecules.");
68 return _bond->leftatom->getMolecule();
69}
70
71static const molecule * const getMoleculeConst(const bond::ptr _bond)
72{
73 ASSERT( _bond->leftatom->getMolecule() == _bond->rightatom->getMolecule(),
74 "getMolecule() - leftatom and rightatom belong to different molecules.");
75 return _bond->leftatom->getMolecule();
76}
77
78template <class T>
79Observable * const getObservable(const T * _ptr)
80{
81 return static_cast<Observable * const>(
82 const_cast<T * const>(_ptr));
83}
84
85static QtObservedBond::ObservableCount_t initAllsignedOnChannels(const bond::ptr _bond)
86{
87 const QtObservedBond::ObservableCount_t returnlist =
88 boost::assign::list_of< QtObservedBond::ObservableCount_t::value_type >
89 ( getObservable(_bond.get()), 1)
90 ( getObservable(_bond->leftatom), getAllObservedAtomChannels().size())
91 ( getObservable(_bond->rightatom), getAllObservedAtomChannels().size())
92 ( getObservable(getMolecule(_bond)), 1);
93 return returnlist;
94}
95
96
97// static entities
98const Observable::channels_t
99QtObservedBond::BondDegreeChannels(1, BondObservable::DegreeChanged);
100
101
102QtObservedBond::QtObservedBond(
103 const bondId_t _id,
104 const bond::ptr _bond,
105 const QtObservedAtom::ptr &_leftatom,
106 const QtObservedAtom::ptr &_rightatom,
107 QtObservedInstanceBoard &_board,
108 QWidget * _parent) :
109 QWidget(_parent),
110 Observer("QtObservedBond"),
111 AllsignedOnChannels(initAllsignedOnChannels(_bond)),
112 bondowner(NULL),
113 oldbondId(_id),
114 leftatom(_leftatom),
115 rightatom(_rightatom),
116 board(_board),
117 BoardIsGone(false),
118 ObservedValues(QtObservedBond::MAX_ObservedTypes)
119{
120 qRegisterMetaType<bondId_t>("bondId_t");
121
122 typedef boost::function<ObservableCount_t::mapped_type& (const ObservableCount_t::key_type&)> map_accessor_t;
123 const map_accessor_t accessor =
124 boost::bind<ObservableCount_t::mapped_type&>(
125 &ObservableCount_t::at,
126 boost::ref(subjectKilledCount), _1);
127
128 const boost::function<void ()> bondSubjectKilled(
129 boost::bind(&QtObservedBond::countValuesSubjectKilled,
130 boost::ref(*this),
131 boost::bind(&QtObservedBond::getIndex, boost::cref(*this)),
132 boost::bind(accessor,
133 getObservable(_bond.get()))));
134 initObservedValues( ObservedValues, _id, _bond, bondSubjectKilled);
135
136 // activating Observer is done by ObservedValueContainer when it's inserted
137}
138
139QtObservedBond::~QtObservedBond()
140{
141 boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(ObservedValues[BondDegree])->noteCallBackIsGone();
142
143 deactivateObserver();
144
145 destroyObservedValues(ObservedValues);
146}
147
148#ifdef HAVE_INLINE
149inline
150#endif
151int QtObservedBond::updateDegree(const bond &_bond)
152{
153 return _bond.getDegree();
154}
155
156void QtObservedBond::update(Observable *publisher)
157{
158 ASSERT(0, "QtObservedBond::update() - we are not signed on for global updates.");
159}
160
161void QtObservedBond::subjectKilled(Observable *publisher)
162{
163 ++(signedOffChannels[publisher]);
164
165 checkForRemoval(getIndex());
166}
167
168void QtObservedBond::countValuesSubjectKilled(
169 ObservedValue_Index_t _id,
170 unsigned int &_counter)
171{
172 ASSERT( _id == getIndex(),
173 "QtObservedBond::countValuesSubjectKilled() - bond "+toString(getIndex())
174 +" received countValuesSubjectKilled for bond id "+toString(_id)+".");
175
176 ++_counter;
177
178 checkForRemoval(_id);
179}
180
181void QtObservedBond::checkForRemoval(ObservedValue_Index_t _id)
182{
183 if (bondowner != NULL) {
184 // only bond needs to be destroyed to signal removal
185 const ObservableCount_t::const_iterator subjectkillediter =
186 subjectKilledCount.find(const_cast<Observable *>(bondowner));
187 const ObservableCount_t::const_iterator allsignediter =
188 AllsignedOnChannels.find(const_cast<Observable *>(bondowner));
189 const ObservableCount_t::const_iterator signedoffiter =
190 signedOffChannels.find(const_cast<Observable *>(bondowner));
191 ASSERT( (subjectkillediter != subjectKilledCount.end())
192 && (allsignediter != AllsignedOnChannels.end())
193 && (signedoffiter != signedOffChannels.end()),
194 "QtObservedBond::checkForRemoval() - something is wrong here.");
195 if ((signedoffiter->second == allsignediter->second)
196 && (subjectkillediter->second == allsignediter->second)) {
197 // remove owner: no more signOff needed
198 bondowner = NULL;
199
200 emit bondRemoved();
201
202 if (!BoardIsGone) {
203 board.markObservedBondAsDisconnected(_id);
204 board.markObservedBondForErase(_id);
205 }
206 }
207 }
208}
209
210void QtObservedBond::recieveNotification(Observable *publisher, Notification_ptr notification)
211{
212 // ObservedValues have been updated before, hence convert updates to Qt's signals
213 if (publisher == bondowner) {
214 switch (notification->getChannelNo()) {
215 case BondObservable::DegreeChanged:
216 emit degreeChanged();
217 break;
218 default:
219 ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel "
220 +toString(notification->getChannelNo())+" of the bond "
221 +toString(getBondIndex())+".");
222 break;
223 }
224 } else
225 ASSERT(0,
226 "QtObservedBond::recieveNotification() - received signal from unknown source.");
227}
228
229static QtObservedBond::ObservableCount_t::mapped_type getObservableCountValue(
230 const QtObservedBond::ObservableCount_t &_map,
231 const Observable *_obs)
232{
233 Observable * const obs_const = const_cast<Observable * const>(_obs);
234 QtObservedBond::ObservableCount_t::const_iterator iter = _map.find(obs_const);
235 ASSERT( iter != _map.end(),
236 "getObservableCount_tValue");
237 return iter->second;
238}
239
240static void assignObservableCountValue(
241 QtObservedBond::ObservableCount_t &_map,
242 const Observable *_obs,
243 const QtObservedBond::ObservableCount_t::mapped_type &_value)
244{
245 Observable * const obs_const = const_cast<Observable * const>(_obs);
246 QtObservedBond::ObservableCount_t::iterator iter = _map.find(obs_const);
247 ASSERT( iter != _map.end(),
248 "getObservableCount_tValue");
249 iter->second = _value;
250}
251
252void QtObservedBond::activateObserver()
253{
254 signedOffChannels.clear();
255 subjectKilledCount.clear();
256
257 atom * leftatomref = getAtom(getLeftAtomIndex());
258 atom * rightatomref = getAtom(getRightAtomIndex());
259 bond::ptr bondref = leftatomref->getBond(rightatomref);
260 if (bondref != NULL) {
261 // bond
262 {
263 bondowner = static_cast<const Observable *>(bondref.get());
264 bondowner->signOn(this, BondObservable::DegreeChanged);
265 subjectKilledCount.insert( std::make_pair(const_cast<Observable * const>(bondowner), 0));
266 signedOffChannels.insert( std::make_pair(const_cast<Observable * const>(bondowner), 0));
267 }
268
269 // and mark as connected
270 if (!BoardIsGone)
271 board.markObservedBondAsConnected(getIndex());
272 } else {
273 subjectKilledCount.insert( std::make_pair(const_cast<Observable * const>(bondowner), 1));
274 assignObservableCountValue(signedOffChannels, bondowner,
275 getObservableCountValue(AllsignedOnChannels, bondowner));
276 }
277
278 // pass thru to signals from both atoms
279 connect( leftatom.get(), SIGNAL(indexChanged(const atomId_t, const atomId_t)),
280 this, SIGNAL(leftAtomIndexChanged(atomId_t, atomId_t)));
281 connect( leftatom.get(), SIGNAL(elementChanged()), this, SIGNAL(leftAtomElementChanged()));
282 connect( leftatom.get(), SIGNAL(positionChanged()), this, SIGNAL(leftAtomPositionChanged()));
283 connect( leftatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(leftmoleculeChanged()));
284 connect( rightatom.get(), SIGNAL(indexChanged(const atomId_t, const atomId_t)),
285 this, SIGNAL(rightAtomIndexChanged(atomId_t, atomId_t)));
286 connect( rightatom.get(), SIGNAL(elementChanged()), this, SIGNAL(rightAtomElementChanged()));
287 connect( rightatom.get(), SIGNAL(positionChanged()), this, SIGNAL(rightAtomPositionChanged()));
288 connect( rightatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(rightmoleculeChanged()));
289}
290
291void QtObservedBond::deactivateObserver()
292{
293 if (bondowner != NULL) {
294 const ObservableCount_t::iterator subjectkilledbonditer =
295 subjectKilledCount.find(const_cast<Observable *>(bondowner));
296 ASSERT( (subjectkilledbonditer != subjectKilledCount.end()),
297 "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for bond"
298 +toString(bondowner)+","
299 +" has activateObserver() been called?");
300 if (subjectkilledbonditer->second == 0)
301 bondowner->signOff(this, BondObservable::DegreeChanged);
302 subjectkilledbonditer->second = 1;
303 bondowner = NULL;
304 signedOffChannels.clear();
305 signedOffChannels.insert(AllsignedOnChannels.begin(), AllsignedOnChannels.end());
306
307 if (!BoardIsGone)
308 board.markObservedBondAsDisconnected(getIndex());
309 }
310}
311
312const atom * const QtObservedBond::getAtomConst(const atomId_t _id)
313{
314 const atom * const _atom = const_cast<const World &>(World::getInstance()).
315 getAtom(AtomById(_id));
316 return _atom;
317}
318
319atom * const QtObservedBond::getAtom(const atomId_t _id)
320{
321 atom * const _atom = World::getInstance().getAtom(AtomById(_id));
322 return _atom;
323}
324
325void QtObservedBond::initObservedValues(
326 ObservedValues_t &_ObservedValues,
327 const bondId_t _id,
328 const bond::ptr _bondref,
329 const boost::function<void()> &_bondsubjectKilled)
330{
331 // fill ObservedValues: index first
332 const boost::function<ObservedValue_Index_t ()> BondIndexGetter =
333 boost::bind(&QtObservedBond::getIndex,
334 boost::cref(*this));
335
336 // fill ObservedValues: then all the other that need index
337 const boost::function<int ()> BondDegreeUpdater(
338 boost::bind(&QtObservedBond::updateDegree, boost::cref(*_bondref)));
339
340 _ObservedValues[BondDegree] = new ObservedValue_wCallback<int, ObservedValue_Index_t>(
341 _bondref.get(),
342 BondDegreeUpdater,
343 "BondDegree_bond"+toString(_id),
344 BondDegreeUpdater(),
345 BondDegreeChannels,
346 _bondsubjectKilled);
347}
348
349void QtObservedBond::destroyObservedValues(
350 std::vector<boost::any> &_ObservedValues)
351{
352 delete boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(_ObservedValues[BondDegree]);
353 _ObservedValues.clear();
354}
355
356ObservedValue_Index_t QtObservedBond::getIndex() const
357{
358 ASSERT( bondowner != NULL,
359 "QtObservedBond::getIndex() - index is NULL");
360 return bondowner;
361}
362
363const QtObservedBond::bondId_t QtObservedBond::getBondIndex() const
364{
365 return QtObservedBond::bondId_t(getLeftAtomIndex(), getRightAtomIndex());
366}
367
368const int& QtObservedBond::getBondDegree() const
369{
370 return boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(ObservedValues[BondDegree])->get();
371}
372
373const atomId_t& QtObservedBond::getLeftAtomIndex() const
374{
375 return leftatom->getAtomIndex();
376}
377
378const atomicNumber_t& QtObservedBond::getLeftAtomElement() const
379{
380 return leftatom->getAtomElement();
381}
382
383const Vector& QtObservedBond::getLeftAtomPosition() const
384{
385 return leftatom->getAtomPosition();
386}
387
388const moleculeId_t QtObservedBond::getLeftMoleculeIndex() const
389{
390 return leftatom->getMoleculeIndex();
391}
392
393const atomId_t& QtObservedBond::getRightAtomIndex() const
394{
395 return rightatom->getAtomIndex();
396}
397
398const atomicNumber_t& QtObservedBond::getRightAtomElement() const
399{
400 return rightatom->getAtomElement();
401}
402
403const Vector& QtObservedBond::getRightAtomPosition() const
404{
405 return rightatom->getAtomPosition();
406}
407
408const moleculeId_t QtObservedBond::getRightMoleculeIndex() const
409{
410 return rightatom->getMoleculeIndex();
411}
Note: See TracBrowser for help on using the repository browser.