/* * 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 . */ /* * QtMoleculeItem.cpp * * Created on: Jan 17, 2015 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "QtMoleculeItem.hpp" #include #include "UIElements/Views/Qt4/MoleculeList/QtMoleculeList.hpp" #include "CodePatterns/MemDebug.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/toString.hpp" #include "CodePatterns/Observer/Notification.hpp" #include #include #include "Descriptors/MoleculeIdDescriptor.hpp" #include "molecule.hpp" #include "World.hpp" QtMoleculeItem::QtMoleculeItem( const moleculeId_t _molid, const channellist_t &_channellist, const enum MoveTypes _movetype, const emitDirtyState_t _emitDirtyState, const emitSubjectKilledState_t _emitSubjectKilledState) : Observer("QtMoleculeItem"), molid(_molid), movetype(_movetype), channellist(_channellist), owner(NULL), dirty(true), emitDirtyState(_emitDirtyState), emitSubjectKilledState(_emitSubjectKilledState) { // BUG: We cannot sign on here as then and again we catch "pure virtual function called" // this makes no sense as both the Observer part (which also has a recievedNotification()) // nor QtMoleculeItem's vtable have been fully created. // signOnToMolecule(); setFlags(flags() | Qt::ItemIsSelectable); } void QtMoleculeItem::signOnToMolecule() { // count the number of threads entering the function std::cout << "QtMoleculeItem::signOnToMolecule() called for " << this << std::endl; const molecule * const mol = const_cast(World::getInstance()). getMolecule(MoleculeById(molid)); if (mol != NULL) { owner_mutex.lock(); if (owner == NULL) { owner_mutex.unlock(); const Observable *owner_copy = static_cast(mol); for (channellist_t::const_iterator channeliter = channellist.begin(); channeliter != channellist.end(); ++channeliter) owner_copy->signOn(this, *channeliter); owner_mutex.lock(); owner = owner_copy; owner_mutex.unlock(); std::cout << "QtMoleculeItem " << this << " has signed on to " << owner << std::endl; } else owner_mutex.unlock(); } } void QtMoleculeItem::signOffFromMolecule() { // prevent via owner that another thread enters the function again // (re-entrancy) const Observable *owner_copy; { boost::recursive_mutex::scoped_lock lock(owner_mutex); if (owner != NULL) { owner_copy = owner; owner = NULL; } } std::cout << "QtMoleculeItem::signOffFromMolecule() called for " << this << std::endl; if (owner_copy != NULL) { for (channellist_t::const_iterator channeliter = channellist.begin(); channeliter != channellist.end(); ++channeliter) owner_copy->signOff(this, *channeliter); std::cout << "QtMoleculeItem " << this << " has signed off from " << owner_copy << std::endl; owner_copy = NULL; } } QtMoleculeItem::~QtMoleculeItem() { // BUG: We cannot sign off here as then and again we catch "pure virtual function called" // this makes no sense as neither the Observer part (which also has a recievedNotification()) // nor QtMoleculeItem's vtable have yet been destroyed. signOffFromMolecule(); } void QtMoleculeItem::updateState() { if (dirty) { internal_updateState(); dirty = false; } } void QtMoleculeItem::update(Observable *publisher) {} void QtMoleculeItem::recieveNotification(Observable *publisher, Notification_ptr notification) { if (dynamic_cast(publisher) != NULL) { if (notification->getChannelNo() == molecule::AboutToBeRemoved) { signOffFromMolecule(); // prevent any remaining updates from accessing the molecule //molid = -1; dirty = false; } else { channellist_t::const_iterator iter = std::find(channellist.begin(), channellist.end(), notification->getChannelNo()); if (iter != channellist.end()) { dirty = true; emitDirtyState(getMoleculeId(), getType(), movetype); } else { ASSERT(0, "QtMoleculeItem::recieveNotification() - received notification to channel " +toString(notification->getChannelNo())+" we are not subscribed to."); } } } } void QtMoleculeItem::subjectKilled(Observable *publisher) { // signOffFromMolecule(); dirty = false; emitSubjectKilledState(getMoleculeId()); } const molecule * const QtMoleculeItem::getMolecule() const { const molecule * const mol = const_cast(World::getInstance()).getMolecule(MoleculeById(molid)); // ASSERT (mol != NULL, // "QtMoleculeItem::getMolecule() - mol with "+toString(molid)+" is gone."); return mol; }