/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2016 Frederik Heber. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* QtObservedBond.cpp
*
* Created on: Mar 03, 2016
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "QtObservedBond.hpp"
#include
#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
#include "CodePatterns/MemDebug.hpp"
#include
#include "Atom/atom.hpp"
#include "Bond/bond.hpp"
#include "World.hpp"
#include "UIElements/Qt4/InstanceBoard/ObservedValue_wCallback.hpp"
using namespace boost::assign;
template
Observable * const getObservable(const T * _ptr)
{
return static_cast(
const_cast(_ptr));
}
static QtObservedBond::ObservableCount_t initAllsignedOnChannels(const bond::ptr _bond)
{
const QtObservedBond::ObservableCount_t returnlist =
boost::assign::list_of< QtObservedBond::ObservableCount_t::value_type >
( getObservable(_bond.get()), 1);
return returnlist;
}
// static entities
const Observable::channels_t
QtObservedBond::BondDegreeChannels(1, BondObservable::DegreeChanged);
QtObservedBond::QtObservedBond(
const bondId_t _id,
const bond::ptr _bond,
const QtObservedAtom::ptr &_leftatom,
const QtObservedAtom::ptr &_rightatom,
QtObservedInstanceBoard &_board,
QWidget * _parent) :
QWidget(_parent),
Observer("QtObservedBond"),
AllsignedOnChannels(initAllsignedOnChannels(_bond)),
bondowner(NULL),
oldbondId(_id),
leftatom(_leftatom),
rightatom(_rightatom),
index(static_cast(const_cast(this))),
board(_board),
BoardIsGone(false),
ObservedValues(QtObservedBond::MAX_ObservedTypes)
{
qRegisterMetaType("bondId_t");
typedef boost::function map_accessor_t;
const map_accessor_t accessor =
boost::bind(
&ObservableCount_t::at,
boost::ref(subjectKilledCount), _1);
const boost::function bondSubjectKilled(
boost::bind(&QtObservedBond::countValuesSubjectKilled,
boost::ref(*this),
boost::bind(&QtObservedBond::getIndex, boost::cref(*this)),
boost::bind(accessor,
getObservable(_bond.get()))));
initObservedValues( ObservedValues, _id, _bond, bondSubjectKilled);
// activating Observer is done by ObservedValueContainer when it's inserted
}
QtObservedBond::~QtObservedBond()
{
boost::any_cast *>(ObservedValues[BondDegree])->noteCallBackIsGone();
deactivateObserver();
destroyObservedValues(ObservedValues);
}
#ifdef HAVE_INLINE
inline
#endif
int QtObservedBond::updateDegree(const bond &_bond)
{
return _bond.getDegree();
}
void QtObservedBond::update(Observable *publisher)
{
ASSERT(0, "QtObservedBond::update() - we are not signed on for global updates.");
}
void QtObservedBond::subjectKilled(Observable *publisher)
{
++(signedOffChannels[publisher]);
checkForRemoval(getIndex());
}
void QtObservedBond::countValuesSubjectKilled(
ObservedValue_Index_t _id,
unsigned int &_counter)
{
ASSERT( _id == getIndex(),
"QtObservedBond::countValuesSubjectKilled() - bond "+toString(getIndex())
+" received countValuesSubjectKilled for bond id "+toString(_id)+".");
++_counter;
checkForRemoval(_id);
}
void QtObservedBond::checkForRemoval(ObservedValue_Index_t _id)
{
if (bondowner != NULL) {
// only bond needs to be destroyed to signal removal
const ObservableCount_t::const_iterator subjectkillediter =
subjectKilledCount.find(const_cast(bondowner));
const ObservableCount_t::const_iterator allsignediter =
AllsignedOnChannels.find(const_cast(bondowner));
const ObservableCount_t::const_iterator signedoffiter =
signedOffChannels.find(const_cast(bondowner));
ASSERT( (subjectkillediter != subjectKilledCount.end())
&& (allsignediter != AllsignedOnChannels.end())
&& (signedoffiter != signedOffChannels.end()),
"QtObservedBond::checkForRemoval() - something is wrong here.");
if ((signedoffiter->second == allsignediter->second)
&& (subjectkillediter->second == allsignediter->second)) {
// remove owner: no more signOff needed
bondowner = NULL;
emit bondRemoved();
if (!BoardIsGone) {
board.markObservedBondAsDisconnected(_id);
board.markObservedBondForErase(_id);
}
}
}
}
void QtObservedBond::recieveNotification(Observable *publisher, Notification_ptr notification)
{
// ObservedValues have been updated before, hence convert updates to Qt's signals
if (publisher == bondowner) {
switch (notification->getChannelNo()) {
case BondObservable::DegreeChanged:
emit degreeChanged();
break;
default:
ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel "
+toString(notification->getChannelNo())+" of the bond "
+toString(getBondIndex())+".");
break;
}
} else
ASSERT(0,
"QtObservedBond::recieveNotification() - received signal from unknown source.");
}
static QtObservedBond::ObservableCount_t::mapped_type getObservableCountValue(
const QtObservedBond::ObservableCount_t &_map,
const Observable *_obs)
{
Observable * const obs_const = const_cast(_obs);
QtObservedBond::ObservableCount_t::const_iterator iter = _map.find(obs_const);
ASSERT( iter != _map.end(),
"getObservableCount_tValue");
return iter->second;
}
static void assignObservableCountValue(
QtObservedBond::ObservableCount_t &_map,
const Observable *_obs,
const QtObservedBond::ObservableCount_t::mapped_type &_value)
{
Observable * const obs_const = const_cast(_obs);
QtObservedBond::ObservableCount_t::iterator iter = _map.find(obs_const);
ASSERT( iter != _map.end(),
"getObservableCount_tValue");
iter->second = _value;
}
void QtObservedBond::activateObserver()
{
signedOffChannels.clear();
subjectKilledCount.clear();
atom * leftatomref = getAtom(getLeftAtomIndex());
atom * rightatomref = getAtom(getRightAtomIndex());
bond::ptr bondref = leftatomref->getBond(rightatomref);
if (bondref != NULL) {
// bond
{
bondowner = static_cast(bondref.get());
bondowner->signOn(this, BondObservable::DegreeChanged);
subjectKilledCount.insert( std::make_pair(const_cast(bondowner), 0));
signedOffChannels.insert( std::make_pair(const_cast(bondowner), 0));
}
// and mark as connected
if (!BoardIsGone)
board.markObservedBondAsConnected(getIndex());
} else {
subjectKilledCount.insert( std::make_pair(const_cast(bondowner), 1));
assignObservableCountValue(signedOffChannels, bondowner,
getObservableCountValue(AllsignedOnChannels, bondowner));
}
// pass thru to signals from both atoms
connect( leftatom.get(), SIGNAL(indexChanged(const atomId_t, const atomId_t)),
this, SIGNAL(leftAtomIndexChanged(atomId_t, atomId_t)));
connect( leftatom.get(), SIGNAL(elementChanged()), this, SIGNAL(leftAtomElementChanged()));
connect( leftatom.get(), SIGNAL(positionChanged()), this, SIGNAL(leftAtomPositionChanged()));
connect( leftatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(leftmoleculeChanged()));
connect( rightatom.get(), SIGNAL(indexChanged(const atomId_t, const atomId_t)),
this, SIGNAL(rightAtomIndexChanged(atomId_t, atomId_t)));
connect( rightatom.get(), SIGNAL(elementChanged()), this, SIGNAL(rightAtomElementChanged()));
connect( rightatom.get(), SIGNAL(positionChanged()), this, SIGNAL(rightAtomPositionChanged()));
connect( rightatom.get(), SIGNAL(moleculeChanged()), this, SIGNAL(rightmoleculeChanged()));
}
void QtObservedBond::deactivateObserver()
{
if (bondowner != NULL) {
const ObservableCount_t::iterator subjectkilledbonditer =
subjectKilledCount.find(const_cast(bondowner));
ASSERT( (subjectkilledbonditer != subjectKilledCount.end()),
"QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for bond"
+toString(bondowner)+","
+" has activateObserver() been called?");
if (subjectkilledbonditer->second == 0)
bondowner->signOff(this, BondObservable::DegreeChanged);
subjectkilledbonditer->second = 1;
bondowner = NULL;
signedOffChannels.clear();
signedOffChannels.insert(AllsignedOnChannels.begin(), AllsignedOnChannels.end());
if (!BoardIsGone)
board.markObservedBondAsDisconnected(getIndex());
}
}
const atom * const QtObservedBond::getAtomConst(const atomId_t _id)
{
const atom * const _atom = const_cast(World::getInstance()).
getAtom(AtomById(_id));
return _atom;
}
atom * const QtObservedBond::getAtom(const atomId_t _id)
{
atom * const _atom = World::getInstance().getAtom(AtomById(_id));
return _atom;
}
void QtObservedBond::initObservedValues(
ObservedValues_t &_ObservedValues,
const bondId_t _id,
const bond::ptr _bondref,
const boost::function &_bondsubjectKilled)
{
// fill ObservedValues: index first
const boost::function BondIndexGetter =
boost::bind(&QtObservedBond::getIndex,
boost::cref(*this));
// fill ObservedValues: then all the other that need index
const boost::function BondDegreeUpdater(
boost::bind(&QtObservedBond::updateDegree, boost::cref(*_bondref)));
_ObservedValues[BondDegree] = new ObservedValue_wCallback(
_bondref.get(),
BondDegreeUpdater,
"BondDegree_bond"+toString(_id),
BondDegreeUpdater(),
BondDegreeChannels,
_bondsubjectKilled);
}
void QtObservedBond::destroyObservedValues(
std::vector &_ObservedValues)
{
delete boost::any_cast *>(_ObservedValues[BondDegree]);
_ObservedValues.clear();
}
ObservedValue_Index_t QtObservedBond::getIndex() const
{
ASSERT( index != NULL,
"QtObservedBond::getIndex() - index is NULL");
return index;
}
const QtObservedBond::bondId_t QtObservedBond::getBondIndex() const
{
return QtObservedBond::bondId_t(getLeftAtomIndex(), getRightAtomIndex());
}
const int& QtObservedBond::getBondDegree() const
{
return boost::any_cast *>(ObservedValues[BondDegree])->get();
}
const atomId_t& QtObservedBond::getLeftAtomIndex() const
{
return leftatom->getAtomIndex();
}
const atomicNumber_t& QtObservedBond::getLeftAtomElement() const
{
return leftatom->getAtomElement();
}
const Vector& QtObservedBond::getLeftAtomPosition() const
{
return leftatom->getAtomPosition();
}
const moleculeId_t QtObservedBond::getLeftMoleculeIndex() const
{
if (leftatom->getMoleculeRef() != NULL)
return leftatom->getMoleculeRef()->getMolIndex();
else
return (moleculeId_t)-1;
}
const atomId_t& QtObservedBond::getRightAtomIndex() const
{
return rightatom->getAtomIndex();
}
const atomicNumber_t& QtObservedBond::getRightAtomElement() const
{
return rightatom->getAtomElement();
}
const Vector& QtObservedBond::getRightAtomPosition() const
{
return rightatom->getAtomPosition();
}
const moleculeId_t QtObservedBond::getRightMoleculeIndex() const
{
if (rightatom->getMoleculeRef() != NULL)
return rightatom->getMoleculeRef()->getMolIndex();
else
return (moleculeId_t)-1;
}