From kmail-devel Sun Feb 08 11:22:08 2004 From: Edwin Schepers Date: Sun, 08 Feb 2004 11:22:08 +0000 To: kmail-devel Subject: [PATCH] composing html messages Message-Id: <200402081222.08275.yez () home ! nl> X-MARC-Message: https://marc.info/?l=kmail-devel&m=107623900518313 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_gvhJAkFMIb2d2Ef" --Boundary-00=_gvhJAkFMIb2d2Ef Content-Type: text/plain; charset="us-ascii"; boundary="" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi, Finally it looks I have something workable. It's not final: indentation, deleting some kDebug's and naming has to be changed. Could you (someone) review ? If this is the way to go, and when it looks quite stable, can I commit (after the changes to make it final)? This feature also requires a small patch in kdelibs/kdeui/ksyntaxhighlighter. Would that be a problem for kdepim-3.3 ? Regards, Edwin --Boundary-00=_gvhJAkFMIb2d2Ef Content-Type: text/x-diff; charset="us-ascii"; name="htmlmail.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="htmlmail.diff" ? kmail/.kmcomposewin.cpp.swp ? kmail/.kmmessage.h.swp 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 8 Feb 2004 11:06:02 -0000 @@ -1,4 +1,4 @@ - + &Message @@ -32,6 +32,7 @@ + @@ -74,6 +75,7 @@ + Main Toolbar @@ -88,4 +90,18 @@ + Html Toolbar + + + + + + + + + + + + + Index: kmail/kmcomposewin.cpp =================================================================== RCS file: /home/kde/kdepim/kmail/kmcomposewin.cpp,v retrieving revision 1.782 diff -u -r1.782 kmcomposewin.cpp --- kmail/kmcomposewin.cpp 7 Feb 2004 16:52:47 -0000 1.782 +++ kmail/kmcomposewin.cpp 8 Feb 2004 11:06:18 -0000 @@ -7,6 +7,7 @@ #define DEFAULT_EDITOR_STR "kate %f" //#define STRICT_RULES_OF_GERMAN_GOVERNMENT_01 +#define DEBUG #undef GrayScale #undef Color @@ -77,6 +78,7 @@ #include #include #include +#include #include #include @@ -215,10 +217,29 @@ SLOT( slotUpdateAttachActions() ) ); mAttachMenu = 0; + useHTMLEditor = false; + mEditor->setAcceptDrops( true ); readConfig(); setupStatusBar(); setupEditor(); setupActions(); + + // configuration is read now + if (useHTMLEditor) + toggleMarkup(true); + else { + if ( aMsg ) { + if ( aMsg->typeStr()=="multipart" && aMsg->subtypeStr()=="alternative") { + toggleMarkup(true); + } + else { + toggleMarkup(false); + } + } + else + toggleMarkup(false); + } + applyMainWindowSettings(KMKernel::config(), "Composer"); connect(mEdtSubject,SIGNAL(textChanged(const QString&)), @@ -290,6 +311,7 @@ kdDebug(5006) << "KMAIL_DEBUG_COMPOSER_CRYPTO = FALSE" << endl; } mDone = true; + } @@ -962,9 +984,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")); @@ -972,6 +994,14 @@ mEncodingAction->setCurrentItem( -1 ); //these are checkable!!! + //plainTextAction = new KToggleAction (i18n("Plain text"), 0, this, SLOT(slotToggleToPlaintext()), + // actionCollection(), "plaintext"); + + markupAction = new KToggleAction (i18n("HTML"), 0, this, SLOT(slotToggleMarkup()), + actionCollection(), "html"); + //plainTextAction->setChecked(!useHTMLEditor); + markupAction->setChecked(useHTMLEditor); + mAllFieldsAction = new KToggleAction (i18n("&All Fields"), 0, this, SLOT(slotView()), actionCollection(), "show_all_fields"); @@ -1007,6 +1037,10 @@ actionCollection(), "show_subject"); //end of checkable + //mHtmlToolbar = new KAction (i18n("Html Toolbar"), 0, this, + // NULL, + // actionCollection(), "htmlToolBar"); + (void) new KAction (i18n("Append S&ignature"), 0, this, SLOT(slotAppendSignature()), actionCollection(), "append_signature"); @@ -1110,6 +1144,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"); } @@ -1183,6 +1267,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 ) ) ); } @@ -1243,11 +1331,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; @@ -1365,10 +1456,33 @@ if (num > 0) { QCString bodyDecoded; - mMsg->bodyPart(0, &bodyPart); + int firstAttachment=0; - int firstAttachment = (bodyPart.typeStr().lower() == "text") ? 1 : 0; - if (firstAttachment) +//JES : this part has to be refined +// met attachment wordt een mail multipart/mixed. text/html is dan niet meer de 2e bodypart + mMsg->bodyPart(1, &bodyPart); + if (bodyPart.typeStr().lower() == "text" && bodyPart.subtypeStr().lower() == "html" ) { + kdDebug(5006) << "KMComposeWin::setMsg() : text/html found" << endl; + firstAttachment = 2; + toggleMarkup(true); + } else { + mMsg->bodyPart(2, &bodyPart); + if (bodyPart.typeStr().lower() == "text" && bodyPart.subtypeStr().lower() == "html" ) { + kdDebug(5006) << "KMComposeWin::setMsg() : text/html found" << endl; + firstAttachment = 3; + toggleMarkup(true); + } + else { + mMsg->bodyPart(0, &bodyPart); + if (bodyPart.typeStr().lower() == "text" ) { + kdDebug(5006) << "KMComposeWin::setMsg() : text/ found" << endl; + firstAttachment = 1; + toggleMarkup(true); + } + } + } + + if (firstAttachment != 0) // there's text to show { mCharset = bodyPart.charset(); if ( mCharset.isEmpty() || mCharset == "default" ) @@ -1387,11 +1501,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); @@ -1435,6 +1550,7 @@ kmkernel->dumpDeadLetters(); } mEditor->setModified(isModified); + kdDebug(5006) << "leaving KMComposeWin::setMsg()" << endl; } @@ -1553,6 +1669,13 @@ //----------------------------------------------------------------------------- bool KMComposeWin::applyChanges( bool backgroundMode ) { + QString str, atmntStr; + QString temp, replyAddr; +#ifdef DEBUG + kdDebug(5006) << "entering KMComposeWin::applyChanges" << endl; +#endif + + //assert(mMsg!=0); if(!mMsg) { kdDebug(5006) << "KMComposeWin::applyChanges() : mMsg == 0!\n" << endl; return FALSE; @@ -1600,7 +1723,6 @@ mMsg->removeHeaderField("X-KMail-Identity"); else mMsg->setHeaderField("X-KMail-Identity", QString::number( id.uoid() )); - QString replyAddr; if (!replyTo().isEmpty()) replyAddr = replyTo(); else replyAddr = from(); @@ -1917,6 +2039,12 @@ bool ignoreBcc, QCString& signCertFingerprint ) { +#ifdef DEBUG + kdDebug(5006) << "entering KMComposeWin::composeMessage" << endl; + doSign?kdDebug(5006) <<"doSign=true"<msgSender()->sendQuotedPrintable(); + if (useHTMLEditor) { // create a multipart body + // 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,7 +2251,7 @@ body += boundaryCStr; body += "--\n"; } - else + else // !earlyAddAttachments { QValueList allowedCTEs; // the signed body must not be 8bit encoded @@ -2066,6 +2259,7 @@ doSign); oldBodyPart.setCharset(mCharset); } +kdDebug(5006) << "body is now (3): \n" << body << endl; // create S/MIME body part for signing and/or encrypting oldBodyPart.setBodyEncoded( body ); @@ -2202,6 +2396,7 @@ theMessage.setHeaderField( "X-KMail-Recipients", recipientsWithoutBcc.join(",") ); } + kdDebug(5006) << "###BEFORE \"" << oldBodyPart.body() << "\""<< endl; // run encrypting for public recipient(s) if( result == Kpgp::Ok ){ result = encryptMessage( &theMessage, @@ -2213,7 +2408,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; -// 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." ); + 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." ); // add our Body Part - msg->addBodyPart( &ourFineBodyPart ); +DwBodyPart* myDwPart = msg->createDWBodyPart( &ourFineBodyPart ); +DwHeaders& headers = myDwPart->Headers(); +DwMediaType& ct = headers.ContentType(); +ct.SetBoundary(myGlobalBoundary); +myDwPart->Assemble(); + + KMMessagePart newPart; + newPart.setBody(myDwPart->AsString().c_str()); + msg->addDwBodyPart(myDwPart); // only this method doesn't add a bodypart text/plain // add Attachments // create additional bodyparts for the attachments (if any) @@ -2577,8 +2784,9 @@ } } msg->addBodyPart( &newAttachPart ); - } else + } else { msg->addBodyPart( attachPart ); + } kdDebug(5006) << " added " << idx << ". attachment to this Multipart/Mixed" << endl; } else { @@ -2595,13 +2803,16 @@ 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; 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; @@ -2614,13 +2825,18 @@ 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() ); - 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 98.a:\n\n\n\n|||" << ourFineBodyPart.body() << "|||\n\n\n\n\n\n" << endl; + if ( useHTMLEditor) { // add the boundary to the header + DwMediaType & contentType = msg->dwContentType(); + contentType.SetBoundary(myGlobalBoundary); + } + msg->setBody(ourFineBodyPart.body() ); + kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n 99.:\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl; //msg->headers().Assemble(); + kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n 100.:\n\n\n\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl; //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n Z.:\n\n" << msg->headerAsString() << "|||\n\n\n\n\n" << endl; } @@ -2994,7 +3210,7 @@ QString text; QCString cText; - if (mDisableBreaking) + if (mDisableBreaking || mEditor->textFormat() == Qt::RichText) text = mEditor->text(); else text = mEditor->brokenText(); @@ -3022,7 +3238,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" @@ -3031,7 +3247,7 @@ i18n("Send"), i18n("Change Encoding") ) == KMessageBox::Yes); if (!anyway) { - mEditor->setText(oldText); + setBody(oldText); return QCString(); } } @@ -4995,6 +5211,9 @@ mAutoDeleteMsg = FALSE; mFolder = 0; close(); +#ifdef DEBUG + kdDebug(5006) << "leaving KMComposeWin::doSend()" << endl; +#endif return true; } @@ -5074,6 +5293,62 @@ mEditor->cleanWhiteSpace(); } +//----------------------------------------------------------------------------- +void KMComposeWin::slotToggleMarkup() +{ + if ( markupAction->isChecked() ) { + kdDebug(5006) << "KMComposeWin::slotToggleMarkup, markupAction isChecked" << endl; + toggleMarkup(true); + } + else + toggleMarkup(false); + +} +//----------------------------------------------------------------------------- +void KMComposeWin::toggleMarkup(bool markup) +{ + if (markup)kdDebug(5006) << "KMComposeWin::toggleMarkup, entering. markup==true" << endl; + if(!markup)kdDebug(5006) << "KMComposeWin::toggleMarkup, entering. markup==false" << endl; + if ( markup ) { + if (!useHTMLEditor) { + kdDebug(5006) << "setting RichText editor" << endl; + useHTMLEditor = true; // set it directly to true. setColor hits another toggleMarkup + + // 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); + toolBar("htmlToolBar")->show(); + markupAction->setChecked(true); + mEditor->deleteAutoSpellChecking(); + mAutoSpellCheckingAction->setChecked(false); + slotAutoSpellCheckingToggled(false); + } + } + else { + 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); + toolBar("htmlToolBar")->hide(); + //plainTextAction->setChecked(true); + kdDebug(5006) << "here" << endl; + mEditor->initializeAutoSpellChecking( mDictionaryCombo->spellConfig()); + //mAutoSpellCheckingAction->setChecked(true); + slotAutoSpellCheckingToggled(true); + } + +} + //----------------------------------------------------------------------------- void KMComposeWin::slotSpellcheck() @@ -5212,7 +5487,7 @@ { if( !mOldSigText.isEmpty() && mAutoSign ) edtText.append( mOldSigText ); - mEditor->setText( edtText ); + setBody( edtText ); } // disable certain actions if there is no PGP user identity set @@ -5248,6 +5523,12 @@ } //----------------------------------------------------------------------------- +void KMComposeWin::slotAutoSpellCheckingToggled( bool on ) +{ + if (mEditor->AutoSpellChecking(on) == -1 ) + mAutoSpellCheckingAction->setChecked(false); // set it to false again +} +//----------------------------------------------------------------------------- void KMComposeWin::slotSpellcheckConfig() { KWin kwin; @@ -5348,6 +5629,119 @@ 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) +{ + toggleMarkup(true); + mEditor->QTextEdit::setFamily( font ); + mEditor->viewport()->setFocus(); + qDebug( "font %s", font.latin1() ); +} + +void KMComposeWin::slotSizeAction( int size ) +{ + toggleMarkup(true); + mEditor->setPointSize( size ); + mEditor->viewport()->setFocus(); + qDebug( "font size %d", size ); +} + +void KMComposeWin::slotAlignLeft() +{ + toggleMarkup(true); + mEditor->QTextEdit::setAlignment( AlignLeft ); +} + +void KMComposeWin::slotAlignCenter() +{ + toggleMarkup(true); + mEditor->QTextEdit::setAlignment( AlignHCenter ); +} + +void KMComposeWin::slotAlignRight() +{ + toggleMarkup(true); + mEditor->QTextEdit::setAlignment( AlignRight ); +} + +void KMComposeWin::slotAlignJustify() +{ + toggleMarkup(true); + mEditor->QTextEdit::setAlignment( AlignJustify ); +} + +void KMComposeWin::slotTextBold() +{ + kdDebug(5006) << "entering KMComposeWin::slotTextBold()" << endl; + toggleMarkup(true); + mEditor->setBold( textBoldAction->isChecked() ); + //mEditor->QTextEdit::setBold( textBoldAction->isChecked() ); + kdDebug(5006) << "leaving KMComposeWin::slotTextBold()" << endl; +} + +void KMComposeWin::slotTextItalic() +{ + toggleMarkup(true); + mEditor->QTextEdit::setItalic( textItalicAction->isChecked() ); +} + +void KMComposeWin::slotTextUnder() +{ + toggleMarkup(true); + mEditor->QTextEdit::setUnderline( textUnderAction->isChecked() ); +} + +void KMComposeWin::slotTextColor() +{ + QColor color = mEditor->color(); + if ( KColorDialog::getColor( color ) ) { + toggleMarkup(true); + mEditor->setColor( color ); + } +} + +void KMComposeWin::fontChanged( const QFont &f ) +{ + kdDebug(5006) << "KMComposeWin::fontChanged()" << endl; + //if ( useHTMLEditor == true) { + //toggleMarkup(); don't toggle. + fontAction->setFont( f.family() ); + fontSizeAction->setFontSize( f.pointSize() ); +if(f.bold())kdDebug(5006) << "KMComposeWin::fontChanged, f.bold()==true" << endl; +if(!f.bold())kdDebug(5006) << "KMComposeWin::fontChanged, f.bold()==false" << endl; + textBoldAction->setChecked( f.bold() ); + textItalicAction->setChecked( f.italic() ); + textUnderAction->setChecked( f.underline() ); + //} +} + +void KMComposeWin::alignmentChanged( int a ) +{ + //toggleMarkup(); + 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())) @@ -5718,7 +6112,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()); } @@ -5805,6 +6199,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 ); @@ -5825,18 +6220,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; + } } @@ -6004,11 +6415,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; } @@ -6066,8 +6483,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 ); @@ -6085,20 +6510,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 :-( @@ -6122,8 +6553,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); + } + } //----------------------------------------------------------------------------- @@ -6148,7 +6599,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()); @@ -6178,8 +6632,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.230 diff -u -r1.230 kmcomposewin.h --- kmail/kmcomposewin.h 3 Feb 2004 23:11:25 -0000 1.230 +++ kmail/kmcomposewin.h 8 Feb 2004 11:06:22 -0000 @@ -31,6 +31,7 @@ #include "cryptplugwrapper.h" #include +#include class _StringPair { public: @@ -55,6 +56,9 @@ class KProcess; class KDirWatch; class KSelectAction; +class KFontAction; +class KFontSizeAction; +class KSelectAction; class KSpell; class KSpellConfig; class KDictSpellingHighlighter; @@ -64,6 +68,7 @@ class KTempFile; class KToolBar; class KToggleAction; +class KSelectColorAction; class KURL; class IdentityCombo; class SpellingFilter; @@ -98,6 +103,11 @@ QString brokenText(); /** + * Toggle automatic spellchecking + */ + int AutoSpellChecking( bool ); + + /** * For the external editor */ void setUseExternalEditor( bool use ) { mUseExtEditor = use; } @@ -112,15 +122,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 +158,6 @@ private: void killExternalEditor(); - void initializeAutoSpellChecking( KSpellConfig* autoSpellConfig ); private: KSpell *mKSpell; @@ -511,6 +523,9 @@ void slotCleanSpace(); + void slotToggleMarkup(); + void toggleMarkup(bool markup); + // void slotSpellConfigure(); void slotSpellcheckDone(int result); @@ -548,6 +563,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 @@ -692,10 +721,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, @@ -790,6 +819,7 @@ KMFolder *mFolder; long mShowHeaders; QString mExtEditor; + bool useHTMLEditor; bool mUseExtEditor; QPtrList<_StringPair> mCustHeaders; bool mConfirmSend; @@ -821,6 +851,16 @@ 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; + KAction *mHtmlToolbar; + KSelectAction *mEncodingAction; KSelectAction *mCryptoModuleAction; @@ -838,7 +878,14 @@ void slotCompletionModeChanged( KGlobalSettings::Completion ); void slotConfigChanged(); + /** + * toggle automatic spellchecking + */ + void slotAutoSpellCheckingToggled(bool); + + private: +DwString myGlobalBoundary; 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 8 Feb 2004 11:06:32 -0000 @@ -196,7 +196,7 @@ KMMessage* createDeliveryReceipt() const; /** Create a new message that is a MDN for this message, filling all - required felds with proper values. Th ereturned message is not + required fields with proper values. The returned message is not stored in any folder. @param a Use AutomaticAction for filtering and ManualAction for @@ -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=_gvhJAkFMIb2d2Ef Content-Type: text/x-diff; charset="us-ascii"; name="ksyntaxhighlighter.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="ksyntaxhighlighter.diff" Index: kdeui/ksyntaxhighlighter.cpp =================================================================== RCS file: /home/kdecvs/kde/kdelibs/kdeui/ksyntaxhighlighter.cpp,v retrieving revision 1.20 diff -u -p -u -r1.20 ksyntaxhighlighter.cpp --- kdeui/ksyntaxhighlighter.cpp 10 Dec 2003 06:00:22 -0000 1.20 +++ kdeui/ksyntaxhighlighter.cpp 8 Feb 2004 11:04:32 -0000 @@ -131,6 +131,7 @@ KSyntaxHighlighter::KSyntaxHighlighter( d->col5 = depth0; d->mode = mode; + mTextEdit = textEdit; // to be able to check if RichText is being used } KSyntaxHighlighter::~KSyntaxHighlighter() @@ -140,6 +141,7 @@ KSyntaxHighlighter::~KSyntaxHighlighter( int KSyntaxHighlighter::highlightParagraph( const QString &text, int ) { + if (mTextEdit->textFormat() == RichText) return 0; if (!d->enabled) { setFormat( 0, text.length(), textEdit()->viewport()->paletteForegroundColor() ); return 0; Index: kdeui/ksyntaxhighlighter.h =================================================================== RCS file: /home/kdecvs/kde/kdelibs/kdeui/ksyntaxhighlighter.h,v retrieving revision 1.11 diff -u -p -u -r1.11 ksyntaxhighlighter.h --- kdeui/ksyntaxhighlighter.h 10 Dec 2003 06:00:22 -0000 1.11 +++ kdeui/ksyntaxhighlighter.h 8 Feb 2004 11:04:32 -0000 @@ -55,6 +55,7 @@ public: private: class KSyntaxHighlighterPrivate; KSyntaxHighlighterPrivate *d; + QTextEdit *mTextEdit; }; class KSpellingHighlighter : public KSyntaxHighlighter --Boundary-00=_gvhJAkFMIb2d2Ef 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=_gvhJAkFMIb2d2Ef--