make member variables of the classes starting with m;

use timestamps in the log;
avoid logging of full messages e.g. for "body" or "message" filter rule;
line wrapping and logging can be switched on/off in the log viewer;
saving of the log into a file is supported now

svn path=/trunk/kdepim/; revision=290493
wilder-work
Andreas Gungl 22 years ago
parent 693afe4867
commit 7f0618b470
  1. 81
      filterlog.cpp
  2. 57
      filterlog.h
  3. 86
      filterlogdlg.cpp
  4. 10
      filterlogdlg.h
  5. 2
      kmfiltermgr.cpp
  6. 2
      kmmainwidget.cpp
  7. 16
      kmsearchpattern.cpp

@ -31,24 +31,29 @@
#include <kdebug.h>
#include <qdatetime.h>
#include <qfile.h>
#include <sys/stat.h>
using namespace KMail;
FilterLog * FilterLog::self = NULL;
FilterLog * FilterLog::mSelf = NULL;
FilterLog::FilterLog()
{
self = this;
mSelf = this;
// start with logging enabled by default
logging = true;
mLogging = true;
// better limit the log to 512 KByte to avoid out of memory situations
// when the log i sgoing to become very long
maxLogSize = 512 * 1024;
currentLogSize = 0;
allowedTypes = meta | patternDesc | ruleResult |
patternResult | appliedAction;
mMaxLogSize = 512 * 1024;
mCurrentLogSize = 0;
mAllowedTypes = meta | patternDesc | ruleResult |
patternResult | appliedAction;
};
@ -58,8 +63,8 @@ FilterLog::~FilterLog()
FilterLog * FilterLog::instance()
{
if ( !self ) self = new FilterLog();
return self;
if ( !mSelf ) mSelf = new FilterLog();
return mSelf;
}
@ -68,11 +73,16 @@ void FilterLog::add( QString logEntry, ContentType contentType )
#ifndef NDEBUG
kdDebug(5006) << "New filter log entry: " << logEntry << endl;
#endif
if ( isLogging() && ( allowedTypes & contentType ) )
if ( isLogging() && ( mAllowedTypes & contentType ) )
{
logEntries.append( logEntry );
emit logEntryAdded( logEntry );
currentLogSize += logEntry.length();
QString timedLog = "[" + QTime::currentTime().toString() + "] ";
if ( contentType & ~meta )
timedLog += logEntry;
else
timedLog = logEntry;
mLogEntries.append( timedLog );
emit logEntryAdded( timedLog );
mCurrentLogSize += timedLog.length();
checkLogSize();
}
}
@ -85,7 +95,7 @@ void FilterLog::setMaxLogSize( long size )
// do not allow less than 1 KByte except unlimited (-1)
if ( size >= 0 && size < 1024 )
size = 1024;
maxLogSize = size;
mMaxLogSize = size;
checkLogSize();
};
@ -94,8 +104,8 @@ void FilterLog::dump()
{
#ifndef NDEBUG
kdDebug(5006) << "----- starting filter log -----" << endl;
for ( QStringList::Iterator it = logEntries.begin();
it != logEntries.end(); ++it )
for ( QStringList::Iterator it = mLogEntries.begin();
it != mLogEntries.end(); ++it )
{
kdDebug(5006) << *it << endl;
}
@ -106,19 +116,20 @@ void FilterLog::dump()
void FilterLog::checkLogSize()
{
if ( currentLogSize > maxLogSize && maxLogSize > -1 )
if ( mCurrentLogSize > mMaxLogSize && mMaxLogSize > -1 )
{
kdDebug(5006) << "Filter log: memory limit reached, starting to discard old items, size = "
<< QString::number( currentLogSize ) << endl;
<< QString::number( mCurrentLogSize ) << endl;
// avoid some kind of hysteresis, shrink the log to 90% of its maximum
while ( currentLogSize > ( maxLogSize * 0.9 ) )
while ( mCurrentLogSize > ( mMaxLogSize * 0.9 ) )
{
QValueListIterator<QString> it = logEntries.begin();
if ( it != logEntries.end())
QValueListIterator<QString> it = mLogEntries.begin();
if ( it != mLogEntries.end())
{
currentLogSize -= (*it).length();
logEntries.remove( it );
kdDebug(5006) << "Filter log: new size = " << QString::number( currentLogSize ) << endl;
mCurrentLogSize -= (*it).length();
mLogEntries.remove( it );
kdDebug(5006) << "Filter log: new size = "
<< QString::number( mCurrentLogSize ) << endl;
}
else
{
@ -131,4 +142,26 @@ void FilterLog::checkLogSize()
}
bool FilterLog::saveToFile( QString fileName )
{
QFile file( fileName );
if( file.open( IO_WriteOnly ) ) {
fchmod( file.handle(), S_IRUSR | S_IWUSR );
{
QDataStream ds( &file );
for ( QStringList::Iterator it = mLogEntries.begin();
it != mLogEntries.end(); ++it )
{
QString tmpString = *it + '\n';
QCString cstr( tmpString.local8Bit() );
ds.writeRawBytes( cstr, cstr.size() );
}
}
return true;
}
else
return false;
}
#include "filterlog.moc"

@ -46,7 +46,8 @@ namespace KMail {
collected log information can get thrown away, the
next added log entry is the first one until another
clearing.
A signal is emitted whenever a new logentry is added.
A signal is emitted whenever a new logentry is added,
when the log was cleared or any log state was changed.
*/
class FilterLog : public QObject
{
@ -59,30 +60,59 @@ namespace KMail {
/** log data types */
enum ContentType { meta = 1, patternDesc, ruleResult, patternResult, appliedAction };
/** check the logging state */
bool isLogging() { return logging; };
bool isLogging() { return mLogging; };
/** set the logging state */
void setLogging( bool active ) { logging = active; };
void setLogging( bool active )
{
mLogging = active;
emit logStateChanged();
};
/** control the size of the log */
void setMaxLogSize( long size = -1 );
/** add a content type to the set of logged ones */
void enableContentType( ContentType contentType ) { allowedTypes |= contentType; };
void enableContentType( ContentType contentType )
{
mAllowedTypes |= contentType;
emit logStateChanged();
};
/** remove a content type from the set of logged ones */
void disableContentType( ContentType contentType ) { allowedTypes &= ~contentType; };
void disableContentType( ContentType contentType )
{
mAllowedTypes &= ~contentType;
emit logStateChanged();
};
/** check a content type for inclusion in the set of logged ones */
bool isContentTypeEnabled( ContentType contentType )
{
return mAllowedTypes & contentType;
};
/** add a log entry */
void add( QString logEntry, ContentType contentType );
/** add a separating line in the log */
void addSeparator() { add( "------------------------------", meta ); };
/** discard collected log data */
void clear() { logEntries.clear(); currentLogSize = 0; };
void clear()
{
mLogEntries.clear();
mCurrentLogSize = 0;
emit logShrinked();
};
/** get access to the log entries */
const QStringList & getLogEntries() { return logEntries; };
const QStringList & getLogEntries() { return mLogEntries; };
/** dump the log - for testing purposes */
void dump();
/** save the log to a file - returns true if okay */
bool saveToFile( QString fileName );
/** destructor */
virtual ~FilterLog();
@ -90,30 +120,31 @@ namespace KMail {
signals:
void logEntryAdded( QString );
void logShrinked();
void logStateChanged();
protected:
/** Non-public constructor needed by the singleton implementation */
FilterLog();
/** The list contains the single log pieces */
QStringList logEntries;
QStringList mLogEntries;
/** the log status */
bool logging;
bool mLogging;
/** max size for kept log items, when reached
the last recently added items are discarded
-1 means unlimited */
long maxLogSize;
long currentLogSize;
long mMaxLogSize;
long mCurrentLogSize;
/** types currently allowed to be legged */
int allowedTypes;
int mAllowedTypes;
void checkLogSize();
private:
static FilterLog * self;
static FilterLog * mSelf;
};
} // namespace KMail

@ -31,10 +31,16 @@
#include "filterlog.h"
#include <kdebug.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <qcheckbox.h>
#include <qstringlist.h>
#include <qtextedit.h>
#include <qvbox.h>
#include <errno.h>
using namespace KMail;
@ -42,51 +48,111 @@ using namespace KMail;
FilterLogDialog::FilterLogDialog( QWidget * parent )
: KDialogBase( parent, "FilterLogDlg", false, i18n( "KMail Filter Log Viewer" ),
User1|Close, Close, true, i18n("C&lear") )
User1|User2|Close, Close, true, i18n("Clea&r"), i18n("&Save...") )
{
setWFlags( WDestructiveClose );
textEdit = new QTextEdit( this );
setMainWidget( textEdit );
textEdit->setReadOnly( true );
QVBox *page = makeVBoxMainWidget();
mTextEdit = new QTextEdit( page );
mTextEdit->setReadOnly( true );
mTextEdit->setWordWrap( QTextEdit::NoWrap );
mTextEdit->setTextFormat( QTextEdit::PlainText );
QStringList logEntries = FilterLog::instance()->getLogEntries();
for ( QStringList::Iterator it = logEntries.begin();
it != logEntries.end(); ++it )
{
textEdit->append( *it );
mTextEdit->append( *it );
}
mLineWrapBox = new QCheckBox( i18n("&Wrap lines in viewer"), page );
mLineWrapBox->setChecked( false );
connect( mLineWrapBox, SIGNAL(clicked()),
this, SLOT(slotSwitchLineWrap(void)) );
mLogActiveBox = new QCheckBox( i18n("&Log filter activities"), page );
mLogActiveBox->setChecked( FilterLog::instance()->isLogging() );
connect( mLogActiveBox, SIGNAL(clicked()),
this, SLOT(slotSwitchLogState(void)) );
connect(FilterLog::instance(), SIGNAL(logEntryAdded(QString)),
this, SLOT(slotLogEntryAdded(QString)));
connect(FilterLog::instance(), SIGNAL(logShrinked(void)),
this, SLOT(slotLogShrinked(void)));
connect(FilterLog::instance(), SIGNAL(logStateChanged(void)),
this, SLOT(slotLogStateChanged(void)));
setInitialSize( QSize( 500, 300 ) );
setInitialSize( QSize( 500, 400 ) );
}
void FilterLogDialog::slotLogEntryAdded( QString logEntry )
{
textEdit->append( logEntry );
mTextEdit->append( logEntry );
}
void FilterLogDialog::slotLogShrinked()
{
textEdit->clear();
mTextEdit->clear();
QStringList logEntries = FilterLog::instance()->getLogEntries();
for ( QStringList::Iterator it = logEntries.begin();
it != logEntries.end(); ++it )
{
textEdit->append( *it );
mTextEdit->append( *it );
}
}
void FilterLogDialog::slotLogStateChanged()
{
mLogActiveBox->setChecked( FilterLog::instance()->isLogging() );
}
void FilterLogDialog::slotSwitchLogState()
{
FilterLog::instance()->setLogging( mLogActiveBox->isChecked() );
}
void FilterLogDialog::slotSwitchLineWrap()
{
if ( mLineWrapBox->isChecked() )
mTextEdit->setWordWrap( QTextEdit::WidgetWidth );
else
mTextEdit->setWordWrap( QTextEdit::NoWrap );
}
void FilterLogDialog::slotUser1()
{
FilterLog::instance()->clear();
textEdit->clear();
mTextEdit->clear();
}
void FilterLogDialog::slotUser2()
{
QString fileName;
KFileDialog fdlg( QString::null, QString::null, this, 0, true );
fdlg.setMode( KFile::File );
fdlg.setSelection( "kmail-filter.log" );
fdlg.setOperationMode( KFileDialog::Saving );
if ( fdlg.exec() )
{
fileName = "/home/domino/kmail-filter.log";
if ( !FilterLog::instance()->saveToFile( fdlg.selectedFile() ) )
{
KMessageBox::error( this,
i18n( "%1 is detailed error description",
"Could not write the file:\n%2" )
.arg( QString::fromLocal8Bit( strerror( errno ) ) )
.arg( fileName ),
i18n( "KMail Error" ) );
}
}
}

@ -32,6 +32,7 @@
#include <kdialogbase.h>
class QTextEdit;
class QCheckBox;
namespace KMail {
@ -53,10 +54,17 @@ namespace KMail {
protected slots:
void slotLogEntryAdded( QString logEntry );
void slotLogShrinked();
void slotLogStateChanged();
void slotSwitchLogState();
void slotSwitchLineWrap();
protected:
virtual void slotUser1();
QTextEdit * textEdit;
virtual void slotUser2();
QTextEdit * mTextEdit;
QCheckBox * mLineWrapBox;
QCheckBox * mLogActiveBox;
};
} // namespace KMail

@ -210,7 +210,7 @@ int KMFilterMgr::process( KMMessage * msg, FilterSet set ) {
// filter is applicable
if ( FilterLog::instance()->isLogging() ) {
QString logText( i18n( "Evaluating filter rules:\n" ) );
QString logText( i18n( "Evaluating filter rules: " ) );
logText.append( (*it)->pattern()->asString() );
FilterLog::instance()->add( logText, FilterLog::patternDesc );
}

@ -3305,6 +3305,6 @@ void KMMainWidget::slotAntiSpamWizard()
//-----------------------------------------------------------------------------
void KMMainWidget::slotFilterLogViewer()
{
FilterLogDialog * dlg = new FilterLogDialog( this );
FilterLogDialog * dlg = new FilterLogDialog( 0 );
dlg->show();
}

@ -260,11 +260,14 @@ bool KMSearchRuleString::matches( const KMMessage * msg ) const
return false;
QString msgContents;
bool logContents = true;
if( field() == "<message>" ) {
msgContents = msg->asString();
logContents = false;
} else if ( field() == "<body>" ) {
msgContents = msg->bodyDecoded();
logContents = false;
} else if ( field() == "<any header>" ) {
msgContents = msg->headerAsString();
} else if ( field() == "<recipients>" ) {
@ -286,7 +289,10 @@ bool KMSearchRuleString::matches( const KMMessage * msg ) const
bool rc = matchesInternal( msgContents );
if ( FilterLog::instance()->isLogging() ) {
QString msg = ( rc ? "1 = " : "0 = " );
msg += asString() + " (" + msgContents + ")";
msg += asString();
// only log headers bcause messages and bodies can be pretty large
if ( logContents )
msg += " (" + msgContents + ")";
FilterLog::instance()->add( msg, FilterLog::ruleResult );
}
return rc;
@ -720,14 +726,14 @@ void KMSearchPattern::init() {
}
QString KMSearchPattern::asString() const {
QString result = "\t";
QString result;
if ( mOperator == OpOr )
result += i18n("(match any of the following)") + '\n';
result = i18n("(match any of the following)");
else
result += i18n("(match all of the following)") + '\n';
result = i18n("(match all of the following)");
for ( QPtrListIterator<KMSearchRule> it( *this ) ; it.current() ; ++it )
result += '\t' + (*it)->asString() + '\n';
result += "\n\t" + (*it)->asString();
return result;
}

Loading…
Cancel
Save