diff --git a/akonadi/Makefile.am b/akonadi/Makefile.am index 6fdebd283..86d2a7ca0 100644 --- a/akonadi/Makefile.am +++ b/akonadi/Makefile.am @@ -1,19 +1,21 @@ SUBDIRS = . tests INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/libakonadi $(all_includes) noinst_LTLIBRARIES = libakonadi.la libakonadi_la_SOURCES = datarequest.cpp job.cpp query.cpp collection.cpp \ collectionlistjob.cpp collectionmodel.cpp collectionmonitorjob.cpp \ - collectionfetchjob.cpp collectionview.cpp + collectionfetchjob.cpp collectionview.cpp messagecollection.cpp \ + messagecollectionmodel.cpp libakonadi_la_LDFLAGS = $(all_libraries) -no-undefined libakonadi_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) akonadiincludedir = $(includedir)/libakonadi akonadiinclude_HEADERS = datarequest.h job.h query.h collection.h \ collectionlistjob.h collectionmodel.h collectionmonitorjob.h \ - collectionfetchjob.h collectionview.h + collectionfetchjob.h collectionview.h messagecollection.h \ + messagecollectionmodel.h METASOURCES = AUTO include $(top_srcdir)/admin/Doxyfile.am diff --git a/akonadi/collection.cpp b/akonadi/collection.cpp index 96e8e259a..b08d9df08 100644 --- a/akonadi/collection.cpp +++ b/akonadi/collection.cpp @@ -1,114 +1,115 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collection.h" #include #include using namespace PIM; -class Collection::CollectionPrivate +class Collection::Private { public: DataReference ref; DataReference parent; QString name; Type type; QStringList contentTypes; QString query; }; PIM::Collection::Collection( const DataReference &ref ) : - d( new Collection::CollectionPrivate() ) + d( new Collection::Private() ) { d->ref = ref; d->type = Unknown; } +PIM::Collection::Collection( const Collection &other ) : + d( new Collection::Private() ) +{ + d->name = other.name(); + d->ref = other.reference(); + d->parent = other.parent(); + d->type = other.type(); + d->contentTypes = other.contentTypes(); + d->query = other.query(); +} + PIM::Collection::~ Collection( ) { delete d; d = 0; } DataReference PIM::Collection::reference( ) const { return d->ref; } QString PIM::Collection::name( ) const { return d->name; } void PIM::Collection::setName( const QString & name ) { d->name = name; } Collection::Type PIM::Collection::type() const { return d->type; } void PIM::Collection::setType( Type type ) { d->type = type; } QStringList PIM::Collection::contentTypes( ) const { return d->contentTypes; } void PIM::Collection::setContentTypes( const QStringList & types ) { d->contentTypes = types; } DataReference PIM::Collection::parent( ) const { return d->parent; } void PIM::Collection::setParent( const DataReference & parent ) { d->parent = parent; } QString PIM::Collection::query( ) const { return d->query; } void PIM::Collection::setQuery( const QString & query ) { d->query = query; } - -void PIM::Collection::copy( Collection * col ) -{ - d->name = col->name(); - d->ref = col->reference(); - d->parent = col->parent(); - d->type = col->type(); - d->contentTypes = col->contentTypes(); - d->query = col->query(); -} diff --git a/akonadi/collection.h b/akonadi/collection.h index 19da570b7..754117da8 100644 --- a/akonadi/collection.h +++ b/akonadi/collection.h @@ -1,134 +1,132 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PIM_COLLECTION_H #define PIM_COLLECTION_H #include namespace PIM { /** - This class presents a collection of PIM objects, such as a folder on a mail or - groupware server. + This class represents a collection of PIM objects, such as a folder on a mail- or + groupware-server. Collections are hierarchical, i.e. they may have a parent collection. */ class Collection { public: /** Collection types. */ enum Type { Folder, /**< 'Real' folder on eg. an IMAP server. */ Virtual, /**< Virtual collection (aka search folder). */ Resource, /**< Resource or account. */ Category, /**< Category. */ Unknown /**< Unknown collection type. */ }; /** Create a new collection. @param ref The data reference of this collection. */ Collection( const DataReference &ref ); + /** + Copy constructor. + + @param other The collection to copy. + */ + Collection( const Collection &other ); + /** Destroys this collection. */ virtual ~Collection(); /** Returns the DataReference of this object. */ DataReference reference() const; /** Returns the name of this collection. */ QString name() const; /** Sets the name of this collection. */ void setName( const QString &name ); /** Returns the type of this collection (e.g. virtual folder, folder on an IMAP server, etc.). */ Type type() const; /** Sets the type of this collection. */ void setType( Type type ); /** Returns a list of possible content mimetypes, e.g. message/rfc822, x-akonadi/collection for a mail folder that supports sub-folders. */ QStringList contentTypes() const; /** Sets the list of possible content mimetypes. */ void setContentTypes( const QStringList &types ); /** Returns a reference to the parent collection, might be an empty reference if this collection is a top-level collection. */ DataReference parent() const; /** Sets the parent collections. */ void setParent( const DataReference &parent ); /** Returns a query for the Akonadi backend to list the folder content. */ QString query() const; /** Set the content query. */ void setQuery( const QString &query ); - /** - Copy the content of the given collection into this one. - Used in PIM::CollectionModel to handle updates without changing pointers. - - Note: Subclasses should overwrite this method, copy their data and call - the implementation of the super class. - */ - virtual void copy( Collection *col ); - private: - class CollectionPrivate; - CollectionPrivate *d; + class Private; + Private *d; }; } #endif diff --git a/akonadi/collectionfetchjob.cpp b/akonadi/collectionfetchjob.cpp index ad99fa84f..772cf3838 100644 --- a/akonadi/collectionfetchjob.cpp +++ b/akonadi/collectionfetchjob.cpp @@ -1,71 +1,75 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collection.h" #include "collectionfetchjob.h" +#include "messagecollection.h" #include using namespace PIM; // ### just for testing, remove as soon as we have a real backend #define DUMMY_FETCH_JOB #ifdef DUMMY_FETCH_JOB #include static Collection* col = 0; QHash global_collection_map; #endif PIM::CollectionFetchJob::CollectionFetchJob( const DataReference & ref ) { #ifdef DUMMY_FETCH_JOB if ( global_collection_map.contains( ref ) ) { - col = new Collection( ref ); - col->copy( global_collection_map.value( ref ) ); + Collection *c = global_collection_map.value( ref ); + if ( dynamic_cast( c ) ) + col = new MessageCollection( *static_cast( c ) ); + else + col = new Collection( *c ); } else col = 0; #else Q_UNUSED( ref ); #endif } PIM::CollectionFetchJob::~CollectionFetchJob() { } Collection * PIM::CollectionFetchJob::collection() const { #ifdef DUMMY_FETCH_JOB return col; #else return 0; #endif } void PIM::CollectionFetchJob::emitDone() { emit done( this ); } void PIM::CollectionFetchJob::doStart() { QTimer::singleShot( 0, this, SLOT( emitDone() ) ); } #include "collectionfetchjob.moc" diff --git a/akonadi/collectionmodel.cpp b/akonadi/collectionmodel.cpp index 4fea44e07..73a7d2bdd 100644 --- a/akonadi/collectionmodel.cpp +++ b/akonadi/collectionmodel.cpp @@ -1,295 +1,285 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collection.h" #include "collectionfetchjob.h" #include "collectionmodel.h" #include "collectionmonitorjob.h" #include #include #include #include #include #include #include using namespace PIM; class CollectionModel::Private { public: QHash collections; QHash childCollections; CollectionMonitorJob *monitorJob; CollectionFetchJob *fetchJob; QQueue updateQueue; }; PIM::CollectionModel::CollectionModel( const QHash< DataReference, Collection * > & collections, QObject * parent ) : QAbstractItemModel( parent ), d( new Private() ) { d->collections = collections; d->fetchJob = 0; // build child collection hash foreach ( const Collection *col, d->collections ) d->childCollections[ col->parent() ].append( col->reference() ); // monitor collection changes d->monitorJob = new CollectionMonitorJob(); connect( d->monitorJob, SIGNAL( collectionChanged( const DataReference& ) ), SLOT( collectionChanged( const DataReference& ) ) ); connect( d->monitorJob, SIGNAL( collectionRemoved( const DataReference& ) ), SLOT( collectionRemoved( const DataReference& ) ) ); d->monitorJob->start(); // ### Hack to get the kmail resource folder icons KGlobal::instance()->iconLoader()->addAppDir( "kmail" ); } PIM::CollectionModel::~CollectionModel() { d->childCollections.clear(); qDeleteAll( d->collections ); d->collections.clear(); delete d->monitorJob; d->monitorJob = 0; delete d->fetchJob; d->fetchJob = 0; delete d; d = 0; } int PIM::CollectionModel::columnCount( const QModelIndex & parent ) const { Q_UNUSED( parent ); return 1; } QVariant PIM::CollectionModel::data( const QModelIndex & index, int role ) const { Collection *col = static_cast( index.internalPointer() ); - if ( role == Qt::DisplayRole ) { + if ( index.column() == 0 && role == Qt::DisplayRole ) { return col->name(); } - if ( role == Qt::DecorationRole ) { + if ( index.column() == 0 && role == Qt::DecorationRole ) { if ( col->type() == Collection::Resource ) return SmallIcon( "server" ); QStringList content = col->contentTypes(); if ( content.size() == 1 ) { if ( content.first() == "text/x-vcard" ) return SmallIcon( "kmgroupware_folder_contacts" ); // TODO: add all other content types and/or fix their mimetypes if ( content.first() == "akonadi/event" ) return SmallIcon( "kmgroupware_folder_calendar" ); if ( content.first() == "akonadi/task" ) return SmallIcon( "kmgroupware_folder_tasks" ); - } + } else if ( content.isEmpty() ) + return SmallIcon( "folder_grey" ); return SmallIcon( "folder" ); } return QVariant(); } QModelIndex PIM::CollectionModel::index( int row, int column, const QModelIndex & parent ) const { DataReference::List list; if ( !parent.isValid() ) list = d->childCollections.value( DataReference() ); else list = d->childCollections.value( static_cast( parent.internalPointer() )->reference() ); if ( row < 0 || row >= list.size() ) return QModelIndex(); if ( !d->collections.contains( list[row] ) ) return QModelIndex(); return createIndex( row, column, d->collections.value( list[row] ) ); } QModelIndex PIM::CollectionModel::parent( const QModelIndex & index ) const { if ( !index.isValid() ) return QModelIndex(); Collection *col = static_cast( index.internalPointer() ); DataReference parentRef = col->parent(); Collection *parentCol = d->collections.value( parentRef ); if ( !parentCol ) return QModelIndex(); DataReference::List list; list = d->childCollections.value( parentCol->parent() ); int parentRow = list.indexOf( parentRef ); if ( parentRow < 0 ) return QModelIndex(); return createIndex( parentRow, 0, parentCol ); } int PIM::CollectionModel::rowCount( const QModelIndex & parent ) const { DataReference::List list; if ( parent.isValid() ) list = d->childCollections.value( static_cast( parent.internalPointer() )->reference() ); else list = d->childCollections.value( DataReference() ); return list.size(); } QVariant PIM::CollectionModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( section == 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole ) return i18n( "Name" ); return QAbstractItemModel::headerData( section, orientation, role ); } bool PIM::CollectionModel::removeRows( int row, int count, const QModelIndex & parent ) { DataReference::List list; DataReference parentRef; if ( parent.isValid() ) { parentRef = static_cast( parent.internalPointer() )->reference(); list = d->childCollections.value( parentRef ); } else list = d->childCollections.value( DataReference() ); if ( row < 0 || ( row + count - 1 ) >= list.size() ) { kWarning() << k_funcinfo << "Index out of bounds: " << row << "-" << row+count << " parent: " << parentRef.persistanceID() << endl; return false; } DataReference::List removeList = list.mid( row, count ); - beginRemoveRows( parent, row, row + count ); // FIXME row +/- 1??, crashs sort proxy model! + beginRemoveRows( parent, row, row + count - 1 ); // FIXME row +/- 1??, crashs sort proxy model! foreach ( DataReference ref, removeList ) { list.removeAll( ref ); delete d->collections.take( ref ); } d->childCollections.insert( parentRef, list ); endRemoveRows(); return true; } void PIM::CollectionModel::collectionChanged( const DataReference & ref ) { d->updateQueue.enqueue( ref ); processUpdates(); } void PIM::CollectionModel::collectionRemoved( const DataReference & ref ) { QModelIndex colIndex = indexForReference( ref ); if ( colIndex.isValid() ) { QModelIndex parentIndex = parent( colIndex ); // collection is still somewhere in the hierarchy removeRow( colIndex.row(), parentIndex ); } else { if ( d->collections.contains( ref ) ) // collection is orphan, ie. the parent has been removed already delete d->collections.take( ref ); } } void PIM::CollectionModel::fetchDone( Job * job ) { if ( job->error() || !d->fetchJob->collection() ) { // TODO: handle job errors kWarning() << k_funcinfo << "Job error or collection not available!" << endl; } else { Collection *col = d->fetchJob->collection(); Collection *oldCol = d->collections.value( col->reference() ); // update existing collection if ( oldCol ) { if ( oldCol->parent() == col->parent() ) { - // parent didn't change, we can keep the old collection and just update its content - oldCol->copy( col ); - QModelIndex index = indexForReference( col->reference() ); - emit dataChanged( index, index ); // TODO multi-column support - delete col; - col = 0; - // ### that should be the correct code, but it crashs an unpateched QTreeView - // (as soon as QTreeView is fixed, we can also replace Collection::copy() - // by a normal copy ctor. -#if 0 // TODO multi-column support QModelIndex oldIndex = indexForReference( oldCol->reference() ); d->collections.insert( col->reference(), col ); QModelIndex index = indexForReference( col->reference() ); changePersistentIndex( oldIndex, index ); emit dataChanged( index, index ); delete oldCol; -#endif } else { // parent changed, ie. we need to remove and add collectionRemoved( col->reference() ); oldCol = 0; // deleted above } } // add new collection if ( !oldCol && col ) { d->collections.insert( col->reference(), col ); QModelIndex parentIndex = indexForReference( col->parent() ); beginInsertRows( parentIndex, rowCount( parentIndex ) - 1, rowCount( parentIndex ) ); // ### row +/- 1??, crashs sort proxy model! d->childCollections[ col->parent() ].append( col->reference() ); endInsertRows(); } } job->deleteLater(); d->fetchJob = 0; processUpdates(); } void PIM::CollectionModel::processUpdates() { if ( d->fetchJob ) return; if ( d->updateQueue.isEmpty() ) return; d->fetchJob = new CollectionFetchJob( d->updateQueue.dequeue() ); connect( d->fetchJob, SIGNAL( done( PIM::Job* ) ), SLOT( fetchDone( PIM::Job* ) ) ); d->fetchJob->start(); } QModelIndex PIM::CollectionModel::indexForReference( const DataReference & ref, int column ) { if ( !d->collections.contains( ref ) ) return QModelIndex(); DataReference parentRef = d->collections.value( ref )->parent(); // check if parent still exist or if this is an orphan collection if ( !parentRef.isNull() && !d->collections.contains( parentRef ) ) return QModelIndex(); DataReference::List list = d->childCollections.value( parentRef ); int row = list.indexOf( ref ); if ( row >= 0 ) return createIndex( row, column, d->collections.value( list[row] ) ); return QModelIndex(); } #include "collectionmodel.moc" diff --git a/akonadi/collectionview.cpp b/akonadi/collectionview.cpp index a586f215a..61f46686b 100644 --- a/akonadi/collectionview.cpp +++ b/akonadi/collectionview.cpp @@ -1,59 +1,61 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectionview.h" #include #include using namespace PIM; class CollectionView::Private { public: QSortFilterProxyModel *filterModel; }; PIM::CollectionView::CollectionView( QWidget * parent ) : QTreeView( parent ), d( new Private() ) { d->filterModel = new QSortFilterProxyModel( this ); header()->setClickable( true ); header()->setSortIndicatorShown( true ); header()->setSortIndicator( 0, Qt::Ascending ); + header()->setStretchLastSection( false ); d->filterModel->sort( 0, Qt::Ascending ); } PIM::CollectionView::~ CollectionView( ) { delete d; d = 0; } void PIM::CollectionView::setModel( QAbstractItemModel * model ) { // FIXME sort proxy model crashs // d->filterModel->setSourceModel( model ); // QTreeView::setModel( d->filterModel ); QTreeView::setModel( model ); + header()->setResizeMode( 0, QHeaderView::Stretch ); } #include "collectionview.moc" diff --git a/akonadi/collectionview.cpp b/akonadi/messagecollection.cpp similarity index 54% copy from akonadi/collectionview.cpp copy to akonadi/messagecollection.cpp index a586f215a..e25814eaf 100644 --- a/akonadi/collectionview.cpp +++ b/akonadi/messagecollection.cpp @@ -1,59 +1,72 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "collectionview.h" - -#include -#include +#include "messagecollection.h" using namespace PIM; -class CollectionView::Private +class PIM::MessageCollection::Private { public: - QSortFilterProxyModel *filterModel; + int count; + int unreadCount; }; -PIM::CollectionView::CollectionView( QWidget * parent ) : - QTreeView( parent ), + +PIM::MessageCollection::MessageCollection( const DataReference & ref ) : + Collection( ref ), d( new Private() ) { - d->filterModel = new QSortFilterProxyModel( this ); + d->count = -1; + d->unreadCount = -1; +} - header()->setClickable( true ); - header()->setSortIndicatorShown( true ); - header()->setSortIndicator( 0, Qt::Ascending ); - d->filterModel->sort( 0, Qt::Ascending ); +PIM::MessageCollection::MessageCollection( const MessageCollection & other ) : + Collection( other ), + d( new Private() ) +{ + d->count = other.count(); + d->unreadCount = other.unreadCount(); } -PIM::CollectionView::~ CollectionView( ) +PIM::MessageCollection::~MessageCollection() { delete d; d = 0; } -void PIM::CollectionView::setModel( QAbstractItemModel * model ) +int PIM::MessageCollection::count( ) const { - // FIXME sort proxy model crashs -// d->filterModel->setSourceModel( model ); -// QTreeView::setModel( d->filterModel ); - QTreeView::setModel( model ); + return d->count; } -#include "collectionview.moc" +void PIM::MessageCollection::setCount( int count ) +{ + d->count = count; +} + +int PIM::MessageCollection::unreadCount( ) const +{ + return d->unreadCount; +} + +void PIM::MessageCollection::setUnreadCount( int count ) +{ + d->unreadCount = count; +} diff --git a/akonadi/messagecollection.h b/akonadi/messagecollection.h new file mode 100644 index 000000000..4f2540743 --- /dev/null +++ b/akonadi/messagecollection.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2006 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef PIM_MESSAGECOLLECTION_H +#define PIM_MESSAGECOLLECTION_H + +#include + +namespace PIM { + +/** + A collection of messages, eg. emails or news articles. +*/ +class MessageCollection : public Collection +{ + public: + /** + Create a new collection. + + @param ref The data reference of this collection. + */ + MessageCollection( const DataReference &ref ); + + /** + Copy constructor. + + @param other The MessageCollection to copy. + */ + MessageCollection( const MessageCollection &other ); + + /** + Destroys this collection. + */ + virtual ~MessageCollection(); + + /** + Returns the number of objects in this collection. + @returns -1 if this information is not available. + */ + int count() const; + + /** + Sets the number of objects in this collection. + */ + void setCount( int count ); + + /** + Returns the number of unread messages in this collection. + @returns -1 if this information is not available. + */ + int unreadCount() const; + + /** + Sets the number of unread messages in this collection. + */ + void setUnreadCount( int count ); + + private: + class Private; + Private *d; + +}; + +} + +#endif diff --git a/akonadi/messagecollectionmodel.cpp b/akonadi/messagecollectionmodel.cpp new file mode 100644 index 000000000..5a8934c7c --- /dev/null +++ b/akonadi/messagecollectionmodel.cpp @@ -0,0 +1,84 @@ +/* + Copyright (c) 2006 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "messagecollection.h" +#include "messagecollectionmodel.h" + +#include +#include + +#include + +using namespace PIM; + +PIM::MessageCollectionModel::MessageCollectionModel( const QHash< DataReference, Collection * > & collections, + QObject * parent ) : + CollectionModel( collections, parent ) +{ +} + +int PIM::MessageCollectionModel::columnCount( const QModelIndex & parent ) const +{ + Q_UNUSED( parent ); + return 3; +} + +QVariant PIM::MessageCollectionModel::data( const QModelIndex & index, int role ) const +{ + MessageCollection *msgcol = dynamic_cast( static_cast( index.internalPointer() ) ); + + if ( role == Qt::DisplayRole && msgcol && ( index.column() == 1 || index.column() == 2 ) ) { + int value = -1; + switch ( index.column() ) { + case 1: value = msgcol->unreadCount(); break; + case 2: value = msgcol->count(); break; + } + if ( value < 0 ) + return QString(); + else if ( value == 0 ) + return QString( "-" ); + else + return QString::number( value ); + } + + if ( role == Qt::TextAlignmentRole && ( index.column() == 1 || index.column() == 2 ) ) + return Qt::AlignRight; + + // ### that's wrong, we'll need a custom delegate anyway + if ( role == Qt::FontRole && msgcol && msgcol->unreadCount() > 0 ) { + QFont f; + f.setBold( true ); + return f; + } + + return CollectionModel::data( index, role ); +} + +QVariant PIM::MessageCollectionModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) + switch ( section ) { + case 1: return i18n( "Unread" ); + case 2: return i18n( "Total" ); + } + + return CollectionModel::headerData( section, orientation, role ); +} + +#include "messagecollectionmodel.moc" diff --git a/akonadi/messagecollectionmodel.h b/akonadi/messagecollectionmodel.h new file mode 100644 index 000000000..1640d2425 --- /dev/null +++ b/akonadi/messagecollectionmodel.h @@ -0,0 +1,65 @@ +/* + Copyright (c) 2006 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef PIM_MESSAGECOLLECTIONMODEL_H +#define PIM_MESSAGECOLLECTIONMODEL_H + +#include + +namespace PIM { + +class MessageCollectionModel : public CollectionModel +{ + Q_OBJECT + + public: + /** + Create a new message collection model. + @param collections A hash containing all collections. + The CollectionModel takes the ownership of the collection objects, + ie. it will take care of deleting them. + @param parent The parent object. + */ + MessageCollectionModel( const QHash &collections, + QObject *parent = 0 ); + + /** + Reimplemented from CollectionModel. + */ + virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; + + /** + Reimplemented from CollectionModel. + */ + virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; + + /** + Reimplemented from QAbstractItemModel. + */ + virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + + private: + class Private; + Private *d; + +}; + +} + +#endif diff --git a/akonadi/tests/collectionbrowser.cpp b/akonadi/tests/collectionbrowser.cpp index e48090eb8..a3709675c 100644 --- a/akonadi/tests/collectionbrowser.cpp +++ b/akonadi/tests/collectionbrowser.cpp @@ -1,140 +1,154 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "collection.h" +#include "messagecollection.h" #include "collectionbrowser.h" #include "collectionlistjob.h" #define private public -#include "collectionmodel.h" +#include "messagecollectionmodel.h" #include #include #include #include #include #include #include #include using namespace PIM; extern QHash global_collection_map; static int id = 0; static void createCollections( const DataReference &parent, int rec ) { if ( rec <= 0 ) return; int count = rand() % 10; for ( int i = 0; i < count; ++i ) { DataReference ref( QString::number( id++ ), QString() ); - Collection *col = new Collection( ref ); + Collection *col; + int r = rand() % 6; + if ( r <= 3 ) + col = new Collection( ref ); + else { + MessageCollection *mcol = new MessageCollection( ref ); + mcol->setCount( 2000 ); + mcol->setUnreadCount( r % 2 ); + col = mcol; + } col->setParent( parent ); col->setName( ref.persistanceID() ); QStringList content; - switch ( rand() % 6 ) { + switch ( r ) { + case 0: + break; case 1: content << "text/x-vcard"; break; case 2: content << "akonadi/event"; break; case 3: content << "akonadi/task"; break; default: content << "message/rfc822"; } col->setContentTypes( content ); global_collection_map.insert( ref, col ); if ( parent.isNull() ) col->setType( Collection::Resource ); createCollections( ref, rec - ( rand() % 3 ) - 1 ); } } CollectionBrowser::CollectionBrowser() : CollectionView() { CollectionListJob *job = new CollectionListJob(); job->exec(); QHash collections = job->collections(); delete job; // use some dummy collections for now createCollections( DataReference(), 8 ); foreach ( Collection *col, global_collection_map ) { - Collection *colCopy = new Collection( col->reference() ); - colCopy->copy( col ); + Collection *colCopy; + if ( dynamic_cast( col ) ) + colCopy = new MessageCollection( *static_cast( col ) ); + else + colCopy = new Collection( *col ); collections.insert( col->reference(), colCopy ); } - model = new CollectionModel( collections, this ); + model = new MessageCollectionModel( collections, this ); setModel( model ); // emulate the monitor job QTimer *t = new QTimer( this ); connect( t, SIGNAL( timeout() ), SLOT( slotEmitChanged() ) ); t->start( 1000 ); // t->setSingleShot( true ); } void CollectionBrowser::slotEmitChanged() { // update int id = rand() % 1000; DataReference ref( QString::number( id ), QString() ); Collection *col = global_collection_map.value( ref ); if ( col ) { if ( rand() % 10 ) { col->setName( col->name() + " (changed)" ); kDebug() << k_funcinfo << "update collection " << ref.persistanceID() << " parent: " << col->parent().persistanceID() << endl; } else { col->setParent( DataReference( QString::number( rand() % 1000 ), QString() ) ); col->setName( col->name() + " (reparented)" ); kDebug() << k_funcinfo << "reparenting collection " << ref.persistanceID() << " to new parent " << col->parent().persistanceID() << endl; } model->collectionChanged( ref ); } // delete id = rand() % 1000; id += 500; ref = DataReference( QString::number( id ), QString() ); global_collection_map.remove( ref ); kDebug() << k_funcinfo << "remove collection " << ref.persistanceID() << endl; model->collectionRemoved( ref ); // add id = rand() % 1000; id += 10000; ref = DataReference( QString::number( id ), QString() ); col = new Collection( ref ); col->setParent( DataReference( QString::number( rand() % 1000 ), QString() ) ); col->setName( ref.persistanceID() + " (new)" ); global_collection_map.insert( ref, col ); kDebug() << k_funcinfo << "add collection " << ref.persistanceID() << " parent: " << col->parent().persistanceID() << endl; model->collectionChanged( ref ); } int main( int argc, char** argv ) { KCmdLineArgs::init( argc, argv, "test", "Test" ,"test app" ,"1.0" ); KApplication app; CollectionBrowser w; w.show(); return app.exec(); } #include "collectionbrowser.moc"