french -> French
[kdepim.git] / calendarsupport / attachmenthandler.cpp
blob78a6288a7cdafa5114ba92695ecf45505c41884c
1 /*
2 Copyright (c) 2010 Klarlvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
3 Author: Allen Winter <allen.winter@kdab.com>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
20 /**
21 @file
22 This file is part of the API for handling calendar data and provides
23 static functions for dealing with calendar incidence attachments.
25 @brief
26 vCalendar/iCalendar attachment handling.
28 @author Allen Winter \<winter@kde.org\>
30 #include "attachmenthandler.h"
31 #include "next/incidencesearchjob.h"
33 #include <KFileDialog>
34 #include <KLocale>
35 #include <KMessageBox>
36 #include <KMimeType>
37 #include <KRun>
38 #include <KTemporaryFile>
39 #include <KToolInvocation>
40 #include <KIO/NetAccess>
41 #include <KJob>
43 #include <QFile>
44 #include <QPointer>
46 using namespace KCalCore;
48 namespace CalendarSupport {
50 struct ReceivedInfo {
51 QString uid;
52 QString attachmentName;
55 class AttachmentHandler::Private
57 public:
58 Private( QWidget *parent )
60 mParent = parent;
62 QMap<KJob *,ReceivedInfo> mJobToReceivedInfo;
63 QPointer<QWidget> mParent;
66 AttachmentHandler::AttachmentHandler( QWidget *parent ) : QObject( parent ), d( new Private( parent ) )
71 AttachmentHandler::~AttachmentHandler()
73 delete d;
76 Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
77 const Incidence::Ptr &incidence )
79 if ( !incidence ) {
80 return Attachment::Ptr();
83 // get the attachment by name from the incidence
84 const Attachment::List as = incidence->attachments();
85 Attachment::Ptr a;
86 if ( !as.isEmpty() ) {
87 Attachment::List::ConstIterator it;
88 Attachment::List::ConstIterator end( as.constEnd() );
90 for ( it = as.constBegin(); it != end; ++it ) {
91 if ( (*it)->label() == attachmentName ) {
92 a = *it;
93 break;
98 if ( !a ) {
99 KMessageBox::error(
100 d->mParent,
101 i18n( "No attachment named \"%1\" found in the incidence.", attachmentName ) );
102 return Attachment::Ptr();
105 if ( a->isUri() ) {
106 if ( !KIO::NetAccess::exists( a->uri(), KIO::NetAccess::SourceSide, d->mParent ) ) {
107 KMessageBox::sorry(
108 d->mParent,
109 i18n( "The attachment \"%1\" is a web link that is inaccessible from this computer. ",
110 KUrl::fromPercentEncoding( a->uri().toLatin1() ) ) );
111 return Attachment::Ptr();
114 return a;
117 Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
118 const ScheduleMessage::Ptr &message )
120 if ( !message ) {
121 return Attachment::Ptr();
124 Incidence::Ptr incidence = message->event().dynamicCast<Incidence>();
125 if ( !incidence ) {
126 KMessageBox::error(
127 d->mParent,
128 i18n( "The calendar invitation stored in this email message is broken in some way. "
129 "Unable to continue." ) );
130 return Attachment::Ptr();
133 return find( attachmentName, incidence );
136 static KTemporaryFile *s_tempFile = 0;
138 static KUrl tempFileForAttachment( const Attachment::Ptr &attachment )
140 KUrl url;
142 s_tempFile = new KTemporaryFile();
143 s_tempFile->setAutoRemove( false );
144 QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
145 if ( !patterns.empty() ) {
146 s_tempFile->setSuffix( QString( patterns.first() ).remove( QLatin1Char('*') ) );
148 s_tempFile->open();
149 s_tempFile->setPermissions( QFile::ReadUser );
150 s_tempFile->write( QByteArray::fromBase64( attachment->data() ) );
151 s_tempFile->close();
152 QFile tf( s_tempFile->fileName() );
153 if ( tf.size() != attachment->size() ) {
154 //whoops. failed to write the entire attachment. return an invalid URL.
155 delete s_tempFile;
156 s_tempFile = 0;
157 return url;
160 url.setPath( s_tempFile->fileName() );
161 return url;
164 bool AttachmentHandler::view( const Attachment::Ptr &attachment )
166 if ( !attachment ) {
167 return false;
170 bool stat = true;
171 if ( attachment->isUri() ) {
172 KToolInvocation::invokeBrowser( attachment->uri() );
173 } else {
174 // put the attachment in a temporary file and launch it
175 KUrl tempUrl = tempFileForAttachment( attachment );
176 if ( tempUrl.isValid() ) {
177 stat = KRun::runUrl( tempUrl, attachment->mimeType(), 0, true );
178 } else {
179 stat = false;
180 KMessageBox::error(
181 d->mParent,
182 i18n( "Unable to create a temporary file for the attachment." ) );
184 delete s_tempFile;
185 s_tempFile = 0;
187 return stat;
190 bool AttachmentHandler::view( const QString &attachmentName,
191 const Incidence::Ptr &incidence )
193 return view( find( attachmentName, incidence ) );
196 void AttachmentHandler::view( const QString &attachmentName, const QString &uid )
198 IncidenceSearchJob *job = new IncidenceSearchJob();
199 job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid,
200 IncidenceSearchJob::ExactMatch );
201 connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) );
202 ReceivedInfo info;
203 info.attachmentName = attachmentName;
204 info.uid = uid;
205 d->mJobToReceivedInfo[job] = info;
208 bool AttachmentHandler::view( const QString &attachmentName,
209 const ScheduleMessage::Ptr &message )
211 return view( find( attachmentName, message ) );
214 bool AttachmentHandler::saveAs( const Attachment::Ptr &attachment )
216 // get the saveas file name
217 QString saveAsFile = KFileDialog::getSaveFileName( attachment->label(), QString(), d->mParent,
218 i18n( "Save Attachment" ) );
219 if ( saveAsFile.isEmpty() ||
220 ( QFile( saveAsFile ).exists() &&
221 ( KMessageBox::warningYesNo(
222 d->mParent,
223 i18n( "%1 already exists. Do you want to overwrite it?",
224 saveAsFile ) ) == KMessageBox::No ) ) ) {
225 return false;
228 bool stat = false;
229 if ( attachment->isUri() ) {
230 // save the attachment url
231 stat = KIO::NetAccess::file_copy( attachment->uri(), KUrl( saveAsFile ) );
232 } else {
233 // put the attachment in a temporary file and save it
234 KUrl tempUrl = tempFileForAttachment( attachment );
235 if ( tempUrl.isValid() ) {
236 stat = KIO::NetAccess::file_copy( tempUrl, KUrl( saveAsFile ) );
237 if ( !stat && KIO::NetAccess::lastError() ) {
238 KMessageBox::error( d->mParent, KIO::NetAccess::lastErrorString() );
240 } else {
241 stat = false;
242 KMessageBox::error(
243 d->mParent,
244 i18n( "Unable to create a temporary file for the attachment." ) );
246 delete s_tempFile;
247 s_tempFile = 0;
249 return stat;
252 bool AttachmentHandler::saveAs( const QString &attachmentName,
253 const Incidence::Ptr &incidence )
255 return saveAs( find( attachmentName, incidence ) );
258 void AttachmentHandler::saveAs( const QString &attachmentName, const QString &uid )
260 IncidenceSearchJob *job = new IncidenceSearchJob();
261 job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid,
262 IncidenceSearchJob::ExactMatch );
263 connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) );
265 ReceivedInfo info;
266 info.attachmentName = attachmentName;
267 info.uid = uid;
268 d->mJobToReceivedInfo[job] = info;
271 bool AttachmentHandler::saveAs( const QString &attachmentName,
272 const ScheduleMessage::Ptr &message )
274 return saveAs( find( attachmentName, message ) );
277 void AttachmentHandler::slotFinishSaveAs( KJob *job )
279 IncidenceSearchJob *searchJob = qobject_cast<IncidenceSearchJob*>( job );
280 const KCalCore::Incidence::List incidences = searchJob->incidences();
281 ReceivedInfo info = d->mJobToReceivedInfo[job];
283 bool success = false;
284 if ( !incidences.isEmpty() ) {
285 if ( saveAs( info.attachmentName, incidences.first() ) ) {
286 success = true;
290 emit saveAsFinished( info.uid, info.attachmentName, success );
291 d->mJobToReceivedInfo.remove( job );
294 void AttachmentHandler::slotFinishView( KJob *job )
296 IncidenceSearchJob *searchJob = qobject_cast<IncidenceSearchJob*>( job );
297 const KCalCore::Incidence::List incidences = searchJob->incidences();
298 ReceivedInfo info = d->mJobToReceivedInfo[job];
300 bool success = false;
301 if ( !incidences.isEmpty() ) {
302 if ( view( info.attachmentName, incidences.first() ) ) {
303 success = true;
307 emit viewFinished( info.uid, info.attachmentName, success );
308 d->mJobToReceivedInfo.remove( job );
311 } // namespace CalendarSupport