20 #include "itemmodel.h"
22 #include "itemfetchjob.h"
23 #include "collectionfetchjob.h"
24 #include "itemfetchscope.h"
26 #include "pastehelper_p.h"
30 #include <klocalizedstring.h>
33 #include <QCoreApplication>
34 #include <QtCore/QDebug>
35 #include <QtCore/QMimeData>
37 using namespace Akonadi;
49 ItemContainer(
const Item& i,
int r )
60 class ItemModel::Private
64 : mParent( parent ), monitor( new
Monitor() )
66 session =
new Session( QCoreApplication::instance()->applicationName().toUtf8()
67 + QByteArray(
"-ItemModel-" ) + QByteArray::number( qrand() ), mParent );
69 monitor->ignoreSession(
session );
71 mParent->connect( monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
72 mParent, SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
76 mParent, SLOT(itemAdded(Akonadi::Item)) );
77 mParent->connect( monitor, SIGNAL(itemRemoved(Akonadi::Item)),
78 mParent, SLOT(itemRemoved(Akonadi::Item)) );
80 mParent, SLOT(itemAdded(Akonadi::Item)) );
82 mParent, SLOT(itemRemoved(Akonadi::Item)) );
90 void listingDone( KJob* );
91 void collectionFetchResult( KJob* );
92 void itemChanged(
const Akonadi::Item&,
const QSet<QByteArray>& );
93 void itemsAdded(
const Akonadi::Item::List &list );
94 void itemAdded(
const Akonadi::Item &item );
96 void itemRemoved(
const Akonadi::Item& );
97 int rowForItem(
const Akonadi::Item& );
98 bool collectionIsCompatible()
const;
102 QList<ItemContainer*> items;
103 QHash<Item, ItemContainer*> itemHash;
110 bool ItemModel::Private::collectionIsCompatible()
const
113 if ( mParent->mimeTypes() == QStringList( QLatin1String(
"text/uri-list" ) ) )
117 Q_FOREACH(
const QString &type, mParent->mimeTypes() ) {
118 if ( collection.contentMimeTypes().contains( type ) ) {
125 void ItemModel::Private::listingDone( KJob * job )
129 if ( job->error() ) {
131 kWarning() <<
"Item query failed:" << job->errorString();
135 void ItemModel::Private::collectionFetchResult( KJob * job )
145 if ( !c.contentMimeTypes().isEmpty() ) {
146 mParent->setCollection(c);
148 kWarning() <<
"Failed to retrieve the contents mime type of the collection: " << c;
153 int ItemModel::Private::rowForItem(
const Akonadi::Item& item )
155 ItemContainer *container = itemHash.value( item );
164 if ( container->row < items.count()
165 && items.at( container->row ) == container )
166 return container->row;
169 const int numberOfItems( items.size() );
170 for (
int i = 0; i < numberOfItems; ++i ) {
171 if ( items.at( i )->item == item ) {
181 void ItemModel::Private::itemChanged(
const Akonadi::Item &item,
const QSet<QByteArray>& )
183 int row = rowForItem( item );
187 items[ row ]->item = item;
188 itemHash.remove( item );
189 itemHash[ item ] = items[ row ];
191 QModelIndex start = mParent->index( row, 0, QModelIndex() );
192 QModelIndex end = mParent->index( row, mParent->columnCount( QModelIndex() ) - 1 , QModelIndex() );
194 mParent->dataChanged( start, end );
199 if ( colSrc == collection && colDst != collection )
205 if ( colDst == collection && colSrc != collection )
212 void ItemModel::Private::itemsAdded(
const Akonadi::Item::List &list )
214 if ( list.isEmpty() )
216 mParent->beginInsertRows( QModelIndex(), items.count(), items.count() + list.count() - 1 );
217 foreach (
const Item &item, list ) {
218 ItemContainer *c =
new ItemContainer( item, items.count() );
220 itemHash[ item ] = c;
222 mParent->endInsertRows();
225 void ItemModel::Private::itemAdded(
const Akonadi::Item &item )
232 void ItemModel::Private::itemRemoved(
const Akonadi::Item &_item )
234 int row = rowForItem( _item );
238 mParent->beginRemoveRows( QModelIndex(), row, row );
239 const Item item = items.at( row )->item;
240 Q_ASSERT( item.isValid() );
241 itemHash.remove( item );
242 delete items.takeAt( row );
243 mParent->endRemoveRows();
246 ItemModel::ItemModel( QObject *parent ) :
247 QAbstractTableModel( parent ),
248 d( new Private( this ) )
257 QVariant ItemModel::data(
const QModelIndex & index,
int role )
const
259 if ( !index.isValid() )
261 if ( index.row() >= d->items.count() )
263 const Item item = d->items.at( index.row() )->item;
264 if ( !item.isValid() )
267 if ( role == Qt::DisplayRole ) {
268 switch ( index.column() ) {
270 return QString::number( item.id() );
272 return item.remoteId();
274 return item.mimeType();
285 var.setValue( item );
290 return item.mimeType();
295 int ItemModel::rowCount(
const QModelIndex & parent )
const
297 if ( !parent.isValid() )
298 return d->items.count();
302 int ItemModel::columnCount(
const QModelIndex & parent)
const
304 if ( !parent.isValid() )
309 QVariant ItemModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
311 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
316 return i18n(
"Remote Id" );
318 return i18n(
"MimeType" );
323 return QAbstractTableModel::headerData( section, orientation, role );
329 if ( d->collection == collection )
336 connect( job, SIGNAL(result(KJob*)),
this, SLOT(collectionFetchResult(KJob*)) );
340 d->monitor->setCollectionMonitored( d->collection,
false );
344 d->monitor->setCollectionMonitored( d->collection,
true );
347 qDeleteAll( d->items );
355 if ( d->collectionIsCompatible() ) {
358 connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)),
359 SLOT(itemsAdded(Akonadi::Item::List)) );
360 connect( job, SIGNAL(result(KJob*)), SLOT(listingDone(KJob*)) );
368 d->monitor->setItemFetchScope( fetchScope );
373 return d->monitor->itemFetchScope();
378 if ( !index.isValid() )
379 return Akonadi::Item();
381 if ( index.row() >= d->items.count() )
382 return Akonadi::Item();
384 Item item = d->items.at( index.row() )->item;
385 if ( item.isValid() ) {
388 return Akonadi::Item();
392 Qt::ItemFlags ItemModel::flags(
const QModelIndex &index )
const
394 Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
397 return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
399 return Qt::ItemIsDropEnabled | defaultFlags;
402 QStringList ItemModel::mimeTypes()
const
404 return QStringList() << QLatin1String(
"text/uri-list" );
412 QMimeData *ItemModel::mimeData(
const QModelIndexList &indexes )
const
414 QMimeData *data =
new QMimeData();
417 foreach (
const QModelIndex &index, indexes ) {
418 if ( index.column() != 0 )
421 urls <<
itemForIndex( index ).url( Item::UrlWithMimeType );
423 urls.populateMimeData( data );
430 return index( d->rowForItem( item ), column );
433 bool ItemModel::dropMimeData(
const QMimeData * data, Qt::DropAction action,
int row,
int column,
const QModelIndex & parent)
445 return d->collection;
448 Qt::DropActions ItemModel::supportedDropActions()
const
450 return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
453 #include "moc_itemmodel.cpp"
void collectionChanged(const Akonadi::Collection &collection)
This signal is emitted whenever setCollection is called.
Collection::List collections() const
Returns the list of fetched collection.
Session * session() const
Returns the Session object used for all operations by this model.
Represents a collection of PIM items.
KJob * paste(const QMimeData *mimeData, const Collection &collection, bool copy=true, Session *session=0)
Paste/drop the given mime data into the given collection.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Job that fetches collections from the Akonadi storage.
Only fetch the base collection.
Item itemForIndex(const QModelIndex &index) const
Returns the item at the given index.
void setFetchScope(ItemFetchScope &fetchScope)
Sets the item fetch scope.
A communication session with the Akonadi storage.
The mime type of the item.
Specifies which parts of an item should be fetched from the Akonadi storage.
void setCollection(const Akonadi::Collection &collection)
Sets the collection the model should display.
Monitors an item or collection for changes.
void setFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
QModelIndex indexForItem(const Akonadi::Item &item, const int column) const
Returns the model index for the given item, with the given column.
Job that fetches items from the Akonadi storage.
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
Collection collection() const
Returns the collection being displayed in the model.
bool isValid() const
Returns whether the entity is valid.
virtual ~ItemModel()
Destroys the item model.