#include "DictionaryReader.h" #include "Dictionary.h" #include "../version.h" #include "CardPack.h" #include "DicRecord.h" #include "../field-styles/FieldStyleFactory.h" #include #include const QString DictionaryReader::MinSupportedDictVersion = "0.3"; DictionaryReader::DictionaryReader( Dictionary* aDict ): m_dict( aDict ) { } bool DictionaryReader::read( QIODevice* aDevice ) { setDevice( aDevice ); while( !atEnd() ) { readNext(); if( isStartElement() ) { if( name() == "dict" ) readDict(); else raiseError( Dictionary::tr("The file is not a dictionary file.") ); } } return !error(); } void DictionaryReader::readDict() { Q_ASSERT( isStartElement() && name() == "dict" ); m_dict->m_contentModified = false; QString id = attributes().value( "id" ).toString(); if(!id.isEmpty()) // Id is obsolete. If it exists, write it down just for loading the study file. m_dict->obsoleteId = QUuid(id); m_dictVersion = attributes().value( "version" ).toString(); if( m_dictVersion == DIC_VERSION) readDictCurrentVersion(); else if( m_dictVersion == "1.0" ) { notifyObsoleteVersion(m_dictVersion); readDictCurrentVersion(); } else if( m_dictVersion == "0.4" ) { notifyObsoleteVersion( m_dictVersion ); readDict04(); } else if( m_dictVersion == "0.3" ) { notifyObsoleteVersion( m_dictVersion ); readDict03(); } else { QMessageBox::warning( NULL, Dictionary::tr("Unsupported format"), Dictionary::tr("Dictionary uses unsupported format %1.\n" "The minimum supported version is %2" ) .arg( m_dictVersion ) .arg( MinSupportedDictVersion ) ); } } void DictionaryReader::notifyObsoleteVersion( const QString& aOldVersion ) { QMessageBox::warning( NULL, Dictionary::tr("Old dictionary"), Dictionary::tr("Dictionary %1 uses obsolete format %2.\n" "It will be converted to the current format %3." ) .arg(m_dict->shortName(false)) .arg(aOldVersion).arg(DIC_VERSION)); m_dict->m_contentModified = true; } void DictionaryReader::readUnknownElement() { Q_ASSERT( isStartElement() ); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) readUnknownElement(); } } void DictionaryReader::readDictCurrentVersion() { while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "fields" ) readFields(); else if( name() == "packs" ) readPacks(); else if( name() == "entries" ) readEntries(); else readUnknownElement(); } } } void DictionaryReader::readFields() { Q_ASSERT( isStartElement() && name() == "fields" ); if( m_dictVersion == "0.4" ) { m_curCardPack = new CardPack( m_dict ); m_curAnsFieldList.clear(); } while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "field" ) readField(); else readUnknownElement(); } } if( m_dictVersion == "0.4" && m_curCardPack ) { m_curCardPack->setAnsFields( m_curAnsFieldList ); m_dict->m_cardPacks << m_curCardPack; // And create the reversed pack: qst and ans swapped CardPack* pack2 = new CardPack( m_dict ); pack2->setQstField( m_curCardPack->getAnswerFields()[0] ); QList fList2; fList2 << m_curCardPack->getQuestionField(); // First answer for( int i=1; igetAnswerFields().size(); i++ ) // Other answers fList2 << m_curCardPack->getAnswerFields()[i]; pack2->setAnsFields( fList2 ); m_dict->m_cardPacks << pack2; } } void DictionaryReader::readField() { Q_ASSERT( isStartElement() && name() == "field" ); QString qstAttr; QString ansAttr; QString id04Attr; if( m_dictVersion == "0.4" ) { qstAttr = attributes().value("question").toString(); ansAttr = attributes().value("answer").toString(); id04Attr = attributes().value("id").toString(); } QString style = attributes().value("style").toString(); if( style.isEmpty() ) style = FieldStyleFactory::DefaultStyle; QString fieldName = readElementText().trimmed(); Field* field = new Field( fieldName, style ); m_dict->m_fields << field; // insert in order of occurence if( m_dictVersion == "0.4" ) { Field* field = m_dict->m_fields.last(); if( !id04Attr.isEmpty() ) field->setId04( id04Attr ); if( qstAttr == "yes" && m_curCardPack ) m_curCardPack->setQstField( field ); else { bool ok; int ansIx = ansAttr.toInt( &ok ); if( ok ) m_curAnsFieldList.insert( ansIx, field ); } } } void DictionaryReader::readPacks() { Q_ASSERT( isStartElement() && name() == "packs" ); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "pack" ) readPack(); else readUnknownElement(); } } } void DictionaryReader::readPack() { Q_ASSERT( isStartElement() && name() == "pack" ); CardPack* cardPack = new CardPack( m_dict ); QString exactAnswer = attributes().value("exact-ans").toString(); if(exactAnswer == "true") cardPack->setUsesExactAnswer(true); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "qst" || name() == "ans" ) { QString fieldName = readElementText().trimmed(); const Field* field = m_dict->field( fieldName ); if( !field ) continue; if( name() == "qst" ) cardPack->setQstField( field ); else // ans cardPack->addField( field ); } else readUnknownElement(); } } m_dict->addCardPack( cardPack ); } void DictionaryReader::readEntries() { Q_ASSERT( isStartElement() && name() == "entries" ); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "e" ) readE(); else readUnknownElement(); } } } /** Read entry */ void DictionaryReader::readE() { DicRecord* dicEntry = new DicRecord; if( m_dictVersion == "0.4" ) { QString idStr = attributes().value("id").toString(); dicEntry->setId04( idStr ); } int curFieldIx = 0; while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "f" ) { if( m_dictVersion == "0.4" ) { QString fieldId04 = attributes().value("id").toString(); int ix = m_dict->fieldId04ToIx( fieldId04 ); if( ix > -1 ) // found curFieldIx = ix; } QString fieldValue = readElementText().trimmed(); const Field* field = m_dict->field( curFieldIx ); if( !field ) break; // no more fields dicEntry->setField( field->name(), fieldValue ); curFieldIx++; } else readUnknownElement(); } } m_dict->records << dicEntry; } void DictionaryReader::readDict04() { Q_ASSERT( isStartElement() && name() == "dict" && attributes().value("version") == "0.4" ); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "fields" ) readFields(); else if( name() == "c" ) readE(); else readUnknownElement(); } } } void DictionaryReader::readDict03() { Q_ASSERT( isStartElement() && name() == "dict" && attributes().value("version") == "0.3" ); // Read entries while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { if( name() == "card" ) readE03(); else readUnknownElement(); } } } /** Read entry v.0.3*/ void DictionaryReader::readE03() { Q_ASSERT( isStartElement() && m_dictVersion == "0.3" && name() == "card" ); DicRecord* dicEntry = new DicRecord; QMap fieldNames; // tag name, field name fieldNames["qst"] = Dictionary::tr("Question"); fieldNames["ans"] = Dictionary::tr("Answer"); fieldNames["xmp"] = Dictionary::tr("Example"); while( !atEnd() ) { readNext(); if( isEndElement() ) break; if( isStartElement() ) { QString tagName = name().toString(); if( fieldNames.contains( tagName ) ) { QString fieldValue = readElementText().trimmed(); dicEntry->setField( fieldNames.value( tagName ), fieldValue ); } else readUnknownElement(); } } m_dict->records << dicEntry; }