kmail

kmmsgpartdlg.cpp
1 // kmmsgpartdlg.cpp
2 
3 
4 // my includes:
5 #include <config.h>
6 #include "kmmsgpartdlg.h"
7 
8 // other KMail includes:
9 #include "kmmessage.h"
10 #include "kmmsgpart.h"
11 #include "kcursorsaver.h"
12 
13 // other tdenetwork includes: (none)
14 
15 // other KDE includes:
16 #include <kmimetype.h>
17 #include <tdeapplication.h>
18 #include <kiconloader.h>
19 #include <tdeaboutdata.h>
20 #include <kstringvalidator.h>
21 #include <kcombobox.h>
22 #include <kdebug.h>
23 
24 // other TQt includes:
25 #include <tqlabel.h>
26 #include <tqlayout.h>
27 #include <tqwhatsthis.h>
28 #include <klineedit.h>
29 #include <tqcheckbox.h>
30 
31 // other includes:
32 #include <assert.h>
33 
34 static const struct {
36  const char * displayName;
37 } encodingTypes[] = {
38  { KMMsgPartDialog::SevenBit, I18N_NOOP("None (7-bit text)") },
39  { KMMsgPartDialog::EightBit, I18N_NOOP("None (8-bit text)") },
40  { KMMsgPartDialog::QuotedPrintable, I18N_NOOP("Quoted Printable") },
41  { KMMsgPartDialog::Base64, I18N_NOOP("Base 64") },
42 };
43 static const int numEncodingTypes =
44  sizeof encodingTypes / sizeof *encodingTypes;
45 
46 KMMsgPartDialog::KMMsgPartDialog( const TQString & caption,
47  TQWidget * parent, const char * name )
48  : KDialogBase( Plain,
49  caption.isEmpty() ? i18n("Message Part Properties") : caption,
50  Ok|Cancel|Help, Ok, parent, name, true, true)
51 {
52  // tmp vars:
53  TQGridLayout * glay;
54  TQLabel * label;
55  TQString msg;
56 
57  setHelp( TQString::fromLatin1("attachments") );
58 
59  for ( int i = 0 ; i < numEncodingTypes ; ++i )
60  mI18nizedEncodings << i18n( encodingTypes[i].displayName );
61 
62  glay = new TQGridLayout( plainPage(), 9 /*rows*/, 2 /*cols*/, spacingHint() );
63  glay->setColStretch( 1, 1 );
64  glay->setRowStretch( 8, 1 );
65 
66  // mimetype icon:
67  mIcon = new TQLabel( plainPage() );
68  mIcon->setPixmap( DesktopIcon("unknown") );
69  glay->addMultiCellWidget( mIcon, 0, 1, 0, 0 );
70 
71  // row 0: Type combobox:
72  mMimeType = new KComboBox( true, plainPage() );
73  mMimeType->setInsertionPolicy( TQComboBox::NoInsertion );
74  mMimeType->setValidator( new KMimeTypeValidator( TQT_TQOBJECT(mMimeType) ) );
75  mMimeType->insertStringList( TQStringList()
76  << TQString::fromLatin1("text/html")
77  << TQString::fromLatin1("text/plain")
78  << TQString::fromLatin1("image/gif")
79  << TQString::fromLatin1("image/jpeg")
80  << TQString::fromLatin1("image/png")
81  << TQString::fromLatin1("application/octet-stream")
82  << TQString::fromLatin1("application/x-gunzip")
83  << TQString::fromLatin1("application/zip") );
84  connect( mMimeType, TQT_SIGNAL(textChanged(const TQString&)),
85  this, TQT_SLOT(slotMimeTypeChanged(const TQString&)) );
86  glay->addWidget( mMimeType, 0, 1 );
87 
88  msg = i18n("<qt><p>The <em>MIME type</em> of the file:</p>"
89  "<p>normally, you do not need to touch this setting, since the "
90  "type of the file is automatically checked; but, sometimes, %1 "
91  "may not detect the type correctly -- here is where you can fix "
92  "that.</p></qt>").arg( kapp->aboutData()->programName() );
93  TQWhatsThis::add( mMimeType, msg );
94 
95  // row 1: Size label:
96  mSize = new TQLabel( plainPage() );
97  setSize( TDEIO::filesize_t(0) );
98  glay->addWidget( mSize, 1, 1 );
99 
100  msg = i18n("<qt><p>The size of the part:</p>"
101  "<p>sometimes, %1 will only give an estimated size here, "
102  "because calculating the exact size would take too much time; "
103  "when this is the case, it will be made visible by adding "
104  "\"(est.)\" to the size displayed.</p></qt>")
105  .arg( kapp->aboutData()->programName() );
106  TQWhatsThis::add( mSize, msg );
107 
108  // row 2: "Name" lineedit and label:
109  mFileName = new KLineEdit( plainPage() );
110  label = new TQLabel( mFileName, i18n("&Name:"), plainPage() );
111  glay->addWidget( label, 2, 0 );
112  glay->addWidget( mFileName, 2, 1 );
113 
114  msg = i18n("<qt><p>The file name of the part:</p>"
115  "<p>although this defaults to the name of the attached file, "
116  "it does not specify the file to be attached; rather, it "
117  "suggests a file name to be used by the recipient's mail agent "
118  "when saving the part to disk.</p></qt>");
119  TQWhatsThis::add( label, msg );
120  TQWhatsThis::add( mFileName, msg );
121 
122  // row 3: "Description" lineedit and label:
123  mDescription = new KLineEdit( plainPage() );
124  label = new TQLabel( mDescription, i18n("&Description:"), plainPage() );
125  glay->addWidget( label, 3, 0 );
126  glay->addWidget( mDescription, 3, 1 );
127 
128  msg = i18n("<qt><p>A description of the part:</p>"
129  "<p>this is just an informational description of the part, "
130  "much like the Subject is for the whole message; most "
131  "mail agents will show this information in their message "
132  "previews alongside the attachment's icon.</p></qt>");
133  TQWhatsThis::add( label, msg );
134  TQWhatsThis::add( mDescription, msg );
135 
136  // row 4: "Encoding" combobox and label:
137  mEncoding = new TQComboBox( false, plainPage() );
138  mEncoding->insertStringList( mI18nizedEncodings );
139  label = new TQLabel( mEncoding, i18n("&Encoding:"), plainPage() );
140  glay->addWidget( label, 4, 0 );
141  glay->addWidget( mEncoding, 4, 1 );
142 
143  msg = i18n("<qt><p>The transport encoding of this part:</p>"
144  "<p>normally, you do not need to change this, since %1 will use "
145  "a decent default encoding, depending on the MIME type; yet, "
146  "sometimes, you can significantly reduce the size of the "
147  "resulting message, e.g. if a PostScript file does not contain "
148  "binary data, but consists of pure text -- in this case, choosing "
149  "\"quoted-printable\" over the default \"base64\" will save up "
150  "to 25% in resulting message size.</p></qt>")
151  .arg( kapp->aboutData()->programName() );
152  TQWhatsThis::add( label, msg );
153  TQWhatsThis::add( mEncoding, msg );
154 
155  // row 5: "Suggest automatic display..." checkbox:
156  mInline = new TQCheckBox( i18n("Suggest &automatic display"), plainPage() );
157  glay->addMultiCellWidget( mInline, 5, 5, 0, 1 );
158 
159  msg = i18n("<qt><p>Check this option if you want to suggest to the "
160  "recipient the automatic (inline) display of this part in the "
161  "message preview, instead of the default icon view;</p>"
162  "<p>technically, this is carried out by setting this part's "
163  "<em>Content-Disposition</em> header field to \"inline\" "
164  "instead of the default \"attachment\".</p></qt>");
165  TQWhatsThis::add( mInline, msg );
166 
167  // row 6: "Sign" checkbox:
168  mSigned = new TQCheckBox( i18n("&Sign this part"), plainPage() );
169  glay->addMultiCellWidget( mSigned, 6, 6, 0, 1 );
170 
171  msg = i18n("<qt><p>Check this option if you want this message part to be "
172  "signed;</p>"
173  "<p>the signature will be made with the key that you associated "
174  "with the currently-selected identity.</p></qt>");
175  TQWhatsThis::add( mSigned, msg );
176 
177  // row 7: "Encrypt" checkbox:
178  mEncrypted = new TQCheckBox( i18n("Encr&ypt this part"), plainPage() );
179  glay->addMultiCellWidget( mEncrypted, 7, 7, 0, 1 );
180 
181  msg = i18n("<qt><p>Check this option if you want this message part to be "
182  "encrypted;</p>"
183  "<p>the part will be encrypted for the recipients of this "
184  "message</p></qt>");
185  TQWhatsThis::add( mEncrypted, msg );
186  // (row 8: spacer)
187 }
188 
189 
190 KMMsgPartDialog::~KMMsgPartDialog() {}
191 
192 
193 TQString KMMsgPartDialog::mimeType() const {
194  return mMimeType->currentText();
195 }
196 
197 void KMMsgPartDialog::setMimeType( const TQString & mimeType ) {
198  int dummy = 0;
199  TQString tmp = mimeType; // get rid of const'ness
200  if ( mMimeType->validator() && mMimeType->validator()->validate( tmp, dummy ) )
201  for ( int i = 0 ; i < mMimeType->count() ; ++i )
202  if ( mMimeType->text( i ) == mimeType ) {
203  mMimeType->setCurrentItem( i );
204  return;
205  }
206  mMimeType->insertItem( mimeType, 0 );
207  mMimeType->setCurrentItem( 0 );
208  slotMimeTypeChanged( mimeType );
209 }
210 
211 void KMMsgPartDialog::setMimeType( const TQString & type,
212  const TQString & subtype ) {
213  setMimeType( TQString::fromLatin1("%1/%2").arg(type).arg(subtype) );
214 }
215 
216 void KMMsgPartDialog::setMimeTypeList( const TQStringList & mimeTypes ) {
217  mMimeType->insertStringList( mimeTypes );
218 }
219 
220 void KMMsgPartDialog::setSize( TDEIO::filesize_t size, bool estimated ) {
221  TQString text = TDEIO::convertSize( size );
222  if ( estimated )
223  text = i18n("%1: a filesize incl. unit (e.g. \"1.3 KB\")",
224  "%1 (est.)").arg( text );
225  mSize->setText( text );
226 }
227 
228 TQString KMMsgPartDialog::fileName() const {
229  return mFileName->text();
230 }
231 
232 void KMMsgPartDialog::setFileName( const TQString & fileName ) {
233  mFileName->setText( fileName );
234 }
235 
237  return mDescription->text();
238 }
239 
240 void KMMsgPartDialog::setDescription( const TQString & description ) {
241  mDescription->setText( description );
242 }
243 
245  TQString s = mEncoding->currentText();
246  for ( unsigned int i = 0 ; i < mI18nizedEncodings.count() ; ++i )
247  if ( s == *mI18nizedEncodings.at(i) )
248  return encodingTypes[i].encoding;
249  kdFatal(5006) << "KMMsgPartDialog::encoding(): Unknown encoding encountered!"
250  << endl;
251  return None; // keep compiler happy
252 }
253 
255  for ( int i = 0 ; i < numEncodingTypes ; ++i )
256  if ( encodingTypes[i].encoding == encoding ) {
257  TQString text = *mI18nizedEncodings.at(i);
258  for ( int j = 0 ; j < mEncoding->count() ; ++j )
259  if ( mEncoding->text(j) == text ) {
260  mEncoding->setCurrentItem( j );
261  return;
262  }
263  mEncoding->insertItem( text, 0 );
264  mEncoding->setCurrentItem( 0 );
265  }
266  kdFatal(5006) << "KMMsgPartDialog::setEncoding(): "
267  "Unknown encoding encountered!" << endl;
268 }
269 
270 void KMMsgPartDialog::setShownEncodings( int encodings ) {
271  mEncoding->clear();
272  for ( int i = 0 ; i < numEncodingTypes ; ++i )
273  if ( encodingTypes[i].encoding & encodings )
274  mEncoding->insertItem( *mI18nizedEncodings.at(i) );
275 }
276 
278  return mInline->isChecked();
279 }
280 
281 void KMMsgPartDialog::setInline( bool inlined ) {
282  mInline->setChecked( inlined );
283 }
284 
286  return mEncrypted->isChecked();
287 }
288 
289 void KMMsgPartDialog::setEncrypted( bool encrypted ) {
290  mEncrypted->setChecked( encrypted );
291 }
292 
293 void KMMsgPartDialog::setCanEncrypt( bool enable ) {
294  mEncrypted->setEnabled( enable );
295 }
296 
298  return mSigned->isChecked();
299 }
300 
301 void KMMsgPartDialog::setSigned( bool sign ) {
302  mSigned->setChecked( sign );
303 }
304 
305 void KMMsgPartDialog::setCanSign( bool enable ) {
306  mSigned->setEnabled( enable );
307 }
308 
309 void KMMsgPartDialog::slotMimeTypeChanged( const TQString & mimeType ) {
310  // message subparts MUST have 7bit or 8bit encoding...
311 #if 0
312  // ...but until KMail can recode 8bit messages on attach, so that
313  // they can be signed, we can't enforce this :-(
314  if ( mimeType.startsWith("message/") ) {
315  setEncoding( SevenBit );
316  mEncoding->setEnabled( false );
317  } else {
318  mEncoding->setEnabled( !mReadOnly );
319  }
320 #endif
321  // find a mimetype icon:
322  int dummy = 0;
323  TQString tmp = mimeType; // get rid of const'ness
324  if ( mMimeType->validator() && mMimeType->validator()->validate( tmp, dummy )
325  == TQValidator::Acceptable )
326  mIcon->setPixmap( KMimeType::mimeType( mimeType )->pixmap( TDEIcon::Desktop ) );
327  else
328  mIcon->setPixmap( DesktopIcon("unknown") );
329 }
330 
331 
332 
333 
334 KMMsgPartDialogCompat::KMMsgPartDialogCompat( TQWidget * parent, const char *, bool readOnly)
335  : KMMsgPartDialog(TQString(), parent ), mMsgPart( 0 )
336 {
337  setShownEncodings( SevenBit|EightBit|QuotedPrintable|Base64 );
338  if (readOnly)
339  {
340  mMimeType->setEditable(false);
341  mMimeType->setEnabled(false);
342  mFileName->setReadOnly(true);
343  mDescription->setReadOnly(true);
344  mEncoding->setEnabled(false);
345  mInline->setEnabled(false);
346  mEncrypted->setEnabled(false);
347  mSigned->setEnabled(false);
348  }
349 }
350 
351 KMMsgPartDialogCompat::~KMMsgPartDialogCompat() {}
352 
353 void KMMsgPartDialogCompat::setMsgPart( KMMessagePart * aMsgPart )
354 {
355  mMsgPart = aMsgPart;
356  assert( mMsgPart );
357 
358  TQCString enc = mMsgPart->cteStr();
359  if ( enc == "7bit" )
360  setEncoding( SevenBit );
361  else if ( enc == "8bit" )
362  setEncoding( EightBit );
363  else if ( enc == "quoted-printable" )
364  setEncoding( QuotedPrintable );
365  else
366  setEncoding( Base64 );
367 
368  setDescription( mMsgPart->contentDescription() );
369  setFileName( mMsgPart->fileName() );
370  setMimeType( mMsgPart->typeStr(), mMsgPart->subtypeStr() );
371  setSize( mMsgPart->decodedSize() );
372  setInline( mMsgPart->contentDisposition()
373  .find( TQRegExp("^\\s*inline", false) ) >= 0 );
374 }
375 
376 
378 {
379  if (!mMsgPart) return;
380 
381  KCursorSaver busy(KBusyPtr::busy());
382 
383  // apply Content-Disposition:
384  TQCString cDisp;
385  if ( isInline() )
386  cDisp = "inline;";
387  else
388  cDisp = "attachment;";
389 
390  TQString name = fileName();
391  if ( !name.isEmpty() || !mMsgPart->name().isEmpty()) {
392  mMsgPart->setName( name );
393  TQCString encName = KMMsgBase::encodeRFC2231StringAutoDetectCharset( name, mMsgPart->charset() );
394 
395  cDisp += "\n\tfilename";
396  if ( name != TQString( encName ) )
397  cDisp += "*=" + encName;
398  else
399  cDisp += "=\"" + encName.replace( '\\', "\\\\" ).replace( '"', "\\\"" ) + '"';
400  mMsgPart->setContentDisposition( cDisp );
401  }
402 
403  // apply Content-Description"
404  TQString desc = description();
405  if ( !desc.isEmpty() || !mMsgPart->contentDescription().isEmpty() )
406  mMsgPart->setContentDescription( desc );
407 
408  // apply Content-Type:
409  TQCString type = mimeType().latin1();
410  TQCString subtype;
411  int idx = type.find('/');
412  if ( idx < 0 )
413  subtype = "";
414  else {
415  subtype = type.mid( idx+1 );
416  type = type.left( idx );
417  }
418  mMsgPart->setTypeStr(type);
419  mMsgPart->setSubtypeStr(subtype);
420 
421  // apply Content-Transfer-Encoding:
422  TQCString cte;
423  if (subtype == "rfc822" && type == "message")
424  kdWarning( encoding() != SevenBit && encoding() != EightBit, 5006 )
425  << "encoding on rfc822/message must be \"7bit\" or \"8bit\"" << endl;
426  switch ( encoding() ) {
427  case SevenBit: cte = "7bit"; break;
428  case EightBit: cte = "8bit"; break;
429  case QuotedPrintable: cte = "quoted-printable"; break;
430  case Base64: default: cte = "base64"; break;
431  }
432  if ( cte != mMsgPart->cteStr().lower() ) {
433  TQByteArray body = mMsgPart->bodyDecodedBinary();
434  mMsgPart->setCteStr( cte );
435  mMsgPart->setBodyEncodedBinary( body );
436  }
437 }
438 
439 
440 //-----------------------------------------------------------------------------
441 void KMMsgPartDialogCompat::slotOk()
442 {
443  applyChanges();
444  KMMsgPartDialog::slotOk();
445 }
446 
447 
448 //-----------------------------------------------------------------------------
449 #include "kmmsgpartdlg.moc"