/* Copyright (C) 2014 * Swift Project Community / Contributors * * This file is part of Swift Project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, * including this file, may be copied, modified, propagated, or distributed except according to the terms * contained in the LICENSE file. */ //! \file #ifndef BLACKMISC_LOGCATEGORYLIST_H #define BLACKMISC_LOGCATEGORYLIST_H #include "blackmisc/blackmiscexport.h" #include "blackmisc/collection.h" #include "blackmisc/compare.h" #include "blackmisc/logcategory.h" #include "blackmisc/sequence.h" #include "blackmisc/typetraits.h" #include #include #include #include #include #include #include #include #include #include namespace BlackMisc { /*! * A sequence of log categories. */ class BLACKMISC_EXPORT CLogCategoryList : public CSequence { public: //! Empty constructor. CLogCategoryList() = default; //! By single element CLogCategoryList(const CLogCategory &category) { this->push_back(category); } //! Copy constructor. CLogCategoryList(const CLogCategoryList &) = default; //! Copy construct from superclass instance. CLogCategoryList(const CSequence &other) : CSequence(other) {} //! Initializer list constructor. CLogCategoryList(std::initializer_list il) : CSequence(il) {} //! Prevent accidental use of the initializer list constructor. CLogCategoryList(std::nullptr_t) = delete; //! Copy assignment. CLogCategoryList &operator =(const CLogCategoryList &) = default; //! Copy assign from superclass instance. CLogCategoryList &operator =(const CSequence &other) { CSequence::operator =(other); return *this; } /*! * Construct by extracting categories from a class T. * * If T has a member function getLogCategories, then this will be called. * If T inherits from QObject then we get the name of the class and all its superclasses. * If T is registered with QMetaType then we get the name of the class. * If more than one of the above cases is true, then all are combined into the list. * If none of the above cases is true, then the constructed list will be the uncategorized category. * * This constructor will be disabled if T is not a class type. * * \param pointer The value of pointer is unimportant. Only the static type T is considered. * It is legal to pass static_cast(nullptr), but in member functions passing the this pointer is easier. */ template ::value>> CLogCategoryList(const T *pointer) : CLogCategoryList(fromClass()) { Q_UNUSED(pointer); } //! Convert each of the categories to a QString and return the result as a QStringList. QStringList toQStringList() const; //! \copydoc BlackMisc::CValueObject::toQString QString toQString(bool i18n = false) const; //! Convert a string list, such as that returned by toQStringList(), into a CLogCategoryList. static CLogCategoryList fromQStringList(const QStringList &stringList); //! Convert a string, such as that returned by toQString(), into a CLogCategoryList. static CLogCategoryList fromQString(const QString &string); //! Returns true if any of the categories in the list start with the given prefix. bool anyStartWith(const QString &prefix) const; //! Returns true if any of the categories in the list end with the given suffix. bool anyEndWith(const QString &suffix) const; //! Register metadata static void registerMetadata(); //! \copydoc BlackMisc::Mixin::String::toQString QString convertToQString(bool i18n = false) const; private: /* * Templates used by the constructor template: */ template struct tag {}; template static const CLogCategoryList &fromClass() { static_assert(sizeof(T) > 0, "T must be a complete type, not forward declared"); static QThreadStorage list; if (! list.hasLocalData()) { list.localData().appendCategoriesFromMemberFunction(tag(), THasGetLogCategories()); list.localData().appendCategoriesFromMetaType(tag(), std::integral_constant::Defined>()); list.localData().appendCategoriesFromMetaObject(tag(), std::is_base_of()); if (list.localData().isEmpty()) { list.localData().push_back(CLogCategory::uncategorized()); } } return list.localData(); } template void appendCategoriesFromMemberFunction(tag, std::true_type) { push_back(T::getLogCategories()); } void appendCategoriesFromMemberFunction(...) {} template void appendCategoriesFromMetaType(tag, std::true_type) { push_back(QMetaType::typeName(qMetaTypeId())); } void appendCategoriesFromMetaType(...) {} template void appendCategoriesFromMetaObject(tag, std::true_type) { appendCategoriesFromMetaObject(T::staticMetaObject); } void appendCategoriesFromMetaObject(...) {} void appendCategoriesFromMetaObject(const QMetaObject &); }; } Q_DECLARE_METATYPE(BlackMisc::CLogCategoryList) Q_DECLARE_METATYPE(BlackMisc::CCollection) Q_DECLARE_METATYPE(BlackMisc::CSequence) #endif