00001 #include "composemail.h"
00002 #include "viewmail.h"
00003
00004 #include <libmailwrapper/settings.h>
00005 #include <libmailwrapper/abstractmail.h>
00006 #include <libmailwrapper/mailtypes.h>
00007
00008
00009 #include <opie2/odebug.h>
00010 #include <opie2/ofiledialog.h>
00011 #include <opie2/oimagescrollview.h>
00012 #include <qpe/config.h>
00013 #include <qpe/qpeapplication.h>
00014
00015
00016 #include <qtextbrowser.h>
00017 #include <qmessagebox.h>
00018 #include <qtextstream.h>
00019 #include <qaction.h>
00020 #include <qpopupmenu.h>
00021 #include <qfile.h>
00022 #include <qlayout.h>
00023 #include <qstylesheet.h>
00024
00025 using namespace Opie::Ui;
00026 using namespace Opie::Core;
00027
00028 AttachItem::AttachItem(QListView * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file,
00029 const QString&fsize,int num,const QValueList<int>&path)
00030 : QListViewItem(parent,after),_partNum(num)
00031 {
00032 _path=path;
00033 setText(0, mime);
00034 setText(1, desc);
00035 setText(2, file);
00036 setText(3, fsize);
00037 }
00038
00039 AttachItem::AttachItem(QListViewItem * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file,
00040 const QString&fsize,int num,const QValueList<int>&path)
00041 : QListViewItem(parent,after),_partNum(num)
00042 {
00043 _path=path;
00044 setText(0, mime);
00045 setText(1, desc);
00046 setText(2, file);
00047 setText(3, fsize);
00048 }
00049
00050 bool AttachItem::isParentof(const QValueList<int>&path)
00051 {
00052
00053 if (path.count()==0||_path.count()==0) return false;
00054
00055 if (path.count()!=_path.count()+1) return false;
00056 for (unsigned int i=0; i < _path.count();++i)
00057 {
00058 if (_path[i]!=path[i]) return false;
00059 }
00060 return true;
00061 }
00062
00063 AttachItem* ViewMail::searchParent(const QValueList<int>&path)
00064 {
00065 QListViewItemIterator it( attachments );
00066 for ( ; it.current(); ++it )
00067 {
00068 AttachItem*ati = (AttachItem*)it.current();
00069 if (ati->isParentof(path)) return ati;
00070 }
00071 return 0;
00072 }
00073
00074 AttachItem* ViewMail::lastChild(AttachItem*parent)
00075 {
00076 if (!parent) return 0;
00077 AttachItem* item = (AttachItem*)parent->firstChild();
00078 if (!item) return item;
00079 AttachItem*temp=0;
00080 while( (temp=(AttachItem*)item->nextSibling()))
00081 {
00082 item = temp;
00083 }
00084 return item;
00085 }
00086
00087 void ViewMail::setBody(const RecBodyP&body )
00088 {
00089
00090 m_body = body;
00091 m_mail[2] = body->Bodytext();
00092 attachbutton->setEnabled(body->Parts().count()>0);
00093 attachments->setEnabled(body->Parts().count()>0);
00094 if (body->Parts().count()==0)
00095 {
00096 return;
00097 }
00098 AttachItem * curItem=0;
00099 AttachItem * parentItem = 0;
00100 QString type=body->Description()->Type()+"/"+body->Description()->Subtype();
00101 QString desc,fsize;
00102 double s = body->Description()->Size();
00103 int w;
00104 w=0;
00105
00106 while (s>1024)
00107 {
00108 s/=1024;
00109 ++w;
00110 if (w>=2) break;
00111 }
00112
00113 QString q="";
00114 switch(w)
00115 {
00116 case 1:
00117 q="k";
00118 break;
00119 case 2:
00120 q="M";
00121 break;
00122 default:
00123 break;
00124 }
00125
00126 {
00127
00128
00129
00130
00131
00132 QTextOStream o(&fsize);
00133 if (w>0) o.precision(2); else o.precision(0);
00134 o.setf(QTextStream::fixed);
00135 o << s << " " << q << "Byte";
00136 }
00137
00138 curItem=new AttachItem(attachments,curItem,type,"Mailbody","",fsize,-1,body->Description()->Positionlist());
00139 QString filename = "";
00140
00141 for (unsigned int i = 0; i < body->Parts().count();++i)
00142 {
00143 filename = "";
00144 type = body->Parts()[i]->Type()+"/"+body->Parts()[i]->Subtype();
00145 part_plist_t::ConstIterator it = body->Parts()[i]->Parameters().begin();
00146 for (;it!=body->Parts()[i]->Parameters().end();++it)
00147 {
00148 odebug << it.key() << oendl;
00149 if (it.key().lower()=="name")
00150 {
00151 filename=it.data();
00152 }
00153 }
00154 s = body->Parts()[i]->Size();
00155 w = 0;
00156 while (s>1024)
00157 {
00158 s/=1024;
00159 ++w;
00160 if (w>=2) break;
00161 }
00162 switch(w)
00163 {
00164 case 1:
00165 q="k";
00166 break;
00167 case 2:
00168 q="M";
00169 break;
00170 default:
00171 q="";
00172 break;
00173 }
00174 QTextOStream o(&fsize);
00175 if (w>0) o.precision(2); else o.precision(0);
00176 o.setf(QTextStream::fixed);
00177 o << s << " " << q << "Byte";
00178 desc = body->Parts()[i]->Description();
00179 parentItem = searchParent(body->Parts()[i]->Positionlist());
00180 if (parentItem)
00181 {
00182 AttachItem*temp = lastChild(parentItem);
00183 if (temp) curItem = temp;
00184 curItem=new AttachItem(parentItem,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist());
00185 attachments->setRootIsDecorated(true);
00186 curItem = parentItem;
00187 }
00188 else
00189 {
00190 curItem=new AttachItem(attachments,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist());
00191 }
00192 }
00193 }
00194
00195
00196 void ViewMail::slotShowHtml( bool state )
00197 {
00198 m_showHtml = state;
00199 m_lasttextpart=-2;
00200 setMainText();
00201 }
00202
00203 void ViewMail::slotItemClicked( QListViewItem * item , const QPoint & point, int )
00204 {
00205 if (!item )
00206 return;
00207
00208 if ( ( ( AttachItem* )item )->Partnumber() == -1 )
00209 {
00210 setMainText();
00211 return;
00212 }
00213 QPopupMenu *menu = new QPopupMenu();
00214 int ret=0;
00215
00216 if ( item->text( 0 ).left( 5 ) == "text/" || item->text(0)=="message/rfc822" )
00217 {
00218 menu->insertItem( tr( "Show Text" ), 1 );
00219 }
00220 if (item->text(0).left(6)=="image/") {
00221 menu->insertItem(tr("Display image preview"),2);
00222 }
00223 menu->insertItem( tr( "Save Attachment" ), 0 );
00224 menu->insertSeparator(1);
00225
00226 ret = menu->exec( point, 0 );
00227
00228 switch(ret)
00229 {
00230 case 0:
00231 {
00232 MimeTypes types;
00233 types.insert( "all", "*" );
00234 QString str = OFileDialog::getSaveFileName( 1,
00235 "/", item->text( 2 ) , types, 0 );
00236
00237 if( !str.isEmpty() )
00238 {
00239 encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] );
00240 if (content)
00241 {
00242 QFile output(str);
00243 output.open(IO_WriteOnly);
00244 output.writeBlock(content->Content(),content->Length());
00245 output.close();
00246 delete content;
00247 }
00248 }
00249 }
00250 break ;
00251
00252 case 2:
00253 {
00254 if (m_lastimagepart== (( AttachItem* )item )->Partnumber()) {
00255 if (m_lastdlg) {
00256 setUpdatesEnabled(false);
00257 browser->hide();
00258 m_lastdlg->show();
00259 setUpdatesEnabled(true);
00260 return;
00261 }
00262 }
00263 QString tmpfile = QString("/tmp/opiemail-image-%1").arg(_icounter++);
00264 encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] );
00265 if (content && content->Length()) {
00266 QFile output(tmpfile);
00267 output.open(IO_WriteOnly);
00268 output.writeBlock(content->Content(),content->Length());
00269 output.close();
00270 delete content;
00271 if (!m_PicsInline) {
00272 MailImageDlg iview("");
00273 iview.setName(tmpfile);
00274 QPEApplication::execDialog(&iview);
00275 } else {
00276 if (!m_lastdlg) {
00277 m_lastdlg=new Opie::MM::OImageScrollView("",browser->parentWidget(),false);
00278 m_lastdlg->setAutoScale(true);
00279 }
00280
00281 m_lastdlg->setImage(tmpfile);
00282 browser->hide();
00283 m_lastdlg->show();
00284 }
00285 output.remove();
00286 } else {
00287 QMessageBox::critical(this, tr("Reading attachment"), tr("Could not read content of attachment"));
00288 }
00289 m_lastimagepart=(( AttachItem* )item )->Partnumber();
00290 }
00291 break;
00292 case 1:
00293 if ( ( ( AttachItem* )item )->Partnumber() == -1 )
00294 {
00295 setMainText();
00296 }
00297 else
00298 {
00299 if ( m_recMail->Wrapper() != 0l )
00300 {
00301 if (m_lastdlg) {
00302 m_lastdlg->hide();
00303 browser->show();
00304 }
00305 if (m_lasttextpart == ( ( AttachItem* )item )->Partnumber() ) return;
00306 m_lasttextpart = ( ( AttachItem* )item )->Partnumber();
00307 QString s = m_recMail->Wrapper()->fetchTextPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] );;
00308 if (item->text(0).right(4)!="html") {
00309 s = QString("<html><body>\n<font face=fixed>%1</font></body></html>").arg(QStyleSheet::convertFromPlainText(s));
00310 }
00311 browser->setText(s);
00312 }
00313 }
00314 break;
00315 }
00316 delete menu;
00317 }
00318
00319
00320 void ViewMail::setMail(const RecMailP&mail )
00321 {
00322
00323 m_recMail = mail;
00324
00325 m_mail[0] = mail->getFrom();
00326 m_mail[1] = mail->getSubject();
00327 m_mail[3] = mail->getStringDate();
00328 m_mail[4] = mail->Msgid();
00329
00330 m_mail2[0] = mail->To();
00331 m_mail2[1] = mail->CC();
00332 m_mail2[2] = mail->Bcc();
00333
00334 setCaption(tr("E-Mail by %1").arg( m_mail[0] ) );
00335 m_lasttextpart=-2;
00336 setMainText();
00337 }
00338
00339
00340
00341 ViewMail::ViewMail( QWidget *parent, const char *name, WFlags fl)
00342 : ViewMailBase(parent, name, fl), _inLoop(false)
00343 {
00344 m_gotBody = false;
00345 deleted = false;
00346
00347 connect( reply, SIGNAL(activated()), SLOT(slotReply()));
00348 connect( forward, SIGNAL(activated()), SLOT(slotForward()));
00349 connect( deleteMail, SIGNAL( activated() ), SLOT( slotDeleteMail() ) );
00350 connect( showHtml, SIGNAL( toggled(bool) ), SLOT( slotShowHtml(bool) ) );
00351 connect( showPicsInline, SIGNAL( toggled(bool) ), SLOT( slotImageInline(bool) ) );
00352
00353 attachments->setEnabled(m_gotBody);
00354 connect( attachments, SIGNAL( clicked(QListViewItem*,const QPoint&, int) ), SLOT( slotItemClicked(QListViewItem*,const QPoint&, int) ) );
00355 m_lastdlg = 0;
00356 _icounter = 0;
00357 m_lastimagepart = -1;
00358 m_lasttextpart = -2;
00359
00360 readConfig();
00361 attachments->setSorting(-1);
00362 }
00363
00364 void ViewMail::slotImageInline(bool how)
00365 {
00366 Config cfg( "mail" );
00367 cfg.writeEntry( "showPicsInline", how);
00368 m_PicsInline = how;
00369 if (m_lastdlg&&!how) {
00370 browser->show();
00371 m_lastdlg->hide();
00372 m_lastdlg->reparent(0,QPoint(0,0),false);
00373 delete m_lastdlg;
00374 m_lastdlg = 0;
00375 m_lastimagepart = -1;
00376 }
00377 }
00378
00379 void ViewMail::readConfig()
00380 {
00381 Config cfg( "mail" );
00382 cfg.setGroup( "Settings" );
00383 m_showHtml = cfg.readBoolEntry( "showHtml", false );
00384 m_PicsInline = cfg.readBoolEntry( "showPicsInline", true );
00385 showPicsInline->setOn(m_PicsInline);
00386 showHtml->setOn( m_showHtml );
00387 }
00388
00389 void ViewMail::setMainText()
00390 {
00391 QString toString;
00392 QString ccString;
00393 QString bccString;
00394 QString mailHtml;
00395
00396 if (m_lastdlg) {
00397 m_lastdlg->hide();
00398 }
00399 browser->show();
00400 if (m_lasttextpart == -1) return;
00401 m_lasttextpart = -1;
00402 for ( QStringList::Iterator it = ( m_mail2[0] ).begin(); it != ( m_mail2[0] ).end(); ++it )
00403 {
00404 toString += (*it);
00405 }
00406 for ( QStringList::Iterator it = ( m_mail2[1] ).begin(); it != ( m_mail2[1] ).end(); ++it )
00407 {
00408 ccString += (*it);
00409 }
00410 for ( QStringList::Iterator it = ( m_mail2[2] ).begin(); it != ( m_mail2[2] ).end(); ++it )
00411 {
00412 bccString += (*it);
00413 }
00414 browser->setTextFormat(Qt::RichText);
00415 mailHtml = "<html><body>"
00416 "<table width=\"100%\" border=\"0\"><tr bgcolor=\"#FFDD76\"><td>"
00417 "<div align=left><b>" + deHtml(m_mail[1]) + "</b></div>"
00418 "</td></tr><tr bgcolor=\"#EEEEE6\"><td>"
00419 "<b>" + tr( "From" ) + ": </b><font color=#6C86C0>" + deHtml( m_mail[0] ) + "</font><br>"
00420 "<b>" + tr( "To" ) + ": </b><font color=#6C86C0>" + deHtml( toString ) + "</font><br><b>" +
00421 tr( "Cc" ) + ": </b>" + deHtml( ccString ) + "<br>"
00422 "<b>" + tr( "Date" ) + ": </b> " + m_mail[3] +
00423 "</td></tr></table>";
00424 if ( !m_showHtml ) {
00425 browser->setText( mailHtml+"<font face=fixed>" + QStyleSheet::convertFromPlainText(m_mail[2]) + "</font></body></html>" );
00426 } else {
00427 browser->setText(mailHtml+m_mail[2].simplifyWhiteSpace()+"</html>");
00428 }
00429
00430 m_gotBody = true;
00431 }
00432
00433
00434 ViewMail::~ViewMail()
00435 {
00436 m_recMail->Wrapper()->cleanMimeCache();
00437 hide();
00438 }
00439
00440 void ViewMail::hide()
00441 {
00442 QWidget::hide();
00443
00444 if (_inLoop)
00445 {
00446 _inLoop = false;
00447 qApp->exit_loop();
00448
00449 }
00450
00451 }
00452
00453 void ViewMail::exec()
00454 {
00455 show();
00456
00457 if (!_inLoop)
00458 {
00459 _inLoop = true;
00460 qApp->enter_loop();
00461 }
00462
00463 }
00464
00465 QString ViewMail::deHtml(const QString &aString)
00466 {
00467 QString string_ = aString;
00468 string_.replace(QRegExp("&"), "&");
00469 string_.replace(QRegExp("<"), "<");
00470 string_.replace(QRegExp(">"), ">");
00471 string_.replace(QRegExp("\\n"), "<br>");
00472 return string_;
00473 }
00474
00475 void ViewMail::slotReply()
00476 {
00477 if (!m_gotBody)
00478 {
00479 QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot reply yet."), tr("Ok"));
00480 return;
00481 }
00482
00483 QString rtext;
00484 rtext += QString("* %1 wrote on %2:\n")
00485 .arg( m_mail[0] )
00486 .arg( m_mail[3] );
00487
00488 QString text = m_mail[2];
00489 QStringList lines = QStringList::split(QRegExp("\\n"), text);
00490 QStringList::Iterator it;
00491 for (it = lines.begin(); it != lines.end(); it++)
00492 {
00493 rtext += "> " + *it + "\n";
00494 }
00495 rtext += "\n";
00496
00497 QString prefix;
00498 if ( m_mail[1].find(QRegExp("^Re: .*$")) != -1) prefix = "";
00499 else prefix = "Re: ";
00500
00501 Settings *settings = new Settings();
00502 ComposeMail composer( settings ,this, 0, true);
00503 if (m_recMail->Replyto().isEmpty()) {
00504 composer.setTo( m_recMail->getFrom());
00505 } else {
00506 composer.setTo( m_recMail->Replyto());
00507 }
00508 composer.setSubject( prefix + m_mail[1] );
00509 composer.setMessage( rtext );
00510 composer.setInReplyTo(m_recMail->Msgid());
00511
00512 if ( QDialog::Accepted == QPEApplication::execDialog( &composer ) )
00513 {
00514 m_recMail->Wrapper()->answeredMail(m_recMail);
00515 }
00516 }
00517
00518 void ViewMail::slotForward()
00519 {
00520 if (!m_gotBody)
00521 {
00522 QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot forward yet."), tr("Ok"));
00523 return;
00524 }
00525
00526 QString ftext;
00527 ftext += QString("\n----- Forwarded message from %1 -----\n\n")
00528 .arg( m_mail[0] );
00529 if (!m_mail[3].isNull())
00530 ftext += QString("Date: %1\n")
00531 .arg( m_mail[3] );
00532 if (!m_mail[0].isNull())
00533 ftext += QString("From: %1\n")
00534 .arg( m_mail[0] );
00535 if (!m_mail[1].isNull())
00536 ftext += QString("Subject: %1\n")
00537 .arg( m_mail[1] );
00538
00539 ftext += QString("\n%1\n")
00540 .arg( m_mail[2]);
00541
00542 ftext += QString("----- End forwarded message -----\n");
00543
00544 Settings *settings = new Settings();
00545 ComposeMail composer( settings ,this, 0, true);
00546 composer.setSubject( "Fwd: " + m_mail[1] );
00547 composer.setMessage( ftext );
00548 if ( QDialog::Accepted == QPEApplication::execDialog( &composer ))
00549 {
00550 }
00551 }
00552
00553 void ViewMail::slotDeleteMail( )
00554 {
00555 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 )
00556 {
00557 m_recMail->Wrapper()->deleteMail( m_recMail );
00558 hide();
00559 deleted = true;
00560 }
00561 }
00562
00563 MailImageDlg::MailImageDlg(const QString&fname,QWidget *parent, const char *name, bool modal, WFlags f)
00564 : Opie::Ui::ODialog(parent,name,modal,f)
00565 {
00566 QVBoxLayout*dlglayout = new QVBoxLayout(this);
00567 dlglayout->setSpacing(2);
00568 dlglayout->setMargin(1);
00569 m_imageview = new Opie::MM::OImageScrollView(this);
00570 dlglayout->addWidget(m_imageview);
00571 }
00572
00573 MailImageDlg::~MailImageDlg()
00574 {
00575 }
00576
00577 void MailImageDlg::setName(const QString&fname)
00578 {
00579 m_imageview->setImage(fname);
00580 }