/* * 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 . */ /* * QtInstanceInformationBoard.cpp * * Created on: Oct 17, 2015 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "QtInstanceInformationBoard.hpp" #include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.hpp" #include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp" #include "CodePatterns/MemDebug.hpp" #include "CodePatterns/Log.hpp" #include "Atom/atom.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "Descriptors/MoleculeIdDescriptor.hpp" #include "molecule.hpp" #include "World.hpp" QtInstanceInformationBoard::QtInstanceInformationBoard(QWidget * _parent) : QWidget(_parent), Observer("QtInstanceInformationBoard"), WorldSignedOn(false), atomSubjectKilled( boost::bind(&QtInstanceInformationBoard::atomcountsubjectKilled, this, _1)), moleculeSubjectKilled( boost::bind(&QtInstanceInformationBoard::moleculecountsubjectKilled, this, _1)), lastremovedatom((atomId_t)-1), lastremovedmolecule((moleculeId_t)-1) { // be first (besides ObservedValues to know about new insertions) World::getInstance().signOn(this, World::AtomInserted, GlobalObservableInfo::PriorityLevel(int(-10))); World::getInstance().signOn(this, World::AtomRemoved, GlobalObservableInfo::PriorityLevel(int(-10))); World::getInstance().signOn(this, World::MoleculeInserted, GlobalObservableInfo::PriorityLevel(int(-10))); World::getInstance().signOn(this, World::MoleculeRemoved, GlobalObservableInfo::PriorityLevel(int(-10))); WorldSignedOn = true; } QtInstanceInformationBoard::~QtInstanceInformationBoard() { if (WorldSignedOn) { World::getInstance().signOff(this, World::AtomInserted); World::getInstance().signOff(this, World::AtomRemoved); World::getInstance().signOff(this, World::MoleculeInserted); World::getInstance().signOff(this, World::MoleculeRemoved); } // sign off from all remaining molecules and atoms for (SignedOn_t::iterator iter = AtomSignedOn.begin(); !AtomSignedOn.empty(); iter = AtomSignedOn.begin()) { (*iter)->signOff(this, atom::IndexChanged); AtomSignedOn.erase(iter); } for (SignedOn_t::iterator iter = MoleculeSignedOn.begin(); !MoleculeSignedOn.empty(); iter = MoleculeSignedOn.begin()) { (*iter)->signOff(this, molecule::IndexChanged); MoleculeSignedOn.erase(iter); } } void QtInstanceInformationBoard::update(Observable *publisher) { ASSERT(0, "QtInstanceInformationBoard::update() - we are not signed on to general updates."); } void QtInstanceInformationBoard::subjectKilled(Observable *publisher) { SignedOn_t::iterator iter = AtomSignedOn.find(publisher); if ( iter != AtomSignedOn.end()) { LOG(3, "DEBUG: InstanceBoard got subjectKilled() from atom " << publisher); AtomSignedOn.erase(iter); } else { iter = MoleculeSignedOn.find(publisher); if ( iter != MoleculeSignedOn.end()) { LOG(3, "DEBUG: InstanceBoard got subjectKilled() from molecule " << publisher); MoleculeSignedOn.erase(iter); } else { ASSERT(0, "QtObservedInstanceBoard::subjectKilled() - could not find signedOn for atom/molecule "+toString(publisher)); } } } void QtInstanceInformationBoard::recieveNotification(Observable *publisher, Notification_ptr notification) { if (static_cast(publisher) == World::getPointer()) { switch (notification->getChannelNo()) { case World::MoleculeInserted: { const moleculeId_t _id = const_cast(World::getInstance()).lastChangedMolId(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that molecule "+toString(_id)+" has been inserted."; #endif LOG(3, "DEBUG: InformationBoard got moleculeInserted signal for molecule " << _id); const molecule * const _molecule = const_cast(World::getInstance()). getMolecule(MoleculeById(_id)); if (_molecule != NULL) { ObservedValues_t ObservedValues(GLMoleculeObject_molecule::MAX_ObservedTypes); LOG(3, "DEBUG: InformationBoard initializes ObservedValues for molecule " << _id); GLMoleculeObject_molecule::initObservedValues( ObservedValues, _id, _molecule, moleculeSubjectKilled); #ifndef NDEBUG std::pair inserter = #endif moleculeObservedValues.insert( std::make_pair( _id, ObservedValues)); ASSERT( inserter.second, "QtInstanceInformationBoard::recieveNotification() - could not insert ObservedValues for" +toString(_id)+"."); // we need to check for index changes LOG(3, "DEBUG: InformationBoard signOn()s to molecule " << _id); _molecule->signOn(this, molecule::IndexChanged); MoleculeSignedOn.insert( static_cast(const_cast(_molecule)) ); emit moleculeInserted(_id); } else { ELOG(1, "QtInstanceInformationBoard got MoleculeInserted for unknown molecule id " << _id); } break; } case World::MoleculeRemoved: { const moleculeId_t _id = const_cast(World::getInstance()).lastChangedMolId(); LOG(3, "DEBUG: InformationBoard got MoleculeRemoved signal for molecule " << _id); // note down such that ObservedValues are simply dropped lastremovedmolecule = _id; break; } case World::AtomInserted: { const atomId_t _id = const_cast(World::getInstance()).lastChangedAtomId(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that atom "+toString(_id)+" has been inserted."; #endif LOG(3, "DEBUG: InformationBoard got atomInserted signal for atom " << _id); const atom * const _atom = const_cast(World::getInstance()). getAtom(AtomById(_id)); if (_atom!= NULL) { ObservedValues_t ObservedValues(GLMoleculeObject_atom::MAX_ObservedTypes); LOG(3, "DEBUG: InformationBoard initializes ObservedValues for atom " << _id); GLMoleculeObject_atom::initObservedValues( ObservedValues, _id, _atom, atomSubjectKilled); #ifndef NDEBUG std::pair inserter = #endif atomObservedValues.insert( std::make_pair( _id, ObservedValues)); ASSERT( inserter.second, "QtInstanceInformationBoard::recieveNotification() - could not insert ObservedValues for" +toString(_id)+"."); // we need to check for index changes LOG(3, "DEBUG: InformationBoard signOn()s to atom " << _id); _atom->signOn(this, atom::IndexChanged); AtomSignedOn.insert( static_cast(const_cast(_atom)) ); } else { ELOG(1, "QtInstanceInformationBoard got AtomInserted for unknown atom id " << _id); } break; } case World::AtomRemoved: { const atomId_t _id = const_cast(World::getInstance()).lastChangedAtomId(); LOG(3, "DEBUG: InformationBoard got AtomRemoved signal for atom " << _id); // note down such that ObservedValues are simply dropped lastremovedatom = _id; break; } default: ASSERT(0, "QtInstanceInformationBoard::recieveNotification() - we cannot get here for World."); break; } } else if (dynamic_cast(publisher) != NULL) { const moleculeId_t molid = const_cast(World::getInstance()).lastChangedMolId(); switch (notification->getChannelNo()) { case molecule::AtomInserted: { const molecule * const _molecule = const_cast(World::getInstance()). getMolecule(MoleculeById(molid)); if (_molecule != NULL) { const atomId_t atomid = const_cast(_molecule)->lastChangedAtomId(); LOG(3, "DEBUG: InformationBoard got AtomInserted signal for atom " << atomid << " from molecule " << molid); // check whether atom's observedvalues are present ASSERT( atomObservedValues.find(atomid) != atomObservedValues.end(), "QtInstanceInformationBoard::recieveNotification() - ObservedValues for atom " +toString(atomid)+" are not present yet."); // and emit emit atomInserted(molid, atomid); } else { ELOG(2, "QtInstanceInformationBoard::recieveNotification() - molecule " << molid << " has disappeared."); } break; } case molecule::AtomRemoved: { const molecule * const _molecule = const_cast(World::getInstance()). getMolecule(MoleculeById(molid)); if (_molecule != NULL) { const atomId_t atomid = const_cast(_molecule)->lastChangedAtomId(); LOG(3, "DEBUG: InformationBoard got AtomRemoved signal for atom " << atomid << " from molecule " << molid); emit atomRemoved(molid, atomid); } break; } case molecule::IndexChanged: { // molecule has changed its index const moleculeId_t newmoleculeId = dynamic_cast(publisher)->getId(); LOG(3, "DEBUG: InformationBoard got IndexChanged from molecule " << molid << " to " << newmoleculeId); { moleculeObservedValues_t::iterator iter = moleculeObservedValues.find(molid); // change id here only if still present if (iter != moleculeObservedValues.end()) { ObservedValues_t obsvalues = iter->second; moleculeObservedValues.erase(iter); ASSERT( moleculeObservedValues.find(newmoleculeId) == moleculeObservedValues.end(), "QtInstanceInformationBoard::recieveNotification() - ObservedValues for atom " +toString(newmoleculeId)+" already present."); moleculeObservedValues.insert( std::make_pair(newmoleculeId, obsvalues) ); // if (!inserter.second) // ELOG(1, "QtInformationBoard could not insert molecule id change " // << molid << "->" << newmoleculeId); } } // no need update SignedOn, ref does not change emit moleculeIndexChanged(molid, newmoleculeId); break; } default: ASSERT(0, "QtInstanceInformationBoard::recieveNotification() - we cannot get here."); break; } } else if (dynamic_cast(publisher) != NULL) { const atomId_t oldatomId = const_cast(World::getInstance()).lastChangedAtomId(); switch (notification->getChannelNo()) { case AtomObservable::IndexChanged: { const atomId_t newatomId = dynamic_cast(publisher)->getId(); LOG(3, "DEBUG: InformationBoard got IndexChanged from atom " << oldatomId << " to " << newatomId); // update atomObservedValues { atomObservedValues_t::iterator iter = atomObservedValues.find(oldatomId); // change id here only if still present if (iter != atomObservedValues.end()) { ObservedValues_t obsvalues = iter->second; atomObservedValues.erase(iter); ASSERT( atomObservedValues.find(newatomId) == atomObservedValues.end(), "QtInstanceInformationBoard::recieveNotification() - ObservedValues for atom " +toString(newatomId)+" already present."); atomObservedValues.insert( std::make_pair(newatomId, obsvalues) ); // if (!inserter.second) // ELOG(1, "QtInformationBoard could not insert atom id change " // << oldatomId << "->" << newatomId); } } // no need update SignedOn, ref does not change emit atomIndexChanged(oldatomId, newatomId); break; } default: ASSERT(0, "QtInstanceInformationBoard::recieveNotification() - we cannot get here."); break; } } else { ASSERT(0, "QtInstanceInformationBoard::recieveNotification() - notification from unknown source."); } } void QtInstanceInformationBoard::atomcountsubjectKilled(const atomId_t _atomid) { LOG(3, "DEBUG: InformationBoard got subjectKilled() for a value of atom " << _atomid); atomsubjectKilledCount_t::iterator iter = atomsubjectKilledCount.find(_atomid); if (iter == atomsubjectKilledCount.end()) { std::pair inserter = atomsubjectKilledCount.insert( std::make_pair(_atomid, 0) ); iter = inserter.first; } ++(iter->second); if (iter->second > GLMoleculeObject_atom::MAX_ObservedTypes) { atomsubjectKilledCount.erase(iter); } } void QtInstanceInformationBoard::moleculecountsubjectKilled(const moleculeId_t _molid) { LOG(3, "DEBUG: InformationBoard got subjectKilled() for a value of molecule " << _molid); moleculesubjectKilledCount_t::iterator iter = moleculesubjectKilledCount.find(_molid); if (iter == moleculesubjectKilledCount.end()) { std::pair inserter = moleculesubjectKilledCount.insert( std::make_pair(_molid, 0) ); iter = inserter.first; } ++(iter->second); if (iter->second > GLMoleculeObject_molecule::MAX_ObservedTypes) { // then free the instance emit moleculeRemoved(_molid); moleculesubjectKilledCount.erase(iter); } } QtInstanceInformationBoard::ObservedValues_t QtInstanceInformationBoard::getAtomObservedValues(const atomId_t _id) { ObservedValues_t returnvalues; const atomObservedValues_t::iterator iter = atomObservedValues.find(_id); ASSERT(iter != atomObservedValues.end(), "QtInstanceInformationBoard::getAtomObservedValues() - atom values not present for id" +toString(_id)); if (iter->first == _id) { returnvalues = iter->second; atomObservedValues.erase(iter); } return returnvalues; } QtInstanceInformationBoard::ObservedValues_t QtInstanceInformationBoard::getMoleculeObservedValues(const moleculeId_t _id) { ObservedValues_t returnvalues; const moleculeObservedValues_t::iterator iter = moleculeObservedValues.find(_id); ASSERT(iter != moleculeObservedValues.end(), "getMoleculeObservedValues::getAtomObservedValues() - molecule values not present for id" +toString(_id)); if (iter->first == _id) { returnvalues = iter->second; moleculeObservedValues.erase(iter); } return returnvalues; } void QtInstanceInformationBoard::returnAtomObservedValues( const atomId_t _id, ObservedValues_t &_observedvalues) { if (lastremovedatom != _id) { #ifndef NDEBUG std::pair inserter = #endif atomObservedValues.insert( std::make_pair( _id, _observedvalues) ); ASSERT( inserter.second, "QtInstanceInformationBoard::returnAtomObservedValues() - could not insert ObservedValues for" +toString(_id)+"."); } else lastremovedatom = (atomId_t)-1; } void QtInstanceInformationBoard::returnMoleculeObservedValues( const moleculeId_t _id, ObservedValues_t &_observedvalues) { if (lastremovedmolecule != _id) { #ifndef NDEBUG std::pair inserter = #endif moleculeObservedValues.insert( std::make_pair( _id, _observedvalues) ); ASSERT( inserter.second, "QtInstanceInformationBoard::returnMoleculeObservedValues() - could not insert ObservedValues for" +toString(_id)+"."); } else lastremovedmolecule = (moleculeId_t)-1; }