~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/libtomahawk/utils/SmartPointerList.h

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>                                          *
 
5
 *                                                                                      *
 
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           *
 
9
 * version.                                                                             *
 
10
 *                                                                                      *
 
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.             *
 
14
 *                                                                                      *
 
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
 ****************************************************************************************/
 
18
 
 
19
#ifndef SMART_POINTER_LIST_H
 
20
#define SMART_POINTER_LIST_H
 
21
 
 
22
#include <QList>   //baseclass
 
23
#include <QObject> //baseclass
 
24
 
 
25
#include "DllMacro.h"
 
26
 
 
27
class DLLEXPORT SmartPointerListDaddy : public QObject
 
28
{
 
29
    Q_OBJECT
 
30
    QList<QObject*>& m_list;
 
31
 
 
32
public:
 
33
    SmartPointerListDaddy( QList<QObject*>* list ) : m_list( *list )
 
34
    {}
 
35
 
 
36
private slots:
 
37
    void onDestroyed()
 
38
    {
 
39
        m_list.removeAll( sender() );
 
40
    }
 
41
};
 
42
 
 
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.
 
46
  *
 
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.
 
50
  *
 
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.
 
53
  *
 
54
  * --mxcl
 
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
 
57
  *
 
58
  * NOTE:
 
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
 
61
  *       constructor!
 
62
  *
 
63
  */
 
64
template <class T> class SmartPointerList : private QList<T*>
 
65
{
 
66
    class SmartPointerListDaddy* m_daddy;
 
67
 
 
68
public:
 
69
    SmartPointerList() : m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
 
70
    {}
 
71
 
 
72
    ~SmartPointerList()
 
73
    {
 
74
        delete m_daddy;
 
75
    }
 
76
 
 
77
    SmartPointerList( const SmartPointerList<T>& that )
 
78
            : QList<T*>()
 
79
            , m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
 
80
    {
 
81
        QListIterator<T*> i( that );
 
82
        while (i.hasNext())
 
83
            append( i.next() );
 
84
    }
 
85
 
 
86
    SmartPointerList& operator=( const SmartPointerList<T>& that )
 
87
    {
 
88
        QListIterator<T*> i( *this);
 
89
        while (i.hasNext())
 
90
            QObject::disconnect( m_daddy, 0, i.next(), 0 );
 
91
 
 
92
        QList<T*>::operator=( that );
 
93
 
 
94
        if (this != &that) {
 
95
            QListIterator<T*> i( that );
 
96
            while (i.hasNext())
 
97
                m_daddy->connect( i.next(), SIGNAL(destroyed()), SLOT(onDestroyed()) );
 
98
        }
 
99
 
 
100
        return *this;
 
101
    }
 
102
 
 
103
    // keep same function names as Qt
 
104
    void append( T* o )
 
105
    {
 
106
        m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
 
107
        QList<T*>::append( o );
 
108
    }
 
109
 
 
110
    void prepend( T* o )
 
111
    {
 
112
        m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
 
113
        QList<T*>::prepend( o );
 
114
    }
 
115
 
 
116
    SmartPointerList& operator+=( T* o )
 
117
    {
 
118
        append( o );
 
119
        return *this;
 
120
    }
 
121
 
 
122
    SmartPointerList& operator<<( T* o )
 
123
    {
 
124
        return operator+=( o );
 
125
    }
 
126
 
 
127
    SmartPointerList operator+( const SmartPointerList that )
 
128
    {
 
129
        SmartPointerList<T> copy = *this;
 
130
        QListIterator<T*> i( that );
 
131
        while (i.hasNext())
 
132
            copy.append( i.next() );
 
133
        return copy;
 
134
    }
 
135
 
 
136
    SmartPointerList& operator+=( const SmartPointerList that )
 
137
    {
 
138
        QListIterator<T*> i( that );
 
139
        while (i.hasNext())
 
140
            append( i.next() );
 
141
        return *this;
 
142
    }
 
143
 
 
144
    bool operator==( const SmartPointerList& that )
 
145
    {
 
146
        return QList<T*>::operator==( that );
 
147
    }
 
148
 
 
149
    void push_back( T* o )
 
150
    {
 
151
        append( o );
 
152
    }
 
153
 
 
154
    void push_front( T* o )
 
155
    {
 
156
        prepend( o );
 
157
    }
 
158
 
 
159
    void replace( int i, T* o )
 
160
    {
 
161
        QList<T*>::replace( i, o );
 
162
        m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
 
163
    }
 
164
 
 
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 ); }
 
168
 
 
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==;
 
194
 
 
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(); }
 
198
 
 
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
 
201
    // an edge case
 
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;
 
211
};
 
212
 
 
213
#endif //HEADER_GUARD
 
214