/* * Copyright 2009 Ben Boeckel * * This program 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 3 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see . */ #ifndef SIGMOD_SUBCLASS #define SIGMOD_SUBCLASS // Sigmod includes #include "Global.h" #include "Object.h" // Qt includes #include #include #include // Standard includes #include namespace Sigmod { template class SIGMOD_EXPORT Subclass { public: typedef void (U::*Callback)(const int); Subclass(U* parent, Callback insertHook = NULL, Callback deleteHook = NULL); ~Subclass(); void importXml(const QDomElement& parent, const QString& tag); void exportXml(QDomElement* parent) const; void validate() const; T* add(); T* add(const T& copy); T* add(const QDomElement& xml); void deleteAt(const int index); void deleteId(const int id); int count() const; const T* at(const int index) const; T* at(const int index); const T* id(const int id) const; T* id(const int id); int idToIndex(const int id) const; void clear(); Subclass& operator=(const Subclass& rhs); private: T* add(T* object); int newId(); U* const m_parent; QList m_objects; QLinkedList m_freeList; Callback m_insertHook; Callback m_deleteHook; }; template inline Subclass::Subclass(U* parent, Callback insertHook, Callback deleteHook) : m_parent(parent), m_insertHook(insertHook), m_deleteHook(deleteHook) { } template inline Subclass::~Subclass() { clear(); } template inline void Subclass::importXml(const QDomElement& parent, const QString& tag) { QDomElement xml = parent.firstChildElement(tag); while (!xml.isNull()) { add(xml); xml = xml.nextSiblingElement(tag); } } template inline void Subclass::exportXml(QDomElement* parent) const { foreach (T* object, m_objects) parent->appendChild(object->save()); } template inline void Subclass::validate() const { foreach (T* object, m_objects) { m_parent->connect(object, SIGNAL(valMessage(QString)), m_parent, SIGNAL(valMessage(QString))); m_parent->connect(object, SIGNAL(valWarning(QString)), m_parent, SIGNAL(valWarning(QString))); m_parent->connect(object, SIGNAL(valError(QString)), m_parent, SIGNAL(valError(QString))); object->validate(); m_parent->disconnect(object, SIGNAL(valMessage(QString)), m_parent, SIGNAL(valMessage(QString))); m_parent->disconnect(object, SIGNAL(valWarning(QString)), m_parent, SIGNAL(valWarning(QString))); m_parent->disconnect(object, SIGNAL(valError(QString)), m_parent, SIGNAL(valError(QString))); } } template inline T* Subclass::add() { return add(new T(m_parent, newId())); } template inline T* Subclass::add(const T& copy) { return add(new T(copy, m_parent, newId())); } template inline T* Subclass::add(const QDomElement& copy) { return add(new T(copy, m_parent, newId())); } template inline void Subclass::deleteAt(const int index) { if ((index < 0) && (count() <= count)) return; if (m_deleteHook) ((*m_parent).*m_deleteHook)(index); m_freeList.removeAll(m_objects[index]->id()); delete m_objects[index]; m_objects.removeAt(index); } template inline void Subclass::deleteId(const int id) { deleteAt(idToIndex(id)); } template inline int Subclass::count() const { return m_objects.size(); } template inline const T* Subclass::at(const int index) const { if ((index < 0) && (count() <= index)) return NULL; return m_objects[index]; } template inline T* Subclass::at(const int index) { if ((index < 0) && (count() <= index)) return NULL; return m_objects[index]; } template inline const T* Subclass::id(const int id) const { return at(idToIndex(id)); } template inline T* Subclass::id(const int id) { return at(idToIndex(id)); } template inline int Subclass::idToIndex(const int id) const { for (int i = 0; i < count(); ++i) { if (m_objects[i]->id() == id) return i; } return INT_MAX; } template inline void Subclass::clear() { qDeleteAll(m_objects); m_objects.clear(); } template inline Subclass& Subclass::operator=(const Subclass& rhs) { if (this == &rhs) return *this; m_freeList = rhs.m_freeList; foreach (T* object, rhs.m_objects) add(new T(*object, m_parent, object->id())); return *this; } template inline T* Subclass::add(T* object) { m_objects.append(object); if (m_insertHook) ((*m_parent).*m_insertHook)(count()); return object; } template inline int Subclass::newId() { QMutableLinkedListIterator i(m_freeList); int next = 0; while (i.hasNext()) { if (next < i.peekNext()) { i.insert(next); break; } i.next(); ++next; } return next; } } #endif