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.
22 This file is part of the API for handling calendar data and provides
23 static functions for dealing with calendar incidence attachments.
26 vCalendar/iCalendar attachment handling.
28 @author Allen Winter \<winter@kde.org\>
30 #include "attachmenthandler.h"
31 #include "next/incidencesearchjob.h"
33 #include <KFileDialog>
35 #include <KMessageBox>
38 #include <KTemporaryFile>
39 #include <KToolInvocation>
40 #include <KIO/NetAccess>
46 using namespace KCalCore
;
48 namespace CalendarSupport
{
52 QString attachmentName
;
55 class AttachmentHandler::Private
58 Private( QWidget
*parent
)
62 QMap
<KJob
*,ReceivedInfo
> mJobToReceivedInfo
;
63 QPointer
<QWidget
> mParent
;
66 AttachmentHandler::AttachmentHandler( QWidget
*parent
) : QObject( parent
), d( new Private( parent
) )
71 AttachmentHandler::~AttachmentHandler()
76 Attachment::Ptr
AttachmentHandler::find( const QString
&attachmentName
,
77 const Incidence::Ptr
&incidence
)
80 return Attachment::Ptr();
83 // get the attachment by name from the incidence
84 const Attachment::List as
= incidence
->attachments();
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
) {
101 i18n( "No attachment named \"%1\" found in the incidence.", attachmentName
) );
102 return Attachment::Ptr();
106 if ( !KIO::NetAccess::exists( a
->uri(), KIO::NetAccess::SourceSide
, 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();
117 Attachment::Ptr
AttachmentHandler::find( const QString
&attachmentName
,
118 const ScheduleMessage::Ptr
&message
)
121 return Attachment::Ptr();
124 Incidence::Ptr incidence
= message
->event().dynamicCast
<Incidence
>();
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
)
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('*') ) );
149 s_tempFile
->setPermissions( QFile::ReadUser
);
150 s_tempFile
->write( QByteArray::fromBase64( attachment
->data() ) );
152 QFile
tf( s_tempFile
->fileName() );
153 if ( tf
.size() != attachment
->size() ) {
154 //whoops. failed to write the entire attachment. return an invalid URL.
160 url
.setPath( s_tempFile
->fileName() );
164 bool AttachmentHandler::view( const Attachment::Ptr
&attachment
)
171 if ( attachment
->isUri() ) {
172 KToolInvocation::invokeBrowser( attachment
->uri() );
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 );
182 i18n( "Unable to create a temporary file for the attachment." ) );
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
*)) );
203 info
.attachmentName
= attachmentName
;
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(
223 i18n( "%1 already exists. Do you want to overwrite it?",
224 saveAsFile
) ) == KMessageBox::No
) ) ) {
229 if ( attachment
->isUri() ) {
230 // save the attachment url
231 stat
= KIO::NetAccess::file_copy( attachment
->uri(), KUrl( saveAsFile
) );
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() );
244 i18n( "Unable to create a temporary file for the attachment." ) );
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
*)) );
266 info
.attachmentName
= attachmentName
;
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() ) ) {
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() ) ) {
307 emit
viewFinished( info
.uid
, info
.attachmentName
, success
);
308 d
->mJobToReceivedInfo
.remove( job
);
311 } // namespace CalendarSupport