~ubuntu-branches/ubuntu/karmic/kdepim/karmic-backports

« back to all changes in this revision

Viewing changes to akonadi/akonadi_next/entitytreemodel_p.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi, Alessandro Ghersi, Harald Sitter
  • Date: 2009-06-27 04:40:05 UTC
  • mfrom: (1.1.39 upstream)
  • Revision ID: james.westby@ubuntu.com-20090627044005-4y2vm9xz7rvmzi4p
Tags: 4:4.2.95svn20090701-0ubuntu1
[ Alessandro Ghersi ]
* New upstream release
  - Bump build-deps
* Remove akonadi-kde and libmaildir4 packages
  - remove akonadi-kde.install and libmaildir4.install
  - remove libmaildir4 from debian/rules
  - remove akonadi-kde and libmaildir4 from depends
  - remove akonadi-kde and libmaildir4 from installgen
* Update kdepim-dev.install
* Update kpilot.install
* Add akonadi-kde and libmaildir4 transitional packages

[ Harald Sitter ]
* KAddressbook replaces Kontact << 4.2.85 (LP: #378373)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (c) 2008 Stephen Kelly <steveire@gmail.com>
 
3
 
 
4
    This library is free software; you can redistribute it and/or modify it
 
5
    under the terms of the GNU Library General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or (at your
 
7
    option) any later version.
 
8
 
 
9
    This library is distributed in the hope that it will be useful, but WITHOUT
 
10
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 
12
    License for more details.
 
13
 
 
14
    You should have received a copy of the GNU Library General Public License
 
15
    along with this library; see the file COPYING.LIB.  If not, write to the
 
16
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
    02110-1301, USA.
 
18
*/
 
19
 
 
20
#include "entitytreemodel_p.h"
 
21
#include "entitytreemodel.h"
 
22
 
 
23
#include <KDE/KIconLoader>
 
24
#include <KDE/KUrl>
 
25
 
 
26
#include <akonadi/agentmanager.h>
 
27
#include <akonadi/agenttype.h>
 
28
#include <akonadi/collectionfetchjob.h>
 
29
#include <akonadi/collectionstatistics.h>
 
30
#include <akonadi/collectionstatisticsjob.h>
 
31
#include <akonadi/entitydisplayattribute.h>
 
32
#include <akonadi/itemfetchjob.h>
 
33
#include <akonadi/monitor.h>
 
34
#include <akonadi/session.h>
 
35
 
 
36
#include "collectionchildorderattribute.h"
 
37
 
 
38
#include <kdebug.h>
 
39
 
 
40
using namespace Akonadi;
 
41
 
 
42
EntityTreeModelPrivate::EntityTreeModelPrivate( EntityTreeModel *parent )
 
43
    : q_ptr( parent ),
 
44
      m_collectionFetchStrategy( EntityTreeModel::FetchCollectionsRecursive ),
 
45
      m_itemPopulation( EntityTreeModel::ImmediatePopulation ),
 
46
      m_showRootCollection( false )
 
47
{
 
48
}
 
49
 
 
50
 
 
51
int EntityTreeModelPrivate::indexOf( const QList<Node*> &nodes, Entity::Id id ) const
 
52
{
 
53
  int i = 0;
 
54
  foreach ( const Node *node, nodes ) {
 
55
    if ( node->id == id )
 
56
      return i;
 
57
    i++;
 
58
  }
 
59
 
 
60
  return -1;
 
61
}
 
62
 
 
63
void EntityTreeModelPrivate::fetchItems( const Collection &parent )
 
64
{
 
65
  Q_Q( EntityTreeModel );
 
66
//   kDebug() << parent.remoteId();
 
67
  Akonadi::ItemFetchJob *itemJob = new Akonadi::ItemFetchJob( parent, m_session );
 
68
  itemJob->setFetchScope( m_monitor->itemFetchScope() );
 
69
 
 
70
  // ### HACK: itemsReceivedFromJob needs to know which collection items were added to.
 
71
  // That is not provided by akonadi, so we attach it in a property.
 
72
  itemJob->setProperty( ItemFetchCollectionId(), QVariant( parent.id() ) );
 
73
 
 
74
  q->connect( itemJob, SIGNAL( itemsReceived( const Akonadi::Item::List& ) ),
 
75
              q, SLOT( itemsFetched( const Akonadi::Item::List& ) ) );
 
76
  q->connect( itemJob, SIGNAL( result( KJob* ) ),
 
77
              q, SLOT( fetchJobDone( KJob* ) ) );
 
78
}
 
79
 
 
80
void EntityTreeModelPrivate::fetchCollections( const Collection &collection, CollectionFetchJob::Type type )
 
81
{
 
82
  Q_Q( EntityTreeModel );
 
83
  CollectionFetchJob *job = new CollectionFetchJob( collection, type, m_session );
 
84
  job->includeUnsubscribed( m_includeUnsubscribed );
 
85
  q->connect( job, SIGNAL( collectionsReceived( const Akonadi::Collection::List& ) ),
 
86
              q, SLOT( collectionsFetched( const Akonadi::Collection::List& ) ) );
 
87
  q->connect( job, SIGNAL( result( KJob* ) ),
 
88
              q, SLOT( fetchJobDone( KJob* ) ) );
 
89
}
 
90
 
 
91
void EntityTreeModelPrivate::collectionsFetched( const Akonadi::Collection::List& collections )
 
92
{
 
93
  // TODO: refactor this stuff into separate methods for listing resources in Collection::root, and listing collections within resources.
 
94
  Q_Q( EntityTreeModel );
 
95
  QHash<Collection::Id, Collection> newCollections;
 
96
  QHash<Collection::Id, QList<Collection::Id> > newChildCollections;
 
97
 
 
98
  Akonadi::AgentManager *agentManager = Akonadi::AgentManager::self();
 
99
 
 
100
  foreach ( const Collection collection, collections ) {
 
101
    if ( m_collections.contains( collection.id() ) ) {
 
102
      // If we already know about the collection, there is nothing left to do
 
103
      continue;
 
104
    }
 
105
    // ... otherwise we add it to the set of collections we need to handle.
 
106
    if ( collection.parent() == Collection::root().id() ) {
 
107
      Akonadi::AgentInstance agentInstance = agentManager->instance( collection.resource() );
 
108
 
 
109
      if ( ( !m_mimeChecker.isWantedCollection( collection ) ) &&
 
110
           ( !m_monitor->resourcesMonitored().contains( collection.resource().toUtf8() ) ) )
 
111
        continue;
 
112
    }
 
113
 
 
114
    newChildCollections[ collection.parent() ].append( collection.id() );
 
115
    newCollections.insert( collection.id(), collection );
 
116
  }
 
117
 
 
118
  // Insert new child collections into model.
 
119
  QHashIterator<Collection::Id, QList<Collection::Id> > it( newChildCollections );
 
120
  while ( it.hasNext() ) {
 
121
    it.next();
 
122
 
 
123
    // the key is the parent of new collections.
 
124
    const Collection::Id parentId = it.key();
 
125
 
 
126
    const QList<Collection::Id> newChildCollections = it.value();
 
127
    const int newChildCount = newChildCollections.size();
 
128
 
 
129
    if ( m_collections.contains( parentId ) ) {
 
130
      int startRow = 0; // Prepend collections.
 
131
 
 
132
      // TODO: account for ordering.
 
133
      const QModelIndex parentIndex = q->indexForCollection( m_collections.value( parentId ) );
 
134
 
 
135
      q->beginInsertRows( parentIndex, startRow, startRow + newChildCount - 1 );
 
136
      foreach ( const Collection::Id id, newChildCollections ) {
 
137
        const Collection collection = newCollections.value( id );
 
138
        m_collections.insert( id, collection );
 
139
 
 
140
        Node *node = new Node;
 
141
        node->id = id;
 
142
        node->parent = parentId;
 
143
        node->type = Node::Collection;
 
144
        m_childEntities[ parentId ].prepend( node );
 
145
      }
 
146
      q->endInsertRows();
 
147
 
 
148
      foreach ( const Collection::Id id, newChildCollections ) {
 
149
        const Collection collection = newCollections.value( id );
 
150
 
 
151
        // Fetch the next level of collections if necessary.
 
152
        if ( m_collectionFetchStrategy == EntityTreeModel::FetchCollectionsRecursive )
 
153
          fetchCollections( collection, CollectionFetchJob::FirstLevel );
 
154
 
 
155
        // Fetch items if necessary. If we don't fetch them now, we'll wait for an application
 
156
        // to request them through EntityTreeModel::fetchMore
 
157
        if ( m_itemPopulation == EntityTreeModel::ImmediatePopulation )
 
158
          fetchItems( collection );
 
159
      }
 
160
    }
 
161
    // TODO: Fetch parent again so that its entities get ordered properly. Or start a modify job?
 
162
    // Should I do this for all other cases as well instead of using transactions?
 
163
    // Could be a way around the fact that monitor could notify me of things out of order. a parent could
 
164
    // be 'changed' for its entities to be reordered before one of its entities is in the model yet.
 
165
  }
 
166
}
 
167
 
 
168
void EntityTreeModelPrivate::itemsFetched( const Akonadi::Item::List& items )
 
169
{
 
170
  Q_Q( EntityTreeModel );
 
171
  QObject *job = q->sender();
 
172
  if ( job ) {
 
173
    const Collection::Id collectionId = job->property( ItemFetchCollectionId() ).value<Collection::Id>();
 
174
    Item::List itemsToInsert;
 
175
    Item::List itemsToUpdate;
 
176
 
 
177
    const Collection collection = m_collections.value( collectionId );
 
178
 
 
179
    const QList<Node*> collectionEntities = m_childEntities.value( collectionId );
 
180
    foreach ( const Item &item, items ) {
 
181
      if ( indexOf( collectionEntities, item.id() ) != -1 ) {
 
182
        itemsToUpdate << item;
 
183
      } else {
 
184
        if ( m_mimeChecker.isWantedItem( item ) ) {
 
185
          itemsToInsert << item;
 
186
        }
 
187
      }
 
188
    }
 
189
    if ( itemsToInsert.size() > 0 ) {
 
190
      const int startRow = m_childEntities.value( collectionId ).size();
 
191
 
 
192
      const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collectionId ) );
 
193
      q->beginInsertRows( parentIndex, startRow, startRow + items.size() - 1 );
 
194
      foreach ( const Item &item, items ) {
 
195
        Item::Id itemId = item.id();
 
196
        m_items.insert( itemId, item );
 
197
 
 
198
        Node *node = new Node;
 
199
        node->id = itemId;
 
200
        node->parent = collectionId;
 
201
        node->type = Node::Item;
 
202
 
 
203
        m_childEntities[ collectionId ].append( node );
 
204
      }
 
205
      q->endInsertRows();
 
206
    }
 
207
  }
 
208
}
 
209
 
 
210
void EntityTreeModelPrivate::monitoredMimeTypeChanged( const QString & mimeType, bool monitored )
 
211
{
 
212
  if ( monitored )
 
213
    m_mimeChecker.addWantedMimeType( mimeType );
 
214
  else
 
215
    m_mimeChecker.removeWantedMimeType( mimeType );
 
216
}
 
217
 
 
218
void EntityTreeModelPrivate::monitoredCollectionAdded( const Akonadi::Collection& collection, const Akonadi::Collection& parent )
 
219
{
 
220
  Q_Q( EntityTreeModel );
 
221
//   if ( !passesFilter( collection.contentMimeTypes() ) )
 
222
//     return;
 
223
 
 
224
  // TODO: Use order attribute of parent if available
 
225
  // Otherwise prepend collections and append items. Currently this prepends all collections.
 
226
 
 
227
  // Or I can prepend and append for single signals, then 'change' the parent.
 
228
 
 
229
//   QList<qint64> childCols = m_childEntities.value( parent.id() );
 
230
//   int row = childCols.size();
 
231
//   int numChildCols = childCollections.value(parent.id()).size();
 
232
 
 
233
  const int row = 0;
 
234
 
 
235
  const QModelIndex parentIndex = q->indexForCollection( parent );
 
236
  q->beginInsertRows( parentIndex, row, row );
 
237
  m_collections.insert( collection.id(), collection );
 
238
 
 
239
  Node *node = new Node;
 
240
  node->id = collection.id();
 
241
  node->parent = parent.id();
 
242
  node->type = Node::Collection;
 
243
  m_childEntities[ parent.id() ].prepend( node );
 
244
  q->endInsertRows();
 
245
}
 
246
 
 
247
void EntityTreeModelPrivate::monitoredCollectionRemoved( const Akonadi::Collection& collection )
 
248
{
 
249
  Q_Q( EntityTreeModel );
 
250
 
 
251
  const int row = indexOf( m_childEntities.value( collection.parent() ), collection.id() );
 
252
 
 
253
//   int row = m_childEntities.value(collection.parent()).indexOf(collection.id());
 
254
  Q_ASSERT( row >= 0 );
 
255
  const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collection.parent() ) );
 
256
 
 
257
  q->beginRemoveRows( parentIndex, row, row );
 
258
 
 
259
  // TODO: Also need to handle all descendant collections and items here.
 
260
 
 
261
  // Remove deleted collection.
 
262
  m_collections.remove( collection.id() );
 
263
 
 
264
  // Remove children of deleted collection.
 
265
  m_childEntities.remove( collection.id() );
 
266
 
 
267
  // Remove deleted collection from its parent.
 
268
  m_childEntities[ collection.parent() ].removeAt( row );
 
269
 
 
270
  q->endRemoveRows();
 
271
}
 
272
 
 
273
void EntityTreeModelPrivate::monitoredCollectionMoved( const Akonadi::Collection& collection,
 
274
                                                       const Akonadi::Collection& sourceCollection,
 
275
                                                       const Akonadi::Collection& destCollection )
 
276
{
 
277
  Q_Q( EntityTreeModel );
 
278
 
 
279
  const int srcRow = indexOf( m_childEntities.value( sourceCollection.id() ), collection.id() );
 
280
 
 
281
  const QModelIndex srcParentIndex = q->indexForCollection( sourceCollection );
 
282
  const QModelIndex destParentIndex = q->indexForCollection( destCollection );
 
283
 
 
284
  const int destRow = 0; // Prepend collections
 
285
 
 
286
  q->beginMoveRows( srcParentIndex, srcRow, srcRow, destParentIndex, destRow );
 
287
  Node *node = m_childEntities[ sourceCollection.id() ].takeAt( srcRow );
 
288
  m_childEntities[ destCollection.id() ].prepend( node );
 
289
  q->endMoveRows();
 
290
}
 
291
 
 
292
void EntityTreeModelPrivate::monitoredCollectionChanged( const Akonadi::Collection &collection )
 
293
{
 
294
  Q_Q( EntityTreeModel );
 
295
 
 
296
  if ( m_collections.contains( collection.id() ) )
 
297
    m_collections[ collection.id() ] = collection;
 
298
 
 
299
  const QModelIndex index = q->indexForCollection( collection );
 
300
  q->dataChanged( index, index );
 
301
}
 
302
 
 
303
void EntityTreeModelPrivate::monitoredCollectionStatisticsChanged( Akonadi::Collection::Id,
 
304
                                                                   const Akonadi::CollectionStatistics& )
 
305
{
 
306
// kDebug();
 
307
}
 
308
 
 
309
void EntityTreeModelPrivate::monitoredItemAdded( const Akonadi::Item& item, const Akonadi::Collection& collection )
 
310
{
 
311
  Q_Q( EntityTreeModel );
 
312
 
 
313
  if ( !m_mimeChecker.isWantedItem( item ) )
 
314
    return;
 
315
 
 
316
  const int row = m_childEntities.value( collection.id() ).size();
 
317
 
 
318
  const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collection.id() ) );
 
319
 
 
320
  q->beginInsertRows( parentIndex, row, row );
 
321
  m_items.insert( item.id(), item );
 
322
  Node *node = new Node;
 
323
  node->id = item.id();
 
324
  node->parent = collection.id();
 
325
  node->type = Node::Item;
 
326
  m_childEntities[ collection.id() ].append( node );
 
327
  q->endInsertRows();
 
328
}
 
329
 
 
330
void EntityTreeModelPrivate::monitoredItemRemoved( const Akonadi::Item &item )
 
331
{
 
332
  Q_Q( EntityTreeModel );
 
333
 
 
334
  const Collection collection = getParentCollections( item ).at( 0 );
 
335
 
 
336
  const int row = indexOf( m_childEntities.value( collection.id() ), item.id() );
 
337
 
 
338
  const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collection.id() ) );
 
339
 
 
340
  q->beginInsertRows( parentIndex, row, row );
 
341
  m_items.remove( item.id() );
 
342
  m_childEntities[ collection.id() ].removeAt( row );
 
343
  q->endInsertRows();
 
344
}
 
345
 
 
346
void EntityTreeModelPrivate::monitoredItemChanged( const Akonadi::Item &item, const QSet<QByteArray>& )
 
347
{
 
348
  Q_Q( EntityTreeModel );
 
349
  m_items[ item.id() ] = item;
 
350
 
 
351
  const QModelIndexList indexes = q->indexesForItem( item );
 
352
  foreach ( const QModelIndex &index, indexes )
 
353
    q->dataChanged( index, index );
 
354
}
 
355
 
 
356
void EntityTreeModelPrivate::monitoredItemMoved( const Akonadi::Item& item,
 
357
                                                 const Akonadi::Collection& sourceItem,
 
358
                                                 const Akonadi::Collection& destItem )
 
359
{
 
360
  Q_Q( EntityTreeModel );
 
361
 
 
362
  const Item::Id itemId = item.id();
 
363
 
 
364
  const int srcRow = indexOf( m_childEntities.value( sourceItem.id() ), itemId );
 
365
 
 
366
  const QModelIndex srcIndex = q->indexForCollection( sourceItem );
 
367
  const QModelIndex destIndex = q->indexForCollection( destItem );
 
368
 
 
369
  // Where should it go? Always append items and prepend collections and reorganize them with separate reactions to Attributes?
 
370
 
 
371
  const int destRow = q->rowCount( destIndex );
 
372
 
 
373
  q->beginMoveRows( srcIndex, srcRow, srcRow, destIndex, destRow );
 
374
  Node *node = m_childEntities[ sourceItem.id() ].takeAt( srcRow );
 
375
  m_childEntities[ destItem.id() ].append( node );
 
376
  q->endMoveRows();
 
377
}
 
378
 
 
379
void EntityTreeModelPrivate::monitoredItemLinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
 
380
{
 
381
  kDebug() << item.remoteId() << collection.id();
 
382
  Q_Q( EntityTreeModel );
 
383
 
 
384
  if ( !m_mimeChecker.isWantedItem( item ) )
 
385
    return;
 
386
 
 
387
  const int row = m_childEntities.value( collection.id() ).size();
 
388
 
 
389
  const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collection.id() ) );
 
390
 
 
391
  q->beginInsertRows( parentIndex, row, row );
 
392
  Node *node = new Node;
 
393
  node->id = item.id();
 
394
  node->parent = collection.id();
 
395
  node->type = Node::Item;
 
396
  m_childEntities[ collection.id()].append( node );
 
397
  q->endInsertRows();
 
398
}
 
399
 
 
400
void EntityTreeModelPrivate::monitoredItemUnlinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
 
401
{
 
402
  Q_Q( EntityTreeModel );
 
403
 
 
404
  const int row = indexOf( m_childEntities.value( collection.id() ), item.id() );
 
405
 
 
406
  const QModelIndex parentIndex = q->indexForCollection( m_collections.value( collection.id() ) );
 
407
 
 
408
  q->beginInsertRows( parentIndex, row, row );
 
409
  m_childEntities[ collection.id() ].removeAt( row );
 
410
  q->endInsertRows();
 
411
}
 
412
 
 
413
void EntityTreeModelPrivate::fetchJobDone( KJob *job )
 
414
{
 
415
  if ( job->error() ) {
 
416
    kWarning( 5250 ) << "Job error: " << job->errorString() << endl;
 
417
  }
 
418
}
 
419
 
 
420
void EntityTreeModelPrivate::copyJobDone( KJob *job )
 
421
{
 
422
  if ( job->error() ) {
 
423
    kWarning( 5250 ) << "Job error: " << job->errorString() << endl;
 
424
  }
 
425
}
 
426
 
 
427
void EntityTreeModelPrivate::moveJobDone( KJob *job )
 
428
{
 
429
  if ( job->error() ) {
 
430
    kWarning( 5250 ) << "Job error: " << job->errorString() << endl;
 
431
  }
 
432
}
 
433
 
 
434
void EntityTreeModelPrivate::updateJobDone( KJob *job )
 
435
{
 
436
  if ( job->error() ) {
 
437
    // TODO: handle job errors
 
438
    kWarning( 5250 ) << "Job error:" << job->errorString();
 
439
  } else {
 
440
    // TODO: Is this trying to do the job of collectionstatisticschanged?
 
441
//     CollectionStatisticsJob *csjob = static_cast<CollectionStatisticsJob*>( job );
 
442
//     Collection result = csjob->collection();
 
443
//     collectionStatisticsChanged( result.id(), csjob->statistics() );
 
444
  }
 
445
}
 
446
 
 
447
void EntityTreeModelPrivate::startFirstListJob()
 
448
{
 
449
  Q_Q(EntityTreeModel);
 
450
 
 
451
  kDebug() << m_collections.size();
 
452
 
 
453
  if (m_collections.size() > 0)
 
454
    return;
 
455
 
 
456
  Collection rootCollection;
 
457
  // Even if the root collection is the invalid collection, we still need to start
 
458
  // the first list job with Collection::root.
 
459
  if ( m_showRootCollection ) {
 
460
    rootCollection = Collection::root();
 
461
    // Notify the outside that we're putting collection::root into the model.
 
462
//     kDebug() << "begin";
 
463
    q->beginInsertRows( QModelIndex(), 0, 0 );
 
464
    m_collections.insert( rootCollection.id(), rootCollection );
 
465
    m_rootNode = new Node;
 
466
    m_rootNode->id = rootCollection.id();
 
467
    m_rootNode->parent = -1;
 
468
    m_rootNode->type = Node::Collection;
 
469
    m_childEntities[ -1 ].append( m_rootNode );
 
470
//     kDebug() << "why";
 
471
    q->endInsertRows();
 
472
  } else {
 
473
    // Otherwise store it silently because it's not part of the usable model.
 
474
    rootCollection = m_rootCollection;
 
475
    m_rootNode = new Node;
 
476
    m_rootNode->id = rootCollection.id();
 
477
    m_rootNode->parent = -1;
 
478
    m_rootNode->type = Node::Collection;
 
479
    m_collections.insert( rootCollection.id(), rootCollection );
 
480
  }
 
481
 
 
482
//   kDebug() << "inserting" << rootCollection.id();
 
483
 
 
484
  // Includes recursive trees. Lower levels are fetched in the onRowsInserted slot if
 
485
  // necessary.
 
486
  if ( ( m_collectionFetchStrategy == EntityTreeModel::FetchFirstLevelChildCollections)
 
487
    || ( m_collectionFetchStrategy == EntityTreeModel::FetchCollectionsRecursive ) ) {
 
488
    fetchCollections( rootCollection, CollectionFetchJob::FirstLevel );
 
489
  }
 
490
  // If the root collection is not collection::root, then it could have items, and they will need to be
 
491
  // retrieved now.
 
492
 
 
493
  if ( m_itemPopulation != EntityTreeModel::NoItemPopulation ) {
 
494
//     kDebug() << (rootCollection == Collection::root());
 
495
    if (rootCollection != Collection::root())
 
496
      fetchItems( rootCollection );
 
497
  }
 
498
}
 
499
 
 
500
Collection EntityTreeModelPrivate::getParentCollection( Entity::Id id ) const
 
501
{
 
502
  QHashIterator<Collection::Id, QList<Node*> > iter( m_childEntities );
 
503
  while ( iter.hasNext() ) {
 
504
    iter.next();
 
505
    if ( indexOf( iter.value(), id ) != -1 ) {
 
506
      return m_collections.value( iter.key() );
 
507
    }
 
508
  }
 
509
 
 
510
  return Collection();
 
511
}
 
512
 
 
513
Collection::List EntityTreeModelPrivate::getParentCollections( const Item &item ) const
 
514
{
 
515
  Collection::List list;
 
516
  QHashIterator<Collection::Id, QList<Node*> > iter( m_childEntities );
 
517
  while ( iter.hasNext() ) {
 
518
    iter.next();
 
519
    if ( indexOf( iter.value(), item.id() ) != -1 ) {
 
520
      list << m_collections.value( iter.key() );
 
521
    }
 
522
  }
 
523
 
 
524
  return list;
 
525
}
 
526
 
 
527
Collection EntityTreeModelPrivate::getParentCollection( const Collection &collection ) const
 
528
{
 
529
  return m_collections.value( collection.parent() );
 
530
}
 
531
 
 
532
Entity::Id EntityTreeModelPrivate::childAt( Collection::Id id, int position, bool *ok ) const
 
533
{
 
534
  const QList<Node*> list = m_childEntities.value( id );
 
535
  if ( list.size() <= position ) {
 
536
    *ok = false;
 
537
    return 0;
 
538
  }
 
539
 
 
540
  *ok = true;
 
541
  return list.at( position )->id;
 
542
}
 
543
 
 
544
 
 
545
int EntityTreeModelPrivate::indexOf( Collection::Id parent, Collection::Id collectionId ) const
 
546
{
 
547
  return indexOf( m_childEntities.value( parent ), collectionId );
 
548
}
 
549
 
 
550
Item EntityTreeModelPrivate::getItem( Item::Id id) const
 
551
{
 
552
  if ( id > 0 )
 
553
    id *= -1;
 
554
 
 
555
  return m_items.value( id );
 
556
}