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 )
207 if ( colDst == collection && colSrc != collection )
214 void ItemModel::Private::itemsAdded(
const Akonadi::Item::List &list )
216 if ( list.isEmpty() )
218 mParent->beginInsertRows( QModelIndex(), items.count(), items.count() + list.count() - 1 );
219 foreach (
const Item &item, list ) {
220 ItemContainer *c =
new ItemContainer( item, items.count() );
222 itemHash[ item ] = c;
224 mParent->endInsertRows();
227 void ItemModel::Private::itemAdded(
const Akonadi::Item &item )
234 void ItemModel::Private::itemRemoved(
const Akonadi::Item &_item )
236 int row = rowForItem( _item );
240 mParent->beginRemoveRows( QModelIndex(), row, row );
241 const Item item = items.at( row )->item;
242 Q_ASSERT( item.isValid() );
243 itemHash.remove( item );
244 delete items.takeAt( row );
245 mParent->endRemoveRows();
248 ItemModel::ItemModel( QObject *parent ) :
249 QAbstractTableModel( parent ),
250 d( new Private( this ) )
259 QVariant ItemModel::data(
const QModelIndex & index,
int role )
const
261 if ( !index.isValid() )
263 if ( index.row() >= d->items.count() )
265 const Item item = d->items.at( index.row() )->item;
266 if ( !item.isValid() )
269 if ( role == Qt::DisplayRole ) {
270 switch ( index.column() ) {
272 return QString::number( item.id() );
274 return item.remoteId();
276 return item.mimeType();
287 var.setValue( item );
292 return item.mimeType();
297 int ItemModel::rowCount(
const QModelIndex & parent )
const
299 if ( !parent.isValid() )
300 return d->items.count();
304 int ItemModel::columnCount(
const QModelIndex & parent)
const
306 if ( !parent.isValid() )
311 QVariant ItemModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
313 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
318 return i18n(
"Remote Id" );
320 return i18n(
"MimeType" );
325 return QAbstractTableModel::headerData( section, orientation, role );
331 if ( d->collection == collection )
338 connect( job, SIGNAL(result(KJob*)),
this, SLOT(collectionFetchResult(KJob*)) );
342 d->monitor->setCollectionMonitored( d->collection,
false );
346 d->monitor->setCollectionMonitored( d->collection,
true );
349 qDeleteAll( d->items );
357 if ( d->collectionIsCompatible() ) {
360 connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)),
361 SLOT(itemsAdded(Akonadi::Item::List)) );
362 connect( job, SIGNAL(result(KJob*)), SLOT(listingDone(KJob*)) );
370 d->monitor->setItemFetchScope( fetchScope );
375 return d->monitor->itemFetchScope();
380 if ( !index.isValid() )
381 return Akonadi::Item();
383 if ( index.row() >= d->items.count() )
384 return Akonadi::Item();
386 Item item = d->items.at( index.row() )->item;
387 if ( item.isValid() ) {
390 return Akonadi::Item();
394 Qt::ItemFlags ItemModel::flags(
const QModelIndex &index )
const
396 Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
399 return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
401 return Qt::ItemIsDropEnabled | defaultFlags;
404 QStringList ItemModel::mimeTypes()
const
406 return QStringList() << QLatin1String(
"text/uri-list" );
414 QMimeData *ItemModel::mimeData(
const QModelIndexList &indexes )
const
416 QMimeData *data =
new QMimeData();
419 foreach (
const QModelIndex &index, indexes ) {
420 if ( index.column() != 0 )
423 urls <<
itemForIndex( index ).url( Item::UrlWithMimeType );
425 urls.populateMimeData( data );
432 return index( d->rowForItem( item ), column );
435 bool ItemModel::dropMimeData(
const QMimeData * data, Qt::DropAction action,
int row,
int column,
const QModelIndex & parent)
447 return d->collection;
450 Qt::DropActions ItemModel::supportedDropActions()
const
452 return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
455 #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.