source: src/UIElements/Qt4/InstanceBoard/QtObservedBond.cpp

Candidate_v1.6.1
Last change on this file was 4a38b9, checked in by Frederik Heber <frederik.heber@…>, 8 years ago

FIX: needed static_cast in QtObservedBond for stating which map<>::at() function.

  • Property mode set to 100644
File size: 12.2 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#include <boost/bind.hpp>
46
47#include "Atom/atom.hpp"
48#include "Bond/bond.hpp"
49#include "World.hpp"
50
51#include "UIElements/Qt4/InstanceBoard/ObservedValue_wCallback.hpp"
52
53using namespace boost::assign;
54
55template <class T>
56Observable * const getObservable(const T * _ptr)
57{
58 return static_cast<Observable * const>(
59 const_cast<T * const>(_ptr));
60}
61
62static QtObservedBond::ObservableCount_t initAllsignedOnChannels(const bond::ptr _bond)
63{
64 const QtObservedBond::ObservableCount_t returnlist =
65 boost::assign::list_of< QtObservedBond::ObservableCount_t::value_type >
66 ( getObservable(_bond.get()), 1);
67 return returnlist;
68}
69
70// static entities
71const Observable::channels_t
72QtObservedBond::BondDegreeChannels(1, BondObservable::DegreeChanged);
73
74
75QtObservedBond::QtObservedBond(
76 const bondId_t _id,
77 const bond::ptr _bond,
78 const QtObservedAtom::ptr &_leftatom,
79 const QtObservedAtom::ptr &_rightatom,
80 QtObservedInstanceBoard &_board,
81 QWidget * _parent) :
82 QWidget(_parent),
83 Observer("QtObservedBond"),
84 AllsignedOnChannels(initAllsignedOnChannels(_bond)),
85 bondowner(NULL),
86 oldbondId(_id),
87 leftatom(_leftatom),
88 rightatom(_rightatom),
89 index(static_cast<const ObservedValue_Index_t>(const_cast<const QtObservedBond * const>(this))),
90 board(_board),
91 BoardIsGone(false),
92 ObservedValues(QtObservedBond::MAX_ObservedTypes)
93{
94 qRegisterMetaType<bondId_t>("bondId_t");
95
96 typedef boost::function<ObservableCount_t::mapped_type& (const ObservableCount_t::key_type&)> map_accessor_t;
97 const map_accessor_t accessor =
98 boost::bind(
99 static_cast<ObservableCount_t::mapped_type& (ObservableCount_t::*) (const ObservableCount_t::key_type&)>(&ObservableCount_t::at),
100 boost::ref(subjectKilledCount), _1);
101
102 const boost::function<void ()> bondSubjectKilled(
103 boost::bind(&QtObservedBond::countValuesSubjectKilled,
104 boost::ref(*this),
105 boost::bind(&QtObservedBond::getIndex, boost::cref(*this)),
106 boost::bind(accessor,
107 getObservable(_bond.get()))));
108 initObservedValues( ObservedValues, _id, _bond, bondSubjectKilled);
109
110 // activating Observer is done by ObservedValueContainer when it's inserted
111}
112
113QtObservedBond::~QtObservedBond()
114{
115 boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(ObservedValues[BondDegree])->noteCallBackIsGone();
116
117 deactivateObserver();
118
119 destroyObservedValues(ObservedValues);
120}
121
122#ifdef HAVE_INLINE
123inline
124#endif
125int QtObservedBond::updateDegree(const bond &_bond)
126{
127 return _bond.getDegree();
128}
129
130void QtObservedBond::update(Observable *publisher)
131{
132 ASSERT(0, "QtObservedBond::update() - we are not signed on for global updates.");
133}
134
135void QtObservedBond::subjectKilled(Observable *publisher)
136{
137 ++(signedOffChannels[publisher]);
138
139 checkForRemoval(getIndex());
140}
141
142void QtObservedBond::countValuesSubjectKilled(
143 ObservedValue_Index_t _id,
144 unsigned int &_counter)
145{
146 ASSERT( _id == getIndex(),
147 "QtObservedBond::countValuesSubjectKilled() - bond "+toString(getIndex())
148 +" received countValuesSubjectKilled for bond id "+toString(_id)+".");
149
150 ++_counter;
151
152 checkForRemoval(_id);
153}
154
155void QtObservedBond::checkForRemoval(ObservedValue_Index_t _id)
156{
157 if (bondowner != NULL) {
158 // only bond needs to be destroyed to signal removal
159 const ObservableCount_t::const_iterator subjectkillediter =
160 subjectKilledCount.find(const_cast<Observable *>(bondowner));
161 const ObservableCount_t::const_iterator allsignediter =
162 AllsignedOnChannels.find(const_cast<Observable *>(bondowner));
163 const ObservableCount_t::const_iterator signedoffiter =
164 signedOffChannels.find(const_cast<Observable *>(bondowner));
165 ASSERT( (subjectkillediter != subjectKilledCount.end())
166 && (allsignediter != AllsignedOnChannels.end())
167 && (signedoffiter != signedOffChannels.end()),
168 "QtObservedBond::checkForRemoval() - something is wrong here.");
169 if ((signedoffiter->second == allsignediter->second)
170 && (subjectkillediter->second == allsignediter->second)) {
171 // remove owner: no more signOff needed
172 bondowner = NULL;
173
174 emit bondRemoved();
175
176 if (!BoardIsGone) {
177 board.markObservedBondAsDisconnected(_id);
178 board.markObservedBondForErase(_id);
179 }
180 }
181 }
182}
183
184void QtObservedBond::recieveNotification(Observable *publisher, Notification_ptr notification)
185{
186 // ObservedValues have been updated before, hence convert updates to Qt's signals
187 if (publisher == bondowner) {
188 switch (notification->getChannelNo()) {
189 case BondObservable::DegreeChanged:
190 emit degreeChanged();
191 break;
192 default:
193 ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel "
194 +toString(notification->getChannelNo())+" of the bond "
195 +toString(getBondIndex())+".");
196 break;
197 }
198 } else
199 ASSERT(0,
200 "QtObservedBond::recieveNotification() - received signal from unknown source.");
201}
202
203static QtObservedBond::ObservableCount_t::mapped_type getObservableCountValue(
204 const QtObservedBond::ObservableCount_t &_map,
205 const Observable *_obs)
206{
207 Observable * const obs_const = const_cast<Observable * const>(_obs);
208 QtObservedBond::ObservableCount_t::const_iterator iter = _map.find(obs_const);
209 ASSERT( iter != _map.end(),
210 "getObservableCount_tValue");
211 return iter->second;
212}
213
214static void assignObservableCountValue(
215 QtObservedBond::ObservableCount_t &_map,
216 const Observable *_obs,
217 const QtObservedBond::ObservableCount_t::mapped_type &_value)
218{
219 Observable * const obs_const = const_cast<Observable * const>(_obs);
220 QtObservedBond::ObservableCount_t::iterator iter = _map.find(obs_const);
221 ASSERT( iter != _map.end(),
222 "getObservableCount_tValue");
223 iter->second = _value;
224}
225
226void QtObservedBond::activateObserver()
227{
228 signedOffChannels.clear();
229 subjectKilledCount.clear();
230
231 atom * leftatomref = getAtom(getLeftAtomIndex());
232 atom * rightatomref = getAtom(getRightAtomIndex());
233 bond::ptr bondref = leftatomref->getBond(rightatomref);
234 if (bondref != NULL) {
235 // bond
236 {
237 bondowner = static_cast<const Observable *>(bondref.get());
238 bondowner->signOn(this, BondObservable::DegreeChanged);
239 subjectKilledCount.insert( std::make_pair(const_cast<Observable * const>(bondowner), 0));
240 signedOffChannels.insert( std::make_pair(const_cast<Observable * const>(bondowner), 0));
241 }
242
243 // and mark as connected
244 if (!BoardIsGone)
245 board.markObservedBondAsConnected(getIndex());
246 } else {
247 subjectKilledCount.insert( std::make_pair(const_cast<Observable * const>(bondowner), 1));
248 assignObservableCountValue(signedOffChannels, bondowner,
249 getObservableCountValue(AllsignedOnChannels, bondowner));
250 }
251
252 // pass thru to signals from both atoms
253 connect( leftatom.get(), SIGNAL(indexChanged()), this, SIGNAL(leftAtomIndexChanged()));
254 connect( leftatom.get(), SIGNAL(elementChanged()), this, SIGNAL(leftAtomElementChanged()));
255 connect( leftatom.get(), SIGNAL(positionChanged()), this, SIGNAL(leftAtomPositionChanged()));
256 connect( leftatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(leftmoleculeChanged()));
257 connect( rightatom.get(), SIGNAL(indexChanged()), this, SIGNAL(rightAtomIndexChanged()));
258 connect( rightatom.get(), SIGNAL(elementChanged()), this, SIGNAL(rightAtomElementChanged()));
259 connect( rightatom.get(), SIGNAL(positionChanged()), this, SIGNAL(rightAtomPositionChanged()));
260 connect( rightatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(rightmoleculeChanged()));
261}
262
263void QtObservedBond::deactivateObserver()
264{
265 if (bondowner != NULL) {
266 const ObservableCount_t::iterator subjectkilledbonditer =
267 subjectKilledCount.find(const_cast<Observable *>(bondowner));
268 ASSERT( (subjectkilledbonditer != subjectKilledCount.end()),
269 "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for bond"
270 +toString(bondowner)+","
271 +" has activateObserver() been called?");
272 if (subjectkilledbonditer->second == 0)
273 bondowner->signOff(this, BondObservable::DegreeChanged);
274 subjectkilledbonditer->second = 1;
275 bondowner = NULL;
276 signedOffChannels.clear();
277 signedOffChannels.insert(AllsignedOnChannels.begin(), AllsignedOnChannels.end());
278
279 if (!BoardIsGone)
280 board.markObservedBondAsDisconnected(getIndex());
281 }
282}
283
284const atom * const QtObservedBond::getAtomConst(const atomId_t _id)
285{
286 const atom * const _atom = const_cast<const World &>(World::getInstance()).
287 getAtom(AtomById(_id));
288 return _atom;
289}
290
291atom * const QtObservedBond::getAtom(const atomId_t _id)
292{
293 atom * const _atom = World::getInstance().getAtom(AtomById(_id));
294 return _atom;
295}
296
297void QtObservedBond::initObservedValues(
298 ObservedValues_t &_ObservedValues,
299 const bondId_t _id,
300 const bond::ptr _bondref,
301 const boost::function<void()> &_bondsubjectKilled)
302{
303 // fill ObservedValues: index first
304 const boost::function<ObservedValue_Index_t ()> BondIndexGetter =
305 boost::bind(&QtObservedBond::getIndex,
306 boost::cref(*this));
307
308 // fill ObservedValues: then all the other that need index
309 const boost::function<int ()> BondDegreeUpdater(
310 boost::bind(&QtObservedBond::updateDegree, boost::cref(*_bondref)));
311
312 _ObservedValues[BondDegree] = new ObservedValue_wCallback<int, ObservedValue_Index_t>(
313 _bondref.get(),
314 BondDegreeUpdater,
315 "BondDegree_bond"+toString(_id),
316 BondDegreeUpdater(),
317 BondDegreeChannels,
318 _bondsubjectKilled);
319}
320
321void QtObservedBond::destroyObservedValues(
322 std::vector<boost::any> &_ObservedValues)
323{
324 delete boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(_ObservedValues[BondDegree]);
325 _ObservedValues.clear();
326}
327
328ObservedValue_Index_t QtObservedBond::getIndex() const
329{
330 ASSERT( index != NULL,
331 "QtObservedBond::getIndex() - index is NULL");
332 return index;
333}
334
335const QtObservedBond::bondId_t QtObservedBond::getBondIndex() const
336{
337 return QtObservedBond::bondId_t(getLeftAtomIndex(), getRightAtomIndex());
338}
339
340const int& QtObservedBond::getBondDegree() const
341{
342 return boost::any_cast<ObservedValue_wCallback<int, ObservedValue_Index_t> *>(ObservedValues[BondDegree])->get();
343}
344
345const atomId_t& QtObservedBond::getLeftAtomIndex() const
346{
347 return leftatom->getAtomIndex();
348}
349
350const atomicNumber_t& QtObservedBond::getLeftAtomElement() const
351{
352 return leftatom->getAtomElement();
353}
354
355const Vector& QtObservedBond::getLeftAtomPosition() const
356{
357 return leftatom->getAtomPosition();
358}
359
360const moleculeId_t QtObservedBond::getLeftMoleculeIndex() const
361{
362 if (leftatom->getMoleculeRef() != NULL)
363 return leftatom->getMoleculeRef()->getMolIndex();
364 else
365 return (moleculeId_t)-1;
366}
367
368const atomId_t& QtObservedBond::getRightAtomIndex() const
369{
370 return rightatom->getAtomIndex();
371}
372
373const atomicNumber_t& QtObservedBond::getRightAtomElement() const
374{
375 return rightatom->getAtomElement();
376}
377
378const Vector& QtObservedBond::getRightAtomPosition() const
379{
380 return rightatom->getAtomPosition();
381}
382
383const moleculeId_t QtObservedBond::getRightMoleculeIndex() const
384{
385 if (rightatom->getMoleculeRef() != NULL)
386 return rightatom->getMoleculeRef()->getMolIndex();
387 else
388 return (moleculeId_t)-1;
389}
Note: See TracBrowser for help on using the repository browser.