|
|
|
/* -*- c++ -*-
|
|
|
|
kmmimeparttree.h A MIME part tree viwer.
|
|
|
|
|
|
|
|
This file is part of KMail, the KDE mail client.
|
|
|
|
Copyright (c) 2002-2004 Klarälvdalens Datakonsult AB
|
|
|
|
|
|
|
|
KMail is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU General Public License, version 2, as
|
|
|
|
published by the Free Software Foundation.
|
|
|
|
|
|
|
|
KMail 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
|
|
|
|
|
|
|
|
In addition, as a special exception, the copyright holders give
|
|
|
|
permission to link the code of this program with any edition of
|
|
|
|
the TQt library by Trolltech AS, Norway (or with modified versions
|
|
|
|
of TQt that use the same license as TQt), and distribute linked
|
|
|
|
combinations including the two. You must obey the GNU General
|
|
|
|
Public License in all respects for all of the code used other than
|
|
|
|
TQt. If you modify this file, you may extend this exception to
|
|
|
|
your version of the file, but you are not obligated to do so. If
|
|
|
|
you do not wish to do so, delete this exception statement from
|
|
|
|
your version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "kmmimeparttree.h"
|
|
|
|
|
|
|
|
#include "kmreaderwin.h"
|
|
|
|
#include "partNode.h"
|
|
|
|
#include "kmmsgpart.h"
|
|
|
|
#include "kmkernel.h"
|
|
|
|
#include "kmcommands.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqheader.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <kurl.h>
|
|
|
|
|
|
|
|
|
|
|
|
KMMimePartTree::KMMimePartTree( KMReaderWin* readerWin,
|
|
|
|
TQWidget* parent,
|
|
|
|
const char* name )
|
|
|
|
: KListView( parent, name ),
|
|
|
|
mReaderWin( readerWin ), mSizeColumn(0)
|
|
|
|
{
|
|
|
|
setStyleDependantFrameWidth();
|
|
|
|
addColumn( i18n("Description") );
|
|
|
|
addColumn( i18n("Type") );
|
|
|
|
addColumn( i18n("Encoding") );
|
|
|
|
mSizeColumn = addColumn( i18n("Size") );
|
|
|
|
setColumnAlignment( 3, TQt::AlignRight );
|
|
|
|
|
|
|
|
restoreLayoutIfPresent();
|
|
|
|
connect( this, TQT_SIGNAL( clicked( TQListViewItem* ) ),
|
|
|
|
this, TQT_SLOT( itemClicked( TQListViewItem* ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*,
|
|
|
|
const TQPoint&, int ) ),
|
|
|
|
this, TQT_SLOT( itemRightClicked( TQListViewItem*, const TQPoint& ) ) );
|
|
|
|
setSelectionMode( TQListView::Extended );
|
|
|
|
setRootIsDecorated( false );
|
|
|
|
setAllColumnsShowFocus( true );
|
|
|
|
setShowToolTips( true );
|
|
|
|
setSorting(-1);
|
|
|
|
setDragEnabled( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char configGroup[] = "MimePartTree";
|
|
|
|
|
|
|
|
KMMimePartTree::~KMMimePartTree() {
|
|
|
|
saveLayout( KMKernel::config(), configGroup );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KMMimePartTree::restoreLayoutIfPresent() {
|
|
|
|
// first column: soaks up the rest of the space:
|
|
|
|
setColumnWidthMode( 0, Manual );
|
|
|
|
header()->setStretchEnabled( true, 0 );
|
|
|
|
// rest of the columns:
|
|
|
|
if ( KMKernel::config()->hasGroup( configGroup ) ) {
|
|
|
|
// there is a saved layout. use it...
|
|
|
|
restoreLayout( KMKernel::config(), configGroup );
|
|
|
|
// and disable Maximum mode:
|
|
|
|
for ( int i = 1 ; i < 4 ; ++i )
|
|
|
|
setColumnWidthMode( i, Manual );
|
|
|
|
} else {
|
|
|
|
// columns grow with their contents:
|
|
|
|
for ( int i = 1 ; i < 4 ; ++i )
|
|
|
|
setColumnWidthMode( i, Maximum );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KMMimePartTree::itemClicked( TQListViewItem* item )
|
|
|
|
{
|
|
|
|
if ( const KMMimePartTreeItem * i = dynamic_cast<KMMimePartTreeItem*>( item ) ) {
|
|
|
|
if( mReaderWin->mRootNode == i->node() )
|
|
|
|
mReaderWin->update( true ); // Force update
|
|
|
|
else
|
|
|
|
mReaderWin->setMsgPart( i->node() );
|
|
|
|
} else
|
|
|
|
kdWarning(5006) << "Item was not a KMMimePartTreeItem!" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KMMimePartTree::itemRightClicked( TQListViewItem* item,
|
|
|
|
const TQPoint& point )
|
|
|
|
{
|
|
|
|
// TODO: remove this member var?
|
|
|
|
mCurrentContextMenuItem = dynamic_cast<KMMimePartTreeItem*>( item );
|
|
|
|
if ( 0 == mCurrentContextMenuItem ) {
|
|
|
|
kdDebug(5006) << "Item was not a KMMimePartTreeItem!" << endl;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQPopupMenu* popup = new TQPopupMenu;
|
|
|
|
if ( mCurrentContextMenuItem->node()->nodeId() > 2 &&
|
|
|
|
mCurrentContextMenuItem->node()->typeString() != "Multipart" ) {
|
|
|
|
popup->insertItem( SmallIcon("fileopen"), i18n("to open", "Open"), this, TQT_SLOT(slotOpen()) );
|
|
|
|
popup->insertItem( i18n("Open With..."), this, TQT_SLOT(slotOpenWith()) );
|
|
|
|
popup->insertItem( i18n("to view something", "View"), this, TQT_SLOT(slotView()) );
|
|
|
|
}
|
|
|
|
popup->insertItem( SmallIcon("filesaveas"),i18n( "Save &As..." ), this, TQT_SLOT( slotSaveAs() ) );
|
|
|
|
/*
|
|
|
|
* FIXME mkae optional?
|
|
|
|
popup->insertItem( i18n( "Save as &Encoded..." ), this,
|
|
|
|
TQT_SLOT( slotSaveAsEncoded() ) );
|
|
|
|
*/
|
|
|
|
popup->insertItem( i18n( "Save All Attachments..." ), this,
|
|
|
|
TQT_SLOT( slotSaveAll() ) );
|
|
|
|
// edit + delete only for attachments
|
|
|
|
if ( mCurrentContextMenuItem->node()->nodeId() > 2 &&
|
|
|
|
mCurrentContextMenuItem->node()->typeString() != "Multipart" ) {
|
|
|
|
popup->insertItem( SmallIcon("editcopy"), i18n("Copy"), this, TQT_SLOT(slotCopy()) );
|
|
|
|
if ( GlobalSettings::self()->allowAttachmentDeletion() )
|
|
|
|
popup->insertItem( SmallIcon("editdelete"), i18n( "Delete Attachment" ),
|
|
|
|
this, TQT_SLOT( slotDelete() ) );
|
|
|
|
if ( GlobalSettings::self()->allowAttachmentEditing() )
|
|
|
|
popup->insertItem( SmallIcon( "edit" ), i18n( "Edit Attachment" ),
|
|
|
|
this, TQT_SLOT( slotEdit() ) );
|
|
|
|
}
|
|
|
|
if ( mCurrentContextMenuItem->node()->nodeId() > 0 )
|
|
|
|
popup->insertItem( i18n("Properties"), this, TQT_SLOT(slotProperties()) );
|
|
|
|
popup->exec( point );
|
|
|
|
delete popup;
|
|
|
|
mCurrentContextMenuItem = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::slotSaveAs()
|
|
|
|
{
|
|
|
|
saveSelectedBodyParts( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::slotSaveAsEncoded()
|
|
|
|
{
|
|
|
|
saveSelectedBodyParts( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::saveSelectedBodyParts( bool encoded )
|
|
|
|
{
|
|
|
|
TQPtrList<TQListViewItem> selected = selectedItems();
|
|
|
|
|
|
|
|
Q_ASSERT( !selected.isEmpty() );
|
|
|
|
if ( selected.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQPtrListIterator<TQListViewItem> it( selected );
|
|
|
|
TQPtrList<partNode> parts;
|
|
|
|
while ( it.current() ) {
|
|
|
|
parts.append( static_cast<KMMimePartTreeItem *>(it.current())->node() );
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
mReaderWin->setUpdateAttachment();
|
|
|
|
KMSaveAttachmentsCommand *command =
|
|
|
|
new KMSaveAttachmentsCommand( this, parts, mReaderWin->message(), encoded );
|
|
|
|
command->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::slotSaveAll()
|
|
|
|
{
|
|
|
|
if( childCount() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mReaderWin->setUpdateAttachment();
|
|
|
|
KMCommand *command =
|
|
|
|
new KMSaveAttachmentsCommand( this, mReaderWin->message() );
|
|
|
|
command->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::setStyleDependantFrameWidth()
|
|
|
|
{
|
|
|
|
// set the width of the frame to a reasonable value for the current GUI style
|
|
|
|
int frameWidth;
|
|
|
|
if( style().isA("KeramikStyle") )
|
|
|
|
frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
|
|
|
|
else
|
|
|
|
frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
|
|
|
|
if ( frameWidth < 0 )
|
|
|
|
frameWidth = 0;
|
|
|
|
if ( frameWidth != lineWidth() )
|
|
|
|
setLineWidth( frameWidth );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::styleChange( TQStyle& oldStyle )
|
|
|
|
{
|
|
|
|
setStyleDependantFrameWidth();
|
|
|
|
KListView::styleChange( oldStyle );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void KMMimePartTree::correctSize( TQListViewItem * item )
|
|
|
|
{
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
TDEIO::filesize_t totalSize = 0;
|
|
|
|
TQListViewItem * myChild = item->firstChild();
|
|
|
|
while ( myChild )
|
|
|
|
{
|
|
|
|
totalSize += static_cast<KMMimePartTreeItem*>(myChild)->origSize();
|
|
|
|
myChild = myChild->nextSibling();
|
|
|
|
}
|
|
|
|
if ( totalSize > static_cast<KMMimePartTreeItem*>(item)->origSize() )
|
|
|
|
item->setText( mSizeColumn, TDEIO::convertSize(totalSize) );
|
|
|
|
if ( item->parent() )
|
|
|
|
correctSize( item->parent() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotDelete()
|
|
|
|
{
|
|
|
|
TQPtrList<TQListViewItem> selected = selectedItems();
|
|
|
|
if ( selected.count() != 1 )
|
|
|
|
return;
|
|
|
|
mReaderWin->slotDeleteAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotEdit()
|
|
|
|
{
|
|
|
|
TQPtrList<TQListViewItem> selected = selectedItems();
|
|
|
|
if ( selected.count() != 1 )
|
|
|
|
return;
|
|
|
|
mReaderWin->slotEditAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotOpen()
|
|
|
|
{
|
|
|
|
startHandleAttachmentCommand( KMHandleAttachmentCommand::Open );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotOpenWith()
|
|
|
|
{
|
|
|
|
startHandleAttachmentCommand( KMHandleAttachmentCommand::OpenWith );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotView()
|
|
|
|
{
|
|
|
|
startHandleAttachmentCommand( KMHandleAttachmentCommand::View );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotProperties()
|
|
|
|
{
|
|
|
|
startHandleAttachmentCommand( KMHandleAttachmentCommand::Properties );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::startHandleAttachmentCommand(int type)
|
|
|
|
{
|
|
|
|
TQPtrList<TQListViewItem> selected = selectedItems();
|
|
|
|
if ( selected.count() != 1 )
|
|
|
|
return;
|
|
|
|
partNode* node = static_cast<KMMimePartTreeItem*>( selected.first() )->node();
|
|
|
|
TQString name = mReaderWin->tempFileUrlFromPartNode( node ).path();
|
|
|
|
KMHandleAttachmentCommand* command = new KMHandleAttachmentCommand(
|
|
|
|
node, mReaderWin->message(), node->nodeId(), name,
|
|
|
|
KMHandleAttachmentCommand::AttachmentAction( type ), 0, this );
|
|
|
|
connect( command, TQT_SIGNAL( showAttachment( int, const TQString& ) ),
|
|
|
|
mReaderWin, TQT_SLOT( slotAtmView( int, const TQString& ) ) );
|
|
|
|
command->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTree::slotCopy()
|
|
|
|
{
|
|
|
|
KURL::List urls;
|
|
|
|
KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() );
|
|
|
|
if ( !item ) return;
|
|
|
|
KURL url = mReaderWin->tempFileUrlFromPartNode( item->node() );
|
|
|
|
if ( !url.isValid() ) return;
|
|
|
|
urls.append( url );
|
|
|
|
KURLDrag* drag = new KURLDrag( urls, this );
|
|
|
|
TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTree * parent,
|
|
|
|
partNode* node,
|
|
|
|
const TQString & description,
|
|
|
|
const TQString & mimetype,
|
|
|
|
const TQString & encoding,
|
|
|
|
TDEIO::filesize_t size )
|
|
|
|
: TQListViewItem( parent, description,
|
|
|
|
TQString(), // set by setIconAndTextForType()
|
|
|
|
encoding,
|
|
|
|
TDEIO::convertSize( size ) ),
|
|
|
|
mPartNode( node ), mOrigSize(size)
|
|
|
|
{
|
|
|
|
if( node )
|
|
|
|
node->setMimePartTreeItem( this );
|
|
|
|
setIconAndTextForType( mimetype );
|
|
|
|
if ( parent )
|
|
|
|
parent->correctSize(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTreeItem * parent,
|
|
|
|
partNode* node,
|
|
|
|
const TQString & description,
|
|
|
|
const TQString & mimetype,
|
|
|
|
const TQString & encoding,
|
|
|
|
TDEIO::filesize_t size,
|
|
|
|
bool revertOrder )
|
|
|
|
: TQListViewItem( parent, description,
|
|
|
|
TQString(), // set by setIconAndTextForType()
|
|
|
|
encoding,
|
|
|
|
TDEIO::convertSize( size ) ),
|
|
|
|
mPartNode( node ), mOrigSize(size)
|
|
|
|
{
|
|
|
|
if( revertOrder && nextSibling() ){
|
|
|
|
TQListViewItem* sib = nextSibling();
|
|
|
|
while( sib->nextSibling() )
|
|
|
|
sib = sib->nextSibling();
|
|
|
|
moveItem( sib );
|
|
|
|
}
|
|
|
|
if( node )
|
|
|
|
node->setMimePartTreeItem( this );
|
|
|
|
setIconAndTextForType( mimetype );
|
|
|
|
if ( listView() )
|
|
|
|
static_cast<KMMimePartTree*>(listView())->correctSize(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KMMimePartTreeItem::setIconAndTextForType( const TQString & mime )
|
|
|
|
{
|
|
|
|
TQString mimetype = mime.lower();
|
|
|
|
if ( mimetype.startsWith( "multipart/" ) ) {
|
|
|
|
setText( 1, mimetype );
|
|
|
|
setPixmap( 0, SmallIcon("folder") );
|
|
|
|
} else if ( mimetype == "application/octet-stream" ) {
|
|
|
|
setText( 1, i18n("Unspecified Binary Data") ); // don't show "Unknown"...
|
|
|
|
setPixmap( 0, SmallIcon("unknown") );
|
|
|
|
} else {
|
|
|
|
KMimeType::Ptr mtp = KMimeType::mimeType( mimetype );
|
|
|
|
setText( 1, (mtp && !mtp->comment().isEmpty()) ? mtp->comment() : mimetype );
|
|
|
|
setPixmap( 0, mtp ? mtp->pixmap( KIcon::Small) : SmallIcon("unknown") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KMMimePartTree::startDrag()
|
|
|
|
{
|
|
|
|
KURL::List urls;
|
|
|
|
KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() );
|
|
|
|
if ( !item ) return;
|
|
|
|
partNode *node = item->node();
|
|
|
|
if ( !node ) return;
|
|
|
|
KURL url = mReaderWin->tempFileUrlFromPartNode( node );
|
|
|
|
if (!url.isValid() ) return;
|
|
|
|
urls.append( url );
|
|
|
|
KURLDrag* drag = new KURLDrag( urls, this );
|
|
|
|
drag->drag();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kmmimeparttree.moc"
|
|
|
|
|