WABA: New feature! Smart quoting!

KMail is ready for the newbies of the next millenium and
even Emily Post will be happy with this great innovation.

svn path=/trunk/kdenetwork/kmail/; revision=37159
wilder-work
Waldo Bastian 27 years ago
parent fcaeb7e23e
commit fbe9cb18ea
  1. 12
      kmcomposewin.cpp
  2. 250
      kmmessage.cpp
  3. 19
      kmsender.cpp
  4. 3
      kmsender.h
  5. 23
      kmsettings.cpp
  6. 2
      kmsettings.h

@ -208,7 +208,11 @@ void KMComposeWin::readConfig(void)
mDefEncoding = config->readEntry("encoding", "base64");
mShowHeaders = config->readNumEntry("headers", HDR_STANDARD);
mWordWrap = config->readNumEntry("word-wrap", 1);
mLineBreak = config->readNumEntry("break-at", 80);
mLineBreak = config->readNumEntry("break-at", 78);
if ((mLineBreak == 0) || (mLineBreak > 78))
mLineBreak = 78;
if (mLineBreak < 60)
mLineBreak = 60;
mAutoPgpSign = config->readNumEntry("pgp-auto-sign", 0);
config->setGroup("Reader");
@ -696,15 +700,11 @@ void KMComposeWin::setupEditor(void)
mEditor->setModified(FALSE);
//mEditor->setFocusPolicy(QWidget::ClickFocus);
if (mWordWrap && (mLineBreak > 0))
if (mWordWrap)
{
mEditor->setWordWrap( QMultiLineEdit::FixedColumnWidth );
mEditor->setWrapColumnOrWidth(mLineBreak);
}
else if (mWordWrap)
{
mEditor->setWordWrap( QMultiLineEdit::WidgetWidth );
}
else
{
mEditor->setWordWrap( QMultiLineEdit::NoWrap );

@ -46,7 +46,8 @@ static QCString result;
// Values that are set from the config file with KMMessage::readConfig()
static QString sReplyStr, sForwardStr, sReplyAllStr, sIndentPrefixStr;
static bool sSmartQuote;
static int sWrapCol;
/* Start functions added for KRN */
@ -263,7 +264,6 @@ const QString KMMessage::formatString(const QString aStr) const
QString result, str;
const char* pos;
char ch, cstr[64];
QDateTime datetime;
time_t tm;
int i;
@ -282,6 +282,7 @@ const QString KMMessage::formatString(const QString aStr) const
to have a long form of the date used? I don't
like this change to a short XX/XX/YY date format.
At least not for the default. -sanders
QDateTime datetime;
datetime.setTime_t(date());
result += KGlobal::locale()->formatDate(datetime.date());
*/
@ -322,6 +323,227 @@ const QString KMMessage::formatString(const QString aStr) const
return result;
}
static void removeTrailingSpace( QString &line )
{
int i = line.length()-1;
while( (i >= 0) && ((line[i] == ' ') || (line[i] == '\t')))
i--;
line.truncate( i+1);
}
static QString splitLine( QString &line)
{
removeTrailingSpace( line );
int i = 0;
int j = -1;
int l = line.length();
// TODO: Replace tabs with spaces first.
while(i < l)
{
QChar c = line[i];
if ((c == '>') || (c == ':') || (c == '|'))
j = i+1;
else if ((c != ' ') && (c != '\t'))
break;
i++;
}
if ( i == 0 )
{
return "";
}
if ( i == l )
{
QString result = line;
line = QString::null;
return result;
}
QString result = line.left(j);
line = line.mid(j);
return result;
}
static QString flowText(QString &text, const QString &indent, int maxLength)
{
// printf("flowText: \"%s\"\n", text.ascii());
maxLength--;
if (text.isEmpty())
{
return indent+"<NULL>\n";
}
QString result;
while (1)
{
int i;
if ((int) text.length() > maxLength)
{
i = maxLength;
while( (i >= 0) && (text[i] != ' '))
i--;
if (i <= 0)
{
// Couldn't break before maxLength.
i = maxLength;
// while( (i < (int) text.length()) && (text[i] != ' '))
// i++;
}
}
else
{
i = text.length();
}
QString line = text.left(i);
if (i < (int) text.length())
text = text.mid(i);
else
text = QString::null;
result += indent + line + '\n';
if (text.isEmpty())
return result;
}
}
static bool flushPart(QString &msg, QStringList &part,
const QString &indent, int maxLength)
{
maxLength -= indent.length();
if (maxLength < 20) maxLength = 20;
// Remove empty lines at end of quote
while ((part.begin() != part.end()) && part.last().isEmpty())
{
part.remove(part.fromLast());
}
//printf("Start of part.\n");
QString text;
for(QStringList::Iterator it2 = part.begin();
it2 != part.end();
it2++)
{
QString line = (*it2);
if (line.isEmpty())
{
if (!text.isEmpty())
msg += flowText(text, indent, maxLength);
msg += indent + "\n";
}
else
{
if (text.isEmpty())
text = line;
else
text += " "+line.stripWhiteSpace();
if (((int) text.length() < maxLength) || ((int) line.length() < (maxLength-10)))
msg += flowText(text, indent, maxLength);
}
}
if (!text.isEmpty())
msg += flowText(text, indent, maxLength);
//printf("End of of part.\n");
bool appendEmptyLine = true;
if (!part.count())
appendEmptyLine = false;
part.clear();
return appendEmptyLine;
}
static void smartQuote( QString &msg, const QString &ownIndent, int maxLength )
{
QStringList part;
QString startOfSig1;
QString startOfSig2 = ownIndent+"--";
QString oldIndent;
int i = 0;
int l = 0;
while( startOfSig2.left(1) == "\n")
startOfSig2 = startOfSig2.mid(1);
startOfSig1 = startOfSig2 + ' ';
QStringList lines;
while ((i = msg.find('\n', l)) != -1)
{
if (i == l)
lines.append( QString::null);
else
lines.append( msg.mid(l, i-l));
l = i+1;
}
if (l <= (int) msg.length());
lines.append( msg.mid(l));
msg = QString::null;
for(QStringList::Iterator it = lines.begin();
it != lines.end();
it++)
{
QString line = *it;
if (line == startOfSig1) break; // Start of signature
if (line == startOfSig2) break; // Start of malformed signature
QString indent = splitLine( line );
// printf("Quoted Line = \"%s\" \"%s\"\n", line.ascii(), indent.ascii());
if ( line.isEmpty())
{
if (!oldIndent.isEmpty())
part.append(QString::null);
continue;
};
if (oldIndent.isNull())
{
oldIndent = indent;
}
if (oldIndent != indent)
{
QString fromLine;
// Search if the last non-blank line could be "From" line
if (part.count() && (oldIndent.length() < indent.length()))
{
QStringList::Iterator it2 = part.fromLast();
while( (it2 != part.end()) && (*it2).isEmpty())
it2--;
if ((it2 != part.end()) && ((*it2).right(1) == ":"))
{
fromLine = oldIndent + (*it2) + "\n";
part.remove(it2);
}
}
if (flushPart( msg, part, oldIndent, maxLength))
{
if (oldIndent.length() > indent.length())
msg += indent + "\n";
else
msg += oldIndent + "\n";
}
if (!fromLine.isEmpty())
{
msg += fromLine;
//printf("From = %s", fromLine.ascii());
}
oldIndent = indent;
}
part.append(line);
}
flushPart( msg, part, oldIndent, maxLength);
}
//-----------------------------------------------------------------------------
const QString KMMessage::asQuotedString(const QString aHeaderStr,
@ -354,8 +576,10 @@ const QString KMMessage::asQuotedString(const QString aHeaderStr,
} else {
result = result.stripWhiteSpace();
}
result.replace(reNL,nlIndentStr) + '\n';
result.replace(reNL,nlIndentStr);
result = formatString(aIndentStr) + result + '\n';
if (sSmartQuote)
smartQuote(result, nlIndentStr, sWrapCol);
}
else
{
@ -381,15 +605,17 @@ const QString KMMessage::asQuotedString(const QString aHeaderStr,
(pgp->decrypt()))
{
part = QString(pgp->message());
part = part.replace(reNL,nlIndentStr);
}
else
{
part = QString(msgPart.bodyDecoded());
// debug ("part\n" + part ); inexplicably crashes -sanders
part = part.replace(reNL,nlIndentStr);
}
result += part + '\n';
part.replace(reNL,nlIndentStr);
part = formatString(aIndentStr) + part + '\n';
if (sSmartQuote)
smartQuote(part, nlIndentStr, sWrapCol);
result += part;
}
else isInline = FALSE;
}
@ -408,7 +634,7 @@ const QString KMMessage::asQuotedString(const QString aHeaderStr,
}
}
return headerStr + nlIndentStr + result;
return headerStr + "\n" + result;
}
@ -1449,6 +1675,14 @@ void KMMessage::readConfig(void)
sReplyAllStr = config->readEntry("phrase-reply-all",i18n("On %D, %F wrote:"));
sForwardStr = config->readEntry("phrase-forward",i18n("Forwarded Message"));
sIndentPrefixStr = config->readEntry("indent-prefix",">%_");
config->setGroup("Composer");
sSmartQuote = config->readBoolEntry("smart-quote", true);
sWrapCol = config->readNumEntry("break-at", 78);
if ((sWrapCol == 0) || (sWrapCol > 78))
sWrapCol = 78;
if (sWrapCol < 60)
sWrapCol = 60;
}
#if defined CHARSETS

@ -50,7 +50,7 @@ extern KMIdentity *identity;
//-----------------------------------------------------------------------------
KMSender::KMSender()
{
initMetaObject();
// initMetaObject();
mSendDlg = NULL;
mSendProc = NULL;
mSendProcStarted = FALSE;
@ -62,8 +62,6 @@ KMSender::KMSender()
//label->setAutoResize(true);
label->setCaption("KMail");
label->setIcon(kapp->miniIcon());
connect (this, SIGNAL(statusMsg(const QString&)),
label, SLOT(setText(const QString&)));
}
@ -75,6 +73,13 @@ KMSender::~KMSender()
if (label) delete label;
}
//-----------------------------------------------------------------------------
void
KMSender::setStatusMsg(const QString &msg)
{
label->setText( msg );
emit statusMsg( msg);
}
//-----------------------------------------------------------------------------
void KMSender::readConfig(void)
@ -254,7 +259,7 @@ void KMSender::doSendMsg()
label->resize(400, label->sizeHint().height());
label->show();
//kapp->processEvents();
emit statusMsg(i18n("Initiating sender process..."));
setStatusMsg(i18n("Initiating sender process..."));
if (!mSendProc->start())
{
cleanup();
@ -270,7 +275,7 @@ void KMSender::doSendMsg()
// start sending the current message
mSendProc->preSendInit();
emit statusMsg(i18n("Sending message: ")+mCurrentMsg->subject());
setStatusMsg(i18n("Sending message: ")+mCurrentMsg->subject());
if (!mSendProc->send(mCurrentMsg))
{
cleanup();
@ -298,7 +303,7 @@ void KMSender::cleanup(void)
else outboxFolder->compact();
emit statusMsg(i18n("Done sending messages."));
setStatusMsg(i18n("Done sending messages."));
serverReady(true); // sven - enable ipc
label->hide();
if (quitOnDone)
@ -460,7 +465,7 @@ const QString KMSendProc::prepareStr(const QString aStr, bool toCRLF)
//-----------------------------------------------------------------------------
void KMSendProc::statusMsg(const QString& aMsg)
{
if (mSender) emit mSender->statusMsg(aMsg);
if (mSender) mSender->setStatusMsg(aMsg);
app->processEvents(500);
}

@ -86,6 +86,9 @@ public:
* Tells sender to quit application when finished.
*/
void quitWhenFinished();
/** sets a status msg and emits statusMsg() */
void setStatusMsg(const QString&);
signals:
/** Emitted regularly to inform the user of what is going on */

@ -495,7 +495,7 @@ void KMSettings::createTabComposer(QWidget *parent)
//---------- group appearance
grp = new QGroupBox(i18n("Appearance"), tab);
box->addWidget(grp);
grid = new QGridLayout(grp, 8, 3, 20, 4);
grid = new QGridLayout(grp, 8, 5, 20, 4);
autoAppSignFile=new QCheckBox(
i18n("Automatically append signature"), grp);
@ -525,9 +525,17 @@ void KMSettings::createTabComposer(QWidget *parent)
monospFont->setMinimumSize(monospFont->sizeHint());
grid->addMultiCellWidget(monospFont, 3, 3, 0, 1);
smartQuote = new QCheckBox(i18n("Smart quoting"), grp);
smartQuote->adjustSize();
smartQuote->setMinimumSize(smartQuote->sizeHint());
grid->addWidget(smartQuote, 0, 3);
grid->setColStretch(0,1);
grid->setColStretch(1,1);
grid->setColStretch(2,10);
grid->setColStretch(2,1);
grid->addColSpacing(2,20);
grid->setColStretch(3,1);
grid->setColStretch(4,10);
grid->activate();
//---------- group sending
@ -564,9 +572,17 @@ void KMSettings::createTabComposer(QWidget *parent)
config->setGroup("Composer");
autoAppSignFile->setChecked(stricmp(config->readEntry("signature"),"auto")==0);
wordWrap->setChecked(config->readBoolEntry("word-wrap",true));
wrapColumnEdit->setText(config->readEntry("break-at","80"));
wrapColumnEdit->setText(config->readEntry("break-at","78"));
#if 0
// Limit break between 60 and 78
if ((mLineBreak == 0) || (mLineBreak > 78))
mLineBreak = 78;
if (mLineBreak < 60)
mLineBreak = 60;
#endif
monospFont->setChecked(stricmp(config->readEntry("font","variable"),"fixed")==0);
pgpAutoSign->setChecked(config->readBoolEntry("pgp-auto-sign",false));
smartQuote->setChecked(config->readBoolEntry("smart-quote",true));
i = msgSender->sendImmediate();
sendNow->setChecked(i);
@ -918,6 +934,7 @@ void KMSettings::doApply()
config->writeEntry("phrase-reply-all", phraseReplyAllEdit->text());
config->writeEntry("phrase-forward", phraseForwardEdit->text());
config->writeEntry("indent-prefix", indentPrefixEdit->text());
config->writeEntry("smart-quote", smartQuote->isChecked());
//----- composer appearance
config->setGroup("Composer");

@ -70,7 +70,7 @@ private:
QLineEdit *smtpServerEdit,*smtpPortEdit,*sendmailLocationEdit;
QLineEdit *phraseReplyEdit, *phraseReplyAllEdit, *phraseForwardEdit;
QLineEdit *indentPrefixEdit, *wrapColumnEdit;
QCheckBox *autoAppSignFile, *wordWrap, *monospFont, *pgpAutoSign;
QCheckBox *autoAppSignFile, *wordWrap, *monospFont, *pgpAutoSign, *smartQuote;
QCheckBox *emptyTrashOnExit, *sendOnCheck, *longFolderList, *sendReceipts,
*compactOnExit;
QRadioButton *smtpRadio, *sendmailRadio, *sendNow, *sendLater;

Loading…
Cancel
Save