kmail

kmmimeparttree.cpp
1/*
2 kmmimeparttree.h A MIME part tree viwer.
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2002-2004 Klarälvdalens Datakonsult AB
6
7 KMail is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License, version 2, as
9 published by the Free Software Foundation.
10
11 KMail is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 In addition, as a special exception, the copyright holders give
21 permission to link the code of this program with any edition of
22 the TQt library by Trolltech AS, Norway (or with modified versions
23 of TQt that use the same license as TQt), and distribute linked
24 combinations including the two. You must obey the GNU General
25 Public License in all respects for all of the code used other than
26 TQt. If you modify this file, you may extend this exception to
27 your version of the file, but you are not obligated to do so. If
28 you do not wish to do so, delete this exception statement from
29 your version.
30*/
31
32
33#include <config.h>
34
35#include "kmmimeparttree.h"
36
37#include "kmreaderwin.h"
38#include "partNode.h"
39#include "kmmsgpart.h"
40#include "kmkernel.h"
41#include "kmcommands.h"
42
43#include <kdebug.h>
44#include <tdelocale.h>
45#include <tdefiledialog.h>
46#include <tdemessagebox.h>
47#include <kiconloader.h>
48
49#include <tqclipboard.h>
50#include <tqheader.h>
51#include <tqpopupmenu.h>
52#include <tqstyle.h>
53#include <kurldrag.h>
54#include <kurl.h>
55
56
57KMMimePartTree::KMMimePartTree( KMReaderWin* readerWin,
58 TQWidget* parent,
59 const char* name )
60 : TDEListView( parent, name ),
61 mReaderWin( readerWin ), mSizeColumn(0)
62{
63 setStyleDependantFrameWidth();
64 addColumn( i18n("Description") );
65 addColumn( i18n("Type") );
66 addColumn( i18n("Encoding") );
67 mSizeColumn = addColumn( i18n("Size") );
68 setColumnAlignment( 3, TQt::AlignRight );
69
70 restoreLayoutIfPresent();
71 connect( this, TQT_SIGNAL( clicked( TQListViewItem* ) ),
72 this, TQT_SLOT( itemClicked( TQListViewItem* ) ) );
73 connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*,
74 const TQPoint&, int ) ),
75 this, TQT_SLOT( itemRightClicked( TQListViewItem*, const TQPoint& ) ) );
76 setSelectionMode( TQListView::Extended );
77 setRootIsDecorated( false );
78 setAllColumnsShowFocus( true );
79 setShowToolTips( true );
80 setSorting(-1);
81 setDragEnabled( true );
82}
83
84
85static const char configGroup[] = "MimePartTree";
86
87KMMimePartTree::~KMMimePartTree() {
88 saveLayout( KMKernel::config(), configGroup );
89}
90
91
92void KMMimePartTree::restoreLayoutIfPresent() {
93 // first column: soaks up the rest of the space:
94 setColumnWidthMode( 0, Manual );
95 header()->setStretchEnabled( true, 0 );
96 // rest of the columns:
97 if ( KMKernel::config()->hasGroup( configGroup ) ) {
98 // there is a saved layout. use it...
99 restoreLayout( KMKernel::config(), configGroup );
100 // and disable Maximum mode:
101 for ( int i = 1 ; i < 4 ; ++i )
102 setColumnWidthMode( i, Manual );
103 } else {
104 // columns grow with their contents:
105 for ( int i = 1 ; i < 4 ; ++i )
106 setColumnWidthMode( i, Maximum );
107 }
108}
109
110
111void KMMimePartTree::itemClicked( TQListViewItem* item )
112{
113 if ( const KMMimePartTreeItem * i = dynamic_cast<KMMimePartTreeItem*>( item ) ) {
114 if( mReaderWin->mRootNode == i->node() )
115 mReaderWin->update( true ); // Force update
116 else
117 mReaderWin->setMsgPart( i->node() );
118 } else
119 kdWarning(5006) << "Item was not a KMMimePartTreeItem!" << endl;
120}
121
122
123void KMMimePartTree::itemRightClicked( TQListViewItem* item,
124 const TQPoint& point )
125{
126 // TODO: remove this member var?
127 mCurrentContextMenuItem = dynamic_cast<KMMimePartTreeItem*>( item );
128 if ( 0 == mCurrentContextMenuItem ) {
129 kdDebug(5006) << "Item was not a KMMimePartTreeItem!" << endl;
130 }
131 else {
132 TQPopupMenu* popup = new TQPopupMenu;
133 if ( mCurrentContextMenuItem->node()->nodeId() > 2 &&
134 mCurrentContextMenuItem->node()->typeString() != "Multipart" ) {
135 popup->insertItem( SmallIcon("document-open"), i18n("to open", "Open"), this, TQT_SLOT(slotOpen()) );
136 popup->insertItem( i18n("Open With..."), this, TQT_SLOT(slotOpenWith()) );
137 popup->insertItem( i18n("to view something", "View"), this, TQT_SLOT(slotView()) );
138 }
139 popup->insertItem( SmallIcon("document-save-as"),i18n( "Save &As..." ), this, TQT_SLOT( slotSaveAs() ) );
140 /*
141 * FIXME mkae optional?
142 popup->insertItem( i18n( "Save as &Encoded..." ), this,
143 TQT_SLOT( slotSaveAsEncoded() ) );
144 */
145 popup->insertItem( i18n( "Save All Attachments..." ), this,
146 TQT_SLOT( slotSaveAll() ) );
147 // edit + delete only for attachments
148 if ( mCurrentContextMenuItem->node()->nodeId() > 2 &&
149 mCurrentContextMenuItem->node()->typeString() != "Multipart" ) {
150 popup->insertItem( SmallIcon("edit-copy"), i18n("Copy"), this, TQT_SLOT(slotCopy()) );
151 if ( GlobalSettings::self()->allowAttachmentDeletion() )
152 popup->insertItem( SmallIcon("edit-delete"), i18n( "Delete Attachment" ),
153 this, TQT_SLOT( slotDelete() ) );
154 if ( GlobalSettings::self()->allowAttachmentEditing() )
155 popup->insertItem( SmallIcon( "edit" ), i18n( "Edit Attachment" ),
156 this, TQT_SLOT( slotEdit() ) );
157 }
158 if ( mCurrentContextMenuItem->node()->nodeId() > 0 )
159 popup->insertItem( i18n("Properties"), this, TQT_SLOT(slotProperties()) );
160 popup->exec( point );
161 delete popup;
162 mCurrentContextMenuItem = 0;
163 }
164}
165
166//-----------------------------------------------------------------------------
167void KMMimePartTree::slotSaveAs()
168{
169 saveSelectedBodyParts( false );
170}
171
172//-----------------------------------------------------------------------------
173void KMMimePartTree::slotSaveAsEncoded()
174{
175 saveSelectedBodyParts( true );
176}
177
178//-----------------------------------------------------------------------------
179void KMMimePartTree::saveSelectedBodyParts( bool encoded )
180{
181 TQPtrList<TQListViewItem> selected = selectedItems();
182
183 Q_ASSERT( !selected.isEmpty() );
184 if ( selected.isEmpty() )
185 return;
186
187 TQPtrListIterator<TQListViewItem> it( selected );
188 TQPtrList<partNode> parts;
189 while ( it.current() ) {
190 parts.append( static_cast<KMMimePartTreeItem *>(it.current())->node() );
191 ++it;
192 }
193 mReaderWin->setUpdateAttachment();
194 KMSaveAttachmentsCommand *command =
195 new KMSaveAttachmentsCommand( this, parts, mReaderWin->message(), encoded );
196 command->start();
197}
198
199//-----------------------------------------------------------------------------
200void KMMimePartTree::slotSaveAll()
201{
202 if( childCount() == 0)
203 return;
204
205 mReaderWin->setUpdateAttachment();
206 KMCommand *command =
207 new KMSaveAttachmentsCommand( this, mReaderWin->message() );
208 command->start();
209}
210
211//-----------------------------------------------------------------------------
212void KMMimePartTree::setStyleDependantFrameWidth()
213{
214 // set the width of the frame to a reasonable value for the current GUI style
215 int frameWidth;
216 if( style().isA("KeramikStyle") )
217 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
218 else
219 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
220 if ( frameWidth < 0 )
221 frameWidth = 0;
222 if ( frameWidth != lineWidth() )
223 setLineWidth( frameWidth );
224}
225
226
227//-----------------------------------------------------------------------------
228void KMMimePartTree::styleChange( TQStyle& oldStyle )
229{
230 setStyleDependantFrameWidth();
231 TDEListView::styleChange( oldStyle );
232}
233
234//-----------------------------------------------------------------------------
235void KMMimePartTree::correctSize( TQListViewItem * item )
236{
237 if (!item) return;
238
239 TDEIO::filesize_t totalSize = 0;
240 TQListViewItem * myChild = item->firstChild();
241 while ( myChild )
242 {
243 totalSize += static_cast<KMMimePartTreeItem*>(myChild)->origSize();
244 myChild = myChild->nextSibling();
245 }
246 if ( totalSize > static_cast<KMMimePartTreeItem*>(item)->origSize() )
247 item->setText( mSizeColumn, TDEIO::convertSize(totalSize) );
248 if ( item->parent() )
249 correctSize( item->parent() );
250}
251
252void KMMimePartTree::slotDelete()
253{
254 TQPtrList<TQListViewItem> selected = selectedItems();
255 if ( selected.count() != 1 )
256 return;
257 mReaderWin->slotDeleteAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
258}
259
260void KMMimePartTree::slotEdit()
261{
262 TQPtrList<TQListViewItem> selected = selectedItems();
263 if ( selected.count() != 1 )
264 return;
265 mReaderWin->slotEditAttachment( static_cast<KMMimePartTreeItem*>( selected.first() )->node() );
266}
267
268void KMMimePartTree::slotOpen()
269{
270 startHandleAttachmentCommand( KMHandleAttachmentCommand::Open );
271}
272
273void KMMimePartTree::slotOpenWith()
274{
275 startHandleAttachmentCommand( KMHandleAttachmentCommand::OpenWith );
276}
277
278void KMMimePartTree::slotView()
279{
280 startHandleAttachmentCommand( KMHandleAttachmentCommand::View );
281}
282
283void KMMimePartTree::slotProperties()
284{
285 startHandleAttachmentCommand( KMHandleAttachmentCommand::Properties );
286}
287
288void KMMimePartTree::startHandleAttachmentCommand(int type)
289{
290 TQPtrList<TQListViewItem> selected = selectedItems();
291 if ( selected.count() != 1 )
292 return;
293 partNode* node = static_cast<KMMimePartTreeItem*>( selected.first() )->node();
294 TQString name = mReaderWin->tempFileUrlFromPartNode( node ).path();
295 KMHandleAttachmentCommand* command = new KMHandleAttachmentCommand(
296 node, mReaderWin->message(), node->nodeId(), name,
297 KMHandleAttachmentCommand::AttachmentAction( type ), 0, this );
298 connect( command, TQT_SIGNAL( showAttachment( int, const TQString& ) ),
299 mReaderWin, TQT_SLOT( slotAtmView( int, const TQString& ) ) );
300 command->start();
301}
302
303void KMMimePartTree::slotCopy()
304{
305 KURL::List urls;
306 KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() );
307 if ( !item ) return;
308 KURL url = mReaderWin->tempFileUrlFromPartNode( item->node() );
309 if ( !url.isValid() ) return;
310 urls.append( url );
311 KURLDrag* drag = new KURLDrag( urls, this );
312 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
313}
314
315//=============================================================================
316KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTree * parent,
317 partNode* node,
318 const TQString & description,
319 const TQString & mimetype,
320 const TQString & encoding,
321 TDEIO::filesize_t size )
322 : TQListViewItem( parent, description,
323 TQString(), // set by setIconAndTextForType()
324 encoding,
325 TDEIO::convertSize( size ) ),
326 mPartNode( node ), mOrigSize(size)
327{
328 if( node )
329 node->setMimePartTreeItem( this );
330 setIconAndTextForType( mimetype );
331 if ( parent )
332 parent->correctSize(this);
333}
334
335KMMimePartTreeItem::KMMimePartTreeItem( KMMimePartTreeItem * parent,
336 partNode* node,
337 const TQString & description,
338 const TQString & mimetype,
339 const TQString & encoding,
340 TDEIO::filesize_t size,
341 bool revertOrder )
342 : TQListViewItem( parent, description,
343 TQString(), // set by setIconAndTextForType()
344 encoding,
345 TDEIO::convertSize( size ) ),
346 mPartNode( node ), mOrigSize(size)
347{
348 if( revertOrder && nextSibling() ){
349 TQListViewItem* sib = nextSibling();
350 while( sib->nextSibling() )
351 sib = sib->nextSibling();
352 moveItem( sib );
353 }
354 if( node )
355 node->setMimePartTreeItem( this );
356 setIconAndTextForType( mimetype );
357 if ( listView() )
358 static_cast<KMMimePartTree*>(listView())->correctSize(this);
359}
360
361void KMMimePartTreeItem::setIconAndTextForType( const TQString & mime )
362{
363 TQString mimetype = mime.lower();
364 if ( mimetype.startsWith( "multipart/" ) ) {
365 setText( 1, mimetype );
366 setPixmap( 0, SmallIcon("folder") );
367 } else if ( mimetype == "application/octet-stream" ) {
368 setText( 1, i18n("Unspecified Binary Data") ); // don't show "Unknown"...
369 setPixmap( 0, SmallIcon("unknown") );
370 } else {
371 KMimeType::Ptr mtp = KMimeType::mimeType( mimetype );
372 setText( 1, (mtp && !mtp->comment().isEmpty()) ? mtp->comment() : mimetype );
373 setPixmap( 0, mtp ? mtp->pixmap( TDEIcon::Small) : SmallIcon("unknown") );
374 }
375}
376
377
378void KMMimePartTree::startDrag()
379{
380 KURL::List urls;
381 KMMimePartTreeItem *item = static_cast<KMMimePartTreeItem*>( currentItem() );
382 if ( !item ) return;
383 partNode *node = item->node();
384 if ( !node ) return;
385 KURL url = mReaderWin->tempFileUrlFromPartNode( node );
386 if (!url.isValid() ) return;
387 urls.append( url );
388 KURLDrag* drag = new KURLDrag( urls, this );
389 drag->drag();
390}
391
392#include "kmmimeparttree.moc"
393
This class implements a "reader window", that is a window used for reading or viewing messages.
Definition: kmreaderwin.h:75