/* * 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::AtomMoleculeChannels(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 atomId_t _id, const atom * const _atom, QtObservedInstanceBoard &_board, QWidget * _parent) : QWidget(_parent), Observer("QtObservedAtom"), subjectKilledCount(0), AllsignedOnChannels(getAllObservedChannels().size()), signedOffChannels(0), owner(NULL), oldId(_id), board(_board), BoardIsGone(false), ObservedValues(QtObservedAtom::MAX_ObservedTypes) { boost::function atomSubjectKilled( boost::bind(&QtObservedAtom::countValuesSubjectKilled, boost::ref(*this), boost::bind(&QtObservedAtom::getIndex, boost::ref(*this)))); initObservedValues( ObservedValues, _id, _atom, atomSubjectKilled); // activating Observer is done by ObservedValueContainer when it's inserted } QtObservedAtom::~QtObservedAtom() { boost::any_cast *>(ObservedValues[AtomIndex])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomBonds])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomElement])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomMolecule])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomName])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomPosition])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[AtomSelected])->noteCallBackIsGone(); deactivateObserver(); destroyObservedValues(ObservedValues); } 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; } #ifdef HAVE_INLINE inline #endif atomId_t QtObservedAtom::updateIndex(const atom &_atomref) { return _atomref.getId(); } QtObservedAtom::ListOfBonds_t QtObservedAtom::updateBonds( const atom &_atom) { ListOfBonds_t ListOfBonds; // 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; } #ifdef HAVE_INLINE inline #endif atomicNumber_t QtObservedAtom::updateElement( const atom &_atom) { return _atom.getElementNo(); } #ifdef HAVE_INLINE inline #endif QtObservedMolecule* QtObservedAtom::updateMoleculeIndex( const atom &_atom) { if (_atom.getMolecule() != NULL) { const moleculeId_t molid = _atom.getMolecule()->getId(); QtObservedMolecule* mol = board.getObservedMolecule(molid).get(); if (mol != NULL) return mol; else return (QtObservedMolecule*)NULL; } else { return (QtObservedMolecule*)NULL; } } #ifdef HAVE_INLINE inline #endif std::string QtObservedAtom::updateName( const atom &_atom) { return _atom.getName(); } #ifdef HAVE_INLINE inline #endif Vector QtObservedAtom::updatePosition( const atom &_atom) { return _atom.getPosition(); } #ifdef HAVE_INLINE inline #endif bool QtObservedAtom::updateSelected( const atom &_atom) { return _atom.getSelected(); } void QtObservedAtom::update(Observable *publisher) { ASSERT(0, "QtObservedAtom::update() - we are not signed on for global updates."); } void QtObservedAtom::subjectKilled(Observable *publisher) { ++signedOffChannels; checkForRemoval(getIndex()); } void QtObservedAtom::countValuesSubjectKilled(ObservedValue_Index_t _id) { ASSERT( _id == getIndex(), "QtObservedAtom::countValuesSubjectKilled() - atom "+toString(getIndex()) +" received countValuesSubjectKilled for atom id "+toString(_id)+"."); ++subjectKilledCount; checkForRemoval(_id); } #ifdef HAVE_INLINE inline #endif void QtObservedAtom::checkForRemoval(ObservedValue_Index_t _id) { if ((signedOffChannels == AllsignedOnChannels) && (subjectKilledCount == MAX_ObservedTypes)) { // remove owner: no more signOff needed owner = NULL; emit atomRemoved(); if (!BoardIsGone) { board.markObservedAtomAsDisconnected(_id); board.markObservedAtomForErase(_id); } } } 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: { const atomId_t newId = getAtomIndex(); emit indexChanged(oldId, newId); oldId = newId; break; } case AtomObservable::BondsAdded: case AtomObservable::BondsRemoved: emit bondsChanged(); break; case AtomObservable::ElementChanged: emit elementChanged(); break; case AtomObservable::MoleculeChanged: emit moleculeChanged(); 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(getIndex()); } 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(getIndex()); } } void QtObservedAtom::initObservedValues( ObservedValues_t &_ObservedValues, const atomId_t _id, const atom * const _atomref, const boost::function &_subjectKilled) { ASSERT( _ObservedValues.size() == MAX_ObservedTypes, "QtObservedAtom::initObservedValues() - given ObservedValues has not correct size."); // fill ObservedValues: then all the other that need index const boost::function AtomIndexUpdater( boost::bind(&QtObservedAtom::updateIndex, boost::cref(*_atomref))); const boost::function AtomBondsUpdater( boost::bind(&QtObservedAtom::updateBonds, boost::cref(*_atomref))); const boost::function AtomElementUpdater( boost::bind(&QtObservedAtom::updateElement, boost::cref(*_atomref))); const boost::function AtomMoleculeUpdater( boost::bind(&QtObservedAtom::updateMoleculeIndex, this, boost::cref(*_atomref))); const boost::function AtomNameUpdater( boost::bind(&QtObservedAtom::updateName, boost::cref(*_atomref))); const boost::function AtomPositionUpdater( boost::bind(&QtObservedAtom::updatePosition, boost::cref(*_atomref))); const boost::function AtomSelectedUpdater( boost::bind(&QtObservedAtom::updateSelected, boost::cref(*_atomref))); _ObservedValues[AtomIndex] = new ObservedValue_wCallback( _atomref, AtomIndexUpdater, "AtomIndex_"+toString(_id), _id, AtomIndexChannels, _subjectKilled); _ObservedValues[AtomBonds] = new ObservedValue_wCallback( _atomref, AtomBondsUpdater, "AtomBonds_"+toString(_id), AtomBondsUpdater(), AtomBondsChannels, _subjectKilled); _ObservedValues[AtomElement] = new ObservedValue_wCallback( _atomref, AtomElementUpdater, "AtomElement"+toString(_id), AtomElementUpdater(), AtomElementChannels, _subjectKilled); _ObservedValues[AtomMolecule] = new ObservedValue_wCallback( _atomref, AtomMoleculeUpdater, "AtomMolecule"+toString(_id), AtomMoleculeUpdater(), AtomMoleculeChannels, _subjectKilled); _ObservedValues[AtomName] = new ObservedValue_wCallback( _atomref, AtomNameUpdater, "AtomName"+toString(_id), AtomNameUpdater(), AtomNameChannels, _subjectKilled); _ObservedValues[AtomPosition] = new ObservedValue_wCallback( _atomref, AtomPositionUpdater, "AtomPosition_"+toString(_id), AtomPositionUpdater(), AtomPositionChannels, _subjectKilled); _ObservedValues[AtomSelected] = new ObservedValue_wCallback( _atomref, AtomSelectedUpdater, "AtomSelected_"+toString(_id), AtomSelectedUpdater(), AtomSelectedChannels, _subjectKilled); } 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[AtomMolecule]); delete boost::any_cast *>(_ObservedValues[AtomName]); delete boost::any_cast *>(_ObservedValues[AtomPosition]); delete boost::any_cast *>(_ObservedValues[AtomSelected]); _ObservedValues.clear(); } ObservedValue_Index_t QtObservedAtom::getIndex() const { ASSERT( owner != NULL, "QtObservedAtom::getIndex() - index is NULL"); return owner; } 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(); } QtObservedMolecule* const QtObservedAtom::getAtomMolecule() const { return boost::any_cast *>(ObservedValues[AtomMolecule])->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(); }