krop's commit fixes my problem in a better way, reverting
[kdepim.git] / korganizer / koeditorattachments.cpp
blobe1dc55d2ba0e1b3a0ae9b34c101cbe09a66ee0d6
1 /*
2 This file is part of KOrganizer.
4 Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (C) 2005 Reinhold Kainhofer <reinhold@kainhofer.com>
6 Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 As a special exception, permission is given to link this program
23 with any edition of Qt, and distribute the resulting executable,
24 without including the source code for Qt in the source distribution.
27 #include "koeditorattachments.h"
29 #include <libkdepim/kdepimprotocols.h>
30 #include <libkdepim/kvcarddrag.h>
32 #include <KCal/Attachment>
33 #include <KCal/Incidence>
35 #include <K3IconView>
36 #include <KAction>
37 #include <KActionCollection>
38 #include <KLineEdit>
39 #include <KLocale>
40 #include <KMenu>
41 #include <KMessageBox>
42 #include <KRun>
43 #include <KSeparator>
44 #include <KTemporaryFile>
45 #include <KUrlRequester>
46 #include <KIO/Job>
47 #include <KIO/JobUiDelegate>
48 #include <KIO/NetAccess>
50 #include <Q3IconViewItem>
51 #include <QApplication>
52 #include <QCheckBox>
53 #include <QClipboard>
54 #include <QDrag>
55 #include <QDragEnterEvent>
56 #include <QGridLayout>
57 #include <QLabel>
58 #include <KProtocolManager>
59 #include <QSpacerItem>
60 #include <QStyle>
61 #include <QTimer>
62 #include <QVBoxLayout>
64 class AttachmentIconItem : public K3IconViewItem
66 public:
67 AttachmentIconItem( KCal::Attachment *att, Q3IconView *parent )
68 : K3IconViewItem( parent )
70 if ( att ) {
71 mAttachment = new KCal::Attachment( *att );
72 } else {
73 mAttachment = new KCal::Attachment( QString() );
75 readAttachment();
77 ~AttachmentIconItem() { delete mAttachment; }
78 KCal::Attachment *attachment() const
80 return mAttachment;
82 const QString uri() const
84 return mAttachment->uri();
86 void setUri( const QString &uri )
88 mAttachment->setUri( uri );
89 readAttachment();
91 void setData( const QByteArray &data )
93 mAttachment->setDecodedData( data );
94 readAttachment();
96 const QString mimeType() const
98 return mAttachment->mimeType();
100 void setMimeType( const QString &mime )
102 mAttachment->setMimeType( mime );
103 readAttachment();
105 const QString label() const
107 return mAttachment->label();
109 void setLabel( const QString &description )
111 mAttachment->setLabel( description );
112 readAttachment();
114 bool isBinary() const
116 return mAttachment->isBinary();
118 QPixmap icon() const
120 return icon( KMimeType::mimeType( mAttachment->mimeType() ),
121 mAttachment->uri(), mAttachment->isBinary() );
123 static QPixmap icon( KMimeType::Ptr mimeType, const QString &uri,
124 bool binary = false )
126 QString iconStr = mimeType->iconName( uri );
127 QStringList overlays;
128 if ( !uri.isEmpty() && !binary ) {
129 overlays << "emblem-link";
132 return KIconLoader::global()->loadIcon( iconStr, KIconLoader::Desktop, 0,
133 KIconLoader::DefaultState,
134 overlays );
137 void readAttachment()
139 if ( mAttachment->label().isEmpty() ) {
140 if ( mAttachment->isUri() ) {
141 setText( mAttachment->uri() );
142 } else {
143 setText( i18nc( "@label attachment contains binary data", "[Binary data]" ) );
145 } else {
146 setText( mAttachment->label() );
149 setRenameEnabled( true );
151 if ( mAttachment->mimeType().isEmpty() ||
152 !( KMimeType::mimeType( mAttachment->mimeType() ) ) ) {
153 KMimeType::Ptr mimeType;
154 if ( mAttachment->isUri() ) {
155 mimeType = KMimeType::findByUrl( mAttachment->uri() );
156 } else {
157 mimeType = KMimeType::findByContent( mAttachment->decodedData() );
159 mAttachment->setMimeType( mimeType->name() );
162 setPixmap( icon() );
165 private:
166 KCal::Attachment *mAttachment;
169 AttachmentEditDialog::AttachmentEditDialog( AttachmentIconItem *item,
170 QWidget *parent, bool modal )
171 : KDialog ( parent ), mItem( item ), mURLRequester( 0 )
173 // based loosely on KPropertiesDialog code
174 QWidget *page = new QWidget(this);
175 setMainWidget( page );
176 setCaption( i18nc( "@title", "Properties for %1",
177 item->label().isEmpty() ? item->uri() : item->label() ) );
178 setButtons( KDialog::Ok | KDialog::Cancel );
179 setDefaultButton( KDialog::Ok );
180 setModal( modal );
181 QVBoxLayout *vbl = new QVBoxLayout( page );
182 vbl->setSpacing( KDialog::spacingHint() );
183 vbl->setMargin( 0 );
184 QGridLayout *grid = new QGridLayout();
185 grid->setColumnStretch( 0, 0 );
186 grid->setColumnStretch( 1, 0 );
187 grid->setColumnStretch( 2, 1 );
188 grid->addItem( new QSpacerItem( KDialog::spacingHint(), 0 ), 0, 1 );
189 vbl->addLayout( grid );
191 mIcon = new QLabel( page );
192 int bsize = 66 + 2 * mIcon->style()->pixelMetric( QStyle::PM_ButtonMargin );
193 mIcon->setFixedSize( bsize, bsize );
194 mIcon->setPixmap( item->icon() );
195 grid->addWidget( mIcon, 0, 0, Qt::AlignLeft );
197 mLabelEdit = new KLineEdit( page );
198 mLabelEdit->setText( item->label().isEmpty() ? item->uri() : item->label() );
199 mLabelEdit->setClickMessage( i18nc( "@label", "Attachment name" ) );
200 mLabelEdit->setToolTip(
201 i18nc( "@info:tooltip", "Give the attachment a name" ) );
202 mLabelEdit->setWhatsThis(
203 i18nc( "@info:whatsthis", "Type any string you desire here for the name of the attachment" ) );
204 grid->addWidget( mLabelEdit, 0, 2 );
206 KSeparator *sep = new KSeparator( Qt::Horizontal, page );
207 grid->addWidget( sep, 1, 0, 1, 3 );
209 QLabel *label = new QLabel( i18nc( "@label", "Type:" ), page );
210 grid->addWidget( label, 2, 0 );
211 QString typecomment = item->mimeType().isEmpty() ?
212 i18nc( "@label unknown mimetype", "Unknown" ) :
213 KMimeType::mimeType( item->mimeType() )->comment();
214 mTypeLabel = new QLabel( typecomment, page );
215 grid->addWidget( mTypeLabel, 2, 2 );
216 mMimeType = KMimeType::mimeType( item->mimeType() );
218 mInline = new QCheckBox( i18nc( "@option:check", "Store attachment inline" ), page );
219 grid->addWidget( mInline, 3, 0, 1, 3 );
220 mInline->setChecked( item->isBinary() );
221 mInline->setToolTip(
222 i18nc( "@info:tooltip", "Store the attachment file inside the calendar" ) );
223 mInline->setWhatsThis(
224 i18nc( "@info:whatsthis",
225 "Checking this option will cause the attachment to be stored inside "
226 "your calendar, which can take a lot of space depending on the size "
227 "of the attachment. If this option is not checked, then only a link "
228 "pointing to the attachment will be stored. Do not use a link for "
229 "attachments that change often or may be moved (or removed) from "
230 "their current location." ) );
232 if ( item->attachment()->isUri() ) {
233 label = new QLabel( i18nc( "@label", "Location:" ), page );
234 grid->addWidget( label, 4, 0 );
235 mURLRequester = new KUrlRequester( item->uri(), page );
236 mURLRequester->setToolTip(
237 i18nc( "@info:tooltip", "Provide a location for the attachment file" ) );
238 mURLRequester->setWhatsThis(
239 i18nc( "@info:whatsthis",
240 "Enter the path to the attachment file or use the file browser "
241 "by pressing the adjacent button" ) );
242 grid->addWidget( mURLRequester, 4, 2 );
243 connect( mURLRequester, SIGNAL(urlSelected(const KUrl &)),
244 SLOT(urlChanged(const KUrl &)) );
245 connect( mURLRequester, SIGNAL( textChanged( const QString& ) ),
246 SLOT( urlChanged( const QString& ) ) );
247 urlChanged( item->uri() );
248 } else {
249 grid->addWidget( new QLabel( i18nc( "@label", "Size:" ), page ), 4, 0 );
250 grid->addWidget( new QLabel( QString::fromLatin1( "%1 (%2)" ).
251 arg( KIO::convertSize( item->attachment()->size() ) ).
252 arg( KGlobal::locale()->formatNumber(
253 item->attachment()->size(), 0 ) ), page ), 4, 2 );
255 vbl->addStretch( 10 );
258 void AttachmentEditDialog::slotApply()
260 if ( mLabelEdit->text().isEmpty() ) {
261 if ( mURLRequester->url().isLocalFile() ) {
262 mItem->setLabel( mURLRequester->url().fileName() );
263 } else {
264 mItem->setLabel( mURLRequester->url().url() );
266 } else {
267 mItem->setLabel( mLabelEdit->text() );
269 if ( mItem->label().isEmpty() ) {
270 mItem->setLabel( i18nc( "@label", "New attachment" ) );
272 mItem->setMimeType( mMimeType->name() );
273 if ( mURLRequester ) {
274 if ( mInline->isChecked() ) {
275 QString tmpFile;
276 if ( KIO::NetAccess::download( mURLRequester->url(), tmpFile, this ) ) {
277 QFile f( tmpFile );
278 if ( !f.open( QIODevice::ReadOnly ) ) {
279 return;
281 QByteArray data = f.readAll();
282 f.close();
283 mItem->setData( data );
285 KIO::NetAccess::removeTempFile( tmpFile );
286 } else {
287 mItem->setUri( mURLRequester->url().url() );
292 void AttachmentEditDialog::accept()
294 slotApply();
295 KDialog::accept();
298 void AttachmentEditDialog::urlChanged( const QString &url )
300 enableButtonOk( !url.isEmpty() );
303 void AttachmentEditDialog::urlChanged( const KUrl &url )
305 mMimeType = KMimeType::findByUrl( url );
306 mTypeLabel->setText( mMimeType->comment() );
307 mIcon->setPixmap( AttachmentIconItem::icon( mMimeType, url.path() ) );
310 class AttachmentIconView : public K3IconView
312 friend class KOEditorAttachments;
313 public:
314 AttachmentIconView( QWidget *parent ) : K3IconView( parent )
316 setAcceptDrops( true );
317 setSelectionMode( Q3IconView::Extended );
318 setMode( K3IconView::Select );
319 setItemTextPos( Q3IconView::Right );
320 setArrangement( Q3IconView::LeftToRight );
321 setMaxItemWidth( qMax( maxItemWidth(), 250 ) );
324 KUrl tempFileForAttachment( KCal::Attachment *attachment )
326 if ( mTempFiles.contains( attachment ) ) {
327 return mTempFiles.value( attachment );
329 KTemporaryFile *file = new KTemporaryFile();
330 file->setParent( this );
332 QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
334 if ( !patterns.empty() ) {
335 file->setSuffix( QString( patterns.first() ).remove( '*' ) );
337 file->setAutoRemove( true );
338 file->open();
339 // read-only not to give the idea that it could be written to
340 file->setPermissions( QFile::ReadUser );
341 file->write( QByteArray::fromBase64( attachment->data() ) );
342 mTempFiles.insert( attachment, file->fileName() );
343 file->close();
344 return mTempFiles.value( attachment );
347 protected:
349 QMimeData *mimeData()
351 // create a list of the URL:s that we want to drag
352 KUrl::List urls;
353 QStringList labels;
354 for ( Q3IconViewItem *it = firstItem(); it; it = it->nextItem() ) {
355 if ( it->isSelected() ) {
356 AttachmentIconItem *item = static_cast<AttachmentIconItem *>( it );
357 if ( item->isBinary() ) {
358 urls.append( tempFileForAttachment( item->attachment() ) );
359 } else {
360 urls.append( item->uri() );
362 labels.append( KUrl::toPercentEncoding( item->label() ) );
365 if ( selectionMode() == Q3IconView::NoSelection ) {
366 AttachmentIconItem *item = static_cast<AttachmentIconItem *>( currentItem() );
367 if ( item ) {
368 urls.append( item->uri() );
369 labels.append( KUrl::toPercentEncoding( item->label() ) );
373 QMap<QString, QString> metadata;
374 metadata["labels"] = labels.join( ":" );
376 QMimeData *mimeData = new QMimeData;
377 urls.populateMimeData( mimeData, metadata );
378 return mimeData;
381 #ifdef __GNUC__
382 #warning Port to QDrag instead of Q3DragObject once we port the view from K3IconView
383 #endif
384 virtual Q3DragObject *dragObject ()
386 int count = 0;
387 for ( Q3IconViewItem *it = firstItem(); it; it = it->nextItem() ) {
388 if ( it->isSelected() ) {
389 ++count;
393 QPixmap pixmap;
394 if ( count > 1 ) {
395 pixmap = KIconLoader::global()->loadIcon( "mail-attachment", KIconLoader::Desktop );
397 if ( pixmap.isNull() ) {
398 pixmap = static_cast<AttachmentIconItem *>( currentItem() )->icon();
401 QPoint hotspot( pixmap.width() / 2, pixmap.height() / 2 );
403 QDrag *drag = new QDrag( this );
404 drag->setMimeData( mimeData() );
406 drag->setPixmap( pixmap );
407 drag->setHotSpot( hotspot );
408 drag->exec( Qt::CopyAction );
409 return 0;
412 private:
413 QHash<KCal::Attachment *, KUrl> mTempFiles;
416 KOEditorAttachments::KOEditorAttachments( int spacing, QWidget *parent )
417 : QWidget( parent )
419 QBoxLayout *topLayout = new QHBoxLayout( this );
420 topLayout->setSpacing( spacing );
422 QLabel *label = new QLabel( i18nc( "@label", "Attachments:" ), this );
423 topLayout->addWidget( label );
425 mAttachments = new AttachmentIconView( this );
426 mAttachments->setWhatsThis( i18nc( "@info:whatsthis",
427 "Displays items (files, mail, etc.) that "
428 "have been associated with this event or to-do." ) );
429 mAttachments->setItemsMovable( false );
430 mAttachments->setSelectionMode( Q3IconView::Extended );
431 topLayout->addWidget( mAttachments );
432 connect( mAttachments, SIGNAL(returnPressed(Q3IconViewItem *)),
433 SLOT(showAttachment(Q3IconViewItem *)) );
434 connect( mAttachments, SIGNAL(doubleClicked(Q3IconViewItem *)),
435 SLOT(showAttachment(Q3IconViewItem *)) );
436 connect( mAttachments, SIGNAL(itemRenamed(Q3IconViewItem *,const QString &)),
437 SLOT(slotItemRenamed(Q3IconViewItem *,const QString &)) );
438 connect( mAttachments, SIGNAL(dropped(QDropEvent *,const Q3ValueList<Q3IconDragItem> &)),
439 SLOT(dropped(QDropEvent *,const Q3ValueList<Q3IconDragItem> &)) );
440 connect( mAttachments, SIGNAL(selectionChanged()),
441 SLOT(selectionChanged()) );
442 connect( mAttachments, SIGNAL(contextMenuRequested(Q3IconViewItem *,const QPoint &)),
443 SLOT(contextMenu(Q3IconViewItem *,const QPoint &)) );
445 QPushButton *addButton = new QPushButton( this );
446 addButton->setIcon( KIcon( "list-add" ) );
447 addButton->setToolTip( i18nc( "@info:tooltip", "Add an attachment" ) );
448 addButton->setWhatsThis( i18nc( "@info:whatsthis",
449 "Shows a dialog used to select an attachment "
450 "to add to this event or to-do as link or as "
451 "inline data." ) );
452 topLayout->addWidget( addButton );
453 connect( addButton, SIGNAL(clicked()), SLOT(slotAdd()) );
455 mRemoveBtn = new QPushButton( this );
456 mRemoveBtn->setIcon( KIcon( "list-remove" ) );
457 mRemoveBtn->setToolTip( i18nc( "@info:tooltip", "Remove the selected attachment" ) );
458 mRemoveBtn->setWhatsThis( i18nc( "@info:whatsthis",
459 "Removes the attachment selected in the "
460 "list above from this event or to-do." ) );
461 topLayout->addWidget( mRemoveBtn );
462 connect( mRemoveBtn, SIGNAL(clicked()), SLOT(slotRemove()) );
464 KActionCollection *ac = new KActionCollection( this );
465 ac->addAssociatedWidget( this );
467 mPopupMenu = new KMenu( this );
469 mOpenAction = new KAction( i18nc( "@action:inmenu open the attachment in a viewer",
470 "&Open" ), this );
471 connect( mOpenAction, SIGNAL(triggered(bool)), this, SLOT(slotShow()) );
472 ac->addAction( "view", mOpenAction );
473 mPopupMenu->addAction( mOpenAction );
474 mPopupMenu->addSeparator();
476 mCopyAction = KStandardAction::copy( this, SLOT(slotCopy()), ac );
477 mPopupMenu->addAction( mCopyAction );
478 mCutAction = KStandardAction::cut( this, SLOT(slotCut()), ac );
479 mPopupMenu->addAction( mCutAction );
480 KAction *action = KStandardAction::paste( this, SLOT(slotPaste()), ac );
481 mPopupMenu->addAction( action );
482 mPopupMenu->addSeparator();
484 mDeleteAction = new KAction( i18nc( "@action:inmenu remove the attachment",
485 "&Remove" ), this );
486 connect( mDeleteAction, SIGNAL(triggered(bool)), this, SLOT(slotRemove()) );
487 ac->addAction( "remove", mDeleteAction );
488 mPopupMenu->addAction( mDeleteAction );
489 mPopupMenu->addSeparator();
491 mEditAction = new KAction( i18nc( "@action:inmenu show a dialog used to edit the attachment",
492 "&Properties..." ), this );
493 connect( mEditAction, SIGNAL(triggered(bool)), this, SLOT(slotEdit()) );
494 ac->addAction( "edit", mEditAction );
495 mPopupMenu->addAction( mEditAction );
497 selectionChanged();
498 setAcceptDrops( true );
501 KOEditorAttachments::~KOEditorAttachments()
505 bool KOEditorAttachments::hasAttachments()
507 return mAttachments->count() > 0;
510 void KOEditorAttachments::dragEnterEvent( QDragEnterEvent *event )
512 const QMimeData *md = event->mimeData();
513 event->setAccepted( KUrl::List::canDecode( md ) || md->hasText() );
516 void KOEditorAttachments::handlePasteOrDrop( const QMimeData *mimeData )
518 KUrl::List urls;
519 bool probablyWeHaveUris = false;
520 bool weCanCopy = true;
521 QStringList labels;
523 if ( KPIM::KVCardDrag::canDecode( mimeData ) ) {
524 KABC::Addressee::List addressees;
525 KPIM::KVCardDrag::fromMimeData( mimeData, addressees );
526 for ( KABC::Addressee::List::ConstIterator it = addressees.constBegin();
527 it != addressees.constEnd(); ++it ) {
528 urls.append( KDEPIMPROTOCOL_CONTACT + ( *it ).uid() );
529 // there is some weirdness about realName(), hence fromUtf8
530 labels.append( QString::fromUtf8( ( *it ).realName().toLatin1() ) );
532 probablyWeHaveUris = true;
533 } else if ( KUrl::List::canDecode( mimeData ) ) {
534 QMap<QString,QString> metadata;
536 urls = KUrl::List::fromMimeData( mimeData, &metadata );
537 probablyWeHaveUris = true;
538 labels = metadata["labels"].split( ':', QString::SkipEmptyParts );
539 for ( QStringList::Iterator it = labels.begin(); it != labels.end(); ++it ) {
540 *it = KUrl::fromPercentEncoding( (*it).toLatin1() );
542 } else if ( mimeData->hasText() ) {
543 QString text = mimeData->text();
544 QStringList lst = text.split( '\n', QString::SkipEmptyParts );
545 for ( QStringList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
546 urls.append( *it );
548 probablyWeHaveUris = true;
551 KMenu menu( this );
552 QAction *linkAction = 0, *cancelAction;
553 if ( probablyWeHaveUris ) {
554 linkAction = menu.addAction( i18nc( "@action:inmenu", "&Link here" ) );
555 // we need to check if we can reasonably expect to copy the objects
556 for ( KUrl::List::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it ) {
557 if ( !( weCanCopy = KProtocolManager::supportsReading( *it ) ) ) {
558 break; // either we can copy them all, or no copying at all
561 if ( weCanCopy ) {
562 menu.addAction( i18nc( "@action:inmenu", "&Copy here" ) );
564 } else {
565 menu.addAction( i18nc( "@action:inmenu", "&Copy here" ) );
568 menu.addSeparator();
569 cancelAction = menu.addAction( i18nc( "@action:inmenu", "C&ancel" ) );
571 QAction *ret = menu.exec( QCursor::pos() );
572 if ( linkAction == ret ) {
573 QStringList::ConstIterator jt = labels.constBegin();
574 for ( KUrl::List::ConstIterator it = urls.constBegin();
575 it != urls.constEnd(); ++it ) {
576 addAttachment( (*it).url(), QString(), ( jt == labels.constEnd() ?
577 QString() : *( jt++ ) ) );
579 } else if ( cancelAction != ret ) {
580 if ( probablyWeHaveUris ) {
581 for ( KUrl::List::ConstIterator it = urls.constBegin();
582 it != urls.constEnd(); ++it ) {
583 KIO::Job *job = KIO::storedGet( *it );
584 connect( job, SIGNAL(result(KJob *)), SLOT(downloadComplete(KJob *)) );
586 } else { // we take anything
587 addAttachment( mimeData->data( mimeData->formats().first() ), mimeData->formats().first(),
588 KMimeType::mimeType( mimeData->formats().first() )->name() );
593 void KOEditorAttachments::dropEvent( QDropEvent *event )
595 handlePasteOrDrop( event->mimeData() );
598 void KOEditorAttachments::downloadComplete( KJob *job )
600 if ( job->error() ) {
601 static_cast<KIO::Job*>(job)->ui()->setWindow( this );
602 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
603 } else {
604 addAttachment( static_cast<KIO::StoredTransferJob *>( job )->data(),
605 QString(),
606 static_cast<KIO::SimpleJob *>( job )->url().fileName() );
610 void KOEditorAttachments::dropped ( QDropEvent *e, const Q3ValueList<Q3IconDragItem> &lst )
612 Q_UNUSED( lst );
613 dropEvent( e );
616 void KOEditorAttachments::showAttachment( Q3IconViewItem *item )
618 AttachmentIconItem *attitem = static_cast<AttachmentIconItem*>( item );
619 if ( !attitem || !attitem->attachment() ) {
620 return;
623 KCal::Attachment *att = attitem->attachment();
624 if ( att->isUri() ) {
625 emit openURL( att->uri() );
626 } else {
627 KRun::runUrl( mAttachments->tempFileForAttachment( att ), att->mimeType(), 0, true );
631 void KOEditorAttachments::slotAdd()
633 AttachmentIconItem *item = new AttachmentIconItem( 0, mAttachments );
635 QPointer<AttachmentEditDialog> dlg = new AttachmentEditDialog( item, mAttachments );
636 dlg->setCaption( i18nc( "@title", "Add Attachment" ) );
637 if ( dlg->exec() == KDialog::Rejected ) {
638 delete item;
640 delete dlg;
643 void KOEditorAttachments::slotEdit()
645 for ( Q3IconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
646 if ( item->isSelected() ) {
647 AttachmentIconItem *attitem = static_cast<AttachmentIconItem*>( item );
648 if ( !attitem || !attitem->attachment() ) {
649 return;
652 AttachmentEditDialog *dialog = new AttachmentEditDialog( attitem, mAttachments, false );
653 dialog->setModal( false );
654 connect( dialog, SIGNAL(hidden()), dialog, SLOT(delayedDestruct()) );
655 dialog->show();
660 void KOEditorAttachments::slotRemove()
662 QList<Q3IconViewItem *> toDelete;
663 for ( Q3IconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) {
664 if ( it->isSelected() ) {
665 AttachmentIconItem *item = static_cast<AttachmentIconItem *>( it );
667 if ( !item ) {
668 continue;
671 if ( KMessageBox::questionYesNo(
672 this,
673 i18nc( "@info",
674 "Do you really want to remove the attachment labeled \"%1\"?", item->label() ),
675 i18nc( "@title:window", "Remove Attachment?" ) ) == KMessageBox::Yes ) {
676 toDelete.append( it );
681 for ( QList<Q3IconViewItem *>::ConstIterator it = toDelete.constBegin();
682 it != toDelete.constEnd(); ++it ) {
683 delete *it;
687 void KOEditorAttachments::slotShow()
689 for ( Q3IconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
690 if ( item->isSelected() ) {
691 showAttachment( item );
696 void KOEditorAttachments::setDefaults()
698 mAttachments->clear();
701 void KOEditorAttachments::addAttachment( const QString &uri,
702 const QString &mimeType,
703 const QString &label,
704 bool binary )
706 if ( !binary ) {
707 AttachmentIconItem *item = new AttachmentIconItem( 0, mAttachments );
708 item->setUri( uri );
709 item->setLabel( label );
710 if ( mimeType.isEmpty() ) {
711 if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) {
712 item->setMimeType( "text/directory" );
713 } else if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) {
714 item->setMimeType( "message/rfc822" );
715 } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) {
716 item->setMimeType( "text/calendar" );
717 } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) {
718 item->setMimeType( "message/news" );
719 } else {
720 item->setMimeType( KMimeType::findByUrl( uri )->name() );
722 } else {
723 QString tmpFile;
724 if ( KIO::NetAccess::download( uri, tmpFile, this ) ) {
725 QFile f( tmpFile );
726 if ( !f.open( QIODevice::ReadOnly ) ) {
727 return;
729 const QByteArray data = f.readAll();
730 f.close();
731 addAttachment( data, mimeType, label );
733 KIO::NetAccess::removeTempFile( tmpFile );
735 } else {
739 void KOEditorAttachments::addAttachment( const QByteArray &data,
740 const QString &mimeType,
741 const QString &label )
743 AttachmentIconItem *item = new AttachmentIconItem( 0, mAttachments );
745 QString nlabel = label;
746 if ( mimeType == "message/rfc822" ) {
747 // mail message. try to set the label from the mail Subject:
748 QString line( data );
749 int index = line.indexOf( "Subject:" );
750 if ( index >= 0 ) {
751 QString substr = line.mid( index, 100 );
752 int len = substr.indexOf( '\n' );
753 nlabel = substr.left( len ).remove( "Subject:" ).
754 simplified().replace( ' ', '_' ).section( '_', 0, 3 );
758 item->setData( data );
759 item->setLabel( nlabel );
760 if ( mimeType.isEmpty() ) {
761 item->setMimeType( KMimeType::findByContent( data )->name() );
762 } else {
763 item->setMimeType( mimeType );
767 void KOEditorAttachments::addAttachment( KCal::Attachment *attachment )
769 new AttachmentIconItem( attachment, mAttachments );
772 void KOEditorAttachments::readIncidence( KCal::Incidence *i )
774 mAttachments->clear();
776 KCal::Attachment::List attachments = i->attachments();
777 KCal::Attachment::List::ConstIterator it;
778 for ( it = attachments.constBegin(); it != attachments.constEnd(); ++it ) {
779 addAttachment( (*it) );
782 mUid = i->uid();
784 if ( mAttachments->count() > 0 ) {
785 QTimer::singleShot( 0, mAttachments, SLOT(arrangeItemsInGrid()) );
789 void KOEditorAttachments::fillIncidence( KCal::Incidence *i )
791 i->clearAttachments();
793 Q3IconViewItem *item;
794 AttachmentIconItem *attitem;
795 for ( item = mAttachments->firstItem(); item; item = item->nextItem() ) {
796 attitem = static_cast<AttachmentIconItem*>(item);
797 if ( attitem ) {
798 i->addAttachment( new KCal::Attachment( *( attitem->attachment() ) ) );
803 void KOEditorAttachments::slotItemRenamed ( Q3IconViewItem *item, const QString &text )
805 static_cast<AttachmentIconItem *>( item )->setLabel( text );
808 void KOEditorAttachments::applyChanges()
812 void KOEditorAttachments::slotCopy()
814 QApplication::clipboard()->setMimeData( mAttachments->mimeData(), QClipboard::Clipboard );
817 void KOEditorAttachments::slotCut()
819 slotCopy();
820 slotRemove();
823 void KOEditorAttachments::slotPaste()
825 handlePasteOrDrop( QApplication::clipboard()->mimeData() );
828 void KOEditorAttachments::selectionChanged()
830 bool selected = false;
831 for ( Q3IconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
832 if ( item->isSelected() ) {
833 selected = true;
834 break;
837 mRemoveBtn->setEnabled( selected );
840 void KOEditorAttachments::contextMenu( Q3IconViewItem *item, const QPoint &pos )
842 const bool enable = item != 0;
843 mOpenAction->setEnabled( enable );
844 mCopyAction->setEnabled( enable );
845 mCutAction->setEnabled( enable );
846 mDeleteAction->setEnabled( enable );
847 mEditAction->setEnabled( enable );
848 mPopupMenu->exec( pos );
851 #include "koeditorattachments.moc"