kmail

kmmimeparttree.cpp

00001 /* -*- c++ -*-
00002     kmmimeparttree.h A MIME part tree viwer.
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2002-2004 Klarälvdalens Datakonsult AB
00006 
00007     KMail is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMail is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this program with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 
00033 #include <config.h>
00034 
00035 #include "kmmimeparttree.h"
00036 
00037 #include "kmreaderwin.h"
00038 #include "partNode.h"
00039 #include "kmmsgpart.h"
00040 #include "kmkernel.h"
00041 #include "kmcommands.h"
00042 
00043 #include <kdebug.h>
00044 #include <klocale.h>
00045 #include <kfiledialog.h>
00046 #include <kmessagebox.h>
00047 #include <kiconloader.h>
00048 
00049 #include <qheader.h>
00050 #include <qpopupmenu.h>
00051 #include <qstyle.h>
00052 #include <kurldrag.h>
00053 #include <kurl.h>
00054 
00055 
00056 KMMimePartTree::KMMimePartTree( KMReaderWin* readerWin,
00057                                 QWidget* parent,
00058                                 const char* name )
00059     : KListView(  parent, name ),
00060       mReaderWin( readerWin ), mSizeColumn(0)
00061 {
00062     setStyleDependantFrameWidth();
00063     addColumn( i18n("Description") );
00064     addColumn( i18n("Type") );
00065     addColumn( i18n("Encoding") );
00066     mSizeColumn = addColumn( i18n("Size") );
00067     setColumnAlignment( 3, Qt::AlignRight );
00068 
00069     restoreLayoutIfPresent();
00070     connect( this, SIGNAL( clicked( QListViewItem* ) ),
00071              this, SLOT( itemClicked( QListViewItem* ) ) );
00072     connect( this, SIGNAL( contextMenuRequested( QListViewItem*,
00073                                                  const QPoint&, int ) ),
00074              this, SLOT( itemRightClicked( QListViewItem*, const QPoint& ) ) );
00075     setSelectionMode( QListView::Extended );
00076     setRootIsDecorated( false );
00077     setAllColumnsShowFocus( true );
00078     setShowToolTips( true );
00079     setSorting(-1);
00080     setDragEnabled( true );
00081 }
00082 
00083 
00084 static const char configGroup[] = "MimePartTree";
00085 
00086 KMMimePartTree::~KMMimePartTree() {
00087   saveLayout( KMKernel::config(), configGroup );
00088 }
00089 
00090 
00091 void KMMimePartTree::restoreLayoutIfPresent() {
00092   // first column: soaks up the rest of the space:
00093   setColumnWidthMode( 0, Manual );
00094   header()->setStretchEnabled( true, 0 );
00095   // rest of the columns:
00096   if ( KMKernel::config()->hasGroup( configGroup ) ) {
00097     // there is a saved layout. use it...
00098     restoreLayout( KMKernel::config(), configGroup );
00099     // and disable Maximum mode:
00100     for ( int i = 1 ; i < 4 ; ++i )
00101       setColumnWidthMode( i, Manual );
00102   } else {
00103     // columns grow with their contents:
00104     for ( int i = 1 ; i < 4 ; ++i )
00105       setColumnWidthMode( i, Maximum );
00106   }
00107 }
00108 
00109 
00110 void KMMimePartTree::itemClicked( QListViewItem* item )
00111 {
00112   if ( const KMMimePartTreeItem * i = dynamic_cast<KMMimePartTreeItem*>( item ) ) {
00113     if( mReaderWin->mRootNode == i->node() )
00114       mReaderWin->update( true ); // Force update
00115     else
00116       mReaderWin->setMsgPart( i->node() );
00117   } else
00118     kdWarning(5006) << "Item was not a KMMimePartTreeItem!" << endl;
00119 }
00120 
00121 
00122 void KMMimePartTree::itemRightClicked( QListViewItem* item,
00123                                        const QPoint& point )
00124 {
00125     // TODO: remove this member var?
00126     mCurrentContextMenuItem = dynamic_cast<KMMimePartTreeItem*>( item );
00127     if ( 0 == mCurrentContextMenuItem ) {
00128         kdDebug(5006) << "Item was not a KMMimePartTreeItem!" << endl;
00129     }
00130     else {
00131         kdDebug(5006) << "\n**\n** KMMimePartTree::itemRightClicked() **\n**" << endl;
00132 
00133         QPopupMenu* popup = new QPopupMenu;
00134         popup->insertItem( SmallIcon("filesaveas"),i18n( "Save &As..." ), this, SLOT( slotSaveAs() ) );
00135         /*
00136          * FIXME mkae optional?
00137         popup->insertItem( i18n( "Save as &Encoded..." ), this,
00138                            SLOT( slotSaveAsEncoded() ) );
00139         */
00140         popup->insertItem( i18n( "Save All Attachments..." ), this,
00141                            SLOT( slotSaveAll() ) );
00142         // edit + delete only for attachments
00143         if ( mCurrentContextMenuItem->node()->nodeId() > 2 ) {
00144           popup->insertItem( SmallIcon("editdelete"), i18n( "Delete Attachment" ),
00145                             this, SLOT( slotDelete() ) );
00146           popup->insertItem( SmallIcon( "edit" ), i18n( "Edit Attachment" ),
00147                             this, SLOT( slotEdit() ) );
00148         }
00149         popup->exec( point );
00150         delete popup;
00151         mCurrentContextMenuItem = 0;
00152     }
00153 }
00154 
00155 //-----------------------------------------------------------------------------
00156 void KMMimePartTree::slotSaveAs()
00157 {
00158   saveSelectedBodyParts( false );
00159 }
00160 
00161 //-----------------------------------------------------------------------------
00162 void KMMimePartTree::slotSaveAsEncoded()
00163 {
00164   saveSelectedBodyParts( true );
00165 }
00166 
00167 //-----------------------------------------------------------------------------
00168 void KMMimePartTree::saveSelectedBodyParts( bool encoded )
00169 {
00170   QPtrList<QListViewItem> selected = selectedItems();
00171 
00172   Q_ASSERT( !selected.isEmpty() );
00173   if ( selected.isEmpty() )
00174     return;
00175 
00176   QPtrListIterator<QListViewItem> it( selected );
00177   QPtrList<partNode> parts;
00178   while ( it.current() ) {
00179     parts.append( static_cast<KMMimePartTreeItem *>(it.current())->node() );
00180     ++it;
00181   }
00182   mReaderWin->setUpdateAttachment();
00183   KMSaveAttachmentsCommand *command =
00184     new KMSaveAttachmentsCommand( this, parts, mReaderWin->message(), encoded );
00185   command->start();
00186 }
00187 
00188 //-----------------------------------------------------------------------------
00189 void KMMimePartTree::slotSaveAll()
00190 {
00191     if( childCount() == 0)
00192         return;
00193 
00194     mReaderWin->setUpdateAttachment();
00195     KMCommand *command =
00196       new KMSaveAttachmentsCommand( this, mReaderWin->message() );
00197     command->start();
00198 }
00199 
00200 //-----------------------------------------------------------------------------
00201 void KMMimePartTree::setStyleDependantFrameWidth()
00202 {
00203   // set the width of the frame to a reasonable value for the current GUI style
00204   int frameWidth;
00205   if( style().isA("KeramikStyle") )
00206     frameWidth = style().pixelMetric( QStyle::PM_DefaultFrameWidth ) - 1;
00207   else
00208     frameWidth = style().pixelMetric( QStyle::PM_DefaultFrameWidth );
00209   if ( frameWidth < 0 )
00210     frameWidth = 0;
00211   if ( frameWidth != lineWidth() )
00212     setLineWidth( frameWidth );
00213 }
00214 
00215 
00216 //-----------------------------------------------------------------------------
00217 void KMMimePartTree::styleChange( QStyle& oldStyle )
00218 {
00219   setStyleDependantFrameWidth();
00220   KListView::styleChange( oldStyle );
00221 }
00222 
00223 //-----------------------------------------------------------------------------
00224 void KMMimePartTree::correctSize( QListViewItem * item )
00225 {
00226   if (!item) return;
00227 
00228   KIO::filesize_t totalSize = 0;
00229   QListViewItem * myChild = item->firstChild();
00230   while ( myChild )
00231   {
00232     totalSize += static_cast<KMMimePartTreeItem*>(myChild)->origSize();
00233     myChild = myChild->nextSibling();
00234   }
00235   if ( totalSize > static_cast<KMMimePartTreeItem*>(item)->origSize() )
00236     item->setText( mSizeColumn, KIO::convertSize(totalSize) );
00237   if ( item->parent() )
00238     correctSize( item->parent() );
00239 }
00240 
00241 void KMMimePartTree::slotDelete()
00242 {
00243   QPtrList<QListViewItem> selected = selectedItems();
00244   if ( selected.count() != 1 )
00245     return;
00246   mReaderWin->slotDeleteAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
00247 }
00248 
00249 void KMMimePartTree::slotEdit()
00250 {
00251   QPtrList<QListViewItem> selected = selectedItems();
00252   if ( selected.count() != 1 )
00253     return;
00254   mReaderWin->slotEditAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
00255 }
00256 
00257 
00258 //=============================================================================
00259 KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTree * parent,
00260                                         partNode* node,
00261                                         const QString & description,
00262                                         const QString & mimetype,
00263                                         const QString & encoding,
00264                                         KIO::filesize_t size )
00265   : QListViewItem( parent, description,
00266            QString::null, // set by setIconAndTextForType()
00267            encoding,
00268            KIO::convertSize( size ) ),
00269     mPartNode( node ), mOrigSize(size)
00270 {
00271   if( node )
00272     node->setMimePartTreeItem( this );
00273   setIconAndTextForType( mimetype );
00274   if ( parent )
00275     parent->correctSize(this);
00276 }
00277 
00278 KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTreeItem * parent,
00279                                         partNode* node,
00280                                         const QString & description,
00281                                         const QString & mimetype,
00282                                         const QString & encoding,
00283                                         KIO::filesize_t size,
00284                                         bool revertOrder )
00285   : QListViewItem( parent, description,
00286            QString::null, // set by setIconAndTextForType()
00287            encoding,
00288            KIO::convertSize( size ) ),
00289     mPartNode( node ), mOrigSize(size)
00290 {
00291   if( revertOrder && nextSibling() ){
00292     QListViewItem* sib = nextSibling();
00293     while( sib->nextSibling() )
00294       sib = sib->nextSibling();
00295     moveItem( sib );
00296   }
00297   if( node )
00298     node->setMimePartTreeItem( this );
00299   setIconAndTextForType( mimetype );
00300   if ( listView() )
00301     static_cast<KMMimePartTree*>(listView())->correctSize(this);
00302 }
00303 
00304 void KMMimePartTreeItem::setIconAndTextForType( const QString & mime )
00305 {
00306   QString mimetype = mime.lower();
00307   if ( mimetype.startsWith( "multipart/" ) ) {
00308     setText( 1, mimetype );
00309     setPixmap( 0, SmallIcon("folder") );
00310   } else if ( mimetype == "application/octet-stream" ) {
00311     setText( 1, i18n("Unspecified Binary Data") ); // don't show "Unknown"...
00312     setPixmap( 0, SmallIcon("unknown") );
00313   } else {
00314     KMimeType::Ptr mtp = KMimeType::mimeType( mimetype );
00315     setText( 1, (mtp && !mtp->comment().isEmpty()) ? mtp->comment() : mimetype );
00316     setPixmap( 0, mtp ? mtp->pixmap( KIcon::Small) : SmallIcon("unknown") );
00317   }
00318 }
00319 
00320 
00321 void KMMimePartTree::startDrag()
00322 {
00323     KURL::List urls;
00324     KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() );
00325     if ( !item ) return;
00326     partNode *node = item->node();
00327     if ( !node ) return;
00328     KURL url = mReaderWin->tempFileUrlFromPartNode( node );
00329     if (!url.isValid() ) return;
00330     urls.append( url );
00331     KURLDrag* drag = new KURLDrag( urls, this );
00332     drag->drag();
00333 }
00334 
00335 #include "kmmimeparttree.moc"
00336 
KDE Home | KDE Accessibility Home | Description of Access Keys