2 KNode, the KDE newsreader
3 Copyright (c) 1999-2006 the KNode authors.
4 See file AUTHORS for details
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 You should have received a copy of the GNU General Public License
11 along with this program; if not, write to the Free Software Foundation,
12 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
15 #include <kstandarddirs.h>
17 #include <kconfiggroup.h>
23 #include "utilities.h"
24 #include "knarticlefilter.h"
26 //=============================================================================================================
29 // the names of our default filters
30 static const char *defFil
[] = { "all","unread","new","watched","threads with unread",
31 "threads with new","own articles","threads with own articles", 0 };
34 i18nc("default filter name","all");
35 i18nc("default filter name","unread");
36 i18nc("default filter name","new");
37 i18nc("default filter name","watched");
38 i18nc("default filter name","threads with unread");
39 i18nc("default filter name","threads with new");
40 i18nc("default filter name","own articles");
41 i18nc("default filter name","threads with own articles");
45 //=============================================================================================================
48 KNArticleFilter::KNArticleFilter(int id
)
49 : i_d(id
), c_ount(0), l_oaded(false), e_nabled(true), translateName(true), s_earchFilter(false), apon(articles
)
54 // constructs a copy of org
55 KNArticleFilter::KNArticleFilter(const KNArticleFilter
& org
)
56 : i_d(-1), c_ount(0), l_oaded(false), e_nabled(org
.e_nabled
), translateName(true), s_earchFilter(org
.s_earchFilter
), apon(org
.apon
)
62 subject
= org
.subject
;
64 messageId
= org
.messageId
;
65 references
= org
.messageId
;
70 KNArticleFilter::~KNArticleFilter()
75 bool KNArticleFilter::loadInfo()
78 QString
fname( KStandardDirs::locate( "data",
79 QString( "knode/filters/%1.fltr" ).arg( i_d
) ) );
83 KConfig
conf( fname
, KConfig::SimpleConfig
);
85 KConfigGroup group
= conf
.group("GENERAL");
86 n_ame
=group
.readEntry("name");
87 translateName
= group
.readEntry("Translate_Name",true);
88 e_nabled
=group
.readEntry("enabled", true);
89 apon
=(ApOn
) group
.readEntry("applyOn", 0);
97 void KNArticleFilter::load()
99 QString
fname(KStandardDirs::locate( "data", QString( "knode/filters/%1.fltr" ).arg( i_d
) ) );
103 KConfig
conf( fname
, KConfig::SimpleConfig
);
105 KConfigGroup group
= conf
.group("STATUS");
108 group
= conf
.group("SCORE");
111 group
= conf
.group("AGE");
114 group
= conf
.group("LINES");
117 group
= conf
.group("SUBJECT");
120 group
= conf
.group("FROM");
123 group
= conf
.group("MESSAGEID");
124 messageId
.load(group
);
126 group
= conf
.group("REFERENCES");
127 references
.load(group
);
131 kDebug(5003) <<"KNMessageFilter: filter loaded \"" << n_ame
<<"\"";
137 void KNArticleFilter::save()
141 QString
dir( KStandardDirs::locateLocal( "data", "knode/filters/" ) );
143 KNHelper::displayInternalFileError();
146 KConfig
conf(dir
+QString("%1.fltr").arg(i_d
), KConfig::SimpleConfig
);
148 KConfigGroup group
= conf
.group("GENERAL");
149 group
.writeEntry("name", QString(n_ame
));
150 group
.writeEntry("Translate_Name",translateName
);
151 group
.writeEntry("enabled", e_nabled
);
152 group
.writeEntry("applyOn", (int) apon
);
154 group
= conf
.group("STATUS");
157 group
= conf
.group("SCORE");
160 group
= conf
.group("AGE");
163 group
= conf
.group("LINES");
166 group
= conf
.group("SUBJECT");
169 group
= conf
.group("FROM");
172 group
= conf
.group("MESSAGEID");
173 messageId
.save(group
);
175 group
= conf
.group("REFERENCES");
176 references
.save(group
);
178 kDebug(5003) <<"KNMessageFilter: filter saved \"" << n_ame
<<"\"";
183 void KNArticleFilter::doFilter( KNGroup::Ptr g
)
186 KNRemoteArticle::Ptr art
, ref
;
187 KNRemoteArticle::List orphant_threads
;
194 subject
.expand( g
.get() ); // replace placeholders
195 from
.expand( g
.get() );
196 messageId
.expand( g
.get() );
197 references
.expand( g
.get() );
199 for(int idx
=0; idx
<g
->length(); idx
++) {
201 art
->setFiltered(false);
202 art
->setVisibleFollowUps(false);
203 art
->setDisplayedReference( KNRemoteArticle::Ptr() );
206 for(int idx
=0; idx
<g
->length(); idx
++) {
210 if(!art
->isFiltered() && applyFilter(art
) && apon
==threads
) {
214 ref
->setFilterResult(true);
215 ref
->setFiltered(true);
216 if ( idRef
==ref
->idRef() ) break;
223 for(int idx
=0; idx
<g
->length(); idx
++) {
227 if( apon
==threads
&& !art
->filterResult() ) {
230 while(idRef
!=0 && !inThread
) {
232 inThread
=ref
->filterResult();
235 art
->setFilterResult(inThread
);
238 if(art
->filterResult()) {
241 ref
= ( art
->idRef() > 0 ) ? g
->byId( art
->idRef() ) : KNRemoteArticle::Ptr();
242 while(ref
&& !ref
->filterResult())
243 ref
= ( ref
->idRef() > 0 ) ? g
->byId( ref
->idRef() ) : KNRemoteArticle::Ptr();
245 art
->setDisplayedReference(ref
);
247 ref
->setVisibleFollowUps(true);
248 else if(art
->idRef()>0) {
249 orphant_threads
.append(art
);
255 if( orphant_threads
.count() > 0 ) {
256 // try to merge orphant threads by subject
257 KNRemoteArticle::List same_subjects
;
259 for ( KNRemoteArticle::List::Iterator it
= orphant_threads
.begin(); it
!= orphant_threads
.end(); ++it
) {
260 if ( (*it
)->displayedReference() ) // already processed
263 s
= (*it
)->subject()->asUnicodeString();
264 same_subjects
.clear();
265 for ( KNRemoteArticle::List::Iterator it2
= orphant_threads
.begin(); it2
!= orphant_threads
.end(); ++it2
) {
266 if ( (*it2
) != (*it
) && (*it2
)->subject()->asUnicodeString() == s
)
267 same_subjects
.append( (*it2
) );
270 (*it
)->setVisibleFollowUps( (*it
)->hasVisibleFollowUps() || same_subjects
.count() > 0 );
271 for ( KNRemoteArticle::List::Iterator it2
= same_subjects
.begin(); it2
!= same_subjects
.end(); ++it2
) {
272 (*it2
)->setDisplayedReference( (*it
) );
278 kDebug(5003) <<"KNArticleFilter::doFilter() : matched" << c_ount
279 << "articles , merged" << mergeCnt
280 << "threads by subject";
285 void KNArticleFilter::doFilter( KNFolder::Ptr f
)
288 KNLocalArticle::Ptr art
;
292 subject
.expand(0); // replace placeholders
295 references
.expand(0);
297 for(int idx
=0; idx
<f
->length(); idx
++) {
299 if (applyFilter(art
))
305 // *tries* to translate the name
306 QString
KNArticleFilter::translatedName()
309 // major hack alert !!!
310 if (!n_ame
.isEmpty()) {
311 if (i18nc("default filter name",n_ame
.toLocal8Bit())!=n_ame
.toLocal8Bit().data()) // try to guess if this english or not
312 return i18nc("default filter name",n_ame
.toLocal8Bit());
323 // *tries* to retranslate the name to english
324 void KNArticleFilter::setTranslatedName(const QString
&s
)
326 bool retranslated
= false;
327 for (const char **c
=defFil
;(*c
)!=0;c
++) // ok, try if it matches any of the standard filter names
328 if (s
==i18nc("default filter name",*c
)) {
329 n_ame
= QString::fromLatin1(*c
);
334 if (!retranslated
) { // ok, we give up and store the maybe non-english string
336 translateName
= false; // and don't try to translate it, so a german user *can* use the original english name
338 translateName
= true;
343 bool KNArticleFilter::applyFilter( KNRemoteArticle::Ptr a
)
347 if(result
) result
=status
.doFilter(a
);
348 if(result
) result
=score
.doFilter(a
->score());
349 if(result
) result
=lines
.doFilter(a
->lines()->numberOfLines());
350 if(result
) result
=age
.doFilter(a
->date()->ageInDays());
351 if(result
) result
=subject
.doFilter(a
->subject()->asUnicodeString());
354 if ( !a
->from()->isEmpty() )
355 tmp
= a
->from()->displayNames().first() + QLatin1String("##")
356 + QString::fromLatin1( a
->from()->addresses().first() );
357 result
=from
.doFilter(tmp
);
359 if(result
) result
=messageId
.doFilter(a
->messageID()->asUnicodeString());
360 if(result
) result
=references
.doFilter(a
->references()->asUnicodeString());
362 a
->setFilterResult(result
);
363 a
->setFiltered(true);
369 bool KNArticleFilter::applyFilter( KNLocalArticle::Ptr a
)
373 if (isSearchFilter()) {
374 if(result
) result
=lines
.doFilter(a
->lines()->numberOfLines());
375 if(result
) result
=age
.doFilter(a
->date()->ageInDays());
376 if(result
) result
=subject
.doFilter(a
->subject()->asUnicodeString());
379 if ( !a
->from()->isEmpty() )
380 tmp
= a
->from()->displayNames().first() + QLatin1String("##")
381 + QString::fromLatin1( a
->from()->addresses().first() );
382 result
=from
.doFilter(tmp
);
384 if(result
) result
=messageId
.doFilter(a
->messageID()->asUnicodeString());
385 if(result
) result
=references
.doFilter(a
->references()->asUnicodeString());
388 a
->setFilterResult(result
);