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 "knfoldermanager.h"
17 #include "knglobals.h"
18 #include "knconfigmanager.h"
20 #include "utilities.h"
21 #include "knarticlemanager.h"
22 #include "kncleanup.h"
23 #include "knmemorymanager.h"
24 #include "knmainwidget.h"
25 #include "utils/scoped_cursor_override.h"
28 #include <KMessageBox>
29 #include <KStandardDirs>
32 using namespace KNode::Utilities
;
35 KNFolderManager::KNFolderManager(KNArticleManager
*a
) : a_rtManager(a
)
38 QString
dir( KStandardDirs::locateLocal( "data", "knode/folders/" ) );
40 KNHelper::displayInternalFileError();
46 f
= KNFolder::Ptr( new KNFolder( 0, i18n( "Local Folders" ), "root" ) );
47 mFolderList
.append( f
);
50 f
= KNFolder::Ptr( new KNFolder( 1, i18n( "Drafts" ), "drafts", root() ) );
51 mFolderList
.append( f
);
54 f
= KNFolder::Ptr( new KNFolder( 2, i18n( "Outbox" ), "outbox", root() ) );
55 mFolderList
.append( f
);
58 f
= KNFolder::Ptr( new KNFolder( 3, i18n( "Sent" ), "sent", root() ) );
59 mFolderList
.append( f
);
67 setCurrentFolder( KNFolder::Ptr() );
71 KNFolderManager::~KNFolderManager()
77 void KNFolderManager::setCurrentFolder( KNFolder::Ptr f
)
80 a_rtManager
->setFolder(f
);
82 kDebug(5003) <<"KNFolderManager::setCurrentFolder() : folder changed";
84 if(f
&& !f
->isRootFolder()) {
86 a_rtManager
->showHdrs();
88 KMessageBox::error(knGlobals
.topWidget
, i18n("Cannot load index-file."));
93 bool KNFolderManager::loadHeaders( KNFolder::Ptr f
)
95 if( !f
|| f
->isRootFolder() )
101 // we want to delete old stuff first => reduce vm fragmentation
102 knGlobals
.memoryManager()->prepareLoad(f
);
105 knGlobals
.memoryManager()->updateCacheEntry( boost::static_pointer_cast
<KNArticleCollection
>( f
) );
113 bool KNFolderManager::unloadHeaders( KNFolder::Ptr f
, bool force
)
115 if(!f
|| !f
->isLoaded())
118 if (!force
&& (c_urrentFolder
== f
))
121 if (f
->unloadHdrs(force
))
122 knGlobals
.memoryManager()->removeCacheEntry( boost::static_pointer_cast
<KNArticleCollection
>( f
) );
130 KNFolder::Ptr
KNFolderManager::folder( int id
)
132 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
)
133 if ( (*it
)->id() == id
)
135 return KNFolder::Ptr();
139 KNFolder::Ptr
KNFolderManager::newFolder( KNFolder::Ptr p
)
143 KNFolder::Ptr f
= KNFolder::Ptr( new KNFolder( ++l_astId
, i18n( "New folder" ), p
) );
144 mFolderList
.append( f
);
150 bool KNFolderManager::deleteFolder( KNFolder::Ptr f
)
152 if(!f
|| f
->isRootFolder() || f
->isStandardFolder() || f
->lockedArticles()>0)
158 // find all subfolders of the folder we want to delete
159 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
) {
163 if ( (*it
)->lockedArticles() > 0 )
172 emit
folderRemoved(f
);
175 for ( KNFolder::List::Iterator it
= del
.begin(); it
!= del
.end(); ++it
) {
176 if ( c_urrentFolder
== (*it
) )
177 c_urrentFolder
= KNFolder::Ptr();
179 if ( unloadHeaders( (*it
), true ) ) {
180 (*it
)->deleteFiles();
181 mFolderList
.removeAll( (*it
) );
190 void KNFolderManager::emptyFolder( KNFolder::Ptr f
)
192 if(!f
|| f
->isRootFolder())
194 knGlobals
.memoryManager()->removeCacheEntry( boost::static_pointer_cast
<KNArticleCollection
>( f
) );
199 bool KNFolderManager::canMoveFolder( KNFolder::Ptr f
, KNFolder::Ptr p
)
201 if(!f
|| p
==f
->parent()) // nothing to be done
204 // Moving a folder on itself
209 // is "p" a child of "f" ?
210 KNCollection::Ptr p2
= p
? p
->parent() : KNCollection::Ptr();
217 if( (p2
&& p2
==f
) || f
==p
|| f
->isStandardFolder() || f
->isRootFolder()) // no way ;-)
223 bool KNFolderManager::moveFolder( KNFolder::Ptr f
, KNFolder::Ptr p
)
225 if ( !f
|| p
==f
->parent() ) { // nothing to be done
229 if ( !canMoveFolder( f
, p
) ) {
233 emit
folderRemoved(f
);
241 if(c_urrentFolder
==f
)
242 emit
folderActivated(f
);
248 int KNFolderManager::unsentForAccount(int accId
)
252 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
) {
253 for ( int idx
= 0; idx
< (*it
)->length(); ++idx
) {
254 KNLocalArticle::Ptr a
= (*it
)->at( idx
);
255 if ( a
->serverId() == accId
&& a
->doPost() && !a
->posted() )
264 void KNFolderManager::compactFolder( KNFolder::Ptr f
)
266 if(!f
|| f
->isRootFolder())
270 cup
.compactFolder(f
);
274 void KNFolderManager::compactAll(KNCleanUp
*cup
)
276 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
)
277 if ( !(*it
)->isRootFolder() && (*it
)->lockedArticles() == 0 )
278 cup
->appendCollection( (*it
) );
282 void KNFolderManager::compactAll()
284 KNCleanUp
*cup
= new KNCleanUp();
288 knGlobals
.configManager()->cleanup()->setLastCompactDate();
293 void KNFolderManager::importFromMBox( KNFolder::Ptr f
)
295 if(!f
|| f
->isRootFolder())
298 f
->setNotUnloadable(true);
300 if (!f
->isLoaded() && !loadHeaders(f
)) {
301 f
->setNotUnloadable(false);
305 KNLoadHelper
helper(knGlobals
.topWidget
);
306 QFile
*file
= helper
.getFile(i18n("Import MBox Folder"));
307 KNLocalArticle::List list
;
308 KNLocalArticle::Ptr art
;
310 int artStart
=0, artEnd
=0;
314 ScopedCursorOverride
cursor( Qt::WaitCursor
);
315 knGlobals
.setStatusMsg(i18n(" Importing articles..."));
316 knGlobals
.top
->secureProcessEvents();
318 if (!file
->atEnd()) { // search for the first article...
319 str
= file
->readLine();
320 if ( str
.left( 5 ) == "From " ) {
321 artStart
= file
->pos();
324 artStart
= KNHelper::findStringInFile( file
, "\n\nFrom " );
325 if (artStart
!= -1) {
326 file
->seek( artStart
+ 1 );
327 str
= file
->readLine();
328 artStart
= file
->pos();
334 knGlobals
.top
->secureProcessEvents();
337 while (!file
->atEnd()) {
338 artEnd
= KNHelper::findStringInFile( file
, "\n\nFrom " );
341 file
->seek( artStart
); // seek the first character of the article
342 int size
=artEnd
-artStart
;
344 buffer
= file
->read( size
);
346 if ( !buffer
.isEmpty() ) {
347 art
= KNLocalArticle::Ptr( new KNLocalArticle( KNArticleCollection::Ptr() ) );
348 art
->setEditDisabled(true);
349 art
->setContent( buffer
);
354 file
->seek( artEnd
+ 1 );
355 str
= file
->readLine();
356 artStart
= file
->pos();
358 if ((int)file
->size() > artStart
) {
359 file
->seek( artStart
); // seek the first character of the article
360 int size
=file
->size()-artStart
;
362 buffer
= file
->read( size
);
364 if ( !buffer
.isEmpty() ) {
365 art
= KNLocalArticle::Ptr( new KNLocalArticle( KNArticleCollection::Ptr() ) );
366 art
->setEditDisabled(true);
367 art
->setContent( buffer
);
374 if (list
.count()%75 == 0)
375 knGlobals
.top
->secureProcessEvents();
379 knGlobals
.setStatusMsg(i18n(" Storing articles..."));
380 knGlobals
.top
->secureProcessEvents();
383 knGlobals
.articleManager()->moveIntoFolder(list
, f
);
385 knGlobals
.setStatusMsg( QString() );
389 f
->setNotUnloadable(false);
393 void KNFolderManager::exportToMBox( KNFolder::Ptr f
)
395 if(!f
|| f
->isRootFolder())
398 f
->setNotUnloadable(true);
400 if (!f
->isLoaded() && !loadHeaders(f
)) {
401 f
->setNotUnloadable(false);
405 KNSaveHelper
helper(f
->name()+".mbox", knGlobals
.topWidget
);
406 QFile
*file
= helper
.getFile(i18n("Export Folder"));
409 ScopedCursorOverride
cursor( Qt::WaitCursor
);
410 knGlobals
.setStatusMsg(i18n(" Exporting articles..."));
411 knGlobals
.top
->secureProcessEvents();
413 QTextStream
ts(file
);
414 ts
.setCodec( "ISO 8859-1" );
415 KNLocalArticle::Ptr a
;
417 for(int idx
=0; idx
<f
->length(); idx
++) {
420 a
->setNotUnloadable(true);
422 if (a
->hasContent() || knGlobals
.articleManager()->loadArticle(a
)) {
423 ts
<< "From aaa@aaa Mon Jan 01 00:00:00 1997\n";
424 a
->toStream(ts
, true);
428 a
->setNotUnloadable(false);
431 knGlobals
.top
->secureProcessEvents();
434 knGlobals
.setStatusMsg( QString() );
439 void KNFolderManager::syncFolders()
441 QString
dir( KStandardDirs::locateLocal( "data", "knode/folders/" ) );
443 KNHelper::displayInternalFileError();
448 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
) {
449 if ( !(*it
)->isRootFolder() )
451 (*it
)->writeConfig();
456 int KNFolderManager::loadCustomFolders()
459 QString
dir( KStandardDirs::locateLocal( "data", "knode/folders/" ) );
463 KNHelper::displayInternalFileError();
468 QStringList
entries(d
.entryList(QStringList("custom_*.info"))); // ignore info files of standard folders
469 for(QStringList::Iterator it
=entries
.begin(); it
!= entries
.end(); ++it
) {
470 f
= KNFolder::Ptr( new KNFolder() );
471 if(f
->readInfo(d
.absoluteFilePath(*it
))) {
474 mFolderList
.append( f
);
481 for ( KNFolder::List::Iterator it
= mFolderList
.begin(); it
!= mFolderList
.end(); ++it
) {
482 if ( !(*it
)->isRootFolder() ) { // the root folder has no parent
483 KNFolder::Ptr par
= folder( (*it
)->parentId() );
486 (*it
)->setParent( par
);