mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
1297 lines
30 KiB
C++
1297 lines
30 KiB
C++
![]() |
/*
|
||
|
kscoring.cpp
|
||
|
|
||
|
Copyright (c) 2001 Mathias Waack <mathias@atoll-net.de>
|
||
|
Copyright (C) 2005 by Volker Krause <vkrause@kde.org>
|
||
|
|
||
|
Author: Mathias Waack <mathias@atoll-net.de>
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software Foundation,
|
||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
|
||
|
*/
|
||
|
#ifdef KDE_USE_FINAL
|
||
|
#undef QT_NO_ASCII_CAST
|
||
|
#endif
|
||
|
|
||
|
#undef QT_NO_COMPAT
|
||
|
|
||
|
#include "kscoring.h"
|
||
|
#include "kscoringeditor.h"
|
||
|
|
||
|
#include <KDebug>
|
||
|
#include <KLocale>
|
||
|
#include <KInputDialog>
|
||
|
#include <KStandardDirs>
|
||
|
#include <KTextEdit>
|
||
|
|
||
|
#include <QCheckBox>
|
||
|
#include <QDomElement>
|
||
|
#include <QDomDocument>
|
||
|
#include <QDomNode>
|
||
|
#include <QDomNodeList>
|
||
|
#include <QFile>
|
||
|
#include <QLayout>
|
||
|
#include <QLabel>
|
||
|
#include <QTextStream>
|
||
|
#include <QVBoxLayout>
|
||
|
#include <Q3PtrList>
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
using namespace KPIM;
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// a small function to encode attribute values, code stolen from QDom
|
||
|
static QString toXml( const QString &str )
|
||
|
{
|
||
|
QString tmp(str);
|
||
|
uint len = tmp.length();
|
||
|
uint i = 0;
|
||
|
while ( i < len ) {
|
||
|
if ( tmp[(int)i] == '<' ) {
|
||
|
tmp.replace( i, 1, "<" );
|
||
|
len += 3;
|
||
|
i += 4;
|
||
|
} else if ( tmp[(int)i] == '"' ) {
|
||
|
tmp.replace( i, 1, """ );
|
||
|
len += 5;
|
||
|
i += 6;
|
||
|
} else if ( tmp[(int)i] == '&' ) {
|
||
|
tmp.replace( i, 1, "&" );
|
||
|
len += 4;
|
||
|
i += 5;
|
||
|
} else if ( tmp[(int)i] == '>' ) {
|
||
|
tmp.replace( i, 1, ">" );
|
||
|
len += 3;
|
||
|
i += 4;
|
||
|
} else {
|
||
|
++i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
// small dialog to display the messages from NotifyAction
|
||
|
NotifyDialog *NotifyDialog::me = 0;
|
||
|
NotifyDialog::NotesMap NotifyDialog::dict;
|
||
|
|
||
|
NotifyDialog::NotifyDialog( QWidget *parent )
|
||
|
: KDialog( parent )
|
||
|
{
|
||
|
setCaption( i18n( "Notify Message" ) );
|
||
|
setButtons( Close );
|
||
|
setDefaultButton( Close );
|
||
|
setModal( true );
|
||
|
|
||
|
QFrame *f = new QFrame( this );
|
||
|
setMainWidget ( f );
|
||
|
QVBoxLayout *topL = new QVBoxLayout( f );
|
||
|
note = new QLabel( f );
|
||
|
note->setTextFormat( Qt::RichText );
|
||
|
topL->addWidget( note );
|
||
|
QCheckBox *check = new QCheckBox( i18n( "Do not show this message again" ), f );
|
||
|
check->setChecked( true );
|
||
|
topL->addWidget( check );
|
||
|
connect( check, SIGNAL(toggled(bool)), SLOT(slotShowAgainToggled(bool)) );
|
||
|
}
|
||
|
|
||
|
void NotifyDialog::slotShowAgainToggled( bool flag )
|
||
|
{
|
||
|
dict.remove( msg );
|
||
|
dict.insert( msg, !flag );
|
||
|
kDebug(5100) <<"note \"" << note <<"\" will popup again:" << flag;
|
||
|
}
|
||
|
|
||
|
void NotifyDialog::display( ScorableArticle &a, const QString &s )
|
||
|
{
|
||
|
kDebug(5100) <<"displaying message";
|
||
|
if ( !me ) {
|
||
|
me = new NotifyDialog();
|
||
|
}
|
||
|
me->msg = s;
|
||
|
|
||
|
NotesMap::Iterator i = dict.find( s );
|
||
|
if ( i == dict.end() || i.value() ) {
|
||
|
QString msg =
|
||
|
i18n( "Article\n<b>%1</b><br /><b>%2</b><br />caused the following note to appear:<br />%3",
|
||
|
a.from(),
|
||
|
a.subject(),
|
||
|
s );
|
||
|
me->note->setText(msg);
|
||
|
if ( i == dict.end() ) {
|
||
|
dict.remove( s );
|
||
|
i = dict.insert( s, false );
|
||
|
}
|
||
|
me->adjustSize();
|
||
|
me->exec();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
ScorableArticle::~ScorableArticle()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void ScorableArticle::displayMessage( const QString ¬e )
|
||
|
{
|
||
|
NotifyDialog::display( *this, note );
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
ScorableGroup::~ScorableGroup()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// the base class for all actions
|
||
|
ActionBase::ActionBase()
|
||
|
{
|
||
|
kDebug(5100) <<"new Action" << this;
|
||
|
}
|
||
|
|
||
|
ActionBase::~ActionBase()
|
||
|
{
|
||
|
kDebug(5100) <<"delete Action" << this;
|
||
|
}
|
||
|
|
||
|
QStringList ActionBase::userNames()
|
||
|
{
|
||
|
QStringList l;
|
||
|
l << userName( SETSCORE );
|
||
|
l << userName( NOTIFY );
|
||
|
l << userName( COLOR );
|
||
|
l << userName( MARKASREAD );
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
ActionBase *ActionBase::factory( int type, const QString &value )
|
||
|
{
|
||
|
switch( type ) {
|
||
|
case SETSCORE:
|
||
|
return new ActionSetScore( value );
|
||
|
case NOTIFY:
|
||
|
return new ActionNotify( value );
|
||
|
case COLOR:
|
||
|
return new ActionColor( value );
|
||
|
case MARKASREAD:
|
||
|
return new ActionMarkAsRead();
|
||
|
default:
|
||
|
kWarning(5100) <<"unknown type" << type <<" in ActionBase::factory()";
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QString ActionBase::userName( int type )
|
||
|
{
|
||
|
switch( type ) {
|
||
|
case SETSCORE:
|
||
|
return i18n( "Adjust Score" );
|
||
|
case NOTIFY:
|
||
|
return i18n( "Display Message" );
|
||
|
case COLOR:
|
||
|
return i18n( "Colorize Header" );
|
||
|
case MARKASREAD:
|
||
|
return i18n( "Mark as Read" );
|
||
|
default:
|
||
|
kWarning(5100) <<"unknown type" << type <<" in ActionBase::userName()";
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ActionBase::getTypeForName( const QString &name )
|
||
|
{
|
||
|
if ( name == "SETSCORE" ) {
|
||
|
return SETSCORE;
|
||
|
} else if ( name == "NOTIFY" ) {
|
||
|
return NOTIFY;
|
||
|
} else if ( name == "COLOR" ) {
|
||
|
return COLOR;
|
||
|
} else if ( name == "MARKASREAD" ) {
|
||
|
return MARKASREAD;
|
||
|
} else {
|
||
|
kWarning(5100) <<"unknown type string" << name
|
||
|
<< "in ActionBase::getTypeForName()";
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ActionBase::getTypeForUserName( const QString &name )
|
||
|
{
|
||
|
if ( name == userName( SETSCORE ) ) {
|
||
|
return SETSCORE;
|
||
|
} else if ( name == userName( NOTIFY ) ) {
|
||
|
return NOTIFY;
|
||
|
} else if ( name == userName( COLOR ) ) {
|
||
|
return COLOR;
|
||
|
} else if ( name == userName( MARKASREAD ) ) {
|
||
|
return MARKASREAD;
|
||
|
} else {
|
||
|
kWarning(5100) <<"unknown type string" << name
|
||
|
<< "in ActionBase::getTypeForUserName()";
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// the set score action
|
||
|
ActionSetScore::ActionSetScore( short v )
|
||
|
: val( v )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ActionSetScore::ActionSetScore( const QString &s )
|
||
|
{
|
||
|
val = s.toShort();
|
||
|
}
|
||
|
|
||
|
ActionSetScore::ActionSetScore( const ActionSetScore &as )
|
||
|
: ActionBase(),
|
||
|
val( as.val )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ActionSetScore::~ActionSetScore()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QString ActionSetScore::toString() const
|
||
|
{
|
||
|
QString a;
|
||
|
a += "<Action type=\"SETSCORE\" value=\"" + QString::number(val) + "\" />";
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
void ActionSetScore::apply( ScorableArticle &a ) const
|
||
|
{
|
||
|
a.addScore( val );
|
||
|
}
|
||
|
|
||
|
ActionSetScore *ActionSetScore::clone() const
|
||
|
{
|
||
|
return new ActionSetScore( *this );
|
||
|
}
|
||
|
|
||
|
// the color action
|
||
|
ActionColor::ActionColor( const QColor &c )
|
||
|
: ActionBase(), color( c )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ActionColor::ActionColor( const QString &s )
|
||
|
: ActionBase()
|
||
|
{
|
||
|
setValue(s);
|
||
|
}
|
||
|
|
||
|
ActionColor::ActionColor( const ActionColor &a )
|
||
|
: ActionBase(), color( a.color )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ActionColor::~ActionColor()
|
||
|
{}
|
||
|
|
||
|
QString ActionColor::toString() const
|
||
|
{
|
||
|
QString a;
|
||
|
a += "<Action type=\"COLOR\" value=\"" + toXml(color.name()) + "\" />";
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
void ActionColor::apply( ScorableArticle &a ) const
|
||
|
{
|
||
|
a.changeColor( color );
|
||
|
}
|
||
|
|
||
|
ActionColor *ActionColor::clone() const
|
||
|
{
|
||
|
return new ActionColor( *this );
|
||
|
}
|
||
|
|
||
|
// the notify action
|
||
|
ActionNotify::ActionNotify( const QString &s )
|
||
|
{
|
||
|
note = s;
|
||
|
}
|
||
|
|
||
|
ActionNotify::ActionNotify( const ActionNotify &an )
|
||
|
: ActionBase()
|
||
|
{
|
||
|
note = an.note;
|
||
|
}
|
||
|
|
||
|
QString ActionNotify::toString() const
|
||
|
{
|
||
|
return "<Action type=\"NOTIFY\" value=\"" + toXml(note) + "\" />";
|
||
|
}
|
||
|
|
||
|
void ActionNotify::apply( ScorableArticle &a ) const
|
||
|
{
|
||
|
a.displayMessage( note );
|
||
|
}
|
||
|
|
||
|
ActionNotify *ActionNotify::clone() const
|
||
|
{
|
||
|
return new ActionNotify( *this );
|
||
|
}
|
||
|
|
||
|
// mark as read action
|
||
|
ActionMarkAsRead::ActionMarkAsRead() :
|
||
|
ActionBase()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ActionMarkAsRead::ActionMarkAsRead( const ActionMarkAsRead &action ) :
|
||
|
ActionBase()
|
||
|
{
|
||
|
Q_UNUSED( action );
|
||
|
}
|
||
|
|
||
|
QString ActionMarkAsRead::toString() const
|
||
|
{
|
||
|
return "<Action type=\"MARKASREAD\"/>";
|
||
|
}
|
||
|
|
||
|
void ActionMarkAsRead::apply( ScorableArticle &article ) const
|
||
|
{
|
||
|
article.markAsRead();
|
||
|
}
|
||
|
|
||
|
ActionMarkAsRead *ActionMarkAsRead::clone() const
|
||
|
{
|
||
|
return new ActionMarkAsRead( *this );
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
NotifyCollection::NotifyCollection()
|
||
|
{
|
||
|
notifyList.setAutoDelete( true );
|
||
|
}
|
||
|
|
||
|
NotifyCollection::~NotifyCollection()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void NotifyCollection::addNote( const ScorableArticle &a, const QString ¬e )
|
||
|
{
|
||
|
article_list *l = notifyList.find( note );
|
||
|
if ( !l ) {
|
||
|
notifyList.insert( note, new article_list );
|
||
|
l = notifyList.find( note );
|
||
|
}
|
||
|
article_info i;
|
||
|
i.from = a.from();
|
||
|
i.subject = a.subject();
|
||
|
l->append(i);
|
||
|
}
|
||
|
|
||
|
QString NotifyCollection::collection() const
|
||
|
{
|
||
|
QString notifyCollection = i18n( "<h1>List of collected notes</h1>" );
|
||
|
notifyCollection += "<p><ul>";
|
||
|
// first look thru the notes and create one string
|
||
|
Q3DictIterator<article_list> it(notifyList);
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
const QString ¬e = it.currentKey();
|
||
|
notifyCollection += "<li>" + note + "<ul>";
|
||
|
article_list *alist = it.current();
|
||
|
article_list::Iterator ait;
|
||
|
for ( ait = alist->begin(); ait != alist->end(); ++ait ) {
|
||
|
notifyCollection += "<li><b>From: </b>" + (*ait).from + "<br>";
|
||
|
notifyCollection += "<b>Subject: </b>" + (*ait).subject;
|
||
|
}
|
||
|
notifyCollection += "</ul>";
|
||
|
}
|
||
|
notifyCollection += "</ul>";
|
||
|
|
||
|
return notifyCollection;
|
||
|
}
|
||
|
|
||
|
void NotifyCollection::displayCollection( QWidget *p ) const
|
||
|
{
|
||
|
//KMessageBox::information(p,collection(),i18n("Collected Notes"));
|
||
|
KDialog *dlg = new KDialog( p );
|
||
|
dlg->setCaption( i18n( "Collected Notes" ) );
|
||
|
dlg->setButtons( KDialog::Close );
|
||
|
dlg->setDefaultButton( KDialog::Close );
|
||
|
dlg->setModal( false );
|
||
|
KTextEdit *text = new KTextEdit( dlg );
|
||
|
text->setReadOnly( true );
|
||
|
text->setText( collection() );
|
||
|
dlg->setMainWidget( text );
|
||
|
dlg->setMinimumWidth( 300 );
|
||
|
dlg->setMinimumHeight( 300 );
|
||
|
dlg->show();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
KScoringExpression::KScoringExpression( const QString &h, const QString &t,
|
||
|
const QString &n, const QString &ng )
|
||
|
: header( h ), expr_str( n )
|
||
|
{
|
||
|
if ( t == "MATCH" ) {
|
||
|
cond = MATCH;
|
||
|
expr.setPattern( expr_str );
|
||
|
expr.setCaseSensitivity( Qt::CaseInsensitive );
|
||
|
} else if ( t == "MATCHCS" ) {
|
||
|
cond = MATCHCS;
|
||
|
expr.setPattern( expr_str );
|
||
|
expr.setCaseSensitivity( Qt::CaseSensitive );
|
||
|
} else if ( t == "CONTAINS" ) {
|
||
|
cond = CONTAINS;
|
||
|
} else if ( t == "EQUALS" ) {
|
||
|
cond = EQUALS;
|
||
|
} else if ( t == "GREATER" ) {
|
||
|
cond = GREATER;
|
||
|
expr_int = expr_str.toInt();
|
||
|
} else if ( t == "SMALLER" ) {
|
||
|
cond = SMALLER;
|
||
|
expr_int = expr_str.toInt();
|
||
|
} else {
|
||
|
kDebug(5100) <<"unknown match type in new expression";
|
||
|
}
|
||
|
|
||
|
neg = ng.toInt();
|
||
|
|
||
|
kDebug(5100) <<"new expr:" << header << t
|
||
|
<< expr_str << neg;
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
int KScoringExpression::getConditionForName( const QString &s )
|
||
|
{
|
||
|
if ( s == getNameForCondition( CONTAINS ) ) {
|
||
|
return CONTAINS;
|
||
|
} else if ( s == getNameForCondition( MATCH ) ) {
|
||
|
return MATCH;
|
||
|
} else if ( s == getNameForCondition( MATCHCS ) ) {
|
||
|
return MATCHCS;
|
||
|
} else if ( s == getNameForCondition( EQUALS ) ) {
|
||
|
return EQUALS;
|
||
|
} else if ( s == getNameForCondition( SMALLER ) ) {
|
||
|
return SMALLER;
|
||
|
} else if ( s == getNameForCondition( GREATER ) ) {
|
||
|
return GREATER;
|
||
|
} else {
|
||
|
kWarning(5100) <<"unknown condition name" << s
|
||
|
<< "in KScoringExpression::getConditionForName()";
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
QString KScoringExpression::getNameForCondition( int cond )
|
||
|
{
|
||
|
switch ( cond ) {
|
||
|
case CONTAINS:
|
||
|
return i18n( "Contains Substring" );
|
||
|
case MATCH:
|
||
|
return i18n( "Matches Regular Expression" );
|
||
|
case MATCHCS:
|
||
|
return i18n( "Matches Regular Expression (Case Sensitive)" );
|
||
|
case EQUALS:
|
||
|
return i18n( "Is Exactly the Same As" );
|
||
|
case SMALLER:
|
||
|
return i18n( "Less Than" );
|
||
|
case GREATER:
|
||
|
return i18n( "Greater Than" );
|
||
|
default:
|
||
|
kWarning(5100) <<"unknown condition" << cond
|
||
|
<< "in KScoringExpression::getNameForCondition()";
|
||
|
return "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
QStringList KScoringExpression::conditionNames()
|
||
|
{
|
||
|
QStringList l;
|
||
|
l << getNameForCondition( CONTAINS );
|
||
|
l << getNameForCondition( MATCH );
|
||
|
l << getNameForCondition( MATCHCS );
|
||
|
l << getNameForCondition( EQUALS );
|
||
|
l << getNameForCondition( SMALLER );
|
||
|
l << getNameForCondition( GREATER );
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
QStringList KScoringExpression::headerNames()
|
||
|
{
|
||
|
QStringList l;
|
||
|
l.append( "From" );
|
||
|
l.append( "Message-ID" );
|
||
|
l.append( "Subject" );
|
||
|
l.append( "Date" );
|
||
|
l.append( "References" );
|
||
|
l.append( "NNTP-Posting-Host" );
|
||
|
l.append( "Bytes" );
|
||
|
l.append( "Lines" );
|
||
|
l.append( "Xref" );
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
KScoringExpression::~KScoringExpression()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool KScoringExpression::match( ScorableArticle &a ) const
|
||
|
{
|
||
|
bool res = true;
|
||
|
QString head;
|
||
|
|
||
|
if ( header == "From" ) {
|
||
|
head = a.from();
|
||
|
} else if ( header == "Subject" ) {
|
||
|
head = a.subject();
|
||
|
} else {
|
||
|
head = a.getHeaderByType( header );
|
||
|
}
|
||
|
|
||
|
if ( !head.isEmpty() ) {
|
||
|
switch( cond ) {
|
||
|
case EQUALS:
|
||
|
res = ( head.toLower() == expr_str.toLower() );
|
||
|
break;
|
||
|
case CONTAINS:
|
||
|
res = ( head.toLower().indexOf( expr_str.toLower() ) >= 0 );
|
||
|
break;
|
||
|
case MATCH:
|
||
|
case MATCHCS:
|
||
|
res = ( expr.indexIn( head ) != -1 );
|
||
|
break;
|
||
|
case GREATER:
|
||
|
res = ( head.toInt() > expr_int );
|
||
|
break;
|
||
|
case SMALLER:
|
||
|
res = ( head.toInt() < expr_int );
|
||
|
break;
|
||
|
default:
|
||
|
kDebug(5100) <<"unknown match";
|
||
|
res = false;
|
||
|
}
|
||
|
} else {
|
||
|
res = false;
|
||
|
}
|
||
|
|
||
|
return neg ? !res : res;
|
||
|
}
|
||
|
|
||
|
void KScoringExpression::write( QTextStream &st ) const
|
||
|
{
|
||
|
st << toString();
|
||
|
}
|
||
|
|
||
|
QString KScoringExpression::toString() const
|
||
|
{
|
||
|
QString e;
|
||
|
e += "<Expression neg=\"" + QString::number( neg ? 1 : 0 ) +
|
||
|
"\" header=\"" + header +
|
||
|
"\" type=\"" + getTypeString() +
|
||
|
"\" expr=\"" + toXml(expr_str) +
|
||
|
"\" />";
|
||
|
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
QString KScoringExpression::getTypeString() const
|
||
|
{
|
||
|
return KScoringExpression::getTypeString(cond);
|
||
|
}
|
||
|
|
||
|
QString KScoringExpression::getTypeString( int cond )
|
||
|
{
|
||
|
switch( cond ) {
|
||
|
case CONTAINS:
|
||
|
return "CONTAINS";
|
||
|
case MATCH:
|
||
|
return "MATCH";
|
||
|
case MATCHCS:
|
||
|
return "MATCHCS";
|
||
|
case EQUALS:
|
||
|
return "EQUALS";
|
||
|
case SMALLER:
|
||
|
return "SMALLER";
|
||
|
case GREATER:
|
||
|
return "GREATER";
|
||
|
default:
|
||
|
kWarning(5100) <<"unknown cond" << cond
|
||
|
<<" in KScoringExpression::getTypeString()";
|
||
|
return "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int KScoringExpression::getType() const
|
||
|
{
|
||
|
return cond;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
KScoringRule::KScoringRule( const QString &n )
|
||
|
: name( n ), link( AND )
|
||
|
{
|
||
|
expressions.setAutoDelete( true );
|
||
|
actions.setAutoDelete( true );
|
||
|
}
|
||
|
|
||
|
KScoringRule::KScoringRule( const KScoringRule &r )
|
||
|
{
|
||
|
kDebug(5100) <<"copying rule" << r.getName();
|
||
|
name = r.getName();
|
||
|
expressions.setAutoDelete( true );
|
||
|
actions.setAutoDelete( true );
|
||
|
// copy expressions
|
||
|
expressions.clear();
|
||
|
const ScoreExprList &rexpr = r.expressions;
|
||
|
Q3PtrListIterator<KScoringExpression> it( rexpr );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
KScoringExpression *t = new KScoringExpression( **it );
|
||
|
expressions.append( t );
|
||
|
}
|
||
|
// copy actions
|
||
|
actions.clear();
|
||
|
const ActionList &ract = r.actions;
|
||
|
Q3PtrListIterator<ActionBase> ait( ract );
|
||
|
for ( ; ait.current(); ++ait ) {
|
||
|
ActionBase *t = *ait;
|
||
|
actions.append( t->clone() );
|
||
|
}
|
||
|
// copy groups, servers, linkmode and expires
|
||
|
groups = r.groups;
|
||
|
expires = r.expires;
|
||
|
link = r.link;
|
||
|
}
|
||
|
|
||
|
KScoringRule::~KScoringRule()
|
||
|
{
|
||
|
cleanExpressions();
|
||
|
cleanActions();
|
||
|
}
|
||
|
|
||
|
void KScoringRule::cleanExpressions()
|
||
|
{
|
||
|
// the expressions is setAutoDelete(true)
|
||
|
expressions.clear();
|
||
|
}
|
||
|
|
||
|
void KScoringRule::cleanActions()
|
||
|
{
|
||
|
// the actions is setAutoDelete(true)
|
||
|
actions.clear();
|
||
|
}
|
||
|
|
||
|
void KScoringRule::addExpression( KScoringExpression *expr )
|
||
|
{
|
||
|
kDebug(5100) <<"KScoringRule::addExpression";
|
||
|
expressions.append(expr);
|
||
|
}
|
||
|
|
||
|
void KScoringRule::addAction( int type, const QString &val )
|
||
|
{
|
||
|
ActionBase *action = ActionBase::factory( type, val );
|
||
|
addAction( action );
|
||
|
}
|
||
|
|
||
|
void KScoringRule::addAction( ActionBase *a )
|
||
|
{
|
||
|
kDebug(5100) <<"KScoringRule::addAction()" << a->toString();
|
||
|
actions.append(a);
|
||
|
}
|
||
|
|
||
|
void KScoringRule::setLinkMode( const QString &l )
|
||
|
{
|
||
|
if ( l == "OR" ) {
|
||
|
link = OR;
|
||
|
} else {
|
||
|
link = AND;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringRule::setExpire( const QString &e )
|
||
|
{
|
||
|
if ( e != "never" ) {
|
||
|
QStringList l = e.split( '-', QString::SkipEmptyParts );
|
||
|
Q_ASSERT( l.count() == 3 );
|
||
|
expires.setYMD( l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt() );
|
||
|
}
|
||
|
kDebug(5100) <<"Rule" << getName() <<" expires at" << getExpireDateString();
|
||
|
}
|
||
|
|
||
|
bool KScoringRule::matchGroup( const QString &group ) const
|
||
|
{
|
||
|
for ( GroupList::ConstIterator i = groups.begin(); i != groups.end(); ++i ) {
|
||
|
QRegExp e( *i );
|
||
|
if ( e.indexIn( group, 0 ) != -1 && e.matchedLength() == group.length() ) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void KScoringRule::applyAction( ScorableArticle &a ) const
|
||
|
{
|
||
|
Q3PtrListIterator<ActionBase> it( actions );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
it.current()->apply( a );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringRule::applyRule( ScorableArticle &a ) const
|
||
|
{
|
||
|
bool oper_and = ( link == AND );
|
||
|
bool res = true;
|
||
|
Q3PtrListIterator<KScoringExpression> it( expressions );
|
||
|
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
Q_ASSERT( it.current() );
|
||
|
res = it.current()->match( a );
|
||
|
if ( !res && oper_and ) {
|
||
|
return;
|
||
|
} else if ( res && !oper_and ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( res ) {
|
||
|
applyAction( a );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringRule::applyRule( ScorableArticle &a, const QString &g ) const
|
||
|
{
|
||
|
// check if one of the groups match
|
||
|
for ( QStringList::ConstIterator i = groups.begin(); i != groups.end(); ++i ) {
|
||
|
if ( QRegExp( *i ).indexIn( g ) != -1 ) {
|
||
|
applyRule( a );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringRule::write( QTextStream &s ) const
|
||
|
{
|
||
|
s << toString();
|
||
|
}
|
||
|
|
||
|
QString KScoringRule::toString() const
|
||
|
{
|
||
|
QString r;
|
||
|
r += "<Rule name=\"" + toXml(name) + "\" linkmode=\"" + getLinkModeName();
|
||
|
r += "\" expires=\"" + getExpireDateString() + "\">";
|
||
|
|
||
|
for ( GroupList::ConstIterator i = groups.begin(); i != groups.end(); ++i ) {
|
||
|
r += "<Group name=\"" + toXml(*i) + "\" />";
|
||
|
}
|
||
|
|
||
|
Q3PtrListIterator<KScoringExpression> eit(expressions);
|
||
|
for ( ; eit.current(); ++eit ) {
|
||
|
r += eit.current()->toString();
|
||
|
}
|
||
|
|
||
|
Q3PtrListIterator<ActionBase> ait(actions);
|
||
|
for ( ; ait.current(); ++ait ) {
|
||
|
r += ait.current()->toString();
|
||
|
}
|
||
|
r += "</Rule>";
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
QString KScoringRule::getLinkModeName() const
|
||
|
{
|
||
|
switch( link ) {
|
||
|
case AND:
|
||
|
return "AND";
|
||
|
case OR:
|
||
|
return "OR";
|
||
|
default:
|
||
|
return "AND";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QString KScoringRule::getExpireDateString() const
|
||
|
{
|
||
|
if ( expires.isNull() ) {
|
||
|
return "never";
|
||
|
} else {
|
||
|
return
|
||
|
QString::number( expires.year() ) + QString( '-' ) +
|
||
|
QString::number( expires.month() ) + QString( '-' ) +
|
||
|
QString::number( expires.day() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool KScoringRule::isExpired() const
|
||
|
{
|
||
|
return
|
||
|
expires.isValid() &&
|
||
|
( expires < QDate::currentDate() );
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
KScoringManager::KScoringManager( const QString &appName )
|
||
|
: cacheValid( false )
|
||
|
{
|
||
|
allRules.setAutoDelete( true );
|
||
|
// determine filename of the scorefile
|
||
|
if ( appName.isEmpty() ) {
|
||
|
mFilename = KGlobal::dirs()->saveLocation( "appdata" ) + "/scorefile";
|
||
|
} else {
|
||
|
mFilename = KGlobal::dirs()->saveLocation( "data" ) + '/' + appName + "/scorefile";
|
||
|
}
|
||
|
// open the score file
|
||
|
load();
|
||
|
}
|
||
|
|
||
|
KScoringManager::~KScoringManager()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void KScoringManager::load()
|
||
|
{
|
||
|
QDomDocument sdoc( "Scorefile" );
|
||
|
QFile f( mFilename );
|
||
|
if ( !f.open( QIODevice::ReadOnly ) ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( !sdoc.setContent( &f ) ) {
|
||
|
f.close();
|
||
|
kDebug(5100) <<"loading the scorefile failed";
|
||
|
return;
|
||
|
}
|
||
|
f.close();
|
||
|
kDebug(5100) <<"loaded the scorefile, creating internal representation";
|
||
|
allRules.clear();
|
||
|
createInternalFromXML( sdoc );
|
||
|
expireRules();
|
||
|
kDebug(5100) <<"ready, got" << allRules.count() <<" rules";
|
||
|
}
|
||
|
|
||
|
void KScoringManager::save()
|
||
|
{
|
||
|
kDebug(5100) <<"KScoringManager::save() starts";
|
||
|
QFile f( mFilename );
|
||
|
if ( !f.open( QIODevice::WriteOnly ) ) {
|
||
|
return;
|
||
|
}
|
||
|
QTextStream stream( &f );
|
||
|
stream.setCodec( "UTF-8" );
|
||
|
kDebug(5100) <<"KScoringManager::save() creating xml";
|
||
|
createXMLfromInternal().save( stream, 2 );
|
||
|
kDebug(5100) <<"KScoringManager::save() finished";
|
||
|
}
|
||
|
|
||
|
QDomDocument KScoringManager::createXMLfromInternal()
|
||
|
{
|
||
|
// I was'nt able to create a QDomDocument in memory:(
|
||
|
// so I write the content into a string, which is really stupid
|
||
|
QDomDocument sdoc( "Scorefile" );
|
||
|
QString ss; // scorestring
|
||
|
ss += "<?xml version = '1.0'?><!DOCTYPE Scorefile >";
|
||
|
ss += toString();
|
||
|
ss += "</Scorefile>\n";
|
||
|
kDebug(5100) <<"KScoringManager::createXMLfromInternal():" << endl << ss;
|
||
|
sdoc.setContent(ss);
|
||
|
return sdoc;
|
||
|
}
|
||
|
|
||
|
QString KScoringManager::toString() const
|
||
|
{
|
||
|
QString s;
|
||
|
s += "<Scorefile>\n";
|
||
|
Q3PtrListIterator<KScoringRule> it( allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
s += it.current()->toString();
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
void KScoringManager::expireRules()
|
||
|
{
|
||
|
for ( KScoringRule *cR = allRules.first(); cR; cR=allRules.next() ) {
|
||
|
if ( cR->isExpired() ) {
|
||
|
kDebug(5100) <<"Rule" << cR->getName() <<" is expired, deleting it";
|
||
|
allRules.remove();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringManager::createInternalFromXML( QDomNode n )
|
||
|
{
|
||
|
static KScoringRule *cR = 0; // the currentRule
|
||
|
// the XML file was parsed and now we simply traverse the resulting tree
|
||
|
if ( !n.isNull() ) {
|
||
|
kDebug(5100) <<"inspecting node of type" << n.nodeType()
|
||
|
<< "named" << n.toElement().tagName();
|
||
|
|
||
|
switch ( n.nodeType() ) {
|
||
|
case QDomNode::DocumentNode:
|
||
|
{
|
||
|
// the document itself
|
||
|
break;
|
||
|
}
|
||
|
case QDomNode::ElementNode:
|
||
|
{
|
||
|
// Server, Newsgroup, Rule, Expression, Action
|
||
|
QDomElement e = n.toElement();
|
||
|
QString s = e.tagName();
|
||
|
if ( s == "Rule" ) {
|
||
|
cR = new KScoringRule( e.attribute( "name" ) );
|
||
|
cR->setLinkMode( e.attribute( "linkmode" ) );
|
||
|
cR->setExpire( e.attribute( "expires" ) );
|
||
|
addRuleInternal( cR );
|
||
|
} else if ( s == "Group" ) {
|
||
|
Q_CHECK_PTR( cR );
|
||
|
cR->addGroup( e.attribute( "name" ) );
|
||
|
} else if ( s == "Expression" ) {
|
||
|
cR->addExpression( new KScoringExpression( e.attribute( "header" ),
|
||
|
e.attribute( "type" ),
|
||
|
e.attribute( "expr" ),
|
||
|
e.attribute( "neg" ) ) );
|
||
|
} else if ( s == "Action" ) {
|
||
|
Q_CHECK_PTR( cR );
|
||
|
cR->addAction( ActionBase::getTypeForName( e.attribute( "type" ) ),
|
||
|
e.attribute( "value" ) );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
;
|
||
|
}
|
||
|
QDomNodeList nodelist = n.childNodes();
|
||
|
int cnt = nodelist.count();
|
||
|
for ( int i=0; i<cnt; ++i ) {
|
||
|
createInternalFromXML( nodelist.item( i ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
KScoringRule *KScoringManager::addRule( const ScorableArticle &a,
|
||
|
const QString &group, short score )
|
||
|
{
|
||
|
KScoringRule *rule = new KScoringRule( findUniqueName() );
|
||
|
rule->addGroup( group );
|
||
|
rule->addExpression( new KScoringExpression( "From","CONTAINS", a.from(), "0" ) );
|
||
|
if ( score ) {
|
||
|
rule->addAction( new ActionSetScore( score ) );
|
||
|
}
|
||
|
rule->setExpireDate( QDate::currentDate().addDays( 30 ) );
|
||
|
KScoringEditor *edit = KScoringEditor::createEditor( this );
|
||
|
// Note: the call to createEditor() call this->pushRuleList(). So addRule(KScoringRule)
|
||
|
// must be place after it, otherwise the cancel button of the editor is not effective (bug #101092).
|
||
|
addRule( rule );
|
||
|
edit->setRule( rule );
|
||
|
edit->show();
|
||
|
setCacheValid( false );
|
||
|
return rule;
|
||
|
}
|
||
|
|
||
|
KScoringRule *KScoringManager::addRule( KScoringRule *expr )
|
||
|
{
|
||
|
int i = allRules.findRef( expr );
|
||
|
if ( i == -1 ) {
|
||
|
// only add a rule we don't know
|
||
|
addRuleInternal( expr );
|
||
|
} else {
|
||
|
emit changedRules();
|
||
|
}
|
||
|
return expr;
|
||
|
}
|
||
|
|
||
|
KScoringRule *KScoringManager::addRule()
|
||
|
{
|
||
|
KScoringRule *rule = new KScoringRule( findUniqueName() );
|
||
|
addRule( rule );
|
||
|
return rule;
|
||
|
}
|
||
|
|
||
|
void KScoringManager::addRuleInternal( KScoringRule *e )
|
||
|
{
|
||
|
allRules.append( e ) ;
|
||
|
setCacheValid( false );
|
||
|
emit changedRules();
|
||
|
kDebug(5100) <<"KScoringManager::addRuleInternal" << e->getName();
|
||
|
}
|
||
|
|
||
|
void KScoringManager::cancelNewRule( KScoringRule *r )
|
||
|
{
|
||
|
// if e was'nt previously added to the list of rules, we delete it
|
||
|
int i = allRules.findRef( r );
|
||
|
if ( i == -1 ) {
|
||
|
kDebug(5100) <<"deleting rule" << r->getName();
|
||
|
deleteRule( r );
|
||
|
} else {
|
||
|
kDebug(5100) <<"rule" << r->getName() <<" not deleted";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringManager::setRuleName( KScoringRule *r, const QString &s )
|
||
|
{
|
||
|
bool cont = true;
|
||
|
QString text = s;
|
||
|
QString oldName = r->getName();
|
||
|
while ( cont ) {
|
||
|
cont = false;
|
||
|
Q3PtrListIterator<KScoringRule> it( allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
if ( it.current() != r && it.current()->getName() == text ) {
|
||
|
kDebug(5100) <<"rule name" << text <<" is not unique";
|
||
|
text = KInputDialog::getText(
|
||
|
i18n( "Choose Another Rule Name" ),
|
||
|
i18n( "The rule name is already assigned, please choose another name:" ),
|
||
|
text );
|
||
|
cont = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( text != oldName ) {
|
||
|
r->setName( text );
|
||
|
emit changedRuleName( oldName, text );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringManager::deleteRule( KScoringRule *r )
|
||
|
{
|
||
|
int i = allRules.findRef( r );
|
||
|
if ( i != -1 ) {
|
||
|
allRules.remove();
|
||
|
emit changedRules();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringManager::editRule( KScoringRule *e, QWidget *w )
|
||
|
{
|
||
|
KScoringEditor *edit = KScoringEditor::createEditor( this, w );
|
||
|
edit->setRule( e );
|
||
|
edit->show();
|
||
|
delete edit;
|
||
|
}
|
||
|
|
||
|
void KScoringManager::moveRuleAbove( KScoringRule *above, KScoringRule *below )
|
||
|
{
|
||
|
int aindex = allRules.findRef( above );
|
||
|
int bindex = allRules.findRef( below );
|
||
|
if ( aindex <= 0 || bindex < 0 ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( aindex < bindex ) {
|
||
|
--bindex;
|
||
|
}
|
||
|
allRules.take( aindex );
|
||
|
allRules.insert( bindex, above );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::moveRuleBelow( KScoringRule *below, KScoringRule *above )
|
||
|
{
|
||
|
int bindex = allRules.findRef( below );
|
||
|
int aindex = allRules.findRef( above );
|
||
|
if ( bindex < 0 || bindex >= (int)allRules.count() - 1 || aindex < 0 ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( bindex < aindex ) {
|
||
|
--aindex;
|
||
|
}
|
||
|
allRules.take( bindex );
|
||
|
allRules.insert( aindex + 1, below );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::editorReady()
|
||
|
{
|
||
|
kDebug(5100) <<"emitting signal finishedEditing";
|
||
|
save();
|
||
|
emit finishedEditing();
|
||
|
}
|
||
|
|
||
|
KScoringRule *KScoringManager::copyRule( KScoringRule *r )
|
||
|
{
|
||
|
KScoringRule *rule = new KScoringRule( *r );
|
||
|
rule->setName( findUniqueName() );
|
||
|
addRuleInternal( rule );
|
||
|
return rule;
|
||
|
}
|
||
|
|
||
|
void KScoringManager::applyRules( ScorableGroup * )
|
||
|
{
|
||
|
kWarning(5100) <<"KScoringManager::applyRules(ScorableGroup* ) isn't implemented";
|
||
|
}
|
||
|
|
||
|
void KScoringManager::applyRules( ScorableArticle &article, const QString &group )
|
||
|
{
|
||
|
setGroup( group );
|
||
|
applyRules( article );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::applyRules( ScorableArticle &a )
|
||
|
{
|
||
|
Q3PtrListIterator<KScoringRule> it( isCacheValid() ? ruleList : allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
it.current()->applyRule( a );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void KScoringManager::initCache( const QString &g )
|
||
|
{
|
||
|
group = g;
|
||
|
ruleList.clear();
|
||
|
Q3PtrListIterator<KScoringRule> it(allRules);
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
if ( it.current()->matchGroup( group ) ) {
|
||
|
ruleList.append( it.current() );
|
||
|
}
|
||
|
}
|
||
|
kDebug(5100) <<"created cache for group" << group
|
||
|
<< "with" << ruleList.count() << "rules";
|
||
|
setCacheValid( true );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::setGroup( const QString &g )
|
||
|
{
|
||
|
if ( group != g ) {
|
||
|
initCache( g );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool KScoringManager::hasRulesForCurrentGroup()
|
||
|
{
|
||
|
return ruleList.count() != 0;
|
||
|
}
|
||
|
|
||
|
QStringList KScoringManager::getRuleNames()
|
||
|
{
|
||
|
QStringList l;
|
||
|
Q3PtrListIterator<KScoringRule> it( allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
l << it.current()->getName();
|
||
|
}
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
KScoringRule *KScoringManager::findRule( const QString &ruleName )
|
||
|
{
|
||
|
Q3PtrListIterator<KScoringRule> it( allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
if ( it.current()->getName() == ruleName ) {
|
||
|
return it;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool KScoringManager::setCacheValid( bool v )
|
||
|
{
|
||
|
bool res = cacheValid;
|
||
|
cacheValid = v;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
QString KScoringManager::findUniqueName() const
|
||
|
{
|
||
|
int nr = 0;
|
||
|
QString ret;
|
||
|
bool duplicated = false;
|
||
|
|
||
|
while ( nr < 99999999 ) {
|
||
|
nr++;
|
||
|
ret = i18n( "rule %1", nr );
|
||
|
|
||
|
duplicated = false;
|
||
|
Q3PtrListIterator<KScoringRule> it( allRules );
|
||
|
for ( ; it.current(); ++it ) {
|
||
|
if ( it.current()->getName() == ret ) {
|
||
|
duplicated = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !duplicated ) {
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
bool KScoringManager::hasFeature( int p )
|
||
|
{
|
||
|
switch ( p ) {
|
||
|
case ActionBase::SETSCORE:
|
||
|
return canScores();
|
||
|
case ActionBase::NOTIFY:
|
||
|
return canNotes();
|
||
|
case ActionBase::COLOR:
|
||
|
return canColors();
|
||
|
case ActionBase::MARKASREAD:
|
||
|
return canMarkAsRead();
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QStringList KScoringManager::getDefaultHeaders() const
|
||
|
{
|
||
|
QStringList l;
|
||
|
l.append( "Subject" );
|
||
|
l.append( "From" );
|
||
|
l.append( "Date" );
|
||
|
l.append( "Message-ID" );
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
void KScoringManager::pushRuleList()
|
||
|
{
|
||
|
stack.push( allRules );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::popRuleList()
|
||
|
{
|
||
|
stack.pop( allRules );
|
||
|
}
|
||
|
|
||
|
void KScoringManager::removeTOS()
|
||
|
{
|
||
|
stack.drop();
|
||
|
}
|
||
|
|
||
|
RuleStack::RuleStack()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
RuleStack::~RuleStack()
|
||
|
{}
|
||
|
|
||
|
void RuleStack::push( Q3PtrList<KScoringRule> &l )
|
||
|
{
|
||
|
kDebug(5100) <<"RuleStack::push pushing list with" << l.count() <<" rules";
|
||
|
KScoringManager::ScoringRuleList *l1 = new KScoringManager::ScoringRuleList;
|
||
|
for ( KScoringRule *r=l.first(); r != 0; r=l.next() ) {
|
||
|
l1->append( new KScoringRule( *r ) );
|
||
|
}
|
||
|
stack.push( l1 );
|
||
|
kDebug(5100) <<"now there are" << stack.count() <<" lists on the stack";
|
||
|
}
|
||
|
|
||
|
void RuleStack::pop( Q3PtrList<KScoringRule> &l )
|
||
|
{
|
||
|
top( l );
|
||
|
drop();
|
||
|
kDebug(5100) <<"RuleStack::pop pops list with" << l.count() <<" rules";
|
||
|
kDebug(5100) <<"now there are" << stack.count() <<" lists on the stack";
|
||
|
}
|
||
|
|
||
|
void RuleStack::top( Q3PtrList<KScoringRule> &l )
|
||
|
{
|
||
|
l.clear();
|
||
|
KScoringManager::ScoringRuleList *l1 = stack.top();
|
||
|
l = *l1;
|
||
|
}
|
||
|
|
||
|
void RuleStack::drop()
|
||
|
{
|
||
|
kDebug(5100) <<"drop: now there are" << stack.count() <<" lists on the stack";
|
||
|
stack.remove();
|
||
|
}
|
||
|
|