File indexing completed on 2024-05-05 04:38:46

0001 /*
0002     SPDX-FileCopyrightText: 2014 Kevin Funk <kfunk@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #ifndef KDEVPLATFORM_OBJECTLIST_H
0008 #define KDEVPLATFORM_OBJECTLIST_H
0009 
0010 #include <QObject>
0011 #include <QList>
0012 
0013 #include "utilexport.h"
0014 
0015 namespace KDevelop {
0016 class ObjectListTrackerPrivate;
0017 
0018 /**
0019  * @brief Class for tracking a set of alive objects inheriting from QObject.
0020  *
0021  * Add individual objects via the append() method to have their lifetime being monitored by this class.
0022  * In case one of the tracked objects is destroyed, it is removed from the list.
0023  *
0024  * This means this class always contains a set of valid pointers to QObject instances.
0025  * The up-to-date list can be access via the data() method.
0026  *
0027  * @note You are *not* being notified if an item is removed from the list.
0028  * The purpose of this class is to provide a simple mechanism to keep track of a set of *alive* objects
0029  *
0030  * @sa append()
0031  * @sa data()
0032  */
0033 class KDEVPLATFORMUTIL_EXPORT ObjectListTracker : public QObject
0034 {
0035     Q_OBJECT
0036 
0037 public:
0038     enum CleanupBehavior {
0039         NoCleanupWhenDone,  ///< Do nothing when this object is destructed
0040         CleanupWhenDone     ///< Delete list of items when this object is destructed
0041     };
0042 
0043     explicit ObjectListTracker(CleanupBehavior behavior = NoCleanupWhenDone, QObject* parent = nullptr);
0044     ~ObjectListTracker() override;
0045 
0046     /**
0047      * Append and track object @p object
0048      *
0049      * In case @p object is destroyed, it gets removed from the list
0050      *
0051      * @note If @p object is already tracked, this operation is a no-op
0052      */
0053     void append(QObject* object);
0054     /**
0055      * Remove and no longer track object @p object
0056      *
0057      * @return False if object @p object wasn't tracked or null, otherwise true
0058      */
0059     bool remove(QObject* object);
0060     /**
0061      * Delete all objects currently tracked and clears the list
0062      */
0063     void deleteAll();
0064 
0065     /**
0066      * Accessor towards to the internal list of currently tracked objects
0067      */
0068     const QList<QObject*>& data() const;
0069 
0070 private:
0071     void objectDestroyed(QObject*);
0072 
0073 private:
0074     const QScopedPointer<class ObjectListTrackerPrivate> d_ptr;
0075     Q_DECLARE_PRIVATE(ObjectListTracker)
0076 };
0077 
0078 /**
0079  * @brief Template-based wrapper around ObjectListTracker for tracking a set of objects inheriting from QObject
0080  *
0081  * Provides a type-safe way to access and mutate ObjectListTracker
0082  *
0083  * @sa KDevelop::ObjectListTracker
0084  */
0085 template<class T>
0086 class ObjectList
0087 {
0088 public:
0089     explicit ObjectList(ObjectListTracker::CleanupBehavior behavior = ObjectListTracker::NoCleanupWhenDone)
0090         : m_tracker(behavior)
0091     {
0092     };
0093 
0094     void append(T* object)
0095     {
0096         m_tracker.append(object);
0097     }
0098     bool remove(T* object)
0099     {
0100         return m_tracker.remove(object);
0101     }
0102     void deleteAll()
0103     {
0104         m_tracker.deleteAll();
0105     }
0106 
0107     /**
0108      * Accessor to the up-to-date list inside the object tracker
0109      */
0110     QList<T*> data() const
0111     {
0112         // This is considered safe, as QList<X*> and QList<Y*> have the same memory layout
0113         // also see http://comments.gmane.org/gmane.comp.lib.qt.general/38943
0114         return *reinterpret_cast<const QList<T*>*>(&m_tracker.data());
0115     }
0116 
0117 private:
0118     ObjectListTracker m_tracker;
0119 };
0120 
0121 }
0122 
0123 #endif // KDEVPLATFORM_OBJECTLIST_H