summaryrefslogtreecommitdiff
path: root/src/dictionary/DictionaryReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dictionary/DictionaryReader.cpp')
-rw-r--r--src/dictionary/DictionaryReader.cpp384
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;
+ }