summaryrefslogtreecommitdiffabout
path: root/kmicromail/viewmail.cpp
Unidiff
Diffstat (limited to 'kmicromail/viewmail.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/viewmail.cpp525
1 files changed, 525 insertions, 0 deletions
diff --git a/kmicromail/viewmail.cpp b/kmicromail/viewmail.cpp
new file mode 100644
index 0000000..1b74564
--- a/dev/null
+++ b/kmicromail/viewmail.cpp
@@ -0,0 +1,525 @@
1#include "composemail.h"
2#include "viewmail.h"
3
4#include <libmailwrapper/settings.h>
5#include <libmailwrapper/abstractmail.h>
6#include <libmailwrapper/mailtypes.h>
7#include <kapplication.h>
8
9/* OPIE */
10//#include <opie2/odebug.h>
11//#include <opie2/ofiledialog.h>
12//#include <opie2/oimagescrollview.h>
13
14#include <kfiledialog.h>
15#include <kdialog.h>
16
17#include <qpe/config.h>
18#include <qpe/qpeapplication.h>
19
20/* QT */
21#include <qtextbrowser.h>
22#include <qmessagebox.h>
23#include <qtextstream.h>
24#include <qaction.h>
25#include <qpopupmenu.h>
26#include <qfile.h>
27#include <qlayout.h>
28
29//using namespace Opie::Ui;
30//using namespace Opie::Core;
31
32AttachItem::AttachItem(QListView * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file,
33 const QString&fsize,int num,const QValueList<int>&path)
34 : QListViewItem(parent,after),_partNum(num)
35{
36 _path=path;
37 setText(0, mime);
38 setText(1, desc);
39 setText(2, file);
40 setText(3, fsize);
41}
42
43AttachItem::AttachItem(QListViewItem * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file,
44 const QString&fsize,int num,const QValueList<int>&path)
45 : QListViewItem(parent,after),_partNum(num)
46{
47 _path=path;
48 setText(0, mime);
49 setText(1, desc);
50 setText(2, file);
51 setText(3, fsize);
52}
53
54bool AttachItem::isParentof(const QValueList<int>&path)
55{
56 /* if not set, then no parent */
57 if (path.count()==0||_path.count()==0) return false;
58 /* the parent must have one digit less then a child */
59 if (path.count()!=_path.count()+1) return false;
60 for (unsigned int i=0; i < _path.count();++i)
61 {
62 if (_path[i]!=path[i]) return false;
63 }
64 return true;
65}
66
67AttachItem* ViewMail::searchParent(const QValueList<int>&path)
68{
69 QListViewItemIterator it( attachments );
70 for ( ; it.current(); ++it )
71 {
72 AttachItem*ati = (AttachItem*)it.current();
73 if (ati->isParentof(path)) return ati;
74 }
75 return 0;
76}
77
78AttachItem* ViewMail::lastChild(AttachItem*parent)
79{
80 if (!parent) return 0;
81 AttachItem* item = (AttachItem*)parent->firstChild();
82 if (!item) return item;
83 AttachItem*temp=0;
84 while( (temp=(AttachItem*)item->nextSibling()))
85 {
86 item = temp;
87 }
88 return item;
89}
90
91void ViewMail::setBody(const RecBodyP&body )
92{
93
94 m_body = body;
95 m_mail[2] = body->Bodytext();
96 attachbutton->setEnabled(body->Parts().count()>0);
97 attachments->setEnabled(body->Parts().count()>0);
98 if (body->Parts().count()==0)
99 {
100 return;
101 }
102 AttachItem * curItem=0;
103 AttachItem * parentItem = 0;
104 QString type=body->Description()->Type()+"/"+body->Description()->Subtype();
105 QString desc,fsize;
106 double s = body->Description()->Size();
107 int w;
108 w=0;
109
110 while (s>1024)
111 {
112 s/=1024;
113 ++w;
114 if (w>=2) break;
115 }
116
117 QString q="";
118 switch(w)
119 {
120 case 1:
121 q="k";
122 break;
123 case 2:
124 q="M";
125 break;
126 default:
127 break;
128 }
129
130 {
131 /* I did not found a method to make a CONTENT reset on a QTextStream
132 so I use this construct that the stream will re-constructed in each
133 loop. To let it work, the textstream is packed into a own area of
134 code is it will be destructed after finishing its small job.
135 */
136 QTextOStream o(&fsize);
137 if (w>0) o.precision(2); else o.precision(0);
138 o.setf(QTextStream::fixed);
139 o << s << " " << q << "Byte";
140 }
141
142 curItem=new AttachItem(attachments,curItem,type,"Mailbody","",fsize,-1,body->Description()->Positionlist());
143 QString filename = "";
144
145 for (unsigned int i = 0; i < body->Parts().count();++i)
146 {
147 filename = "";
148 type = body->Parts()[i]->Type()+"/"+body->Parts()[i]->Subtype();
149 part_plist_t::ConstIterator it = body->Parts()[i]->Parameters().begin();
150 for (;it!=body->Parts()[i]->Parameters().end();++it)
151 {
152 if (it.key().lower()=="name")
153 {
154 filename=it.data();
155 }
156 }
157 s = body->Parts()[i]->Size();
158 w = 0;
159 while (s>1024)
160 {
161 s/=1024;
162 ++w;
163 if (w>=2) break;
164 }
165 switch(w)
166 {
167 case 1:
168 q="k";
169 break;
170 case 2:
171 q="M";
172 break;
173 default:
174 q="";
175 break;
176 }
177 QTextOStream o(&fsize);
178 if (w>0) o.precision(2); else o.precision(0);
179 o.setf(QTextStream::fixed);
180 o << s << " " << q << "Byte";
181 desc = body->Parts()[i]->Description();
182 parentItem = searchParent(body->Parts()[i]->Positionlist());
183 if (parentItem)
184 {
185 AttachItem*temp = lastChild(parentItem);
186 if (temp) curItem = temp;
187 curItem=new AttachItem(parentItem,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist());
188 attachments->setRootIsDecorated(true);
189 curItem = parentItem;
190 }
191 else
192 {
193 curItem=new AttachItem(attachments,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist());
194 }
195 }
196}
197
198
199void ViewMail::slotShowHtml( bool state )
200{
201 m_showHtml = state;
202 setText();
203}
204
205void ViewMail::slotItemClicked( QListViewItem * item , const QPoint & point, int )
206{
207 if (!item )
208 return;
209
210 if ( ( ( AttachItem* )item )->Partnumber() == -1 )
211 {
212 setText();
213 return;
214 }
215 QPopupMenu *menu = new QPopupMenu();
216 int ret=0;
217
218 if ( item->text( 0 ).left( 5 ) == "text/" || item->text(0)=="message/rfc822" )
219 {
220 menu->insertItem( tr( "Show Text" ), 1 );
221 }
222 if (item->text(0).left(6)=="image/") {
223 menu->insertItem(tr("Display image preview"),2);
224 }
225 menu->insertItem( tr( "Save Attachment" ), 0 );
226 menu->insertSeparator(1);
227
228 ret = menu->exec( point, 0 );
229
230 switch(ret)
231 {
232 case 0:
233 {
234 //MimeTypes types;
235 //types.insert( "all", "*" );
236 QString str = KFileDialog::getSaveFileName( "/", item->text( 2 ), this );
237
238 if( !str.isEmpty() )
239 {
240 encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] );
241 if (content)
242 {
243 QFile output(str);
244 output.open(IO_WriteOnly);
245 output.writeBlock(content->Content(),content->Length());
246 output.close();
247 delete content;
248 }
249 }
250 }
251 break ;
252
253 case 2:
254 {
255 QString tmpfile = "/tmp/opiemail-image";
256 encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] );
257 if (content) {
258 QFile output(tmpfile);
259 output.open(IO_WriteOnly);
260 output.writeBlock(content->Content(),content->Length());
261 output.close();
262 delete content;
263 MailImageDlg iview("");
264 iview.setName(tmpfile);
265 KApplication::execDialog(&iview);
266 output.remove();
267 }
268 }
269 break;
270 case 1:
271 if ( ( ( AttachItem* )item )->Partnumber() == -1 )
272 {
273 setText();
274 }
275 else
276 {
277 if ( m_recMail->Wrapper() != 0l )
278 { // make sure that there is a wrapper , even after delete or simular actions
279 browser->setText( m_recMail->Wrapper()->fetchTextPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] ) );
280 }
281 }
282 break;
283 }
284 delete menu;
285}
286
287
288void ViewMail::setMail(const RecMailP&mail )
289{
290
291 m_recMail = mail;
292
293 m_mail[0] = mail->getFrom();
294 m_mail[1] = mail->getSubject();
295 m_mail[3] = mail->getDate();
296 m_mail[4] = mail->Msgid();
297
298 m_mail2[0] = mail->To();
299 m_mail2[1] = mail->CC();
300 m_mail2[2] = mail->Bcc();
301
302 setText();
303}
304
305
306
307ViewMail::ViewMail( QWidget *parent, const char *name, WFlags fl)
308 : ViewMailBase(parent, name, fl), _inLoop(false)
309{
310 m_gotBody = false;
311 deleted = false;
312
313 connect( reply, SIGNAL(activated()), SLOT(slotReply()));
314 connect( forward, SIGNAL(activated()), SLOT(slotForward()));
315 connect( deleteMail, SIGNAL( activated() ), SLOT( slotDeleteMail() ) );
316 connect( showHtml, SIGNAL( toggled(bool) ), SLOT( slotShowHtml(bool) ) );
317
318 attachments->setEnabled(m_gotBody);
319 connect( attachments, SIGNAL( clicked(QListViewItem*,const QPoint&, int) ), SLOT( slotItemClicked(QListViewItem*,const QPoint&, int) ) );
320
321 readConfig();
322 attachments->setSorting(-1);
323}
324
325void ViewMail::readConfig()
326{
327 Config cfg( "mail" );
328 cfg.setGroup( "Settings" );
329 m_showHtml = cfg.readBoolEntry( "showHtml", false );
330 showHtml->setOn( m_showHtml );
331}
332
333void ViewMail::setText()
334{
335
336 QString toString;
337 QString ccString;
338 QString bccString;
339
340 for ( QStringList::Iterator it = ( m_mail2[0] ).begin(); it != ( m_mail2[0] ).end(); ++it )
341 {
342 toString += (*it);
343 }
344 for ( QStringList::Iterator it = ( m_mail2[1] ).begin(); it != ( m_mail2[1] ).end(); ++it )
345 {
346 ccString += (*it);
347 }
348 for ( QStringList::Iterator it = ( m_mail2[2] ).begin(); it != ( m_mail2[2] ).end(); ++it )
349 {
350 bccString += (*it);
351 }
352
353 setCaption( caption().arg( m_mail[0] ) );
354
355 m_mailHtml = "<html><body>"
356 "<table width=\"100%\" border=\"0\"><tr bgcolor=\"#FFDD76\"><td>"
357 "<div align=left><b>" + deHtml( m_mail[1] ) + "</b></div>"
358 "</td></tr><tr bgcolor=\"#EEEEE6\"><td>"
359 "<b>" + tr( "From" ) + ": </b><font color=#6C86C0>" + deHtml( m_mail[0] ) + "</font><br>"
360 "<b>" + tr( "To" ) + ": </b><font color=#6C86C0>" + deHtml( toString ) + "</font><br><b>" +
361 tr( "Cc" ) + ": </b>" + deHtml( ccString ) + "<br>"
362 "<b>" + tr( "Date" ) + ": </b> " + m_mail[3] +
363 "</td></tr></table><font face=fixed>";
364
365 if ( !m_showHtml )
366 {
367 browser->setText( QString( m_mailHtml) + deHtml( m_mail[2] ) + "</font></html>" );
368 }
369 else
370 {
371 browser->setText( QString( m_mailHtml) + m_mail[2] + "</font></html>" );
372 }
373 // remove later in favor of a real handling
374 m_gotBody = true;
375}
376
377
378ViewMail::~ViewMail()
379{
380 m_recMail->Wrapper()->cleanMimeCache();
381 hide();
382}
383
384void ViewMail::hide()
385{
386 QWidget::hide();
387
388 if (_inLoop)
389 {
390 _inLoop = false;
391 qApp->exit_loop();
392
393 }
394
395}
396
397void ViewMail::exec()
398{
399 show();
400
401 if (!_inLoop)
402 {
403 _inLoop = true;
404 qApp->enter_loop();
405 }
406
407}
408
409QString ViewMail::deHtml(const QString &string)
410{
411 QString string_ = string;
412 string_.replace(QRegExp("&"), "&amp;");
413 string_.replace(QRegExp("<"), "&lt;");
414 string_.replace(QRegExp(">"), "&gt;");
415 string_.replace(QRegExp("\\n"), "<br>");
416 return string_;
417}
418
419void ViewMail::slotReply()
420{
421 if (!m_gotBody)
422 {
423 QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot reply yet."), tr("Ok"));
424 return;
425 }
426
427 QString rtext;
428 rtext += QString("* %1 wrote on %2:\n") // no i18n on purpose
429 .arg( m_mail[0] )
430 .arg( m_mail[3] );
431
432 QString text = m_mail[2];
433 QStringList lines = QStringList::split(QRegExp("\\n"), text);
434 QStringList::Iterator it;
435 for (it = lines.begin(); it != lines.end(); it++)
436 {
437 rtext += "> " + *it + "\n";
438 }
439 rtext += "\n";
440
441 QString prefix;
442 if ( m_mail[1].find(QRegExp("^Re: .*$")) != -1) prefix = "";
443 else prefix = "Re: "; // no i18n on purpose
444
445 Settings *settings = new Settings();
446 ComposeMail composer( settings ,this, 0, true);
447 if (m_recMail->Replyto().isEmpty()) {
448 composer.setTo( m_recMail->getFrom());
449 } else {
450 composer.setTo( m_recMail->Replyto());
451 }
452 composer.setSubject( prefix + m_mail[1] );
453 composer.setMessage( rtext );
454 composer.setInReplyTo(m_recMail->Msgid());
455
456 if ( QDialog::Accepted == KApplication::execDialog( &composer ) )
457 {
458 m_recMail->Wrapper()->answeredMail(m_recMail);
459 }
460}
461
462void ViewMail::slotForward()
463{
464 if (!m_gotBody)
465 {
466 QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot forward yet."), tr("Ok"));
467 return;
468 }
469
470 QString ftext;
471 ftext += QString("\n----- Forwarded message from %1 -----\n\n")
472 .arg( m_mail[0] );
473 if (!m_mail[3].isNull())
474 ftext += QString("Date: %1\n")
475 .arg( m_mail[3] );
476 if (!m_mail[0].isNull())
477 ftext += QString("From: %1\n")
478 .arg( m_mail[0] );
479 if (!m_mail[1].isNull())
480 ftext += QString("Subject: %1\n")
481 .arg( m_mail[1] );
482
483 ftext += QString("\n%1\n")
484 .arg( m_mail[2]);
485
486 ftext += QString("----- End forwarded message -----\n");
487
488 Settings *settings = new Settings();
489 ComposeMail composer( settings ,this, 0, true);
490 composer.setSubject( "Fwd: " + m_mail[1] );
491 composer.setMessage( ftext );
492 if ( QDialog::Accepted == KApplication::execDialog( &composer ))
493 {
494 }
495}
496
497void ViewMail::slotDeleteMail( )
498{
499 if ( QMessageBox::warning(this, tr("Delete Mail"), QString( tr("<p>Do you really want to delete this mail? <br><br>" ) + m_mail[0] + " - " + m_mail[1] ) , QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
500 {
501 m_recMail->Wrapper()->deleteMail( m_recMail );
502 hide();
503 deleted = true;
504 }
505}
506
507MailImageDlg::MailImageDlg(const QString&fname,QWidget *parent, const char *name, bool modal, WFlags f)
508 : KDialog(parent,name,modal)
509{
510 QVBoxLayout*dlglayout = new QVBoxLayout(this);
511 dlglayout->setSpacing(2);
512 dlglayout->setMargin(1);
513 //m_imageview = new Opie::MM::OImageScrollView(this);
514 //dlglayout->addWidget(m_imageview);
515}
516
517MailImageDlg::~MailImageDlg()
518{
519}
520
521void MailImageDlg::setName(const QString&fname)
522{
523 qDebug("viewmail.cpp: MailImageDlg::setName Pending");
524 // m_imageview->setImage(fname);
525}