Word types were badly defined and multiple strings written in the entries.
- For the next release word types will use the lesson class.
- The container (KEduVocContainer, the current lesson) will be the base for Leitner, Lesson and Word Type.
Rename some writeType to writeWordType.
Update the dtd
svn path=/trunk/KDE/kdeedu/libkdeedu/; revision=742066
#include "keduvockvtmlreader.h"
#include "keduvoccommon_p.h"
+#include <KDebug>
+
KEduVocKvtml2Reader::KEduVocKvtml2Reader( QIODevice *file )
: m_inputFile( file )
{
}
}
- groupElement = domElementParent.firstChildElement( KVTML_WORDTYPEDEFINITIONS );
- if ( !groupElement.isNull() ) {
- readTypes( groupElement );
- }
-
groupElement = domElementParent.firstChildElement( KVTML_TENSES );
if ( !groupElement.isNull() ) {
readTenses( groupElement );
}
}
+ groupElement = domElementParent.firstChildElement( KVTML_WORDTYPES );
+ if ( !groupElement.isNull() ) {
+ readWordTypes( groupElement );
+ }
+
groupElement = domElementParent.firstChildElement( KVTML_LESSONS );
if ( !groupElement.isNull() ) {
- QDomNodeList entryList = groupElement.elementsByTagName( KVTML_LESSON );
- if ( entryList.length() <= 0 ) {
- m_errorMessage = i18n( "no lessons found in 'lessons' tag" );
- return false; // at least one entry is required
+ QDomNodeList entryList = groupElement.elementsByTagName( KVTML_CONTAINER );
+ for ( int i = 0; i < entryList.count(); ++i ) {
+ currentElement = entryList.item( i ).toElement();
+ if ( currentElement.parentNode() == groupElement ) {
+ result = readLesson( currentElement );
+ if ( !result )
+ return false;
+ }
}
+ ///@todo past 4.0: remove reading "lesson" it was only for compability with documents created during the beta for KDE 4.0
+ entryList = groupElement.elementsByTagName( "lesson" );
for ( int i = 0; i < entryList.count(); ++i ) {
currentElement = entryList.item( i ).toElement();
if ( currentElement.parentNode() == groupElement ) {
return false;
}
}
+ // end @todo
}
return true;
}
// read info tags: inactive, inquery, and sizehint
- currentElement = entryElement.firstChildElement( KVTML_INACTIVE );
+ currentElement = entryElement.firstChildElement( KVTML_DEACTIVATED );
if ( !currentElement.isNull() ) {
// set the active state of the expression
if ( currentElement.text() == KVTML_TRUE ) {
expr.translation( index ).setComment( currentElement.text() );
}
- currentElement = translationElement.firstChildElement( KVTML_WORDTYPE );
- if ( !currentElement.isNull() ) {
- QDomElement typeElement = currentElement.firstChildElement( KVTML_TYPENAME );
- expr.translation( index ).setType( typeElement.text() );
- // read subtype if the type is not empty
- typeElement = currentElement.firstChildElement( KVTML_SUBTYPENAME );
- if ( !typeElement.isNull() ) {
- expr.translation( index ).setSubType( typeElement.text() );
- }
- }
-
//<pronunciation></pronunciation>
currentElement = translationElement.firstChildElement( KVTML_PRONUNCIATION );
if ( !currentElement.isNull() ) {
}
//<query>true</query>
- currentElement = lessonElement.firstChildElement( KVTML_QUERY );
+ currentElement = lessonElement.firstChildElement( KVTML_INPRACTICE );
m_doc->lesson(lessonId).setInPractice(currentElement.text() == KVTML_TRUE);
//<current>true</current>
}
}
+ //<entry id="123"/>
+ currentElement = lessonElement.firstChildElement( KVTML_ENTRY );
+ while ( !currentElement.isNull() ) {
+ bool result = false;
+ int id = currentElement.attribute( KVTML_ID ).toInt( &result );
+ if(result) {
+ m_doc->entry(id)->setLesson(lessonId);
+ m_doc->lesson(lessonId).addEntry(id);
+ }
+ currentElement = currentElement.nextSiblingElement( KVTML_ENTRY );
+ }
+
+ ///@todo remove this after 4.0 release. it provides compability with some documents written with kvtml2 prior to the 4.0 release during the beta phase.
//<entryid>0</entryid>
- currentElement = lessonElement.firstChildElement( KVTML_ENTRYID );
+ currentElement = lessonElement.firstChildElement( "entryid" );
while ( !currentElement.isNull() ) {
+ kWarning() << "Found old style lesson definition. Please save this file to update it and notify the creator of it.";
int entryId = currentElement.text().toInt();
- // TODO: once we have a lesson class, add each of these entryids to the lesson
- // set this lesson for the given enty
m_doc->entry( entryId )->setLesson( lessonId );
m_doc->lesson( lessonId ).addEntry( entryId );
- currentElement = currentElement.nextSiblingElement( KVTML_ENTRYID );
+ currentElement = currentElement.nextSiblingElement( "entryid" );
}
+ // end @todo
return true;
}
}
-bool KEduVocKvtml2Reader::readTypes( QDomElement &typesElement )
+bool KEduVocKvtml2Reader::readWordTypes( QDomElement &typesElement )
{
QString mainTypeName;
- QDomElement currentTypeElement = typesElement.firstChildElement( KVTML_WORDTYPEDEFINITION );
+ QDomElement currentTypeElement = typesElement.firstChildElement( KVTML_CONTAINER );
// go over <wordtypedefinition> elements
while ( !currentTypeElement.isNull() ) {
// set type and specialtype
mainTypeName =
- currentTypeElement.firstChildElement( KVTML_TYPENAME ).text();
+ currentTypeElement.firstChildElement( KVTML_NAME ).text();
QString specialType = currentTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
if ( !specialType.isEmpty() ) {
}
}
m_doc->wordTypes().addType( mainTypeName, specialType );
+ kDebug() << "Add word type:" << mainTypeName << "special:" << specialType;
+
+ // set word types to entries:
+ // <entry id="123"><translation id="0"/><translation id="2"/><...></entry>
+ QDomElement entryElement = currentTypeElement.firstChildElement( KVTML_ENTRY );
+ while ( !entryElement.isNull() ) {
+ // read <entry id="123"></entryid>
+ int entryId = entryElement.attribute( KVTML_ID ).toInt();
+ QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
+ while( !translationElement.isNull() ) {
+ // <translation id="234"/>
+ int translationId = translationElement.attribute( KVTML_ID ).toInt();
+ m_doc->entry(entryId)->translation(translationId).setType( mainTypeName );
+ translationElement = translationElement.nextSiblingElement( KVTML_TRANSLATION );
+ }
+ entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
+ }
- // iterate sub type elements <subwordtypedefinition>
- QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_SUBWORDTYPEDEFINITION );
+ // iterate sub type elements <container>
+ QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_CONTAINER );
while ( !currentSubTypeElement.isNull() ) {
QString specialSubType = currentSubTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
if ( !specialSubType.isEmpty() ) {
specialSubType = m_doc->wordTypes().specialTypeNounNeutral();
}
}
+
+ QString subTypeName = currentSubTypeElement.firstChildElement( KVTML_NAME ).text();
// set type and specialtype
- m_doc->wordTypes().addSubType( mainTypeName,
- currentSubTypeElement.firstChildElement( KVTML_SUBTYPENAME ).text(),
- specialSubType );
- currentSubTypeElement = currentSubTypeElement.nextSiblingElement( KVTML_SUBWORDTYPEDEFINITION );
+ m_doc->wordTypes().addSubType( mainTypeName, subTypeName, specialSubType );
+
+ // set word types to entries:
+ // <entry id="123"><translation id="0"/><translation id="2"/><...></entry>
+ entryElement = currentSubTypeElement.firstChildElement( KVTML_ENTRY );
+ while ( !entryElement.isNull() ) {
+ // read <entry id="123"></entryid>
+ int entryId = entryElement.attribute( KVTML_ID ).toInt();
+ QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
+ while( !translationElement.isNull() ) {
+ // <translation id="234"/>
+ int translationId = translationElement.attribute( KVTML_ID ).toInt();
+ // set the main type again, usually the entry will only be in the deepest container in the hierachy
+ m_doc->entry(entryId)->translation(translationId).setType( mainTypeName );
+ m_doc->entry(entryId)->translation(translationId).setSubType( subTypeName );
+ translationElement = translationElement.nextSiblingElement( KVTML_TRANSLATION );
+ }
+ entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
+ }
+ // next sub word type
+ currentSubTypeElement = currentSubTypeElement.nextSiblingElement( KVTML_CONTAINER );
}
- currentTypeElement = currentTypeElement.nextSiblingElement( KVTML_WORDTYPEDEFINITION );
+ // next main word type
+ currentTypeElement = currentTypeElement.nextSiblingElement( KVTML_CONTAINER );
}
return true;
}
/** read the types
* @param typesElement QDomElement for the types group
*/
- bool readTypes( QDomElement &typesElement );
+ bool readWordTypes( QDomElement &typesElement );
/** read the tenses
* @param tensesElement QDomElement for the tenses group
writeIdentifiers( currentElement );
domElementKvtml.appendChild( currentElement );
- // types
- currentElement = m_domDoc.createElement( KVTML_WORDTYPEDEFINITIONS );
- writeTypes( currentElement );
- if ( currentElement.hasChildNodes() ) {
- domElementKvtml.appendChild( currentElement );
- }
-
// tenses
currentElement = m_domDoc.createElement( KVTML_TENSES );
writeTenses( currentElement );
domElementKvtml.appendChild( currentElement );
}
+ // types
+ m_wordTypeElement = m_domDoc.createElement( KVTML_WORDTYPES );
+ writeWordTypes( m_wordTypeElement );
+ if ( m_wordTypeElement.hasChildNodes() ) {
+ domElementKvtml.appendChild( m_wordTypeElement );
+ }
+
m_domDoc.appendChild( domElementKvtml );
QTextStream ts( m_outputFile );
{
for( int lessonId = 0; lessonId < m_doc->lessonCount(); lessonId++ ) {
// make lesson element
- QDomElement thisLessonElement = m_domDoc.createElement( KVTML_LESSON );
+ QDomElement thisLessonElement = m_domDoc.createElement( KVTML_CONTAINER );
// add a name
thisLessonElement.appendChild( newTextElement( KVTML_NAME, m_doc->lesson(lessonId).name() ) );
// add a inquery tag
if ( m_doc->lesson(lessonId).inPractice() ) {
- thisLessonElement.appendChild( newTextElement( KVTML_QUERY, KVTML_TRUE ) );
+ thisLessonElement.appendChild( newTextElement( KVTML_INPRACTICE, KVTML_TRUE ) );
}
// add a current tag
thisLessonElement.appendChild( newTextElement( KVTML_CURRENT, KVTML_TRUE ) );
}
- // TODO: add the entryids...
for ( int i = 0; i < m_doc->entryCount(); ++i ) {
- if ( m_doc->entry( i )->lesson() == lessonId ) {
- thisLessonElement.appendChild( newTextElement( KVTML_ENTRYID, QString::number( i ) ) );
+ if ( m_doc->entry(i)->lesson() == lessonId ) {
+ QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY );
+ entryElement.setAttribute( KVTML_ID, QString::number( i ) );
+ thisLessonElement.appendChild(entryElement);
}
}
return true;
}
-bool KEduVocKvtml2Writer::writeTypes( QDomElement &typesElement )
+bool KEduVocKvtml2Writer::writeWordTypes( QDomElement &typesElement )
{
KEduVocWordType wt = m_doc->wordTypes();
foreach( QString mainTypeName, wt.typeNameList() ) {
kDebug() << "Writing type: " << mainTypeName;
- QDomElement typeDefinitionElement = m_domDoc.createElement( KVTML_WORDTYPEDEFINITION );
- typeDefinitionElement.appendChild( newTextElement( KVTML_TYPENAME, mainTypeName ) );
+ QDomElement typeDefinitionElement = m_domDoc.createElement( KVTML_CONTAINER );
+ typeDefinitionElement.appendChild( newTextElement( KVTML_NAME, mainTypeName ) );
QString specialType = wt.specialType( mainTypeName );
if ( !specialType.isEmpty() ) {
typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, specialType ) );
}
+ // go through the entries - this is pretty inefficient but will change when the
+ // container class is used for word types.
+ for(int i = 0; i<m_doc->entryCount(); i++) {
+ QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY );
+ for(int translation = 0; translation<m_doc->identifierCount(); translation++) {
+ // if it has a subtype, add there
+ if(m_doc->entry(i)->translation(translation).subType().isEmpty()) {
+ if (m_doc->entry(i)->translation(translation).type()== mainTypeName) {
+ // create <element id="123">
+ entryElement.setAttribute( KVTML_ID, QString::number( i ) );
+ // create <translation id="123">
+ QDomElement translationElement = m_domDoc.createElement( KVTML_TRANSLATION );
+ translationElement.setAttribute( KVTML_ID, QString::number(translation) );
+ // append both
+ entryElement.appendChild(translationElement);
+ }
+ }
+ }
+ if (entryElement.hasChildNodes()) {
+ typeDefinitionElement.appendChild(entryElement);
+ }
+ }
+
+
// subtypes
foreach( QString subTypeName, wt.subTypeNameList( mainTypeName ) ) {
- QDomElement subTypeDefinitionElement = m_domDoc.createElement( KVTML_SUBWORDTYPEDEFINITION );
- subTypeDefinitionElement.appendChild( newTextElement( KVTML_SUBTYPENAME, subTypeName ) );
+ QDomElement subTypeDefinitionElement = m_domDoc.createElement( KVTML_CONTAINER );
+ subTypeDefinitionElement.appendChild( newTextElement( KVTML_NAME, subTypeName ) );
QString specialSubType = wt.specialSubType( mainTypeName, subTypeName );
if ( !specialSubType.isEmpty() ) {
if ( specialSubType == m_doc->wordTypes().specialTypeNounMale() ) {
subTypeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, specialSubType ) );
}
typeDefinitionElement.appendChild( subTypeDefinitionElement );
+
+ // go through the entries - this is pretty inefficient but will change when the
+ // container class is used for word types.
+ for(int i = 0; i<m_doc->entryCount(); i++) {
+ QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY );
+ for(int translation = 0; translation<m_doc->identifierCount(); translation++) {
+ // if it has a subtype, add there
+ if(m_doc->entry(i)->translation(translation).subType() == subTypeName) {
+ if (m_doc->entry(i)->translation(translation).type()== mainTypeName) {
+ // create <element id="123">
+ entryElement.setAttribute( KVTML_ID, QString::number( i ) );
+ // create <translation id="123">
+ QDomElement translationElement = m_domDoc.createElement( KVTML_TRANSLATION );
+ translationElement.setAttribute( KVTML_ID, QString::number(translation) );
+ // append both
+ entryElement.appendChild(translationElement);
+ }
+ }
+ }
+ if (entryElement.hasChildNodes()) {
+ subTypeDefinitionElement.appendChild(entryElement);
+ }
+ }
}
typesElement.appendChild( typeDefinitionElement );
}
entryElement.setAttribute( KVTML_ID, QString::number( i ) );
// write inactive
- entryElement.appendChild( newTextElement( KVTML_INACTIVE, thisEntry->isActive() ? KVTML_FALSE : KVTML_TRUE ) );
+ entryElement.appendChild( newTextElement( KVTML_DEACTIVATED, thisEntry->isActive() ? KVTML_FALSE : KVTML_TRUE ) );
// kvtml 1 relic no longer used
// // write inquery
return true;
}
+
bool KEduVocKvtml2Writer::writeTranslation( QDomElement &translationElement, KEduVocTranslation &translation )
{
// <text>Kniebeugen</text>
translationElement.appendChild( newTextElement( KVTML_TEXT, translation.text() ) );
- // <wordtype></wordtype>
- if ( !translation.type().isEmpty() ) {
- QDomElement wordTypeElement = m_domDoc.createElement( KVTML_WORDTYPE );
- translationElement.appendChild( wordTypeElement );
- //<typename>noun</typename>
- wordTypeElement.appendChild( newTextElement( KVTML_TYPENAME, translation.type() ) );
- // <subwordtype>male</subwordtype>
- if ( !translation.subType().isEmpty() ) {
- wordTypeElement.appendChild( newTextElement( KVTML_SUBTYPENAME, translation.subType() ) );
- }
- }
-
// <comment></comment>
if ( !translation.comment().isEmpty() ) {
translationElement.appendChild( newTextElement( KVTML_COMMENT, translation.comment() ) );
}
return true;
}
+
/** write types
* @param typesElement QDomElement types to write to
*/
- bool writeTypes( QDomElement &typesElement );
+ bool writeWordTypes( QDomElement &typesElement );
/** write tenses
* @param tensesElement QDomElement tenses to write to
QFile *m_outputFile;
KEduVocDocument *m_doc;
+ QDomElement m_wordTypeElement;
+
QDomDocument m_domDoc;
};
-<!ELEMENT kvtml (information, identifiers, wordtypedefinitions?, usages?, entries, tenses?, lessons?) >
+<!ELEMENT kvtml (information, identifiers, wordtypedefinitions?, usages?, entries, tenses?, lessons?) >
<!ATTLIST kvtml version CDATA #REQUIRED>
<!ELEMENT information (generator?, title, author?, license?, comment?, category?) >
<!ELEMENT secondperson (#PCDATA) >
<!ELEMENT thirdperson (common|(male, female, neutral)) >
-<!ELEMENT wordtypedefinitions (wordtypedefinition*) >
-<!ELEMENT wordtypedefinition (typename, specialwordtype?, subwordtypedefinition*) >
-<!ELEMENT subwordtypedefinition (subtypename, specialwordtype?) >
-<!ELEMENT specialwordtype (#PCDATA) >
-<!ELEMENT subtypename (#PCDATA) >
-<!ELEMENT typename (#PCDATA) >
-
<!ELEMENT tenses (tense*) >
<!ELEMENT tense (#PCDATA) >
<!ELEMENT usages (usage*) >
<!ELEMENT usage (#PCDATA) >
-<!ELEMENT lessons (lesson*) >
-<!ELEMENT lesson (name, query?, current?, entryid*) >
-<!ELEMENT query (#PCDATA) >
-<!ELEMENT current (#PCDATA) >
-<!ELEMENT entryid (#PCDATA) >
+<!ELEMENT lessons (container*) >
+<!ELEMENT wordtypes (container*) >
+<!ELEMENT leitnerboxes (container*) >
+
+<!ELEMENT container (name, containertype?, inPractice?, image?, containerentry*) >
+<!ELEMENT containertype (lesson|leitnerbox|wordtype|wordtype-noun|wordtype-noun-male|wordtype-noun-female|wordtype-noun-neutral|wordtype-verb|wordtype-adjective|wordtype-adverb) >
+<!ELEMENT inPractice (#PCDATA) >
+<!ELEMENT containerentry (containertranslation*) >
+<!ATTLIST containerentry id CDATA #REQUIRED>
+<!ELEMENT containertranslation>
+<!ATTLIST containertranslation id CDATA #REQUIRED>
<!ELEMENT entries (entry*) >
-<!ELEMENT entry (inactive?, inquery?, sizehint?, translation*) >
+<!ELEMENT entry (inactive?, sizehint?, translation*) >
<!ATTLIST entry id CDATA #REQUIRED>
<!ELEMENT inactive (#PCDATA) >
-<!ELEMENT inquery (#PCDATA) >
-<!ELEMENT translation (text, wordtype?, inquery?, comment?, pronunciation?, falsefriend?, antonym?, synonym?, example?, usage*, paraphrase?, comparison?, conjugation*, grade?, image?, multiplechoice?, sound?) >
+<!ELEMENT translation (text, inquery?, comment?, pronunciation?, falsefriend?, antonym?, synonym?, example?, usage*, paraphrase?, comparison?, conjugation*, grade?, image?, multiplechoice?, sound?) >
<!ATTLIST translation id CDATA #REQUIRED >
-<!ELEMENT wordtype (typename?|(typename, subtypename?)) >
<!ELEMENT text (#PCDATA) >
<!ELEMENT pronunciation (#PCDATA) >
<!ELEMENT falsefriend (#PCDATA) >
#define KVTML_THIRD_PERSON_NEUTRAL_EXISTS "neutralexists"
#define KVTML_DUAL_EXISTS "dualexists"
-// word types
-#define KVTML_WORDTYPEDEFINITIONS "wordtypedefinitions"
-#define KVTML_WORDTYPEDEFINITION "wordtypedefinition"
-#define KVTML_SUBWORDTYPEDEFINITION "subwordtypedefinition"
-
-#define KVTML_WORDTYPE "wordtype"
-#define KVTML_TYPENAME "typename"
-#define KVTML_SUBTYPENAME "subtypename"
+// word types, lessons and leitner boxes are vocabulary containers.
+// each is allowed to have as many child containers as desired.
+// for KDE 4.0 Parley will only allow a depth of wordtype cildren of two,
+// leitner is not implemented at all.
+// it is assumed that one container only has children of the same type.
+// containers may have an image associated to represent them visually.
+#define KVTML_WORDTYPES "wordtypes"
+#define KVTML_LESSONS "lessons"
+#define KVTML_LEITNERBOXES "leitnerboxes"
+#define KVTML_CONTAINER "container"
+#define KVTML_INPRACTICE "inpractice"
-// these are necessary to enable practices based on word types. users can give types arbitrary names, but these few are hardcoded.
+// these are necessary to enable practices based on word types. users can give types arbitrary names, but these few are hardcoded. special container types
#define KVTML_SPECIALWORDTYPE "specialwordtype"
#define KVTML_SPECIALWORDTYPE_NOUN "noun"
-#define KVTML_SPECIALWORDTYPE_NOUN_MALE "male"
-#define KVTML_SPECIALWORDTYPE_NOUN_FEMALE "female"
-#define KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL "neutral"
+#define KVTML_SPECIALWORDTYPE_NOUN_MALE "noun/male"
+#define KVTML_SPECIALWORDTYPE_NOUN_FEMALE "noun/female"
+#define KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL "noun/neutral"
#define KVTML_SPECIALWORDTYPE_VERB "verb"
#define KVTML_SPECIALWORDTYPE_ADJECTIVE "adjective"
#define KVTML_SPECIALWORDTYPE_ADVERB "adverb"
+
#define KVTML_TENSES "tenses"
#define KVTML_TENSE "tense"
#define KVTML_USAGES "usages"
#define KVTML_USAGE "usage"
-#define KVTML_LESSONS "lessons"
-#define KVTML_LESSON "lesson"
-#define KVTML_QUERY "query"
#define KVTML_CURRENT "current"
-#define KVTML_ENTRYID "entryid"
#define KVTML_ENTRIES "entries"
#define KVTML_ENTRY "entry"
-#define KVTML_INACTIVE "inactive"
-#define KVTML_INQUERY "inquery"
+#define KVTML_DEACTIVATED "deactivated"
#define KVTML_TRANSLATION "translation"
#define KVTML_TEXT "text"