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
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
00353 QByteArray data;
00354
00355 QDataStream out( data, IO_WriteOnly );
00356 out.setVersion( 3 );
00357
00358
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
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
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
00587
00588 out << QString( "F" );
00589 out << *((const Folder*)folderChild);
00590 }
00591 else if( strcmp( folderChild->className(), "Vocabulary" ) == 0 ) {
00592
00593
00594 out << QString( "V" );
00595
00596
00597
00598 out << ((Vocabulary*)folderChild)->getId();
00599 }
00600 }
00601 }
00602
00603 out << QString( "EOF" );
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 }