/*! * ChainBuilder.h * * \brief Generic implementation for chain building, i.e. building ordered lists. * The ChainBuilder is initialized with a pool of objects and a (pointer to a) function * that decides if two objects have a parent child relation. Duplicates are filtered out. * * All found chains are returned by the function /ref ChainBuilder::getChains(). * * \copyright Copyright (c) 2015 Governikus GmbH & Co. KG */ #pragma once #include #include #include namespace governikus { template class ChainBuilder { protected: QVector > mChains; private: std::function mIsChildFunc; void buildChain(const QVector& pAllElements, const QVector& pChain) { bool chainComplete = true; for (const auto& elem : pAllElements) { if (pChain.contains(elem)) { continue; } if (mIsChildFunc(elem, pChain.last())) { QVector extendedChain(pChain); extendedChain += elem; buildChain(pAllElements, extendedChain); chainComplete = false; } else if (mIsChildFunc(pChain.first(), elem)) { QVector extendedChain(pChain); extendedChain.prepend(elem); buildChain(pAllElements, extendedChain); chainComplete = false; } } if (chainComplete && !isSubChain(pChain)) { mChains += pChain; } } bool isSubChain(const QVector& pSubChain) { for (const auto& chain : qAsConst(mChains)) { if (std::search(chain.begin(), chain.end(), pSubChain.begin(), pSubChain.end()) != chain.end()) { return true; } } return false; } public: ChainBuilder(const QVector& pAllElements, const std::function& pIsChildFunc) : mChains() , mIsChildFunc(pIsChildFunc) { for (const auto& elem : pAllElements) { const QVector chain({elem}); if (!isSubChain(chain)) { buildChain(pAllElements, chain); } } } const QVector >& getChains() const { return mChains; } }; } /* namespace governikus */