summaryrefslogtreecommitdiffstats
path: root/korganizer/koeditorattachments.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch)
tree67208f7c145782a7e90b123b982ca78d88cc2c87 /korganizer/koeditorattachments.cpp
downloadtdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz
tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'korganizer/koeditorattachments.cpp')
-rw-r--r--korganizer/koeditorattachments.cpp501
1 files changed, 501 insertions, 0 deletions
diff --git a/korganizer/koeditorattachments.cpp b/korganizer/koeditorattachments.cpp
new file mode 100644
index 00000000..51dd6304
--- /dev/null
+++ b/korganizer/koeditorattachments.cpp
@@ -0,0 +1,501 @@
+/*
+ This file is part of KOrganizer.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2005 Reinhold Kainhofer <reinhold@kainhofer.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include "koeditorattachments.h"
+
+#include <libkcal/incidence.h>
+#include <libkdepim/kpimurlrequesterdlg.h>
+#include <libkdepim/kfileio.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmdcodec.h>
+#include <kmessagebox.h>
+#include <kiconview.h>
+#include <krun.h>
+#include <kurldrag.h>
+#include <ktempfile.h>
+#include <ktempdir.h>
+#include <kio/netaccess.h>
+#include <kmimetype.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <kstdaction.h>
+#include <kactioncollection.h>
+#include <kpopupmenu.h>
+
+#include <qfile.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qdragobject.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+
+#include <cassert>
+#include <set>
+
+class AttachmentListItem : public KIconViewItem
+{
+ public:
+ AttachmentListItem( KCal::Attachment*att, QIconView *parent ) :
+ KIconViewItem( parent )
+ {
+ if ( att ) {
+ mAttachment = new KCal::Attachment( *att );
+ } else {
+ mAttachment = new KCal::Attachment( QString::null );
+ }
+ readAttachment();
+ setDragEnabled( true );
+ }
+ ~AttachmentListItem() { delete mAttachment; }
+ KCal::Attachment *attachment() const { return mAttachment; }
+
+ void setUri( const QString &uri )
+ {
+ mAttachment->setUri( uri );
+ readAttachment();
+ }
+ void setData( const char *base64 )
+ {
+ mAttachment->setData( base64 );
+ readAttachment();
+ }
+ void setMimeType( const QString &mime )
+ {
+ mAttachment->setMimeType( mime );
+ readAttachment();
+ }
+ void setLabel( const QString &label )
+ {
+ mAttachment->setLabel( label );
+ readAttachment();
+ }
+
+ void readAttachment()
+ {
+ if ( mAttachment->isUri() )
+ setText( mAttachment->uri() );
+ else {
+ if ( mAttachment->label().isEmpty() )
+ setText( i18n("[Binary data]") );
+ else
+ setText( mAttachment->label() );
+ }
+ KMimeType::Ptr mt = KMimeType::mimeType( mAttachment->mimeType() );
+ if ( mt ) {
+ const QString iconName( mt->icon( QString(), false ) );
+ QPixmap pix = KGlobal::iconLoader( )->loadIcon( iconName, KIcon::Small );
+ if ( pix.isNull() )
+ pix = KGlobal::iconLoader( )->loadIcon( "unknown", KIcon::Small );
+ if ( !pix.isNull() )
+ setPixmap( pix );
+ }
+ }
+
+ private:
+ KCal::Attachment *mAttachment;
+};
+
+class AttachmentIconView : public KIconView
+{
+ friend class KOEditorAttachments;
+ public:
+ AttachmentIconView( KOEditorAttachments* parent=0 )
+ :KIconView( parent ),
+ mParent( parent )
+ {
+ setAcceptDrops( true );
+ setSelectionMode( QIconView::Extended );
+ setMode( KIconView::Select );
+ setItemTextPos( QIconView::Right );
+ setArrangement( QIconView::LeftToRight );
+ setMaxItemWidth( QMAX(maxItemWidth(), 250) );
+ setMinimumHeight( QMAX(fontMetrics().height(), 16) + 12 );
+ }
+ ~AttachmentIconView()
+ {
+ for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) {
+ delete *it;
+ }
+ }
+ protected:
+ QDragObject * dragObject()
+ {
+ KURL::List urls;
+ for ( QIconViewItem *it = firstItem( ); it; it = it->nextItem( ) ) {
+ if ( !it->isSelected() ) continue;
+ AttachmentListItem * item = dynamic_cast<AttachmentListItem*>( it );
+ if ( !item ) return 0;
+ KCal::Attachment * att = item->attachment();
+ assert( att );
+ KURL url;
+ if ( att->isUri() ) {
+ url.setPath( att->uri() );
+ } else {
+ KTempDir * tempDir = new KTempDir(); // will be deleted on editor close
+ tempDir->setAutoDelete( true );
+ mTempDirs.insert( tempDir );
+ QByteArray encoded;
+ encoded.duplicate( att->data(), strlen(att->data()) );
+ QByteArray decoded;
+ KCodecs::base64Decode( encoded, decoded );
+ const QString fileName = tempDir->name( ) + "/" + att->label();
+ KPIM::kByteArrayToFile( decoded, fileName, false, false, false );
+ url.setPath( fileName );
+ }
+ urls << url;
+ }
+ KURLDrag *drag = new KURLDrag( urls, this );
+ return drag;
+ }
+ void contentsDropEvent( QDropEvent* event )
+ {
+ mParent->handlePasteOrDrop( event );
+ }
+ private:
+ std::set<KTempDir*> mTempDirs;
+ KOEditorAttachments* mParent;
+};
+
+KOEditorAttachments::KOEditorAttachments( int spacing, QWidget *parent,
+ const char *name )
+ : QWidget( parent, name )
+{
+ QBoxLayout *topLayout = new QHBoxLayout( this );
+ topLayout->setSpacing( spacing );
+
+ QLabel *label = new QLabel( i18n("Attachments:"), this );
+ topLayout->addWidget( label );
+
+ mAttachments = new AttachmentIconView( this );
+ QWhatsThis::add( mAttachments,
+ i18n("Displays a list of current items (files, mail, etc.) "
+ "that have been associated with this event or to-do. ") );
+ topLayout->addWidget( mAttachments );
+ connect( mAttachments, SIGNAL( doubleClicked( QIconViewItem * ) ),
+ SLOT( showAttachment( QIconViewItem * ) ) );
+ connect( mAttachments, SIGNAL(selectionChanged()),
+ SLOT(selectionChanged()) );
+ connect( mAttachments, SIGNAL(contextMenuRequested(QIconViewItem*,const QPoint&)),
+ SLOT(contextMenu(QIconViewItem*,const QPoint&)) );
+
+ mAddMenu = new KPopupMenu( this );
+ mContextMenu = new KPopupMenu( this );
+
+ KActionCollection* ac = new KActionCollection( this, this );
+
+ mOpenAction = new KAction( i18n("View"), 0, this, SLOT(slotShow()), ac );
+ mOpenAction->plug( mContextMenu );
+ mContextMenu->insertSeparator();
+
+ mCopyAction = KStdAction::copy(this, SLOT(slotCopy( ) ), ac );
+ mCopyAction->plug( mContextMenu );
+ mCutAction = KStdAction::cut(this, SLOT(slotCut( ) ), ac );
+ mCutAction->plug( mContextMenu );
+ KAction *action = KStdAction::paste(this, SLOT(slotPaste( ) ), ac );
+ action->plug( mContextMenu );
+
+ action = new KAction( i18n("&Attach File..."), 0, this, SLOT(slotAddData()), ac );
+ action->setWhatsThis( i18n("Shows a dialog used to select an attachment "
+ "to add to this event or to-do as link as inline data.") );
+ action->plug( mAddMenu );
+ action = new KAction( i18n("Attach &Link..."), 0, this, SLOT(slotAdd()), ac );
+ action->setWhatsThis( i18n("Shows a dialog used to select an attachment "
+ "to add to this event or to-do as link.") );
+ action->plug( mAddMenu );
+
+ QPushButton *addButton = new QPushButton( this );
+ addButton->setIconSet( SmallIconSet( "add" ) );
+ addButton->setPopup( mAddMenu );
+ topLayout->addWidget( addButton );
+
+ mRemoveBtn = new QPushButton( this );
+ mRemoveBtn->setIconSet( SmallIconSet( "remove" ) );
+ QToolTip::add( mRemoveBtn, i18n("&Remove") );
+ QWhatsThis::add( mRemoveBtn,
+ i18n("Removes the attachment selected in the list above "
+ "from this event or to-do.") );
+ topLayout->addWidget( mRemoveBtn );
+ connect( mRemoveBtn, SIGNAL( clicked() ), SLOT( slotRemove() ) );
+
+ selectionChanged();
+ setAcceptDrops( true );
+}
+
+KOEditorAttachments::~KOEditorAttachments()
+{
+}
+
+bool KOEditorAttachments::hasAttachments()
+{
+ return mAttachments->count() != 0;
+}
+
+void KOEditorAttachments::dragEnterEvent( QDragEnterEvent* event )
+{
+ event->accept( KURLDrag::canDecode( event ) | QTextDrag::canDecode( event ) );
+}
+
+void KOEditorAttachments::handlePasteOrDrop( QMimeSource* source )
+{
+ KURL::List urls;
+ QString text;
+ if ( KURLDrag::decode( source, urls ) ) {
+ const bool asUri = KMessageBox::questionYesNo( this,
+ i18n("Do you want to link to the attachments, or include them in the event?"),
+ i18n("Attach as link?"), i18n("As Link"), i18n("As File") ) == KMessageBox::Yes;
+ for ( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) {
+ addAttachment( (*it).url(), QString::null, asUri );
+ }
+ } else if ( QTextDrag::decode( source, text ) ) {
+ QStringList lst = QStringList::split( '\n', text );
+ for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
+ addAttachment( (*it) );
+ }
+ }
+}
+
+void KOEditorAttachments::dropEvent( QDropEvent* event )
+{
+ handlePasteOrDrop( event );
+}
+
+void KOEditorAttachments::showAttachment( QIconViewItem *item )
+{
+ AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item);
+ if ( !attitem || !attitem->attachment() ) return;
+
+ KCal::Attachment *att = attitem->attachment();
+ if ( att->isUri() ) {
+ emit openURL( att->uri() );
+ } else {
+ KTempFile f;
+ if ( !f.file() )
+ return;
+ QByteArray encoded;
+ encoded.duplicate( att->data(), strlen(att->data()) );
+ QByteArray decoded;
+ KCodecs::base64Decode( encoded, decoded );
+ f.file()->writeBlock( decoded );
+ f.file()->close();
+ KRun::runURL( f.name(), att->mimeType(), true, false );
+ }
+}
+
+void KOEditorAttachments::slotAdd()
+{
+ KURL uri = KPimURLRequesterDlg::getURL( QString::null, i18n(
+ "URL (e.g. a web page) or file to be attached (only "
+ "the link will be attached, not the file itself):"), this,
+ i18n("Add Attachment") );
+ if ( !uri.isEmpty() ) {
+ addAttachment( uri );
+ }
+}
+
+void KOEditorAttachments::slotAddData()
+{
+ KURL uri = KFileDialog::getOpenFileName( QString(), QString(), this, i18n("Add Attachment") );
+ if ( !uri.isEmpty() ) {
+ addAttachment( uri, QString::null, false );
+ }
+}
+
+void KOEditorAttachments::slotEdit()
+{
+ QIconViewItem *item = mAttachments->currentItem();
+ AttachmentListItem *attitem = static_cast<AttachmentListItem*>(item);
+ if ( !attitem || !attitem->attachment() ) return;
+
+ KCal::Attachment *att = attitem->attachment();
+ if ( att->isUri() ) {
+ KURL uri = KPimURLRequesterDlg::getURL( att->uri(), i18n(
+ "URL (e.g. a web page) or file to be attached (only "
+ "the link will be attached, not the file itself):"), this,
+ i18n("Edit Attachment") );
+
+ if ( !uri.isEmpty() )
+ attitem->setUri( uri.url() );
+ } else {
+ KURL uri = KPimURLRequesterDlg::getURL( QString::null, i18n(
+ "File to be attached:"), this, i18n("Add Attachment") );
+ if ( !uri.isEmpty() ) {
+ QString tmpFile;
+ if ( KIO::NetAccess::download( uri, tmpFile, this ) ) {
+ QFile f( tmpFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+ QByteArray data = f.readAll();
+ f.close();
+ attitem->setData( KCodecs::base64Encode( data ) );
+ attitem->setMimeType( KIO::NetAccess::mimetype( uri, this ) );
+ QString label = uri.fileName();
+ if ( label.isEmpty() )
+ label = uri.prettyURL();
+ attitem->setLabel( label );
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+ }
+ }
+}
+
+void KOEditorAttachments::slotRemove()
+{
+ QValueList<QIconViewItem*> selected;
+ for ( QIconViewItem *it = mAttachments->firstItem( ); it; it = it->nextItem( ) ) {
+ if ( !it->isSelected() ) continue;
+ selected << it;
+ }
+ if ( selected.isEmpty() || KMessageBox::warningContinueCancel(this,
+ selected.count() == 1?i18n("This item will be permanently deleted."):
+ i18n("The selected items will be permanently deleted."),
+ i18n("KOrganizer Confirmation"),KStdGuiItem::del()) != KMessageBox::Continue )
+ return;
+
+ for ( QValueList<QIconViewItem*>::iterator it( selected.begin() ), end( selected.end() ); it != end ; ++it ) {
+ delete *it;
+ }
+}
+
+void KOEditorAttachments::slotShow()
+{
+ for ( QIconViewItem *it = mAttachments->firstItem(); it; it = it->nextItem() ) {
+ if ( !it->isSelected() )
+ continue;
+ showAttachment( it );
+ }
+}
+
+void KOEditorAttachments::setDefaults()
+{
+ mAttachments->clear();
+}
+
+void KOEditorAttachments::addAttachment( const KURL &uri,
+ const QString &mimeType, bool asUri )
+{
+ AttachmentListItem *item = new AttachmentListItem( 0, mAttachments );
+ if ( asUri ) {
+ item->setUri( uri.url() );
+ if ( !mimeType.isEmpty() ) item->setMimeType( mimeType );
+ } else {
+ QString tmpFile;
+ if ( KIO::NetAccess::download( uri, tmpFile, this ) ) {
+ QFile f( tmpFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+ QByteArray data = f.readAll();
+ f.close();
+ item->setData( KCodecs::base64Encode( data ) );
+ if ( !mimeType.isEmpty() )
+ item->setMimeType( mimeType );
+ else
+ item->setMimeType( KIO::NetAccess::mimetype( uri, this ) );
+ QString label = uri.fileName();
+ if ( label.isEmpty() )
+ label = uri.prettyURL();
+ item->setLabel( label );
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+ }
+}
+
+
+void KOEditorAttachments::addAttachment( KCal::Attachment *attachment )
+{
+ new AttachmentListItem( attachment, mAttachments );
+}
+
+void KOEditorAttachments::readIncidence( KCal::Incidence *i )
+{
+ mAttachments->clear();
+
+ KCal::Attachment::List attachments = i->attachments();
+ KCal::Attachment::List::ConstIterator it;
+ for( it = attachments.begin(); it != attachments.end(); ++it ) {
+ addAttachment( (*it) );
+ }
+ if ( mAttachments->count() > 0 ) {
+ QTimer::singleShot( 0, mAttachments, SLOT(arrangeItemsInGrid()) );
+ }
+}
+
+void KOEditorAttachments::writeIncidence( KCal::Incidence *i )
+{
+ i->clearAttachments();
+
+ QIconViewItem *item;
+ AttachmentListItem *attitem;
+ for( item = mAttachments->firstItem(); item; item = item->nextItem() ) {
+ attitem = static_cast<AttachmentListItem*>(item);
+ if ( attitem )
+ i->addAttachment( new KCal::Attachment( *(attitem->attachment() ) ) );
+ }
+}
+
+
+void KOEditorAttachments::slotCopy()
+{
+ QApplication::clipboard()->setData( mAttachments->dragObject(), QClipboard::Clipboard );
+}
+
+void KOEditorAttachments::slotCut()
+{
+ slotCopy();
+ slotRemove();
+}
+
+void KOEditorAttachments::slotPaste()
+{
+ handlePasteOrDrop( QApplication::clipboard()->data() );
+}
+
+void KOEditorAttachments::selectionChanged()
+{
+ bool selected = false;
+ for ( QIconViewItem *item = mAttachments->firstItem(); item; item = item->nextItem() ) {
+ if ( item->isSelected() ) {
+ selected = true;
+ break;
+ }
+ }
+ mRemoveBtn->setEnabled( selected );
+}
+
+void KOEditorAttachments::contextMenu(QIconViewItem * item, const QPoint & pos)
+{
+ const bool enable = item != 0;
+ mOpenAction->setEnabled( enable );
+ mCopyAction->setEnabled( enable );
+ mCutAction->setEnabled( enable );
+ mContextMenu->exec( pos );
+}
+
+#include "koeditorattachments.moc"