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 TQt library by Trolltech AS, Norway (or with modified versions 00023 of TQt that use the same license as TQt), 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 TQt. 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 <tdelocale.h> 00045 #include <tdefiledialog.h> 00046 #include <tdemessagebox.h> 00047 #include <kiconloader.h> 00048 00049 #include <tqclipboard.h> 00050 #include <tqheader.h> 00051 #include <tqpopupmenu.h> 00052 #include <tqstyle.h> 00053 #include <kurldrag.h> 00054 #include <kurl.h> 00055 00056 00057 KMMimePartTree::KMMimePartTree( KMReaderWin* readerWin, 00058 TQWidget* parent, 00059 const char* name ) 00060 : TDEListView( parent, name ), 00061 mReaderWin( readerWin ), mSizeColumn(0) 00062 { 00063 setStyleDependantFrameWidth(); 00064 addColumn( i18n("Description") ); 00065 addColumn( i18n("Type") ); 00066 addColumn( i18n("Encoding") ); 00067 mSizeColumn = addColumn( i18n("Size") ); 00068 setColumnAlignment( 3, TQt::AlignRight ); 00069 00070 restoreLayoutIfPresent(); 00071 connect( this, TQT_SIGNAL( clicked( TQListViewItem* ) ), 00072 this, TQT_SLOT( itemClicked( TQListViewItem* ) ) ); 00073 connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*, 00074 const TQPoint&, int ) ), 00075 this, TQT_SLOT( itemRightClicked( TQListViewItem*, const TQPoint& ) ) ); 00076 setSelectionMode( TQListView::Extended ); 00077 setRootIsDecorated( false ); 00078 setAllColumnsShowFocus( true ); 00079 setShowToolTips( true ); 00080 setSorting(-1); 00081 setDragEnabled( true ); 00082 } 00083 00084 00085 static const char configGroup[] = "MimePartTree"; 00086 00087 KMMimePartTree::~KMMimePartTree() { 00088 saveLayout( KMKernel::config(), configGroup ); 00089 } 00090 00091 00092 void KMMimePartTree::restoreLayoutIfPresent() { 00093 // first column: soaks up the rest of the space: 00094 setColumnWidthMode( 0, Manual ); 00095 header()->setStretchEnabled( true, 0 ); 00096 // rest of the columns: 00097 if ( KMKernel::config()->hasGroup( configGroup ) ) { 00098 // there is a saved layout. use it... 00099 restoreLayout( KMKernel::config(), configGroup ); 00100 // and disable Maximum mode: 00101 for ( int i = 1 ; i < 4 ; ++i ) 00102 setColumnWidthMode( i, Manual ); 00103 } else { 00104 // columns grow with their contents: 00105 for ( int i = 1 ; i < 4 ; ++i ) 00106 setColumnWidthMode( i, Maximum ); 00107 } 00108 } 00109 00110 00111 void KMMimePartTree::itemClicked( TQListViewItem* item ) 00112 { 00113 if ( const KMMimePartTreeItem * i = dynamic_cast<KMMimePartTreeItem*>( item ) ) { 00114 if( mReaderWin->mRootNode == i->node() ) 00115 mReaderWin->update( true ); // Force update 00116 else 00117 mReaderWin->setMsgPart( i->node() ); 00118 } else 00119 kdWarning(5006) << "Item was not a KMMimePartTreeItem!" << endl; 00120 } 00121 00122 00123 void KMMimePartTree::itemRightClicked( TQListViewItem* item, 00124 const TQPoint& point ) 00125 { 00126 // TODO: remove this member var? 00127 mCurrentContextMenuItem = dynamic_cast<KMMimePartTreeItem*>( item ); 00128 if ( 0 == mCurrentContextMenuItem ) { 00129 kdDebug(5006) << "Item was not a KMMimePartTreeItem!" << endl; 00130 } 00131 else { 00132 TQPopupMenu* popup = new TQPopupMenu; 00133 if ( mCurrentContextMenuItem->node()->nodeId() > 2 && 00134 mCurrentContextMenuItem->node()->typeString() != "Multipart" ) { 00135 popup->insertItem( SmallIcon("document-open"), i18n("to open", "Open"), this, TQT_SLOT(slotOpen()) ); 00136 popup->insertItem( i18n("Open With..."), this, TQT_SLOT(slotOpenWith()) ); 00137 popup->insertItem( i18n("to view something", "View"), this, TQT_SLOT(slotView()) ); 00138 } 00139 popup->insertItem( SmallIcon("document-save-as"),i18n( "Save &As..." ), this, TQT_SLOT( slotSaveAs() ) ); 00140 /* 00141 * FIXME mkae optional? 00142 popup->insertItem( i18n( "Save as &Encoded..." ), this, 00143 TQT_SLOT( slotSaveAsEncoded() ) ); 00144 */ 00145 popup->insertItem( i18n( "Save All Attachments..." ), this, 00146 TQT_SLOT( slotSaveAll() ) ); 00147 // edit + delete only for attachments 00148 if ( mCurrentContextMenuItem->node()->nodeId() > 2 && 00149 mCurrentContextMenuItem->node()->typeString() != "Multipart" ) { 00150 popup->insertItem( SmallIcon("edit-copy"), i18n("Copy"), this, TQT_SLOT(slotCopy()) ); 00151 if ( GlobalSettings::self()->allowAttachmentDeletion() ) 00152 popup->insertItem( SmallIcon("edit-delete"), i18n( "Delete Attachment" ), 00153 this, TQT_SLOT( slotDelete() ) ); 00154 if ( GlobalSettings::self()->allowAttachmentEditing() ) 00155 popup->insertItem( SmallIcon( "edit" ), i18n( "Edit Attachment" ), 00156 this, TQT_SLOT( slotEdit() ) ); 00157 } 00158 if ( mCurrentContextMenuItem->node()->nodeId() > 0 ) 00159 popup->insertItem( i18n("Properties"), this, TQT_SLOT(slotProperties()) ); 00160 popup->exec( point ); 00161 delete popup; 00162 mCurrentContextMenuItem = 0; 00163 } 00164 } 00165 00166 //----------------------------------------------------------------------------- 00167 void KMMimePartTree::slotSaveAs() 00168 { 00169 saveSelectedBodyParts( false ); 00170 } 00171 00172 //----------------------------------------------------------------------------- 00173 void KMMimePartTree::slotSaveAsEncoded() 00174 { 00175 saveSelectedBodyParts( true ); 00176 } 00177 00178 //----------------------------------------------------------------------------- 00179 void KMMimePartTree::saveSelectedBodyParts( bool encoded ) 00180 { 00181 TQPtrList<TQListViewItem> selected = selectedItems(); 00182 00183 Q_ASSERT( !selected.isEmpty() ); 00184 if ( selected.isEmpty() ) 00185 return; 00186 00187 TQPtrListIterator<TQListViewItem> it( selected ); 00188 TQPtrList<partNode> parts; 00189 while ( it.current() ) { 00190 parts.append( static_cast<KMMimePartTreeItem *>(it.current())->node() ); 00191 ++it; 00192 } 00193 mReaderWin->setUpdateAttachment(); 00194 KMSaveAttachmentsCommand *command = 00195 new KMSaveAttachmentsCommand( this, parts, mReaderWin->message(), encoded ); 00196 command->start(); 00197 } 00198 00199 //----------------------------------------------------------------------------- 00200 void KMMimePartTree::slotSaveAll() 00201 { 00202 if( childCount() == 0) 00203 return; 00204 00205 mReaderWin->setUpdateAttachment(); 00206 KMCommand *command = 00207 new KMSaveAttachmentsCommand( this, mReaderWin->message() ); 00208 command->start(); 00209 } 00210 00211 //----------------------------------------------------------------------------- 00212 void KMMimePartTree::setStyleDependantFrameWidth() 00213 { 00214 // set the width of the frame to a reasonable value for the current GUI style 00215 int frameWidth; 00216 if( style().isA("KeramikStyle") ) 00217 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1; 00218 else 00219 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ); 00220 if ( frameWidth < 0 ) 00221 frameWidth = 0; 00222 if ( frameWidth != lineWidth() ) 00223 setLineWidth( frameWidth ); 00224 } 00225 00226 00227 //----------------------------------------------------------------------------- 00228 void KMMimePartTree::styleChange( TQStyle& oldStyle ) 00229 { 00230 setStyleDependantFrameWidth(); 00231 TDEListView::styleChange( oldStyle ); 00232 } 00233 00234 //----------------------------------------------------------------------------- 00235 void KMMimePartTree::correctSize( TQListViewItem * item ) 00236 { 00237 if (!item) return; 00238 00239 TDEIO::filesize_t totalSize = 0; 00240 TQListViewItem * myChild = item->firstChild(); 00241 while ( myChild ) 00242 { 00243 totalSize += static_cast<KMMimePartTreeItem*>(myChild)->origSize(); 00244 myChild = myChild->nextSibling(); 00245 } 00246 if ( totalSize > static_cast<KMMimePartTreeItem*>(item)->origSize() ) 00247 item->setText( mSizeColumn, TDEIO::convertSize(totalSize) ); 00248 if ( item->parent() ) 00249 correctSize( item->parent() ); 00250 } 00251 00252 void KMMimePartTree::slotDelete() 00253 { 00254 TQPtrList<TQListViewItem> selected = selectedItems(); 00255 if ( selected.count() != 1 ) 00256 return; 00257 mReaderWin->slotDeleteAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() ); 00258 } 00259 00260 void KMMimePartTree::slotEdit() 00261 { 00262 TQPtrList<TQListViewItem> selected = selectedItems(); 00263 if ( selected.count() != 1 ) 00264 return; 00265 mReaderWin->slotEditAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() ); 00266 } 00267 00268 void KMMimePartTree::slotOpen() 00269 { 00270 startHandleAttachmentCommand( KMHandleAttachmentCommand::Open ); 00271 } 00272 00273 void KMMimePartTree::slotOpenWith() 00274 { 00275 startHandleAttachmentCommand( KMHandleAttachmentCommand::OpenWith ); 00276 } 00277 00278 void KMMimePartTree::slotView() 00279 { 00280 startHandleAttachmentCommand( KMHandleAttachmentCommand::View ); 00281 } 00282 00283 void KMMimePartTree::slotProperties() 00284 { 00285 startHandleAttachmentCommand( KMHandleAttachmentCommand::Properties ); 00286 } 00287 00288 void KMMimePartTree::startHandleAttachmentCommand(int type) 00289 { 00290 TQPtrList<TQListViewItem> selected = selectedItems(); 00291 if ( selected.count() != 1 ) 00292 return; 00293 partNode* node = static_cast<KMMimePartTreeItem*>( selected.first() )->node(); 00294 TQString name = mReaderWin->tempFileUrlFromPartNode( node ).path(); 00295 KMHandleAttachmentCommand* command = new KMHandleAttachmentCommand( 00296 node, mReaderWin->message(), node->nodeId(), name, 00297 KMHandleAttachmentCommand::AttachmentAction( type ), 0, this ); 00298 connect( command, TQT_SIGNAL( showAttachment( int, const TQString& ) ), 00299 mReaderWin, TQT_SLOT( slotAtmView( int, const TQString& ) ) ); 00300 command->start(); 00301 } 00302 00303 void KMMimePartTree::slotCopy() 00304 { 00305 KURL::List urls; 00306 KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() ); 00307 if ( !item ) return; 00308 KURL url = mReaderWin->tempFileUrlFromPartNode( item->node() ); 00309 if ( !url.isValid() ) return; 00310 urls.append( url ); 00311 KURLDrag* drag = new KURLDrag( urls, this ); 00312 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard ); 00313 } 00314 00315 //============================================================================= 00316 KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTree * parent, 00317 partNode* node, 00318 const TQString & description, 00319 const TQString & mimetype, 00320 const TQString & encoding, 00321 TDEIO::filesize_t size ) 00322 : TQListViewItem( parent, description, 00323 TQString(), // set by setIconAndTextForType() 00324 encoding, 00325 TDEIO::convertSize( size ) ), 00326 mPartNode( node ), mOrigSize(size) 00327 { 00328 if( node ) 00329 node->setMimePartTreeItem( this ); 00330 setIconAndTextForType( mimetype ); 00331 if ( parent ) 00332 parent->correctSize(this); 00333 } 00334 00335 KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTreeItem * parent, 00336 partNode* node, 00337 const TQString & description, 00338 const TQString & mimetype, 00339 const TQString & encoding, 00340 TDEIO::filesize_t size, 00341 bool revertOrder ) 00342 : TQListViewItem( parent, description, 00343 TQString(), // set by setIconAndTextForType() 00344 encoding, 00345 TDEIO::convertSize( size ) ), 00346 mPartNode( node ), mOrigSize(size) 00347 { 00348 if( revertOrder && nextSibling() ){ 00349 TQListViewItem* sib = nextSibling(); 00350 while( sib->nextSibling() ) 00351 sib = sib->nextSibling(); 00352 moveItem( sib ); 00353 } 00354 if( node ) 00355 node->setMimePartTreeItem( this ); 00356 setIconAndTextForType( mimetype ); 00357 if ( listView() ) 00358 static_cast<KMMimePartTree*>(listView())->correctSize(this); 00359 } 00360 00361 void KMMimePartTreeItem::setIconAndTextForType( const TQString & mime ) 00362 { 00363 TQString mimetype = mime.lower(); 00364 if ( mimetype.startsWith( "multipart/" ) ) { 00365 setText( 1, mimetype ); 00366 setPixmap( 0, SmallIcon("folder") ); 00367 } else if ( mimetype == "application/octet-stream" ) { 00368 setText( 1, i18n("Unspecified Binary Data") ); // don't show "Unknown"... 00369 setPixmap( 0, SmallIcon("unknown") ); 00370 } else { 00371 KMimeType::Ptr mtp = KMimeType::mimeType( mimetype ); 00372 setText( 1, (mtp && !mtp->comment().isEmpty()) ? mtp->comment() : mimetype ); 00373 setPixmap( 0, mtp ? mtp->pixmap( TDEIcon::Small) : SmallIcon("unknown") ); 00374 } 00375 } 00376 00377 00378 void KMMimePartTree::startDrag() 00379 { 00380 KURL::List urls; 00381 KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() ); 00382 if ( !item ) return; 00383 partNode *node = item->node(); 00384 if ( !node ) return; 00385 KURL url = mReaderWin->tempFileUrlFromPartNode( node ); 00386 if (!url.isValid() ) return; 00387 urls.append( url ); 00388 KURLDrag* drag = new KURLDrag( urls, this ); 00389 drag->drag(); 00390 } 00391 00392 #include "kmmimeparttree.moc" 00393