/* * QtObservedMolecule.hpp * * Created on: Oct 28, 2015 * Author: heber */ #ifndef QTOBSERVEDMOLECULE_HPP_ #define QTOBSERVEDMOLECULE_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "CodePatterns/Observer/Observable.hpp" #include "CodePatterns/Observer/Observer.hpp" #include "LinearAlgebra/Vector.hpp" #include "molecule.hpp" #include "UIElements/Qt4/InstanceBoard/ObservedValue_types.hpp" #include "UIElements/Qt4/InstanceBoard/ObservedValuesContainer.hpp" #include "UIElements/Qt4/InstanceBoard/QtObservedAtom.hpp" #include "types.hpp" class QtObservedInstanceBoard; /** This instance is the ObservedValue representation of a World's molecule. * * Due to the signal/slot mechanism and its delays, lifetime of objects in the * World and their QtGui representation cannot directly be related (without * slowing down Actions just for having the representation up to speed). * Hence, the required information for displaying and representing these * objects must be contained in an extra instance. * * This is the instance for information about a particular molecule. */ class QtObservedMolecule : public QWidget, public Observer { Q_OBJECT public: //!> typedef for instance wrapped in shared ptr typedef boost::shared_ptr ptr; //!> typedef for instance wrapped in shared ptr typedef boost::weak_ptr weak_ptr; private: //!> ObservedValuesContainer needs to access private cstor and dstor friend class ObservedValuesContainer; //!> QtObservedInstanceBoard needs to access private cstor and dstor friend class QtObservedInstanceBoard; /** Cstor of QtObservedMolecule. * * \param _id id of observed molecule * \param _mol ref to observed molecule * \param _board ref to InstanceBoard for callbacks on occasion of subjectKilled() * \param _parent Qt parent to automatically destroy when parent is destroyed */ QtObservedMolecule( const moleculeId_t _id, const molecule * const _mol, QtObservedInstanceBoard &_board, QWidget * _parent=0); public: /** Dstor of QtObservedMolecule. * */ ~QtObservedMolecule(); // Observer functions void update(Observable *publisher); void subjectKilled(Observable *publisher); void recieveNotification(Observable *publisher, Notification_ptr notification); /** Getter for a permanent and unique index of this instance. * * \note ALWAYS use this index if you need to store and identifier to this * instance which you might need to retrieve at some later date. * * \warning DO NOT STORE the QtObserved...:ptr directly. This will possibly * prevent their eventual destruction. Only store the ObservedValue_Index_t * as means to obtain the ptr from the QtObservedInstanceBoard. * * \return returns a unique and permanent index that can be used to retrieve this * instance from the QtObservedInstanceBoard as it must not be stored. */ ObservedValue_Index_t getIndex() const; /** Getter to molecule atom count contained in \a ObservedValues. * * \return molecule's atom count */ const int& getAtomCount() const; /** Getter to molecule bond count contained in \a ObservedValues. * * \return molecule's bond count */ const int& getBondCount() const; /** Getter to molecule center contained in \a ObservedValues. * * \return molecule's center */ const Vector& getMolCenter() const; /** Getter to molecule index contained in \a ObservedValues. * * \return molecule's index */ const moleculeId_t& getMolIndex() const; /** Getter to molecule name contained in \a ObservedValues. * * \return molecule's name */ const std::string& getMolName() const; /** Getter to molecule formula contained in \a ObservedValues. * * \return molecule's formula */ const std::string& getMolFormula() const; /** Getter to molecule non-hydrogen atom count contained in \a ObservedValues. * * \return molecule's non-hydrogen atom count */ const int& getNonHydrogenCount() const; /** Getter to molecule's bounding box contained in \a ObservedValues. * * \return molecule's bounding box */ const molecule::BoundingBoxInfo& getBoundingBox() const; /** Getter to molecule's selected status. * * \return true - molecule selected, false - else */ const bool& getMolSelected() const; static const molecule * const getMolecule(const moleculeId_t _id); signals: void atomcountChanged(); void bondcountChanged(); void formulaChanged(); void indexChanged(const moleculeId_t, const moleculeId_t); void nameChanged(); void nononhydrogenChanged(); void centerChanged(); void tesselationhullChanged(); void boundingboxChanged(); void atomInserted(QtObservedAtom::ptr, QtObservedMolecule *); void atomRemoved(ObservedValue_Index_t, QtObservedMolecule *); void moleculeRemoved(); void selectedChanged(); private: void activateObserver(); void deactivateObserver(); private: static int updateAtomCount(const molecule &mol); static int updateBondCount(const molecule &mol); static molecule::BoundingBoxInfo updateBoundingBox(const molecule &mol); static std::string updateFormulaString(const molecule &mol); static Vector updateCenter(const molecule &mol); static moleculeId_t updateIndex(const molecule &mol); static std::string updateName(const molecule &mol); static int updateNonHydrogenCount(const molecule &mol); static bool updateSelected(const molecule &mol); //!> list of channels when atom count needs to update static const Observable::channels_t AtomCountChannels; //!> list of channels when bond count needs to update static const Observable::channels_t BondCountChannels; //!> list of channels when bounding box needs to update static const Observable::channels_t BoundingBoxChannels; //!> list of channels when formula needs to update static const Observable::channels_t FormulaStringChannels; //!> list of channels when the center needs to update static const Observable::channels_t CenterChannels; //!> list of channels when the index needs to update static const Observable::channels_t IndexChannels; //!> list of channels when the name needs to update static const Observable::channels_t NameChannels; //!> list of channels when the name needs to update static const Observable::channels_t NonHydrogenCountChannels; //!> list of channels when the name needs to update static const Observable::channels_t SelectedChannels; private: /** Observed Values **/ //!> enumeration of observed values to match with entries in ObservedValues enum ObservedTypes { //!> contains the current molecule index MolIndex, //!> contains the current molecule's atom count AtomCount, //!> contains the current molecule's number of bonds BondCount, //!> contains newest version of the bounding box on request BoundingBox, //!> contains the current molecule's formula FormulaString, //!> contains the current molecule's center MolCenter, //!> contains the current molecule name MolName, //!> contains the current molecule's non-hydrogen atom count NonHydrogenCount, //!> contains the current molecule's selection status MolSelected, //!> gives the size of the enumeration MAX_ObservedTypes }; /** Initializes all \a _ObservedValues entries. * * \param _ObservedValues vector of ObservedValue to be filled * \param _moid molecule id * \param _molref reference to molecule * \param _subjectKilled ref to function to call on subjectKilled() */ void initObservedValues( ObservedValues_t &_ObservedValues, const moleculeId_t _molid, const molecule * const _molref, const boost::function &_subjectKilled); /** Destroys all \a ObservedValues entries. * * \param _ObservedValues vector of ObservedValue to be destroyed */ void destroyObservedValues( std::vector &_ObservedValues); /** Function is called by InstanceBoard to inform about its destruction. * * \note callbacks must not be used after this */ void noteBoardIsGone() { BoardIsGone = true; } /** Counts the number of subject killed received from the observed values. * * \param _id id to check against ours */ void countValuesSubjectKilled(ObservedValue_Index_t _id); //!> counts how many ObservedValues have already been subjectKilled() mutable size_t subjectKilledCount; /** Helper function to check that all subjectKilled have been received for both * this instance and all its internal observed values. * * \param _id id to check against ours */ void checkForRemoval(ObservedValue_Index_t _id); private: //!> we get multiple subjectKilled(), count and call callback() only on last const unsigned int AllsignedOnChannels; unsigned int signedOffChannels; //!> the Observable we are signed on, also indicates whether we are sign on (not NULL) const Observable *owner; private: /** Internal setter for the weak shared_ptr instance that we sometimes * need to convert the ref to this instance into an shared ptr instance that * is safe to hand around. * * \param _selfref ref to shared ptr instance that is internally stored */ void setSelfRef(const weak_ptr &_selfref) { const_cast(selfref) = _selfref; } //!> reference to this instance wrapped in a shared ptr for handing around const weak_ptr selfref; public: /** Getter for this instance safely wrapped in a shared ptr instance for * handing arount. * * \return shared ptr of this instance */ ptr getRef() const { return ptr(selfref); } private: //!> contains still the old index after the index changed moleculeId_t oldId; //!> reference to InstanceBoard for callbacks on subjectKilled() QtObservedInstanceBoard & board; //!> is board still alive or not, impacts callbacks bool BoardIsGone; //!> internal reference to ObservedValues held by QtObservedInstanceBoard ObservedValues_t ObservedValues; }; #endif /* QTOBSERVEDMOLECULE_HPP_ */