• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

itemmodel.cpp

00001 /*
00002     Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "itemmodel.h"
00021 
00022 #include "itemfetchjob.h"
00023 #include "itemfetchscope.h"
00024 #include "monitor.h"
00025 #include "pastehelper.h"
00026 #include "session.h"
00027 
00028 #include <kmime/kmime_message.h>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kurl.h>
00033 
00034 #include <QtCore/QDebug>
00035 #include <QtCore/QMimeData>
00036 
00037 using namespace Akonadi;
00038 
00047 struct ItemContainer
00048 {
00049   ItemContainer( const Item& i, int r )
00050   {
00051     item = i;
00052     row = r;
00053   }
00054   Item item;
00055   int row;
00056 };
00057 
00061 class ItemModel::Private
00062 {
00063   public:
00064     Private( ItemModel *parent )
00065       : mParent( parent ), monitor( new Monitor() )
00066     {
00067       session = new Session( QByteArray("ItemModel-") + QByteArray::number( qrand() ), mParent );
00068 
00069       monitor->ignoreSession( session );
00070 
00071       mParent->connect( monitor, SIGNAL(itemChanged( const Akonadi::Item&, const QSet<QByteArray>& )),
00072                         mParent, SLOT(itemChanged( const Akonadi::Item&, const QSet<QByteArray>& )) );
00073       mParent->connect( monitor, SIGNAL(itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& )),
00074                         mParent, SLOT(itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& ) ) );
00075       mParent->connect( monitor, SIGNAL(itemAdded( const Akonadi::Item&, const Akonadi::Collection& )),
00076                         mParent, SLOT(itemAdded( const Akonadi::Item& )) );
00077       mParent->connect( monitor, SIGNAL(itemRemoved(Akonadi::Item)),
00078                         mParent, SLOT(itemRemoved(Akonadi::Item)) );
00079     }
00080 
00081     ~Private()
00082     {
00083       delete monitor;
00084     }
00085 
00086     void listingDone( KJob* );
00087     void itemChanged( const Akonadi::Item&, const QSet<QByteArray>& );
00088     void itemsAdded( const Akonadi::Item::List &list );
00089     void itemAdded( const Akonadi::Item &item );
00090     void itemMoved( const Akonadi::Item&, const Akonadi::Collection& src, const Akonadi::Collection& dst );
00091     void itemRemoved( const Akonadi::Item& );
00092     int rowForItem( const Akonadi::Item& );
00093 
00094     ItemModel *mParent;
00095 
00096     QList<ItemContainer*> items;
00097     QHash<Item, ItemContainer*> itemHash;
00098 
00099     Collection collection;
00100     Monitor *monitor;
00101     Session *session;
00102 };
00103 
00104 void ItemModel::Private::listingDone( KJob * job )
00105 {
00106   ItemFetchJob *fetch = static_cast<ItemFetchJob*>( job );
00107   Q_UNUSED( fetch );
00108   if ( job->error() ) {
00109     // TODO
00110     kWarning( 5250 ) << "Item query failed:" << job->errorString();
00111   }
00112 }
00113 
00114 int ItemModel::Private::rowForItem( const Akonadi::Item& item )
00115 {
00116   ItemContainer *container = itemHash.value( item );
00117   if ( !container )
00118     return -1;
00119 
00120   /* Try to find the item directly;
00121 
00122      If items have been removed, this first try won't succeed because
00123      the ItemContainer rows have not been updated (costs too much).
00124   */
00125   if ( container->row < items.count()
00126        && items.at( container->row ) == container )
00127     return container->row;
00128   else { // Slow solution if the fist one has not succeeded
00129     int row = -1;
00130     for ( int i = 0; i < items.size(); ++i ) {
00131       if ( items.at( i )->item == item ) {
00132         row = i;
00133         break;
00134       }
00135     }
00136     return row;
00137   }
00138 
00139 }
00140 
00141 void ItemModel::Private::itemChanged( const Akonadi::Item &item, const QSet<QByteArray>& )
00142 {
00143   int row = rowForItem( item );
00144   if ( row < 0 )
00145     return;
00146 
00147   items[ row ]->item = item;
00148   itemHash.remove( item );
00149   itemHash[ item ] = items[ row ];
00150 
00151   QModelIndex start = mParent->index( row, 0, QModelIndex() );
00152   QModelIndex end = mParent->index( row, mParent->columnCount( QModelIndex() ) - 1 , QModelIndex() );
00153 
00154   mParent->dataChanged( start, end );
00155 }
00156 
00157 void ItemModel::Private::itemMoved( const Akonadi::Item &item, const Akonadi::Collection& colSrc, const Akonadi::Collection& colDst )
00158 {
00159   if ( colSrc == collection && colDst != collection ) // item leaving this model
00160   {
00161     itemRemoved( item );
00162     return;
00163   }
00164 
00165 
00166   if ( colDst == collection && colSrc != collection )
00167   {
00168     itemAdded( item );
00169     return;
00170   }
00171 }
00172 
00173 void ItemModel::Private::itemsAdded( const Akonadi::Item::List &list )
00174 {
00175   if ( list.isEmpty() )
00176     return;
00177   mParent->beginInsertRows( QModelIndex(), items.count(), items.count() + list.count() - 1 );
00178   foreach( const Item &item, list ) {
00179     ItemContainer *c = new ItemContainer( item, items.count() );
00180     items.append( c );
00181     itemHash[ item ] = c;
00182   }
00183   mParent->endInsertRows();
00184 }
00185 
00186 void ItemModel::Private::itemAdded( const Akonadi::Item &item )
00187 {
00188   Item::List l;
00189   l << item;
00190   itemsAdded( l );
00191 }
00192 
00193 void ItemModel::Private::itemRemoved( const Akonadi::Item &_item )
00194 {
00195   int row = rowForItem( _item );
00196   if ( row < 0 )
00197     return;
00198 
00199   mParent->beginRemoveRows( QModelIndex(), row, row );
00200   const Item item = items.at( row )->item;
00201   Q_ASSERT( item.isValid() );
00202   itemHash.remove( item );
00203   delete items.takeAt( row );
00204   mParent->endRemoveRows();
00205 }
00206 
00207 ItemModel::ItemModel( QObject *parent ) :
00208     QAbstractTableModel( parent ),
00209     d( new Private( this ) )
00210 {
00211   setSupportedDragActions( Qt::MoveAction | Qt::CopyAction );
00212 }
00213 
00214 ItemModel::~ItemModel()
00215 {
00216   delete d;
00217 }
00218 
00219 QVariant ItemModel::data( const QModelIndex & index, int role ) const
00220 {
00221   if ( !index.isValid() )
00222     return QVariant();
00223   if ( index.row() >= d->items.count() )
00224     return QVariant();
00225   const Item item = d->items.at( index.row() )->item;
00226   if ( !item.isValid() )
00227     return QVariant();
00228 
00229   if ( role == Qt::DisplayRole ) {
00230     switch ( index.column() ) {
00231       case Id:
00232         return QString::number( item.id() );
00233       case RemoteId:
00234         return item.remoteId();
00235       case MimeType:
00236         return item.mimeType();
00237       default:
00238         return QVariant();
00239     }
00240   }
00241 
00242   if ( role == IdRole )
00243     return item.id();
00244 
00245   if ( role == ItemRole ) {
00246     QVariant var;
00247     var.setValue( item );
00248     return var;
00249   }
00250 
00251   if ( role == MimeTypeRole )
00252     return item.mimeType();
00253 
00254   return QVariant();
00255 }
00256 
00257 int ItemModel::rowCount( const QModelIndex & parent ) const
00258 {
00259   if ( !parent.isValid() )
00260     return d->items.count();
00261   return 0;
00262 }
00263 
00264 int ItemModel::columnCount(const QModelIndex & parent) const
00265 {
00266   if ( !parent.isValid() )
00267     return 3; // keep in sync with Column enum
00268   return 0;
00269 }
00270 
00271 QVariant ItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
00272 {
00273   if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
00274     switch ( section ) {
00275       case Id:
00276         return i18n( "Id" );
00277       case RemoteId:
00278         return i18n( "Remote Id" );
00279       case MimeType:
00280         return i18n( "MimeType" );
00281       default:
00282         return QString();
00283     }
00284   }
00285   return QAbstractTableModel::headerData( section, orientation, role );
00286 }
00287 
00288 void ItemModel::setCollection( const Collection &collection )
00289 {
00290   kDebug( 5250 );
00291   if ( d->collection == collection )
00292     return;
00293 
00294   d->monitor->setCollectionMonitored( d->collection, false );
00295 
00296   d->collection = collection;
00297 
00298   d->monitor->setCollectionMonitored( d->collection, true );
00299 
00300   // the query changed, thus everything we have already is invalid
00301   qDeleteAll( d->items );
00302   d->items.clear();
00303   reset();
00304 
00305   // stop all running jobs
00306   d->session->clear();
00307 
00308   // start listing job
00309   ItemFetchJob* job = new ItemFetchJob( collection, session() );
00310   job->setFetchScope( d->monitor->itemFetchScope() );
00311   connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)), SLOT(itemsAdded(Akonadi::Item::List)) );
00312   connect( job, SIGNAL(result(KJob*)), SLOT(listingDone(KJob*)) );
00313 
00314   emit collectionChanged( collection );
00315 }
00316 
00317 void ItemModel::setFetchScope( const ItemFetchScope &fetchScope )
00318 {
00319   d->monitor->setItemFetchScope( fetchScope );
00320 }
00321 
00322 ItemFetchScope &ItemModel::fetchScope()
00323 {
00324   return d->monitor->itemFetchScope();
00325 }
00326 
00327 Item ItemModel::itemForIndex( const QModelIndex & index ) const
00328 {
00329   if ( !index.isValid() )
00330     return Akonadi::Item();
00331 
00332   if ( index.row() >= d->items.count() )
00333     return Akonadi::Item();
00334 
00335   Item item = d->items.at( index.row() )->item;
00336   Q_ASSERT( item.isValid() );
00337 
00338   return item;
00339 }
00340 
00341 Qt::ItemFlags ItemModel::flags( const QModelIndex &index ) const
00342 {
00343   Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
00344 
00345   if (index.isValid())
00346     return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
00347   else
00348     return Qt::ItemIsDropEnabled | defaultFlags;
00349 }
00350 
00351 QStringList ItemModel::mimeTypes() const
00352 {
00353   return QStringList();
00354 }
00355 
00356 Session * ItemModel::session() const
00357 {
00358   return d->session;
00359 }
00360 
00361 QMimeData *ItemModel::mimeData( const QModelIndexList &indexes ) const
00362 {
00363   QMimeData *data = new QMimeData();
00364   // Add item uri to the mimedata for dropping in external applications
00365   KUrl::List urls;
00366   foreach ( const QModelIndex &index, indexes ) {
00367     if ( index.column() != 0 )
00368       continue;
00369 
00370     urls << itemForIndex( index ).url( Item::UrlWithMimeType );
00371   }
00372   urls.populateMimeData( data );
00373 
00374   return data;
00375 }
00376 
00377 QModelIndex ItemModel::indexForItem( const Akonadi::Item &item, const int column ) const
00378 {
00379   return index( d->rowForItem( item ), column );
00380 }
00381 
00382 bool ItemModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent)
00383 {
00384   Q_UNUSED( row );
00385   Q_UNUSED( column );
00386   Q_UNUSED( parent );
00387   KJob* job = PasteHelper::paste( data, d->collection, action != Qt::MoveAction );
00388   // TODO: error handling
00389   return job;
00390 }
00391 
00392 Collection ItemModel::collection() const
00393 {
00394   return d->collection;
00395 }
00396 
00397 #include "itemmodel.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal