Folder.cpp

Go to the documentation of this file.
00001 #include "Folder.h"
00002 
00003 Folder::Folder( int id, const QString& title ) : Base(), id( id ), title( title ), markedForStudy( false ), markedForDeletion( false ), 
00004     dirty( false ), parent( NULL ) {
00005     QDateTime now( QDateTime::currentDateTime() );
00006     creationDate = modificationDate = now;
00007 }
00008 
00009 Folder::Folder( const Folder& folder ) 
00010     : Base(), id( folder.id ), title( folder.title ), description( folder.description ), author( folder.author ),
00011         creationDate( folder.creationDate ), modificationDate( folder.modificationDate ), 
00012             markedForStudy( folder.isMarkedForStudy() ), markedForDeletion( folder.markedForDeletion ), dirty( folder.dirty ), parent( folder.parent ) {
00013     for( QListIterator<Base> it( folder.children ); it.current(); ++it ) {
00014         const Base* childItem = it.current();
00015         if( strcmp( childItem->className(), "Folder" ) == 0 ) {
00016             Folder* childFolder = new Folder( *((Folder*)childItem) );
00017             add( childFolder );
00018         }
00019         else if( strcmp( childItem->className(), "Vocabulary" ) == 0 ) {
00020             Vocabulary* childVocab = new Vocabulary( *((Vocabulary*)childItem) ); 
00021             add( childVocab );
00022         }
00023     }
00024 }
00025 
00026 Folder::~Folder() {
00027 }
00028 
00029 int Folder::getId() const {
00030     return( id );
00031 }
00032 
00033 int Folder::getMaxId() {
00034     int maxId = getId();
00035     for( Base* child = children.first(); child; child = children.next() ) {
00036         if( strcmp( child->className(), "Folder" ) == 0 ) {
00037             int childMaxId = ((Folder*)child)->getMaxId();
00038             if( childMaxId > maxId )
00039                 maxId = childMaxId;
00040         }
00041     }
00042     return( maxId );
00043 }
00044 
00045 int Folder::getMaxVocabId() {
00046     int maxId = 0;
00047     for( Base* child = children.first(); child; child = children.next() ) { 
00048         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00049             Vocabulary* vocab = (Vocabulary*)child;
00050             if( vocab->getId() > maxId )
00051                 maxId = vocab->getId();
00052         }
00053         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00054             int childMaxId = ((Folder*)child)->getMaxVocabId();
00055             if( childMaxId > maxId )
00056                 maxId = childMaxId;
00057         }
00058     }
00059     return( maxId );
00060 }
00061 
00062 
00063 const QString Folder::getTitle() const {
00064     return( title );
00065     //return( title + QString( "(" ) + QString::number( getId() ) + QString( ")" ) ); // For debugging.
00066 }
00067 
00068 void Folder::setTitle( const QString& title ) {
00069     this->title = title;
00070 }
00071 
00072 const QString Folder::getDescription() const {
00073     return( description );
00074 }
00075 
00076 void Folder::setDescription( const QString& desc ) {
00077     this->description = desc;
00078 }
00079 
00080 const QString Folder::getAuthor() const {
00081     return( author );
00082 }
00083 
00084 void Folder::setAuthor( const QString& author ) {
00085     this->author = author;
00086 }
00087 
00088 const QDateTime Folder::getCreationDate() const {
00089     return( creationDate );
00090 }
00091 
00092 void Folder::setCreationDate( const QDateTime& creationDate ) {
00093     this->creationDate = creationDate;
00094 }
00095 
00096 const QDateTime Folder::getModificationDate() const {
00097     return( modificationDate );
00098 }
00099 
00100 void Folder::setModificationDate( const QDateTime& modificationDate ) {
00101     this->modificationDate = modificationDate;
00102 }
00103 
00104 bool Folder::isMarkedForStudy() const {
00105     return( markedForStudy );
00106 }
00107 
00108 void Folder::setMarkedForStudy( bool isMarkedForStudy ) {
00109     markedForStudy = isMarkedForStudy;
00110 }
00111 
00112 bool Folder::isMarkedForDeletion() const {
00113     return( markedForDeletion );
00114 }
00115 
00116 void Folder::setMarkedForDeletion( bool isMarkedForDeletion ) {
00117     markedForDeletion = isMarkedForDeletion;
00118     for( QListIterator<Base> it( children ); it.current(); ++it ) {
00119         const Base* folderChild = it.current();
00120         if( strcmp( folderChild->className(), "Folder" ) == 0 ) {
00121             Folder* childFolder = (Folder*)folderChild;
00122             childFolder->setMarkedForDeletion( isMarkedForDeletion );
00123         }
00124         else if( strcmp( folderChild->className(), "Vocabulary" ) == 0 ) {
00125             Vocabulary* childVocab = (Vocabulary*)folderChild;
00126             childVocab->setMarkedForDeletion( isMarkedForDeletion );
00127         }
00128     }
00129 
00130 }
00131 
00132 bool Folder::containsTermWithTranslations( const QString& lang1, const QString& lang2 ) {
00133     for( Base* child = children.first(); child; child = children.next() ) {
00134         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00135             Vocabulary* vocab = (Vocabulary*)child;
00136             if( vocab->containsTermWithTranslations( lang1, lang2 ) )
00137                 return( true );
00138         }
00139         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00140             Folder* folder = (Folder*)child;
00141             if( folder->containsTermWithTranslations( lang1, lang2 ) )
00142                 return( true );
00143         }
00144     }
00145     return( false );
00146 }
00147 
00148 bool Folder::isReachableFromRoot() const {
00149     if( !isMarkedForStudy() )
00150         return( false );
00151     const Folder* folder = this;
00152     for( ;; ) {
00153         folder = folder->getParent();
00154         if( !folder )
00155             return( true );
00156         if( !folder->isMarkedForStudy() )
00157             return( false );
00158     } 
00159 }
00160 
00161 Folder* Folder::getFolder( int id ) {
00162     if( getId() == id )
00163         return( this );
00164 
00165     for( Base* child = children.first(); child; child = children.next() ) { 
00166         if( strcmp( child->className(), "Folder" ) == 0 ) {
00167             Folder* childFolder = (Folder*)child;
00168             Folder* folder = childFolder->getFolder( id );
00169             if( folder )
00170                 return( folder );
00171         }
00172     }
00173 
00174     return( NULL );
00175 }
00176 
00177 QStringList Folder::getTranslationLanguages() {
00178     QStringList languages;
00179     for( Base* child = children.first(); child; child = children.next() ) {
00180         QStringList childLanguages;
00181         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00182             Vocabulary* vocab = (Vocabulary*)child;
00183             childLanguages = vocab->getTranslationLanguages();
00184         }
00185         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00186             Folder* folder = (Folder*)child;
00187             childLanguages = folder->getTranslationLanguages();
00188         }
00189         for( QStringList::ConstIterator it = childLanguages.begin(); it != childLanguages.end(); it++ ) {
00190             const QString& lang = *it;
00191             if( !languages.contains( lang ) )
00192                 languages.append( lang );
00193         }
00194     }
00195     return( languages );
00196 }
00197 
00198 void Folder::removeTranslations( const QStringList& languages ) {
00199     for( Base* child = children.first(); child; child = children.next() ) {
00200         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00201             Vocabulary* vocab = (Vocabulary*)child;
00202             vocab->removeTranslations( languages );
00203         }
00204         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00205             Folder* folder = (Folder*)child;
00206             folder->removeTranslations( languages );
00207         }
00208     }
00209 }
00210 
00211 void Folder::add( Vocabulary* child ) {
00212     children.append( child );
00213     child->setParent( this );
00214 }
00215 
00216 void Folder::add( Folder* child ) {
00217     children.append( child );
00218     child->setParent( this );
00219 }
00220 
00221 void Folder::remove( Vocabulary* child ) {
00222     children.remove( child );
00223     delete( child );
00224 }
00225 
00226 void Folder::remove( Folder* child ) {
00227     children.remove( child );
00228     delete( child );
00229 }
00230 
00231 bool Folder::isEmpty() const {
00232     return( children.isEmpty() );
00233 }
00234 
00235 int Folder::getChildrenCount() const {
00236     return( children.count() );
00237 }
00238 
00239 Vocabulary* Folder::getVocabulary( int id ) {
00240     return( getVocabularyRec( id ) );
00241 }
00242 
00243 Base* Folder::first() {
00244     return( children.first() );
00245 }
00246 
00247 Base* Folder::next() {
00248     return( children.next() );
00249 }
00250 
00251 bool Folder::load( const QString& filename ) {
00252     QFile dataFile( filename );
00253     if( !dataFile.open( IO_ReadOnly ) )
00254         return( false );
00255     
00256     QByteArray compressedData( dataFile.readAll() );
00257     QByteArray data( Util::qUncompress( compressedData ) );
00258 
00259     QDataStream in( data, IO_ReadOnly );
00260 
00261     Q_UINT32 tempMagicNumber;
00262     Q_UINT16 tempVersion;
00263     Folder tempFolder;
00264 
00265     in >> tempMagicNumber >> tempVersion;
00266 
00267     if( tempMagicNumber != Folder::magicNumber ) {
00268         cerr << "Wrong magic number: Incompatible folder data file." << endl;
00269         return( false );
00270     }
00271     if( tempVersion > 0x0009 ) {
00272         cerr << "Folder data file is from a more recent version.  Upgrade toMOTko." << endl;
00273         return( false );
00274     }
00275 
00276     in.setVersion( 3 );
00277     in >> tempFolder;
00278 
00279     dataFile.close();
00280 
00281     id = tempFolder.getId();
00282     title = tempFolder.getTitle();
00283     description = tempFolder.getDescription();
00284     author = tempFolder.getAuthor();
00285     creationDate = tempFolder.getCreationDate();
00286     modificationDate = tempFolder.getModificationDate();
00287     markedForStudy = tempFolder.isMarkedForStudy();
00288 
00289     for( QListIterator<Base> it( tempFolder.children ); it.current(); ++it ) {
00290         const Base* childItem = it.current();
00291         if( strcmp( childItem->className(), "Folder" ) == 0 ) {
00292             Folder* folder = (Folder*)childItem;
00293             add( folder );
00294         }
00295         else if( strcmp( childItem->className(), "Vocabulary" ) == 0 ) {
00296             Vocabulary* vocab = (Vocabulary*)childItem;
00297             add( vocab );
00298         }
00299     }
00300 
00301     return( true );
00302 }
00303 
00304 bool Folder::loadMetadata( const QString& filename ) {
00305     QFile dataFile( filename );
00306     if( !dataFile.open( IO_ReadOnly ) ) {
00307         cerr << "Cannot open metadata file: " << filename << endl;
00308         return( false );
00309     }
00310     
00311     QByteArray compressedData( dataFile.readAll() );
00312     QByteArray data( Util::qUncompress( compressedData ) );
00313 
00314     QDataStream in( data, IO_ReadOnly );
00315 
00316     Q_UINT32 tempMagicNumber;
00317     Q_UINT16 tempVersion;
00318     int tempId;
00319     QString tempTitle;
00320     QString tempDescription;
00321     QString tempAuthor;
00322     QDateTime tempCreationDate;
00323     QDateTime tempModificationDate;
00324 
00325     in >> tempMagicNumber >> tempVersion;
00326 
00327     if( tempMagicNumber != Folder::magicNumber ) {
00328         cerr << "Wrong magic number: Incompatible folder data file." << endl;
00329         return( false );
00330     }
00331     if( tempVersion > 0x0010 ) {
00332         cerr << "Folder data file is from a more recent version.  Upgrade toMOTko." << endl;
00333         return( false );
00334     }
00335 
00336     in.setVersion( 3 );
00337     in >> tempId >> tempTitle >> tempDescription >> tempAuthor >> tempCreationDate >> tempModificationDate;
00338 
00339     dataFile.close();
00340 
00341     id = tempId;
00342     title = tempTitle;
00343     description = tempDescription;
00344     author = tempAuthor;
00345     creationDate = tempCreationDate;
00346     modificationDate = tempModificationDate;
00347 
00348     return( true );
00349 }
00350 
00351 bool Folder::saveMetadata( const QString& filename ) const {
00352     //cerr << "saveMetadata " << filename << endl;
00353     QByteArray data;
00354 
00355     QDataStream out( data, IO_WriteOnly );
00356     out.setVersion( 3 /* QDataStream::Qt_3 ? */ );
00357 
00358     // 0x0010 means 0.10.x version.
00359     out << Q_UINT32( Folder::magicNumber ) << Q_UINT16( 0x0010 );
00360     out << getId() << getTitle() << getDescription() << getAuthor() << getCreationDate() << getModificationDate();  
00361 
00362     QByteArray compressedData( Util::qCompress( data ) ); 
00363 
00364     QFile dataFile( filename );
00365     QFileInfo dataFileInfo( dataFile );
00366 
00367     if( !Util::makeDirectory( dataFileInfo.dirPath() ) )
00368         return( false );
00369 
00370     if( !dataFile.open( IO_WriteOnly ) )
00371         return( false );
00372 
00373     int ret = dataFile.writeBlock( compressedData );
00374     dataFile.close();
00375 
00376     if( ret == -1 || dataFile.status() != IO_Ok ) {
00377         dataFile.resetStatus();
00378         return( false );
00379     }
00380 
00381     return( true );
00382 }
00383 
00384 void Folder::buildVocabCopiesMap( QMap<int,Vocabulary>& vocabularies ) const {
00385     for( QListIterator<Base> it( children ); it.current(); ++it ) {
00386         const Base* folderChild = it.current();
00387         if( strcmp( folderChild->className(), "Folder" ) == 0 ) {
00388             Folder* childFolder = (Folder*)folderChild;
00389             childFolder->buildVocabCopiesMap( vocabularies );
00390         }
00391         else if( strcmp( folderChild->className(), "Vocabulary" ) == 0 ) {
00392             Vocabulary* childVocab = (Vocabulary*)folderChild;
00393             vocabularies.insert( childVocab->getId(), *childVocab );
00394         }
00395     }
00396 }
00397 
00398 Folder* Folder::getRoot() const {
00399     if( getParent() )
00400         return( getParent()->getRoot() );
00401     return( (Folder*)this );
00402 }
00403 
00404 bool Folder::isDirty() const {
00405     return( dirty );
00406 }
00407 
00408 void Folder::setDirty( bool isDirty, bool recursive = false ) {
00409     dirty = isDirty;
00410     if( recursive ) {
00411         for( Base* child = children.first(); child; child = children.next() ) { 
00412             if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00413                 Vocabulary* childVocab = (Vocabulary*)child;
00414                 childVocab->setDirty( isDirty );
00415             }
00416             else if( strcmp( child->className(), "Folder" ) == 0 ) {
00417                 Folder* childFolder = ((Folder*)child);
00418                 childFolder->setDirty( isDirty, true );
00419             }
00420         }
00421     }
00422 }
00423 
00424 Folder* Folder::getParent() const {
00425     return( parent );
00426 }
00427 
00428 QString Folder::getPath() const {
00429     Folder* parentFolder = getParent();
00430     if( parentFolder )
00431         return( QString( parentFolder->getPath() + QString( "/" ) + QString::number( getId() ) ) );
00432     else
00433         return( QString::number( getId() ) );
00434 }
00435 
00436 QString Folder::getHumanReadablePath() const {
00437     Folder* rootFolder = getRoot();
00438     QString str;
00439     QStringList folders = QStringList::split( "/", getPath() );
00440     QString delim = "";
00441     for( QStringList::Iterator it = folders.begin(); it != folders.end(); it++ ) {
00442         QString strFolderId = *it;
00443         bool isFolderIdValid;
00444         int folderId = strFolderId.toInt( &isFolderIdValid, 10 );
00445         if( isFolderIdValid ) {
00446             Folder* folder = rootFolder->getFolder( folderId );
00447             if( folder ) {
00448                 str += delim + folder->getTitle();
00449                 delim = "/";
00450             }
00451         }
00452     }
00453     return( str ); 
00454 }
00455 
00456 void Folder::setParent( Folder* parent ) {
00457     this->parent = parent;
00458 }
00459 
00460 /*
00461 uint Folder::getTermCount() {
00462     uint termCount = 0;
00463     for( Base* child = children.first(); child; child = children.next() ) { 
00464         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00465             Vocabulary* vocab = (Vocabulary*)child;
00466             termCount += vocab->getSize();
00467         }
00468         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00469             Folder* folder = (Folder*)child;
00470             termCount += folder->getTermCount();
00471         }
00472     }
00473     return( termCount );
00474 }
00475 
00476 uint Folder::getVocabularyCount() {
00477     uint vocabCount = 0;
00478     for( Base* child = children.first(); child; child = children.next() ) { 
00479         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00480             vocabCount += 1; 
00481         }
00482         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00483             Folder* folder = (Folder*)child;
00484             vocabCount += folder->getVocabularyCount();
00485         }
00486     }
00487     return( vocabCount );
00488 }
00489 
00490 uint Folder::getFolderCount() {
00491     uint folderCount = 0;
00492     for( Base* child = children.first(); child; child = children.next() ) { 
00493         if( strcmp( child->className(), "Folder" ) == 0 ) {
00494             folderCount += 1;
00495         }
00496     }
00497     return( folderCount );
00498 }
00499 */
00500 
00501 void Folder::getItemsCount( uint* termCount, uint* vocabCount, uint* folderCount, 
00502         uint* checkedTermCount, uint* checkedVocabCount, uint* checkedFolderCount, 
00503             uint* selectedTermCount, uint* selectedVocabCount, uint* selectedFolderCount, 
00504                 bool isReachableFromRoot,
00505                     const QString& firstLang = QString::null, const QString& testLang = QString::null ) {
00506     if( !isMarkedForDeletion() ) {
00507         for( Base* child = children.first(); child; child = children.next() ) { 
00508             if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00509                 Vocabulary* vocab = (Vocabulary*)child;
00510                 if( !vocab->isMarkedForDeletion() ) {
00511                     if( !firstLang.isNull() && !testLang.isNull() ) {
00512                         if( vocab->containsTermWithTranslations( firstLang, testLang ) ) {
00513                             *vocabCount += 1;
00514                             if( vocab->isMarkedForStudy() ) {
00515                                 *checkedVocabCount += 1;
00516                                 if( isReachableFromRoot )
00517                                     *selectedVocabCount += 1;
00518                             }
00519                         }
00520                     }
00521                     else {
00522                         *vocabCount += 1;
00523                         if( vocab->isMarkedForStudy() ) {
00524                             *checkedVocabCount += 1;
00525                             if( isReachableFromRoot )
00526                                 *selectedVocabCount += 1;
00527                         }
00528                     }
00529                     vocab->getItemsCount( termCount, checkedTermCount, selectedTermCount, isReachableFromRoot && vocab->isMarkedForStudy(), firstLang, testLang );
00530                 }
00531             }
00532             else if( strcmp( child->className(), "Folder" ) == 0 ) {
00533                 Folder* folder = (Folder*)child;
00534                 if( !folder->isMarkedForDeletion() ) {
00535                     if( !firstLang.isNull() && !testLang.isNull() ) {
00536                         if( folder->containsTermWithTranslations( firstLang, testLang ) ) {
00537                             *folderCount += 1;
00538                             if( folder->isMarkedForStudy() ) {
00539                                 *checkedFolderCount += 1;
00540                                 if( isReachableFromRoot )
00541                                     *selectedFolderCount += 1;
00542                             }
00543                         }
00544                     }
00545                     else {
00546                         *folderCount += 1;
00547                         if( folder->isMarkedForStudy() ) {
00548                             *checkedFolderCount += 1;
00549                             if( isReachableFromRoot )
00550                                 *selectedFolderCount += 1;
00551                         }
00552                     }
00553                     folder->getItemsCount( termCount, vocabCount, folderCount, 
00554                         checkedTermCount, checkedVocabCount, checkedFolderCount,
00555                             selectedTermCount, selectedVocabCount, selectedFolderCount, 
00556                                 isReachableFromRoot && folder->isMarkedForStudy(), firstLang, testLang );
00557                 }
00558             }
00559         }
00560     }
00561 }
00562 
00563 Vocabulary* Folder::getVocabularyRec( int id ) {
00564     for( Base* child = children.first(); child; child = children.next() ) { 
00565         if( strcmp( child->className(), "Vocabulary" ) == 0 ) {
00566             Vocabulary* vocab = (Vocabulary*)child;
00567             if( vocab->getId() == id )
00568                 return( vocab );
00569         }
00570         else if( strcmp( child->className(), "Folder" ) == 0 ) {
00571             Vocabulary* vocab = ((Folder*)child)->getVocabularyRec( id );
00572             if( vocab )
00573                 return( vocab );
00574         }
00575     }
00576     return( NULL );
00577 }
00578 
00579 QDataStream& operator<<( QDataStream& out, const Folder& folder ) {
00580     out << folder.getId() << folder.getTitle() << folder.getDescription() << folder.getAuthor();
00581     out << folder.getCreationDate() << folder.getModificationDate();
00582     if( !folder.isEmpty() ) {
00583         for( QListIterator<Base> it( folder.children ); it.current(); ++it ) {
00584             const Base* folderChild = it.current();
00585             if( strcmp( folderChild->className(), "Folder" ) == 0 ) {
00586                 // This deliminer indicates that what follows is a folder.
00587                 // This is required as the structure is recursive and heterogeous (contains folder and vocabularies).
00588                 out << QString( "F" );
00589                 out << *((const Folder*)folderChild);
00590             }
00591             else if( strcmp( folderChild->className(), "Vocabulary" ) == 0 ) {
00592                 // This deliminer indicates that what follows is a folder.
00593                 // This is required as the structure is recursive and heterogeous (contains folder and vocabularies).
00594                 out << QString( "V" );
00595 
00596                 // We just write the vocabulary's idas a reference.
00597                 // Vocabularies are stored separately in their own files to reduce i/o operations.
00598                 out << ((Vocabulary*)folderChild)->getId();
00599             }
00600         }
00601     }
00602 
00603     out << QString( "EOF" ); // End of Folder delimiter.
00604 
00605     return( out );
00606 }
00607 
00608 QDataStream& operator>>( QDataStream& in, Folder& folder ) {
00609     int tempId;
00610     QString tempTitle;
00611     QString tempDescription;
00612     QString tempAuthor;
00613     QDateTime tempCreationDate;
00614     QDateTime tempModificationDate;
00615     QString tempChildType;
00616     Folder tempChildFolder;
00617     int tempVocabId;
00618 
00619     in >> tempId >> tempTitle >> tempDescription >> tempAuthor;
00620     in >> tempCreationDate >> tempModificationDate;
00621 
00622     folder = Folder( tempId, tempTitle );
00623     folder.setDescription( tempDescription );
00624     folder.setAuthor( tempAuthor );
00625     folder.setCreationDate( tempCreationDate );
00626     folder.setModificationDate( tempModificationDate );
00627 
00628     in >> tempChildType;
00629     while( tempChildType != "EOF" ) {
00630         if( tempChildType == "F" ) {
00631             in >> tempChildFolder;
00632             Folder* childFolder = new Folder( tempChildFolder );
00633             folder.add( childFolder );
00634         }
00635         else if( tempChildType == "V" ) {
00636             in >> tempVocabId;
00637             Vocabulary* childVocab = new Vocabulary( tempVocabId );
00638             folder.add( childVocab );
00639         }
00640         in >> tempChildType;
00641     }
00642 
00643     return( in );
00644 }

Generated on Sun Mar 1 17:30:47 2009 for toMOTko by  doxygen 1.5.6