1/*
2 Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
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 "partfetcher.h"
21
22#include "entitytreemodel.h"
23#include "session.h"
24#include "itemfetchjob.h"
25#include "itemfetchscope.h"
26#include <KLocalizedString>
27
28#ifndef KDE_USE_FINAL
29Q_DECLARE_METATYPE(QSet<QByteArray>)
30#endif
31
32using namespace Akonadi;
33
34namespace Akonadi
35{
36
37class PartFetcherPrivate
38{
39 PartFetcherPrivate(PartFetcher *partFetcher, const QModelIndex &index, const QByteArray &partName)
40 : m_persistentIndex(index)
41 , m_partName(partName)
42 , q_ptr(partFetcher)
43 {
44 }
45
46 void fetchJobDone(KJob *);
47
48 void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
49
50 QPersistentModelIndex m_persistentIndex;
51 QByteArray m_partName;
52 Item m_item;
53
54 Q_DECLARE_PUBLIC(PartFetcher)
55 PartFetcher *q_ptr;
56};
57
58}
59
60void PartFetcherPrivate::fetchJobDone(KJob *job)
61{
62 Q_Q(PartFetcher);
63 if (job->error()) {
64 q->setError(KJob::UserDefinedError);
65 q->setErrorText(i18n("Unable to fetch item for index"));
66 q->emitResult();
67 return;
68 }
69
70 ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job);
71
72 const Item::List list = fetchJob->items();
73
74 Q_ASSERT(list.size() == 1);
75
76 // If m_persistentIndex comes from a selection proxy model, it could become
77 // invalid if the user clicks around a lot.
78 if (!m_persistentIndex.isValid()) {
79 q->setError(KJob::UserDefinedError);
80 q->setErrorText(i18n("Index is no longer available"));
81 q->emitResult();
82 return;
83 }
84
85 const QSet<QByteArray> loadedParts = m_persistentIndex.data(EntityTreeModel::LoadedPartsRole).value<QSet<QByteArray> >();
86
87 Q_ASSERT(!loadedParts.contains(m_partName));
88
89 Item item = m_persistentIndex.data(EntityTreeModel::ItemRole).value<Item>();
90
91 item.apply(list.at(0));
92
93 QAbstractItemModel *model = const_cast<QAbstractItemModel *>(m_persistentIndex.model());
94
95 Q_ASSERT(model);
96
97 QVariant itemVariant = QVariant::fromValue(item);
98 model->setData(m_persistentIndex, itemVariant, EntityTreeModel::ItemRole);
99
100 m_item = item;
101
102 emit q->emitResult();
103}
104
105PartFetcher::PartFetcher(const QModelIndex &index, const QByteArray &partName, QObject *parent)
106 : KJob(parent)
107 , d_ptr(new PartFetcherPrivate(this, index, partName))
108{
109}
110
111PartFetcher::~PartFetcher()
112{
113 delete d_ptr;
114}
115
116void PartFetcher::start()
117{
118 Q_D(PartFetcher);
119
120 const QModelIndex index = d->m_persistentIndex;
121
122 const QSet<QByteArray> loadedParts = index.data(EntityTreeModel::LoadedPartsRole).value<QSet<QByteArray> >();
123
124 if (loadedParts.contains(d->m_partName)) {
125 d->m_item = d->m_persistentIndex.data(EntityTreeModel::ItemRole).value<Item>();
126 emitResult();
127 return;
128 }
129
130 const QSet<QByteArray> availableParts = index.data(EntityTreeModel::AvailablePartsRole).value<QSet<QByteArray> >();
131 if (!availableParts.contains(d->m_partName)) {
132 setError(UserDefinedError);
133 setErrorText(i18n("Payload part '%1' is not available for this index" , QString::fromLatin1(d->m_partName)));
134 emitResult();
135 return;
136 }
137
138 Akonadi::Session *session = qobject_cast<Akonadi::Session *>(qvariant_cast<QObject *>(index.data(EntityTreeModel::SessionRole)));
139
140 if (!session) {
141 setError(UserDefinedError);
142 setErrorText(i18n("No session available for this index"));
143 emitResult();
144 return;
145 }
146
147 const Akonadi::Item item = index.data(EntityTreeModel::ItemRole).value<Akonadi::Item>();
148
149 if (!item.isValid()) {
150 setError(UserDefinedError);
151 setErrorText(i18n("No item available for this index"));
152 emitResult();
153 return;
154 }
155
156 ItemFetchScope scope;
157 scope.fetchPayloadPart(d->m_partName);
158 ItemFetchJob *itemFetchJob = new Akonadi::ItemFetchJob(item, session);
159 itemFetchJob->setFetchScope(scope);
160
161 connect(itemFetchJob, SIGNAL(result(KJob*)),
162 this, SLOT(fetchJobDone(KJob*)));
163}
164
165QModelIndex PartFetcher::index() const
166{
167 Q_D(const PartFetcher);
168
169 return d->m_persistentIndex;
170}
171
172QByteArray PartFetcher::partName() const
173{
174 Q_D(const PartFetcher);
175
176 return d->m_partName;
177}
178
179Item PartFetcher::item() const
180{
181 Q_D(const PartFetcher);
182
183 return d->m_item;
184}
185
186#include "moc_partfetcher.cpp"
187