00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <QByteArray>
00016 #include <QList>
00017 #include <krun.h>
00018 #include <kmessagebox.h>
00019 #include <kmimetypetrader.h>
00020 #include <klocale.h>
00021 #include <kdebug.h>
00022 #include <kwindowsystem.h>
00023 #include <ktemporaryfile.h>
00024
00025 #include "articlewidget.h"
00026 #include "knmainwidget.h"
00027 #include "knglobals.h"
00028 #include "utilities.h"
00029 #include "knarticlemanager.h"
00030 #include "kngroupmanager.h"
00031 #include "knsearchdialog.h"
00032 #include "knfiltermanager.h"
00033 #include "knfolder.h"
00034 #include "knarticlefilter.h"
00035 #include "knhdrviewitem.h"
00036 #include "scheduler.h"
00037 #include "knnntpaccount.h"
00038 #include "knscoring.h"
00039 #include "knmemorymanager.h"
00040 #include "knarticlefactory.h"
00041 #include "knarticlewindow.h"
00042 #include "knfoldermanager.h"
00043 #include "headerview.h"
00044 #include "nntpjobs.h"
00045 #include "settings.h"
00046
00047 using namespace KNode;
00048
00049
00050 KNArticleManager::KNArticleManager() : QObject(0)
00051 {
00052 g_roup=0;
00053 f_older=0;
00054 f_ilterMgr = knGlobals.filterManager();
00055 f_ilter = f_ilterMgr->currentFilter();
00056 s_earchDlg=0;
00057 d_isableExpander=false;
00058
00059 connect(f_ilterMgr, SIGNAL(filterChanged(KNArticleFilter*)), this,
00060 SLOT(slotFilterChanged(KNArticleFilter*)));
00061 }
00062
00063
00064 KNArticleManager::~KNArticleManager()
00065 {
00066 delete s_earchDlg;
00067 }
00068
00069
00070 void KNArticleManager::deleteTempFiles()
00071 {
00072 for ( QList<KTemporaryFile*>::Iterator it = mTempFiles.begin(); it != mTempFiles.end(); ++it ) {
00073 delete (*it);
00074 }
00075 mTempFiles.clear();
00076 }
00077
00078
00079 void KNArticleManager::saveContentToFile(KMime::Content *c, QWidget *parent)
00080 {
00081 KNSaveHelper helper(c->contentType()->name(),parent);
00082
00083 QFile *file = helper.getFile(i18n("Save Attachment"));
00084
00085 if (file) {
00086 QByteArray data=c->decodedContent();
00087 if (file->write(data.data(), data.size()) == -1 )
00088 KNHelper::displayExternalFileError( parent );
00089 }
00090 }
00091
00092
00093 void KNArticleManager::saveArticleToFile(KNArticle *a, QWidget *parent)
00094 {
00095 QString fName = a->subject()->asUnicodeString();
00096 QString s = "";
00097
00098 for ( int i = 0; i < fName.length(); ++i )
00099 if (fName[i].isLetterOrNumber())
00100 s.append(fName[i]);
00101 else
00102 s.append(' ');
00103 fName = s.simplified();
00104 fName.replace(QRegExp("[\\s]"),"_");
00105
00106 KNSaveHelper helper(fName,parent);
00107 QFile *file = helper.getFile(i18n("Save Article"));
00108
00109 if (file) {
00110 QByteArray tmp=a->encodedContent(false);
00111 if ( file->write(tmp.data(), tmp.size()) == -1 )
00112 KNHelper::displayExternalFileError( parent );
00113 }
00114 }
00115
00116
00117 QString KNArticleManager::saveContentToTemp(KMime::Content *c)
00118 {
00119 QString path;
00120 KTemporaryFile* tmpFile;
00121 KMime::Headers::Base *pathHdr=c->getHeaderByType("X-KNode-Tempfile");
00122
00123 if(pathHdr) {
00124 path = pathHdr->asUnicodeString();
00125 bool found=false;
00126
00127
00128 for ( QList<KTemporaryFile*>::Iterator it = mTempFiles.begin(); it != mTempFiles.end(); ++it ) {
00129 if ( (*it)->fileName() == path ) {
00130 found = true;
00131 break;
00132 }
00133 }
00134
00135 if (found)
00136 return path;
00137 else
00138 c->removeHeader("X-KNode-Tempfile");
00139 }
00140
00141 tmpFile=new KTemporaryFile();
00142 if (!tmpFile->open()) {
00143 KNHelper::displayTempFileError();
00144 delete tmpFile;
00145 return QString();
00146 }
00147
00148 mTempFiles.append(tmpFile);
00149 QByteArray data=c->decodedContent();
00150 tmpFile->write(data.data(), data.size());
00151 tmpFile->flush();
00152 path=tmpFile->fileName();
00153 pathHdr=new KMime::Headers::Generic("X-KNode-Tempfile", c, path, "UTF-8");
00154 c->setHeader(pathHdr);
00155
00156 return path;
00157 }
00158
00159
00160 void KNArticleManager::openContent(KMime::Content *c)
00161 {
00162 QString path=saveContentToTemp(c);
00163 if(path.isNull()) return;
00164
00165 KService::Ptr offer = KMimeTypeTrader::self()->preferredService(c->contentType()->mimeType(), "Application");
00166 KUrl::List lst;
00167 KUrl url;
00168 url.setPath(path);
00169 lst.append(url);
00170
00171 if (offer)
00172 KRun::run(*offer, lst, knGlobals.top);
00173 else
00174 KRun::displayOpenWithDialog(lst, knGlobals.top);
00175 }
00176
00177
00178 void KNArticleManager::showHdrs(bool clear)
00179 {
00180 if(!g_roup && !f_older) return;
00181
00182 bool setFirstChild=true;
00183 bool showThreads=knGlobals.settings()->showThreads();
00184 bool expandThreads=knGlobals.settings()->defaultToExpandedThreads();
00185
00186 if(clear)
00187 v_iew->clear();
00188
00189 knGlobals.top->setCursorBusy(true);
00190 knGlobals.setStatusMsg(i18n(" Creating list..."));
00191 knGlobals.top->secureProcessEvents();
00192
00193 if(g_roup) {
00194 KNRemoteArticle *art, *ref, *current;
00195
00196 current = static_cast<KNRemoteArticle*>( knGlobals.top->articleViewer()->article() );
00197
00198 if(current && (current->collection() != g_roup)) {
00199 current=0;
00200 knGlobals.top->articleViewer()->setArticle( 0 );
00201 }
00202
00203 if(g_roup->isLocked())
00204 knGlobals.scheduler()->nntpMutex().lock();
00205
00206 if(f_ilter)
00207 f_ilter->doFilter(g_roup);
00208 else
00209 for(int i=0; i<g_roup->length(); i++) {
00210 art=g_roup->at(i);
00211 art->setFilterResult(true);
00212 art->setFiltered(true);
00213 ref=(art->idRef()!=0) ? g_roup->byId(art->idRef()) : 0;
00214 art->setDisplayedReference(ref);
00215 if(ref)
00216 ref->setVisibleFollowUps(true);
00217 }
00218
00219 d_isableExpander=true;
00220
00221 for(int i=0; i<g_roup->length(); i++) {
00222
00223 art=g_roup->at(i);
00224 art->setThreadMode(showThreads);
00225
00226 if(showThreads) {
00227 art->propagateThreadChangedDate();
00228
00229 if( !art->listItem() && art->filterResult() ) {
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 createThread(art);
00252 if ( expandThreads )
00253 art->listItem()->setOpen(true);
00254
00255
00256 }
00257 else if(art->listItem()) {
00258 art->updateListItem();
00259 if (expandThreads)
00260 art->listItem()->setOpen(true);
00261 }
00262
00263 }
00264 else {
00265
00266 if(!art->listItem() && art->filterResult()) {
00267 art->setListItem(new KNHdrViewItem(v_iew));
00268 art->initListItem();
00269 } else if(art->listItem())
00270 art->updateListItem();
00271
00272 }
00273
00274 }
00275
00276 if (current && !current->filterResult()) {
00277 int idRef;
00278 while (current && !current->filterResult()) {
00279 idRef=current->idRef();
00280 if (idRef == -1)
00281 break;
00282 current = g_roup->byId(idRef);
00283 }
00284 }
00285
00286 if(current && current->filterResult()) {
00287 if(!current->listItem())
00288 createCompleteThread(current);
00289 v_iew->setActive( current->listItem() );
00290 setFirstChild=false;
00291 }
00292
00293 d_isableExpander=false;
00294
00295 if (g_roup->isLocked())
00296 knGlobals.scheduler()->nntpMutex().unlock();
00297 }
00298
00299 else {
00300
00301 KNLocalArticle *art;
00302 if(f_ilter) {
00303 f_ilter->doFilter(f_older);
00304 } else {
00305 for(int i=0; i<f_older->length(); i++) {
00306 art=f_older->at(i);
00307 art->setFilterResult(true);
00308 }
00309 }
00310
00311 for(int idx=0; idx<f_older->length(); idx++) {
00312 art=f_older->at(idx);
00313
00314 if(!art->listItem() && art->filterResult()) {
00315 art->setListItem( new KNHdrViewItem(v_iew, art) );
00316 art->updateListItem();
00317 } else if(art->listItem())
00318 art->updateListItem();
00319 }
00320
00321 }
00322
00323 if(setFirstChild && v_iew->firstChild()) {
00324 v_iew->setCurrentItem(v_iew->firstChild());
00325 knGlobals.top->articleViewer()->setArticle( 0 );
00326 }
00327
00328 knGlobals.setStatusMsg( QString() );
00329 updateStatusString();
00330 knGlobals.top->setCursorBusy(false);
00331 }
00332
00333
00334 void KNArticleManager::updateViewForCollection(KNArticleCollection *c)
00335 {
00336 if(g_roup==c || f_older==c)
00337 showHdrs(false);
00338 }
00339
00340
00341 void KNArticleManager::updateListViewItems()
00342 {
00343 if(!g_roup && !f_older) return;
00344
00345 if(g_roup) {
00346 KNRemoteArticle *art;
00347
00348 for(int i=0; i<g_roup->length(); i++) {
00349 art=g_roup->at(i);
00350 if(art->listItem())
00351 art->updateListItem();
00352 }
00353 } else {
00354 KNLocalArticle *art;
00355
00356 for(int idx=0; idx<f_older->length(); idx++) {
00357 art=f_older->at(idx);
00358 if(art->listItem())
00359 art->updateListItem();
00360 }
00361 }
00362 }
00363
00364
00365 void KNArticleManager::setAllThreadsOpen(bool b)
00366 {
00367 KNRemoteArticle *art;
00368 if(g_roup) {
00369 knGlobals.top->setCursorBusy(true);
00370 d_isableExpander = true;
00371 for(int idx=0; idx<g_roup->length(); idx++) {
00372 art = g_roup->at(idx);
00373 if (art->listItem())
00374 art->listItem()->setOpen(b);
00375 else
00376 if (b && art->filterResult()) {
00377 createThread(art);
00378 art->listItem()->setOpen(true);
00379 }
00380 }
00381 d_isableExpander = false;
00382 knGlobals.top->setCursorBusy(false);
00383 }
00384 }
00385
00386
00387 void KNArticleManager::search()
00388 {
00389 if(s_earchDlg) {
00390 s_earchDlg->show();
00391 #ifdef Q_OS_UNIX
00392 KWindowSystem::activateWindow(s_earchDlg->winId());
00393 #endif
00394 } else {
00395 s_earchDlg = new SearchDialog( SearchDialog::STgroupSearch, 0 );
00396 connect(s_earchDlg, SIGNAL(doSearch(KNArticleFilter*)), this,
00397 SLOT(slotFilterChanged(KNArticleFilter*)));
00398 connect(s_earchDlg, SIGNAL(dialogDone()), this,
00399 SLOT(slotSearchDialogDone()));
00400 s_earchDlg->show();
00401 }
00402 }
00403
00404
00405 void KNArticleManager::setGroup(KNGroup *g)
00406 {
00407 g_roup = g;
00408 if ( g )
00409 emit aboutToShowGroup();
00410 }
00411
00412
00413 void KNArticleManager::setFolder(KNFolder *f)
00414 {
00415 f_older = f;
00416 if ( f )
00417 emit aboutToShowFolder();
00418 }
00419
00420
00421 KNArticleCollection* KNArticleManager::collection()
00422 {
00423 if(g_roup)
00424 return g_roup;
00425 if(f_older)
00426 return f_older;
00427
00428 return 0;
00429 }
00430
00431
00432 bool KNArticleManager::loadArticle(KNArticle *a)
00433 {
00434 if (!a)
00435 return false;
00436
00437 if (a->hasContent())
00438 return true;
00439
00440 if (a->isLocked()) {
00441 if ( a->type() == KNArticle::ATremote )
00442 return true;
00443 else
00444 return false;
00445 }
00446
00447 if ( a->type() == KNArticle::ATremote ) {
00448 KNGroup *g=static_cast<KNGroup*>(a->collection());
00449 if(g)
00450 emitJob( new ArticleFetchJob( this, g->account(), a ) );
00451 else
00452 return false;
00453 }
00454 else {
00455 KNFolder *f=static_cast<KNFolder*>(a->collection());
00456 if( f && f->loadArticle( static_cast<KNLocalArticle*>(a) ) )
00457 knGlobals.memoryManager()->updateCacheEntry(a);
00458 else
00459 return false;
00460 }
00461 return true;
00462 }
00463
00464
00465 bool KNArticleManager::unloadArticle(KNArticle *a, bool force)
00466 {
00467 if(!a || a->isLocked() )
00468 return false;
00469 if(!a->hasContent())
00470 return true;
00471
00472 if (!force && a->isNotUnloadable())
00473 return false;
00474
00475 if ( !force && ( ArticleWidget::articleVisible( a ) ) )
00476 return false;
00477
00478 if (!force && ( a->type()== KNArticle::ATlocal ) &&
00479 (knGlobals.artFactory->findComposer(static_cast<KNLocalArticle*>(a))!=0))
00480 return false;
00481
00482 if ( !ArticleWindow::closeAllWindowsForArticle( a, force ) )
00483 if (!force)
00484 return false;
00485
00486 ArticleWidget::articleRemoved( a );
00487 if ( a->type() != KNArticle::ATlocal )
00488 knGlobals.artFactory->deleteComposerForArticle(static_cast<KNLocalArticle*>(a));
00489 a->Content::clear();
00490 a->updateListItem();
00491 knGlobals.memoryManager()->removeCacheEntry(a);
00492
00493 return true;
00494 }
00495
00496
00497 void KNArticleManager::copyIntoFolder(KNArticle::List &l, KNFolder *f)
00498 {
00499 if(!f) return;
00500
00501 KNLocalArticle *loc;
00502 KNLocalArticle::List l2;
00503
00504 for ( KNArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00505 if ( !(*it)->hasContent() )
00506 continue;
00507 loc=new KNLocalArticle(0);
00508 loc->setEditDisabled(true);
00509 loc->setContent( (*it)->encodedContent() );
00510 loc->parse();
00511 l2.append(loc);
00512 }
00513
00514 if ( !l2.isEmpty() ) {
00515
00516 f->setNotUnloadable(true);
00517
00518 if ( !f->isLoaded() && !knGlobals.folderManager()->loadHeaders( f ) ) {
00519 for ( KNLocalArticle::List::Iterator it = l2.begin(); it != l2.end(); ++it )
00520 delete (*it);
00521 l2.clear();
00522 f->setNotUnloadable(false);
00523 return;
00524 }
00525
00526 if( !f->saveArticles( l2 ) ) {
00527 for ( KNLocalArticle::List::Iterator it = l2.begin(); it != l2.end(); ++it ) {
00528 if ( (*it)->isOrphant() )
00529 delete (*it);
00530 else
00531 (*it)->Content::clear();
00532 }
00533 KNHelper::displayInternalFileError();
00534 } else {
00535 for ( KNLocalArticle::List::Iterator it = l2.begin(); it != l2.end(); ++it )
00536 (*it)->Content::clear();
00537 knGlobals.memoryManager()->updateCacheEntry(f);
00538 }
00539
00540 f->setNotUnloadable(false);
00541 }
00542 }
00543
00544
00545 void KNArticleManager::moveIntoFolder(KNLocalArticle::List &l, KNFolder *f)
00546 {
00547 if(!f) return;
00548 kDebug(5003) <<" Target folder:" << f->name();
00549
00550 f->setNotUnloadable(true);
00551
00552 if (!f->isLoaded() && !knGlobals.folderManager()->loadHeaders(f)) {
00553 f->setNotUnloadable(false);
00554 return;
00555 }
00556
00557 if ( f->saveArticles( l ) ) {
00558 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it )
00559 knGlobals.memoryManager()->updateCacheEntry( (*it) );
00560 knGlobals.memoryManager()->updateCacheEntry(f);
00561 } else {
00562 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it )
00563 if ( (*it)->isOrphant() )
00564 delete (*it);
00565 KNHelper::displayInternalFileError();
00566 }
00567
00568 f->setNotUnloadable(false);
00569 }
00570
00571
00572 bool KNArticleManager::deleteArticles(KNLocalArticle::List &l, bool ask)
00573 {
00574 if(ask) {
00575 QStringList lst;
00576 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00577 if ( (*it)->isLocked() )
00578 continue;
00579 if ( (*it)->subject()->isEmpty() )
00580 lst << i18n("no subject");
00581 else
00582 lst << (*it)->subject()->asUnicodeString();
00583 }
00584 if( KMessageBox::Cancel == KMessageBox::warningContinueCancelList(
00585 knGlobals.topWidget, i18n("Do you really want to delete these articles?"), lst,
00586 i18n("Delete Articles"), KGuiItem(i18n("&Delete"),"edit-delete")) )
00587 return false;
00588 }
00589
00590 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it )
00591 knGlobals.memoryManager()->removeCacheEntry( (*it) );
00592
00593 KNFolder *f=static_cast<KNFolder*>(l.first()->collection());
00594 if ( f ) {
00595 f->removeArticles( l, true );
00596 knGlobals.memoryManager()->updateCacheEntry( f );
00597 return false;
00598 }
00599 else {
00600 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it )
00601 delete (*it);
00602 }
00603
00604 return true;
00605 }
00606
00607
00608 void KNArticleManager::setAllRead( bool read, int lastcount )
00609 {
00610 if ( !g_roup )
00611 return;
00612
00613 int groupLength = g_roup->length();
00614 int newCount = g_roup->newCount();
00615 int readCount = g_roup->readCount();
00616 int offset = lastcount;
00617
00618 if ( lastcount > groupLength || lastcount < 0 )
00619 offset = groupLength;
00620
00621 KNRemoteArticle *a;
00622 for ( int i = groupLength - offset; i < groupLength; i++ ) {
00623 a = g_roup->at( i );
00624 if ( a->getReadFlag() != read && !a->isIgnored() ) {
00625 a->setRead( read );
00626 a->setChanged( true );
00627 if ( !read ) {
00628 readCount--;
00629 if ( a->isNew() )
00630 newCount++;
00631 } else {
00632 readCount++;
00633 if ( a->isNew() )
00634 newCount--;
00635 }
00636 }
00637 }
00638
00639 g_roup->updateThreadInfo();
00640 if ( lastcount < 0 && read ) {
00641
00642 g_roup->setReadCount( groupLength );
00643 g_roup->setNewCount( 0 );
00644 } else {
00645 g_roup->setReadCount( readCount );
00646 g_roup->setNewCount( newCount );
00647 }
00648
00649 g_roup->updateListItem();
00650 showHdrs( true );
00651 }
00652
00653
00654 void KNArticleManager::setRead(KNRemoteArticle::List &l, bool r, bool handleXPosts)
00655 {
00656 if ( l.isEmpty() )
00657 return;
00658
00659 KNRemoteArticle *ref = 0;
00660 KNGroup *g=static_cast<KNGroup*>( l.first()->collection() );
00661 int changeCnt=0, idRef=0;
00662
00663 for ( KNRemoteArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00664 if( r && knGlobals.settings()->markCrossposts() &&
00665 handleXPosts && (*it)->newsgroups()->isCrossposted() ) {
00666
00667 QList<QByteArray> groups = (*it)->newsgroups()->groups();
00668 KNGroup *targetGroup=0;
00669 KNRemoteArticle *xp=0;
00670 KNRemoteArticle::List al;
00671 QByteArray mid = (*it)->messageID()->as7BitString( false );
00672
00673 for ( QList<QByteArray>::Iterator it2 = groups.begin(); it2 != groups.end(); ++it2 ) {
00674 targetGroup = knGlobals.groupManager()->group(*it2, g->account());
00675 if (targetGroup) {
00676 if (targetGroup->isLoaded() && (xp=targetGroup->byMessageId(mid)) ) {
00677 al.clear();
00678 al.append(xp);
00679 setRead(al, r, false);
00680 } else {
00681 targetGroup->appendXPostID(mid);
00682 }
00683 }
00684 }
00685 }
00686
00687 else if ( (*it)->getReadFlag() != r ) {
00688 (*it)->setRead( r );
00689 (*it)->setChanged( true );
00690 (*it)->updateListItem();
00691
00692 if ( !(*it)->isIgnored() ) {
00693 changeCnt++;
00694 idRef = (*it)->idRef();
00695
00696 while ( idRef != 0 ) {
00697 ref=g->byId(idRef);
00698 if(r) {
00699 ref->decUnreadFollowUps();
00700 if ( (*it)->isNew() )
00701 ref->decNewFollowUps();
00702 }
00703 else {
00704 ref->incUnreadFollowUps();
00705 if ( (*it)->isNew() )
00706 ref->incNewFollowUps();
00707 }
00708
00709 if(ref->listItem() &&
00710 ((ref->unreadFollowUps()==0 || ref->unreadFollowUps()==1) ||
00711 (ref->newFollowUps()==0 || ref->newFollowUps()==1)))
00712 ref->updateListItem();
00713
00714 idRef=ref->idRef();
00715 }
00716
00717 if(r) {
00718 g->incReadCount();
00719 if ( (*it)->isNew() )
00720 g->decNewCount();
00721 }
00722 else {
00723 g->decReadCount();
00724 if ( (*it)->isNew() )
00725 g->incNewCount();
00726 }
00727 }
00728 }
00729 }
00730
00731 if(changeCnt>0) {
00732 g->updateListItem();
00733 if(g==g_roup)
00734 updateStatusString();
00735 }
00736 }
00737
00738
00739 void KNArticleManager::setAllNotNew()
00740 {
00741 if ( !g_roup )
00742 return;
00743 KNRemoteArticle *a;
00744 for ( int i = 0; i < g_roup->length(); ++i) {
00745 a = g_roup->at(i);
00746 if ( a->isNew() ) {
00747 a->setNew( false );
00748 a->setChanged( true );
00749 }
00750 }
00751 g_roup->setFirstNewIndex( -1 );
00752 g_roup->setNewCount( 0 );
00753 g_roup->updateThreadInfo();
00754 }
00755
00756
00757 bool KNArticleManager::toggleWatched(KNRemoteArticle::List &l)
00758 {
00759 if(l.isEmpty())
00760 return true;
00761
00762 KNRemoteArticle *a=l.first(), *ref=0;
00763 bool watch = (!a->isWatched());
00764 KNGroup *g=static_cast<KNGroup*>(a->collection() );
00765 int changeCnt=0, idRef=0;
00766
00767 for ( KNRemoteArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00768 if ( (*it)->isIgnored() ) {
00769 (*it)->setIgnored(false);
00770
00771 if ( !(*it)->getReadFlag() ) {
00772 changeCnt++;
00773 idRef = (*it)->idRef();
00774
00775 while ( idRef != 0 ) {
00776 ref=g->byId(idRef);
00777
00778 ref->incUnreadFollowUps();
00779 if ( (*it)->isNew() )
00780 ref->incNewFollowUps();
00781
00782 if(ref->listItem() &&
00783 ((ref->unreadFollowUps()==0 || ref->unreadFollowUps()==1) ||
00784 (ref->newFollowUps()==0 || ref->newFollowUps()==1)))
00785 ref->updateListItem();
00786
00787 idRef=ref->idRef();
00788 }
00789 g->decReadCount();
00790 if ( (*it)->isNew() )
00791 g->incNewCount();
00792 }
00793 }
00794
00795 (*it)->setWatched( watch );
00796 (*it)->updateListItem();
00797 (*it)->setChanged( true );
00798 }
00799
00800 if(changeCnt>0) {
00801 g->updateListItem();
00802 if(g==g_roup)
00803 updateStatusString();
00804 }
00805
00806 return watch;
00807 }
00808
00809
00810 bool KNArticleManager::toggleIgnored(KNRemoteArticle::List &l)
00811 {
00812 if(l.isEmpty())
00813 return true;
00814
00815 KNRemoteArticle *ref = 0;
00816 bool ignore = !l.first()->isIgnored();
00817 KNGroup *g = static_cast<KNGroup*>( l.first()->collection() );
00818 int changeCnt = 0, idRef = 0;
00819
00820 for ( KNRemoteArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00821 (*it)->setWatched(false);
00822 if ( (*it)->isIgnored() != ignore ) {
00823 (*it)->setIgnored( ignore );
00824
00825 if ( !(*it)->getReadFlag() ) {
00826 changeCnt++;
00827 idRef = (*it)->idRef();
00828
00829 while ( idRef != 0 ) {
00830 ref = g->byId( idRef );
00831
00832 if ( ignore ) {
00833 ref->decUnreadFollowUps();
00834 if ( (*it)->isNew() )
00835 ref->decNewFollowUps();
00836 } else {
00837 ref->incUnreadFollowUps();
00838 if ( (*it)->isNew() )
00839 ref->incNewFollowUps();
00840 }
00841
00842 if(ref->listItem() &&
00843 ((ref->unreadFollowUps()==0 || ref->unreadFollowUps()==1) ||
00844 (ref->newFollowUps()==0 || ref->newFollowUps()==1)))
00845 ref->updateListItem();
00846
00847 idRef=ref->idRef();
00848 }
00849
00850 if ( ignore ) {
00851 g->incReadCount();
00852 if ( (*it)->isNew() )
00853 g->decNewCount();
00854 } else {
00855 g->decReadCount();
00856 if ( (*it)->isNew() )
00857 g->incNewCount();
00858 }
00859
00860 }
00861 }
00862 (*it)->updateListItem();
00863 (*it)->setChanged(true);
00864 }
00865
00866 if(changeCnt>0) {
00867 g->updateListItem();
00868 if(g==g_roup)
00869 updateStatusString();
00870 }
00871
00872 return ignore;
00873 }
00874
00875
00876 void KNArticleManager::rescoreArticles(KNRemoteArticle::List &l)
00877 {
00878 if ( l.isEmpty() )
00879 return;
00880
00881 KNGroup *g = static_cast<KNGroup*>( l.first()->collection() );
00882 KScoringManager *sm = knGlobals.scoringManager();
00883 sm->initCache(g->groupname());
00884
00885 for ( KNRemoteArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00886 int defScore = 0;
00887 if ( (*it)->isIgnored())
00888 defScore = knGlobals.settings()->ignoredThreshold();
00889 else if ( (*it)->isWatched() )
00890 defScore = knGlobals.settings()->watchedThreshold();
00891 (*it)->setScore(defScore);
00892
00893 bool read = (*it)->isRead();
00894
00895 KNScorableArticle sa( (*it) );
00896 sm->applyRules(sa);
00897 (*it)->updateListItem();
00898 (*it)->setChanged( true );
00899
00900 if ( !read && (*it)->isRead() != read )
00901 g_roup->incReadCount();
00902 }
00903 }
00904
00905
00906 void KNArticleManager::processJob(KNJobData *j)
00907 {
00908 if(j->type()==KNJobData::JTfetchArticle && !j->canceled()) {
00909 KNRemoteArticle *a = static_cast<KNRemoteArticle*>( j->data() );
00910 if(j->success()) {
00911 ArticleWidget::articleChanged( a );
00912 if(!a->isOrphant())
00913 knGlobals.memoryManager()->updateCacheEntry(a);
00914 if(a->listItem())
00915 a->updateListItem();
00916 } else {
00917 if ( j->error() == KIO::ERR_DOES_NOT_EXIST ) {
00918
00919 QString msgId = a->messageID()->as7BitString( false );
00920
00921 msgId = msgId.mid( 1, msgId.length() - 2 );
00922 ArticleWidget::articleLoadError( a,
00923 i18n("The article you requested is not available on your news server."
00924 "<br />You could try to get it from <a href=\"http://groups.google.com/groups?selm=%1\">groups.google.com</a>.",
00925 msgId ) );
00926
00927 if ( knGlobals.settings()->autoMark() && !a->isOrphant() ) {
00928 KNRemoteArticle::List l;
00929 l.append( a );
00930 setRead( l, true );
00931 }
00932 } else
00933 ArticleWidget::articleLoadError( a, j->errorString() );
00934 }
00935 }
00936
00937 delete j;
00938 }
00939
00940
00941 void KNArticleManager::createThread(KNRemoteArticle *a)
00942 {
00943 KNRemoteArticle *ref=a->displayedReference();
00944
00945 if(ref) {
00946 if(!ref->listItem())
00947 createThread(ref);
00948 a->setListItem(new KNHdrViewItem(ref->listItem()));
00949 }
00950 else
00951 a->setListItem(new KNHdrViewItem(v_iew));
00952
00953 a->setThreadMode( knGlobals.settings()->showThreads() );
00954 a->initListItem();
00955 }
00956
00957
00958 void KNArticleManager::createCompleteThread(KNRemoteArticle *a)
00959 {
00960 KNRemoteArticle *ref=a->displayedReference(), *art, *top;
00961 bool inThread=false;
00962 bool showThreads = knGlobals.settings()->showThreads();
00963
00964 while (ref->displayedReference() != 0)
00965 ref=ref->displayedReference();
00966
00967 top = ref;
00968
00969 if (!top->listItem())
00970 return;
00971
00972 for(int i=0; i<g_roup->count(); i++) {
00973 art=g_roup