20 #include "itemmodel.h"
22 #include "itemfetchjob.h"
23 #include "collectionfetchjob.h"
24 #include "itemfetchscope.h"
26 #include "pastehelper_p.h"
29 #include <kmime/kmime_message.h>
32 #include <klocalizedstring.h>
35 #include <QCoreApplication>
36 #include <QtCore/QDebug>
37 #include <QtCore/QMimeData>
39 using namespace Akonadi;
51 ItemContainer(
const Item& i,
int r )
62 class ItemModel::Private
66 : mParent( parent ), monitor( new
Monitor() )
68 session =
new Session( QCoreApplication::instance()->applicationName().toUtf8()
69 + QByteArray(
"-ItemModel-" ) + QByteArray::number( qrand() ), mParent );
71 monitor->ignoreSession(
session );
73 mParent->connect( monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
74 mParent, SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
78 mParent, SLOT(itemAdded(Akonadi::Item)) );
79 mParent->connect( monitor, SIGNAL(itemRemoved(Akonadi::Item)),
80 mParent, SLOT(itemRemoved(Akonadi::Item)) );
82 mParent, SLOT(itemAdded(Akonadi::Item)) );
84 mParent, SLOT(itemRemoved(Akonadi::Item)) );
92 void listingDone( KJob* );
93 void collectionFetchResult( KJob* );
94 void itemChanged(
const Akonadi::Item&,
const QSet<QByteArray>& );
95 void itemsAdded(
const Akonadi::Item::List &list );
96 void itemAdded(
const Akonadi::Item &item );
98 void itemRemoved(
const Akonadi::Item& );
99 int rowForItem(
const Akonadi::Item& );
100 bool collectionIsCompatible()
const;
104 QList<ItemContainer*> items;
105 QHash<Item, ItemContainer*> itemHash;
112 bool ItemModel::Private::collectionIsCompatible()
const
115 if ( mParent->mimeTypes() == QStringList( QLatin1String(
"text/uri-list" ) ) )
119 Q_FOREACH(
const QString &type, mParent->mimeTypes() ) {
120 if ( collection.contentMimeTypes().contains( type ) ) {
127 void ItemModel::Private::listingDone( KJob * job )
131 if ( job->error() ) {
133 kWarning() <<
"Item query failed:" << job->errorString();
137 void ItemModel::Private::collectionFetchResult( KJob * job )
147 if ( !c.contentMimeTypes().isEmpty() ) {
148 mParent->setCollection(c);
150 kWarning() <<
"Failed to retrieve the contents mime type of the collection: " << c;
155 int ItemModel::Private::rowForItem(
const Akonadi::Item& item )
157 ItemContainer *container = itemHash.value( item );
166 if ( container->row < items.count()
167 && items.at( container->row ) == container )
168 return container->row;
171 const int numberOfItems( items.size() );
172 for (
int i = 0; i < numberOfItems; ++i ) {
173 if ( items.at( i )->item == item ) {
183 void ItemModel::Private::itemChanged(
const Akonadi::Item &item,
const QSet<QByteArray>& )
185 int row = rowForItem( item );
189 items[ row ]->item = item;
190 itemHash.remove( item );
191 itemHash[ item ] = items[ row ];
193 QModelIndex start = mParent->index( row, 0, QModelIndex() );
194 QModelIndex end = mParent->index( row, mParent->columnCount( QModelIndex() ) - 1 , QModelIndex() );
196 mParent->dataChanged( start, end );
201 if ( colSrc == collection && colDst != collection )
208 if ( colDst == collection && colSrc != collection )
215 void ItemModel::Private::itemsAdded(
const Akonadi::Item::List &list )
217 if ( list.isEmpty() )
219 mParent->beginInsertRows( QModelIndex(), items.count(), items.count() + list.count() - 1 );
220 foreach (
const Item &item, list ) {
221 ItemContainer *c =
new ItemContainer( item, items.count() );
223 itemHash[ item ] = c;
225 mParent->endInsertRows();
228 void ItemModel::Private::itemAdded(
const Akonadi::Item &item )
235 void ItemModel::Private::itemRemoved(
const Akonadi::Item &_item )
237 int row = rowForItem( _item );
241 mParent->beginRemoveRows( QModelIndex(), row, row );
242 const Item item = items.at( row )->item;
243 Q_ASSERT( item.isValid() );
244 itemHash.remove( item );
245 delete items.takeAt( row );
246 mParent->endRemoveRows();
249 ItemModel::ItemModel( QObject *parent ) :
250 QAbstractTableModel( parent ),
251 d( new Private( this ) )
260 QVariant ItemModel::data(
const QModelIndex & index,
int role )
const
262 if ( !index.isValid() )
264 if ( index.row() >= d->items.count() )
266 const Item item = d->items.at( index.row() )->item;
267 if ( !item.isValid() )
270 if ( role == Qt::DisplayRole ) {
271 switch ( index.column() ) {
273 return QString::number( item.id() );
275 return item.remoteId();
277 return item.mimeType();
288 var.setValue( item );
293 return item.mimeType();
298 int ItemModel::rowCount(
const QModelIndex & parent )
const
300 if ( !parent.isValid() )
301 return d->items.count();
305 int ItemModel::columnCount(
const QModelIndex & parent)
const
307 if ( !parent.isValid() )
312 QVariant ItemModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
314 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
319 return i18n(
"Remote Id" );
321 return i18n(
"MimeType" );
326 return QAbstractTableModel::headerData( section, orientation, role );
332 if ( d->collection == collection )
339 connect( job, SIGNAL(result(KJob*)),
this, SLOT(collectionFetchResult(KJob*)) );
343 d->monitor->setCollectionMonitored( d->collection,
false );
347 d->monitor->setCollectionMonitored( d->collection,
true );
350 qDeleteAll( d->items );
358 if ( d->collectionIsCompatible() ) {
361 connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)),
362 SLOT(itemsAdded(Akonadi::Item::List)) );
363 connect( job, SIGNAL(result(KJob*)), SLOT(listingDone(KJob*)) );
371 d->monitor->setItemFetchScope( fetchScope );
376 return d->monitor->itemFetchScope();
381 if ( !index.isValid() )
382 return Akonadi::Item();
384 if ( index.row() >= d->items.count() )
385 return Akonadi::Item();
387 Item item = d->items.at( index.row() )->item;
388 if ( item.isValid() ) {
391 return Akonadi::Item();
395 Qt::ItemFlags ItemModel::flags(
const QModelIndex &index )
const
397 Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
400 return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
402 return Qt::ItemIsDropEnabled | defaultFlags;
405 QStringList ItemModel::mimeTypes()
const
407 return QStringList() << QLatin1String(
"text/uri-list" );
415 QMimeData *ItemModel::mimeData(
const QModelIndexList &indexes )
const
417 QMimeData *data =
new QMimeData();
420 foreach (
const QModelIndex &index, indexes ) {
421 if ( index.column() != 0 )
424 urls <<
itemForIndex( index ).url( Item::UrlWithMimeType );
426 urls.populateMimeData( data );
433 return index( d->rowForItem( item ), column );
436 bool ItemModel::dropMimeData(
const QMimeData * data, Qt::DropAction action,
int row,
int column,
const QModelIndex & parent)
448 return d->collection;
451 Qt::DropActions ItemModel::supportedDropActions()
const
453 return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
457 #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.
The item's mime type.
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.