From 7f0618b4707517060bbaa6c5d0fb4b25978c0a3d Mon Sep 17 00:00:00 2001 From: Andreas Gungl Date: Mon, 23 Feb 2004 10:43:50 +0000 Subject: [PATCH] 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 --- filterlog.cpp | 81 +++++++++++++++++++++++++++++------------- filterlog.h | 57 +++++++++++++++++++++++------- filterlogdlg.cpp | 86 +++++++++++++++++++++++++++++++++++++++------ filterlogdlg.h | 10 +++++- kmfiltermgr.cpp | 2 +- kmmainwidget.cpp | 2 +- kmsearchpattern.cpp | 16 ++++++--- 7 files changed, 199 insertions(+), 55 deletions(-) diff --git a/filterlog.cpp b/filterlog.cpp index a6c3f8823..99b2c3bc8 100644 --- a/filterlog.cpp +++ b/filterlog.cpp @@ -31,24 +31,29 @@ #include +#include +#include + +#include + 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 it = logEntries.begin(); - if ( it != logEntries.end()) + QValueListIterator 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" diff --git a/filterlog.h b/filterlog.h index b99031e39..e1e79a30a 100644 --- a/filterlog.h +++ b/filterlog.h @@ -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 diff --git a/filterlogdlg.cpp b/filterlogdlg.cpp index aa1b27303..6c2d2c700 100644 --- a/filterlogdlg.cpp +++ b/filterlogdlg.cpp @@ -31,10 +31,16 @@ #include "filterlog.h" #include +#include #include +#include +#include #include #include +#include + +#include 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" ) ); + } + } } diff --git a/filterlogdlg.h b/filterlogdlg.h index da4ebb9a6..ca469a7a4 100644 --- a/filterlogdlg.h +++ b/filterlogdlg.h @@ -32,6 +32,7 @@ #include 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 diff --git a/kmfiltermgr.cpp b/kmfiltermgr.cpp index 442c796de..3021fb46c 100644 --- a/kmfiltermgr.cpp +++ b/kmfiltermgr.cpp @@ -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 ); } diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index 2a84585c2..51285fed7 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -3305,6 +3305,6 @@ void KMMainWidget::slotAntiSpamWizard() //----------------------------------------------------------------------------- void KMMainWidget::slotFilterLogViewer() { - FilterLogDialog * dlg = new FilterLogDialog( this ); + FilterLogDialog * dlg = new FilterLogDialog( 0 ); dlg->show(); } diff --git a/kmsearchpattern.cpp b/kmsearchpattern.cpp index d12db4c22..9b62e1c86 100644 --- a/kmsearchpattern.cpp +++ b/kmsearchpattern.cpp @@ -260,11 +260,14 @@ bool KMSearchRuleString::matches( const KMMessage * msg ) const return false; QString msgContents; + bool logContents = true; if( field() == "" ) { msgContents = msg->asString(); + logContents = false; } else if ( field() == "" ) { msgContents = msg->bodyDecoded(); + logContents = false; } else if ( field() == "" ) { msgContents = msg->headerAsString(); } else if ( field() == "" ) { @@ -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 it( *this ) ; it.current() ; ++it ) - result += '\t' + (*it)->asString() + '\n'; + result += "\n\t" + (*it)->asString(); return result; }