From kmail-devel Mon Jan 26 19:33:47 2004 From: Edwin Schepers Date: Mon, 26 Jan 2004 19:33:47 +0000 To: kmail-devel Subject: [PATCH] composing html messages Message-Id: <200401262033.47326.yez () home ! nl> X-MARC-Message: https://marc.info/?l=kmail-devel&m=107514532317823 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_buWFAMvscan2VQv" --Boundary-00=_buWFAMvscan2VQv Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi, This is a first rough patch for composing html messages. Could someone review it ? Thanks, Edwin behaviour is : - Composing a new mail : default always starting in plaintext. when some markup is selected, the mail becomes multipart/altenative. - Spellchecking : on "cancel", the original text is not set. only the spellchecking dialog disappears. - With a menu option "Editor" in the "options" menu, one can explicitly choose the type. here, richtext can be set back to plaintext. - in "Settings"->"Toolbars", the HTML toolbar can be choosen Automatic Spellchecking on RichText is not possible, since QSyntaxHighlighter doesn't supprt this. TODO : - more \n cq.

appear in the message after repeatedly opening and saving from drafts - spacing between lines is much more when first started with selecting for example the bold-button than when selecting all text and then selecting bold. Is this a QTextEdit issue which cannot be solved easily? - boundaries dissapear after setMultiPartBody() .Could someone help me with this one ? The boundaries are set, but it seems setMultiPartBody() deletes them again. Maybe with a reason but I don't know. (kmail however doesn't have a problem showing the message) Debug info from a test : KMComposeWin::composeMessage(): 98.a: |||--Boundary-00=_QQWFAngVx+VKruL Content-Type: text/plain Content-Transfer-Encoding: 7bit test --Boundary-00=_QQWFAngVx+VKruL Content-Type: text/html Content-Transfer-Encoding: 7bit

test

kmail: ||| kmail: kmail: KMComposeWin::composeMessage(): 99.: |||From: JES Reply-To: Bcc: To: Subject: Date: Mon, 26 Jan 2004 20:01:36 +0100 User-Agent: KMail/1.6.50 Cc: MIME-Version: 1.0 Content-Description: Content-Disposition: inline Content-Type: multipart/alternative; charset="us-ascii" Content-Transfer-Encoding: 7bit -- Content-Type: text/plain Content-Transfer-Encoding: 7bit test -- Content-Type: text/html Content-Transfer-Encoding: 7bit

test

---- kmail: ||| --Boundary-00=_buWFAMvscan2VQv Content-Type: text/x-diff; charset="us-ascii"; name="htmlmail.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="htmlmail.diff" Index: kmail/kmcomposerui.rc =================================================================== RCS file: /home/kde/kdepim/kmail/kmcomposerui.rc,v retrieving revision 1.28 diff -u -r1.28 kmcomposerui.rc --- kmail/kmcomposerui.rc 11 Nov 2003 01:23:52 -0000 1.28 +++ kmail/kmcomposerui.rc 26 Jan 2004 19:12:07 -0000 @@ -32,6 +32,10 @@ + &Editor + + + @@ -74,6 +78,7 @@ + Main Toolbar @@ -88,4 +93,18 @@ + Html Toolbar + + + + + + + + + + + + + Index: kmail/kmcomposewin.cpp =================================================================== RCS file: /home/kde/kdepim/kmail/kmcomposewin.cpp,v retrieving revision 1.772 diff -u -r1.772 kmcomposewin.cpp --- kmail/kmcomposewin.cpp 24 Jan 2004 23:39:03 -0000 1.772 +++ kmail/kmcomposewin.cpp 26 Jan 2004 19:12:26 -0000 @@ -7,6 +7,7 @@ #define DEFAULT_EDITOR_STR "kate %f" //#define STRICT_RULES_OF_GERMAN_GOVERNMENT_01 +#define DEBUG #undef GrayScale #undef Color @@ -75,6 +76,8 @@ #include #include #include +#include +#include #include #include @@ -213,10 +216,29 @@ SLOT( slotUpdateAttachActions() ) ); mAttachMenu = 0; + useHTMLEditor = false; + mEditor->setAcceptDrops( true ); readConfig(); setupStatusBar(); setupEditor(); setupActions(); + + // configuration is read now + if (useHTMLEditor) + slotToggleToHTML(); + else { + if ( aMsg ) { + if ( aMsg->typeStr()=="multipart" && aMsg->subtypeStr()=="alternative") { + slotToggleToHTML(); + } + else { + slotToggleToPlaintext(); + } + } + else + slotToggleToPlaintext(); + } + applyMainWindowSettings(KMKernel::config(), "Composer"); connect(mEdtSubject,SIGNAL(textChanged(const QString&)), @@ -288,6 +310,7 @@ kdDebug(5006) << "KMAIL_DEBUG_COMPOSER_CRYPTO = FALSE" << endl; } mDone = true; + } @@ -943,9 +966,9 @@ composerConfig.readBoolEntry( "autoSpellChecking", true ); mAutoSpellCheckingAction->setEnabled( !mUseExtEditor ); mAutoSpellCheckingAction->setChecked( !mUseExtEditor && spellChecking ); - mEditor->slotAutoSpellCheckingToggled( !mUseExtEditor && spellChecking ); + slotAutoSpellCheckingToggled( !mUseExtEditor && spellChecking ); connect( mAutoSpellCheckingAction, SIGNAL( toggled( bool ) ), - mEditor, SLOT( slotAutoSpellCheckingToggled( bool ) ) ); + this, SLOT( slotAutoSpellCheckingToggled( bool ) ) ); QStringList encodings = KMMsgBase::supportedEncodings(TRUE); encodings.prepend( i18n("Auto-Detect")); @@ -953,6 +976,14 @@ mEncodingAction->setCurrentItem( -1 ); //these are checkable!!! + plainTextAction = new KToggleAction (i18n("Plain text"), 0, this, SLOT(slotToggleToPlaintext()), + actionCollection(), "plaintext"); + + markupAction = new KToggleAction (i18n("With markup"), 0, this, SLOT(slotToggleToHTML()), + actionCollection(), "html"); + plainTextAction->setChecked(!useHTMLEditor); + markupAction->setChecked(useHTMLEditor); + mAllFieldsAction = new KToggleAction (i18n("&All Fields"), 0, this, SLOT(slotView()), actionCollection(), "show_all_fields"); @@ -1091,6 +1122,56 @@ mCryptoModuleAction->setCurrentItem( idx ); } + QStringList styleItems; + styleItems << i18n( "Standard" ); + styleItems << i18n( "Bullet List (Disc)" ); + styleItems << i18n( "Bullet List (Circle)" ); + styleItems << i18n( "Bullet List (Square)" ); + styleItems << i18n( "Ordered List (Decimal)" ); + styleItems << i18n( "Ordered List (Alpha lower)" ); + styleItems << i18n( "Ordered List (Alpha upper)" ); + + listAction = new KSelectAction( i18n( "Select Style" ), 0, actionCollection(), + "text_list" ); + listAction->setItems( styleItems ); + connect( listAction, SIGNAL( activated( const QString& ) ), + SLOT( slotListAction( const QString& ) ) ); + fontAction = new KFontAction( "Select Font", 0, actionCollection(), + "text_font" ); + connect( fontAction, SIGNAL( activated( const QString& ) ), + SLOT( slotFontAction( const QString& ) ) ); + fontSizeAction = new KFontSizeAction( "Select Size", 0, actionCollection(), + "text_size" ); + connect( fontSizeAction, SIGNAL( fontSizeChanged( int ) ), + SLOT( slotSizeAction( int ) ) ); + + alignLeftAction = new KToggleAction (i18n("Align Left"), "text_left", 0, + this, SLOT(slotAlignLeft()), actionCollection(), + "align_left"); + alignLeftAction->setChecked( TRUE ); + alignRightAction = new KToggleAction (i18n("Align Right"), "text_right", 0, + this, SLOT(slotAlignRight()), actionCollection(), + "align_right"); + alignCenterAction = new KToggleAction (i18n("Align Center"), "text_center", 0, + this, SLOT(slotAlignCenter()), actionCollection(), + "align_center"); + alignJustifyAction = new KToggleAction (i18n("Align Justify"), "kmtextjustify", 0, + this, SLOT(slotAlignJustify()), + actionCollection(), + "align_justify"); + textBoldAction = new KToggleAction (i18n("&Bold"), "text_bold", 0, + this, SLOT(slotTextBold()), + actionCollection(), "text_bold"); + textItalicAction = new KToggleAction (i18n("&Italic"), "text_italic", 0, + this, SLOT(slotTextItalic()), + actionCollection(), "text_italic"); + textUnderAction = new KToggleAction (i18n("&Under"), "text_under", 0, + this, SLOT(slotTextUnder()), + actionCollection(), "text_under"); + actionFormatColor = new KAction( i18n( "Text Color..." ), "colorize", 0, + this, SLOT( slotTextColor() ), + actionCollection(), "format_color"); + createGUI("kmcomposerui.rc"); } @@ -1164,6 +1245,10 @@ */ updateCursorPosition(); connect(mEditor,SIGNAL(CursorPositionChanged()),SLOT(updateCursorPosition())); + connect( mEditor, SIGNAL( currentFontChanged( const QFont & ) ), + this, SLOT( fontChanged( const QFont & ) ) ); + connect( mEditor, SIGNAL( currentAlignmentChanged( int ) ), + this, SLOT( alignmentChanged( int ) ) ); } @@ -1224,11 +1309,14 @@ { KMMessagePart bodyPart, *msgPart; int i, num; +#ifdef DEBUG + kdDebug(5006) << "entering KMComposeWin::setMsg()" << endl; +#endif //assert(newMsg!=0); if(!newMsg) { - kdDebug(5006) << "KMComposeWin::setMsg() : newMsg == 0!\n" << endl; + kdDebug(5006) << "KMComposeWin::setMsg() : newMsg == 0!" << endl; return; } mMsg = newMsg; @@ -1346,10 +1434,23 @@ if (num > 0) { QCString bodyDecoded; - mMsg->bodyPart(0, &bodyPart); + int firstAttachment=0; - int firstAttachment = (bodyPart.typeStr().lower() == "text") ? 1 : 0; - if (firstAttachment) + mMsg->bodyPart(1, &bodyPart); + if (bodyPart.typeStr().lower() == "text" && bodyPart.subtypeStr().lower() == "html" ) { + kdDebug(5006) << "KMComposeWin::setMsg() : text/html found" << endl; + firstAttachment = 2; + slotToggleToHTML(); + } else { + mMsg->bodyPart(0, &bodyPart); + if (bodyPart.typeStr().lower() == "text" ) { + kdDebug(5006) << "KMComposeWin::setMsg() : text/ found" << endl; + firstAttachment = 1; + slotToggleToPlaintext(); + } + } + + if (firstAttachment != 0) // there's text to show { mCharset = bodyPart.charset(); if ( mCharset.isEmpty() || mCharset == "default" ) @@ -1368,11 +1469,12 @@ const QTextCodec *codec = KMMsgBase::codecForName(mCharset); if (codec) - mEditor->setText(codec->toUnicode(bodyDecoded)); + setBody(codec->toUnicode(bodyDecoded)); else - mEditor->setText(QString::fromLocal8Bit(bodyDecoded)); + setBody(QString::fromLocal8Bit(bodyDecoded)); mEditor->insertLine("\n", -1); - } else mEditor->setText(""); + } else setBody(""); + for(i=firstAttachment; isetText(codec->toUnicode(bodyDecoded)); + setBody(codec->toUnicode(bodyDecoded)); } else - mEditor->setText(QString::fromLocal8Bit(bodyDecoded)); + setBody(QString::fromLocal8Bit(bodyDecoded)); } setCharset(mCharset); @@ -1416,6 +1518,7 @@ kmkernel->dumpDeadLetters(); } mEditor->setModified(isModified); + kdDebug(5006) << "leaving KMComposeWin::setMsg()" << endl; } @@ -1536,6 +1639,9 @@ { QString str, atmntStr; QString temp, replyAddr; +#ifdef DEBUG + kdDebug(5006) << "entering KMComposeWin::applyChanges" << endl; +#endif //assert(mMsg!=0); if(!mMsg) @@ -1909,6 +2015,12 @@ bool ignoreBcc, QCString& signCertFingerprint ) { +#ifdef DEBUG + kdDebug(5006) << "entering KMComposeWin::composeMessage" << endl; + doSign?kdDebug(5006) <<"doSign=true"<msgSender()->sendQuotedPrintable(); + if (useHTMLEditor) { + // calculate a boundary string + QCString boundaryCStr; // storing boundary string data + QCString newbody=""; + DwMediaType tmpCT; + tmpCT.CreateBoundary( 0 ); + boundaryCStr = tmpCT.Boundary().c_str(); + QValueList allowedCTEs; + + KMMessagePart textBodyPart; + textBodyPart.setTypeStr("text"); + textBodyPart.setSubtypeStr("plain"); + mEditor->setTextFormat(Qt::PlainText); + QCString textbody = breakLinesAndApplyCodec(); + mEditor->setTextFormat(Qt::RichText); + textBodyPart.setBodyAndGuessCte(textbody, allowedCTEs, !isQP && !doSign, + doSign); + DwBodyPart* textDwPart = theMessage.createDWBodyPart( &textBodyPart ); + textDwPart->Assemble(); + newbody += "--"; + newbody += boundaryCStr; + newbody += "\n"; + newbody += textDwPart->AsString().c_str(); + delete textDwPart; + textDwPart = 0; + + KMMessagePart htmlBodyPart; + htmlBodyPart.setTypeStr("text"); + htmlBodyPart.setSubtypeStr("html"); + // the signed body must not be 8bit encoded + QCString htmlbody = breakLinesAndApplyCodec(); + htmlBodyPart.setBodyAndGuessCte(htmlbody, allowedCTEs, !isQP && !doSign, + doSign); + DwBodyPart* htmlDwPart = theMessage.createDWBodyPart( &htmlBodyPart ); + htmlDwPart->Assemble(); + newbody += "\n--"; + newbody += boundaryCStr; + newbody += "\n"; + newbody += htmlDwPart->AsString().c_str(); + delete htmlDwPart; + htmlDwPart = 0; + + //newbody += "--"; + //newbody += boundaryCStr; + //newbody += "\n"; + kdDebug(5006) << "###newbody to add in message : \"" << newbody << "\""< allowedCTEs; // the signed body must not be 8bit encoded innerBodyPart.setBodyAndGuessCte(body, allowedCTEs, !isQP && !doSign, doSign); innerBodyPart.setCharset(mCharset); - innerBodyPart.setBodyEncoded( body ); + innerBodyPart.setBodyEncoded( body ); // do we need this, since setBodyAndGuessCte does this already? DwBodyPart* innerDwPart = theMessage.createDWBodyPart( &innerBodyPart ); innerDwPart->Assemble(); body = "--"; @@ -2058,6 +2231,7 @@ doSign); oldBodyPart.setCharset(mCharset); } +kdDebug(5006) << "body is now : \n" << body << endl; // create S/MIME body part for signing and/or encrypting oldBodyPart.setBodyEncoded( body ); @@ -2205,7 +2379,7 @@ newBodyPart, signCertFingerprint ); } - // kdDebug(5006) << "###AFTER ENCRYPTION\"" << theMessage.asString() << "\""<headers().ContentType().FromString( "Multipart/Mixed" ); -kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type to Multipart/Mixed" << endl; + kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type to Multipart/Mixed" << endl; // msg->setBody( "This message is in MIME format.\n" // "Since your mail reader does not understand this format,\n" // "some or all parts of this message may not be legible." ); @@ -2587,13 +2765,18 @@ msg->headers().ContentType().Parse(); //msg->headers().Assemble(); //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n C.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; -kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type from originalContentTypeStr()" << endl; + //kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type from originalContentTypeStr()" << endl; } else { + kdDebug(5006) << "KMComposeWin::composeMessage():\n 98.:\n\n|||" << msg->asString() << "|||\n\n" << endl; + //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage(): ourFineBodyPart.originalContentTypeStr()='"<< + // ourFineBodyPart.originalContentTypeStr()<<"'" << endl; msg->headers().ContentType().FromString( ourFineBodyPart.typeStr() + "/" + ourFineBodyPart.subtypeStr() ); -kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type from typeStr()/subtypeStr()" << endl; + //kdDebug(5006) << "ourFineBodyPart.typeStr()=" << ourFineBodyPart.typeStr() << ", ourFineBodyPart.subtypeStr()=" << ourFineBodyPart.subtypeStr() << endl; + + //kdDebug(5006) << "5. KMComposeWin::encryptMessage() : set top level Content-Type from typeStr()/subtypeStr()" << endl; } //msg->headers().Assemble(); - //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n D.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; + //kdDebug(5006) << "KMComposeWin::composeMessage():\n D.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; msg->setCharset( ourFineBodyPart.charset() ); //msg->headers().Assemble(); //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n E.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; @@ -2606,12 +2789,12 @@ msg->setHeaderField( "Content-Disposition", ourFineBodyPart.contentDisposition() ); -kdDebug(5006) << "KMComposeWin::encryptMessage() : top level headers and body adjusted" << endl; + kdDebug(5006) << "KMComposeWin::encryptMessage() : top level headers and body adjusted" << endl; // set body content - // msg->setBody( ourFineBodyPart.body() ); + kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n 98.a:\n\n\n\n|||" << ourFineBodyPart.body() << "|||\n\n\n\n\n\n" << endl; msg->setMultiPartBody( ourFineBodyPart.body() ); - //kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n 99.:\n\n\n\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl; + kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n 99.:\n\n\n\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl; //msg->headers().Assemble(); //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n Z.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; } @@ -2986,7 +3169,7 @@ QString text; QCString cText; - if (mDisableBreaking) + if (mDisableBreaking || mEditor->textFormat() == Qt::RichText) text = mEditor->text(); else text = mEditor->brokenText(); @@ -3014,7 +3197,7 @@ if (!text.isEmpty() && (newText != text)) { QString oldText = mEditor->text(); - mEditor->setText(newText); + setBody(newText); KCursorSaver idle(KBusyPtr::idle()); bool anyway = (KMessageBox::warningYesNo(this, i18n("Not all characters fit into the chosen" @@ -3023,7 +3206,7 @@ i18n("Send"), i18n("Change Encoding") ) == KMessageBox::Yes); if (!anyway) { - mEditor->setText(oldText); + setBody(oldText); return QCString(); } } @@ -4985,6 +5168,9 @@ mAutoDeleteMsg = FALSE; mFolder = 0; close(); +#ifdef DEBUG + kdDebug(5006) << "leaving KMComposeWin::doSend()" << endl; +#endif return true; } @@ -5064,6 +5250,48 @@ mEditor->cleanWhiteSpace(); } +//----------------------------------------------------------------------------- +void KMComposeWin::slotToggleToPlaintext() +{ + if ( useHTMLEditor == true) { // don't do it twice + kdDebug(5006) << "setting PlainText editor" << endl; + useHTMLEditor = false; + mEditor->setTextFormat(Qt::PlainText); + QString text = mEditor->text(); + mEditor->setText(text); // otherwise the text still looks formatted + mEditor->setModified(true); + markupAction->setChecked(false); + plainTextAction->setChecked(true); + mEditor->initializeAutoSpellChecking( mDictionaryCombo->spellConfig()); + //mAutoSpellCheckingAction->setChecked(true); + slotAutoSpellCheckingToggled(true); + } +} + +//----------------------------------------------------------------------------- +void KMComposeWin::slotToggleToHTML() +{ + if ( useHTMLEditor == false ) { // don't do it twice + kdDebug(5006) << "setting RichText editor" << endl; + useHTMLEditor = true; // set it directly to true. setColor hits another slotToggleToHTML + + // set all highlighted text caused by spelling back to black + int paraFrom, indexFrom, paraTo, indexTo; + mEditor->getSelection ( ¶From, &indexFrom, ¶To, &indexTo); + mEditor->selectAll(); + mEditor->setColor(QColor(0,0,0)); + mEditor->setSelection ( paraFrom, indexFrom, paraTo, indexTo); + + mEditor->setTextFormat(Qt::RichText); + mEditor->setModified(true); + plainTextAction->setChecked(false); + markupAction->setChecked(true); + mEditor->deleteAutoSpellChecking(); + mAutoSpellCheckingAction->setChecked(false); + slotAutoSpellCheckingToggled(false); + } +} + //----------------------------------------------------------------------------- void KMComposeWin::slotSpellcheck() @@ -5202,7 +5430,7 @@ { if( !mOldSigText.isEmpty() && mAutoSign ) edtText.append( mOldSigText ); - mEditor->setText( edtText ); + setBody( edtText ); } // disable certain actions if there is no PGP user identity set @@ -5238,6 +5466,12 @@ } //----------------------------------------------------------------------------- +void KMComposeWin::slotAutoSpellCheckingToggled( bool on ) +{ + if (mEditor->AutoSpellChecking(on) == -1 ) + mAutoSpellCheckingAction->setChecked(false); // set it to false again +} +//----------------------------------------------------------------------------- void KMComposeWin::slotSpellcheckConfig() { KWin kwin; @@ -5338,6 +5572,117 @@ mAlwaysSend = bAlways; } +void KMComposeWin::slotListAction( const QString& style ) +{ + if ( style == i18n( "Standard" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc ); + else if ( style == i18n( "Bullet List (Disc)" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); + else if ( style == i18n( "Bullet List (Circle)" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListCircle ); + else if ( style == i18n( "Bullet List (Square)" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListSquare ); + else if ( style == i18n( "Ordered List (Decimal)" )) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDecimal ); + else if ( style == i18n( "Ordered List (Alpha lower)" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListLowerAlpha ); + else if ( style == i18n( "Ordered List (Alpha upper)" ) ) + mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListUpperAlpha ); + mEditor->viewport()->setFocus(); +} + +void KMComposeWin::slotFontAction( const QString& font) +{ + slotToggleToHTML(); + mEditor->QTextEdit::setFamily( font ); + mEditor->viewport()->setFocus(); + qDebug( "font %s", font.latin1() ); +} + +void KMComposeWin::slotSizeAction( int size ) +{ + slotToggleToHTML(); + mEditor->setPointSize( size ); + mEditor->viewport()->setFocus(); + qDebug( "font size %d", size ); +} + +void KMComposeWin::slotAlignLeft() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setAlignment( AlignLeft ); +} + +void KMComposeWin::slotAlignCenter() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setAlignment( AlignHCenter ); +} + +void KMComposeWin::slotAlignRight() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setAlignment( AlignRight ); +} + +void KMComposeWin::slotAlignJustify() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setAlignment( AlignJustify ); +} + +void KMComposeWin::slotTextBold() +{ + kdDebug(5006) << "entering KMComposeWin::slotTextBold()" << endl; + slotToggleToHTML(); + mEditor->setBold( textBoldAction->isChecked() ); + //mEditor->QTextEdit::setBold( textBoldAction->isChecked() ); + kdDebug(5006) << "leaving KMComposeWin::slotTextBold()" << endl; +} + +void KMComposeWin::slotTextItalic() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setItalic( textItalicAction->isChecked() ); +} + +void KMComposeWin::slotTextUnder() +{ + slotToggleToHTML(); + mEditor->QTextEdit::setUnderline( textUnderAction->isChecked() ); +} + +void KMComposeWin::slotTextColor() +{ + QColor color = mEditor->color(); + if ( KColorDialog::getColor( color ) ) { + slotToggleToHTML(); + mEditor->setColor( color ); + } +} + +void KMComposeWin::fontChanged( const QFont &f ) +{ + kdDebug(5006) << "KMComposeWin::fontChanged()" << endl; + //if ( useHTMLEditor == true) { + //slotToggleToHTML(); don't toggle. + fontAction->setFont( f.family() ); + fontSizeAction->setFontSize( f.pointSize() ); + textBoldAction->setChecked( f.bold() ); + textItalicAction->setChecked( f.italic() ); + textUnderAction->setChecked( f.underline() ); + //} +} + +void KMComposeWin::alignmentChanged( int a ) +{ + slotToggleToHTML(); + alignLeftAction->setChecked( ( a == AlignAuto ) || ( a & AlignLeft ) ); + alignCenterAction->setChecked( ( a & AlignHCenter ) ); + alignRightAction->setChecked( ( a & AlignRight ) ); + alignJustifyAction->setChecked( ( a & AlignJustify ) ); +} + void KMEdit::contentsDragEnterEvent(QDragEnterEvent *e) { if (e->provides(MailListDrag::format())) @@ -5681,7 +6026,7 @@ newText.replace( QRegExp("\\s*\\(at\\)\\s*"), "@" ); } contents = contents.left(pos)+newText+contents.mid(pos); - setText(contents); + setBody(contents); setEdited( true ); setCursorPosition(pos+newText.length()); } @@ -5767,6 +6112,7 @@ QColor defaultColor2( 0x00, 0x70, 0x00 ); QColor defaultColor3( 0x00, 0x60, 0x00 ); QColor defaultForeground( kapp->palette().active().text() ); + QColor col1 = readerConfig.readColorEntry( "ForegroundColor", &defaultForeground ); QColor col2 = readerConfig.readColorEntry( "QuotedText3", &defaultColor3 ); QColor col3 = readerConfig.readColorEntry( "QuotedText2", &defaultColor2 ); @@ -5787,18 +6133,34 @@ } //----------------------------------------------------------------------------- +void KMEdit::deleteAutoSpellChecking() +{ // because the highlighter doesn''t support RichText, delete its instance. + delete mSpellChecker; +} +//----------------------------------------------------------------------------- void KMEdit::addSuggestion(const QString& text, const QStringList& lst, unsigned int ) { mReplacements[text] = lst; } + +void KMEdit::setSpellCheckingActive(bool spellCheckingActive) +{ + if (textFormat() != Qt::RichText) { + mSpellChecker->setActive(spellCheckingActive); + } +} + + //----------------------------------------------------------------------------- KMEdit::~KMEdit() { removeEventFilter(this); delete mKSpell; + if (textFormat() != Qt::RichText) { delete mSpellChecker; + } } @@ -5966,11 +6328,17 @@ //----------------------------------------------------------------------------- -void KMEdit::slotAutoSpellCheckingToggled( bool on ) +int KMEdit::AutoSpellChecking( bool on ) { + if (textFormat() == Qt::RichText ) { + // syntax highlighter doesn't support extended text properties + if (on) KMessageBox::sorry(this, i18n("Automatic spellchecking is not possible on text with markup.")); + return -1; + } // don't autoEnable spell checking if the user turned spell checking off mSpellChecker->setAutomatic( on ); mSpellChecker->setActive( on ); + return 1; } @@ -6028,8 +6396,16 @@ return; mWasModifiedBeforeSpellCheck = isModified(); mSpellLineEdit = !mSpellLineEdit; - mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this, - SLOT(slotSpellcheck2(KSpell*))); +// maybe for later, for now plaintext is given to KSpell +// if (textFormat() == Qt::RichText ) { +// kdDebug(5006) << "KMEdit::spellcheck, spellchecking for RichText" << endl; +// mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this, +// SLOT(slotSpellcheck2(KSpell*)),0,true,false,KSpell::HTML); +// } +// else { + mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this, + SLOT(slotSpellcheck2(KSpell*))); +// } QStringList l = KSpellingHighlighter::personalWords(); for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { mKSpell->addPersonal( *it ); @@ -6047,20 +6423,26 @@ #if KDE_IS_VERSION( 3, 1, 92 ) void KMEdit::cut() { - KEdit::cut(); - mSpellChecker->restartBackgroundSpellCheck(); + KEdit::cut(); + if (textFormat() != Qt::RichText) { + mSpellChecker->restartBackgroundSpellCheck(); + } } void KMEdit::clear() { - KEdit::clear(); - mSpellChecker->restartBackgroundSpellCheck(); + KEdit::clear(); + if (textFormat() != Qt::RichText) { + mSpellChecker->restartBackgroundSpellCheck(); + } } void KMEdit::del() { - KEdit::del(); - mSpellChecker->restartBackgroundSpellCheck(); + KEdit::del(); + if (textFormat() != Qt::RichText) { + mSpellChecker->restartBackgroundSpellCheck(); + } } #else // can't #ifdef slots :-( @@ -6084,8 +6466,28 @@ kdDebug()<<"slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos) : "<sujectLineWidget()->spellCheckerCorrected( oldWord, newWord, pos); - else - corrected(oldWord, newWord, pos); + else { + unsigned int l = 0; + unsigned int cnt = 0; + bool _bold,_underline,_italic; + QColor _color; + QFont _font; + posToRowCol (pos, l, cnt); + setCursorPosition(l, cnt+1); // the new word will get the same markup now + _bold = bold(); + _underline = underline(); + _italic = italic(); + _color = color(); + _font = currentFont(); + corrected(oldWord, newWord, pos); + setSelection (l, cnt, l, cnt+newWord.length()); + setBold(_bold); + setItalic(_italic); + setUnderline(_underline); + setColor(_color); + setCurrentFont(_font); + } + } //----------------------------------------------------------------------------- @@ -6110,7 +6512,10 @@ } kdDebug(5006) << "spelling: new SpellingFilter with prefix=\"" << quotePrefix << "\"" << endl; - mSpellingFilter = new SpellingFilter(text(), quotePrefix, SpellingFilter::FilterUrls, + QTextEdit plaintext; + plaintext.setText(text()); + plaintext.setTextFormat(Qt::PlainText); + mSpellingFilter = new SpellingFilter(plaintext.text(), quotePrefix, SpellingFilter::FilterUrls, SpellingFilter::FilterEmailAddresses); mKSpell->check(mSpellingFilter->filteredText()); @@ -6140,8 +6545,9 @@ } else { - kdDebug(5006) << "spelling: canceled - restoring text from SpellingFilter" << endl; - setText(mSpellingFilter->originalText()); + // don't restore, why undo all explicit replacements? + //kdDebug(5006) << "spelling: canceled - restoring text from SpellingFilter" << endl; + //setText(mSpellingFilter->originalText()); setModified(mWasModifiedBeforeSpellCheck); } } Index: kmail/kmcomposewin.h =================================================================== RCS file: /home/kde/kdepim/kmail/kmcomposewin.h,v retrieving revision 1.226 diff -u -r1.226 kmcomposewin.h --- kmail/kmcomposewin.h 28 Dec 2003 14:10:34 -0000 1.226 +++ kmail/kmcomposewin.h 26 Jan 2004 19:12:26 -0000 @@ -55,6 +55,9 @@ class KProcess; class KDirWatch; class KSelectAction; +class KFontAction; +class KFontSizeAction; +class KSelectAction; class KSpell; class KSpellConfig; class KDictSpellingHighlighter; @@ -64,6 +67,7 @@ class KTempFile; class KToolBar; class KToggleAction; +class KSelectColorAction; class KURL; class IdentityCombo; class SpellingFilter; @@ -98,6 +102,11 @@ QString brokenText(); /** + * Toggle automatic spellchecking + */ + int AutoSpellChecking( bool ); + + /** * For the external editor */ void setUseExternalEditor( bool use ) { mUseExtEditor = use; } @@ -112,15 +121,18 @@ bool checkExternalEditorFinished(); + void setSpellCheckingActive(bool spellCheckingActive); + /** Drag and drop methods */ void contentsDragEnterEvent(QDragEnterEvent *e); void contentsDragMoveEvent(QDragMoveEvent *e); void contentsDropEvent(QDropEvent *e); + void initializeAutoSpellChecking( KSpellConfig* autoSpellConfig ); + void deleteAutoSpellChecking(); signals: void spellcheck_done(int result); public slots: - void slotAutoSpellCheckingToggled( bool ); void slotSpellcheck2(KSpell*); void slotSpellResult(const QString&); void slotSpellDone(); @@ -145,7 +157,6 @@ private: void killExternalEditor(); - void initializeAutoSpellChecking( KSpellConfig* autoSpellConfig ); private: KSpell *mKSpell; @@ -505,6 +516,9 @@ void slotCleanSpace(); + void slotToggleToPlaintext(); + void slotToggleToHTML(); + // void slotSpellConfigure(); void slotSpellcheckDone(int result); @@ -542,6 +556,20 @@ */ void addAttach(const KMMessagePart* msgPart); + void slotListAction(const QString &); + void slotFontAction(const QString &); + void slotSizeAction(int); + void slotAlignLeft(); + void slotAlignCenter(); + void slotAlignRight(); + void slotAlignJustify(); + void slotTextBold(); + void slotTextItalic(); + void slotTextUnder(); + void slotTextColor(); + void fontChanged( const QFont & ); + void alignmentChanged( int ); + signals: /** * A message has been queued or saved in the drafts folder @@ -685,10 +713,10 @@ * called via pgpSignedMsg() (or pgpEncryptedMsg(), resp.). * * NOTE: The c string representation of the MIME object (or the - * flat text, resp.) is returned in resultingData, so just + * flat text, resp.) is returned in resultingPart, so just * use this string as body text of the surrounding MIME object. * This string *is* encoded according to contentTEncClear - * and thus should be ready for neing sended via SMTP. + * and thus should be ready for being sent via SMTP. */ bool processStructuringInfo( const QString bugURL, uint boundaryLevel, @@ -783,6 +811,7 @@ KMFolder *mFolder; long mShowHeaders; QString mExtEditor; + bool useHTMLEditor; bool mUseExtEditor; QPtrList<_StringPair> mCustHeaders; bool mConfirmSend; @@ -813,6 +842,15 @@ KToggleAction *mWordWrapAction, *mFixedFontAction, *mAutoSpellCheckingAction; KToggleAction *mDictionaryAction; + KSelectAction *listAction; + KFontAction *fontAction; + KFontSizeAction *fontSizeAction; + KToggleAction *alignLeftAction, *alignCenterAction, *alignRightAction, + *alignJustifyAction; + KToggleAction *textBoldAction, *textItalicAction, *textUnderAction; + KToggleAction *plainTextAction, *markupAction; + KAction *actionFormatColor; + KSelectAction *mEncodingAction; KSelectAction *mCryptoModuleAction; @@ -830,6 +868,12 @@ void slotCompletionModeChanged( KGlobalSettings::Completion ); void slotConfigChanged(); + /** + * toggle automatic spellchecking + */ + void slotAutoSpellCheckingToggled(bool); + + private: QColor mForeColor,mBackColor; struct atmLoadData Index: kmail/kmmessage.h =================================================================== RCS file: /home/kde/kdepim/kmail/kmmessage.h,v retrieving revision 1.159 diff -u -r1.159 kmmessage.h --- kmail/kmmessage.h 20 Jan 2004 12:28:09 -0000 1.159 +++ kmail/kmmessage.h 26 Jan 2004 19:12:29 -0000 @@ -589,7 +589,7 @@ DwBodyPart * getFirstDwBodyPart() const; /** Fill the KMMessagePart structure for a given DwBodyPart. - Iff withBody is false the body of the KMMessagePart will be left + If withBody is false the body of the KMMessagePart will be left empty and only the headers of the part will be filled in*/ static void bodyPart(DwBodyPart* aDwBodyPart, KMMessagePart* aPart, bool withBody = true ); --Boundary-00=_buWFAMvscan2VQv Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ KMail developers mailing list KMail-devel@kde.org https://mail.kde.org/mailman/listinfo/kmail-devel --Boundary-00=_buWFAMvscan2VQv--