]> Git trees. - libqmvoc.git/commitdiff
kvtml2 writer initial checkin, writeInformation working
authorJeremy Paul Whiting <jpwhiting@kde.org>
Mon, 23 Jul 2007 15:02:24 +0000 (15:02 +0000)
committerJeremy Paul Whiting <jpwhiting@kde.org>
Mon, 23 Jul 2007 15:02:24 +0000 (15:02 +0000)
svn path=/trunk/KDE/kdeedu/libkdeedu/; revision=691398

kdeeducore/CMakeLists.txt
kdeeducore/keduvockvtml2writer.cpp [new file with mode: 0644]
kdeeducore/keduvockvtml2writer.h [new file with mode: 0644]

index 9a071688a980477b70e151946b1bda99263eb1e9..3666c954ac4a0ea88b07f51b3c6322dd05fa3ed1 100644 (file)
@@ -12,6 +12,7 @@ set(kdeeducore_LIB_SRCS
    keduvockvtmlreader.cpp
    keduvockvtml2reader.cpp
    keduvockvtmlwriter.cpp
+   keduvockvtml2writer.cpp
    keduvocmultiplechoice.cpp
    keduvocpaukerreader.cpp
    keduvocvokabelnreader.cpp
diff --git a/kdeeducore/keduvockvtml2writer.cpp b/kdeeducore/keduvockvtml2writer.cpp
new file mode 100644 (file)
index 0000000..409cb07
--- /dev/null
@@ -0,0 +1,874 @@
+/***************************************************************************
+                   export a KEduVocDocument to a KVTML file
+    -----------------------------------------------------------------------
+    copyright           : (C) 2007 Jeremy Whiting <jeremy@scitools.com>
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "keduvockvtml2writer.h"
+
+#include <QTextStream>
+#include <QFile>
+
+#include <kdebug.h>
+
+#include "keduvocdocument.h"
+#include "keduvocexpression.h"
+#include "kvtmldefs.h"
+#include "kvtml2defs.h"
+
+KEduVocKvtml2Writer::KEduVocKvtml2Writer(QFile *file)
+{
+  // the file must be already open
+  m_outputFile = file;
+}
+
+
+bool KEduVocKvtml2Writer::writeDoc(KEduVocDocument *doc, const QString &generator)
+{
+  bool first_expr = true;
+
+  m_doc = doc;
+
+  m_domDoc = QDomDocument("kvtml SYSTEM \"kvtml2.dtd\"");
+  m_domDoc.appendChild(m_domDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
+  QDomElement domElementKvtml = m_domDoc.createElement("kvtml");
+  m_domDoc.appendChild(domElementKvtml);
+
+  domElementKvtml.setAttribute(KVTML_VERSION, (QString) "2.0");
+
+  // information group
+  QDomElement currentElement = m_domDoc.createElement(KVTML_INFORMATION);
+  writeInformation(currentElement, generator);
+  domElementKvtml.appendChild(currentElement);
+  
+  
+  //** NOTE: everything below this point has not been updated to use kvtml2 format****
+  if (!writeLesson(m_domDoc, domElementKvtml))
+    return false;
+
+  if (!writeArticle(m_domDoc, domElementKvtml))
+    return false;
+
+  QList<KEduVocConjugation> conjugations;
+  for (int i = 0; i < m_doc->conjugationCount(); i++)
+    conjugations.append(m_doc->conjugation(i));
+  if (conjugations.count() > 0) {
+    if (!writeConjugHeader(m_domDoc, domElementKvtml, conjugations))
+      return false;
+  }
+
+  if (!writeOption(m_domDoc, domElementKvtml))
+    return false;
+
+  if (!writeType(m_domDoc, domElementKvtml))
+    return false;
+
+  if (!writeTense(m_domDoc, domElementKvtml))
+    return false;
+
+  if (!writeUsage(m_domDoc, domElementKvtml))
+    return false;
+
+  QString q_org, q_trans;
+  m_doc->queryIdentifier(q_org, q_trans);
+
+  int entryCount = m_doc->entryCount();
+
+  for (int i = 0; i < entryCount; i++)
+  {
+    KEduVocExpression *entry = m_doc->entry(i);
+    QDomElement domElementExpression = m_domDoc.createElement(KV_EXPR);
+
+    if (entry->lesson() != 0)
+    {
+      int lm = entry->lesson();
+      if (lm > m_doc->lessonDescriptions().count())
+      {
+        // should not be
+        kError() << "index of lesson member too high: " << lm << endl;
+        lm = 0;
+      }
+      domElementExpression.setAttribute(KV_LESS_MEMBER, lm);
+    }
+
+    if (entry->isInQuery())
+      domElementExpression.setAttribute(KV_SELECTED, 1);
+
+    if (!entry->isActive())
+      domElementExpression.setAttribute (KV_INACTIVE, 1);
+
+    if (entry->uniqueType() && !entry->translation(0).type().isEmpty())
+      domElementExpression.setAttribute (KV_EXPRTYPE, entry->translation(0).type());
+
+    QDomElement domElementOriginal = m_domDoc.createElement(KV_ORG);
+    if (first_expr)
+    {
+      // save space, only tell language in first entry
+      QString s;
+      domElementOriginal.setAttribute(KV_SIZEHINT, m_doc->sizeHint(0));
+
+      s = m_doc->identifier(0).simplified();
+      if (s.isEmpty() )
+        s = "original";
+      domElementOriginal.setAttribute(KV_LANG, s);
+      if (s == q_org)
+        domElementOriginal.setAttribute(KV_QUERY, (QString) KV_O);
+      else if (s == q_trans)
+        domElementOriginal.setAttribute(KV_QUERY, (QString) KV_T);
+    }
+
+    if (!entry->translation(0).comment().isEmpty() )
+      domElementOriginal.setAttribute(KV_REMARK, entry->translation(0).comment());
+
+    if (!entry->translation(0).synonym().isEmpty() )
+      domElementOriginal.setAttribute(KV_SYNONYM, entry->translation(0).synonym());
+
+    if (!entry->translation(0).example().isEmpty() )
+      domElementOriginal.setAttribute(KV_EXAMPLE, entry->translation(0).example());
+
+    if (!entry->translation(0).usageLabel().isEmpty() )
+      domElementOriginal.setAttribute(KV_USAGE, entry->translation(0).usageLabel());
+
+    if (!entry->translation(0).paraphrase().isEmpty() )
+      domElementOriginal.setAttribute(KV_PARAPHRASE, entry->translation(0).paraphrase());
+
+    if (!entry->translation(0).antonym().isEmpty() )
+      domElementOriginal.setAttribute(KV_ANTONYM, entry->translation(0).antonym());
+
+    if (!entry->translation(0).pronunciation().isEmpty() )
+      domElementOriginal.setAttribute(KV_PRONUNCE, entry->translation(0).pronunciation());
+
+    if (!entry->uniqueType() && !entry->translation(0).type().isEmpty())
+      domElementOriginal.setAttribute(KV_EXPRTYPE, entry->translation(0).type());
+
+    if (!writeMultipleChoice(m_domDoc, domElementOriginal, entry->translation(0).multipleChoice()))
+      return false;
+
+    QString s;
+    QString entype = s = entry->translation(0).type();
+    int pos;
+    if (pos >= 0)
+      entype = s.left(pos);
+    else
+      entype = s;
+
+    if (entry->translation(0).conjugation().entryCount() > 0)
+    {
+      KEduVocConjugation conj = entry->translation(0).conjugation();
+      if (!writeConjugEntry(m_domDoc, domElementOriginal, conj))
+        return false;
+    }
+    else if (!entry->translation(0).comparison().isEmpty())
+    {
+      KEduVocComparison comp = entry->translation(0).comparison();
+      if (!writeComparison(m_domDoc, domElementOriginal, comp))
+        return false;
+    }
+
+    QDomText domTextOriginal = m_domDoc.createTextNode(entry->translation(0).translation());
+    domElementOriginal.appendChild(domTextOriginal);
+    domElementExpression.appendChild(domElementOriginal);
+
+    int trans = 1;
+    while (trans < m_doc->identifierCount())
+    {
+      QDomElement domElementTranslation = m_domDoc.createElement(KV_TRANS);
+      if (first_expr)
+      {
+        // save space, only tell language in first entry
+        QString s;
+        domElementTranslation.setAttribute(KV_SIZEHINT, m_doc->sizeHint(trans));
+
+        s = m_doc->identifier(trans).simplified();
+        if (s.isEmpty() )
+        {
+          s.setNum(trans);
+          s.prepend("translation ");
+        }
+        domElementTranslation.setAttribute(KV_LANG, s);
+        if (s == q_org)
+          domElementTranslation.setAttribute(KV_QUERY, (QString) KV_O);
+        else if (s == q_trans)
+          domElementTranslation.setAttribute(KV_QUERY, (QString) KV_T);
+      }
+
+      if (entry->translation(trans).gradeFrom(0).grade() != 0 || entry->translation(0).gradeFrom(trans).grade() != 0)
+        domElementTranslation.setAttribute(KV_GRADE, QString::number(entry->translation(trans).gradeFrom(0).grade()) + ';' + QString::number(entry->translation(0).gradeFrom(trans).grade()));
+
+      if (entry->translation(trans).gradeFrom(0).queryCount() != 0 || entry->translation(0).gradeFrom(trans).queryCount() != 0)
+        domElementTranslation.setAttribute(KV_COUNT, QString::number(entry->translation(trans).gradeFrom(0).queryCount()) + ';' + QString::number(entry->translation(0).gradeFrom(trans).queryCount()));
+
+      if (entry->translation(trans).gradeFrom(0).badCount() != 0 || entry->translation(0).gradeFrom(trans).badCount() != 0)
+        domElementTranslation.setAttribute(KV_BAD, QString::number(entry->translation(trans).gradeFrom(0).badCount()) + ';' + QString::number(entry->translation(0).gradeFrom(trans).badCount()));
+
+      if (entry->translation(trans).gradeFrom(0).queryDate().toTime_t() != 0 || entry->translation(0).gradeFrom(trans).queryDate().toTime_t() != 0)
+        domElementTranslation.setAttribute(KV_DATE, QString::number(entry->translation(trans).gradeFrom(0).queryDate().toTime_t()) + ';' + QString::number(entry->translation(0).gradeFrom(trans).queryDate().toTime_t()));
+
+      if (!entry->translation(trans).comment().isEmpty() )
+        domElementTranslation.setAttribute(KV_REMARK, entry->translation(trans).comment());
+
+      if (!entry->translation(trans).falseFriend(0).isEmpty() )
+        domElementTranslation.setAttribute(KV_FAUX_AMI_F, entry->translation(trans).falseFriend(0));
+
+      if (!entry->translation(0).falseFriend(trans).isEmpty() )
+        domElementTranslation.setAttribute(KV_FAUX_AMI_T, entry->translation(0).falseFriend(trans));
+
+      if (!entry->translation(trans).synonym().isEmpty() )
+        domElementTranslation.setAttribute(KV_SYNONYM, entry->translation(trans).synonym());
+
+      if (!entry->translation(trans).example().isEmpty() )
+        domElementTranslation.setAttribute(KV_EXAMPLE, entry->translation(trans).example());
+
+      if (!entry->translation(trans).usageLabel().isEmpty() )
+        domElementTranslation.setAttribute(KV_USAGE, entry->translation(trans).usageLabel());
+
+      if (!entry->translation(trans).paraphrase().isEmpty() )
+        domElementTranslation.setAttribute(KV_PARAPHRASE, entry->translation(trans).paraphrase());
+
+      if (!entry->translation(trans).antonym().isEmpty() )
+        domElementTranslation.setAttribute(KV_ANTONYM, entry->translation(trans).antonym());
+
+      if (!entry->translation(trans).pronunciation().isEmpty() )
+        domElementTranslation.setAttribute(KV_PRONUNCE, entry->translation(trans).pronunciation());
+
+      if (!entry->uniqueType() && !entry->translation(trans).type().isEmpty())
+        domElementTranslation.setAttribute(KV_EXPRTYPE, entry->translation(trans).type());
+
+      if (!writeMultipleChoice(m_domDoc, domElementTranslation, entry->translation(trans).multipleChoice()))
+        return false;
+
+      QString s;
+      QString entype = s = entry->translation(0).type();
+      int pos;
+      if (pos >= 0)
+        entype = s.left (pos);
+      else
+        entype = s;
+
+      if (entry->translation(trans).conjugation().entryCount() > 0)
+      {
+        KEduVocConjugation conj = entry->translation(trans).conjugation();
+        if (!writeConjugEntry(m_domDoc, domElementTranslation, conj))
+          return false;
+      }
+
+      if (!entry->translation(trans).comparison().isEmpty())
+      {
+        KEduVocComparison comp = entry->translation(trans).comparison();
+        if (!writeComparison(m_domDoc, domElementTranslation, comp))
+          return false;
+      }
+
+      QDomText domTextTranslation = m_domDoc.createTextNode(entry->translation(trans).translation());
+      domElementTranslation.appendChild(domTextTranslation);
+      domElementExpression.appendChild(domElementTranslation);
+
+      trans++;
+    }
+
+    domElementKvtml.appendChild(domElementExpression);
+
+    first_expr = false;
+  }
+
+  m_domDoc.appendChild(domElementKvtml);
+
+  QTextStream ts(m_outputFile);
+  m_domDoc.save(ts, 2);
+
+  return true;
+}
+
+bool KEduVocKvtml2Writer::writeInformation(QDomElement &informationElement, const QString &generator)
+{
+  QDomElement currentElement;
+  QDomText textNode;
+  
+  // generator
+  currentElement = m_domDoc.createElement(KVTML_GENERATOR);
+  textNode = m_domDoc.createTextNode(generator);
+  currentElement.appendChild(textNode);
+  informationElement.appendChild(currentElement);
+  
+  // title
+  if (!m_doc->title().isEmpty())
+  {
+    currentElement = m_domDoc.createElement(KVTML_TITLE);
+    textNode = m_domDoc.createTextNode(m_doc->title());
+    currentElement.appendChild(textNode);
+    informationElement.appendChild(currentElement);
+  }
+
+  // author
+  if (!m_doc->author().isEmpty())
+  {
+    currentElement = m_domDoc.createElement(KVTML_AUTHOR);
+    textNode = m_domDoc.createTextNode(m_doc->author());
+    currentElement.appendChild(textNode);
+    informationElement.appendChild(currentElement);
+  }
+
+  // license
+  if (!m_doc->license().isEmpty())
+  {
+    currentElement = m_domDoc.createElement(KVTML_LICENSE);
+    textNode = m_domDoc.createTextNode(m_doc->license());
+    currentElement.appendChild(textNode);
+    informationElement.appendChild(currentElement);
+  }
+
+  // comment
+  if (!m_doc->documentRemark().isEmpty())
+  {
+    currentElement = m_domDoc.createElement(KVTML_COMMENT);
+    textNode = m_domDoc.createTextNode(m_doc->documentRemark());
+    currentElement.appendChild(textNode);
+    informationElement.appendChild(currentElement);
+  }
+  
+  return true;
+}
+
+bool KEduVocKvtml2Writer::writeLesson(QDomDocument &domDoc, QDomElement &domElementParent)
+{
+  if (m_doc->lessonDescriptions().count() == 0)
+    return true;
+
+  QDomElement domElementLesson = domDoc.createElement(KV_LESS_GRP);
+  domElementLesson.setAttribute(KV_SIZEHINT, m_doc->sizeHint(-1));
+  int count = 1;
+
+  foreach(QString lesson, m_doc->lessonDescriptions())
+  {
+    if (!lesson.isNull())
+    {
+      QDomElement domElementDesc = domDoc.createElement(KV_LESS_DESC);
+      QDomText domTextDesc = domDoc.createTextNode(lesson);
+
+      domElementDesc.setAttribute(KV_LESS_NO, count);
+      if (m_doc->currentLesson() == count)
+        domElementDesc.setAttribute(KV_LESS_CURR, 1);
+      if (m_doc->lessonInQuery(count))
+        domElementDesc.setAttribute(KV_LESS_QUERY, 1);
+
+      domElementDesc.appendChild(domTextDesc);
+      domElementLesson.appendChild(domElementDesc);
+      count++;
+    }
+  }
+
+  domElementParent.appendChild(domElementLesson);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeArticle(QDomDocument &domDoc, QDomElement &domElementParent)
+/*
+ <article>
+  <e l="de">    lang determines also lang order in entries !!
+   <fi>eine</fi>  which must NOT differ
+   <fd>die</fd>
+   <mi>ein</mi>
+   <md>der</md>
+   <ni>ein</ni>
+   <nd>das</nd>
+  </e>
+ </article>
+*/
+{
+  if (m_doc->articleCount() == 0)
+    return true;
+
+  QDomElement domElementArticle = domDoc.createElement(KV_ARTICLE_GRP);
+  QString def;
+  QString indef;
+  QString s;
+
+  for (int lfn = 0; lfn < qMin(m_doc->articleCount(), m_doc->identifierCount()); lfn++)
+  {
+    QDomElement domElementEntry = domDoc.createElement(KV_ART_ENTRY);
+    if (lfn == 0)
+    {
+      s = m_doc->identifier(0).simplified();
+      if (s.isEmpty())
+        s = "original";
+    }
+    else
+    {
+      s = m_doc->identifier(lfn).simplified();
+      if (s.isEmpty())
+      {
+        s.setNum(lfn);
+        s.prepend("translation ");
+      }
+    }
+    domElementEntry.setAttribute(KV_LANG, s);
+
+    m_doc->article(lfn).getFemale(&def, &indef);
+    if (!def.isEmpty())
+    {
+      QDomElement domElementFD = domDoc.createElement(KV_ART_FD);
+      QDomText domTextFD = domDoc.createTextNode(def);
+
+      domElementFD.appendChild(domTextFD);
+      domElementEntry.appendChild(domElementFD);
+    }
+    if (!indef.isEmpty())
+    {
+      QDomElement domElementFI = domDoc.createElement(KV_ART_FI);
+      QDomText domTextFI = domDoc.createTextNode(indef);
+
+      domElementFI.appendChild(domTextFI);
+      domElementEntry.appendChild(domElementFI);
+    }
+
+    m_doc->article(lfn).getMale(&def, &indef);
+    if (!def.isEmpty())
+    {
+      QDomElement domElementMD = domDoc.createElement(KV_ART_MD);
+      QDomText domTextMD = domDoc.createTextNode(def);
+
+      domElementMD.appendChild(domTextMD);
+      domElementEntry.appendChild(domElementMD);
+    }
+    if (!indef.isEmpty())
+    {
+      QDomElement domElementMI = domDoc.createElement(KV_ART_MI);
+      QDomText domTextMI = domDoc.createTextNode(indef);
+
+      domElementMI.appendChild(domTextMI);
+      domElementEntry.appendChild(domElementMI);
+    }
+
+    m_doc->article(lfn).getNatural(&def, &indef);
+    if (!def.isEmpty())
+    {
+      QDomElement domElementND = domDoc.createElement(KV_ART_ND);
+      QDomText domTextND = domDoc.createTextNode(def);
+
+      domElementND.appendChild(domTextND);
+      domElementEntry.appendChild(domElementND);
+    }
+    if (!indef.isEmpty())
+    {
+      QDomElement domElementNI = domDoc.createElement(KV_ART_NI);
+      QDomText domTextNI = domDoc.createTextNode(indef);
+
+      domElementNI.appendChild(domTextNI);
+      domElementEntry.appendChild(domElementNI);
+    }
+
+    domElementArticle.appendChild(domElementEntry);
+  }
+
+  domElementParent.appendChild(domElementArticle);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeOption(QDomDocument &domDoc, QDomElement &domElementParent)
+{
+  QDomElement domElementOption = domDoc.createElement(KV_OPTION_GRP);
+  QDomElement domElementSort = domDoc.createElement(KV_OPT_SORT);
+
+  domElementSort.setAttribute(KV_BOOL_FLAG, (m_doc->isSortingEnabled()?1:0));
+  domElementOption.appendChild(domElementSort);
+
+  domElementParent.appendChild(domElementOption);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeType(QDomDocument &domDoc, QDomElement &domElementParent)
+{
+  if (m_doc->typeDescriptions().count() == 0)
+    return true;
+
+  QDomElement domElementType = domDoc.createElement(KV_TYPE_GRP);
+  int count = 1;
+
+  foreach(QString type, m_doc->typeDescriptions())
+  {
+    if (!(type.isNull()) )
+    {
+      QDomElement domElementDesc = domDoc.createElement(KV_TYPE_DESC);
+      QDomText domTextDesc = domDoc.createTextNode(type);
+
+      domElementDesc.setAttribute(KV_TYPE_NO, count);
+      domElementDesc.appendChild(domTextDesc);
+      domElementType.appendChild(domElementDesc);
+      count++;
+    }
+  }
+
+  domElementParent.appendChild(domElementType);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeTense(QDomDocument &domDoc, QDomElement &domElementParent)
+{
+  if (m_doc->tenseDescriptions().count() == 0)
+    return true;
+
+  QDomElement domElementTense = domDoc.createElement(KV_TENSE_GRP);
+  int count = 1;
+
+  foreach(QString tense, m_doc->tenseDescriptions())
+  {
+    if (!(tense.isNull())) {
+      QDomElement domElementDesc = domDoc.createElement(KV_TENSE_DESC);
+      QDomText domTextDesc = domDoc.createTextNode(tense);
+
+      domElementDesc.setAttribute(KV_TENSE_NO, count);
+      domElementDesc.appendChild(domTextDesc);
+      domElementTense.appendChild(domElementDesc);
+      count++;
+    }
+  }
+
+  domElementParent.appendChild(domElementTense);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeUsage(QDomDocument &domDoc, QDomElement &domElementParent)
+{
+  if (m_doc->usageDescriptions().count() == 0)
+    return true;
+
+  QDomElement domElementUsage = domDoc.createElement(KV_USAGE_GRP);
+  int count = 1;
+
+  foreach(QString usage, m_doc->usageDescriptions())
+  {
+    if (!(usage.isNull()))
+    {
+      QDomElement domElementDesc = domDoc.createElement(KV_USAGE_DESC);
+      QDomText domTextDesc = domDoc.createTextNode(usage);
+
+      domElementDesc.setAttribute(KV_USAGE_NO, count);
+      domElementDesc.appendChild(domTextDesc);
+      domElementUsage.appendChild(domElementDesc);
+      count++;
+    }
+  }
+
+  domElementParent.appendChild(domElementUsage);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeComparison(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocComparison &comp)
+/*
+ <comparison>
+   <l1>good</l1>
+   <l2>better</l2>
+   <l3>best</l3>
+ </comparison>
+*/
+{
+  if (comp.isEmpty())
+    return true;
+
+  QDomElement domElementComparison = domDoc.createElement(KV_COMPARISON_GRP);
+
+  if (!comp.l1().isEmpty() )
+  {
+    QDomElement domElementL1 = domDoc.createElement(KV_COMP_L1);
+    QDomText domTextL1 = domDoc.createTextNode(comp.l1());
+
+    domElementL1.appendChild(domTextL1);
+    domElementComparison.appendChild(domElementL1);
+  }
+
+  if (!comp.l2().isEmpty() )
+  {
+    QDomElement domElementL2 = domDoc.createElement(KV_COMP_L2);
+    QDomText domTextL2 = domDoc.createTextNode(comp.l2());
+
+    domElementL2.appendChild(domTextL2);
+    domElementComparison.appendChild(domElementL2);
+  }
+
+  if (!comp.l3().isEmpty() )
+  {
+    QDomElement domElementL3 = domDoc.createElement(KV_COMP_L3);
+    QDomText domTextL3 = domDoc.createTextNode(comp.l3());
+
+    domElementL3.appendChild(domTextL3);
+    domElementComparison.appendChild(domElementL3);
+  }
+
+  domElementParent.appendChild(domElementComparison);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeMultipleChoice(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocMultipleChoice &mc)
+/*
+ <multiplechoice>
+   <mc1>good</mc1>
+   <mc2>better</mc2>
+   <mc3>best</mc3>
+   <mc4>best 2</mc4>
+   <mc5>best 3</mc5>
+ </multiplechoice>
+*/
+{
+  if (mc.isEmpty())
+    return true;
+
+  QDomElement domElementMC = domDoc.createElement(KV_MULTIPLECHOICE_GRP);
+
+  if (!mc.choice(1).isEmpty() )
+  {
+    QDomElement domElementMC1 = domDoc.createElement(KV_MC_1);
+    QDomText domTextMC1 = domDoc.createTextNode(mc.choice(1));
+
+    domElementMC1.appendChild(domTextMC1);
+    domElementMC.appendChild(domElementMC1);
+  }
+
+  if (!mc.choice(2).isEmpty() )
+  {
+    QDomElement domElementMC2 = domDoc.createElement(KV_MC_2);
+    QDomText domTextMC2 = domDoc.createTextNode(mc.choice(2));
+
+    domElementMC2.appendChild(domTextMC2);
+    domElementMC.appendChild(domElementMC2);
+  }
+
+  if (!mc.choice(3).isEmpty() )
+  {
+    QDomElement domElementMC3 = domDoc.createElement(KV_MC_3);
+    QDomText domTextMC3 = domDoc.createTextNode(mc.choice(3));
+
+    domElementMC3.appendChild(domTextMC3);
+    domElementMC.appendChild(domElementMC3);
+  }
+
+  if (!mc.choice(4).isEmpty() )
+  {
+    QDomElement domElementMC4 = domDoc.createElement(KV_MC_4);
+    QDomText domTextMC4 = domDoc.createTextNode(mc.choice(4));
+
+    domElementMC4.appendChild(domTextMC4);
+    domElementMC.appendChild(domElementMC4);
+  }
+
+  if (!mc.choice(5).isEmpty() )
+  {
+    QDomElement domElementMC5 = domDoc.createElement(KV_MC_5);
+    QDomText domTextMC5 = domDoc.createTextNode(mc.choice(5));
+
+    domElementMC5.appendChild(domTextMC5);
+    domElementMC.appendChild(domElementMC5);
+  }
+
+  domElementParent.appendChild(domElementMC);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeConjugHeader(QDomDocument &domDoc, QDomElement &domElementParent, QList<KEduVocConjugation> &curr_conjug)
+{
+/*
+ <conjugation>    used in header for definiton of "prefix"
+  <e l="de">      lang determines also lang order in entries !!
+   <s1>I</s1>     which must NOT differ
+   <s2>you<2>
+   <s3f common="0">he</s3f>
+   <s3m>she</s3m>
+   <s3n>it</s3n>
+   <p1>we</p1>
+   <p2>you</p2>
+   <p3f common="1">they</p3f>
+   <p3m>they</p3m>
+   <p3n>they</p3n>
+  </e>
+ </conjugation>
+
+*/
+  if (curr_conjug.size() == 0)
+    return true;
+
+  QDomElement domElementConjug = domDoc.createElement(KV_CONJUG_GRP);
+  QString s;
+
+  for (int ent = 0; ent < qMin(curr_conjug.count(), m_doc->identifierCount()); ent++)
+  {
+    QDomElement domElementEntry = domDoc.createElement(KV_CON_ENTRY);
+
+      s = m_doc->identifier(ent).simplified();
+      if (s.isEmpty())
+      {
+        s.setNum(ent);
+        s.prepend("translation ");
+      }
+
+    domElementEntry.setAttribute(KV_LANG, s);
+
+    if (!writeConjug(domDoc, domElementEntry, curr_conjug[ent], CONJ_PREFIX))
+      return false;
+
+    domElementConjug.appendChild(domElementEntry);
+  }
+
+  domElementParent.appendChild(domElementConjug);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeConjugEntry(QDomDocument &domDoc, QDomElement &domElementParent, KEduVocConjugation &curr_conjug)
+/*
+ <conjugation>    in entry for definition of tenses of (irreg.) verbs
+  <t n="sipa">
+   <s1>go</s1>
+   <s2>go</s2>
+   <s3f>goes</s3f>
+   <s3m>goes</s3m>
+   <s3n>goes</s3n>
+   <p1>go</p1>
+   <p2>go</p2>
+   <p3f>go</p3f>
+   <p3m>go</p3m>
+   <p3n>go</p3n>
+  </t>
+ </conjugation>
+*/
+{
+  curr_conjug.cleanUp();
+  if (curr_conjug.entryCount() == 0 )
+    return true;
+
+  QDomElement domElementConjug = domDoc.createElement(KV_CONJUG_GRP);
+  QString type;
+
+  for (int lfn = 0; lfn < curr_conjug.entryCount(); lfn++)
+  {
+    QDomElement domElementType = domDoc.createElement(KV_CON_TYPE);
+
+    type = curr_conjug.getType(lfn);
+    domElementType.setAttribute(KV_CON_NAME, type);
+
+    if (!writeConjug(domDoc, domElementType, curr_conjug, curr_conjug.getType(lfn)))
+      return false;
+
+    domElementConjug.appendChild(domElementType);
+  }
+
+  domElementParent.appendChild(domElementConjug);
+  return true;
+}
+
+
+bool KEduVocKvtml2Writer::writeConjug(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocConjugation &curr_conjug, const QString &type)
+{
+  if (!curr_conjug.pers1Singular(type).isEmpty())
+  {
+    QDomElement domElementP1s = domDoc.createElement(KV_CON_P1S);
+    QDomText domTextP1s = domDoc.createTextNode(curr_conjug.pers1Singular(type));
+
+    domElementP1s.appendChild(domTextP1s);
+    domElementParent.appendChild(domElementP1s);
+  }
+
+  if (!curr_conjug.pers2Singular(type).isEmpty())
+  {
+    QDomElement domElementP2s = domDoc.createElement(KV_CON_P2S);
+    QDomText domTextP2s = domDoc.createTextNode(curr_conjug.pers2Singular(type));
+
+    domElementP2s.appendChild(domTextP2s);
+    domElementParent.appendChild(domElementP2s);
+  }
+
+  if (!curr_conjug.pers3FemaleSingular(type).isEmpty() || curr_conjug.pers3SingularCommon(type))
+  {
+    QDomElement domElementP3sf = domDoc.createElement(KV_CON_P3SF);
+    QDomText domTextP3sf = domDoc.createTextNode(curr_conjug.pers3FemaleSingular(type));
+
+    if (curr_conjug.pers3SingularCommon(type))
+      domElementP3sf.setAttribute(KV_CONJ_COMMON, 1);
+
+    domElementP3sf.appendChild(domTextP3sf);
+    domElementParent.appendChild(domElementP3sf);
+  }
+
+  if (!curr_conjug.pers3MaleSingular(type).isEmpty())
+  {
+    QDomElement domElementP3sm = domDoc.createElement(KV_CON_P3SM);
+    QDomText domTextP3sm = domDoc.createTextNode(curr_conjug.pers3MaleSingular(type));
+
+    domElementP3sm.appendChild(domTextP3sm);
+    domElementParent.appendChild(domElementP3sm);
+  }
+
+  if (!curr_conjug.pers3NaturalSingular(type).isEmpty())
+  {
+    QDomElement domElementP3sn = domDoc.createElement(KV_CON_P3SN);
+    QDomText domTextP3sn = domDoc.createTextNode(curr_conjug.pers3NaturalSingular(type));
+
+    domElementP3sn.appendChild(domTextP3sn);
+    domElementParent.appendChild(domElementP3sn);
+  }
+
+  if (!curr_conjug.pers1Plural(type).isEmpty())
+  {
+    QDomElement domElementP1p = domDoc.createElement(KV_CON_P1P);
+    QDomText domTextP1p = domDoc.createTextNode(curr_conjug.pers1Plural(type));
+
+    domElementP1p.appendChild(domTextP1p);
+    domElementParent.appendChild(domElementP1p);
+  }
+
+  if (!curr_conjug.pers2Plural(type).isEmpty())
+  {
+    QDomElement domElementP2p = domDoc.createElement(KV_CON_P2P);
+    QDomText domTextP2p = domDoc.createTextNode(curr_conjug.pers2Plural(type));
+
+    domElementP2p.appendChild(domTextP2p);
+    domElementParent.appendChild(domElementP2p);
+  }
+
+  if (!curr_conjug.pers3FemalePlural(type).isEmpty() || curr_conjug.pers3PluralCommon(type))
+  {
+    QDomElement domElementP3pf = domDoc.createElement(KV_CON_P3PF);
+    QDomText domTextP3pf = domDoc.createTextNode(curr_conjug.pers3FemalePlural(type));
+
+    if (curr_conjug.pers3PluralCommon(type))
+      domElementP3pf.setAttribute(KV_CONJ_COMMON, 1);
+
+    domElementP3pf.appendChild(domTextP3pf);
+    domElementParent.appendChild(domElementP3pf);
+  }
+
+  if (!curr_conjug.pers3MalePlural(type).isEmpty())
+  {
+    QDomElement domElementP3pm = domDoc.createElement(KV_CON_P3PM);
+    QDomText domTextP3pm = domDoc.createTextNode(curr_conjug.pers3MalePlural(type));
+
+    domElementP3pm.appendChild(domTextP3pm);
+    domElementParent.appendChild(domElementP3pm);
+  }
+
+  if (!curr_conjug.pers3NaturalPlural(type).isEmpty())
+  {
+    QDomElement domElementP3pn = domDoc.createElement(KV_CON_P3PN);
+    QDomText domTextP3pn = domDoc.createTextNode(curr_conjug.pers3NaturalPlural(type));
+
+    domElementP3pn.appendChild(domTextP3pn);
+    domElementParent.appendChild(domElementP3pn);
+  }
+
+  return true;
+}
diff --git a/kdeeducore/keduvockvtml2writer.h b/kdeeducore/keduvockvtml2writer.h
new file mode 100644 (file)
index 0000000..aae083c
--- /dev/null
@@ -0,0 +1,61 @@
+/***************************************************************************
+                     export a KEduVocDocument to a KVTML file
+    -----------------------------------------------------------------------
+    copyright       : (C) 2007 Jeremy Whiting <jeremy@scitools.com>
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef KEDUVOCKVTML2WRITER_H
+#define KEDUVOCKVTML2WRITER_H
+
+#include <QtXml/QDomDocument>
+#include <QList>
+#include <QFile>
+
+#include "keduvocgrammar.h"
+#include "keduvocmultiplechoice.h"
+
+class KEduVocDocument;
+
+class KEduVocKvtml2Writer
+{
+public:
+  KEduVocKvtml2Writer(QFile *file);
+
+  bool writeDoc(KEduVocDocument *doc, const QString &generator);
+  
+  /** write information entries
+   * @param informationElement QDomElement <information> to write to
+   * @param generator text describing generator
+   */
+  bool writeInformation(QDomElement &informationElement, const QString &generator);
+
+
+  bool writeLesson(QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeType(QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeTense(QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeUsage(QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeOption(QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeArticle (QDomDocument &domDoc, QDomElement &domElementParent);
+  bool writeConjugHeader(QDomDocument &domDoc, QDomElement &domElementParent, QList<KEduVocConjugation> &curr_conjug);
+  bool writeConjug(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocConjugation &curr_conjug, const QString &type);
+  bool writeConjugEntry(QDomDocument &domDoc, QDomElement &domElementParent, KEduVocConjugation &curr_conjug);
+  bool writeComparison(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocComparison &comp);
+  bool writeMultipleChoice(QDomDocument &domDoc, QDomElement &domElementParent, const KEduVocMultipleChoice &mc);
+
+private:
+  QFile *m_outputFile;
+  KEduVocDocument *m_doc;
+  
+  QDomDocument m_domDoc;
+};
+
+#endif