korganizer

koeditorattachments.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (c) 2005 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
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( QString::null );
00082       }
00083       readAttachment();
00084       setDragEnabled( true );
00085     }
00086     ~AttachmentListItem() { delete mAttachment; }
00087     KCal::Attachment *attachment() const { return mAttachment; }
00088 
00089     const QString uri() const
00090     {
00091       return mAttachment->uri();
00092     }
00093     void setUri( const QString &uri )
00094     {
00095       mAttachment->setUri( uri );
00096       readAttachment();
00097     }
00098     void setData( const QByteArray data )
00099     {
00100       mAttachment->setDecodedData( data );
00101       readAttachment();
00102     }
00103     const QString mimeType() const
00104     {
00105       return mAttachment->mimeType();
00106     }
00107     void setMimeType( const QString &mime )
00108     {
00109       mAttachment->setMimeType( mime );
00110       readAttachment();
00111     }
00112     const QString label() const
00113     {
00114       return mAttachment->label();
00115     }
00116     void setLabel( const QString &label )
00117     {
00118       mAttachment->setLabel( label );
00119       readAttachment();
00120     }
00121     bool isBinary() const
00122     {
00123       return mAttachment->isBinary();
00124     }
00125     QPixmap icon() const
00126     {
00127       return icon( KMimeType::mimeType( mAttachment->mimeType() ),
00128                    mAttachment->uri() );
00129     }
00130     static QPixmap icon( KMimeType::Ptr mimeType, const QString &uri )
00131     {
00132       QString iconStr = mimeType->icon( uri, false );
00133       return KGlobal::iconLoader()->loadIcon( iconStr, KIcon::Small );
00134     }
00135     void readAttachment()
00136     {
00137       if ( mAttachment->label().isEmpty() ) {
00138         if ( mAttachment->isUri() ) {
00139           setText( mAttachment->uri() );
00140         } else {
00141           setText( i18n( "[Binary data]" ) );
00142         }
00143       } else {
00144         setText( mAttachment->label() );
00145       }
00146       if ( mAttachment->mimeType().isEmpty() ||
00147            !( KMimeType::mimeType( mAttachment->mimeType() ) ) ) {
00148         KMimeType::Ptr mimeType;
00149         if ( mAttachment->isUri() ) {
00150           mimeType = KMimeType::findByURL( mAttachment->uri() );
00151         } else {
00152           mimeType = KMimeType::findByContent( mAttachment->decodedData() );
00153         }
00154         mAttachment->setMimeType( mimeType->name() );
00155       }
00156 
00157       setPixmap( icon() );
00158     }
00159 
00160   private:
00161     KCal::Attachment *mAttachment;
00162 };
00163 
00164 AttachmentEditDialog::AttachmentEditDialog( AttachmentListItem *item,
00165                                             QWidget *parent )
00166   : KDialogBase ( Plain, i18n( "Add Attachment" ), Ok|Cancel, Ok, parent, 0, false, false ),
00167     mItem( item ), mURLRequester( 0 )
00168 {
00169   QFrame *topFrame = plainPage();
00170   QVBoxLayout *vbl = new QVBoxLayout( topFrame, 0, spacingHint() );
00171 
00172   QGridLayout *grid = new QGridLayout();
00173   grid->setColStretch( 0, 0 );
00174   grid->setColStretch( 1, 0 );
00175   grid->setColStretch( 2, 1 );
00176   vbl->addLayout( grid );
00177 
00178   mIcon = new QLabel( topFrame );
00179   mIcon->setPixmap( item->icon() );
00180   grid->addWidget( mIcon, 0, 0 );
00181 
00182   mLabelEdit = new KLineEdit( topFrame );
00183   mLabelEdit->setClickMessage( i18n( "Attachment name" ) );
00184   if ( !item->uri().isEmpty() ) {
00185     KURL url( item->uri() );
00186     if ( url.isLocalFile() ) {
00187       mLabelEdit->setText( url.fileName() );
00188     } else {
00189       mLabelEdit->setText( url.url() );
00190     }
00191   }
00192   QToolTip::add( mLabelEdit, i18n( "Give the attachment a name" ) );
00193   QWhatsThis::add( mLabelEdit,
00194                    i18n( "Type any string you desire here for the name of the attachment" ) );
00195   grid->addMultiCellWidget( mLabelEdit, 0, 0, 1, 2 );
00196 
00197   KSeparator *sep = new KSeparator( Qt::Horizontal, topFrame );
00198   grid->addMultiCellWidget( sep, 1, 1, 0, 2 );
00199 
00200   QLabel *label = new QLabel( i18n( "Type:" ), topFrame );
00201   grid->addWidget( label, 2, 0 );
00202   QString typecomment = item->mimeType().isEmpty() ?
00203                         i18n( "Unknown" ) :
00204                         KMimeType::mimeType( item->mimeType() )->comment();
00205   mTypeLabel = new QLabel( typecomment, topFrame );
00206   grid->addWidget( mTypeLabel, 2, 1 );
00207   mMimeType = KMimeType::mimeType( item->mimeType() );
00208 
00209   mInline = new QCheckBox( i18n( "Store attachment inline" ), topFrame );
00210   grid->addMultiCellWidget( mInline, 3, 3, 0, 2 );
00211   mInline->setChecked( item->isBinary() );
00212   QToolTip::add( mInline, i18n( "Store the attachment file inside the calendar" ) );
00213   QWhatsThis::add(
00214     mInline,
00215     i18n( "Checking this option will cause the attachment to be stored inside "
00216           "your calendar, which can take a lot of space depending on the size "
00217           "of the attachment. If this option is not checked, then only a link "
00218           "pointing to the attachment will be stored.  Do not use a link for "
00219           "attachments that change often or may be moved (or removed) from "
00220           "their current location." ) );
00221 
00222   if ( item->attachment()->isUri() ) {
00223     label = new QLabel( i18n( "Location:" ), topFrame );
00224     grid->addWidget( label, 4, 0 );
00225     mURLRequester = new KURLRequester( item->uri(), topFrame );
00226     QToolTip::add( mURLRequester, i18n( "Provide a location for the attachment file" ) );
00227     QWhatsThis::add(
00228       mURLRequester,
00229       i18n( "Enter the path to the attachment file or use the "
00230             "file browser by pressing the adjacent button" ) );
00231     grid->addMultiCellWidget( mURLRequester, 4, 4, 1, 2 );
00232     connect( mURLRequester, SIGNAL(urlSelected(const QString &)),
00233              SLOT(urlSelected(const QString &)) );
00234     connect( mURLRequester, SIGNAL( textChanged( const QString& ) ),
00235              SLOT( urlChanged( const QString& ) ) );
00236     urlChanged( item->uri() );
00237   } else {
00238     uint size = QCString( item->attachment()->data() ).size();
00239     grid->addWidget( new QLabel( i18n( "Size:" ), topFrame ), 4, 0 );
00240     grid->addWidget( new QLabel( QString::fromLatin1( "%1 (%2)" ).
00241                                  arg( KIO::convertSize( size ) ).
00242                                  arg( KGlobal::locale()->formatNumber(
00243                                         size, 0 ) ), topFrame ), 4, 2 );
00244   }
00245   vbl->addStretch( 10 );
00246 }
00247 
00248 void AttachmentEditDialog::slotApply()
00249 {
00250   KURL url( mURLRequester->url() );
00251   if ( mLabelEdit->text().isEmpty() ) {
00252     if ( url.isLocalFile() ) {
00253       mItem->setLabel( url.fileName() );
00254     } else {
00255       mItem->setLabel( url.url() );
00256     }
00257   } else {
00258     mItem->setLabel( mLabelEdit->text() );
00259   }
00260   if ( mItem->label().isEmpty() ) {
00261     mItem->setLabel( i18n( "New attachment" ) );
00262   }
00263   mItem->setMimeType( mMimeType->name() );
00264   if ( mURLRequester ) {
00265     if ( mInline->isChecked() ) {
00266       QString tmpFile;
00267       if ( KIO::NetAccess::download( mURLRequester->url(), tmpFile, this ) ) {
00268         QFile f( tmpFile );
00269         if ( !f.open( IO_ReadOnly ) ) {
00270           return;
00271         }
00272         QByteArray data = f.readAll();
00273         f.close();
00274         mItem->setData( data );
00275       }
00276       KIO::NetAccess::removeTempFile( tmpFile );
00277     } else {
00278       mItem->setUri( url.url() );
00279     }
00280   }
00281 }
00282 
00283 void AttachmentEditDialog::accept()
00284 {
00285   slotApply();
00286   KDialog::accept();
00287 }
00288 
00289 void AttachmentEditDialog::urlChanged( const QString &url )
00290 {
00291   enableButton( Ok, !url.isEmpty() );
00292 }
00293 
00294 void AttachmentEditDialog::urlSelected( const QString &url )
00295 {
00296   KURL kurl( url );
00297   mMimeType = KMimeType::findByURL( kurl );
00298   mTypeLabel->setText( mMimeType->comment() );
00299   mIcon->setPixmap( AttachmentListItem::icon( mMimeType, kurl.path() ) );
00300 }
00301 
00302 AttachmentIconView::AttachmentIconView( KOEditorAttachments* parent )
00303   : KIconView( parent ),
00304     mParent( parent )
00305 {
00306   setSelectionMode( QIconView::Extended );
00307   setMode( KIconView::Select );
00308   setItemTextPos( QIconView::Right );
00309   setArrangement( QIconView::LeftToRight );
00310   setMaxItemWidth( QMAX(maxItemWidth(), 250) );
00311   setMinimumHeight( QMAX(fontMetrics().height(), 16) + 12 );
00312 
00313   connect( this, SIGNAL( dropped ( QDropEvent *, const QValueList<QIconDragItem> & ) ),
00314            this, SLOT( handleDrop( QDropEvent *, const QValueList<QIconDragItem> & ) ) );
00315 }
00316 
00317 KURL AttachmentIconView::tempFileForAttachment( KCal::Attachment *attachment )
00318 {
00319   if ( mTempFiles.contains( attachment ) ) {
00320     return mTempFiles[attachment];
00321   }
00322   QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
00323 
00324   KTempFile *file;
00325   if ( !patterns.empty() ) {
00326     file = new KTempFile( QString::null,
00327                           QString( patterns.first() ).remove( '*' ),0600 );
00328   } else {
00329     file = new KTempFile( QString::null, QString::null, 0600 );
00330   }
00331   file->setAutoDelete( true );
00332   file->file()->open( IO_WriteOnly );
00333   QTextStream stream( file->file() );
00334   stream << attachment->decodedData().data();
00335   KURL url( file->name() );
00336   mTempFiles.insert( attachment, url );
00337   file->close();
00338   return mTempFiles[attachment];
00339 }
00340 
00341 QDragObject *AttachmentIconView::mimeData()
00342 {
00343   // create a list of the URL:s that we want to drag
00344   KURL::List urls;
00345   QStringList labels;
00346   for ( QIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
00347     if ( it->isSelected() ) {
00348       AttachmentListItem *item = static_cast<AttachmentListItem *>( it );
00349       if ( item->isBinary() ) {
00350         urls.append( tempFileForAttachment( item->attachment() ) );
00351       } else {
00352         urls.append( item->uri() );
00353       }
00354       labels.append( KURL::encode_string( item->label() ) );
00355     }
00356   }
00357   if ( selectionMode() == QIconView::NoSelection ) {
00358     AttachmentListItem *item = static_cast<AttachmentListItem *>( currentItem() );
00359     if ( item ) {
00360       urls.append( item->uri() );
00361       labels.append( KURL::encode_string( item->label() ) );
00362     }
00363   }
00364 
00365   QMap<QString, QString> metadata;
00366   metadata["labels"] = labels.join( ":" );
00367 
00368   KURLDrag *drag = new KURLDrag( urls, metadata );
00369   return drag;
00370 }
00371 
00372 AttachmentIconView::~AttachmentIconView()
00373 {
00374   for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) {
00375     delete *it;
00376   }
00377 }
00378 
00379 QDragObject * AttachmentIconView::dragObject()
00380 {
00381   KURL::List urls;
00382   for ( QIconViewItem *it = firstItem( ); it; it = it->nextItem( ) ) {
00383     if ( !it->isSelected() ) continue;
00384     AttachmentListItem * item = dynamic_cast<AttachmentListItem*>( it );
00385     if ( !item ) return 0;
00386     KCal::Attachment * att = item->attachment();
00387     assert( att );
00388     KURL url;
00389     if ( att->isUri() ) {
00390       url.setPath( att->uri() );
00391     } else {
00392       KTempDir * tempDir = new KTempDir(); // will be deleted on editor close
00393       tempDir->setAutoDelete( true );
00394       mTempDirs.insert( tempDir );
00395       QByteArray encoded;
00396       encoded.duplicate( att->data(), strlen(att->data()) );
00397       QByteArray decoded;
00398       KCodecs::base64Decode( encoded, decoded );
00399       const QString fileName = tempDir->name( ) + "/" + att->label();
00400       KPIM::kByteArrayToFile( decoded, fileName, false, false, false );
00401       url.setPath( fileName );
00402     }
00403     urls << url;
00404   }
00405   KURLDrag *drag  = new KURLDrag( urls, this );
00406   return drag;
00407 }
00408 
00409 void AttachmentIconView::handleDrop( QDropEvent *event, const QValueList<QIconDragItem> & list )
00410 {
00411   Q_UNUSED( list );
00412   mParent->handlePasteOrDrop( event );
00413 }
00414 
00415 
00416 void AttachmentIconView::dragMoveEvent( QDragMoveEvent *event )
00417 {
00418   mParent->dragMoveEvent( event );
00419 }
00420 
00421 void AttachmentIconView::contentsDragMoveEvent( QDragMoveEvent *event )
00422 {
00423   mParent->dragMoveEvent( event );
00424 }
00425 
00426 void AttachmentIconView::contentsDragEnterEvent( QDragEnterEvent *event )
00427 {
00428   mParent->dragMoveEvent( event );
00429 }
00430 
00431 void AttachmentIconView::dragEnterEvent( QDragEnterEvent *event )
00432 {
00433   mParent->dragEnterEvent( event );
00434 }
00435 
00436 KOEditorAttachments::KOEditorAttachments( int spacing, QWidget *parent,
00437                                           const char *name )
00438   : QWidget( parent, name )
00439 {
00440   QBoxLayout *topLayout = new QHBoxLayout( this );
00441   topLayout->setSpacing( spacing );
00442 
00443   QLabel *label = new QLabel( i18n("Attachments:"), this );
00444   topLayout->addWidget( label );
00445 
00446   mAttachments = new AttachmentIconView( this );
00447   QWhatsThis::add( mAttachments,
00448                    i18n("Displays a list of current items (files, mail, etc.) "
00449                         "that have been associated with this event or to-do. ") );
00450   topLayout->addWidget( mAttachments );
00451   connect( mAttachments, SIGNAL( doubleClicked( QIconViewItem * ) ),
00452            SLOT( showAttachment( QIconViewItem * ) ) );
00453   connect( mAttachments, SIGNAL(selectionChanged()),
00454            SLOT(selectionChanged()) );
00455   connect( mAttachments, SIGNAL(contextMenuRequested(QIconViewItem*,const QPoint&)),
00456            SLOT(contextMenu(QIconViewItem*,const QPoint&)) );
00457 
00458     QPushButton *addButton = new QPushButton( this );
00459   addButton->setIconSet( SmallIconSet( "add" ) );
00460   QToolTip::add( addButton, i18n( "Add an attachment" ) );
00461   QWhatsThis::add( addButton,
00462                    i18n( "Shows a dialog used to select an attachment "
00463                          "to add to this event or to-do as link or as "
00464                          "inline data." ) );
00465   topLayout->addWidget( addButton );
00466   connect( addButton, SIGNAL(clicked()), SLOT(slotAdd()) );
00467 
00468   mRemoveBtn = new QPushButton( this );
00469   mRemoveBtn->setIconSet( SmallIconSet( "remove" ) );
00470   QToolTip::add( mRemoveBtn, i18n("&Remove") );
00471   QWhatsThis::add( mRemoveBtn,
00472                    i18n("Removes the attachment selected in the list above "
00473                         "from this event or to-do.") );
00474   topLayout->addWidget( mRemoveBtn );
00475   connect( mRemoveBtn, SIGNAL(clicked()), SLOT(slotRemove()) );
00476 
00477   mContextMenu = new KPopupMenu( this );
00478 
00479   KActionCollection* ac = new KActionCollection( this, this );
00480 
00481   mOpenAction = new KAction( i18n("Open"), 0, this, SLOT(slotShow()), ac );
00482   mOpenAction->plug( mContextMenu );
00483   mContextMenu->insertSeparator();
00484 
00485   mCopyAction = KStdAction::copy(this, SLOT(slotCopy()), ac );
00486   mCopyAction->plug( mContextMenu );
00487   mCutAction = KStdAction::cut(this, SLOT(slotCut()), ac );
00488   mCutAction->plug( mContextMenu );
00489   KAction *action = KStdAction::paste(this, SLOT(slotPaste()), ac );
00490   action->plug( mContextMenu );
00491   mContextMenu->insertSeparator();
00492 
00493   mDeleteAction = new KAction( i18n( "&Remove" ), 0, this, SLOT(slotRemove()),  ac );
00494   mDeleteAction->plug( mContextMenu );
00495   mContextMenu->insertSeparator();
00496 
00497   mEditAction = new KAction( i18n( "&Properties..." ), 0, this, SLOT(slotEdit()), ac );
00498   mEditAction->plug( mContextMenu );
00499 
00500   selectionChanged();
00501   setAcceptDrops( true );
00502 }
00503 
00504 KOEditorAttachments::~KOEditorAttachments()
00505 {
00506 }
00507 
00508 bool KOEditorAttachments::hasAttachments()
00509 {
00510   return mAttachments->count() != 0;
00511 }
00512 
00513 void KOEditorAttachments::dragMoveEvent( QDragMoveEvent *event )
00514 {
00515   event->accept( KURLDrag::canDecode( event ) ||
00516                  QTextDrag::canDecode( event ) ||
00517                  KPIM::MailListDrag::canDecode( event ) ||
00518                  KVCardDrag::canDecode( event ) );
00519 }
00520 
00521 void KOEditorAttachments::dragEnterEvent( QDragEnterEvent* event )
00522 {
00523   dragMoveEvent( event );
00524 }
00525 
00526 void KOEditorAttachments::handlePasteOrDrop( QMimeSource* source )
00527 {
00528   KURL::List urls;
00529   bool probablyWeHaveUris = false;
00530   bool weCanCopy = true;
00531   QStringList labels;
00532 
00533   if ( KVCardDrag::canDecode( source ) ) {
00534     KABC::Addressee::List addressees;
00535     KVCardDrag::decode( source, addressees );
00536     for ( KABC::Addressee::List::ConstIterator it = addressees.constBegin();
00537           it != addressees.constEnd(); ++it ) {
00538       urls.append( KDEPIMPROTOCOL_CONTACT + ( *it ).uid() );
00539       // there is some weirdness about realName(), hence fromUtf8
00540       labels.append( QString::fromUtf8( ( *it ).realName().latin1() ) );
00541     }
00542     probablyWeHaveUris = true;
00543   } else if ( KURLDrag::canDecode( source ) ) {
00544     QMap<QString,QString> metadata;
00545     if ( KURLDrag::decode( source, urls, metadata ) ) {
00546       probablyWeHaveUris = true;
00547       labels = QStringList::split( ':', metadata["labels"], FALSE );
00548       for ( QStringList::Iterator it = labels.begin(); it != labels.end(); ++it ) {
00549         *it = KURL::decode_string( (*it).latin1() );
00550       }
00551 
00552     }
00553   } else if ( QTextDrag::canDecode( source ) ) {
00554     QString text;
00555     QTextDrag::decode( source, text );
00556     QStringList lst = QStringList::split( '\n', text, FALSE );
00557     for ( QStringList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
00558       urls.append( *it );
00559       labels.append( QString::null );
00560     }
00561     probablyWeHaveUris = true;
00562   }
00563 
00564   KPopupMenu menu;
00565   int items=0;
00566   if ( probablyWeHaveUris ) {
00567     menu.insertItem( i18n( "&Link here" ), DRAG_LINK, items++ );
00568     // we need to check if we can reasonably expect to copy the objects
00569     for ( KURL::List::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it ) {
00570       if ( !( weCanCopy = KProtocolInfo::supportsReading( *it ) ) ) {
00571         break; // either we can copy them all, or no copying at all
00572       }
00573     }
00574     if ( weCanCopy ) {
00575       menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ );
00576     }
00577   } else {
00578       menu.insertItem( SmallIcon( "editcopy" ), i18n( "&Copy Here" ), DRAG_COPY, items++ );
00579   }
00580 
00581   menu.insertSeparator();
00582   items++;
00583   menu.insertItem( SmallIcon( "cancel" ), i18n( "C&ancel" ), DRAG_CANCEL, items );
00584   int action = menu.exec( QCursor::pos(), 0 );
00585 
00586   if ( action == DRAG_LINK ) {
00587     QStringList::ConstIterator jt = labels.constBegin();
00588     for ( KURL::List::ConstIterator it = urls.constBegin();
00589           it != urls.constEnd(); ++it ) {
00590       QString label = (*jt++);
00591       if ( mAttachments->findItem( label ) ) {
00592         label += '~' + randomString( 3 );
00593       }
00594       addUriAttachment( (*it).url(), QString::null, label, true );
00595     }
00596   } else if ( action != DRAG_CANCEL ) {
00597     if ( probablyWeHaveUris ) {
00598       for ( KURL::List::ConstIterator it = urls.constBegin();
00599             it != urls.constEnd(); ++it ) {
00600         QString label = (*it).fileName();
00601         if ( label.isEmpty() ) {
00602           label = (*it).prettyURL();
00603         }
00604         if ( mAttachments->findItem( label ) ) {
00605           label += '~' + randomString( 3 );
00606         }
00607         addUriAttachment( (*it).url(), QString::null, label, true );
00608       }
00609     } else { // we take anything
00610       addDataAttachment( source->encodedData( source->format() ),
00611                          source->format(),
00612                          KMimeType::mimeType( source->format() )->name() );
00613     }
00614   }
00615 }
00616 
00617 void KOEditorAttachments::dropEvent( QDropEvent* event )
00618 {
00619     handlePasteOrDrop( event );
00620 }
00621 
00622 void KOEditorAttachments::showAttachment( QIconViewItem *item )
00623 {
00624   AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item);
00625   if ( !attitem || !attitem->attachment() ) return;
00626 
00627   KCal::Attachment *att = attitem->attachment();
00628   if ( att->isUri() ) {
00629     emit openURL( att->uri() );
00630   } else {
00631     KRun::runURL( mAttachments->tempFileForAttachment( att ), att->mimeType(), 0, true );
00632   }
00633 }
00634 
00635 void KOEditorAttachments::slotAdd()
00636 {
00637   AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00638 
00639   AttachmentEditDialog *dlg = new AttachmentEditDialog( item, mAttachments )
00640 ;
00641   if ( dlg->exec() == KDialog::Rejected ) {
00642     delete item;
00643   }
00644   delete dlg;
00645 }
00646 
00647 void KOEditorAttachments::slotAddData()
00648 {
00649   KURL uri = KFileDialog::getOpenFileName( QString(), QString(), this, i18n("Add Attachment") );
00650   if ( !uri.isEmpty() ) {
00651     QString label = uri.fileName();
00652     if ( label.isEmpty() ) {
00653       label = uri.prettyURL();
00654     }
00655     addUriAttachment( uri.url(), QString::null, label, true );
00656   }
00657 }
00658 
00659 void KOEditorAttachments::slotEdit()
00660 {
00661   for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00662     if ( item->isSelected() ) {
00663       AttachmentListItem *attitem = static_cast<AttachmentListItem*>( item );
00664       if ( !attitem || !attitem->attachment() ) {
00665         return;
00666       }
00667 
00668       AttachmentEditDialog *dialog = new AttachmentEditDialog( attitem, mAttachments );
00669       dialog->mInline->setEnabled( false );
00670       dialog->setModal( false );
00671       connect( dialog, SIGNAL(hidden()), dialog, SLOT(delayedDestruct()) );
00672       dialog->show();
00673     }
00674   }
00675 }
00676 
00677 void KOEditorAttachments::slotRemove()
00678 {
00679     QValueList<QIconViewItem*> selected;
00680     for ( QIconViewItem *it = mAttachments->firstItem( ); it; it = it->nextItem( ) ) {
00681         if ( !it->isSelected() ) continue;
00682         selected << it;
00683     }
00684     if ( selected.isEmpty() || KMessageBox::warningContinueCancel(this,
00685                     selected.count() == 1?i18n("This item will be permanently deleted."):
00686                     i18n("The selected items will be permanently deleted."),
00687                     i18n("KOrganizer Confirmation"),KStdGuiItem::del()) != KMessageBox::Continue )
00688         return;
00689 
00690     for ( QValueList<QIconViewItem*>::iterator it( selected.begin() ), end( selected.end() ); it != end ; ++it ) {
00691         delete *it;
00692     }
00693 }
00694 
00695 void KOEditorAttachments::slotShow()
00696 {
00697   for ( QIconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) {
00698     if ( !it->isSelected() )
00699       continue;
00700     showAttachment( it );
00701   }
00702 }
00703 
00704 void KOEditorAttachments::setDefaults()
00705 {
00706   mAttachments->clear();
00707 }
00708 
00709 QString KOEditorAttachments::randomString(int length) const
00710 {
00711    if (length <=0 ) return QString();
00712 
00713    QString str; str.setLength( length );
00714    int i = 0;
00715    while (length--)
00716    {
00717       int r=random() % 62;
00718       r+=48;
00719       if (r>57) r+=7;
00720       if (r>90) r+=6;
00721       str[i++] =  char(r);
00722       // so what if I work backwards?
00723    }
00724    return str;
00725 }
00726 
00727 void KOEditorAttachments::addUriAttachment( const QString &uri,
00728                                             const QString &mimeType,
00729                                             const QString &label,
00730                                             bool inLine )
00731 {
00732   if ( !inLine ) {
00733     AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00734     item->setUri( uri );
00735     item->setLabel( label );
00736     if ( mimeType.isEmpty() ) {
00737       if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) {
00738         item->setMimeType( "text/directory" );
00739       } else if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) {
00740         item->setMimeType( "message/rfc822" );
00741       } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) {
00742         item->setMimeType( "text/calendar" );
00743       } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) {
00744         item->setMimeType( "message/news" );
00745       } else {
00746         item->setMimeType( KMimeType::findByURL( uri )->name() );
00747       }
00748     }
00749   } else {
00750     QString tmpFile;
00751     if ( KIO::NetAccess::download( uri, tmpFile, this ) ) {
00752       QFile f( tmpFile );
00753       if ( !f.open( IO_ReadOnly ) ) {
00754         return;
00755       }
00756       const QByteArray data = f.readAll();
00757       f.close();
00758       addDataAttachment( data, mimeType, label );
00759     }
00760     KIO::NetAccess::removeTempFile( tmpFile );
00761   }
00762 }
00763 
00764 void KOEditorAttachments::addDataAttachment( const QByteArray &data,
00765                                              const QString &mimeType,
00766                                              const QString &label )
00767 {
00768   AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
00769 
00770   QString nlabel = label;
00771   if ( mimeType == "message/rfc822" ) {
00772     // mail message. try to set the label from the mail Subject:
00773     KMime::Message msg;
00774     msg.setContent( data.data() );
00775     msg.parse();
00776     nlabel = msg.subject()->asUnicodeString();
00777   }
00778 
00779   item->setData( data );
00780   item->setLabel( nlabel );
00781   if ( mimeType.isEmpty() ) {
00782     item->setMimeType( KMimeType::findByContent( data )->name() );
00783   } else {
00784     item->setMimeType( mimeType );
00785   }
00786 }
00787 
00788 void KOEditorAttachments::addAttachment( KCal::Attachment *attachment )
00789 {
00790   new AttachmentListItem( attachment, mAttachments );
00791 }
00792 
00793 void KOEditorAttachments::readIncidence( KCal::Incidence *i )
00794 {
00795   mAttachments->clear();
00796 
00797   KCal::Attachment::List attachments = i->attachments();
00798   KCal::Attachment::List::ConstIterator it;
00799   for( it = attachments.begin(); it != attachments.end(); ++it ) {
00800     addAttachment( (*it) );
00801   }
00802   if ( mAttachments->count() > 0 ) {
00803     QTimer::singleShot( 0, mAttachments, SLOT(arrangeItemsInGrid()) );
00804   }
00805 }
00806 
00807 void KOEditorAttachments::writeIncidence( KCal::Incidence *i )
00808 {
00809   i->clearAttachments();
00810 
00811   QIconViewItem *item;
00812   AttachmentListItem *attitem;
00813   for( item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00814     attitem = static_cast<AttachmentListItem*>(item);
00815     if ( attitem )
00816       i->addAttachment( new KCal::Attachment( *(attitem->attachment() ) ) );
00817   }
00818 }
00819 
00820 
00821 void KOEditorAttachments::slotCopy()
00822 {
00823     QApplication::clipboard()->setData( mAttachments->mimeData(), QClipboard::Clipboard );
00824 }
00825 
00826 void KOEditorAttachments::slotCut()
00827 {
00828     slotCopy();
00829     slotRemove();
00830 }
00831 
00832 void KOEditorAttachments::slotPaste()
00833 {
00834     handlePasteOrDrop( QApplication::clipboard()->data() );
00835 }
00836 
00837 void KOEditorAttachments::selectionChanged()
00838 {
00839   bool selected = false;
00840   for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
00841     if ( item->isSelected() ) {
00842       selected = true;
00843       break;
00844     }
00845   }
00846   mRemoveBtn->setEnabled( selected );
00847 }
00848 
00849 void KOEditorAttachments::contextMenu(QIconViewItem * item, const QPoint & pos)
00850 {
00851   const bool enable = item != 0;
00852   mOpenAction->setEnabled( enable );
00853   mCopyAction->setEnabled( enable );
00854   mCutAction->setEnabled( enable );
00855   mDeleteAction->setEnabled( enable );
00856   mEditAction->setEnabled( enable );
00857   mContextMenu->exec( pos );
00858 }
00859 
00860 #include "koeditorattachments.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys