-rw-r--r-- | kmicromail/viewmail.cpp | 525 |
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 | |||
32 | AttachItem::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 | |||
43 | AttachItem::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 | |||
54 | bool 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 | |||
67 | AttachItem* 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 | |||
78 | AttachItem* 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 | |||
91 | void 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 | |||
199 | void ViewMail::slotShowHtml( bool state ) | ||
200 | { | ||
201 | m_showHtml = state; | ||
202 | setText(); | ||
203 | } | ||
204 | |||
205 | void 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 | |||
288 | void 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 | |||
307 | ViewMail::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 | |||
325 | void 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 | |||
333 | void 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 | |||
378 | ViewMail::~ViewMail() | ||
379 | { | ||
380 | m_recMail->Wrapper()->cleanMimeCache(); | ||
381 | hide(); | ||
382 | } | ||
383 | |||
384 | void ViewMail::hide() | ||
385 | { | ||
386 | QWidget::hide(); | ||
387 | |||
388 | if (_inLoop) | ||
389 | { | ||
390 | _inLoop = false; | ||
391 | qApp->exit_loop(); | ||
392 | |||
393 | } | ||
394 | |||
395 | } | ||
396 | |||
397 | void ViewMail::exec() | ||
398 | { | ||
399 | show(); | ||
400 | |||
401 | if (!_inLoop) | ||
402 | { | ||
403 | _inLoop = true; | ||
404 | qApp->enter_loop(); | ||
405 | } | ||
406 | |||
407 | } | ||
408 | |||
409 | QString ViewMail::deHtml(const QString &string) | ||
410 | { | ||
411 | QString string_ = string; | ||
412 | string_.replace(QRegExp("&"), "&"); | ||
413 | string_.replace(QRegExp("<"), "<"); | ||
414 | string_.replace(QRegExp(">"), ">"); | ||
415 | string_.replace(QRegExp("\\n"), "<br>"); | ||
416 | return string_; | ||
417 | } | ||
418 | |||
419 | void 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 | |||
462 | void 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 | |||
497 | void 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 | |||
507 | MailImageDlg::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 | |||
517 | MailImageDlg::~MailImageDlg() | ||
518 | { | ||
519 | } | ||
520 | |||
521 | void MailImageDlg::setName(const QString&fname) | ||
522 | { | ||
523 | qDebug("viewmail.cpp: MailImageDlg::setName Pending"); | ||
524 | // m_imageview->setImage(fname); | ||
525 | } | ||