~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to libs/oxygen/oxygenlistmodel.h

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef ListModel_h
 
2
#define ListModel_h
 
3
//////////////////////////////////////////////////////////////////////////////
 
4
// listmodel.h
 
5
// -------------------
 
6
//
 
7
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
 
8
//
 
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
10
// of this software and associated documentation files (the "Software"), to
 
11
// deal in the Software without restriction, including without limitation the
 
12
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
13
// sell copies of the Software, and to permit persons to whom the Software is
 
14
// furnished to do so, subject to the following conditions:
 
15
//
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
//
 
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
24
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
25
// IN THE SOFTWARE.
 
26
//////////////////////////////////////////////////////////////////////////////
 
27
 
 
28
#include <algorithm>
 
29
#include <assert.h>
 
30
#include <set>
 
31
#include <vector>
 
32
 
 
33
#include "oxygenitemmodel.h"
 
34
 
 
35
namespace Oxygen
 
36
{
 
37
    //! Job model. Stores job information for display in lists
 
38
    template<class T> class ListModel : public ItemModel
 
39
    {
 
40
        
 
41
        public:
 
42
        
 
43
        //! value type
 
44
        typedef T ValueType;
 
45
        
 
46
        //! reference
 
47
        typedef T& Reference;
 
48
        
 
49
        //! pointer
 
50
        typedef T* Pointer;
 
51
        
 
52
        //! list of vector
 
53
        typedef std::vector<ValueType> List;
 
54
        
 
55
        //! list of vector
 
56
        typedef std::set<ValueType> Set;
 
57
        
 
58
        //! constructor
 
59
        ListModel(QObject *parent = 0):
 
60
            ItemModel( parent )
 
61
        {}
 
62
            
 
63
        //! destructor
 
64
        virtual ~ListModel()
 
65
        {}
 
66
        
 
67
        //!@name methods reimplemented from base class
 
68
        //@{
 
69
        
 
70
        //! flags
 
71
        virtual Qt::ItemFlags flags(const QModelIndex &index) const
 
72
        {
 
73
            if (!index.isValid()) return 0;
 
74
            return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 
75
        }
 
76
        
 
77
        //! unique index for given row, column and parent index
 
78
        virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
 
79
        {
 
80
            
 
81
            // check if index is valid
 
82
            if( !hasIndex( row, column, parent ) ) return QModelIndex();
 
83
            
 
84
            // return invalid index if parent is valid
 
85
            if( parent.isValid() ) return QModelIndex();
 
86
            
 
87
            // check against _values
 
88
            return ( row < (int) _values.size() ) ? createIndex( row, column ):QModelIndex();
 
89
            
 
90
        }
 
91
        
 
92
        //! index of parent
 
93
        virtual QModelIndex parent(const QModelIndex &) const
 
94
        { return QModelIndex(); }
 
95
        
 
96
        //! number of rows below given index
 
97
        virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
 
98
        { return parent.isValid() ? 0:_values.size(); }
 
99
        
 
100
        //@}
 
101
        
 
102
        //!@name selection
 
103
        //@{
 
104
        
 
105
        //! clear internal list selected items
 
106
        virtual void clearSelectedIndexes( void )
 
107
        { _selection.clear(); }
 
108
        
 
109
        //! store index internal selection state
 
110
        virtual void setIndexSelected( const QModelIndex& index, bool value )
 
111
        {
 
112
            if( value ) _selection.push_back( get(index) );
 
113
            else _selection.erase( std::remove( _selection.begin(), _selection.end(), get(index) ), _selection.end() );
 
114
        }
 
115
        
 
116
        //! get list of internal selected items
 
117
        virtual QModelIndexList selectedIndexes( void ) const
 
118
        {
 
119
            
 
120
            QModelIndexList out;
 
121
            for( typename List::const_iterator iter = _selection.begin(); iter != _selection.end(); iter++ )
 
122
            {
 
123
                QModelIndex index( ListModel::index( *iter ) );
 
124
                if( index.isValid() ) out.push_back( index );
 
125
            }
 
126
            return out;
 
127
            
 
128
        }
 
129
        
 
130
        //@}
 
131
        
 
132
        //!@name interface
 
133
        //@{
 
134
        
 
135
        //! add value
 
136
        virtual void add( const ValueType& value )
 
137
        {
 
138
            
 
139
            emit layoutAboutToBeChanged();
 
140
            _add( value );
 
141
            privateSort();
 
142
            emit layoutChanged();
 
143
            
 
144
        }
 
145
        
 
146
        //! add values
 
147
        virtual void add( const List& values )
 
148
        {
 
149
            
 
150
            // check if not empty
 
151
            // this avoids sending useless signals
 
152
            if( values.empty() ) return;
 
153
            
 
154
            emit layoutAboutToBeChanged();
 
155
            
 
156
            for( typename List::const_iterator iter = values.begin(); iter != values.end(); iter++ )
 
157
            { _add( *iter ); }
 
158
            
 
159
            privateSort();
 
160
            emit layoutChanged();
 
161
            
 
162
        }
 
163
        
 
164
        
 
165
        //! add values
 
166
        /*! this method uses a Set to add the values. It speeds up the updating of existing values */
 
167
        virtual void add( Set values )
 
168
        {
 
169
            
 
170
            emit layoutAboutToBeChanged();
 
171
            
 
172
            for( typename List::iterator iter = _values.begin(); iter != _values.end(); iter++ )
 
173
            {
 
174
                // see if current iterator is found in values set
 
175
                typename Set::iterator found_iter( values.find( *iter ) );
 
176
                if( found_iter != values.end() )
 
177
                {
 
178
                    *iter = *found_iter;
 
179
                    values.erase( found_iter );
 
180
                }
 
181
            }
 
182
            
 
183
            // insert remaining values at the end
 
184
            _values.insert( _values.end(), values.begin(), values.end() );
 
185
            
 
186
            privateSort();
 
187
            emit layoutChanged();
 
188
            
 
189
        }
 
190
        
 
191
        
 
192
        //! insert values
 
193
        virtual void insert( const QModelIndex& index, const ValueType& value )
 
194
        {
 
195
            emit layoutAboutToBeChanged();
 
196
            _insert( index, value );
 
197
            emit layoutChanged();
 
198
        }
 
199
        
 
200
        //! insert values
 
201
        virtual void insert( const QModelIndex& index, const List& values )
 
202
        {
 
203
            emit layoutAboutToBeChanged();
 
204
            
 
205
            // need to loop in reverse order so that the "values" ordering is preserved
 
206
            for( typename List::const_reverse_iterator iter = values.rbegin(); iter != values.rend(); iter++ )
 
207
                _insert( index, *iter );
 
208
            emit layoutChanged();
 
209
        }
 
210
        
 
211
        //! insert values
 
212
        virtual void replace( const QModelIndex& index, const ValueType& value )
 
213
        {
 
214
            if( !index.isValid() ) add( value );
 
215
            else {
 
216
                emit layoutAboutToBeChanged();
 
217
                setIndexSelected( index, false );
 
218
                _values[index.row()] = value;
 
219
                setIndexSelected( index, true );
 
220
                emit layoutChanged();
 
221
            }
 
222
        }
 
223
        
 
224
        //! remove
 
225
        virtual void remove( const ValueType& value )
 
226
        {
 
227
            
 
228
            emit layoutAboutToBeChanged();
 
229
            _remove( value );
 
230
            emit layoutChanged();
 
231
            return;
 
232
            
 
233
        }
 
234
        
 
235
        //! remove
 
236
        virtual void remove( const List& values )
 
237
        {
 
238
            
 
239
            // check if not empty
 
240
            // this avoids sending useless signals
 
241
            if( values.empty() ) return;
 
242
            
 
243
            emit layoutAboutToBeChanged();
 
244
            for( typename List::const_iterator iter = values.begin(); iter != values.end(); iter++ )
 
245
            { _remove( *iter ); }
 
246
            emit layoutChanged();
 
247
            return;
 
248
            
 
249
        }
 
250
        
 
251
        //! clear
 
252
        virtual void clear( void )
 
253
        { set( List() ); }
 
254
        
 
255
        //! update values from list
 
256
        /*!
 
257
        values that are not found in current are removed
 
258
        new values are set to the end.
 
259
        This is slower than the "set" method, but the selection is not cleared in the process
 
260
        */
 
261
        virtual void update( List values )
 
262
        {
 
263
            
 
264
            emit layoutAboutToBeChanged();
 
265
            
 
266
            // store values to be removed
 
267
            List removed_values;
 
268
            
 
269
            // update values that are common to both lists
 
270
            for( typename List::iterator iter = _values.begin(); iter != _values.end(); iter++ )
 
271
            {
 
272
                
 
273
                // see if iterator is in list
 
274
                typename List::iterator found_iter( std::find( values.begin(), values.end(), *iter ) );
 
275
                if( found_iter == values.end() ) removed_values.push_back( *iter );
 
276
                else {
 
277
                    *iter = *found_iter;
 
278
                    values.erase( found_iter );
 
279
                }
 
280
                
 
281
            }
 
282
            
 
283
            // remove values that have not been found in new list
 
284
            for( typename List::const_iterator iter = removed_values.begin(); iter != removed_values.end(); iter++ )
 
285
            { _remove( *iter ); }
 
286
            
 
287
            // add remaining values
 
288
            for( typename List::const_iterator iter = values.begin(); iter != values.end(); iter++ )
 
289
            { _add( *iter ); }
 
290
            
 
291
            privateSort();
 
292
            emit layoutChanged();
 
293
            
 
294
        }
 
295
        
 
296
        //! set all values
 
297
        virtual void set( const List& values )
 
298
        {
 
299
            
 
300
            emit layoutAboutToBeChanged();
 
301
            _values = values;
 
302
            _selection.clear();
 
303
            privateSort();
 
304
            emit layoutChanged();
 
305
            
 
306
            return;
 
307
        }
 
308
        
 
309
        //! return all values
 
310
        const List& get( void ) const
 
311
        { return _values; }
 
312
        
 
313
        //! return value for given index
 
314
        virtual ValueType get( const QModelIndex& index ) const
 
315
        { return (index.isValid() && index.row() < int(_values.size()) ) ? _values[index.row()]:ValueType(); }
 
316
        
 
317
        //! return value for given index
 
318
        virtual ValueType& get( const QModelIndex& index )
 
319
        {
 
320
            assert( index.isValid() && index.row() < int( _values.size() ) );
 
321
            return _values[index.row()];
 
322
        }
 
323
        
 
324
        //! return all values
 
325
        List get( const QModelIndexList& indexes ) const
 
326
        {
 
327
            List out;
 
328
            for( QModelIndexList::const_iterator iter = indexes.begin(); iter != indexes.end(); iter++ )
 
329
            { if( iter->isValid() && iter->row() < int(_values.size()) ) out.push_back( get( *iter ) ); }
 
330
            return out;
 
331
        }
 
332
        
 
333
        //! return index associated to a given value
 
334
        virtual QModelIndex index( const ValueType& value, int column = 0 ) const
 
335
        {
 
336
            for( unsigned int row=0; row<_values.size(); row++ )
 
337
            { if( value == _values[row] ) return index( row, column ); }
 
338
            return QModelIndex();
 
339
        }
 
340
        
 
341
        //@}
 
342
        
 
343
        protected:
 
344
        
 
345
        //! return all values
 
346
        List& _get( void )
 
347
        { return _values; }
 
348
        
 
349
        //! add, without update
 
350
        virtual void _add( const ValueType& value )
 
351
        {
 
352
            typename List::iterator iter = std::find( _values.begin(), _values.end(), value );
 
353
            if( iter == _values.end() ) _values.push_back( value );
 
354
            else *iter = value;
 
355
        }
 
356
        
 
357
        //! add, without update
 
358
        virtual void _insert( const QModelIndex& index, const ValueType& value )
 
359
        {
 
360
            if( !index.isValid() ) add( value );
 
361
            int row = 0;
 
362
            typename List::iterator iter( _values.begin() );
 
363
            for( ;iter != _values.end() && row != index.row(); iter++, row++ )
 
364
            {}
 
365
            
 
366
            _values.insert( iter, value );
 
367
        }
 
368
        
 
369
        //! remove, without update
 
370
        virtual void _remove( const ValueType& value )
 
371
        {
 
372
            _values.erase( std::remove( _values.begin(), _values.end(), value ), _values.end() );
 
373
            _selection.erase( std::remove( _selection.begin(), _selection.end(), value ), _selection.end() );
 
374
        }
 
375
        
 
376
        private:
 
377
        
 
378
        //! values
 
379
        List _values;
 
380
        
 
381
        //! selection
 
382
        List _selection;
 
383
        
 
384
    };
 
385
}
 
386
#endif