]> Git trees. - libqmvoc.git/commitdiff
Merged revisions 735356-742172 via svnmerge from
authorFrederik Gladhorn <gladhorn@kde.org>
Tue, 27 Nov 2007 16:10:01 +0000 (16:10 +0000)
committerFrederik Gladhorn <gladhorn@kde.org>
Tue, 27 Nov 2007 16:10:01 +0000 (16:10 +0000)
svn://anonsvn.kde.org/home/kde/trunk/KDE/kdeedu
Finally have nice lesson and word type handling.
For now word types still use the unmodified lesson class.

svn path=/branches/work/kdeedu_parley/libkdeedu/; revision=742235

1  2 
keduvocdocument/keduvocdocument.cpp
keduvocdocument/keduvockvtml2reader.cpp
keduvocdocument/keduvockvtml2reader.h
keduvocdocument/keduvockvtml2writer.cpp
keduvocdocument/keduvockvtml2writer.h
keduvocdocument/keduvockvtmlreader.cpp
keduvocdocument/keduvocwordtype.h
keduvocdocument/kvtml2defs.h

index 217ad54cc19014a21ca2caf62d89b7f3ef151ae2,09c87209528a9579b1dccea1ec2b56b0cbcbfc52..c99a7eb32f1be874ee1e8a65c85497bf06aedc6d
@@@ -109,21 -105,13 +109,22 @@@ KEduVocDocument::KEduVocDocumentPrivate
  
  void KEduVocDocument::KEduVocDocumentPrivate::init()
  {
 -    m_lessons.clear();
 +    if ( m_lessonContainer ) {
 +        delete m_lessonContainer;
 +    }
 +    m_lessonContainer = new KEduVocLesson("root");
 +    m_lessonContainer->setContainerType(KEduVocLesson::LessonContainer);
 +    if ( m_wordTypeContainer ) {
 +        delete m_wordTypeContainer;
 +    }
 +    m_wordTypeContainer = new KEduVocLesson(i18n( "Word types" ));
 +    m_wordTypeContainer->setContainerType(KEduVocLesson::WordTypeContainer);
 +
      m_tenseDescriptions.clear();
      m_identifiers.clear();
+     m_wordTypes.clear();
      m_extraSizeHints.clear();
      m_sizeHints.clear();
 -    m_vocabulary.clear();
      m_dirty = false;
      m_currentLesson = 0;
      m_queryorg = "";
index 05ceccfc098c194cac396d69808ad58fab83a7d9,9d0c39de686d22ace524f624a96539a7e0419f50..0e3e8d304fd1f63e17782997f35dbc9e57eeacd9
@@@ -58,21 -58,21 +58,21 @@@ bool KEduVocKvtml2Reader::readDoc( KEdu
          m_errorMessage = i18n( "This is not a KDE Vocabulary document." );
          return false;
      }
 -
 -    if ( domElementKvtml.attribute( KVTML_VERSION ).toFloat() < 2.0 ) {
 -        // read the file with the old format
 -
 -        // first reset the file to the beginning
 -        m_inputFile->seek( 0 );
 -        KEduVocKvtmlReader oldFormat( m_inputFile );
 -
 -        // get the return value
 -        bool retval = oldFormat.readDoc( doc );
 -
 -        // pass the errormessage up
 -        m_errorMessage = oldFormat.errorMessage();
 -        return retval;
 -    }
 +///@todo port me
 +//     if ( domElementKvtml.attribute( KVTML_VERSION ).toFloat() < 2.0 ) {
 +//         // read the file with the old format
- // 
++//
 +//         // first reset the file to the beginning
 +//         m_inputFile->seek( 0 );
 +//         KEduVocKvtmlReader oldFormat( m_inputFile );
- // 
++//
 +//         // get the return value
 +//         bool retval = oldFormat.readDoc( doc );
- // 
++//
 +//         // pass the errormessage up
 +//         m_errorMessage = oldFormat.errorMessage();
 +//         return retval;
 +//     }
  
      //-------------------------------------------------------------------------
      // Information
@@@ -182,12 -182,35 +177,33 @@@ bool KEduVocKvtml2Reader::readGroups( Q
          }
      }
  
 -        readWordTypes( groupElement );
+     groupElement = domElementParent.firstChildElement( KVTML_WORDTYPES );
+     if ( !groupElement.isNull() ) {
++        readChildWordTypes( m_doc->wordTypeContainer(), groupElement );
+     }
      groupElement = domElementParent.firstChildElement( KVTML_LESSONS );
      if ( !groupElement.isNull() ) {
 -        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;
 -            }
 -        }
 +        readChildLessons(m_doc->lesson(), groupElement);
 +    }
  
-     ///@todo create dynamic lessons (word type)
 -        ///@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 ) {
 -                result = readLesson( currentElement );
 -                if ( !result )
 -                    return false;
 -            }
++    // Additional cleanup: Put orphaned entries without a lesson into a default lesson.
++    KEduVocLesson *defaultLesson = new KEduVocLesson(i18n("Default Lesson"), m_doc->lesson());
++
++    // now make sure we don't have any orphan entries
++    foreach (KEduVocExpression * entry, m_allEntries.values()) {
++        if (entry->lessons().count() == 0)
++        {
++            defaultLesson->addEntry(entry);
+         }
 -        // end @todo
++    }
++
++    if (defaultLesson->entryCount() > 0)
++    {
++        m_doc->lesson()->appendChildLesson(defaultLesson);
++    } else {
++        delete defaultLesson;
+     }
  
      return true;
  }
@@@ -296,27 -333,9 +312,9 @@@ bool KEduVocKvtml2Reader::readTranslati
  
      currentElement = translationElement.firstChildElement( KVTML_COMMENT );
      if ( !currentElement.isNull() ) {
 -        expr.translation( index ).setComment( currentElement.text() );
 +        expr->translation(index)->setComment( currentElement.text() );
      }
  
-     currentElement = translationElement.firstChildElement( KVTML_WORDTYPE );
-     if ( !currentElement.isNull() ) {
-         QDomElement typeElement = currentElement.firstChildElement( KVTML_TYPENAME );
-         QString wordTypeString = typeElement.text();
-         typeElement = currentElement.firstChildElement( KVTML_WORDTYPE );
-         QString childWordTypeString = typeElement.text();
-         KEduVocLesson* typeLesson = m_doc->wordTypeContainer()->childLesson(wordTypeString);
-         if(!childWordTypeString.isEmpty()) {
-             typeLesson = typeLesson->childLesson(childWordTypeString);
-         }
-         if ( typeLesson ) {
-             expr->translation(index)->setWordType(typeLesson);
-         }
-     }
      //<pronunciation></pronunciation>
      currentElement = translationElement.firstChildElement( KVTML_PRONUNCIATION );
      if ( !currentElement.isNull() ) {
      return true;
  }
  
 -bool KEduVocKvtml2Reader::readLesson( QDomElement &lessonElement )
 +bool KEduVocKvtml2Reader::readChildLessons( KEduVocLesson* parentLesson, QDomElement &lessonElement )
 +{
-     QDomElement currentElement = lessonElement.firstChildElement( KVTML_LESSON );
++    QDomElement currentElement = lessonElement.firstChildElement( KVTML_CONTAINER );
 +    while ( !currentElement.isNull() ) {
 +        readLesson(parentLesson, currentElement);
-         currentElement = currentElement.nextSiblingElement( KVTML_LESSON );
++        currentElement = currentElement.nextSiblingElement( KVTML_CONTAINER );
 +    }
 +}
 +
++
 +bool KEduVocKvtml2Reader::readLesson( KEduVocLesson* parentLesson, QDomElement &lessonElement )
  {
 -    // NOTE: currently this puts an identifier into the last lesson it is in, once support for multiple lessons
 -    // is in the entry class, all lessons that include an entry will be in there
 -    int lessonId;
      //<name>Lesson name</name>
      QDomElement currentElement = lessonElement.firstChildElement( KVTML_NAME );
 -    if ( !currentElement.isNull() ) {
 -        lessonId = m_doc->appendLesson( currentElement.text() );
 -    } else {
 -        m_errorMessage = i18n( "each lesson must have a name" );
 -        return false;
 -    }
 +    KEduVocLesson * lesson = new KEduVocLesson(currentElement.text(), parentLesson);
 +    parentLesson->appendChildLesson( lesson );
 +
 +    readChildLessons( lesson, lessonElement );
  
      //<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>
 -    currentElement = lessonElement.firstChildElement( KVTML_CURRENT );
 -    if ( !currentElement.isNull() ) {
 -        if ( currentElement.text() == KVTML_TRUE ) {
 -            m_doc->setCurrentLesson( lessonId );
 -        }
 -    }
 +    lesson->setInPractice(currentElement.text() == KVTML_TRUE);
  
-     //<entryid>0</entryid>
-     currentElement = lessonElement.firstChildElement( KVTML_ENTRYID );
+     //<entry id="123"/>
+     currentElement = lessonElement.firstChildElement( KVTML_ENTRY );
      while ( !currentElement.isNull() ) {
-         int entryId = currentElement.text().toInt();
-         lesson->addEntry( m_allEntries[entryId] );
-         currentElement = currentElement.nextSiblingElement( KVTML_ENTRYID );
+         bool result = false;
 -        int id = currentElement.attribute( KVTML_ID ).toInt( &result );
++        int entryId = currentElement.attribute( KVTML_ID ).toInt( &result );
+         if(result) {
 -            m_doc->entry(id)->setLesson(lessonId);
 -            m_doc->lesson(lessonId).addEntry(id);
++            lesson->addEntry( m_allEntries[entryId] );
+         }
+         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( "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();
 -        m_doc->entry( entryId )->setLesson( lessonId );
 -        m_doc->lesson( lessonId ).addEntry( entryId );
 -        currentElement = currentElement.nextSiblingElement( "entryid" );
 -    }
 -    // end @todo
--
      return true;
  }
  
@@@ -510,77 -551,96 +511,69 @@@ bool KEduVocKvtml2Reader::readArticle( 
  }
  
  
--bool KEduVocKvtml2Reader::readWordTypes( QDomElement &typesElement )
++bool KEduVocKvtml2Reader::readChildWordTypes( KEduVocLesson* parentContainer, QDomElement &lessonElement )
  {
--    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();
-         KEduVocLesson * wordTypeContainer = new KEduVocLesson(mainTypeName, m_doc->wordTypeContainer());
-         m_doc->wordTypeContainer()->appendChildLesson(wordTypeContainer);
 -            currentTypeElement.firstChildElement( KVTML_NAME ).text();
--
 -        QString specialType = currentTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
 -        if ( !specialType.isEmpty() ) {
 -            // get the localized version
 -            if ( specialType == KVTML_SPECIALWORDTYPE_NOUN ) {
 -                specialType = m_doc->wordTypes().specialTypeNoun();
 -            }
 -            if ( specialType == KVTML_SPECIALWORDTYPE_VERB ) {
 -                specialType = m_doc->wordTypes().specialTypeVerb();
 -            }
 -            if ( specialType == KVTML_SPECIALWORDTYPE_ADVERB ) {
 -                specialType = m_doc->wordTypes().specialTypeAdverb();
 -            }
 -            if ( specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE ) {
 -                specialType = m_doc->wordTypes().specialTypeAdjective();
 -            }
++    QDomElement currentElement = lessonElement.firstChildElement( KVTML_CONTAINER );
++    while ( !currentElement.isNull() ) {
++        readWordType(parentContainer, currentElement);
++        currentElement = currentElement.nextSiblingElement( KVTML_CONTAINER );
++    }
++    return true;
++}
 +
-         QString specialType = currentTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
-         if ( !specialType.isEmpty() ) {
-             // get the localized version
-             if ( specialType == KVTML_SPECIALWORDTYPE_NOUN ) {
-                 specialType = m_doc->wordTypes().specialTypeNoun();
-                 wordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounContainer);
-             }
-             if ( specialType == KVTML_SPECIALWORDTYPE_VERB ) {
-                 specialType = m_doc->wordTypes().specialTypeVerb();
-                 wordTypeContainer->setContainerType(KEduVocLesson::WordTypeVerbContainer);
-             }
-             if ( specialType == KVTML_SPECIALWORDTYPE_ADVERB ) {
-                 specialType = m_doc->wordTypes().specialTypeAdverb();
-                 wordTypeContainer->setContainerType(KEduVocLesson::WordTypeAdverbContainer);
-             }
-             if ( specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE ) {
-                 specialType = m_doc->wordTypes().specialTypeAdjective();
-                 wordTypeContainer->setContainerType(KEduVocLesson::WordTypeAdjectiveContainer);
-             }
++bool KEduVocKvtml2Reader::readWordType( KEduVocLesson* parentContainer, QDomElement &typeElement )
++{
++    // set type and specialtype
++    QString typeName =
++        typeElement.firstChildElement( KVTML_NAME ).text();
++
++    KEduVocLesson * wordTypeContainer = new KEduVocLesson(typeName, parentContainer);
++    parentContainer->appendChildLesson(wordTypeContainer);
++
++    QString specialType = typeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
++    if ( !specialType.isEmpty() ) {
++        // get the localized version
++        if ( specialType == KVTML_SPECIALWORDTYPE_NOUN ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounContainer);
          }
- //         m_doc->wordTypes().addType( mainTypeName, specialType );
-         // iterate sub type elements <subwordtypedefinition>
-         QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_WORDTYPEDEFINITION );
-         while ( !currentSubTypeElement.isNull() ) {
-             QString specialSubType = currentSubTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
-             QString subTypeName = currentSubTypeElement.firstChildElement( KVTML_TYPENAME ).text();
-             KEduVocLesson * subWordTypeContainer = new KEduVocLesson(subTypeName, wordTypeContainer);
-             wordTypeContainer->appendChildLesson(subWordTypeContainer);
 -        m_doc->wordTypes().addType( mainTypeName, specialType );
 -        kDebug() << "Add word type:" << mainTypeName << "special:" << specialType;
--
-             if ( !specialSubType.isEmpty() ) {
-                 // get the localized version
-                 if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_MALE ) {
-                     specialSubType = m_doc->wordTypes().specialTypeNounMale();
-                     subWordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounMaleContainer);
-                 }
-                 if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE ) {
-                     specialSubType = m_doc->wordTypes().specialTypeNounFemale();
-                     subWordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounFemaleContainer);
-                 }
-                 if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL ) {
-                     specialSubType = m_doc->wordTypes().specialTypeNounNeutral();
-                     subWordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounNeutralContainer);
-                 }
 -        // 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 );
--            }
-             // set type and specialtype
- //             m_doc->wordTypes().addSubType( mainTypeName, subTypeName,
- //                                             specialSubType );
-             currentSubTypeElement = currentSubTypeElement.nextSiblingElement( KVTML_WORDTYPEDEFINITION );
 -            entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
++        if ( specialType == KVTML_SPECIALWORDTYPE_VERB ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeVerbContainer);
+         }
 -
 -        // iterate sub type elements <container>
 -        QDomElement currentSubTypeElement = currentTypeElement.firstChildElement( KVTML_CONTAINER );
 -        while ( !currentSubTypeElement.isNull() ) {
 -            QString specialSubType = currentSubTypeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
 -            if ( !specialSubType.isEmpty() ) {
 -                // get the localized version
 -                if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_MALE ) {
 -                    specialSubType = m_doc->wordTypes().specialTypeNounMale();
 -                }
 -                if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE ) {
 -                    specialSubType = m_doc->wordTypes().specialTypeNounFemale();
 -                }
 -                if ( specialSubType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL ) {
 -                    specialSubType = m_doc->wordTypes().specialTypeNounNeutral();
 -                }
 -            }
 -
 -            QString subTypeName = currentSubTypeElement.firstChildElement( KVTML_NAME ).text();
 -            // set type and specialtype
 -            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 );
++        if ( specialType == KVTML_SPECIALWORDTYPE_ADVERB ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeAdverbContainer);
++        }
++        if ( specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeAdjectiveContainer);
++        }
++        if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_MALE ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounMaleContainer);
          }
-         currentTypeElement = currentTypeElement.nextSiblingElement( KVTML_WORDTYPEDEFINITION );
 -        // next main word type
 -        currentTypeElement = currentTypeElement.nextSiblingElement( KVTML_CONTAINER );
++        if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounFemaleContainer);
++        }
++        if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL ) {
++            wordTypeContainer->setContainerType(KEduVocLesson::WordTypeNounNeutralContainer);
++        }
++    } // special type
++
++
++    // read entries
++    QDomElement entryElement = typeElement.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_allEntries.value(entryId)->translation(translationId)->setWordType(wordTypeContainer);
++            translationElement = translationElement.nextSiblingElement( KVTML_TRANSLATION );
++        }
++        entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
      }
++
++    readChildWordTypes(wordTypeContainer, typeElement);
++
      return true;
  }
  
index 4c39acb6ff6e10fb7212fbc3a62f1fa3b0ee8c92,3b664beed60e356c3f1182057a17c85a8c4e468e..487ac7fe20927c94e8c54ab077edf05cf015ad73
@@@ -85,10 -85,10 +85,21 @@@ private
      bool readConjugation( QDomElement &conjugElement, KEduVocConjugation &conjugation );
      bool readConjugationPerson( QDomElement &personElement, KEduVocConjugation &conjugation, KEduVocConjugation::ConjugationNumber number );
  
--    /** read the types
--     * @param typesElement QDomElement for the types group
++    /**
++     * Read an individual word type
++     * @param parentContainer 
++     * @param typesElement 
++     * @return 
       */
--    bool readWordTypes( QDomElement &typesElement );
++    bool readWordType( KEduVocLesson* parentContainer, QDomElement &typesElement );
++
++    /**
++     * Read all <container> tags within a word type definition.
++     * @param parentContainer 
++     * @param lessonElement 
++     * @return 
++     */
++    bool readChildWordTypes( KEduVocLesson* parentContainer, QDomElement &lessonElement );
  
      /** read the tenses
       * @param tensesElement QDomElement for the tenses group
index d8fbffaaa07ce99835f1498d7a18d58915d2f057,62c29f65c4450bdd2aa86aa6f0bca34a9fedf1c3..43cfd20f1dd6db52fdcaf68a3e815d01afd9557b
@@@ -85,6 -85,13 +78,13 @@@ bool KEduVocKvtml2Writer::writeDoc( KEd
          domElementKvtml.appendChild( currentElement );
      }
  
 -    m_wordTypeElement = m_domDoc.createElement( KVTML_WORDTYPES );
 -    writeWordTypes( m_wordTypeElement );
 -    if ( m_wordTypeElement.hasChildNodes() ) {
+     // types
++    currentElement = m_domDoc.createElement( KVTML_WORDTYPES );
++    writeWordTypes( currentElement, m_doc->wordTypeContainer() );
++    if ( currentElement.hasChildNodes() ) {
+         domElementKvtml.appendChild( m_wordTypeElement );
+     }
      m_domDoc.appendChild( domElementKvtml );
  
      QTextStream ts( m_outputFile );
@@@ -165,32 -172,36 +165,34 @@@ bool KEduVocKvtml2Writer::writeIdentifi
      return true;
  }
  
 -bool KEduVocKvtml2Writer::writeLessons( QDomElement &lessonsElement )
 +bool KEduVocKvtml2Writer::writeLessons( KEduVocLesson *parentLesson, QDomElement &lessonsElement )
  {
 -    for( int lessonId = 0; lessonId < m_doc->lessonCount(); lessonId++ ) {
 +    // iterate over child lessons.
 +    // the first time this is called with the root lesson which does not have a <lesson> entry.
 +    for( int i = 0; i < parentLesson->childLessonCount(); i++ ) {
 +        KEduVocLesson *lesson = parentLesson->childLesson(i);
          // 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() ) );
 +        thisLessonElement.appendChild( newTextElement( KVTML_NAME, lesson->name() ) );
  
          // add a inquery tag
 -        if ( m_doc->lesson(lessonId).inPractice() ) {
 +        if ( lesson->inPractice() ) {
-             thisLessonElement.appendChild( newTextElement( KVTML_QUERY, KVTML_TRUE ) );
+             thisLessonElement.appendChild( newTextElement( KVTML_INPRACTICE, KVTML_TRUE ) );
          }
  
 -        // add a current tag
 -        if ( lessonId == m_doc->currentLesson() ) {
 -            thisLessonElement.appendChild( newTextElement( KVTML_CURRENT, KVTML_TRUE ) );
 -        }
 +        // child lessons
 +        writeLessons(lesson, thisLessonElement);
  
 -        for ( int i = 0; i < m_doc->entryCount(); ++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);
 -            }
 +        // child entries
 +        foreach(KEduVocExpression *entry, lesson->entries()) {
-             thisLessonElement.appendChild( newTextElement( KVTML_ENTRYID, QString::number( m_allEntries.indexOf(entry) ) ) );
++            QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY );
++            entryElement.setAttribute( KVTML_ID, QString::number(m_allEntries.indexOf(entry)) );
++            thisLessonElement.appendChild(entryElement);
          }
 -
          lessonsElement.appendChild( thisLessonElement );
      }
 -
      return true;
  }
  
@@@ -262,43 -265,98 +264,66 @@@ bool KEduVocKvtml2Writer::writeArticle
      return true;
  }
  
- bool KEduVocKvtml2Writer::writeTypes( QDomElement &typesElement, KEduVocLesson* parentContainer )
 -bool KEduVocKvtml2Writer::writeWordTypes( QDomElement &typesElement )
++
++bool KEduVocKvtml2Writer::writeWordTypes( QDomElement &typesElement, KEduVocLesson* parentContainer )
  {
 -    KEduVocWordType wt = m_doc->wordTypes();
 -    foreach( QString mainTypeName, wt.typeNameList() ) {
 -        kDebug() << "Writing type: " << mainTypeName;
 -        QDomElement typeDefinitionElement = m_domDoc.createElement( KVTML_CONTAINER );
 -        typeDefinitionElement.appendChild( newTextElement( KVTML_NAME, mainTypeName ) );
 +    foreach( KEduVocLesson* wordType, parentContainer->childLessons() ) {
 +        kDebug() << "Writing type: " << wordType->name();
  
-         QDomElement typeDefinitionElement = m_domDoc.createElement( KVTML_WORDTYPEDEFINITION );
-         typeDefinitionElement.appendChild( newTextElement( KVTML_TYPENAME, wordType->name() ) );
 -        QString specialType = wt.specialType( mainTypeName );
 -        if ( !specialType.isEmpty() ) {
 -            // get the NOT localized version for the doc
 -            if ( specialType == m_doc->wordTypes().specialTypeNoun() ) {
 -                specialType = KVTML_SPECIALWORDTYPE_NOUN;
 -            }
 -            if ( specialType == m_doc->wordTypes().specialTypeVerb()) {
 -                specialType =  KVTML_SPECIALWORDTYPE_VERB;
 -            }
 -            if ( specialType == m_doc->wordTypes().specialTypeAdverb()) {
 -                specialType = KVTML_SPECIALWORDTYPE_ADVERB;
 -            }
 -            if ( specialType ==  m_doc->wordTypes().specialTypeAdjective()) {
 -                specialType = KVTML_SPECIALWORDTYPE_ADJECTIVE;
 -            }
 -            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, specialType ) );
++        QDomElement typeDefinitionElement = m_domDoc.createElement( KVTML_CONTAINER );
++        typeDefinitionElement.appendChild( newTextElement( KVTML_NAME, wordType->name() ) );
 +
 +        switch (wordType->containerType()) {
 +        case KEduVocLesson::WordTypeNounContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN ) );
 +            break;
 +        case KEduVocLesson::WordTypeNounMaleContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_MALE ) );
 +            break;
 +        case KEduVocLesson::WordTypeNounFemaleContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_FEMALE ) );
 +            break;
 +        case KEduVocLesson::WordTypeNounNeutralContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL ) );
 +            break;
 +        case KEduVocLesson::WordTypeVerbContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_VERB ) );
 +            break;
 +        case KEduVocLesson::WordTypeAdjectiveContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_ADJECTIVE ) );
 +            break;
 +        case KEduVocLesson::WordTypeAdverbContainer:
 +            typeDefinitionElement.appendChild( newTextElement( KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_ADVERB ) );
 +            break;
 +        default:
 +            // no special type, no tag
 +            break;
          }
  
-         writeTypes( typeDefinitionElement, wordType );
 -        // 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++) {
++
++// child entries
++
++        // child entries
++        foreach(KEduVocExpression *entry, wordType->entries()) {
+             QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY );
++            entryElement.setAttribute( KVTML_ID, QString::number(m_allEntries.indexOf(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 (entry->translation(translation)->wordType()== wordType) {
++                    // create <element id="123">
++                    entryElement.setAttribute( KVTML_ID, QString::number(translation) );
++                    // 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);
 -            }
++            typeDefinitionElement.appendChild( entryElement );
+         }
++        writeWordTypes( typeDefinitionElement, wordType );
  
 -        // subtypes
 -        foreach( QString subTypeName, wt.subTypeNameList( mainTypeName ) ) {
 -            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() ) {
 -                    specialSubType = KVTML_SPECIALWORDTYPE_NOUN_MALE;
 -                }
 -                if ( specialSubType == m_doc->wordTypes().specialTypeNounFemale() ) {
 -                    specialSubType = KVTML_SPECIALWORDTYPE_NOUN_FEMALE;
 -                }
 -                if ( specialSubType == m_doc->wordTypes().specialTypeNounNeutral() ) {
 -                    specialSubType = KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL;
 -                }
 -                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 );
      }
      return true;
@@@ -331,8 -397,17 +356,8 @@@ bool KEduVocKvtml2Writer::writeEntries
          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
 -//         entryElement.appendChild( newTextElement( KVTML_INQUERY, thisEntry->isInQuery() ? KVTML_TRUE : KVTML_FALSE ) );
 -
 -        // write sizehint
 -        if ( thisEntry->sizeHint() > 0 ) {
 -            entryElement.appendChild( newTextElement( KVTML_SIZEHINT, QString::number( thisEntry->sizeHint() ) ) );
 -        }
 -
          // loop through translations
          foreach( int trans, thisEntry->translationIndices() ) {
              // write translations
      return true;
  }
  
 -bool KEduVocKvtml2Writer::writeTranslation( QDomElement &translationElement, KEduVocTranslation &translation )
 +bool KEduVocKvtml2Writer::writeTranslation( QDomElement &translationElement, KEduVocTranslation* translation )
  {
      // <text>Kniebeugen</text>
 -    translationElement.appendChild( newTextElement( KVTML_TEXT, translation.text() ) );
 +    translationElement.appendChild( newTextElement( KVTML_TEXT, translation->text() ) );
 +kDebug() << "write tranlation:" << translation->text();
-     // <wordtype></wordtype>
-     if ( translation->wordType() ) {
- kDebug() << "word type" << translation->wordType()->name();
-         QDomElement wordTypeElement = m_domDoc.createElement( KVTML_WORDTYPE );
-         translationElement.appendChild( wordTypeElement );
-         //<typename>noun</typename>
-         wordTypeElement.appendChild( newTextElement( KVTML_TYPENAME, translation->wordType()->name() ) );
-     }
  
      // <comment></comment>
 -    if ( !translation.comment().isEmpty() ) {
 -        translationElement.appendChild( newTextElement( KVTML_COMMENT, translation.comment() ) );
 +    if ( !translation->comment().isEmpty() ) {
 +        translationElement.appendChild( newTextElement( KVTML_COMMENT, translation->comment() ) );
      }
  
      // <pronunciation></pronunciation>
index d1f186d362715d26a3c5bb5d7136f56edffcec71,f4c3445358ec7f2895a7942b7e5bdb5e4f0128fe..ac998a20f969353fe289558e22b4e9504ff8f4df
@@@ -70,7 -68,7 +70,7 @@@ public
      /** write types
       * @param typesElement QDomElement types to write to
       */
-     bool writeTypes( QDomElement &typesElement, KEduVocLesson* parentContainer );
 -    bool writeWordTypes( QDomElement &typesElement );
++    bool writeWordTypes( QDomElement &typesElement, KEduVocLesson* parentContainer );
  
      /** write tenses
       * @param tensesElement QDomElement tenses to write to
@@@ -118,7 -116,7 +118,9 @@@ private
      QFile *m_outputFile;
      KEduVocDocument *m_doc;
  
++    ///@todo which of the following is in use?
 +    QList<KEduVocExpression*>  m_allEntries;
+     QDomElement m_wordTypeElement;
  
      QDomDocument m_domDoc;
  };
index f8f14a53a47479d3e9c8a195325d8afbe61c50ad,0bf1cb3851f7c1345daa20f8cea490c6d6105647..fbba117ddebae8e0b6beb1db3473b745614fbebe
@@@ -139,7 -139,11 +139,9 @@@ public
      QString specialTypeAdjective() const;
      QString specialTypeAdverb() const;
  
+     void clear();
  private:
 -
 -
      QString mainTypeName( int index ) const;
      int mainTypeIndex( const QString& name ) const;
      int subTypeIndex( const QString& mainTypeName, const QString& subTypeName ) const;
index d3cea46ebc63ef559d06419f268dcbf236f541e1,f8442e7fc679d5f5117fb200defef9994f910924..52c6b26ed3def38eb4197fdcb2193d9bd042f17f
  #define KVTML_THIRD_PERSON_NEUTRAL_EXISTS "neutralexists"
  #define KVTML_DUAL_EXISTS        "dualexists"
  
- // word types
- #define KVTML_WORDTYPEDEFINITIONS   "wordtypedefinitions"
- #define KVTML_WORDTYPEDEFINITION    "wordtypedefinition"
+ // 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"
  
- #define KVTML_WORDTYPE              "wordtype"
- #define KVTML_TYPENAME              "typename"
 +
- // 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   "noun/male"