From bfe5a0c058f1ae06b919feec48965db51e835dbc Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 27 Nov 2007 01:32:29 +0000 Subject: [PATCH] Last cleanup the definition of KVTML-2 XML for KDE4. 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 --- keduvocdocument/keduvockvtml2reader.cpp | 120 +++++++++++++++++------- keduvocdocument/keduvockvtml2reader.h | 2 +- keduvocdocument/keduvockvtml2writer.cpp | 98 +++++++++++++------ keduvocdocument/keduvockvtml2writer.h | 4 +- keduvocdocument/kvtml2.dtd | 31 +++--- keduvocdocument/kvtml2defs.h | 35 ++++--- 6 files changed, 187 insertions(+), 103 deletions(-) diff --git a/keduvocdocument/keduvockvtml2reader.cpp b/keduvocdocument/keduvockvtml2reader.cpp index 8a04958..9d0c39d 100644 --- a/keduvocdocument/keduvockvtml2reader.cpp +++ b/keduvocdocument/keduvockvtml2reader.cpp @@ -32,6 +32,8 @@ #include "keduvockvtmlreader.h" #include "keduvoccommon_p.h" +#include + KEduVocKvtml2Reader::KEduVocKvtml2Reader( QIODevice *file ) : m_inputFile( file ) { @@ -157,11 +159,6 @@ bool KEduVocKvtml2Reader::readGroups( QDomElement &domElementParent ) } } - groupElement = domElementParent.firstChildElement( KVTML_WORDTYPEDEFINITIONS ); - if ( !groupElement.isNull() ) { - readTypes( groupElement ); - } - groupElement = domElementParent.firstChildElement( KVTML_TENSES ); if ( !groupElement.isNull() ) { readTenses( groupElement ); @@ -185,14 +182,25 @@ bool KEduVocKvtml2Reader::readGroups( QDomElement &domElementParent ) } } + 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 ) { @@ -201,6 +209,7 @@ bool KEduVocKvtml2Reader::readGroups( QDomElement &domElementParent ) return false; } } + // end @todo } return true; @@ -266,7 +275,7 @@ bool KEduVocKvtml2Reader::readEntry( QDomElement &entryElement ) } // 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 ) { @@ -327,17 +336,6 @@ bool KEduVocKvtml2Reader::readTranslation( QDomElement &translationElement, 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() ); - } - } - // currentElement = translationElement.firstChildElement( KVTML_PRONUNCIATION ); if ( !currentElement.isNull() ) { @@ -448,7 +446,7 @@ bool KEduVocKvtml2Reader::readLesson( QDomElement &lessonElement ) } //true - currentElement = lessonElement.firstChildElement( KVTML_QUERY ); + currentElement = lessonElement.firstChildElement( KVTML_INPRACTICE ); m_doc->lesson(lessonId).setInPractice(currentElement.text() == KVTML_TRUE); //true @@ -459,16 +457,29 @@ bool KEduVocKvtml2Reader::readLesson( QDomElement &lessonElement ) } } + // + 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. //0 - 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; } @@ -540,16 +551,16 @@ bool KEduVocKvtml2Reader::readArticle( QDomElement &articleElement, int identifi } -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 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() ) { @@ -568,9 +579,26 @@ bool KEduVocKvtml2Reader::readTypes( QDomElement &typesElement ) } } m_doc->wordTypes().addType( mainTypeName, specialType ); + kDebug() << "Add word type:" << mainTypeName << "special:" << specialType; + + // set word types to entries: + // <...> + QDomElement entryElement = currentTypeElement.firstChildElement( KVTML_ENTRY ); + while ( !entryElement.isNull() ) { + // read + int entryId = entryElement.attribute( KVTML_ID ).toInt(); + QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION ); + while( !translationElement.isNull() ) { + // + 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 - QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_SUBWORDTYPEDEFINITION ); + // iterate sub type elements + QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_CONTAINER ); while ( !currentSubTypeElement.isNull() ) { QString specialSubType = currentSubTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text(); if ( !specialSubType.isEmpty() ) { @@ -585,13 +613,33 @@ bool KEduVocKvtml2Reader::readTypes( QDomElement &typesElement ) 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: + // <...> + entryElement = currentSubTypeElement.firstChildElement( KVTML_ENTRY ); + while ( !entryElement.isNull() ) { + // read + int entryId = entryElement.attribute( KVTML_ID ).toInt(); + QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION ); + while( !translationElement.isNull() ) { + // + 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; } diff --git a/keduvocdocument/keduvockvtml2reader.h b/keduvocdocument/keduvockvtml2reader.h index 6feedeb..3b664be 100644 --- a/keduvocdocument/keduvockvtml2reader.h +++ b/keduvocdocument/keduvockvtml2reader.h @@ -88,7 +88,7 @@ private: /** 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 diff --git a/keduvocdocument/keduvockvtml2writer.cpp b/keduvocdocument/keduvockvtml2writer.cpp index 0682a12..62c29f6 100644 --- a/keduvocdocument/keduvockvtml2writer.cpp +++ b/keduvocdocument/keduvockvtml2writer.cpp @@ -56,13 +56,6 @@ bool KEduVocKvtml2Writer::writeDoc( KEduVocDocument *doc, const QString &generat 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 ); @@ -92,6 +85,13 @@ bool KEduVocKvtml2Writer::writeDoc( KEduVocDocument *doc, const QString &generat 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 ); @@ -176,14 +176,14 @@ bool KEduVocKvtml2Writer::writeLessons( QDomElement &lessonsElement ) { 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 @@ -191,10 +191,11 @@ bool KEduVocKvtml2Writer::writeLessons( QDomElement &lessonsElement ) 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); } } @@ -264,13 +265,13 @@ bool KEduVocKvtml2Writer::writeArticle( QDomElement &articleElement, int article 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() ) { @@ -290,10 +291,34 @@ bool KEduVocKvtml2Writer::writeTypes( QDomElement &typesElement ) 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; ientryCount(); i++) { + QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY ); + for(int translation = 0; translationidentifierCount(); 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 + entryElement.setAttribute( KVTML_ID, QString::number( i ) ); + // create + 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() ) { @@ -308,6 +333,29 @@ bool KEduVocKvtml2Writer::writeTypes( QDomElement &typesElement ) 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; ientryCount(); i++) { + QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY ); + for(int translation = 0; translationidentifierCount(); 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 + entryElement.setAttribute( KVTML_ID, QString::number( i ) ); + // create + 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 ); } @@ -349,7 +397,7 @@ bool KEduVocKvtml2Writer::writeEntries( QDomElement &entriesElement ) 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 @@ -374,23 +422,12 @@ bool KEduVocKvtml2Writer::writeEntries( QDomElement &entriesElement ) return true; } + bool KEduVocKvtml2Writer::writeTranslation( QDomElement &translationElement, KEduVocTranslation &translation ) { // Kniebeugen translationElement.appendChild( newTextElement( KVTML_TEXT, translation.text() ) ); - // - if ( !translation.type().isEmpty() ) { - QDomElement wordTypeElement = m_domDoc.createElement( KVTML_WORDTYPE ); - translationElement.appendChild( wordTypeElement ); - //noun - wordTypeElement.appendChild( newTextElement( KVTML_TYPENAME, translation.type() ) ); - // male - if ( !translation.subType().isEmpty() ) { - wordTypeElement.appendChild( newTextElement( KVTML_SUBTYPENAME, translation.subType() ) ); - } - } - // if ( !translation.comment().isEmpty() ) { translationElement.appendChild( newTextElement( KVTML_COMMENT, translation.comment() ) ); @@ -656,3 +693,4 @@ bool KEduVocKvtml2Writer::writePersonalPronoun(QDomElement & pronounElement, con } return true; } + diff --git a/keduvocdocument/keduvockvtml2writer.h b/keduvocdocument/keduvockvtml2writer.h index 51efe0e..f4c3445 100644 --- a/keduvocdocument/keduvockvtml2writer.h +++ b/keduvocdocument/keduvockvtml2writer.h @@ -68,7 +68,7 @@ public: /** 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 @@ -116,6 +116,8 @@ private: QFile *m_outputFile; KEduVocDocument *m_doc; + QDomElement m_wordTypeElement; + QDomDocument m_domDoc; }; diff --git a/keduvocdocument/kvtml2.dtd b/keduvocdocument/kvtml2.dtd index e83fe55..772d249 100644 --- a/keduvocdocument/kvtml2.dtd +++ b/keduvocdocument/kvtml2.dtd @@ -1,4 +1,4 @@ - + @@ -31,34 +31,31 @@ - - - - - - - - - - - - + + + + + + + + + + + - + - - + - diff --git a/keduvocdocument/kvtml2defs.h b/keduvocdocument/kvtml2defs.h index 04abd5f..f8442e7 100644 --- a/keduvocdocument/kvtml2defs.h +++ b/keduvocdocument/kvtml2defs.h @@ -67,41 +67,40 @@ #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" -- 2.47.3