Fix wrong connect
[kdepim.git] / calendarsupport / attachmenthandler.cpp
blob15537501fbe5260f599d9abe3e13ed67052c842d
1 /*
2 Copyright (c) 2010 Klarlvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
3 Author: Allen Winter <allen.winter@kdab.com>
4 Copyright (C) 2014 Sergio Martins <iamsergio@gmail.com>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
21 /**
22 @file
23 This file is part of the API for handling calendar data and provides
24 static functions for dealing with calendar incidence attachments.
26 @brief
27 vCalendar/iCalendar attachment handling.
29 @author Allen Winter \<winter@kde.org\>
31 #include "attachmenthandler.h"
32 #include "calendarsupport/utils.h"
34 #include <ItemFetchJob>
35 #include <QFileDialog>
36 #include <KLocalizedString>
37 #include <KMessageBox>
39 #include <KRun>
40 #include <QTemporaryFile>
41 #include <KToolInvocation>
42 #include <KIO/NetAccess>
43 #include <KJob>
44 #include "calendarsupport_debug.h"
46 #include <QFile>
47 #include <QPointer>
48 #include <QMimeDatabase>
50 using namespace KCalCore;
51 using namespace Akonadi;
53 namespace CalendarSupport
56 struct ReceivedInfo {
57 QString uid;
58 QString attachmentName;
61 class AttachmentHandler::Private
63 public:
64 Private(QWidget *parent)
66 mParent = parent;
68 QMap<KJob *, ReceivedInfo> mJobToReceivedInfo;
69 QPointer<QWidget> mParent;
72 AttachmentHandler::AttachmentHandler(QWidget *parent) : QObject(parent), d(new Private(parent))
77 AttachmentHandler::~AttachmentHandler()
79 delete d;
82 Attachment::Ptr AttachmentHandler::find(const QString &attachmentName,
83 const Incidence::Ptr &incidence)
85 if (!incidence) {
86 return Attachment::Ptr();
89 // get the attachment by name from the incidence
90 const Attachment::List as = incidence->attachments();
91 Attachment::Ptr a;
92 if (!as.isEmpty()) {
93 Attachment::List::ConstIterator it;
94 Attachment::List::ConstIterator end(as.constEnd());
96 for (it = as.constBegin(); it != end; ++it) {
97 if ((*it)->label() == attachmentName) {
98 a = *it;
99 break;
104 if (!a) {
105 KMessageBox::error(
106 d->mParent,
107 i18n("No attachment named \"%1\" found in the incidence.", attachmentName));
108 return Attachment::Ptr();
111 if (a->isUri()) {
112 if (!KIO::NetAccess::exists(a->uri(), KIO::NetAccess::SourceSide, d->mParent)) {
113 KMessageBox::sorry(
114 d->mParent,
115 i18n("The attachment \"%1\" is a web link that is inaccessible from this computer. ",
116 QUrl::fromPercentEncoding(a->uri().toLatin1())));
117 return Attachment::Ptr();
120 return a;
123 Attachment::Ptr AttachmentHandler::find(const QString &attachmentName,
124 const ScheduleMessage::Ptr &message)
126 if (!message) {
127 return Attachment::Ptr();
130 Incidence::Ptr incidence = message->event().dynamicCast<Incidence>();
131 if (!incidence) {
132 KMessageBox::error(
133 d->mParent,
134 i18n("The calendar invitation stored in this email message is broken in some way. "
135 "Unable to continue."));
136 return Attachment::Ptr();
139 return find(attachmentName, incidence);
142 static QTemporaryFile *s_tempFile = 0;
144 static QUrl tempFileForAttachment(const Attachment::Ptr &attachment)
146 QUrl url;
148 QMimeDatabase db;
149 QStringList patterns = db.mimeTypeForName(attachment->mimeType()).globPatterns();
150 if (!patterns.empty()) {
151 s_tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/attachementview_XXXXXX") + patterns.first().remove(QLatin1Char('*')));
152 } else {
153 s_tempFile = new QTemporaryFile();
155 s_tempFile->setAutoRemove(false);
156 s_tempFile->open();
157 s_tempFile->setPermissions(QFile::ReadUser);
158 s_tempFile->write(QByteArray::fromBase64(attachment->data()));
159 s_tempFile->close();
160 QFile tf(s_tempFile->fileName());
161 if (tf.size() != attachment->size()) {
162 //whoops. failed to write the entire attachment. return an invalid URL.
163 delete s_tempFile;
164 s_tempFile = 0;
165 return url;
168 url.setPath(s_tempFile->fileName());
169 return url;
172 bool AttachmentHandler::view(const Attachment::Ptr &attachment)
174 if (!attachment) {
175 return false;
178 bool stat = true;
179 if (attachment->isUri()) {
180 KToolInvocation::invokeBrowser(attachment->uri());
181 } else {
182 // put the attachment in a temporary file and launch it
183 QUrl tempUrl = tempFileForAttachment(attachment);
184 if (tempUrl.isValid()) {
185 stat = KRun::runUrl(tempUrl, attachment->mimeType(), 0, true);
186 } else {
187 stat = false;
188 KMessageBox::error(
189 d->mParent,
190 i18n("Unable to create a temporary file for the attachment."));
192 delete s_tempFile;
193 s_tempFile = 0;
195 return stat;
198 bool AttachmentHandler::view(const QString &attachmentName,
199 const Incidence::Ptr &incidence)
201 return view(find(attachmentName, incidence));
204 void AttachmentHandler::view(const QString &attachmentName, const QString &uid)
206 Item item;
207 item.setGid(uid);
208 ItemFetchJob *job = new ItemFetchJob(item);
209 connect(job, &ItemFetchJob::result, this, &AttachmentHandler::slotFinishView);
210 ReceivedInfo info;
211 info.attachmentName = attachmentName;
212 info.uid = uid;
213 d->mJobToReceivedInfo[job] = info;
216 bool AttachmentHandler::view(const QString &attachmentName,
217 const ScheduleMessage::Ptr &message)
219 return view(find(attachmentName, message));
222 bool AttachmentHandler::saveAs(const Attachment::Ptr &attachment)
224 // get the saveas file name
225 QString saveAsFile = QFileDialog::getSaveFileName(d->mParent, i18n("Save Attachment"), attachment->label());
226 if (saveAsFile.isEmpty() ||
227 (QFile(saveAsFile).exists() &&
228 (KMessageBox::warningYesNo(
229 d->mParent,
230 i18n("%1 already exists. Do you want to overwrite it?",
231 saveAsFile)) == KMessageBox::No))) {
232 return false;
235 bool stat = false;
236 if (attachment->isUri()) {
237 // save the attachment url
238 stat = KIO::NetAccess::file_copy(attachment->uri(), QUrl::fromLocalFile(saveAsFile));
239 } else {
240 // put the attachment in a temporary file and save it
241 QUrl tempUrl = tempFileForAttachment(attachment);
242 if (tempUrl.isValid()) {
243 stat = KIO::NetAccess::file_copy(tempUrl, QUrl::fromLocalFile(saveAsFile));
244 if (!stat && KIO::NetAccess::lastError()) {
245 KMessageBox::error(d->mParent, KIO::NetAccess::lastErrorString());
247 } else {
248 stat = false;
249 KMessageBox::error(
250 d->mParent,
251 i18n("Unable to create a temporary file for the attachment."));
253 delete s_tempFile;
254 s_tempFile = 0;
256 return stat;
259 bool AttachmentHandler::saveAs(const QString &attachmentName,
260 const Incidence::Ptr &incidence)
262 return saveAs(find(attachmentName, incidence));
265 void AttachmentHandler::saveAs(const QString &attachmentName, const QString &uid)
267 Item item;
268 item.setGid(uid);
269 ItemFetchJob *job = new ItemFetchJob(item);
270 connect(job, &ItemFetchJob::result, this, &AttachmentHandler::slotFinishView);
272 ReceivedInfo info;
273 info.attachmentName = attachmentName;
274 info.uid = uid;
275 d->mJobToReceivedInfo[job] = info;
278 bool AttachmentHandler::saveAs(const QString &attachmentName,
279 const ScheduleMessage::Ptr &message)
281 return saveAs(find(attachmentName, message));
284 void AttachmentHandler::slotFinishSaveAs(KJob *job)
286 ReceivedInfo info = d->mJobToReceivedInfo[job];
287 bool success = false;
289 if (job->error() != 0) {
290 ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job);
291 const Item::List items = fetchJob->items();
292 if (!items.isEmpty()) {
293 Incidence::Ptr incidence = CalendarSupport::incidence(items.first());
294 success = incidence && saveAs(info.attachmentName, incidence);
295 } else {
296 qCWarning(CALENDARSUPPORT_LOG) << Q_FUNC_INFO << "No item found";
298 } else {
299 qCWarning(CALENDARSUPPORT_LOG) << Q_FUNC_INFO << "Job error:" << job->errorString();
302 Q_EMIT saveAsFinished(info.uid, info.attachmentName, success);
303 d->mJobToReceivedInfo.remove(job);
306 void AttachmentHandler::slotFinishView(KJob *job)
308 ReceivedInfo info = d->mJobToReceivedInfo[job];
309 bool success = false;
311 if (job->error() != 0) {
312 ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job);
313 const Item::List items = fetchJob->items();
314 if (!items.isEmpty()) {
315 Incidence::Ptr incidence = CalendarSupport::incidence(items.first());
316 success = incidence && view(info.attachmentName, incidence);
317 } else {
318 qCWarning(CALENDARSUPPORT_LOG) << Q_FUNC_INFO << "No item found";
320 } else {
321 qCWarning(CALENDARSUPPORT_LOG) << Q_FUNC_INFO << "Job error:" << job->errorString();
324 Q_EMIT viewFinished(info.uid, info.attachmentName, success);
325 d->mJobToReceivedInfo.remove(job);
328 } // namespace CalendarSupport