• Skip to content
  • Skip to link menu
KDE 4.2 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 <QCoreApplication>
00035 #include <QtCore/QDebug>
00036 #include <QtCore/QMimeData>
00037 
00038 using namespace Akonadi;
00039 
00048 struct ItemContainer
00049 {
00050   ItemContainer( const Item& i, int r )
00051   {
00052     item = i;
00053     row = r;
00054   }
00055   Item item;
00056   int row;
00057 };
00058 
00062 class ItemModel::Private
00063 {
00064   public:
00065     Private( ItemModel *parent )
00066       : mParent( parent ), monitor( new Monitor() )
00067     {
00068       session = new Session( QCoreApplication::instance()->applicationName().toUtf8()
00069           + QByteArray("-ItemModel-") + QByteArray::number( qrand() ), mParent );
00070 
00071       monitor->ignoreSession( session );
00072 
00073       mParent->connect( monitor, SIGNAL(itemChanged( const Akonadi::Item&, const QSet<QByteArray>& )),
00074                         mParent, SLOT(itemChanged( const Akonadi::Item&, const QSet<QByteArray>& )) );
00075       mParent->connect( monitor, SIGNAL(itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& )),
00076                         mParent, SLOT(itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& ) ) );
00077       mParent->connect( monitor, SIGNAL(itemAdded( const Akonadi::Item&, const Akonadi::Collection& )),
00078                         mParent, SLOT(itemAdded( const Akonadi::Item& )) );
00079       mParent->connect( monitor, SIGNAL(itemRemoved(Akonadi::Item)),
00080                         mParent, SLOT(itemRemoved(Akonadi::Item)) );
00081       mParent->connect( monitor, SIGNAL(itemLinked(const Akonadi::Item&, const Akonadi::Collection&)),
00082                         mParent, SLOT(itemAdded(const Akonadi::Item&)) );
00083       mParent->connect( monitor, SIGNAL(itemUnlinked(const Akonadi::Item&, const Akonadi::Collection&)),
00084                         mParent, SLOT(itemRemoved(const Akonadi::Item&)) );
00085     }
00086 
00087     ~Private()
00088     {
00089       delete monitor;
00090     }
00091 
00092     void listingDone( KJob* );
00093     void itemChanged( const Akonadi::Item&, const QSet<QByteArray>& );
00094     void itemsAdded( const Akonadi::Item::List &list );
00095     void itemAdded( const Akonadi::Item &item );
00096     void itemMoved( const Akonadi::Item&, const Akonadi::Collection& src, const Akonadi::Collection& dst );
00097     void itemRemoved( const Akonadi::Item& );
00098     int rowForItem( const Akonadi::Item& );
00099 
00100     ItemModel *mParent;
00101 
00102     QList<ItemContainer*> items;
00103     QHash<Item, ItemContainer*> itemHash;
00104 
00105     Collection collection;
00106     Monitor *monitor;
00107     Session *session;
00108 };
00109 
00110 void ItemModel::Private::listingDone( KJob * job )
00111 {
00112   ItemFetchJob *fetch = static_cast<ItemFetchJob*>( job );
00113   Q_UNUSED( fetch );
00114   if ( job->error() ) {
00115     // TODO
00116     kWarning( 5250 ) << "Item query failed:" << job->errorString();
00117   }
00118 }
00119 
00120 int ItemModel::Private::rowForItem( const Akonadi::Item& item )
00121 {
00122   ItemContainer *container = itemHash.value( item );
00123   if ( !container )
00124     return -1;
00125 
00126   /* Try to find the item directly;
00127 
00128      If items have been removed, this first try won't succeed because
00129      the ItemContainer rows have not been updated (costs too much).
00130   */
00131   if ( container->row < items.count()
00132        && items.at( container->row ) == container )
00133     return container->row;
00134   else { // Slow solution if the fist one has not succeeded
00135     int row = -1;
00136     for ( int i = 0; i < items.size(); ++i ) {
00137       if ( items.at( i )->item == item ) {
00138         row = i;
00139         break;
00140       }
00141     }
00142     return row;
00143   }
00144 
00145 }
00146 
00147 void ItemModel::Private::itemChanged( const Akonadi::Item &item, const QSet<QByteArray>& )
00148 {
00149   int row = rowForItem( item );
00150   if ( row < 0 )
00151     return;
00152 
00153   items[ row ]->item = item;
00154   itemHash.remove( item );
00155   itemHash[ item ] = items[ row ];
00156 
00157   QModelIndex start = mParent->index( row, 0, QModelIndex() );
00158   QModelIndex end = mParent->index( row, mParent->columnCount( QModelIndex() ) - 1 , QModelIndex() );
00159 
00160   mParent->dataChanged( start, end );
00161 }
00162 
00163 void ItemModel::Private::itemMoved( const Akonadi::Item &item, const Akonadi::Collection& colSrc, const Akonadi::Collection& colDst )
00164 {
00165   if ( colSrc == collection && colDst != collection ) // item leaving this model
00166   {
00167     itemRemoved( item );
00168     return;
00169   }
00170 
00171 
00172   if ( colDst == collection && colSrc != collection )
00173   {
00174     itemAdded( item );
00175     return;
00176   }
00177 }
00178 
00179 void ItemModel::Private::itemsAdded( const Akonadi::Item::List &list )
00180 {
00181   if ( list.isEmpty() )
00182     return;
00183   mParent->beginInsertRows( QModelIndex(), items.count(), items.count() + list.count() - 1 );
00184   foreach( const Item &item, list ) {
00185     ItemContainer *c = new ItemContainer( item, items.count() );
00186     items.append( c );
00187     itemHash[ item ] = c;
00188   }
00189   mParent->endInsertRows();
00190 }
00191 
00192 void ItemModel::Private::itemAdded( const Akonadi::Item &item )
00193 {
00194   Item::List l;
00195   l << item;
00196   itemsAdded( l );
00197 }
00198 
00199 void ItemModel::Private::itemRemoved( const Akonadi::Item &_item )
00200 {
00201   int row = rowForItem( _item );
00202   if ( row < 0 )
00203     return;
00204 
00205   mParent->beginRemoveRows( QModelIndex(), row, row );
00206   const Item item = items.at( row )->item;
00207   Q_ASSERT( item.isValid() );
00208   itemHash.remove( item );
00209   delete items.takeAt( row );
00210   mParent->endRemoveRows();
00211 }
00212 
00213 ItemModel::ItemModel( QObject *parent ) :
00214     QAbstractTableModel( parent ),
00215     d( new Private( this ) )
00216 {
00217   setSupportedDragActions( Qt::MoveAction | Qt::CopyAction );
00218 }
00219 
00220 ItemModel::~ItemModel()
00221 {
00222   delete d;
00223 }
00224 
00225 QVariant ItemModel::data( const QModelIndex & index, int role ) const
00226 {
00227   if ( !index.isValid() )
00228     return QVariant();
00229   if ( index.row() >= d->items.count() )
00230     return QVariant();
00231   const Item item = d->items.at( index.row() )->item;
00232   if ( !item.isValid() )
00233     return QVariant();
00234 
00235   if ( role == Qt::DisplayRole ) {
00236     switch ( index.column() ) {
00237       case Id:
00238         return QString::number( item.id() );
00239       case RemoteId:
00240         return item.remoteId();
00241       case MimeType:
00242         return item.mimeType();
00243       default:
00244         return QVariant();
00245     }
00246   }
00247 
00248   if ( role == IdRole )
00249     return item.id();
00250 
00251   if ( role == ItemRole ) {
00252     QVariant var;
00253     var.setValue( item );
00254     return var;
00255   }
00256 
00257   if ( role == MimeTypeRole )
00258     return item.mimeType();
00259 
00260   return QVariant();
00261 }
00262 
00263 int ItemModel::rowCount( const QModelIndex & parent ) const
00264 {
00265   if ( !parent.isValid() )
00266     return d->items.count();
00267   return 0;
00268 }
00269 
00270 int ItemModel::columnCount(const QModelIndex & parent) const
00271 {
00272   if ( !parent.isValid() )
00273     return 3; // keep in sync with Column enum
00274   return 0;
00275 }
00276 
00277 QVariant ItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
00278 {
00279   if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
00280     switch ( section ) {
00281       case Id:
00282         return i18n( "Id" );
00283       case RemoteId:
00284         return i18n( "Remote Id" );
00285       case MimeType:
00286         return i18n( "MimeType" );
00287       default:
00288         return QString();
00289     }
00290   }
00291   return QAbstractTableModel::headerData( section, orientation, role );
00292 }
00293 
00294 void ItemModel::setCollection( const Collection &collection )
00295 {
00296   kDebug( 5250 );
00297   if ( d->collection == collection )
00298     return;
00299 
00300   d->monitor->setCollectionMonitored( d->collection, false );
00301 
00302   d->collection = collection;
00303 
00304   d->monitor->setCollectionMonitored( d->collection, true );
00305 
00306   // the query changed, thus everything we have already is invalid
00307   qDeleteAll( d->items );
00308   d->items.clear();
00309   reset();
00310 
00311   // stop all running jobs
00312   d->session->clear();
00313 
00314   // start listing job
00315   ItemFetchJob* job = new ItemFetchJob( collection, session() );
00316   job->setFetchScope( d->monitor->itemFetchScope() );
00317   connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)), SLOT(itemsAdded(Akonadi::Item::List)) );
00318   connect( job, SIGNAL(result(KJob*)), SLOT(listingDone(KJob*)) );
00319 
00320   emit collectionChanged( collection );
00321 }
00322 
00323 void ItemModel::setFetchScope( const ItemFetchScope &fetchScope )
00324 {
00325   d->monitor->setItemFetchScope( fetchScope );
00326 }
00327 
00328 ItemFetchScope &ItemModel::fetchScope()
00329 {
00330   return d->monitor->itemFetchScope();
00331 }
00332 
00333 Item ItemModel::itemForIndex( const QModelIndex & index ) const
00334 {
00335   if ( !index.isValid() )
00336     return Akonadi::Item();
00337 
00338   if ( index.row() >= d->items.count() )
00339     return Akonadi::Item();
00340 
00341   Item item = d->items.at( index.row() )->item;
00342   Q_ASSERT( item.isValid() );
00343 
00344   return item;
00345 }
00346 
00347 Qt::ItemFlags ItemModel::flags( const QModelIndex &index ) const
00348 {
00349   Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
00350 
00351   if (index.isValid())
00352     return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
00353   else
00354     return Qt::ItemIsDropEnabled | defaultFlags;
00355 }
00356 
00357 QStringList ItemModel::mimeTypes() const
00358 {
00359   return QStringList();
00360 }
00361 
00362 Session * ItemModel::session() const
00363 {
00364   return d->session;
00365 }
00366 
00367 QMimeData *ItemModel::mimeData( const QModelIndexList &indexes ) const
00368 {
00369   QMimeData *data = new QMimeData();
00370   // Add item uri to the mimedata for dropping in external applications
00371   KUrl::List urls;
00372   foreach ( const QModelIndex &index, indexes ) {
00373     if ( index.column() != 0 )
00374       continue;
00375 
00376     urls << itemForIndex( index ).url( Item::UrlWithMimeType );
00377   }
00378   urls.populateMimeData( data );
00379 
00380   return data;
00381 }
00382 
00383 QModelIndex ItemModel::indexForItem( const Akonadi::Item &item, const int column ) const
00384 {
00385   return index( d->rowForItem( item ), column );
00386 }
00387 
00388 bool ItemModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent)
00389 {
00390   Q_UNUSED( row );
00391   Q_UNUSED( column );
00392   Q_UNUSED( parent );
00393   KJob* job = PasteHelper::paste( data, d->collection, action != Qt::MoveAction );
00394   // TODO: error handling
00395   return job;
00396 }
00397 
00398 Collection ItemModel::collection() const
00399 {
00400   return d->collection;
00401 }
00402 
00403 #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
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.6
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