/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2015 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 .
*/
/*
* QtObservedAtom.cpp
*
* Created on: Oct 28, 2015
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "QtObservedAtom.hpp"
#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
#include "CodePatterns/MemDebug.hpp"
#include
#include "Atom/atom.hpp"
#include "Bond/bond.hpp"
#include "Descriptors/AtomIdDescriptor.hpp"
#include "Element/element.hpp"
#include "World.hpp"
#include "UIElements/Qt4/InstanceBoard/ObservedValue_wCallback.hpp"
using namespace boost::assign;
static const Observable::channels_t getAtomBondsChannels()
{
Observable::channels_t channels;
channels += AtomObservable::BondsAdded, AtomObservable::BondsRemoved;
return channels;
}
static const Observable::channels_t getAllObservedChannels()
{
Observable::channels_t channels;
channels +=
AtomObservable::IndexChanged,
AtomObservable::BondsAdded,
AtomObservable::BondsRemoved,
AtomObservable::MoleculeChanged,
AtomObservable::NameChanged,
AtomObservable::ElementChanged,
AtomObservable::PositionChanged,
AtomObservable::SelectionChanged;
return channels;
}
// static entities
const Observable::channels_t
QtObservedAtom::AtomIndexChannels(1, AtomObservable::IndexChanged);
const Observable::channels_t
QtObservedAtom::AtomBondsChannels(getAtomBondsChannels());
const Observable::channels_t
QtObservedAtom::AtomElementChannels(1, AtomObservable::ElementChanged);
const Observable::channels_t
QtObservedAtom::AtomMoleculeIndexChannels(1, AtomObservable::MoleculeChanged);
const Observable::channels_t
QtObservedAtom::AtomNameChannels(1, AtomObservable::NameChanged);
const Observable::channels_t
QtObservedAtom::AtomPositionChannels(1, AtomObservable::PositionChanged);
const Observable::channels_t
QtObservedAtom::AtomSelectedChannels(1, AtomObservable::SelectionChanged);
QtObservedAtom::QtObservedAtom(
const ObservedValues_t &_ObservedValues,
QtObservedInstanceBoard &_board,
QWidget * _parent) :
QWidget(_parent),
Observer("QtObservedAtom"),
subjectKilledCount(0),
AllsignedOnChannels(getAllObservedChannels().size()),
signedOffChannels(0),
owner(NULL),
board(_board),
BoardIsGone(false),
ObservedValues(_ObservedValues)
{
// activating Observer is done by ObservedValueContainer when it's prepared
}
QtObservedAtom::~QtObservedAtom()
{
boost::any_cast *>(ObservedValues[AtomIndex])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomBonds])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomElement])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomMoleculeIndex])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomName])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomPosition])->noteCallBackIsGone();
boost::any_cast *>(ObservedValues[AtomSelected])->noteCallBackIsGone();
deactivateObserver();
}
const atom * const QtObservedAtom::getAtomConst(const atomId_t _id)
{
const atom * const _atom = const_cast(World::getInstance()).
getAtom(AtomById(_id));
return _atom;
}
atom * const QtObservedAtom::getAtom(const atomId_t _id)
{
atom * const _atom = World::getInstance().getAtom(AtomById(_id));
return _atom;
}
atomId_t QtObservedAtom::updateIndex()
{
return const_cast(World::getInstance()).lastChangedAtomId();
}
QtObservedAtom::ListOfBonds_t QtObservedAtom::updateBonds(
const boost::function &_getAtomIndex)
{
ListOfBonds_t ListOfBonds;
const atom * const _atom = getAtomConst(_getAtomIndex());
if (_atom != NULL) {
// make sure bonds is up-to-date
const BondList ListBonds = _atom->getListOfBonds();
for (BondList::const_iterator iter = ListBonds.begin();
iter != ListBonds.end();
++iter)
ListOfBonds.insert( ListOfBonds.end(), std::make_pair(
(*iter)->leftatom->getId(),
(*iter)->rightatom->getId()) );
}
return ListOfBonds;
}
atomicNumber_t QtObservedAtom::updateElement(
const boost::function &_getAtomIndex)
{
const atom * const _atom = getAtomConst(_getAtomIndex());
if (_atom != NULL) {
return _atom->getElementNo();
} else {
return (atomicNumber_t)-1;
}
}
moleculeId_t QtObservedAtom::updateMoleculeIndex(
const boost::function &_getAtomIndex)
{
const atom * const _atom = getAtomConst(_getAtomIndex());
if ((_atom != NULL) && (_atom->getMolecule() != NULL)) {
return _atom->getMolecule()->getId();
} else {
return (moleculeId_t)0;
}
}
std::string QtObservedAtom::updateName(
const boost::function &_getAtomIndex)
{
const atom * const _atom = getAtomConst(_getAtomIndex());
if (_atom != NULL) {
return _atom->getName();
} else {
return std::string("");
}
}
Vector QtObservedAtom::updatePosition(
const boost::function &_getAtomIndex)
{
const atom * const _atom = getAtomConst(_getAtomIndex());
if (_atom != NULL) {
return _atom->getPosition();
} else {
return zeroVec;
}
}
bool QtObservedAtom::updateSelected(
const boost::function &_getAtomIndex)
{
const atom * const _atom = getAtomConst(_getAtomIndex());
if (_atom != NULL) {
return _atom->getSelected();
} else {
return false;
}
}
void QtObservedAtom::update(Observable *publisher)
{
ASSERT(0, "QtObservedAtom::update() - we are not signed on for global updates.");
}
void QtObservedAtom::subjectKilled(Observable *publisher)
{
++signedOffChannels;
if (signedOffChannels == AllsignedOnChannels) {
// remove owner: no more signOff needed
owner = NULL;
emit atomRemoved();
if (!BoardIsGone) {
board.markObservedAtomAsDisconnected(getAtomIndex());
board.markObservedAtomForErase(getAtomIndex());
}
}
}
void QtObservedAtom::recieveNotification(Observable *publisher, Notification_ptr notification)
{
// ObservedValues have been updated before, hence convert updates to Qt's signals
switch (notification->getChannelNo()) {
case AtomObservable::IndexChanged:
emit indexChanged();
break;
case AtomObservable::BondsAdded:
case AtomObservable::BondsRemoved:
emit bondsChanged();
break;
case AtomObservable::ElementChanged:
emit elementChanged();
break;
case AtomObservable::MoleculeChanged:
emit moleculeindexChanged();
break;
case AtomObservable::NameChanged:
emit nameChanged();
break;
case AtomObservable::PositionChanged:
emit positionChanged();
break;
case AtomObservable::SelectionChanged:
emit selectedChanged();
break;
default:
ASSERT(0, "QtObservedAtom::recieveNotification() - we are not signed on to channel "
+toString(notification->getChannelNo())+" of the atom.");
break;
}
}
void QtObservedAtom::activateObserver()
{
atom * atomref = getAtom(getAtomIndex());
if (atomref != NULL) {
Observable::channels_t channels = getAllObservedChannels();
owner = static_cast(atomref);
for (Observable::channels_t::const_iterator iter = channels.begin();
iter != channels.end(); ++iter)
owner->signOn(this, *iter);
if (!BoardIsGone)
board.markObservedAtomAsConnected(getAtomIndex());
} else
signedOffChannels = AllsignedOnChannels;
}
void QtObservedAtom::deactivateObserver()
{
// sign Off
if (owner != NULL) {
Observable::channels_t channels = getAllObservedChannels();
for (Observable::channels_t::const_iterator iter = channels.begin();
iter != channels.end(); ++iter)
owner->signOff(this, *iter);
owner = NULL;
signedOffChannels = AllsignedOnChannels;
if (!BoardIsGone)
board.markObservedAtomAsDisconnected(getAtomIndex());
}
}
void QtObservedAtom::initObservedValues(
ObservedValues_t &_ObservedValues,
const atomId_t _id,
const atom * const _atomref,
const boost::function &_subjectKilled)
{
/* This is an old note from when the code was still part of cstor's initializer body.
* TODO: Probably does not apply anymore but has not yet been tested.
*
* We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
* boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
* the class has not been fully constructed yet. "This" itself seems to be working fine.
*/
ASSERT( _ObservedValues.size() == MAX_ObservedTypes,
"QtObservedAtom::initObservedValues() - given ObservedValues has not correct size.");
// fill ObservedValues: index first
const boost::function AtomIndexUpdater(
boost::bind(&QtObservedAtom::updateIndex));
ObservedValue_wCallback * const IndexObservable =
new ObservedValue_wCallback(
_atomref,
boost::bind(&QtObservedAtom::updateIndex),
"AtomIndex_"+toString(_id),
_id,
AtomIndexChannels,
_subjectKilled);
_ObservedValues[AtomIndex] = IndexObservable;
const boost::function AtomIndexGetter =
boost::bind(&ObservedValue_wCallback::get,
IndexObservable);
// fill ObservedValues: then all the other that need index
const boost::function AtomBondsUpdater(
boost::bind(&QtObservedAtom::updateBonds, AtomIndexGetter));
const boost::function AtomElementUpdater(
boost::bind(&QtObservedAtom::updateElement, AtomIndexGetter));
const boost::function AtomMoleculeIndexUpdater(
boost::bind(&QtObservedAtom::updateMoleculeIndex, AtomIndexGetter));
const boost::function AtomNameUpdater(
boost::bind(&QtObservedAtom::updateName, AtomIndexGetter));
const boost::function AtomPositionUpdater(
boost::bind(&QtObservedAtom::updatePosition, AtomIndexGetter));
const boost::function AtomSelectedUpdater(
boost::bind(&QtObservedAtom::updateSelected, AtomIndexGetter));
_ObservedValues[AtomBonds] = new ObservedValue_wCallback(
_atomref,
AtomBondsUpdater,
"AtomBonds_"+toString(_id),
AtomBondsUpdater(),
AtomBondsChannels,
_subjectKilled,
AtomIndexGetter);
_ObservedValues[AtomElement] = new ObservedValue_wCallback(
_atomref,
AtomElementUpdater,
"AtomElement"+toString(_id),
AtomElementUpdater(),
AtomElementChannels,
_subjectKilled,
AtomIndexGetter);
_ObservedValues[AtomMoleculeIndex] = new ObservedValue_wCallback(
_atomref,
AtomMoleculeIndexUpdater,
"AtomMoleculeIndex"+toString(_id),
AtomMoleculeIndexUpdater(),
AtomMoleculeIndexChannels,
_subjectKilled,
AtomIndexGetter);
_ObservedValues[AtomName] = new ObservedValue_wCallback(
_atomref,
AtomNameUpdater,
"AtomName"+toString(_id),
AtomNameUpdater(),
AtomNameChannels,
_subjectKilled,
AtomIndexGetter);
_ObservedValues[AtomPosition] = new ObservedValue_wCallback(
_atomref,
AtomPositionUpdater,
"AtomPosition_"+toString(_id),
AtomPositionUpdater(),
AtomPositionChannels,
_subjectKilled,
AtomIndexGetter);
_ObservedValues[AtomSelected] = new ObservedValue_wCallback(
_atomref,
AtomSelectedUpdater,
"AtomSelected_"+toString(_id),
AtomSelectedUpdater(),
AtomSelectedChannels,
_subjectKilled,
AtomIndexGetter);
}
void QtObservedAtom::destroyObservedValues(
std::vector &_ObservedValues)
{
delete boost::any_cast *>(_ObservedValues[AtomIndex]);
delete boost::any_cast *>(_ObservedValues[AtomBonds]);
delete boost::any_cast *>(_ObservedValues[AtomElement]);
delete boost::any_cast *>(_ObservedValues[AtomMoleculeIndex]);
delete boost::any_cast *>(_ObservedValues[AtomName]);
delete boost::any_cast *>(_ObservedValues[AtomPosition]);
delete boost::any_cast *>(_ObservedValues[AtomSelected]);
_ObservedValues.clear();
}
const atomId_t& QtObservedAtom::getAtomIndex() const
{
return boost::any_cast *>(ObservedValues[AtomIndex])->get();
}
const QtObservedAtom::ListOfBonds_t& QtObservedAtom::getAtomBonds() const
{
return boost::any_cast *>(ObservedValues[AtomBonds])->get();
}
const atomicNumber_t& QtObservedAtom::getAtomElement() const
{
return boost::any_cast *>(ObservedValues[AtomElement])->get();
}
const moleculeId_t& QtObservedAtom::getAtomMoleculeIndex() const
{
return boost::any_cast *>(ObservedValues[AtomMoleculeIndex])->get();
}
const std::string& QtObservedAtom::getAtomName() const
{
return boost::any_cast *>(ObservedValues[AtomName])->get();
}
const Vector& QtObservedAtom::getAtomPosition() const
{
return boost::any_cast *>(ObservedValues[AtomPosition])->get();
}
const bool QtObservedAtom::getAtomSelected() const
{
return boost::any_cast *>(ObservedValues[AtomSelected])->get();
}