00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "koeditorattachments.h"
00027
00028 #include <libkcal/incidence.h>
00029 #include <libkdepim/kpimurlrequesterdlg.h>
00030 #include <libkdepim/kfileio.h>
00031 #include <libkdepim/kdepimprotocols.h>
00032 #include <libkdepim/maillistdrag.h>
00033 #include <libkdepim/kvcarddrag.h>
00034 #include <libkdepim/kdepimprotocols.h>
00035
00036 #include <klocale.h>
00037 #include <kdebug.h>
00038 #include <kmdcodec.h>
00039 #include <kmessagebox.h>
00040 #include <krun.h>
00041 #include <kurldrag.h>
00042 #include <ktempfile.h>
00043 #include <ktempdir.h>
00044 #include <kio/netaccess.h>
00045 #include <kmimetype.h>
00046 #include <kiconloader.h>
00047 #include <kfiledialog.h>
00048 #include <kstdaction.h>
00049 #include <kactioncollection.h>
00050 #include <kpopupmenu.h>
00051 #include <kprotocolinfo.h>
00052 #include <klineedit.h>
00053 #include <kseparator.h>
00054 #include <kurlrequester.h>
00055 #include <libkmime/kmime_message.h>
00056
00057 #include <qcheckbox.h>
00058 #include <qfile.h>
00059 #include <qlabel.h>
00060 #include <qlayout.h>
00061 #include <qlistview.h>
00062 #include <qpushbutton.h>
00063 #include <qdragobject.h>
00064 #include <qtooltip.h>
00065 #include <qwhatsthis.h>
00066 #include <qapplication.h>
00067 #include <qclipboard.h>
00068
00069 #include <cassert>
00070 #include <cstdlib>
00071
00072 class AttachmentListItem : public KIconViewItem
00073 {
00074 public:
00075 AttachmentListItem( KCal::Attachment*att, QIconView *parent ) :
00076 KIconViewItem( parent )
00077 {
00078 if ( att ) {
00079 mAttachment = new KCal::Attachment( *att );
00080 } else {
00081 mAttachment = new KCal::Attachment( '\0' );
00082
00083 }
00084 readAttachment();
00085 setDragEnabled( true );
00086 }
00087 ~AttachmentListItem() { delete mAttachment; }
00088 KCal::Attachment *attachment() const { return mAttachment; }
00089
00090 const QString uri() const
00091 {
00092 return mAttachment->uri();
00093 }
00094 void setUri( const QString &uri )
00095 {
00096 mAttachment->setUri( uri );
00097 readAttachment();
00098 }
00099 void setData( const QByteArray data )
00100 {
00101 mAttachment->setDecodedData( data );
00102 readAttachment();
00103 }
00104 const QString mimeType() const
00105 {
00106 return mAttachment->mimeType();
00107 }
00108 void setMimeType( const QString &mime )
00109 {
00110 mAttachment->setMimeType( mime );
00111 readAttachment();
00112 }
00113 const QString label() const
00114 {
00115 return mAttachment->label();
00116 }
00117 void setLabel( const QString &label )
00118 {
00119 mAttachment->setLabel( label );
00120 readAttachment();
00121 }
00122 bool isBinary() const
00123 {
00124 return mAttachment->isBinary();
00125 }
00126 QPixmap icon() const
00127 {
00128 return icon( KMimeType::mimeType( mAttachment->mimeType() ),
00129 mAttachment->uri() );
00130 }
00131 static QPixmap icon( KMimeType::Ptr mimeType, const QString &uri )
00132 {
00133 QString iconStr = mimeType->icon( uri, false );
00134 return KGlobal::iconLoader()->loadIcon( iconStr, KIcon::Small );
00135 }
00136 void readAttachment()
00137 {
00138 if ( mAttachment->label().isEmpty() ) {
00139 if ( mAttachment->isUri() ) {
00140 setText( mAttachment->uri() );
00141 } else {
00142 setText( i18n( "[Binary data]" ) );
00143 }
00144 } else {
00145 setText( mAttachment->label() );
00146 }
00147 if ( mAttachment->mimeType().isEmpty() ||
00148 !( KMimeType::mimeType( mAttachment->mimeType() ) ) ) {
00149 KMimeType::Ptr mimeType;
00150 if ( mAttachment->isUri() ) {
00151 mimeType = KMimeType::findByURL( mAttachment->uri() );
00152 } else {
00153 mimeType = KMimeType::findByContent( mAttachment->decodedData() );
00154 }
00155 mAttachment->setMimeType( mimeType->name() );
00156 }
00157
00158 setPixmap( icon() );
00159 }
00160
00161 private:
00162 KCal::Attachment *mAttachment;
00163 };
00164
00165 AttachmentEditDialog::AttachmentEditDialog( AttachmentListItem *item,
00166 QWidget *parent )
00167 : KDialogBase ( Plain, i18n( "Add Attachment" ), Ok|Cancel, Ok, parent, 0, false, false ),
00168 mItem( item ), mURLRequester( 0 )
00169 {
00170 QFrame *topFrame = plainPage();
00171 QVBoxLayout *vbl = new QVBoxLayout( topFrame, 0, spacingHint() );
00172
00173 QGridLayout *grid = new QGridLayout();
00174 grid->setColStretch( 0, 0 );
00175 grid->setColStretch( 1, 0 );
00176 grid->setColStretch( 2, 1 );
00177 vbl->addLayout( grid );
00178
00179 mIcon = new QLabel( topFrame );
00180 mIcon->setPixmap( item->icon() );
00181 grid->addWidget( mIcon, 0, 0 );
00182
00183 mLabelEdit = new KLineEdit( topFrame );
00184 mLabelEdit->setText( item->label().isEmpty() ? item->uri() : item->label() );
00185 mLabelEdit->setClickMessage( i18n( "Attachment name" ) );
00186 QToolTip::add( mLabelEdit, i18n( "Give the attachment a name" ) );
00187 QWhatsThis::add( mLabelEdit,
00188 i18n( "Type any string you desire here for the name of the attachment" ) );
00189 grid->addMultiCellWidget( mLabelEdit, 0, 0, 1, 2 );
00190
00191 KSeparator *sep = new KSeparator( Qt::Horizontal, topFrame );
00192 grid->addMultiCellWidget( sep, 1, 1, 0, 2 );
00193
00194 QLabel *label = new QLabel( i18n( "Type:" ), topFrame );
00195 grid->addWidget( label, 2, 0 );
00196 QString typecomment = item->mimeType().isEmpty() ?
00197 i18n( "Unknown" ) :
00198 KMimeType::mimeType( item->mimeType() )->comment();
00199 mTypeLabel = new QLabel( typecomment, topFrame );
00200 grid->addWidget( mTypeLabel, 2, 1 );
00201 mMimeType = KMimeType::mimeType( item->mimeType() );
00202
00203 mInline = new QCheckBox( i18n( "Store attachment inline" ), topFrame );
00204 grid->addMultiCellWidget( mInline, 3, 3, 0, 2 );
00205 mInline->setChecked( item->isBinary() );
00206 QToolTip::add( mInline, i18n( "Store the attachment file inside the calendar" ) );
00207 QWhatsThis::add(
00208 mInline,
00209 i18n( "Checking this option will cause the attachment to be stored inside "
00210 "your calendar, which can take a lot of space depending on the size "
00211 "of the attachment. If this option is not checked, then only a link "
00212 "pointing to the attachment will be stored. Do not use a link for "
00213 "attachments that change often or may be moved (or removed) from "
00214 "their current location." ) );
00215
00216 if ( item->attachment()->isUri() || !item->attachment()->data() ) {
00217 label = new QLabel( i18n( "Location:" ), topFrame );
00218 grid->addWidget( label, 4, 0 );
00219 mURLRequester = new KURLRequester( item->uri(), topFrame );
00220 QToolTip::add( mURLRequester, i18n( "Provide a location for the attachment file" ) );
00221 QWhatsThis::add(
00222 mURLRequester,
00223 i18n( "Enter the path to the attachment file or use the "
00224 "file browser by pressing the adjacent button" ) );
00225 grid->addMultiCellWidget( mURLRequester, 4, 4, 1, 2 );
00226 connect( mURLRequester, SIGNAL(urlSelected(const QString &)),
00227 SLOT(urlSelected(const QString &)) );
00228 connect( mURLRequester, SIGNAL( textChanged( const QString& ) ),
00229 SLOT( urlChanged( const QString& ) ) );
00230 urlChanged( item->uri() );
00231 } else {
00232 uint size = item->attachment()->size();
00233 grid->addWidget( new QLabel( i18n( "Size:" ), topFrame ), 4, 0 );
00234 grid->addWidget( new QLabel( QString::fromLatin1( "%1 (%2)" ).
00235 arg( KIO::convertSize( size ) ).
00236 arg( KGlobal::locale()->formatNumber(
00237 size, 0 ) ), topFrame ), 4, 2 );
00238 }
00239 vbl->addStretch( 10 );
00240 }
00241
00242 void AttachmentEditDialog::slotApply()
00243 {
00244 if ( !mLabelEdit->text().isEmpty() ) {
00245 mItem->setLabel( mLabelEdit->text() );
00246 } else {
00247 if ( mURLRequester ) {
00248 KURL url( mURLRequester->url() );
00249 if ( url.isLocalFile() ) {
00250 mItem->setLabel( url.fileName() );
00251 } else {
00252 mItem->setLabel( url.url() );
00253 }
00254 }
00255 }
00256 if ( mItem->label().isEmpty() ) {
00257 mItem->setLabel( i18n( "New attachment" ) );
00258 }
00259 mItem->setMimeType( mMimeType->name() );
00260 if ( mURLRequester ) {
00261 KURL url( mURLRequester->url() );
00262
00263 QString correctedUrl = mURLRequester->url();
00264 if ( !url.isValid() ) {
00265
00266
00267
00268
00269
00270 correctedUrl = QDir::home().filePath( mURLRequester->url() );
00271 url = KURL( correctedUrl );
00272 if ( url.isValid() ) {
00273 urlSelected( correctedUrl );
00274 mItem->setMimeType( mMimeType->name() );
00275 }
00276 }
00277
00278 if ( mInline->isChecked() ) {
00279 QString tmpFile;
00280 if ( KIO::NetAccess::download( correctedUrl, tmpFile, this ) ) {
00281 QFile f( tmpFile );
00282 if ( !f.open( IO_ReadOnly ) ) {
00283 return;
00284 }
00285 QByteArray data = f.readAll();
00286 f.close();
00287 mItem->setData( data );
00288 }
00289 KIO::NetAccess::removeTempFile( tmpFile );
00290 } else {
00291 mItem->setUri( url.url() );
00292 }
00293 }
00294 }
00295
00296 void AttachmentEditDialog::accept()
00297 {
00298 slotApply();
00299 KDialog::accept();
00300 }
00301
00302 void AttachmentEditDialog::urlChanged( const QString &url )
00303 {
00304 enableButton( Ok, !url.isEmpty() );
00305 }
00306
00307 void AttachmentEditDialog::urlSelected( const QString &url )
00308 {
00309 KURL kurl( url );
00310 mMimeType = KMimeType::findByURL( kurl );
00311 mTypeLabel->setText( mMimeType->comment() );
00312 mIcon->setPixmap( AttachmentListItem::icon( mMimeType, kurl.path() ) );
00313 }
00314
00315 AttachmentIconView::AttachmentIconView( KOEditorAttachments* parent )
00316 : KIconView( parent ),
00317 mParent( parent )
00318 {
00319 setSelectionMode( QIconView::Extended );
00320 setMode( KIconView::Select );
00321 setItemTextPos( QIconView::Right );
00322 setArrangement( QIconView::LeftToRight );
00323 setMaxItemWidth( QMAX(maxItemWidth(), 250) );
00324 setMinimumHeight( QMAX(fontMetrics().height(), 16) + 12 );
00325
00326 connect( this, SIGNAL( dropped ( QDropEvent *, const QValueList<QIconDragItem> & ) ),
00327 this, SLOT( handleDrop( QDropEvent *, const QValueList<QIconDragItem> & ) ) );
00328 }
00329
00330 KURL AttachmentIconView::tempFileForAttachment( KCal::Attachment *attachment )
00331 {
00332 if ( mTempFiles.contains( attachment ) ) {
00333 return mTempFiles[attachment];
00334 }
00335 QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
00336
00337 KTempFile *file;
00338 if ( !patterns.empty() ) {
00339 file = new KTempFile( QString::null,
00340 QString( patterns.first() ).remove( '*' ),0600 );
00341 } else {
00342 file = new KTempFile( QString::null, QString::null, 0600 );
00343 }
00344 file->setAutoDelete( true );
00345 file->file()->open( IO_WriteOnly );
00346 QTextStream stream( file->file() );
00347 stream.writeRawBytes( attachment->decodedData().data(), attachment->size() );
00348 KURL url( file->name() );
00349 mTempFiles.insert( attachment, url );
00350 file->close();
00351 return mTempFiles[attachment];
00352 }
00353
00354 QDragObject *AttachmentIconView::mimeData()
00355 {
00356
00357 KURL::List urls;
00358 QStringList labels;
00359 for ( QIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
00360 if ( it->isSelected() ) {
00361 AttachmentListItem *item = static_cast<AttachmentListItem *>( it );
00362 if ( item->isBinary() ) {
00363 urls.append( tempFileForAttachment( item->attachment() ) );
00364 } else {
00365 urls.append( item->uri() );
00366 }
00367 labels.append( KURL::encode_string( item->label() ) );
00368 }
00369 }
00370 if ( selectionMode() == QIconView::NoSelection ) {
00371 AttachmentListItem *item = static_cast<AttachmentListItem *>( currentItem() );
00372 if ( item ) {
00373 urls.append( item->uri() );
00374 labels.append( KURL::encode_string( item->label() ) );
00375 }
00376 }
00377
00378 QMap<QString, QString> metadata;
00379 metadata["labels"] = labels.join( ":" );
00380
00381 KURLDrag *drag = new KURLDrag( urls, metadata );
00382 return drag;
00383 }
00384
00385 AttachmentIconView::~AttachmentIconView()
00386 {
00387 for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) {
00388 delete *it;
00389 }
00390 }
00391
00392 QDragObject * AttachmentIconView::dragObject()
00393 {
00394 KURL::List urls;
00395 for ( QIconViewItem *it = firstItem( ); it; it = it->nextItem( ) ) {
00396 if ( !it->isSelected() ) continue;
00397 AttachmentListItem * item = dynamic_cast<AttachmentListItem*>( it );
00398 if ( !item ) return 0;
00399 KCal::Attachment * att = item->attachment();
00400 assert( att );
00401 KURL url;
00402 if ( att->isUri() ) {
00403 url.setPath( att->uri() );
00404 } else {
00405 KTempDir *tempDir = new KTempDir();
00406 tempDir->setAutoDelete( true );
00407 mTempDirs.insert( tempDir );
00408 QByteArray encoded;
00409 encoded.duplicate( att->data(), strlen( att->data() ) );
00410 QByteArray decoded;
00411 KCodecs::base64Decode( encoded, decoded );
00412
00413
00414 unsigned int len = decoded.size();
00415 if ( len > 0 && decoded[len - 1] == 0 ) {
00416 decoded.truncate( len - 1 );
00417 }
00418 const QString fileName = tempDir->name( ) + '/' + att->label();
00419 KPIM::kByteArrayToFile( decoded, fileName, false, false, false );
00420 url.setPath( fileName );
00421 }
00422 urls << url;
00423 }
00424 KURLDrag *drag = new KURLDrag( urls, this );
00425 return drag;
00426 }
00427
00428 void AttachmentIconView::handleDrop( QDropEvent *event, const QValueList<QIconDragItem> & list )
00429 {
00430 Q_UNUSED( list );
00431 mParent->handlePasteOrDrop( event );
00432 }
00433
00434
00435 void AttachmentIconView::dragMoveEvent( QDragMoveEvent *event )
00436 {
00437 mParent->dragMoveEvent( event );
00438 }
00439
00440 void AttachmentIconView::contentsDragMoveEvent( QDragMoveEvent *event )
00441 {
00442 mParent->dragMoveEvent( event );
00443 }
00444
00445 void AttachmentIconView::contentsDragEnterEvent( QDragEnterEvent *event )
00446 {
00447 mParent->dragMoveEvent( event );
00448 }
00449
00450 void AttachmentIconView::dragEnterEvent( QDragEnterEvent *event )
00451 {
00452 mParent->dragEnterEvent( event );
00453 }
00454
00455 KOEditorAttachments::KOEditorAttachments( int spacing, QWidget *parent,
00456 const char *name )
00457 : QWidget( parent, name )
00458 {
00459 QBoxLayout *topLayout = new QHBoxLayout( this );
00460 topLayout->setSpacing( spacing );
00461
00462 QLabel *label = new QLabel( i18n("Attachments:"), this );
00463 topLayout->addWidget( label );
00464
00465 mAttachments = new AttachmentIconView( this );
00466 QWhatsThis::add( mAttachments,
00467 i18n("Displays a list of current items (files, mail, etc.) "
00468 "that have been associated with this event or to-do. ") );
00469 topLayout->addWidget( mAttachments );
00470 connect( mAttachments, SIGNAL( doubleClicked( QIconViewItem * ) ),
00471 SLOT( showAttachment( QIconViewItem * ) ) );
00472 connect( mAttachments, SIGNAL(selectionChanged()),
00473 SLOT(selectionChanged()) );
00474 connect( mAttachments, SIGNAL(contextMenuRequested(QIconViewItem*,const QPoint&)),
00475 SLOT(contextMenu(QIconViewItem*,const QPoint&)) );
00476
00477 QPushButton *addButton = new QPushButton( this );
00478 addButton->setIconSet( SmallIconSet( "add" ) );
00479 QToolTip::add( addButton, i18n( "Add an attachment" ) );
00480 QWhatsThis::add( addButton,
00481 i18n( "Shows a dialog used to select an attachment "
00482 "to add to this event or to-do as link or as "
00483 "inline data." ) );
00484 topLayout->addWidget( addButton );
00485 connect( addButton, SIGNAL(clicked()), SLOT(slotAdd()) );
00486
00487 mRemoveBtn = new QPushButton( this );
00488 mRemoveBtn->setIconSet( SmallIconSet( "remove" ) );
00489 QToolTip::add( mRemoveBtn, i18n("&Remove") );
00490 QWhatsThis::add( mRemoveBtn,
00491 i18n("Removes the attachment selected in the list above "
00492 "from this event or to-do.") );
00493 topLayout->addWidget( mRemoveBtn );
00494 connect( mRemoveBtn, SIGNAL(clicked()), SLOT(slotRemove()) );
00495
00496 mContextMenu = new KPopupMenu( this );
00497
00498 KActionCollection* ac = new KActionCollection( this, this );
00499
00500 mOpenAction = new KAction( i18n("Open"), 0, this, SLOT(slotShow()), ac );
00501 mOpenAction->plug( mContextMenu );
00502
00503 mSaveAsAction = new KAction( i18n( "Save As..." ), 0, this, SLOT(slotSaveAs()), ac );
00504 mSaveAsAction->plug( mContextMenu );
00505 mContextMenu->insertSeparator();
00506
00507 mCopyAction = KStdAction::copy(this, SLOT(slotCopy()), ac );
00508 mCopyAction->plug( mContextMenu );
00509 mCutAction = KStdAction::cut(this, SLOT(slotCut()), ac );
00510 mCutAction->plug( mContextMenu );
00511 KAction *action = KStdAction::paste(this, SLOT(slotPaste()), ac );
00512 action->plug( mContextMenu );
00513 mContextMenu->insertSeparator();
00514
00515 mDeleteAction = new KAction( i18n( "&Remove" ), 0, this, SLOT(slotRemove()), ac );
00516 mDeleteAction->plug( mContextMenu );
00517 mDeleteAction->setShortcut( Key_Delete );
00518 mContextMenu->insertSeparator();
00519
00520 mEditAction = new KAction( i18n( "&Properties..." ), 0, this, SLOT(slotEdit()), ac );
00521 mEditAction->plug( mContextMenu );
00522
00523 selectionChanged();
00524 setAcceptDrops( true );
00525 }
00526
00527 KOEditorAttachments::~KOEditorAttachments()
00528 {
00529 }
00530
00531 bool KOEditorAttachments::hasAttachments()
00532 {
00533 return mAttachments->count() != 0;
00534 }
00535
00536 void KOEditorAttachments::dragMoveEvent( QDragMoveEvent *event )
00537 {
00538 event->accept( KURLDrag::canDecode( event ) ||
00539 QTextDrag::canDecode( event ) ||
00540 KPIM::MailListDrag::canDecode( event ) ||
00541 KVCardDrag::canDecode( event ) );
00542 }
00543
00544 void KOEditorAttachments::dragEnterEvent( QDragEnterEvent* event )
00545 {
00546 dragMoveEvent( event );
00547 }
00548
00549 void KOEditorAttachments::handlePasteOrDrop( QMimeSource* source )
00550 {
00551 KURL::List urls;
00552 bool probablyWeHaveUris = false;
00553 bool weCanCopy = true;
00554 QStringList labels;
00555
00556 if ( KVCardDrag::canDecode( source ) ) {
00557 KABC::Addressee::List addressees;
00558 KVCardDrag::decode( source, addressees );
00559 for ( KABC::Addressee::List::ConstIterator it = addressees.constBegin();
00560 it != addressees.constEnd(); ++it ) {
00561 urls.append( KDEPIMPROTOCOL_CONTACT + ( *it ).uid() );
00562
00563 labels.append( QString::fromUtf8( ( *it ).realName().latin1() ) );
00564 }
00565 probablyWeHaveUris = true;
00566 } else if ( KURLDrag::canDecode( source ) ) {
00567 QMap<QString,QString> metadata;
00568 if ( KURLDrag::decode( source, urls, metadata ) ) {
00569 probablyWeHaveUris = true;
00570 labels = QStringList::split( ':', metadata["labels"], FALSE );
00571 for ( QStringList::Iterator it = labels.begin(); it != labels.end(); ++it ) {
00572 *it = KURL::decode_string( (*it).latin1() );
00573 }
00574
00575 }
00576 } else if ( QTextDrag::canDecode( source ) ) {
00577 QString text;
00578 QTextDrag::decode( source, text );
00579 QStringList lst = QStringList::split( '\n', text, FALSE );
00580 for ( QStringList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
00581 urls.append( *it );
00582 labels.append( QString::null );
00583 }
00584 probablyWeHaveUris = true;
00585 }
00586
00587 KPopupMenu menu;
00588 int items=0;
00589 if ( probablyWeHaveUris ) {
00590 menu.insertItem( i18n( "&Link here" ), DRAG_LINK, items++ );
00591
00592 for ( KURL::List::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it ) {
00593 if ( !( weCanCopy = KProtocolInfo::supportsReading( *it ) ) ) {
00594 break;
00595 }
00596 }
00597 if ( weCanCopy ) {
00598 menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ );
00599 }
00600 } else {
00601 menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ );
00602 }
00603
00604 menu.insertSeparator();
00605 items++;
00606 menu.insertItem( SmallIcon( "cancel" ), i18n( "C&ancel" ), DRAG_CANCEL, items );
00607 int action = menu.exec( QCursor::pos(), 0 );
00608
00609 if ( action == DRAG_LINK ) {
00610 QStringList::ConstIterator jt = labels.constBegin();
00611 for ( KURL::List::ConstIterator it = urls.constBegin();
00612 it != urls.constEnd(); ++it ) {
00613 QString label = (*jt++);
00614 if ( mAttachments->findItem( label ) ) {
00615 label += '~' + randomString( 3 );
00616 }
00617 addUriAttachment( (*it).url(), QString::null, label, true );
00618 }
00619 } else if ( action != DRAG_CANCEL ) {
00620 if ( probablyWeHaveUris ) {
00621 for ( KURL::List::ConstIterator it = urls.constBegin();
00622 it != urls.constEnd(); ++it ) {
00623 QString label = (*it).fileName();
00624 if ( label.isEmpty() ) {
00625 label = (*it).prettyURL();
00626 }
00627 if ( mAttachments->findItem( label ) ) {
00628 label += '~' + randomString( 3 );
00629 }
00630 addUriAttachment( (*it).url(), QString::null, label, true );
00631 }
00632 } else {
00633 addDataAttachment( source->encodedData( source->format() ),
00634 source->format(),
00635 KMimeType::mimeType( source->format() )->name() );
00636 }
00637 }
00638 }
00639
00640 void KOEditorAttachments::dropEvent( QDropEvent* event )
00641 {
00642 handlePasteOrDrop( event );
00643 }
00644
00645 void KOEditorAttachments::showAttachment( QIconViewItem *item )
00646 {
00647 AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item);
00648 if ( !attitem || !attitem->attachment() ) return;
00649
00650 KCal::Attachment *att = attitem->attachment();
00651 if ( att->isUri() ) {
00652 emit openURL( att->uri() );
00653 } else {
00654 KRun::runURL( mAttachments->tempFileForAttachment( att ), att->mimeType(), 0, true );
00655 }
00656 }
00657
00658 void KOEditorAttachments::saveAttachment( QIconViewItem *item )
00659 {
00660 AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item);
00661 if ( !attitem || !attitem->attachment() ) return;
00662
00663 KCal::Attachment *att = attitem->attachment();
00664
00665
00666 QString saveAsFile =
00667 KFileDialog::getSaveFileName( att->label(),
00668 QString::null, 0,
00669 i18n( "Save Attachment" ) );
00670 if ( saveAsFile.isEmpty() ||
00671 ( QFile( saveAsFile ).exists() &&
00672 ( KMessageBox::warningYesNo(
00673 0,
00674 i18n( "%1 already exists. Do you want to overwrite it?").
00675 arg( saveAsFile ) ) == KMessageBox::No ) ) ) {
00676 return;
00677 }
00678
00679 KURL sourceUrl;
00680 if ( att->isUri() ) {
00681 sourceUrl = att->uri();
00682 } else {
00683 sourceUrl = mAttachments->tempFileForAttachment( att );
00684 }
00685
00686 if ( !KIO::NetAccess::file_copy( sourceUrl, KURL( saveAsFile ), -1, true ) &&
00687 KIO::NetAccess::lastError() ) {
00688 KMessageBox::error( this, KIO::NetAccess::lastErrorString() );
00689 }
00690 }
00691
00692 void KOEditorAttachments::slotAdd()
00693 {
00694 AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00695
00696 AttachmentEditDialog *dlg = new AttachmentEditDialog( item, mAttachments )
00697 ;
00698 if ( dlg->exec() == KDialog::Rejected ) {
00699 delete item;
00700 }
00701 delete dlg;
00702 }
00703
00704 void KOEditorAttachments::slotAddData()
00705 {
00706 KURL uri = KFileDialog::getOpenFileName( QString(), QString(), this, i18n("Add Attachment") );
00707 if ( !uri.isEmpty() ) {
00708 QString label = uri.fileName();
00709 if ( label.isEmpty() ) {
00710 label = uri.prettyURL();
00711 }
00712 addUriAttachment( uri.url(), QString::null, label, true );
00713 }
00714 }
00715
00716 void KOEditorAttachments::slotEdit()
00717 {
00718 for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00719 if ( item->isSelected() ) {
00720 AttachmentListItem *attitem = static_cast<AttachmentListItem*>( item );
00721 if ( !attitem || !attitem->attachment() ) {
00722 return;
00723 }
00724
00725 AttachmentEditDialog *dialog = new AttachmentEditDialog( attitem, mAttachments );
00726 dialog->mInline->setEnabled( false );
00727 dialog->setModal( false );
00728 connect( dialog, SIGNAL(hidden()), dialog, SLOT(delayedDestruct()) );
00729 dialog->show();
00730 }
00731 }
00732 }
00733
00734 void KOEditorAttachments::slotRemove()
00735 {
00736 QValueList<QIconViewItem*> selected;
00737 QStringList labels;
00738 for ( QIconViewItem *it = mAttachments->firstItem( ); it; it = it->nextItem( ) ) {
00739 if ( !it->isSelected() ) continue;
00740 selected << it;
00741
00742 AttachmentListItem *attitem = static_cast<AttachmentListItem*>(it);
00743 KCal::Attachment *att = attitem->attachment();
00744 labels << att->label();
00745 }
00746
00747 if ( selected.isEmpty() ) {
00748 return;
00749 }
00750
00751 QString labelsStr = labels.join( "<br>" );
00752
00753 if ( KMessageBox::questionYesNo(
00754 this,
00755 i18n( "<qt>Do you really want to remove these attachments?<p>%1</qt>" ).arg( labelsStr ),
00756 i18n( "Remove Attachment?" ),
00757 KStdGuiItem::yes(), KStdGuiItem::no(),
00758 "calendarRemoveAttachments" ) != KMessageBox::Yes ) {
00759 return;
00760 }
00761
00762 for ( QValueList<QIconViewItem*>::iterator it( selected.begin() ), end( selected.end() );
00763 it != end ; ++it ) {
00764 if ( (*it)->nextItem() ) {
00765 (*it)->nextItem()->setSelected( true );
00766 } else if ( (*it)->prevItem() ) {
00767 (*it)->prevItem()->setSelected( true );
00768 }
00769 delete *it;
00770 }
00771 mAttachments->slotUpdate();
00772 }
00773
00774 void KOEditorAttachments::slotShow()
00775 {
00776 for ( QIconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) {
00777 if ( !it->isSelected() )
00778 continue;
00779 showAttachment( it );
00780 }
00781 }
00782
00783 void KOEditorAttachments::slotSaveAs()
00784 {
00785 for ( QIconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) {
00786 if ( !it->isSelected() )
00787 continue;
00788 saveAttachment( it );
00789 }
00790 }
00791
00792 void KOEditorAttachments::setDefaults()
00793 {
00794 mAttachments->clear();
00795 }
00796
00797 QString KOEditorAttachments::randomString(int length) const
00798 {
00799 if (length <=0 ) return QString();
00800
00801 QString str; str.setLength( length );
00802 int i = 0;
00803 while (length--)
00804 {
00805 int r=random() % 62;
00806 r+=48;
00807 if (r>57) r+=7;
00808 if (r>90) r+=6;
00809 str[i++] = char(r);
00810
00811 }
00812 return str;
00813 }
00814
00815 void KOEditorAttachments::addUriAttachment( const QString &uri,
00816 const QString &mimeType,
00817 const QString &label,
00818 bool inLine )
00819 {
00820 if ( !inLine ) {
00821 AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00822 item->setUri( uri );
00823 item->setLabel( label );
00824 if ( mimeType.isEmpty() ) {
00825 if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) {
00826 item->setMimeType( "text/directory" );
00827 } else if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) {
00828 item->setMimeType( "message/rfc822" );
00829 } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) {
00830 item->setMimeType( "text/calendar" );
00831 } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) {
00832 item->setMimeType( "message/news" );
00833 } else {
00834 item->setMimeType( KMimeType::findByURL( uri )->name() );
00835 }
00836 }
00837 } else {
00838 QString tmpFile;
00839 if ( KIO::NetAccess::download( uri, tmpFile, this ) ) {
00840 QFile f( tmpFile );
00841 if ( !f.open( IO_ReadOnly ) ) {
00842 return;
00843 }
00844 const QByteArray data = f.readAll();
00845 f.close();
00846 addDataAttachment( data, mimeType, label );
00847 }
00848 KIO::NetAccess::removeTempFile( tmpFile );
00849 }
00850 }
00851
00852 void KOEditorAttachments::addDataAttachment( const QByteArray &data,
00853 const QString &mimeType,
00854 const QString &label )
00855 {
00856 AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00857
00858 QString nlabel = label;
00859 if ( mimeType == "message/rfc822" ) {
00860
00861 KMime::Message msg;
00862 msg.setContent( data.data() );
00863 msg.parse();
00864 nlabel = msg.subject()->asUnicodeString();
00865 }
00866
00867 item->setData( data );
00868 item->setLabel( nlabel );
00869 if ( mimeType.isEmpty() ) {
00870 item->setMimeType( KMimeType::findByContent( data )->name() );
00871 } else {
00872 item->setMimeType( mimeType );
00873 }
00874 }
00875
00876 void KOEditorAttachments::addAttachment( KCal::Attachment *attachment )
00877 {
00878 new AttachmentListItem( attachment, mAttachments );
00879 }
00880
00881 void KOEditorAttachments::readIncidence( KCal::Incidence *i )
00882 {
00883 mAttachments->clear();
00884
00885 KCal::Attachment::List attachments = i->attachments();
00886 KCal::Attachment::List::ConstIterator it;
00887 for( it = attachments.begin(); it != attachments.end(); ++it ) {
00888 addAttachment( (*it) );
00889 }
00890 if ( mAttachments->count() > 0 ) {
00891 QTimer::singleShot( 0, mAttachments, SLOT(arrangeItemsInGrid()) );
00892 }
00893 }
00894
00895 void KOEditorAttachments::writeIncidence( KCal::Incidence *i )
00896 {
00897 i->clearAttachments();
00898
00899 QIconViewItem *item;
00900 AttachmentListItem *attitem;
00901 for( item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00902 attitem = static_cast<AttachmentListItem*>(item);
00903 if ( attitem )
00904 i->addAttachment( new KCal::Attachment( *(attitem->attachment() ) ) );
00905 }
00906 }
00907
00908
00909 void KOEditorAttachments::slotCopy()
00910 {
00911 QApplication::clipboard()->setData( mAttachments->mimeData(), QClipboard::Clipboard );
00912 }
00913
00914 void KOEditorAttachments::slotCut()
00915 {
00916 slotCopy();
00917 slotRemove();
00918 }
00919
00920 void KOEditorAttachments::slotPaste()
00921 {
00922 handlePasteOrDrop( QApplication::clipboard()->data() );
00923 }
00924
00925 void KOEditorAttachments::selectionChanged()
00926 {
00927 bool selected = false;
00928 for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00929 if ( item->isSelected() ) {
00930 selected = true;
00931 break;
00932 }
00933 }
00934 mRemoveBtn->setEnabled( selected );
00935 }
00936
00937 void KOEditorAttachments::contextMenu(QIconViewItem * item, const QPoint & pos)
00938 {
00939 const bool enable = item != 0;
00940
00941 int numSelected = 0;
00942 for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00943 if ( item->isSelected() ) {
00944 numSelected++;
00945 }
00946 }
00947
00948 mOpenAction->setEnabled( enable );
00949
00950 mSaveAsAction->setEnabled( enable && numSelected == 1 );
00951 mCopyAction->setEnabled( enable && numSelected == 1 );
00952 mCutAction->setEnabled( enable && numSelected == 1 );
00953 mDeleteAction->setEnabled( enable );
00954 mEditAction->setEnabled( enable );
00955 mContextMenu->exec( pos );
00956 }
00957
00958 #include "koeditorattachments.moc"