* Permit collapse/expand quoted mail (default disabled).

* Automatic collapse level of quoted mail with default to 3.

GUI:

svn path=/trunk/kdepim/; revision=407347
wilder-work
Mario Teijeiro Otero 21 years ago
parent 52ae3c1e7e
commit 01be904470
  1. 38
      configuredialog.cpp
  2. 2
      configuredialog_p.h
  3. 5
      csshelper.cpp
  4. 13
      kmail.kcfg
  5. 17
      kmreaderwin.cpp
  6. 3
      kmreaderwin.h
  7. 94
      objecttreeparser.cpp
  8. 3
      objecttreeparser.h
  9. 3
      pics/Makefile.am
  10. BIN
      pics/quotecollapse.png
  11. BIN
      pics/quoteexpand.png
  12. 32
      urlhandlermanager.cpp

@ -2175,6 +2175,10 @@ static const BoolConfigEntry showSpamStatusMode = {
static const BoolConfigEntry showEmoticons = {
"Reader", "ShowEmoticons", I18N_NOOP("Replace smileys by emoticons"), true
};
static const BoolConfigEntry showExpandQuotesMark= {
"Reader", "ShowExpandQuotesMark", I18N_NOOP("Show expand/collapse quote marks"), false
};
QString AppearancePage::ReaderTab::helpAnchor() const {
return QString::fromLatin1("configure-appearance-reader");
@ -2204,8 +2208,32 @@ AppearancePageReaderTab::AppearancePageReaderTab( QWidget * parent,
connect( mShowEmoticonsCheck, SIGNAL ( stateChanged( int ) ),
this, SLOT( slotEmitChanged() ) );
// "Show expand/collaps quote marks" check box;
QHBoxLayout *hlay= new QHBoxLayout( vlay ); // inherits spacing
populateCheckBox( mShowExpandQuotesMark= new QCheckBox( this ), showExpandQuotesMark);
hlay->addWidget( mShowExpandQuotesMark);
connect( mShowExpandQuotesMark, SIGNAL ( stateChanged( int ) ),
this, SLOT( slotEmitChanged() ) );
hlay->addStretch( 1 );
mCollapseQuoteLevelSpin = new KIntSpinBox( 0/*min*/,10/*max*/,1/*step*/,
3/*init*/,10/*base*/,this );
QLabel *label = new QLabel( mCollapseQuoteLevelSpin,
GlobalSettings::self()->collapseQuoteLevelSpinItem()->label(), this );
hlay->addWidget( label );
mCollapseQuoteLevelSpin->setEnabled( false ); //since !mShowExpandQuotesMark->isCheckec()
connect( mCollapseQuoteLevelSpin, SIGNAL( valueChanged( int ) ),
this, SLOT( slotEmitChanged( void ) ) );
hlay->addWidget( mCollapseQuoteLevelSpin);
connect( mShowExpandQuotesMark, SIGNAL( toggled( bool ) ),
mCollapseQuoteLevelSpin, SLOT( setEnabled( bool ) ) );
// Fallback Character Encoding
QHBoxLayout *hlay = new QHBoxLayout( vlay ); // inherits spacing
hlay = new QHBoxLayout( vlay ); // inherits spacing
mCharsetCombo = new QComboBox( this );
const QStringList &encodings = KMMsgBase::supportedEncodings( false );
mCharsetCombo->insertStringList( encodings );
@ -2230,7 +2258,7 @@ AppearancePageReaderTab::AppearancePageReaderTab( QWidget * parent,
i18n( GlobalSettings::self()->fallbackCharacterEncodingItem()->whatsThis().utf8() );
QWhatsThis::add( mCharsetCombo, fallbackCharsetWhatsThis );
QLabel *label = new QLabel( i18n("Fallback ch&aracter encoding:"), this );
label = new QLabel( i18n("Fallback ch&aracter encoding:"), this );
label->setBuddy( mCharsetCombo );
hlay->addWidget( label );
@ -2283,6 +2311,8 @@ void AppearancePage::ReaderTab::readCurrentOverrideCodec()
void AppearancePage::ReaderTab::doLoadFromGlobalSettings()
{
mShowEmoticonsCheck->setChecked( GlobalSettings::showEmoticons() );
mShowExpandQuotesMark->setChecked( GlobalSettings::showExpandQuotesMark() );
mCollapseQuoteLevelSpin->setValue( GlobalSettings::collapseQuoteLevelSpin() );
readCurrentOverrideCodec();
}
@ -2299,6 +2329,9 @@ void AppearancePage::ReaderTab::save() {
saveCheckBox( mShowColorbarCheck, reader, showColorbarMode );
saveCheckBox( mShowSpamStatusCheck, reader, showSpamStatusMode );
GlobalSettings::setShowEmoticons( mShowEmoticonsCheck->isChecked() );
GlobalSettings::setShowExpandQuotesMark( mShowExpandQuotesMark->isChecked() );
GlobalSettings::setCollapseQuoteLevelSpin( mCollapseQuoteLevelSpin->value() );
GlobalSettings::setFallbackCharacterEncoding(
KGlobal::charsets()->encodingForName( mCharsetCombo->currentText() ) );
GlobalSettings::setOverrideCharacterEncoding(
@ -2311,6 +2344,7 @@ void AppearancePage::ReaderTab::installProfile( KConfig * /* profile */ ) {
loadProfile( mShowColorbarCheck, reader, showColorbarMode );
loadProfile( mShowSpamStatusCheck, reader, showSpamStatusMode );
loadProfile( mShowEmoticonsCheck, reader, showEmoticons );
loadProfile( mShowExpandQuotesMark, reader, showExpandQuotesMark);
}

@ -519,6 +519,8 @@ private: // data
QCheckBox *mShowColorbarCheck;
QCheckBox *mShowSpamStatusCheck;
QCheckBox *mShowEmoticonsCheck;
QCheckBox *mShowExpandQuotesMark;
KIntSpinBox *mCollapseQuoteLevelSpin;
QComboBox *mCharsetCombo;
QComboBox *mOverrideCharsetCombo;
};

@ -718,6 +718,11 @@ namespace KMail {
"img.pimsmileyimg {\n"
"}\n\n"
"div.quotelevelmark {\n"
" position: absolute;\n"
" margin-left:-10px;\n"
"}\n\n"
;
}

@ -388,6 +388,19 @@
<label>Replace smileys by emoticons</label>
<whatsthis>Enable this if you want smileys like :-) appearing in the message text to be replaced by emoticons (small pictures).</whatsthis>
</entry>
<entry name="ShowExpandQuotesMark" type="Bool">
<default>false</default>
<label>Show expand/collapse quote marks</label>
<whatsthis>Enable this option to show different levels of quoted text. Disable to hide the levels of quoted text.</whatsthis>
</entry>
<entry name="CollapseQuoteLevelSpin" type="Int" >
<label>Automatic collapse level:</label>
<default>3</default>
<min>0</min>
<max>10</max>
</entry>
</group>
</kcfg>

@ -529,12 +529,15 @@ KMReaderWin::KMReaderWin(QWidget *aParent,
mHtmlOverride = false;
mHtmlLoadExtOverride = false;
mLevelQuote=GlobalSettings::self()->collapseQuoteLevelSpin()-1;
connect( &updateReaderWinTimer, SIGNAL(timeout()),
this, SLOT(updateReaderWin()) );
connect( &mResizeTimer, SIGNAL(timeout()),
this, SLOT(slotDelayedResize()) );
connect( &mDelayedMarkTimer, SIGNAL(timeout()),
this, SLOT(slotTouchMessage()) );
}
void KMReaderWin::createActions( KActionCollection * ac ) {
@ -725,6 +728,13 @@ void KMReaderWin::slotAllHeaders() {
HeaderStrategy::all() );
}
void KMReaderWin::slotLevelQuote( int l )
{
kdDebug( 5006 ) << "Old Level: " << mLevelQuote << " New Level: " << l << endl;
mLevelQuote = l;
update(true);
}
void KMReaderWin::slotCycleHeaderStyles() {
const HeaderStrategy * strategy = headerStrategy();
const HeaderStyle * style = headerStyle();
@ -1061,6 +1071,13 @@ void KMReaderWin::setMsg(KMMessage* aMsg, bool force)
kdDebug(5006) << "(" << aMsg->getMsgSerNum() << ", last " << mLastSerNum << ") " << aMsg->subject() << " "
<< aMsg->fromStrip() << ", readyToShow " << (aMsg->readyToShow()) << endl;
//Reset the level quote if the msg has changed.
if (aMsg && aMsg->getMsgSerNum() != mLastSerNum ){
mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin()-1;
}
if ( mPrinting )
mLevelQuote = -1;
bool complete = true;
if ( aMsg &&
!aMsg->readyToShow() &&

@ -336,6 +336,8 @@ public slots:
void slotIMChat();
void contactStatusChanged( const QString &uid);
void slotLevelQuote( int l );
protected slots:
void slotCycleHeaderStyles();
void slotBriefHeaders();
@ -466,6 +468,7 @@ private:
int mChoice;
unsigned long mWaitingForSerNum;
float mSavedRelativePosition;
int mLevelQuote;
};

@ -76,11 +76,17 @@
#include <kstandarddirs.h>
#include <kapplication.h>
#include <kmessagebox.h>
#include <kiconloader.h>
#include <kmdcodec.h>
// other Qt headers
#include <qtextcodec.h>
#include <qfile.h>
#include <qapplication.h>
#include <kstyle.h>
#include <qbuffer.h>
#include <qpixmap.h>
#include <qpainter.h>
// other headers
#include <sys/stat.h>
@ -2402,6 +2408,21 @@ void ObjectTreeParser::writeBodyStr( const QCString& aStr, const QTextCodec *aCo
else
htmlWriter()->queue( quotedHTML( aCodec->toUnicode( aStr ), decorate ) );
}
static QString pngToDataUrl( const QString & iconPath )
{
if ( iconPath.isEmpty() )
return QString::null;
QFile pngFile( iconPath );
if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
return QString::null;
QByteArray ba = pngFile.readAll();
pngFile.close();
return QString::fromLatin1("data:image/png;base64,%1")
.arg( KCodecs::base64Encode( ba ) );
}
QString ObjectTreeParser::quotedHTML( const QString& s, bool decorate )
{
@ -2429,6 +2450,7 @@ QString ObjectTreeParser::quotedHTML( const QString& s, bool decorate )
beg = pos;
int currQuoteLevel = -2; // -2 == no previous lines
bool curHidden = false; // no hide any block
while (beg<length)
{
@ -2460,34 +2482,80 @@ QString ObjectTreeParser::quotedHTML( const QString& s, bool decorate )
}
} /* for() */
bool actHidden = false;
QString textExpand;
// LevelQuote:
// 0 don't hide anything
// >0 hide the level 1, 2,3,... and so on
if ( mReader->mLevelQuote >= 0 && mReader->mLevelQuote <= ( actQuoteLevel ) )
actHidden = true;
if ( actQuoteLevel != currQuoteLevel ) {
/* finish last quotelevel */
if (currQuoteLevel == -1)
htmlStr.append( normalEndTag );
else if (currQuoteLevel >= 0)
else if ( currQuoteLevel >= 0 && !curHidden )
htmlStr.append( quoteEnd );
/* start new quotelevel */
currQuoteLevel = actQuoteLevel;
if (actQuoteLevel == -1)
htmlStr += normalStartTag;
else
htmlStr += quoteFontTag[currQuoteLevel%3];
{
if ( GlobalSettings::showExpandQuotesMark() )
{
// Cache Icons
if ( mCollapseIcon.isEmpty() )
mCollapseIcon= pngToDataUrl(
KGlobal::instance()->iconLoader()->iconPath( "quotecollapse",0 ));
if ( mExpandIcon.isEmpty() )
mExpandIcon= pngToDataUrl(
KGlobal::instance()->iconLoader()->iconPath( "quoteexpand",0 ));
if ( !actHidden )
{
htmlStr += "<div class=\"quotelevelmark\" >" ;
htmlStr += QString( "<a href=\"kmail:levelquote?%1 \">"
"<img src=\"%2\" alt=\"\" title=\"\"/></a>" )
.arg(actQuoteLevel)
.arg( mCollapseIcon);
htmlStr += "</div>";
htmlStr += quoteFontTag[actQuoteLevel%3];
}
else
//only show the QuoteMark when is the first level hidden
if ( mReader->mLevelQuote == actQuoteLevel && currQuoteLevel < actQuoteLevel )
{
//Expand all quotes
htmlStr += "<div class=\"quotelevelmark\" >" ;
htmlStr += QString( "<a href=\"kmail:levelquote?%1 \">"
"<img src=\"%2\" alt=\"\" title=\"\"/></a>" )
.arg(-1)
.arg( mExpandIcon );
htmlStr += "</div><br/>";
htmlStr += quoteEnd;
}
} else
htmlStr += quoteFontTag[actQuoteLevel%3];
}
currQuoteLevel = actQuoteLevel;
}
curHidden = actHidden;
// don't write empty <div ...></div> blocks (they have zero height)
// ignore ^M DOS linebreaks
if( !line.replace('\015', "").isEmpty() )
if ( !actHidden )
{
if( line.isRightToLeft() )
htmlStr += QString( "<div dir=\"rtl\">" );
// don't write empty <div ...></div> blocks (they have zero height)
// ignore ^M DOS linebreaks
if( !line.replace('\015', "").isEmpty() )
{
htmlStr +=QString( "<div dir=\"%1\">" ).arg( line.isRightToLeft() ? "rtl":"ltr" );
htmlStr += LinkLocator::convertToHtml( line, convertFlags );
htmlStr += QString( "</div>" );
}
else
htmlStr += QString( "<div dir=\"ltr\">" );
htmlStr += LinkLocator::convertToHtml( line, convertFlags );
htmlStr += QString( "</div>" );
htmlStr += "<br>";
}
else
htmlStr += "<br>";
} /* while() */
/* really finish the last quotelevel */

@ -278,6 +278,9 @@ namespace KMail {
const KMail::AttachmentStrategy * mAttachmentStrategy;
KMail::HtmlWriter * mHtmlWriter;
KMail::CSSHelper * mCSSHelper;
// DataUrl Icons cache
QString mCollapseIcon;
QString mExpandIcon;
};
} // namespace KMail

@ -12,7 +12,8 @@ pics_DATA = kmmsgdel.png kmmsgnew.png kmmsgunseen.png kmmsgread.png \
kmmsgspam.png kmmsgham.png kmmsgattachment.png \
kmgroupware_folder_contacts.png \
kmgroupware_folder_calendar.png kmgroupware_folder_notes.png \
kmgroupware_folder_tasks.png kmgroupware_folder_journals.png
kmgroupware_folder_tasks.png kmgroupware_folder_journals.png \
quotecollapse.png quoteexpand.png
picsdir = $(kde_datadir)/kmail/pics

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -340,6 +340,18 @@ namespace {
w->update( true );
return true;
}
//Format url:
// kmail:levelquote/?inc -> inc the level quote shown.
// kmail:levelquote/?dec -> dec the level quote shown.
if ( url.path() == "levelquote" ){
QString levelStr= url.query().mid( 1,url.query().length() );
bool isNumber;
int levelQuote= levelStr.toInt(&isNumber);
if ( isNumber )
w->slotLevelQuote( levelQuote );
return true;
}
// if ( url.path() == "startIMApp" )
// {
// kmkernel->imProxy()->startPreferredApp();
@ -351,10 +363,22 @@ namespace {
}
QString ShowHtmlSwitchURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
if ( url.url() == "kmail:showHTML" )
return i18n("Turn on HTML rendering for this message.");
if ( url.url() == "kmail:loadExternal" )
return i18n("Load external references from the Internet for this message.");
if ( url.protocol() == "kmail" )
{
if ( url.path() == "showHTML" )
return i18n("Turn on HTML rendering for this message.");
if ( url.path() == "loadExternal" )
return i18n("Load external references from the Internet for this message.");
if ( url.path() == "levelquote" )
{
QString query= url.query();
if ( query.length()>=2 )
if ( query[ 1 ] =='-' )
return i18n("Expand all quoted text.");
else
return i18n("Collapse quoted text.");
}
}
return QString::null ;
}
}

Loading…
Cancel
Save