1
/****************************************************************************************
2
* Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org> *
3
* Copyright (c) 2009 Ian Monroe <ian@monroe.nu> *
4
* Copyright (c) 2009 Max Howell <max@last.fm> *
6
* This program is free software; you can redistribute it and/or modify it under *
7
* the terms of the GNU General Public License as published by the Free Software *
8
* Foundation; either version 2 of the License, or (at your option) any later *
11
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
12
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
13
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License along with *
16
* this program. If not, see <http://www.gnu.org/licenses/>. *
17
****************************************************************************************/
19
#ifndef SMART_POINTER_LIST_H
20
#define SMART_POINTER_LIST_H
22
#include <QList> //baseclass
23
#include <QObject> //baseclass
27
class DLLEXPORT SmartPointerListDaddy : public QObject
30
QList<QObject*>& m_list;
33
SmartPointerListDaddy( QList<QObject*>* list ) : m_list( *list )
39
m_list.removeAll( sender() );
43
/** QList has no virtual functions, so we inherit privately and define the
44
* interface exactly to ensure users can't write code that breaks the
45
* class's internal behaviour.
47
* I deliberately didn't define clear. I worried people would assume it
48
* deleted the pointers. Or assume it didn't. I didn't expose a few other
49
* functions for that reason.
51
* non-const iterator functions are not exposed as they access the QList
52
* baseclass, and then the Daddy wouldn't be watching newly inserted items.
55
* Exposed clear. This class doesn't have a QPtrList autodelete functionality
56
* ever, so if people think that, they're really confused! -- Ian Monroe
59
* This class is NOT implicitly shared like QList. Passing it around
60
* ***will*** cause it to iterate and copy all the elements in the copy
64
template <class T> class SmartPointerList : private QList<T*>
66
class SmartPointerListDaddy* m_daddy;
69
SmartPointerList() : m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
77
SmartPointerList( const SmartPointerList<T>& that )
79
, m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
81
QListIterator<T*> i( that );
86
SmartPointerList& operator=( const SmartPointerList<T>& that )
88
QListIterator<T*> i( *this);
90
QObject::disconnect( m_daddy, 0, i.next(), 0 );
92
QList<T*>::operator=( that );
95
QListIterator<T*> i( that );
97
m_daddy->connect( i.next(), SIGNAL(destroyed()), SLOT(onDestroyed()) );
103
// keep same function names as Qt
106
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
107
QList<T*>::append( o );
112
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
113
QList<T*>::prepend( o );
116
SmartPointerList& operator+=( T* o )
122
SmartPointerList& operator<<( T* o )
124
return operator+=( o );
127
SmartPointerList operator+( const SmartPointerList that )
129
SmartPointerList<T> copy = *this;
130
QListIterator<T*> i( that );
132
copy.append( i.next() );
136
SmartPointerList& operator+=( const SmartPointerList that )
138
QListIterator<T*> i( that );
144
bool operator==( const SmartPointerList& that )
146
return QList<T*>::operator==( that );
149
void push_back( T* o )
154
void push_front( T* o )
159
void replace( int i, T* o )
161
QList<T*>::replace( i, o );
162
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
165
/** this is a "safe" class. We always bounds check */
166
inline T* operator[]( int index ) const { return QList<T*>::value( index ); }
167
inline T* at( int index ) const { return QList<T*>::value( index ); }
169
// make public safe functions again
170
using QList<T*>::back;
171
using QList<T*>::constBegin;
172
using QList<T*>::constEnd;
173
using typename QList<T*>::const_iterator;
174
using QList<T*>::contains;
175
using QList<T*>::count;
176
using QList<T*>::empty;
177
using QList<T*>::erase;
178
using QList<T*>::first;
179
using QList<T*>::front;
180
using QList<T*>::indexOf;
181
using QList<T*>::insert;
182
using QList<T*>::isEmpty;
183
using QList<T*>::last;
184
using QList<T*>::lastIndexOf;
185
using QList<T*>::mid;
186
using QList<T*>::move;
187
using QList<T*>::pop_back;
188
using QList<T*>::pop_front;
189
using QList<T*>::size;
190
using QList<T*>::swap;
191
using QList<T*>::value;
192
using QList<T*>::operator!=;
193
// using QList<T*>::operator==;
195
// can't use using directive here since we only want the const versions
196
typename QList<T*>::const_iterator begin() const { return QList<T*>::constBegin(); }
197
typename QList<T*>::const_iterator end() const { return QList<T*>::constEnd(); }
199
// it can lead to poor performance situations if we don't disconnect
200
// but I think it's not worth making this class more complicated for such
202
using QList<T*>::clear;
203
using QList<T*>::removeAll;
204
using QList<T*>::removeAt;
205
using QList<T*>::removeFirst;
206
using QList<T*>::removeLast;
207
using QList<T*>::removeOne;
208
using QList<T*>::takeAt;
209
using QList<T*>::takeFirst;
210
using QList<T*>::takeLast;
213
#endif //HEADER_GUARD