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",QString( "knode/filters/%1.fltr" ).arg(i_d
) ) );
82 KConfig
conf( fname
, KConfig::SimpleConfig
);
84 KConfigGroup group
= conf
.group("GENERAL");
85 n_ame
=group
.readEntry("name");
86 translateName
= group
.readEntry("Translate_Name",true);
87 e_nabled
=group
.readEntry("enabled", true);
88 apon
=(ApOn
) group
.readEntry("applyOn", 0);
96 void KNArticleFilter::load()
98 QString
fname(KStandardDirs::locate("data",QString( "knode/filters/%1.fltr").arg(i_d
) ) );
102 KConfig
conf( fname
, KConfig::SimpleConfig
);
104 KConfigGroup group
= conf
.group("STATUS");
107 group
= conf
.group("SCORE");
110 group
= conf
.group("AGE");
113 group
= conf
.group("LINES");
116 group
= conf
.group("SUBJECT");
119 group
= conf
.group("FROM");
122 group
= conf
.group("MESSAGEID");
123 messageId
.load(group
);
125 group
= conf
.group("REFERENCES");
126 references
.load(group
);
130 kDebug(5003) <<"KNMessageFilter: filter loaded \"" << n_ame
<<"\"";
136 void KNArticleFilter::save()
140 QString
dir(KStandardDirs::locateLocal("data","knode/")+"filters/");
142 KNHelper::displayInternalFileError();
145 KConfig
conf(dir
+QString("%1.fltr").arg(i_d
), KConfig::SimpleConfig
);
147 KConfigGroup group
= conf
.group("GENERAL");
148 group
.writeEntry("name", QString(n_ame
));
149 group
.writeEntry("Translate_Name",translateName
);
150 group
.writeEntry("enabled", e_nabled
);
151 group
.writeEntry("applyOn", (int) apon
);
153 group
= conf
.group("STATUS");
156 group
= conf
.group("SCORE");
159 group
= conf
.group("AGE");
162 group
= conf
.group("LINES");
165 group
= conf
.group("SUBJECT");
168 group
= conf
.group("FROM");
171 group
= conf
.group("MESSAGEID");
172 messageId
.save(group
);
174 group
= conf
.group("REFERENCES");
175 references
.save(group
);
177 kDebug(5003) <<"KNMessageFilter: filter saved \"" << n_ame
<<"\"";
182 void KNArticleFilter::doFilter(KNGroup
*g
)
185 KNRemoteArticle
*art
=0, *ref
=0;
186 KNRemoteArticle::List orphant_threads
;
193 subject
.expand(g
); // replace placeholders
196 references
.expand(g
);
198 for(int idx
=0; idx
<g
->length(); idx
++) {
200 art
->setFiltered(false);
201 art
->setVisibleFollowUps(false);
202 art
->setDisplayedReference(0);
205 for(int idx
=0; idx
<g
->length(); idx
++) {
209 if(!art
->isFiltered() && applyFilter(art
) && apon
==threads
) {
213 ref
->setFilterResult(true);
214 ref
->setFiltered(true);
215 if ( idRef
==ref
->idRef() ) break;
222 for(int idx
=0; idx
<g
->length(); idx
++) {
226 if( apon
==threads
&& !art
->filterResult() ) {
229 while(idRef
!=0 && !inThread
) {
231 inThread
=ref
->filterResult();
234 art
->setFilterResult(inThread
);
237 if(art
->filterResult()) {
240 ref
= (art
->idRef()>0) ? g
->byId(art
->idRef()) : 0;
241 while(ref
&& !ref
->filterResult())
242 ref
= (ref
->idRef()>0) ? g
->byId(ref
->idRef()) : 0;
244 art
->setDisplayedReference(ref
);
246 ref
->setVisibleFollowUps(true);
247 else if(art
->idRef()>0) {
248 orphant_threads
.append(art
);
254 if( orphant_threads
.count() > 0 ) {
255 // try to merge orphant threads by subject
256 KNRemoteArticle::List same_subjects
;
258 for ( KNRemoteArticle::List::Iterator it
= orphant_threads
.begin(); it
!= orphant_threads
.end(); ++it
) {
259 if ( (*it
)->displayedReference() ) // already processed
262 s
= (*it
)->subject()->asUnicodeString();
263 same_subjects
.clear();
264 for ( KNRemoteArticle::List::Iterator it2
= orphant_threads
.begin(); it2
!= orphant_threads
.end(); ++it2
) {
265 if ( (*it2
) != (*it
) && (*it2
)->subject()->asUnicodeString() == s
)
266 same_subjects
.append( (*it2
) );
269 (*it
)->setVisibleFollowUps( (*it
)->hasVisibleFollowUps() || same_subjects
.count() > 0 );
270 for ( KNRemoteArticle::List::Iterator it2
= same_subjects
.begin(); it2
!= same_subjects
.end(); ++it2
) {
271 (*it2
)->setDisplayedReference( (*it
) );
277 kDebug(5003) <<"KNArticleFilter::doFilter() : matched" << c_ount
278 << "articles , merged" << mergeCnt
279 << "threads by subject";
284 void KNArticleFilter::doFilter(KNFolder
*f
)
287 KNLocalArticle
*art
=0;
291 subject
.expand(0); // replace placeholders
294 references
.expand(0);
296 for(int idx
=0; idx
<f
->length(); idx
++) {
298 if (applyFilter(art
))
304 // *tries* to translate the name
305 QString
KNArticleFilter::translatedName()
308 // major hack alert !!!
309 if (!n_ame
.isEmpty()) {
310 if (i18nc("default filter name",n_ame
.toLocal8Bit())!=n_ame
.toLocal8Bit().data()) // try to guess if this english or not
311 return i18nc("default filter name",n_ame
.toLocal8Bit());
322 // *tries* to retranslate the name to english
323 void KNArticleFilter::setTranslatedName(const QString
&s
)
325 bool retranslated
= false;
326 for (const char **c
=defFil
;(*c
)!=0;c
++) // ok, try if it matches any of the standard filter names
327 if (s
==i18nc("default filter name",*c
)) {
328 n_ame
= QString::fromLatin1(*c
);
333 if (!retranslated
) { // ok, we give up and store the maybe non-english string
335 translateName
= false; // and don't try to translate it, so a german user *can* use the original english name
337 translateName
= true;
342 bool KNArticleFilter::applyFilter(KNRemoteArticle
*a
)
346 if(result
) result
=status
.doFilter(a
);
347 if(result
) result
=score
.doFilter(a
->score());
348 if(result
) result
=lines
.doFilter(a
->lines()->numberOfLines());
349 if(result
) result
=age
.doFilter(a
->date()->ageInDays());
350 if(result
) result
=subject
.doFilter(a
->subject()->asUnicodeString());
353 if ( !a
->from()->isEmpty() )
354 tmp
= a
->from()->displayNames().first() + QLatin1String("##")
355 + QString::fromLatin1( a
->from()->addresses().first() );
356 result
=from
.doFilter(tmp
);
358 if(result
) result
=messageId
.doFilter(a
->messageID()->asUnicodeString());
359 if(result
) result
=references
.doFilter(a
->references()->asUnicodeString());
361 a
->setFilterResult(result
);
362 a
->setFiltered(true);
368 bool KNArticleFilter::applyFilter(KNLocalArticle
*a
)
372 if (isSearchFilter()) {
373 if(result
) result
=lines
.doFilter(a
->lines()->numberOfLines());
374 if(result
) result
=age
.doFilter(a
->date()->ageInDays());
375 if(result
) result
=subject
.doFilter(a
->subject()->asUnicodeString());
378 if ( !a
->from()->isEmpty() )
379 tmp
= a
->from()->displayNames().first() + QLatin1String("##")
380 + QString::fromLatin1( a
->from()->addresses().first() );
381 result
=from
.doFilter(tmp
);
383 if(result
) result
=messageId
.doFilter(a
->messageID()->asUnicodeString());
384 if(result
) result
=references
.doFilter(a
->references()->asUnicodeString());
387 a
->setFilterResult(result
);