• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

knode

knfolder.cpp

Go to the documentation of this file.
00001 /*
00002     KNode, the KDE newsreader
00003     Copyright (c) 1999-2006 the KNode authors.
00004     See file AUTHORS for details
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010     You should have received a copy of the GNU General Public License
00011     along with this program; if not, write to the Free Software Foundation,
00012     Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
00013 */
00014 
00015 #include <QByteArray>
00016 #include <QFileInfo>
00017 #include <QTextStream>
00018 
00019 #include <kconfig.h>
00020 #include <kstandarddirs.h>
00021 #include <kdebug.h>
00022 #include <klocale.h>
00023 
00024 #include "articlewidget.h"
00025 #include "knarticlemanager.h"
00026 #include "kncollectionviewitem.h"
00027 #include "knhdrviewitem.h"
00028 #include "utilities.h"
00029 #include "knglobals.h"
00030 #include "knarticlefactory.h"
00031 #include "knfolder.h"
00032 #include "knarticlewindow.h"
00033 #include "knmainwidget.h"
00034 
00035 using namespace KNode;
00036 
00037 
00038 KNFolder::KNFolder()
00039   : KNArticleCollection(0), i_d(-1), p_arentId(-1), i_ndexDirty(false), w_asOpen(true)
00040 {
00041 }
00042 
00043 
00044 KNFolder::KNFolder(int id, const QString &name, KNFolder *parent)
00045   : KNArticleCollection(parent), i_d(id), i_ndexDirty(false), w_asOpen(true)
00046 {
00047   QString fname=path()+QString("custom_%1").arg(i_d);
00048 
00049   n_ame = name;
00050   m_boxFile.setFileName(fname+".mbox");
00051   i_ndexFile.setFileName(fname+".idx");
00052   i_nfoPath=fname+".info";
00053 
00054   p_arentId=parent?parent->id():-1;
00055 
00056   if(i_ndexFile.exists())
00057     c_ount=i_ndexFile.size()/sizeof(DynData);
00058   else
00059     c_ount=0;
00060 }
00061 
00062 
00063 KNFolder::KNFolder(int id, const QString &name, const QString &prefix, KNFolder *parent)
00064   : KNArticleCollection(parent), i_d(id), i_ndexDirty(false), w_asOpen(true)
00065 {
00066   QString fname=path()+QString("%1_%2").arg(prefix).arg(i_d);
00067 
00068   n_ame = name;
00069   m_boxFile.setFileName(fname+".mbox");
00070   i_ndexFile.setFileName(fname+".idx");
00071   i_nfoPath=fname+".info";
00072 
00073   p_arentId=parent?parent->id():-1;
00074 
00075   if(i_ndexFile.exists())
00076     c_ount=i_ndexFile.size()/sizeof(DynData);
00077   else
00078     c_ount=0;
00079 }
00080 
00081 
00082 KNFolder::~KNFolder()
00083 {
00084   closeFiles();
00085 }
00086 
00087 
00088 void KNFolder::updateListItem()
00089 {
00090   if(l_istItem) {
00091     l_istItem->setText(0, n_ame);
00092     if (!isRootFolder())
00093       l_istItem->setTotalCount( c_ount );
00094   }
00095 }
00096 
00097 
00098 QString KNFolder::path()
00099 {
00100   QString dir(KStandardDirs::locateLocal("data","knode/")+"folders/");
00101   /*if (dir.isNull())
00102     KNHelper::displayInternalFileError();*/
00103   return dir;
00104 }
00105 
00106 
00107 bool KNFolder::readInfo(const QString &infoPath)
00108 {
00109   if(infoPath.isEmpty())
00110     return false;
00111 
00112   i_nfoPath=infoPath;
00113 
00114   KConfig info(i_nfoPath, KConfig::SimpleConfig);
00115   KConfigGroup grp(&info, QString());
00116   if (!isRootFolder() && !isStandardFolder()) {
00117     n_ame=grp.readEntry("name");
00118     i_d=grp.readEntry("id", -1);
00119     p_arentId=grp.readEntry("parentId", -1);
00120   }
00121   w_asOpen=grp.readEntry("wasOpen", true);
00122 
00123   if(i_d>-1) {
00124     QFileInfo fi(infoPath);
00125     QString fname = fi.absolutePath() + '/' + fi.baseName();
00126     closeFiles();
00127     clear();
00128 
00129     m_boxFile.setFileName(fname+".mbox");
00130     i_ndexFile.setFileName(fname+".idx");
00131     c_ount=i_ndexFile.exists() ? (i_ndexFile.size()/sizeof(DynData)) : 0;
00132   }
00133 
00134   return (i_d!=-1);
00135 }
00136 
00137 
00138 bool KNFolder::readInfo()
00139 {
00140   return readInfo(i_nfoPath);
00141 }
00142 
00143 
00144 void KNFolder::saveInfo()
00145 {
00146   if(!i_nfoPath.isEmpty()) {
00147     KConfig info(i_nfoPath, KConfig::SimpleConfig);
00148     KConfigGroup grp(&info, QString());
00149     if (!isRootFolder() && !isStandardFolder()) {
00150       grp.writeEntry("name", n_ame);
00151       grp.writeEntry("id", i_d);
00152       grp.writeEntry("parentId", p_arentId);
00153     }
00154     if(l_istItem)
00155       grp.writeEntry("wasOpen", l_istItem->isOpen());
00156   }
00157 }
00158 
00159 
00160 void KNFolder::setParent(KNCollection *p)
00161 {
00162   p_arent = p;
00163   p_arentId = p ? (static_cast<KNFolder*>(p))->id() : -1;
00164 }
00165 
00166 
00167 bool KNFolder::loadHdrs()
00168 {
00169   if(isLoaded()) {
00170     kDebug(5003) <<"KNFolder::loadHdrs() : already loaded";
00171     return true;
00172   }
00173 
00174   if(!i_ndexFile.open(QIODevice::ReadOnly)) {
00175     kError(5003) <<"KNFolder::loadHdrs() : cannot open index-file!";
00176     closeFiles();
00177     return false;
00178   }
00179 
00180   if(!m_boxFile.open(QIODevice::ReadOnly)) {
00181     kError(5003) <<"KNFolder::loadHdrs() : cannot open mbox-file!";
00182     closeFiles();
00183     return false;
00184   }
00185 
00186   if(!resize(c_ount)) {
00187     closeFiles();
00188     return false;
00189   }
00190 
00191   QByteArray tmp;
00192   KNLocalArticle *art;
00193   DynData dynamic;
00194   int pos1=0, pos2=0, cnt=0, byteCount;
00195 
00196   knGlobals.top->setCursorBusy(true);
00197   knGlobals.setStatusMsg(i18n(" Loading folder..."));
00198   knGlobals.top->secureProcessEvents();
00199 
00200   while(!i_ndexFile.atEnd()) {
00201 
00202     //read index-data
00203     byteCount=i_ndexFile.read((char*)(&dynamic), sizeof(DynData));
00204     if(byteCount!=sizeof(DynData))
00205       if( i_ndexFile.error() == QFile::NoError ) {
00206         kWarning(5003) <<"KNFolder::loadHeaders() : found broken entry in index-file: Ignored!";
00207         continue;
00208       }
00209       else {
00210         kError(5003) <<"KNFolder::loadHeaders() : corrupted index-file, IO-error!";
00211         closeFiles();
00212         clear();
00213         knGlobals.top->setCursorBusy( false );
00214         return false;
00215       }
00216 
00217     art=new KNLocalArticle(this);
00218 
00219     //set index-data
00220     dynamic.getData(art);
00221 
00222     //read overview
00223     if ( !m_boxFile.seek( art->startOffset() ) ) {
00224       kError(5003) <<"KNFolder::loadHdrs() : cannot set mbox file-pointer!";
00225       closeFiles();
00226       clear();
00227       knGlobals.top->setCursorBusy( false );
00228       return false;
00229     }
00230     tmp = m_boxFile.readLine();
00231     if ( tmp.endsWith( '\n' ) )
00232       tmp.resize( tmp.length() - 1 );
00233     if(tmp.isEmpty()) {
00234       if( m_boxFile.error() == QFile::NoError ) {
00235         kWarning(5003) <<"found broken entry in mbox-file: Ignored!";
00236         delete art;
00237         continue;
00238       }
00239       else {
00240         kError(5003) <<"KNFolder::loadHdrs() : corrupted mbox-file, IO-error!";
00241         closeFiles();
00242         clear();
00243         knGlobals.top->setCursorBusy( false );
00244         return false;
00245       }
00246     }
00247 
00248     //set overview
00249     bool end=false;
00250     pos1 = tmp.indexOf( ' ' ) + 1;
00251     pos2 = tmp.indexOf( '\t', pos1 );
00252     if (pos2 == -1) {
00253       pos2=tmp.length();
00254       end=true;
00255     }
00256     art->subject()->from7BitString(tmp.mid(pos1, pos2-pos1));
00257 
00258     if (!end) {
00259       pos1=pos2+1;
00260       pos2 = tmp.indexOf( '\t', pos1 );
00261       if (pos2 == -1) {
00262         pos2=tmp.length();
00263         end=true;
00264       }
00265       art->newsgroups()->from7BitString(tmp.mid(pos1, pos2-pos1));
00266     }
00267 
00268     if (!end) {
00269       pos1=pos2+1;
00270       pos2 = tmp.indexOf( '\t', pos1 );
00271       if (pos2 == -1) {
00272         pos2=tmp.length();
00273         end=true;
00274       }
00275       art->to()->from7BitString(tmp.mid(pos1,pos2-pos1));
00276     }
00277 
00278     if (!end) {
00279       pos1=pos2+1;
00280       pos2=tmp.length();
00281       art->lines()->from7BitString(tmp.mid(pos1,pos2-pos1));
00282     }
00283 
00284     if(!append(art)) {
00285       kError(5003) <<"KNFolder::loadHdrs() : cannot append article!";
00286       delete art;
00287       clear();
00288       closeFiles();
00289 
00290       knGlobals.setStatusMsg( QString() );
00291       knGlobals.top->setCursorBusy(false);
00292       return false;
00293     }
00294 
00295     cnt++;
00296   }
00297 
00298   closeFiles();
00299   setLastID();
00300   c_ount=cnt;
00301   updateListItem();
00302 
00303   knGlobals.setStatusMsg( QString() );
00304   knGlobals.top->setCursorBusy(false);
00305 
00306   return true;
00307 }
00308 
00309 
00310 bool KNFolder::unloadHdrs(bool force)
00311 {
00312   if(l_ockedArticles>0)
00313     return false;
00314 
00315   if (!force && isNotUnloadable())
00316     return false;
00317 
00318   KNLocalArticle *a;
00319   for(int idx=0; idx<length(); idx++) {
00320     a=at(idx);
00321     if (a->hasContent() && !knGlobals.articleManager()->unloadArticle(a, force))
00322       return false;
00323   }
00324   syncIndex();
00325   clear();
00326 
00327   return true;
00328 }
00329 
00330 bool KNFolder::loadArticle(KNLocalArticle *a)
00331 {
00332   if(a->hasContent())
00333     return true;
00334 
00335   closeFiles();
00336   if(!m_boxFile.open(QIODevice::ReadOnly)) {
00337     kError(5003) <<"KNFolder::loadArticle(KNLocalArticle *a) : cannot open mbox file:"
00338                   << m_boxFile.fileName();
00339     return false;
00340   }
00341 
00342   //set file-pointer
00343   if ( !m_boxFile.seek( a->startOffset() ) ) {
00344     kError(5003) <<"KNFolder::loadArticle(KNLocalArticle *a) : cannot set mbox file-pointer!";
00345     closeFiles();
00346     return false;
00347   }
00348 
00349   //read content
00350   m_boxFile.readLine(); //skip X-KNode-Overview
00351 
00352   unsigned int size = a->endOffset() - m_boxFile.pos() - 1;
00353   QByteArray buff;
00354   buff.resize( size + 10 );
00355   int readBytes=m_boxFile.read(buff.data(), size);
00356   closeFiles();
00357   if ( readBytes < (int)(size) && m_boxFile.error() != QFile::NoError ) {  // cannot read file
00358     kError(5003) <<"KNFolder::loadArticle(KNLocalArticle *a) : corrupted mbox file, IO-error!";
00359     return false;
00360   }
00361 
00362   //set content
00363   buff.resize( readBytes );
00364   a->setContent(buff);
00365   a->parse();
00366 
00367   return true;
00368 }
00369 
00370 
00371 bool KNFolder::saveArticles( KNLocalArticle::List &l )
00372 {
00373   if(!isLoaded())  // loading should not be done here - keep the StorageManager in sync !!
00374     return false;
00375 
00376   if(!m_boxFile.open(QIODevice::WriteOnly | QIODevice::Append)) {
00377     kError(5003) <<"KNFolder::saveArticles() : cannot open mbox-file!";
00378     closeFiles();
00379     return false;
00380   }
00381 
00382   int addCnt=0;
00383   bool ret=true;
00384   bool clear=false;
00385   QTextStream ts(&m_boxFile);
00386   ts.setCodec( "ISO 8859-1" );
00387 
00388   for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00389 
00390     clear=false;
00391     if ( (*it)->id() == -1 || (*it)->collection() != this ) {
00392       if ( (*it)->id() != -1 ) {
00393         KNFolder *oldFolder = static_cast<KNFolder*>( (*it)->collection() );
00394         if ( !(*it)->hasContent() )
00395           if( !( clear = oldFolder->loadArticle( (*it) ) ) ) {
00396             ret = false;
00397             continue;
00398           }
00399 
00400         KNLocalArticle::List l;
00401         l.append( (*it) );
00402         oldFolder->removeArticles( l, false );
00403       }
00404       if ( !append( (*it) ) ) {
00405         kError(5003) <<"KNFolder::saveArticle(KNLocalArticle::List *l) : cannot append article!";
00406         ret = false;
00407         continue;
00408         (*it)->setCollection(0);
00409       }
00410       else {
00411         (*it)->setCollection(this);
00412         addCnt++;
00413       }
00414     }
00415 
00416     if ( byId( (*it)->id() ) == (*it) ) {
00417 
00418       //MBox
00419       ts << "From aaa@aaa Mon Jan 01 00:00:00 1997\n";
00420       ts.flush();
00421       (*it)->setStartOffset( m_boxFile.pos() ); //save offset
00422 
00423       //write overview information
00424       ts << "X-KNode-Overview: ";
00425       ts << (*it)->subject()->as7BitString(false) << '\t';
00426 
00427       KMime::Headers::Base* h;
00428       if( ( h = (*it)->newsgroups( false ) ) !=0 )
00429         ts << h->as7BitString(false);
00430       ts << '\t';
00431 
00432       if( (h = (*it)->to( false ) ) != 0 )
00433         ts << h->as7BitString(false);
00434       ts << '\t';
00435 
00436       ts << (*it)->lines()->as7BitString(false) << '\n';
00437 
00438       //write article
00439       (*it)->toStream( ts );
00440       ts << "\n";
00441       ts.flush();
00442 
00443       (*it)->setEndOffset( m_boxFile.pos() ); //save offset
00444 
00445       //update
00446       ArticleWidget::articleChanged( (*it) );
00447       i_ndexDirty=true;
00448 
00449     }
00450     else {
00451       kError(5003) <<"KNFolder::saveArticle() : article not in folder!";
00452       ret=false;
00453     }
00454 
00455     if ( clear )
00456       (*it)->Content::clear();
00457   }
00458 
00459   closeFiles();
00460   syncIndex();
00461 
00462   if(addCnt>0) {
00463     c_ount=length();
00464     updateListItem();
00465     knGlobals.articleManager()->updateViewForCollection(this);
00466   }
00467 
00468   return ret;
00469 }
00470 
00471 
00472 void KNFolder::removeArticles( KNLocalArticle::List &l, bool del )
00473 {
00474   if( !isLoaded() || l.isEmpty() )
00475     return;
00476 
00477   int idx = 0, delCnt = 0, *positions;
00478   positions = new int[l.count()];
00479   KNLocalArticle *a = 0;
00480 
00481   for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it, ++idx ) {
00482     if ( (*it)->isLocked() )
00483       positions[idx] = -1;
00484     else
00485       positions[idx] = a_rticles.indexForId( (*it)->id() );
00486   }
00487 
00488   for ( idx = 0; idx < (int)(l.count()); ++idx ) {
00489     if(positions[idx]==-1)
00490       continue;
00491 
00492     a=at(positions[idx]);
00493 
00494     //update
00495     knGlobals.artFactory->deleteComposerForArticle(a);
00496     ArticleWindow::closeAllWindowsForArticle( a );
00497     ArticleWidget::articleRemoved( a );
00498     delete a->listItem();
00499 
00500     //delete article
00501     a_rticles.remove(positions[idx], del, false);
00502     delCnt++;
00503     if(!del)
00504       a->setId(-1);
00505   }
00506 
00507   if(delCnt>0) {
00508     compact();
00509     c_ount-=delCnt;
00510     updateListItem();
00511     i_ndexDirty=true;
00512   }
00513   delete[] positions;
00514 }
00515 
00516 
00517 void KNFolder::deleteAll()
00518 {
00519   if(l_ockedArticles>0)
00520     return;
00521 
00522   if (!unloadHdrs(true))
00523     return;
00524 
00525   clear();
00526   c_ount=0;
00527   syncIndex(true);
00528   updateListItem();
00529 }
00530 
00531 
00532 void KNFolder::deleteFiles()
00533 {
00534   m_boxFile.remove();
00535   i_ndexFile.remove();
00536   QFile::remove(i_nfoPath);
00537 }
00538 
00539 
00540 void KNFolder::syncIndex(bool force)
00541 {
00542   if(!i_ndexDirty && !force)
00543     return;
00544 
00545   if(!i_ndexFile.open(QIODevice::WriteOnly)) {
00546     kError(5003) <<"KNFolder::syncIndex(bool force) : cannot open index-file!";
00547     closeFiles();
00548     return;
00549   }
00550 
00551   KNLocalArticle *a;
00552   DynData d;
00553   for(int idx=0; idx<length(); idx++) {
00554     a=at(idx);
00555     d.setData(a);
00556     i_ndexFile.write((char*)(&d), sizeof(DynData));
00557   }
00558   closeFiles();
00559 
00560   i_ndexDirty=false;
00561 }
00562 
00563 
00564 void KNFolder::closeFiles()
00565 {
00566   if(m_boxFile.isOpen())
00567     m_boxFile.close();
00568   if(i_ndexFile.isOpen())
00569     i_ndexFile.close();
00570 }
00571 
00572 
00573 //==============================================================================
00574 
00575 
00576 void KNFolder::DynData::setData(KNLocalArticle *a)
00577 {
00578   id=a->id();
00579   so=a->startOffset();
00580   eo=a->endOffset();
00581   sId=a->serverId();
00582   ti=a->date()->dateTime().toTime_t();
00583 
00584   flags[0]=a->doMail();
00585   flags[1]=a->mailed();
00586   flags[2]=a->doPost();
00587   flags[3]=a->posted();
00588   flags[4]=a->canceled();
00589   flags[5]=a->editDisabled();
00590 }
00591 
00592 
00593 void KNFolder::DynData::getData(KNLocalArticle *a)
00594 {
00595   a->setId(id);
00596   KDateTime dt;
00597   dt.setTime_t( ti );
00598   a->date()->setDateTime( dt );
00599   a->setStartOffset(so);
00600   a->setEndOffset(eo);
00601   a->setServerId(sId);
00602   a->setDoMail(flags[0]);
00603   a->setMailed(flags[1]);
00604   a->setDoPost(flags[2]);
00605   a->setPosted(flags[3]);
00606   a->setCanceled(flags[4]);
00607   a->setEditDisabled(flags[5]);
00608 }
00609 

knode

Skip menu "knode"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal