Fix typo found by Yuri Chornoivan
[kdepim.git] / knode / kncleanup.cpp
blobfaeaab6a72830436819542817f2f47b538b48462
1 /*
2 KNode, the KDE newsreader
3 Copyright (c) 1999-2005 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
16 #include <QDir>
17 #include <QFile>
18 #include <QLabel>
19 #include <QProgressBar>
20 #include <QVBoxLayout>
21 #include <QApplication>
22 #include <QFrame>
23 #include <QTextStream>
24 #include <QCloseEvent>
26 #include <klocale.h>
27 #include <kmessagebox.h>
28 #include <kseparator.h>
29 #include <kdebug.h>
31 #include "knfolder.h"
32 #include "knglobals.h"
33 #include "kncleanup.h"
34 #include "knconfig.h"
35 #include "knfoldermanager.h"
36 #include "kngroupmanager.h"
37 #include "knarticlemanager.h"
38 #include "knnntpaccount.h"
41 KNCleanUp::KNCleanUp() : d_lg(0)
46 KNCleanUp::~KNCleanUp()
48 delete d_lg;
52 void KNCleanUp::start()
54 if ( mColList.isEmpty() )
55 return;
57 d_lg = new ProgressDialog( mColList.count() );
58 d_lg->show();
60 for ( QList<KNArticleCollection*>::Iterator it = mColList.begin(); it != mColList.end(); ++it ) {
61 if ( (*it)->type() == KNCollection::CTgroup ) {
62 d_lg->showMessage( i18n("Deleting expired articles in <b>%1</b>", (*it)->name() ) );
63 qApp->processEvents();
64 expireGroup( static_cast<KNGroup*>( (*it) ) );
65 d_lg->doProgress();
67 else if ( (*it)->type() == KNCollection::CTfolder ) {
68 d_lg->showMessage( i18n("Compacting folder <b>%1</b>", (*it)->name() ) );
69 qApp->processEvents();
70 compactFolder( static_cast<KNFolder*>( (*it) ) );
71 d_lg->doProgress();
75 delete d_lg;
76 d_lg=0;
80 void KNCleanUp::reset()
82 mColList.clear();
83 if(d_lg) {
84 delete d_lg;
85 d_lg=0;
90 void KNCleanUp::expireGroup( KNGroup *g, bool showResult )
92 int expDays=0, idRef=0, foundId=-1, delCnt=0, leftCnt=0, newCnt=0, firstArtNr=g->firstNr(), firstNew=-1;
93 bool unavailable=false;
94 KNRemoteArticle *art, *ref;
96 KNode::Cleanup *conf = g->activeCleanupConfig();
98 g->setNotUnloadable(true);
100 if (!g->isLoaded() && !knGlobals.groupManager()->loadHeaders(g)) {
101 g->setNotUnloadable(false);
102 return;
105 //find all expired
106 for(int i=0; i<g->length(); i++) {
107 art=g->at(i);
108 if(art->isRead())
109 expDays = conf->maxAgeForRead();
110 else
111 expDays = conf->maxAgeForUnread();
113 unavailable = false;
114 if ((art->articleNumber() != -1) && conf->removeUnavailable())
115 unavailable = (art->articleNumber() < firstArtNr);
117 art->setExpired( (art->date()->ageInDays() >= expDays) || unavailable );
120 //save threads
121 if (conf->preserveThreads()) {
122 for(int i=0; i<g->length(); i++) {
123 art=g->at(i);
124 if(!art->isExpired()) {
125 idRef=art->idRef();
126 while(idRef!=0) {
127 ref=g->byId(idRef);
128 ref->setExpired(false);
129 idRef=ref->idRef();
135 //restore threading
136 for(int i=0; i<g->length(); i++) {
137 art=g->at(i);
138 if(!art->isExpired()) {
139 idRef=art->idRef();
140 foundId=0;
141 while(foundId==0 && idRef!=0) {
142 ref=g->byId(idRef);
143 if(!ref->isExpired()) foundId=ref->id();
144 idRef=ref->idRef();
146 art->setIdRef(foundId);
150 //delete expired
151 for(int i=0; i<g->length(); i++) {
152 art=g->at(i);
153 if(art->isExpired()) {
154 if(art->isRead())
155 g->decReadCount();
156 delCnt++;
157 if (art->hasContent())
158 knGlobals.articleManager()->unloadArticle(art, true);
160 else if(art->isNew() && !art->isRead()) {
161 if(firstNew==-1)
162 firstNew=i;
163 newCnt++;
167 g->setNotUnloadable(false);
169 if(delCnt>0) {
170 g->saveStaticData(g->length(), true);
171 g->saveDynamicData(g->length(), true);
172 g->decCount(delCnt);
173 g->setNewCount(newCnt);
174 g->setFirstNewIndex(firstNew);
175 g->saveInfo();
176 knGlobals.groupManager()->unloadHeaders(g, true);
178 else
179 g->syncDynamicData();
181 conf->setLastExpireDate();
182 g->saveInfo();
183 leftCnt=g->count();
185 kDebug(5003) <<"KNCleanUp::expireGroup() :" << g->groupname() <<":"
186 << delCnt << "deleted ," << leftCnt << "left";
188 if(showResult)
189 KMessageBox::information(knGlobals.topWidget,
190 i18n("<b>%1</b><br />expired: %2<br />left: %3", g->groupname(), delCnt, leftCnt));
194 void KNCleanUp::compactFolder(KNFolder *f)
196 KNLocalArticle *art;
198 if (!f)
199 return;
201 QDir dir(f->path());
203 if(!dir.exists())
204 return;
206 f->setNotUnloadable(true);
208 if (!f->isLoaded() && !knGlobals.folderManager()->loadHeaders(f)) {
209 f->setNotUnloadable(false);
210 return;
213 f->closeFiles();
214 QFileInfo info(f->m_boxFile);
215 QString oldName=info.fileName();
216 QString newName=oldName+".new";
217 QFile newMBoxFile( info.absolutePath() + '/' + newName );
219 if( (f->m_boxFile.open(QIODevice::ReadOnly)) && (newMBoxFile.open(QIODevice::WriteOnly)) ) {
220 QTextStream ts(&newMBoxFile);
221 ts.setCodec( "ISO 8859-1" );
222 for(int idx=0; idx<f->length(); idx++) {
223 art=f->at(idx);
224 if ( f->m_boxFile.seek( art->startOffset() ) ) {
225 ts << "From aaa@aaa Mon Jan 01 00:00:00 1997\n";
226 ts.flush();
227 art->setStartOffset( newMBoxFile.pos() );
228 while ( f->m_boxFile.pos() < (uint)art->endOffset() && !f->m_boxFile.atEnd() )
229 ts << f->m_boxFile.readLine();
230 ts.flush();
231 art->setEndOffset( newMBoxFile.pos() );
232 newMBoxFile.putChar('\n');
236 f->syncIndex(true);
237 newMBoxFile.close();
238 f->closeFiles();
240 dir.remove(oldName);
241 dir.rename(newName, oldName);
244 f->setNotUnloadable(false);
248 //===============================================================================================
251 KNCleanUp::ProgressDialog::ProgressDialog( int steps, QWidget *parent ) :
252 KDialog( parent )
254 const int w=400,
255 h=160;
257 setCaption(i18n("Cleaning Up"));
258 setButtons( KDialog::None );
260 setFixedSize(w,h);
261 QFrame *top = new QFrame( this );
262 top->setGeometry(0,0, w,h);
264 QVBoxLayout *topL=new QVBoxLayout(top);
265 topL->setSpacing(10);
267 QLabel *l=new QLabel(i18n("Cleaning up. Please wait..."),top);
268 topL->addWidget(l);
270 KSeparator *sep=new KSeparator(top);
271 topL->addWidget(sep);
273 m_sg=new QLabel(top);
274 topL->addWidget(m_sg);
276 mProgressBar = new QProgressBar( top );
277 topL->addWidget( mProgressBar );
278 mProgressBar->setRange( 0, steps );
279 mProgressBar->setValue( 0 );
282 if(knGlobals.topWidget->isVisible()) {
283 int x, y;
284 x=(knGlobals.topWidget->width()-w)/2;
285 y=(knGlobals.topWidget->height()-h)/2;
286 if(x<0 || y<0) {
287 x=0;
288 y=0;
290 x+=knGlobals.topWidget->x();
291 y+=knGlobals.topWidget->y();
292 move(x,y);
297 KNCleanUp::ProgressDialog::~ProgressDialog()
302 void KNCleanUp::ProgressDialog::showMessage(const QString &s)
304 m_sg->setText(s);
308 void KNCleanUp::ProgressDialog::doProgress()
310 mProgressBar->setValue( mProgressBar->value() + 1 );
314 void KNCleanUp::ProgressDialog::closeEvent(QCloseEvent *)
316 // do nothing => prevent that the user closes the window