1/*
2 Copyright (c) 2007 Volker Krause <vkrause@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "subscriptionmodel_p.h"
21#include "collectionfetchjob.h"
22#include "collectionutils_p.h"
23#include "specialcollectionattribute_p.h"
24
25#include "entityhiddenattribute.h"
26
27#include <kdebug.h>
28
29#include <QtCore/QStringList>
30#include <QFont>
31
32using namespace Akonadi;
33
34/**
35 * @internal
36 */
37class SubscriptionModel::Private
38{
39 public:
40 Private( SubscriptionModel* parent ) : q( parent ), showHiddenCollection(false) {}
41 SubscriptionModel* q;
42 QHash<Collection::Id, bool> subscriptions;
43 QSet<Collection::Id> changes;
44 bool showHiddenCollection;
45
46 Collection::List changedSubscriptions( bool subscribed )
47 {
48 Collection::List list;
49 foreach ( Collection::Id id, changes ) {
50 if ( subscriptions.value( id ) == subscribed )
51 list << Collection( id );
52 }
53 return list;
54 }
55
56 void listResult( KJob* job )
57 {
58 if ( job->error() ) {
59 // TODO
60 kWarning() << job->errorString();
61 return;
62 }
63 Collection::List cols = static_cast<CollectionFetchJob*>( job )->collections();
64 foreach ( const Collection &col, cols )
65 if ( !CollectionUtils::isStructural( col ) )
66 subscriptions[ col.id() ] = true;
67 q->reset();
68 emit q->loaded();
69 }
70
71 bool isSubscribable( Collection::Id id )
72 {
73 Collection col = q->collectionForId( id );
74 if ( CollectionUtils::isStructural( col ) || col.isVirtual() )
75 return false;
76 if ( col.hasAttribute<SpecialCollectionAttribute>() )
77 return false;
78 if ( col.contentMimeTypes().isEmpty() )
79 return false;
80 return true;
81 }
82};
83
84SubscriptionModel::SubscriptionModel(QObject * parent) :
85 CollectionModel( parent ),
86 d( new Private( this ) )
87{
88 includeUnsubscribed();
89 CollectionFetchJob* job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, this );
90 connect( job, SIGNAL(result(KJob*)), this, SLOT(listResult(KJob*)) );
91}
92
93SubscriptionModel::~ SubscriptionModel()
94{
95 delete d;
96}
97
98QVariant SubscriptionModel::data(const QModelIndex & index, int role) const
99{
100 switch ( role ) {
101 case Qt::CheckStateRole:
102 {
103 const Collection::Id col = index.data( CollectionIdRole ).toLongLong();
104 if ( !d->isSubscribable( col ) )
105 return QVariant();
106 if ( d->subscriptions.value( col ) )
107 return Qt::Checked;
108 return Qt::Unchecked;
109 }
110 case SubscriptionChangedRole:
111 {
112 const Collection::Id col = index.data( CollectionIdRole ).toLongLong();
113 if ( d->changes.contains( col ) )
114 return true;
115 return false;
116 }
117 case Qt::FontRole:
118 {
119 const Collection::Id col = index.data( CollectionIdRole ).toLongLong();
120
121 QFont font = CollectionModel::data( index, role ).value<QFont>();
122 font.setBold( d->changes.contains( col ) );
123
124 return font;
125 }
126 }
127
128 if ( role == CollectionIdRole ) {
129 return CollectionModel::data( index, CollectionIdRole );
130 } else {
131 const Collection::Id collectionId = index.data( CollectionIdRole ).toLongLong();
132 const Collection collection = collectionForId( collectionId );
133 if ( collection.hasAttribute<EntityHiddenAttribute>() ) {
134 if (d->showHiddenCollection) {
135 return CollectionModel::data( index, role );
136 } else {
137 return QVariant();
138 }
139 } else {
140 return CollectionModel::data( index, role );
141 }
142 }
143}
144
145Qt::ItemFlags SubscriptionModel::flags(const QModelIndex & index) const
146{
147 Qt::ItemFlags flags = CollectionModel::flags( index );
148 if ( d->isSubscribable( index.data( CollectionIdRole ).toLongLong() ) )
149 return flags | Qt::ItemIsUserCheckable;
150 return flags;
151}
152
153bool SubscriptionModel::setData(const QModelIndex & index, const QVariant & value, int role)
154{
155 if ( role == Qt::CheckStateRole ) {
156 const Collection::Id col = index.data( CollectionIdRole ).toLongLong();
157 if ( !d->isSubscribable(col) ) {
158 return true; //No change
159 }
160 if ( d->subscriptions.contains( col ) && d->subscriptions.value( col ) == (value == Qt::Checked) )
161 return true; // no change
162 d->subscriptions[ col ] = value == Qt::Checked;
163 if ( d->changes.contains( col ) )
164 d->changes.remove( col );
165 else
166 d->changes.insert( col );
167 emit dataChanged( index, index );
168 return true;
169 }
170 return CollectionModel::setData( index, value, role );
171}
172
173Akonadi::Collection::List SubscriptionModel::subscribed() const
174{
175 return d->changedSubscriptions( true );
176}
177
178Akonadi::Collection::List SubscriptionModel::unsubscribed() const
179{
180 return d->changedSubscriptions( false );
181}
182
183void SubscriptionModel::showHiddenCollection(bool showHidden)
184{
185 d->showHiddenCollection = showHidden;
186}
187
188#include "moc_subscriptionmodel_p.cpp"
189