[prev in list] [next in list] [prev in thread] [next in thread]
List: kmail-devel
Subject: [PATCH] composing html messages
From: Edwin Schepers <yez () home ! nl>
Date: 2004-01-26 19:33:47
Message-ID: 200401262033.47326.yez () home ! nl
[Download RAW message or body]
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. <p></p> 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
<html><head><meta name="qrichtext" content="1" /></head><body
style="font-size:12pt;font-family:helvetica">
<p><span style="font-weight:600">test</span></p>
</body></html>
kmail: |||
kmail:
kmail:
KMComposeWin::composeMessage():
99.:
|||From: JES <yez@home.nl>
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
<html><head><meta name="qrichtext" content="1" /></head><body
style="font-size:12pt;font-family:helvetica">
<p><span style="font-weight:600">test</span></p>
</body></html>
----
kmail: |||
["htmlmail.diff" (text/x-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 @@
<Action name="encrypt_message" />
<Separator/>
<Action name="options_select_crypto" />
+ <Menu name="editor"><text>&Editor</text>
+ <Action name="plaintext"/>
+ <Action name="html"/>
+ </Menu>
<Action name="charsets" />
<Action name="wordwrap" />
<Action name="options_auto_spellchecking" />
@@ -74,6 +78,7 @@
<Action name="setup_spellchecker" append="save_merge"/>
</Menu>
</MenuBar>
+
<ToolBar noMerge="1" name="mainToolBar" fullWidth="true" ><text>Main Toolbar</text>
<Action name="send_default" />
<Action name="send_alternative" />
@@ -88,4 +93,18 @@
<Action name="encrypt_message" />
<Action name="options_select_crypto" />
</ToolBar>
+ <ToolBar noMerge="1" name="htmlToolBar" ><text>Html Toolbar</text>
+ <Action name="text_list" />
+ <Action name="text_font" />
+ <Action name="text_size" />
+ <Action name="text_bold" />
+ <Action name="text_italic" />
+ <Action name="text_under" />
+ <Action name="format_color" />
+ <Action name="align_left" />
+ <Action name="align_right" />
+ <Action name="align_center" />
+ <Action name="align_justify" />
+ </ToolBar>
+
</kpartgui>
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 <kspelldlg.h>
#include <spellingfilter.h>
#include <ksyntaxhighlighter.h>
+#include <kcoloractions.h>
+#include <kcolordialog.h>
#include <qtabdialog.h>
#include <qregexp.h>
@@ -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; i<num; i++)
{
msgPart = new KMMessagePart;
@@ -1397,9 +1499,9 @@
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));
}
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"<<endl:kdDebug(5006) <<"doSign=false"<<endl;
+ doEncrypt?kdDebug(5006) <<"doEncrypt=true"<<endl:kdDebug(5006) \
<<"doEncrypt=false"<<endl; +#endif
+
Kpgp::Result result = Kpgp::Ok;
// create informative header for those that have no mime-capable
// email client
@@ -1976,14 +2088,69 @@
}
KMMessagePart oldBodyPart;
- oldBodyPart.setTypeStr( earlyAddAttachments ? "multipart" : "text" );
- oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed" : "plain");
+ if ( useHTMLEditor ) {
+ oldBodyPart.setTypeStr( "multipart");
+ oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed" : "alternative");
+ }
+ else {
+ oldBodyPart.setTypeStr( earlyAddAttachments ? "multipart" : "text" );
+ oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed" : "plain");
+ }
oldBodyPart.setContentDisposition( "inline" );
- QCString boundaryCStr;
-
bool isQP = kmkernel->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<int> 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 << "\""<<endl;
+ body = newbody;
+ }
+
+ QCString boundaryCStr;
+
if( earlyAddAttachments ) {
// calculate a boundary string
++previousBoundaryLevel;
@@ -1992,15 +2159,21 @@
boundaryCStr = tmpCT.Boundary().c_str();
// add the normal body text
KMMessagePart innerBodyPart;
- innerBodyPart.setTypeStr( "text" );
- innerBodyPart.setSubtypeStr("plain");
+ if ( useHTMLEditor ) {
+ innerBodyPart.setTypeStr( "text" );
+ innerBodyPart.setSubtypeStr("html");
+ }
+ else {
+ innerBodyPart.setTypeStr( "text" );
+ innerBodyPart.setSubtypeStr("plain");
+ }
innerBodyPart.setContentDisposition( "inline" );
QValueList<int> 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() << \
"\""<<endl; + kdDebug(5006) << "###AFTER ENCRYPTION : \"" << theMessage.asString() \
<< "\""<<endl; }
return result;
}
@@ -2311,6 +2485,10 @@
KMMessagePart newBodyPart,
QCString& signCertFingerprint )
{
+#ifdef DEBUG
+ kdDebug(5006) << "entering KMComposeWin::encryptMessage" << endl;
+#endif
+
Kpgp::Result result = Kpgp::Ok;
if(!msg)
{
@@ -2442,7 +2620,7 @@
&& ( !earlyAddAttachments || !allAttachmentsAreInBody ) ) {
// set the content type header
msg->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("<qt>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) : "<<oldWord<<endl; if( mSpellLineEdit )
mComposer->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 );
_______________________________________________
KMail developers mailing list
KMail-devel@kde.org
https://mail.kde.org/mailman/listinfo/kmail-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic