kmail

kmmsgpartdlg.cpp

00001 // kmmsgpartdlg.cpp
00002 
00003 
00004 // my includes:
00005 #include <config.h>
00006 #include "kmmsgpartdlg.h"
00007 
00008 // other KMail includes:
00009 #include "kmmessage.h"
00010 #include "kmmsgpart.h"
00011 #include "kcursorsaver.h"
00012 
00013 // other kdenetwork includes: (none)
00014 
00015 // other KDE includes:
00016 #include <kmimetype.h>
00017 #include <kapplication.h>
00018 #include <kiconloader.h>
00019 #include <kaboutdata.h>
00020 #include <kstringvalidator.h>
00021 #include <kcombobox.h>
00022 #include <kdebug.h>
00023 
00024 // other TQt includes:
00025 #include <tqlabel.h>
00026 #include <tqlayout.h>
00027 #include <tqwhatsthis.h>
00028 #include <klineedit.h>
00029 #include <tqcheckbox.h>
00030 
00031 // other includes:
00032 #include <assert.h>
00033 
00034 static const struct {
00035   KMMsgPartDialog::Encoding encoding;
00036   const char * displayName;
00037 } encodingTypes[] = {
00038   { KMMsgPartDialog::SevenBit, I18N_NOOP("None (7-bit text)") },
00039   { KMMsgPartDialog::EightBit, I18N_NOOP("None (8-bit text)") },
00040   { KMMsgPartDialog::QuotedPrintable, I18N_NOOP("Quoted Printable") },
00041   { KMMsgPartDialog::Base64, I18N_NOOP("Base 64") },
00042 };
00043 static const int numEncodingTypes =
00044   sizeof encodingTypes / sizeof *encodingTypes;
00045 
00046 KMMsgPartDialog::KMMsgPartDialog( const TQString & caption,
00047                   TQWidget * parent, const char * name )
00048   : KDialogBase( Plain,
00049          caption.isEmpty() ? i18n("Message Part Properties") : caption,
00050          Ok|Cancel|Help, Ok, parent, name, true, true)
00051 {
00052   // tmp vars:
00053   TQGridLayout * glay;
00054   TQLabel      * label;
00055   TQString       msg;
00056 
00057   setHelp( TQString::fromLatin1("attachments") );
00058 
00059   for ( int i = 0 ; i < numEncodingTypes ; ++i )
00060     mI18nizedEncodings << i18n( encodingTypes[i].displayName );
00061 
00062   glay = new TQGridLayout( plainPage(), 9 /*rows*/, 2 /*cols*/, spacingHint() );
00063   glay->setColStretch( 1, 1 );
00064   glay->setRowStretch( 8, 1 );
00065 
00066   // mimetype icon:
00067   mIcon = new TQLabel( plainPage() );
00068   mIcon->setPixmap( DesktopIcon("unknown") );
00069   glay->addMultiCellWidget( mIcon, 0, 1, 0, 0 );
00070 
00071   // row 0: Type combobox:
00072   mMimeType = new KComboBox( true, plainPage() );
00073   mMimeType->setInsertionPolicy( TQComboBox::NoInsertion );
00074   mMimeType->setValidator( new KMimeTypeValidator( TQT_TQOBJECT(mMimeType) ) );
00075   mMimeType->insertStringList( TQStringList()
00076                    << TQString::fromLatin1("text/html")
00077                    << TQString::fromLatin1("text/plain")
00078                    << TQString::fromLatin1("image/gif")
00079                    << TQString::fromLatin1("image/jpeg")
00080                    << TQString::fromLatin1("image/png")
00081                    << TQString::fromLatin1("application/octet-stream")
00082                    << TQString::fromLatin1("application/x-gunzip")
00083                    << TQString::fromLatin1("application/zip") );
00084   connect( mMimeType, TQT_SIGNAL(textChanged(const TQString&)),
00085        this, TQT_SLOT(slotMimeTypeChanged(const TQString&)) );
00086   glay->addWidget( mMimeType, 0, 1 );
00087 
00088   msg = i18n("<qt><p>The <em>MIME type</em> of the file:</p>"
00089          "<p>normally, you do not need to touch this setting, since the "
00090          "type of the file is automatically checked; but, sometimes, %1 "
00091          "may not detect the type correctly -- here is where you can fix "
00092          "that.</p></qt>").arg( kapp->aboutData()->programName() );
00093   TQWhatsThis::add( mMimeType, msg );
00094 
00095   // row 1: Size label:
00096   mSize = new TQLabel( plainPage() );
00097   setSize( KIO::filesize_t(0) );
00098   glay->addWidget( mSize, 1, 1 );
00099 
00100   msg = i18n("<qt><p>The size of the part:</p>"
00101          "<p>sometimes, %1 will only give an estimated size here, "
00102          "because calculating the exact size would take too much time; "
00103          "when this is the case, it will be made visible by adding "
00104          "\"(est.)\" to the size displayed.</p></qt>")
00105     .arg( kapp->aboutData()->programName() );
00106   TQWhatsThis::add( mSize, msg );
00107 
00108   // row 2: "Name" lineedit and label:
00109   mFileName = new KLineEdit( plainPage() );
00110   label = new TQLabel( mFileName, i18n("&Name:"), plainPage() );
00111   glay->addWidget( label, 2, 0 );
00112   glay->addWidget( mFileName, 2, 1 );
00113 
00114   msg = i18n("<qt><p>The file name of the part:</p>"
00115          "<p>although this defaults to the name of the attached file, "
00116          "it does not specify the file to be attached; rather, it "
00117          "suggests a file name to be used by the recipient's mail agent "
00118          "when saving the part to disk.</p></qt>");
00119   TQWhatsThis::add( label, msg );
00120   TQWhatsThis::add( mFileName, msg );
00121 
00122   // row 3: "Description" lineedit and label:
00123   mDescription = new KLineEdit( plainPage() );
00124   label = new TQLabel( mDescription, i18n("&Description:"), plainPage() );
00125   glay->addWidget( label, 3, 0 );
00126   glay->addWidget( mDescription, 3, 1 );
00127 
00128   msg = i18n("<qt><p>A description of the part:</p>"
00129          "<p>this is just an informational description of the part, "
00130          "much like the Subject is for the whole message; most "
00131          "mail agents will show this information in their message "
00132          "previews alongside the attachment's icon.</p></qt>");
00133   TQWhatsThis::add( label, msg );
00134   TQWhatsThis::add( mDescription, msg );
00135 
00136   // row 4: "Encoding" combobox and label:
00137   mEncoding = new TQComboBox( false, plainPage() );
00138   mEncoding->insertStringList( mI18nizedEncodings );
00139   label = new TQLabel( mEncoding, i18n("&Encoding:"), plainPage() );
00140   glay->addWidget( label, 4, 0 );
00141   glay->addWidget( mEncoding, 4, 1 );
00142 
00143   msg = i18n("<qt><p>The transport encoding of this part:</p>"
00144          "<p>normally, you do not need to change this, since %1 will use "
00145          "a decent default encoding, depending on the MIME type; yet, "
00146          "sometimes, you can significantly reduce the size of the "
00147          "resulting message, e.g. if a PostScript file does not contain "
00148          "binary data, but consists of pure text -- in this case, choosing "
00149          "\"quoted-printable\" over the default \"base64\" will save up "
00150          "to 25% in resulting message size.</p></qt>")
00151     .arg( kapp->aboutData()->programName() );
00152   TQWhatsThis::add( label, msg );
00153   TQWhatsThis::add( mEncoding, msg );
00154 
00155   // row 5: "Suggest automatic display..." checkbox:
00156   mInline = new TQCheckBox( i18n("Suggest &automatic display"), plainPage() );
00157   glay->addMultiCellWidget( mInline, 5, 5, 0, 1 );
00158 
00159   msg = i18n("<qt><p>Check this option if you want to suggest to the "
00160          "recipient the automatic (inline) display of this part in the "
00161          "message preview, instead of the default icon view;</p>"
00162          "<p>technically, this is carried out by setting this part's "
00163          "<em>Content-Disposition</em> header field to \"inline\" "
00164          "instead of the default \"attachment\".</p></qt>");
00165   TQWhatsThis::add( mInline, msg );
00166 
00167   // row 6: "Sign" checkbox:
00168   mSigned = new TQCheckBox( i18n("&Sign this part"), plainPage() );
00169   glay->addMultiCellWidget( mSigned, 6, 6, 0, 1 );
00170 
00171   msg = i18n("<qt><p>Check this option if you want this message part to be "
00172          "signed;</p>"
00173          "<p>the signature will be made with the key that you associated "
00174          "with the currently-selected identity.</p></qt>");
00175   TQWhatsThis::add( mSigned, msg );
00176 
00177   // row 7: "Encrypt" checkbox:
00178   mEncrypted = new TQCheckBox( i18n("Encr&ypt this part"), plainPage() );
00179   glay->addMultiCellWidget( mEncrypted, 7, 7, 0, 1 );
00180 
00181   msg = i18n("<qt><p>Check this option if you want this message part to be "
00182          "encrypted;</p>"
00183          "<p>the part will be encrypted for the recipients of this "
00184          "message</p></qt>");
00185   TQWhatsThis::add( mEncrypted, msg );
00186   // (row 8: spacer)
00187 }
00188 
00189 
00190 KMMsgPartDialog::~KMMsgPartDialog() {}
00191 
00192 
00193 TQString KMMsgPartDialog::mimeType() const {
00194   return mMimeType->currentText();
00195 }
00196 
00197 void KMMsgPartDialog::setMimeType( const TQString & mimeType ) {
00198   int dummy = 0;
00199   TQString tmp = mimeType; // get rid of const'ness
00200   if ( mMimeType->validator() && mMimeType->validator()->validate( tmp, dummy ) )
00201     for ( int i = 0 ; i < mMimeType->count() ; ++i )
00202       if ( mMimeType->text( i ) == mimeType ) {
00203     mMimeType->setCurrentItem( i );
00204     return;
00205       }
00206   mMimeType->insertItem( mimeType, 0 );
00207   mMimeType->setCurrentItem( 0 );
00208   slotMimeTypeChanged( mimeType );
00209 }
00210 
00211 void KMMsgPartDialog::setMimeType( const TQString & type,
00212                    const TQString & subtype ) {
00213   setMimeType( TQString::fromLatin1("%1/%2").arg(type).arg(subtype) );
00214 }
00215 
00216 void KMMsgPartDialog::setMimeTypeList( const TQStringList & mimeTypes ) {
00217   mMimeType->insertStringList( mimeTypes );
00218 }
00219 
00220 void KMMsgPartDialog::setSize( KIO::filesize_t size, bool estimated ) {
00221   TQString text = KIO::convertSize( size );
00222   if ( estimated )
00223     text = i18n("%1: a filesize incl. unit (e.g. \"1.3 KB\")",
00224         "%1 (est.)").arg( text );
00225   mSize->setText( text );
00226 }
00227 
00228 TQString KMMsgPartDialog::fileName() const {
00229   return mFileName->text();
00230 }
00231 
00232 void KMMsgPartDialog::setFileName( const TQString & fileName ) {
00233   mFileName->setText( fileName );
00234 }
00235 
00236 TQString KMMsgPartDialog::description() const {
00237   return mDescription->text();
00238 }
00239 
00240 void KMMsgPartDialog::setDescription( const TQString & description ) {
00241   mDescription->setText( description );
00242 }
00243 
00244 KMMsgPartDialog::Encoding KMMsgPartDialog::encoding() const {
00245   TQString s = mEncoding->currentText();
00246   for ( unsigned int i = 0 ; i < mI18nizedEncodings.count() ; ++i )
00247     if ( s == *mI18nizedEncodings.at(i) )
00248       return encodingTypes[i].encoding;
00249   kdFatal(5006) << "KMMsgPartDialog::encoding(): Unknown encoding encountered!"
00250         << endl;
00251   return None; // keep compiler happy
00252 }
00253 
00254 void KMMsgPartDialog::setEncoding( Encoding encoding ) {
00255   for ( int i = 0 ; i < numEncodingTypes ; ++i )
00256     if ( encodingTypes[i].encoding == encoding ) {
00257       TQString text = *mI18nizedEncodings.at(i);
00258       for ( int j = 0 ; j < mEncoding->count() ; ++j )
00259     if ( mEncoding->text(j) == text ) {
00260       mEncoding->setCurrentItem( j );
00261       return;
00262     }
00263       mEncoding->insertItem( text, 0 );
00264       mEncoding->setCurrentItem( 0 );
00265     }
00266   kdFatal(5006) << "KMMsgPartDialog::setEncoding(): "
00267     "Unknown encoding encountered!" << endl;
00268 }
00269 
00270 void KMMsgPartDialog::setShownEncodings( int encodings ) {
00271   mEncoding->clear();
00272   for ( int i = 0 ; i < numEncodingTypes ; ++i )
00273     if ( encodingTypes[i].encoding & encodings )
00274       mEncoding->insertItem( *mI18nizedEncodings.at(i) );
00275 }
00276 
00277 bool KMMsgPartDialog::isInline() const {
00278   return mInline->isChecked();
00279 }
00280 
00281 void KMMsgPartDialog::setInline( bool inlined ) {
00282   mInline->setChecked( inlined );
00283 }
00284 
00285 bool KMMsgPartDialog::isEncrypted() const {
00286   return mEncrypted->isChecked();
00287 }
00288 
00289 void KMMsgPartDialog::setEncrypted( bool encrypted ) {
00290   mEncrypted->setChecked( encrypted );
00291 }
00292 
00293 void KMMsgPartDialog::setCanEncrypt( bool enable ) {
00294   mEncrypted->setEnabled( enable );
00295 }
00296 
00297 bool KMMsgPartDialog::isSigned() const {
00298   return mSigned->isChecked();
00299 }
00300 
00301 void KMMsgPartDialog::setSigned( bool sign ) {
00302   mSigned->setChecked( sign );
00303 }
00304 
00305 void KMMsgPartDialog::setCanSign( bool enable ) {
00306   mSigned->setEnabled( enable );
00307 }
00308 
00309 void KMMsgPartDialog::slotMimeTypeChanged( const TQString & mimeType ) {
00310   // message subparts MUST have 7bit or 8bit encoding...
00311 #if 0
00312   // ...but until KMail can recode 8bit messages on attach, so that
00313   // they can be signed, we can't enforce this :-(
00314   if ( mimeType.startsWith("message/") ) {
00315     setEncoding( SevenBit );
00316     mEncoding->setEnabled( false );
00317   } else {
00318     mEncoding->setEnabled( !mReadOnly );
00319   }
00320 #endif
00321   // find a mimetype icon:
00322   int dummy = 0;
00323   TQString tmp = mimeType; // get rid of const'ness
00324   if ( mMimeType->validator() && mMimeType->validator()->validate( tmp, dummy )
00325        == TQValidator::Acceptable )
00326     mIcon->setPixmap( KMimeType::mimeType( mimeType )->pixmap( KIcon::Desktop ) );
00327   else
00328     mIcon->setPixmap( DesktopIcon("unknown") );
00329 }
00330 
00331 
00332 
00333 
00334 KMMsgPartDialogCompat::KMMsgPartDialogCompat( TQWidget * parent, const char *, bool readOnly)
00335   : KMMsgPartDialog(TQString(), parent ), mMsgPart( 0 )
00336 {
00337   setShownEncodings( SevenBit|EightBit|QuotedPrintable|Base64 );
00338   if (readOnly)
00339   {
00340     mMimeType->setEditable(false);
00341     mMimeType->setEnabled(false);
00342     mFileName->setReadOnly(true);
00343     mDescription->setReadOnly(true);
00344     mEncoding->setEnabled(false);
00345     mInline->setEnabled(false);
00346     mEncrypted->setEnabled(false);
00347     mSigned->setEnabled(false);
00348   }
00349 }
00350 
00351 KMMsgPartDialogCompat::~KMMsgPartDialogCompat() {}
00352 
00353 void KMMsgPartDialogCompat::setMsgPart( KMMessagePart * aMsgPart )
00354 {
00355   mMsgPart = aMsgPart;
00356   assert( mMsgPart );
00357 
00358   TQCString enc = mMsgPart->cteStr();
00359   if ( enc == "7bit" )
00360     setEncoding( SevenBit );
00361   else if ( enc == "8bit" )
00362     setEncoding( EightBit );
00363   else if ( enc == "quoted-printable" )
00364     setEncoding( QuotedPrintable );
00365   else
00366     setEncoding( Base64 );
00367 
00368   setDescription( mMsgPart->contentDescription() );
00369   setFileName( mMsgPart->fileName() );
00370   setMimeType( mMsgPart->typeStr(), mMsgPart->subtypeStr() );
00371   setSize( mMsgPart->decodedSize() );
00372   setInline( mMsgPart->contentDisposition()
00373          .find( TQRegExp("^\\s*inline", false) ) >= 0 );
00374 }
00375 
00376 
00377 void KMMsgPartDialogCompat::applyChanges()
00378 {
00379   if (!mMsgPart) return;
00380 
00381   KCursorSaver busy(KBusyPtr::busy());
00382 
00383   // apply Content-Disposition:
00384   TQCString cDisp;
00385   if ( isInline() )
00386     cDisp = "inline;";
00387   else
00388     cDisp = "attachment;";
00389 
00390   TQString name = fileName();
00391   if ( !name.isEmpty() || !mMsgPart->name().isEmpty()) {
00392     mMsgPart->setName( name );
00393     TQCString encName = KMMsgBase::encodeRFC2231StringAutoDetectCharset( name, mMsgPart->charset() );
00394 
00395     cDisp += "\n\tfilename";
00396     if ( name != TQString( encName ) )
00397       cDisp += "*=" + encName;
00398     else
00399       cDisp += "=\"" + encName.replace( '\\', "\\\\" ).replace( '"', "\\\"" ) + '"';
00400     mMsgPart->setContentDisposition( cDisp );
00401   }
00402 
00403   // apply Content-Description"
00404   TQString desc = description();
00405   if ( !desc.isEmpty() || !mMsgPart->contentDescription().isEmpty() )
00406     mMsgPart->setContentDescription( desc );
00407 
00408   // apply Content-Type:
00409   TQCString type = mimeType().latin1();
00410   TQCString subtype;
00411   int idx = type.find('/');
00412   if ( idx < 0 )
00413     subtype = "";
00414   else {
00415     subtype = type.mid( idx+1 );
00416     type = type.left( idx );
00417   }
00418   mMsgPart->setTypeStr(type);
00419   mMsgPart->setSubtypeStr(subtype);
00420 
00421   // apply Content-Transfer-Encoding:
00422   TQCString cte;
00423   if (subtype == "rfc822" && type == "message")
00424     kdWarning( encoding() != SevenBit && encoding() != EightBit, 5006 )
00425       << "encoding on rfc822/message must be \"7bit\" or \"8bit\"" << endl;
00426   switch ( encoding() ) {
00427   case SevenBit:        cte = "7bit";             break;
00428   case EightBit:        cte = "8bit";             break;
00429   case QuotedPrintable: cte = "quoted-printable"; break;
00430   case Base64: default: cte = "base64";           break;
00431   }
00432   if ( cte != mMsgPart->cteStr().lower() ) {
00433     TQByteArray body = mMsgPart->bodyDecodedBinary();
00434     mMsgPart->setCteStr( cte );
00435     mMsgPart->setBodyEncodedBinary( body );
00436   }
00437 }
00438 
00439 
00440 //-----------------------------------------------------------------------------
00441 void KMMsgPartDialogCompat::slotOk()
00442 {
00443   applyChanges();
00444   KMMsgPartDialog::slotOk();
00445 }
00446 
00447 
00448 //-----------------------------------------------------------------------------
00449 #include "kmmsgpartdlg.moc"