/* kscoring.cpp Copyright (c) 2001 Mathias Waack Copyright (C) 2005 by Volker Krause Author: Mathias Waack 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 TQT_NO_ASCII_CAST #endif #undef TQT_NO_COMPAT #include #include #include #include #include #include #include #include #include #include #include #include "kscoring.h" #include "kscoringeditor.h" //---------------------------------------------------------------------------- // a small function to encode attribute values, code stolen from TQDom static TQString toXml(const TQString& str) { TQString tmp(str); uint len = tmp.length(); uint i = 0; while ( i < len ) { if (tmp[(int)i] == '<') { tmp.tqreplace(i, 1, "<"); len += 3; i += 4; } else if (tmp[(int)i] == '"') { tmp.tqreplace(i, 1, """); len += 5; i += 6; } else if (tmp[(int)i] == '&') { tmp.tqreplace(i, 1, "&"); len += 4; i += 5; } else if (tmp[(int)i] == '>') { tmp.tqreplace(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(TQWidget* p) : KDialogBase(p,"notify action dialog",true,"Notify Message",Close,Close,true) { TQFrame *f = makeMainWidget(); TQVBoxLayout *topL = new TQVBoxLayout(f); note = new TQLabel(f); note->setTextFormat(RichText); topL->addWidget(note); TQCheckBox *check = new TQCheckBox(i18n("Do not show this message again"),f); check->setChecked(true); topL->addWidget(check); connect(check,TQT_SIGNAL(toggled(bool)),TQT_SLOT(slotShowAgainToggled(bool))); } void NotifyDialog::slotShowAgainToggled(bool flag) { dict.tqreplace(msg,!flag); kdDebug(5100) << "note \"" << note << "\" will popup again: " << flag << endl; } void NotifyDialog::display(ScorableArticle& a, const TQString& s) { kdDebug(5100) << "displaying message" << endl; if (!me) me = new NotifyDialog(); me->msg = s; NotesMap::Iterator i = dict.tqfind(s); if (i == dict.end() || i.data()) { TQString msg = i18n("Article\n%1
%2
caused the following" " note to appear:
%3"). arg(a.from()). arg(a.subject()). arg(s); me->note->setText(msg); if ( i == dict.end() ) i = dict.tqreplace(s,false); me->adjustSize(); me->exec(); } } //---------------------------------------------------------------------------- ScorableArticle::~ScorableArticle() { } void ScorableArticle::displayMessage(const TQString& note) { NotifyDialog::display(*this,note); } //---------------------------------------------------------------------------- ScorableGroup::~ScorableGroup() { } // the base class for all actions ActionBase::ActionBase() { kdDebug(5100) << "new Action " << this << endl; } ActionBase::~ActionBase() { kdDebug(5100) << "delete Action " << this << endl; } TQStringList ActionBase::userNames() { TQStringList l; l << userName(SETSCORE); l << userName(NOTIFY); l << userName(COLOR); l << userName(MARKASREAD); return l; } ActionBase* ActionBase::factory(int type, const TQString &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: kdWarning(5100) << "unknown type " << type << " in ActionBase::factory()" << endl; return 0; } } TQString 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: kdWarning(5100) << "unknown type " << type << " in ActionBase::userName()" << endl; return 0; } } int ActionBase::getTypeForName(const TQString& 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 { kdWarning(5100) << "unknown type string " << name << " in ActionBase::getTypeForName()" << endl; return -1; } } int ActionBase::getTypeForUserName(const TQString& 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 { kdWarning(5100) << "unknown type string " << name << " in ActionBase::getTypeForUserName()" << endl; return -1; } } // the set score action ActionSetScore::ActionSetScore(short v) : val(v) { } ActionSetScore::ActionSetScore(const TQString& s) { val = s.toShort(); } ActionSetScore::ActionSetScore(const ActionSetScore& as) : ActionBase(), val(as.val) { } ActionSetScore::~ActionSetScore() { } TQString ActionSetScore::toString() const { TQString a; a += ""; 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 TQColor& c) : ActionBase(), color(c) { } ActionColor::ActionColor(const TQString& s) : ActionBase() { setValue(s); } ActionColor::ActionColor(const ActionColor& a) : ActionBase(), color(a.color) { } ActionColor::~ActionColor() {} TQString ActionColor::toString() const { TQString a; a += ""; 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 TQString& s) { note = s; } ActionNotify::ActionNotify(const ActionNotify& an) : ActionBase() { note = an.note; } TQString ActionNotify::toString() const { return ""; } 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 ); } TQString ActionMarkAsRead::toString() const { return ""; } 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 TQString& note) { article_list *l = notifyList.tqfind(note); if (!l) { notifyList.insert(note,new article_list); l = notifyList.tqfind(note); } article_info i; i.from = a.from(); i.subject = a.subject(); l->append(i); } TQString NotifyCollection::collection() const { TQString notifyCollection = i18n("

List of collected notes

"); notifyCollection += "

    "; // first look thru the notes and create one string TQDictIterator it(notifyList); for(;it.current();++it) { const TQString& note = it.currentKey(); notifyCollection += "
  • " + note + "
      "; article_list* alist = it.current(); article_list::Iterator ait; for(ait = alist->begin(); ait != alist->end(); ++ait) { notifyCollection += "
    • From: " + (*ait).from + "
      "; notifyCollection += "Subject: " + (*ait).subject; } notifyCollection += "
    "; } notifyCollection += "
"; return notifyCollection; } void NotifyCollection::displayCollection(TQWidget *p) const { //KMessageBox::information(p,collection(),i18n("Collected Notes")); KDialogBase *dlg = new KDialogBase( p, 0, false, i18n("Collected Notes"), KDialogBase::Close, KDialogBase::Close ); TQTextView *text = new TQTextView(dlg); text->setText(collection()); dlg->setMainWidget(text); dlg->setMinimumWidth(300); dlg->setMinimumHeight(300); dlg->show(); } //---------------------------------------------------------------------------- KScoringExpression::KScoringExpression(const TQString& h, const TQString& t, const TQString& n, const TQString& ng) : header(h), expr_str(n) { if (t == "MATCH" ) { cond = MATCH; expr.setPattern(expr_str); expr.setCaseSensitive(false); } else if ( t == "MATCHCS" ) { cond = MATCHCS; expr.setPattern( expr_str ); expr.setCaseSensitive( true ); } else if (t == "CONTAINS" ) cond = CONTAINS; else if (t == "ETQUALS" ) cond = ETQUALS; else if (t == "GREATER") { cond = GREATER; expr_int = expr_str.toInt(); } else if (t == "SMALLER") { cond = SMALLER; expr_int = expr_str.toInt(); } else { kdDebug(5100) << "unknown match type in new expression" << endl; } neg = ng.toInt(); c_header = header.latin1(); kdDebug(5100) << "new expr: " << c_header << " " << t << " " << expr_str << " " << neg << endl; } // static int KScoringExpression::getConditionForName(const TQString& 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(ETQUALS)) return ETQUALS; else if (s == getNameForCondition(SMALLER)) return SMALLER; else if (s == getNameForCondition(GREATER)) return GREATER; else { kdWarning(5100) << "unknown condition name " << s << " in KScoringExpression::getConditionForName()" << endl; return -1; } } // static TQString 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 ETQUALS: return i18n("Is Exactly the Same As"); case SMALLER: return i18n("Less Than"); case GREATER: return i18n("Greater Than"); default: kdWarning(5100) << "unknown condition " << cond << " in KScoringExpression::getNameForCondition()" << endl; return ""; } } // static TQStringList KScoringExpression::conditionNames() { TQStringList l; l << getNameForCondition(CONTAINS); l << getNameForCondition(MATCH); l << getNameForCondition(MATCHCS); l << getNameForCondition(ETQUALS); l << getNameForCondition(SMALLER); l << getNameForCondition(GREATER); return l; } // static TQStringList KScoringExpression::headerNames() { TQStringList 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 { //kdDebug(5100) << "matching against header " << c_header << endl; bool res = true; TQString head; if (header == "From") head = a.from(); else if (header == "Subject") head = a.subject(); else head = a.getHeaderByType(c_header); if (!head.isEmpty()) { switch (cond) { case ETQUALS: res = (head.lower() == expr_str.lower()); break; case CONTAINS: res = (head.lower().tqfind(expr_str.lower()) >= 0); break; case MATCH: case MATCHCS: res = (expr.search(head)!=-1); break; case GREATER: res = (head.toInt() > expr_int); break; case SMALLER: res = (head.toInt() < expr_int); break; default: kdDebug(5100) << "unknown match" << endl; res = false; } } else res = false; // kdDebug(5100) << "matching returns " << res << endl; return (neg)?!res:res; } void KScoringExpression::write(TQTextStream& st) const { st << toString(); } TQString KScoringExpression::toString() const { // kdDebug(5100) << "KScoringExpression::toString() starts" << endl; // kdDebug(5100) << "header is " << header << endl; // kdDebug(5100) << "expr is " << expr_str << endl; // kdDebug(5100) << "neg is " << neg << endl; // kdDebug(5100) << "type is " << getType() << endl; TQString e; e += ""; // kdDebug(5100) << "KScoringExpression::toString() finished" << endl; return e; } TQString KScoringExpression::getTypeString() const { return KScoringExpression::getTypeString(cond); } TQString KScoringExpression::getTypeString(int cond) { switch (cond) { case CONTAINS: return "CONTAINS"; case MATCH: return "MATCH"; case MATCHCS: return "MATCHCS"; case ETQUALS: return "ETQUALS"; case SMALLER: return "SMALLER"; case GREATER: return "GREATER"; default: kdWarning(5100) << "unknown cond " << cond << " in KScoringExpression::getTypeString()" << endl; return ""; } } int KScoringExpression::getType() const { return cond; } //---------------------------------------------------------------------------- KScoringRule::KScoringRule(const TQString& n ) : name(n), link(AND) { expressions.setAutoDelete(true); actions.setAutoDelete(true); } KScoringRule::KScoringRule(const KScoringRule& r) { kdDebug(5100) << "copying rule " << r.getName() << endl; name = r.getName(); expressions.setAutoDelete(true); actions.setAutoDelete(true); // copy expressions expressions.clear(); const ScoreExprList& rexpr = r.expressions; TQPtrListIterator it(rexpr); for ( ; it.current(); ++it ) { KScoringExpression *t = new KScoringExpression(**it); expressions.append(t); } // copy actions actions.clear(); const ActionList& ract = r.actions; TQPtrListIterator 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) { kdDebug(5100) << "KScoringRule::addExpression" << endl; expressions.append(expr); } void KScoringRule::addAction(int type, const TQString& val) { ActionBase *action = ActionBase::factory(type,val); addAction(action); } void KScoringRule::addAction(ActionBase* a) { kdDebug(5100) << "KScoringRule::addAction() " << a->toString() << endl; actions.append(a); } void KScoringRule::setLinkMode(const TQString& l) { if (l == "OR") link = OR; else link = AND; } void KScoringRule::setExpire(const TQString& e) { if (e != "never") { TQStringList l = TQStringList::split("-",e); Q_ASSERT( l.count() == 3 ); expires.setYMD( (*(l.at(0))).toInt(), (*(l.at(1))).toInt(), (*(l.at(2))).toInt()); } kdDebug(5100) << "Rule " << getName() << " expires at " << getExpireDateString() << endl; } bool KScoringRule::matchGroup(const TQString& group) const { for(GroupList::ConstIterator i=groups.begin(); i!=groups.end();++i) { TQRegExp e(*i); if (e.search(group, 0) != -1 && (uint)e.matchedLength() == group.length()) return true; } return false; } void KScoringRule::applyAction(ScorableArticle& a) const { TQPtrListIterator it(actions); for(; it.current(); ++it) { it.current()->apply(a); } } void KScoringRule::applyRule(ScorableArticle& a) const { // kdDebug(5100) << "checking rule " << name << endl; // kdDebug(5100) << " for article from " // << a->from()->asUnicodeString() // << endl; bool oper_and = (link == AND); bool res = true; TQPtrListIterator it(expressions); //kdDebug(5100) << "checking " << expressions.count() << " expressions" << endl; 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 TQString& s*/, const TQString& g) const { // check if one of the groups match for (TQStringList::ConstIterator i = groups.begin(); i != groups.end(); ++i) { if (TQRegExp(*i).search(g) != -1) { applyRule(a); return; } } } void KScoringRule::write(TQTextStream& s) const { s << toString(); } TQString KScoringRule::toString() const { //kdDebug(5100) << "KScoringRule::toString() starts" << endl; TQString r; r += ""; //kdDebug(5100) << "building grouplist..." << endl; for(GroupList::ConstIterator i=groups.begin();i!=groups.end();++i) { r += ""; } //kdDebug(5100) << "building expressionlist..." << endl; TQPtrListIterator eit(expressions); for (; eit.current(); ++eit) { r += eit.current()->toString(); } //kdDebug(5100) << "building actionlist..." << endl; TQPtrListIterator ait(actions); for (; ait.current(); ++ait) { r += ait.current()->toString(); } r += ""; //kdDebug(5100) << "KScoringRule::toString() finished" << endl; return r; } TQString KScoringRule::getLinkModeName() const { switch (link) { case AND: return "AND"; case OR: return "OR"; default: return "AND"; } } TQString KScoringRule::getExpireDateString() const { if (expires.isNull()) return "never"; else { return TQString::number(expires.year()) + TQString("-") + TQString::number(expires.month()) + TQString("-") + TQString::number(expires.day()); } } bool KScoringRule::isExpired() const { return (expires.isValid() && (expires < TQDate::tqcurrentDate())); } //---------------------------------------------------------------------------- KScoringManager::KScoringManager(const TQString& appName) : cacheValid(false)//, _s(0) { 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() { TQDomDocument sdoc("Scorefile"); TQFile f( mFilename ); if ( !f.open( IO_ReadOnly ) ) return; if ( !sdoc.setContent( &f ) ) { f.close(); kdDebug(5100) << "loading the scorefile failed" << endl; return; } f.close(); kdDebug(5100) << "loaded the scorefile, creating internal representation" << endl; allRules.clear(); createInternalFromXML(sdoc); expireRules(); kdDebug(5100) << "ready, got " << allRules.count() << " rules" << endl; } void KScoringManager::save() { kdDebug(5100) << "KScoringManager::save() starts" << endl; TQFile f( mFilename ); if ( !f.open( IO_WriteOnly ) ) return; TQTextStream stream(&f); stream.setEncoding(TQTextStream::Unicode); kdDebug(5100) << "KScoringManager::save() creating xml" << endl; createXMLfromInternal().save(stream,2); kdDebug(5100) << "KScoringManager::save() finished" << endl; } TQDomDocument KScoringManager::createXMLfromInternal() { // I was'nt able to create a TQDomDocument in memory:( // so I write the content into a string, which is really stupid TQDomDocument sdoc("Scorefile"); TQString ss; // scorestring ss += ""; ss += toString(); ss += "\n"; kdDebug(5100) << "KScoringManager::createXMLfromInternal():" << endl << ss << endl; sdoc.setContent(ss); return sdoc; } TQString KScoringManager::toString() const { TQString s; s += "\n"; TQPtrListIterator 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()) { kdDebug(5100) << "Rule " << cR->getName() << " is expired, deleting it" << endl; allRules.remove(); } } } void KScoringManager::createInternalFromXML(TQDomNode n) { static KScoringRule *cR = 0; // the currentRule // the XML file was parsed and now we simply traverse the resulting tree if ( !n.isNull() ) { kdDebug(5100) << "inspecting node of type " << n.nodeType() << " named " << n.toElement().tagName() << endl; switch (n.nodeType()) { case TQDomNode::DocumentNode: { // the document itself break; } case TQDomNode::ElementNode: { // Server, Newsgroup, Rule, Expression, Action TQDomElement e = n.toElement(); //kdDebug(5100) << "The name of the element is " //<< e.tagName().latin1() << endl; TQString 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: // kdDebug(5100) << "unknown DomNode::type" << endl; ; } TQDomNodeList nodelist = n.childNodes(); unsigned cnt = nodelist.count(); //kdDebug(5100) << "recursive checking " << cnt << " nodes" << endl; for (unsigned i=0;iaddGroup( group ); rule->addExpression( new KScoringExpression("From","CONTAINS", a.from(),"0")); if (score) rule->addAction(new ActionSetScore(score)); rule->setExpireDate(TQDate::tqcurrentDate().addDays(30)); addRule(rule); KScoringEditor *edit = KScoringEditor::createEditor(this); edit->setRule(rule); edit->show(); setCacheValid(false); return rule; } KScoringRule* KScoringManager::addRule(KScoringRule* expr) { int i = allRules.tqfindRef(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(); kdDebug(5100) << "KScoringManager::addRuleInternal " << e->getName() << endl; } void KScoringManager::cancelNewRule(KScoringRule *r) { // if e was'nt previously added to the list of rules, we delete it int i = allRules.tqfindRef(r); if (i == -1) { kdDebug(5100) << "deleting rule " << r->getName() << endl; deleteRule(r); } else { kdDebug(5100) << "rule " << r->getName() << " not deleted" << endl; } } void KScoringManager::setRuleName(KScoringRule *r, const TQString& s) { bool cont = true; TQString text = s; TQString oldName = r->getName(); while (cont) { cont = false; TQPtrListIterator it(allRules); for (; it.current(); ++it) { if ( it.current() != r && it.current()->getName() == text ) { kdDebug(5100) << "rule name " << text << " is not unique" << endl; 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.tqfindRef(r); if (i != -1) { allRules.remove(); emit changedRules(); } } void KScoringManager::editRule(KScoringRule *e, TQWidget *w) { KScoringEditor *edit = KScoringEditor::createEditor(this, w); edit->setRule(e); edit->show(); delete edit; } void KScoringManager::moveRuleAbove( KScoringRule *above, KScoringRule *below ) { int aindex = allRules.tqfindRef( above ); int bindex = allRules.tqfindRef( 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.tqfindRef( below ); int aindex = allRules.tqfindRef( 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() { kdDebug(5100) << "emitting signal finishedEditing" << endl; save(); emit finishedEditing(); } KScoringRule* KScoringManager::copyRule(KScoringRule *r) { KScoringRule *rule = new KScoringRule(*r); rule->setName(findUniqueName()); addRuleInternal(rule); return rule; } void KScoringManager::applyRules(ScorableGroup* ) { kdWarning(5100) << "KScoringManager::applyRules(ScorableGroup* ) isn't implemented" << endl; } void KScoringManager::applyRules(ScorableArticle& article, const TQString& group) { setGroup(group); applyRules(article); } void KScoringManager::applyRules(ScorableArticle& a) { TQPtrListIterator it(isCacheValid()? ruleList : allRules); for( ; it.current(); ++it) { it.current()->applyRule(a); } } void KScoringManager::initCache(const TQString& g) { group = g; ruleList.clear(); TQPtrListIterator it(allRules); for (; it.current(); ++it) { if ( it.current()->matchGroup(group) ) { ruleList.append(it.current()); } } kdDebug(5100) << "created cache for group " << group << " with " << ruleList.count() << " rules" << endl; setCacheValid(true); } void KScoringManager::setGroup(const TQString& g) { if (group != g) initCache(g); } bool KScoringManager::hasRulesForCurrentGroup() { return ruleList.count() != 0; } TQStringList KScoringManager::getRuleNames() { TQStringList l; TQPtrListIterator it(allRules); for( ; it.current(); ++it) { l << it.current()->getName(); } return l; } KScoringRule* KScoringManager::findRule(const TQString& ruleName) { TQPtrListIterator 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; } TQString KScoringManager::findUniqueName() const { int nr = 0; TQString ret; bool duplicated=false; while (nr < 99999999) { nr++; ret = i18n("rule %1").tqarg(nr); duplicated=false; TQPtrListIterator 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; } } TQStringList KScoringManager::getDefaultHeaders() const { TQStringList 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(TQPtrList& l) { kdDebug(5100) << "RuleStack::push pushing list with " << l.count() << " rules" << endl; KScoringManager::ScoringRuleList *l1 = new KScoringManager::ScoringRuleList; for ( KScoringRule *r=l.first(); r != 0; r=l.next() ) { l1->append(new KScoringRule(*r)); } stack.push(l1); kdDebug(5100) << "now there are " << stack.count() << " lists on the stack" << endl; } void RuleStack::pop(TQPtrList& l) { top(l); drop(); kdDebug(5100) << "RuleStack::pop pops list with " << l.count() << " rules" << endl; kdDebug(5100) << "now there are " << stack.count() << " lists on the stack" << endl; } void RuleStack::top(TQPtrList& l) { l.clear(); KScoringManager::ScoringRuleList *l1 = stack.top(); l = *l1; } void RuleStack::drop() { kdDebug(5100) << "drop: now there are " << stack.count() << " lists on the stack" << endl; stack.remove(); } #include "kscoring.moc"