diff options
Diffstat (limited to 'src/dictionary/DictionaryReader.cpp')
-rw-r--r-- | src/dictionary/DictionaryReader.cpp | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/src/dictionary/DictionaryReader.cpp b/src/dictionary/DictionaryReader.cpp new file mode 100644 index 0000000..8a3391c --- /dev/null +++ b/src/dictionary/DictionaryReader.cpp @@ -0,0 +1,384 @@ +#include "DictionaryReader.h" +#include "Dictionary.h" +#include "../version.h" +#include "CardPack.h" +#include "DicRecord.h" +#include "../field-styles/FieldStyleFactory.h" + +#include <QUuid> +#include <QMessageBox> + +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<const Field*> fList2; + fList2 << m_curCardPack->getQuestionField(); // First answer + for( int i=1; i<m_curCardPack->getAnswerFields().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<QString, QString> 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; + } |