summaryrefslogtreecommitdiffstats
path: root/kvoctrain/kvoctrain/kvt-core
diff options
context:
space:
mode:
Diffstat (limited to 'kvoctrain/kvoctrain/kvt-core')
-rw-r--r--kvoctrain/kvoctrain/kvt-core/LineList.cpp95
-rw-r--r--kvoctrain/kvoctrain/kvt-core/LineList.h49
-rw-r--r--kvoctrain/kvoctrain/kvt-core/Makefile.am17
-rw-r--r--kvoctrain/kvoctrain/kvt-core/MultipleChoice.cpp119
-rw-r--r--kvoctrain/kvoctrain/kvt-core/MultipleChoice.h74
-rw-r--r--kvoctrain/kvoctrain/kvt-core/QueryManager.cpp673
-rw-r--r--kvoctrain/kvoctrain/kvt-core/QueryManager.h223
-rw-r--r--kvoctrain/kvoctrain/kvt-core/UsageManager.cpp155
-rw-r--r--kvoctrain/kvoctrain/kvt-core/UsageManager.h127
-rw-r--r--kvoctrain/kvoctrain/kvt-core/grammarmanager.cpp503
-rw-r--r--kvoctrain/kvoctrain/kvt-core/grammarmanager.h215
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_csv.cpp243
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_lex.cpp395
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml1.cpp888
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml2.cpp464
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_rh_kvtml.cpp856
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_vcb.cpp199
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_voc.cpp141
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvd_wkvtml.cpp960
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvoctraincore.h115
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvoctraindoc.cpp1061
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvoctraindoc.h747
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.cpp799
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.h465
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/Makefile.am10
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.cpp99
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.h156
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.cpp264
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.h104
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.cpp411
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.h108
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.cpp253
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.h187
-rw-r--r--kvoctrain/kvoctrain/kvt-core/kvt-xml/koxml_config.h47
-rw-r--r--kvoctrain/kvoctrain/kvt-core/langset.cpp220
-rw-r--r--kvoctrain/kvoctrain/kvt-core/langset.h92
36 files changed, 11534 insertions, 0 deletions
diff --git a/kvoctrain/kvoctrain/kvt-core/LineList.cpp b/kvoctrain/kvoctrain/kvt-core/LineList.cpp
new file mode 100644
index 00000000..5b79b3b9
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/LineList.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+
+ maintain list of lines from QMultiLineEdit
+
+ -----------------------------------------------------------------------
+
+ begin : Sun Aug 13 10:00:53 MET 2000
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 "LineList.h"
+
+#include <kdebug.h>
+
+LineList::LineList (const QString &multilines)
+{
+ setLines (multilines);
+}
+
+
+void LineList::setLines(const QString &the_lines )
+{
+ multilines.clear();
+ QString lines = the_lines;
+ int pos;
+ if ((pos = lines.find ('\n')) >= 0) {
+ while (pos >= 0) {
+ multilines.push_back(lines.left(pos));
+ lines.remove (0, pos+1);
+ pos = lines.find ('\n');
+ }
+ }
+
+ if (lines.length() > 0) // empty string at end ==> not an entry!
+ multilines.push_back(lines);
+
+ normalizeWS();
+}
+
+
+void LineList::normalizeWS()
+{
+ for (int i = 0; i < (int) multilines.size(); i++) {
+ multilines[i] = multilines[i].stripWhiteSpace();
+// FIXME: more tolerance with WS? 2*SPC = 1*SPC...
+ }
+}
+
+
+int LineList::count() const
+{
+ return multilines.size();
+}
+
+
+QString LineList::getLine (int index) const
+{
+ if (index < (int) multilines.size())
+ return multilines[index];
+ else {
+ kdError() << "LineList::getLine: index too big";
+ return "";
+ }
+}
+
+
+QString LineList::allLines() const
+{
+ QString ret;
+ if (multilines.size() > 0)
+ ret = multilines[0];
+
+ if (multilines.size() > 1) {
+ for (int i = 1; i < (int) multilines.size(); i++)
+ ret += "\n" + multilines[i];
+ }
+ return ret;
+}
+
diff --git a/kvoctrain/kvoctrain/kvt-core/LineList.h b/kvoctrain/kvoctrain/kvt-core/LineList.h
new file mode 100644
index 00000000..b1d6f01f
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/LineList.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+
+ maintain list of lines from QMultiLineEdit
+
+ -----------------------------------------------------------------------
+
+ begin : Sun Aug 13 10:00:53 MET 2000
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 LineList_h
+#define LineList_h
+
+#include <qstring.h>
+
+#include <vector>
+using namespace std;
+
+class LineList {
+ public:
+ LineList (const QString &multilines = "");
+
+ void setLines(const QString &lines);
+ void normalizeWS();
+ int count() const;
+ QString getLine (int index) const;
+ QString allLines() const;
+
+ protected:
+ vector<QString> multilines;
+};
+
+#endif // LineList_h
diff --git a/kvoctrain/kvoctrain/kvt-core/Makefile.am b/kvoctrain/kvoctrain/kvt-core/Makefile.am
new file mode 100644
index 00000000..fe356907
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/Makefile.am
@@ -0,0 +1,17 @@
+INCLUDES = -I$(srcdir)/.. -I../queryoption-dialogs \
+ -I$(srcdir)/../queryoption-dialogs -I$(top_builddir)/kvoctrain/kvoctrain/common-dialogs $(all_includes)
+
+lib_LTLIBRARIES = libkvoctraincore.la
+
+METASOURCES = AUTO
+
+libkvoctraincore_la_SOURCES = langset.cpp LineList.cpp kvoctrainexpr.cpp \
+ kvoctraindoc.cpp kvd_rh_kvtml.cpp kvd_rb_kvtml1.cpp kvd_rb_kvtml2.cpp kvd_wkvtml.cpp \
+ kvd_csv.cpp kvd_lex.cpp kvd_vcb.cpp UsageManager.cpp QueryManager.cpp \
+ MultipleChoice.cpp grammarmanager.cpp kvd_voc.cpp
+
+SUBDIRS = kvt-xml
+
+libkvoctraincore_la_LIBADD= kvt-xml/libkvtxml.la
+
+noinst_HEADERS = grammarmanager.h
diff --git a/kvoctrain/kvoctrain/kvt-core/MultipleChoice.cpp b/kvoctrain/kvoctrain/kvt-core/MultipleChoice.cpp
new file mode 100644
index 00000000..e73f358a
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/MultipleChoice.cpp
@@ -0,0 +1,119 @@
+/***************************************************************************
+
+ manage multiple choice suggestions for queries
+
+ -----------------------------------------------------------------------
+
+ begin : Mon Oct 29 18:09:29 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "MultipleChoice.h"
+
+MultipleChoice::MultipleChoice (
+ const QString &mc1,
+ const QString &mc2,
+ const QString &mc3,
+ const QString &mc4,
+ const QString &mc5
+ )
+{
+ setMC1 (mc1);
+ setMC2 (mc2);
+ setMC3 (mc3);
+ setMC4 (mc4);
+ setMC5 (mc5);
+}
+
+
+bool MultipleChoice::isEmpty() const
+{
+ return muc1.stripWhiteSpace().isEmpty()
+ && muc2.stripWhiteSpace().isEmpty()
+ && muc3.stripWhiteSpace().isEmpty()
+ && muc4.stripWhiteSpace().isEmpty()
+ && muc5.stripWhiteSpace().isEmpty();
+}
+
+
+void MultipleChoice::clear()
+{
+ muc1 = "";
+ muc2 = "";
+ muc3 = "";
+ muc4 = "";
+ muc5 = "";
+}
+
+
+QString MultipleChoice::mc (unsigned idx) const
+{
+ switch (idx) {
+ case 0: return muc1;
+ case 1: return muc2;
+ case 2: return muc3;
+ case 3: return muc4;
+ case 4: return muc5;
+ }
+ return "";
+}
+
+
+unsigned MultipleChoice::size()
+{
+ normalize();
+ unsigned num = 0;
+ if (!muc1.isEmpty() )
+ ++num;
+ if (!muc2.isEmpty() )
+ ++num;
+ if (!muc3.isEmpty() )
+ ++num;
+ if (!muc4.isEmpty() )
+ ++num;
+ if (!muc5.isEmpty() )
+ ++num;
+ return num;
+}
+
+
+void MultipleChoice::normalize()
+{
+ // fill from first to last
+
+ if (muc1.isEmpty()) {
+ muc1 = muc2;
+ muc2 = "";
+ }
+
+ if (muc2.isEmpty()) {
+ muc2 = muc3;
+ muc3 = "";
+ }
+
+ if (muc3.isEmpty()) {
+ muc3 = muc4;
+ muc4 = "";
+ }
+
+ if (muc4.isEmpty()) {
+ muc4 = muc5;
+ muc5 = "";
+ }
+
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/MultipleChoice.h b/kvoctrain/kvoctrain/kvt-core/MultipleChoice.h
new file mode 100644
index 00000000..99bc56ea
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/MultipleChoice.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+
+ manage multiple choice suggestions for queries
+
+ -----------------------------------------------------------------------
+
+ begin : Mon Oct 29 18:09:29 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 MultipleChoice_included
+#define MultipleChoice_included
+
+#include <qstring.h>
+
+#define MAX_MULTIPLE_CHOICE 5 // select one out of x
+
+class MultipleChoice
+{
+
+public:
+
+ MultipleChoice() {}
+
+ MultipleChoice (
+ const QString &mc1,
+ const QString &mc2,
+ const QString &mc3,
+ const QString &mc4,
+ const QString &mc5
+ );
+
+ void setMC1 (const QString &s) { muc1 = s; }
+ void setMC2 (const QString &s) { muc2 = s; }
+ void setMC3 (const QString &s) { muc3 = s; }
+ void setMC4 (const QString &s) { muc4 = s; }
+ void setMC5 (const QString &s) { muc5 = s; }
+
+ QString mc1 () const { return muc1; }
+ QString mc2 () const { return muc2; }
+ QString mc3 () const { return muc3; }
+ QString mc4 () const { return muc4; }
+ QString mc5 () const { return muc5; }
+
+ QString mc (unsigned idx) const;
+
+ bool isEmpty() const;
+ void normalize();
+ void clear();
+ unsigned size();
+
+protected:
+
+ QString muc1, muc2, muc3, muc4, muc5;
+};
+
+
+#endif // MultipleChoice_included
diff --git a/kvoctrain/kvoctrain/kvt-core/QueryManager.cpp b/kvoctrain/kvoctrain/kvt-core/QueryManager.cpp
new file mode 100644
index 00000000..2c7b76ca
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/QueryManager.cpp
@@ -0,0 +1,673 @@
+/***************************************************************************
+
+ manage queries
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Jul 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <klocale.h>
+#include <kconfig.h>
+
+#include <iostream>
+#include <vector>
+using namespace std;
+
+#include "QueryManager.h"
+#include "kvoctraincore.h"
+#include <prefs.h>
+
+vector<QString> QueryManager::userTypes;
+
+struct t_type_rel
+{
+ const char *short_ref;
+ const char *long_ref;
+};
+
+// types are hierarchical !
+// - . divides main from sub type
+// - sub types must follow main type
+
+// user types are strings-references like this: #1
+
+static t_type_rel InternalTypeRelations [] =
+{
+ { QM_ADJ, I18N_NOOP("Adjective") },
+
+ { QM_ADV, I18N_NOOP("Adverb") },
+
+ { QM_ART, I18N_NOOP("Article") },
+ { QM_ART QM_TYPE_DIV QM_ART_DEF, I18N_NOOP("Article Definite") },
+ { QM_ART QM_TYPE_DIV QM_ART_IND, I18N_NOOP("Article Indefinite") },
+
+ { QM_CON, I18N_NOOP("Conjunction") },
+
+ { QM_NAME, I18N_NOOP("Name") }, // old type "3"
+
+ { QM_NOUN, I18N_NOOP("Noun") }, // old type "2"
+ { QM_NOUN QM_TYPE_DIV QM_NOUN_M, I18N_NOOP("Noun Male") },
+ { QM_NOUN QM_TYPE_DIV QM_NOUN_F, I18N_NOOP("Noun Female") },
+ { QM_NOUN QM_TYPE_DIV QM_NOUN_S, I18N_NOOP("Noun Neutral") },
+
+ { QM_NUM, I18N_NOOP("Numeral") },
+ { QM_NUM QM_TYPE_DIV QM_NUM_ORD, I18N_NOOP("Numeral Ordinal") },
+ { QM_NUM QM_TYPE_DIV QM_NUM_CARD, I18N_NOOP("Numeral Cardinal") },
+
+ { QM_PHRASE, I18N_NOOP("Phrase") },
+
+ { QM_PREP, I18N_NOOP("Preposition") },
+
+ { QM_PRON, I18N_NOOP("Pronoun") },
+ { QM_PRON QM_TYPE_DIV QM_PRON_POS, I18N_NOOP("Pronoun Possessive") },
+ { QM_PRON QM_TYPE_DIV QM_PRON_PER, I18N_NOOP("Pronoun Personal") },
+
+ { QM_QUEST, I18N_NOOP("Question") },
+
+ { QM_VERB, I18N_NOOP("Verb") }, // old type "1"
+ { QM_VERB QM_TYPE_DIV QM_VERB_IRR, I18N_NOOP("Verb Irregular") },
+ { QM_VERB QM_TYPE_DIV QM_VERB_REG, I18N_NOOP("Verb Regular") },
+
+ { 0, 0 } // the end
+};
+
+
+QString QueryManager::getSubType (const QString & type)
+{
+ int i;
+ QString t = type;
+ if ((i = t.find(QM_TYPE_DIV)) >= 0) {
+ t.remove(0, i+1);
+ return t;
+ }
+ else
+ return QString::null;
+}
+
+
+QString QueryManager::getMainType (const QString & type)
+{
+ int i;
+ if ((i = type.find(QM_TYPE_DIV)) >= 0)
+ return type.left(i);
+ else
+ return type;
+}
+
+
+QueryManager::QueryManager()
+{
+ lessonitems.clear();
+}
+
+
+QuerySelection QueryManager::select(kvoctrainDoc *doc, int act_lesson, int oindex, int tindex)
+{
+ QuerySelection random;
+ random.resize(doc->numLessons()+1);
+ for (int i = 0; i < doc->numEntries(); i++)
+ doc->getEntry(i)->setInQuery(false);
+
+ // selecting might take rather long
+ int ent_no = 0;
+ int ent_percent = doc->numEntries() / 100;
+ float f_ent_percent = doc->numEntries() / 100.0;
+ emit doc->progressChanged(doc, 0);
+
+ //Note that Leitner style learning (altlearn) normally only uses 20
+ //entries, we just ignore that here
+ for (int i = 0; i < doc->numEntries(); i++) {
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit doc->progressChanged(doc, int (ent_no / f_ent_percent));
+
+ kvoctrainExpr *expr = doc->getEntry(i);
+ unsigned int lessonno;
+ if (Prefs::altLearn())
+ lessonno = 0; //We only use a single array in Leitner style
+ else
+ lessonno = expr->getLesson();
+
+ if (expr->isActive() ){
+ if (Prefs::swapDirection()) {
+ if ( validate (expr, act_lesson, oindex, tindex)
+ || validate (expr, act_lesson, tindex, oindex)) {
+ random[lessonno].push_back (QueryEntryRef(expr, i));
+ expr->setInQuery(true);
+ }
+ }
+ else {
+ if (validate (expr, act_lesson, oindex, tindex)) {
+ random[lessonno].push_back (QueryEntryRef(expr, i));
+ expr->setInQuery(true);
+ }
+ }
+ }
+ }
+
+ // remove empty lesson elements
+ for (int i = (int) random.size()-1; i >= 0; i--)
+ if (random[i].size() == 0)
+ random.erase(random.begin() + i);
+ return random;
+}
+
+
+bool QueryManager::validate(kvoctrainExpr *expr, int act_lesson, int oindex, int tindex)
+{
+ int index = tindex ? tindex : oindex;
+ if ((compareExpiring(expr->getGrade(index, oindex != 0),
+ expr->getQueryDate(index, oindex != 0), Prefs::expire())
+ ||
+
+ (
+ compareGrade ((CompType) Prefs::compType(Prefs::EnumType::Grade), expr->getGrade(index, oindex != 0), Prefs::gradeItem())
+ && compareQuery ((CompType) Prefs::compType(Prefs::EnumType::Query), expr->getQueryCount(index, oindex != 0), Prefs::queryItem())
+ && compareBad ((CompType) Prefs::compType(Prefs::EnumType::Bad), expr->getBadCount(index, oindex != 0), Prefs::badItem())
+ && compareDate ((CompType) Prefs::compType(Prefs::EnumType::Date), expr->getQueryDate(index, oindex != 0), Prefs::dateItem())
+
+ && compareBlocking(expr->getGrade(index, oindex != 0),
+ expr->getQueryDate(index, oindex != 0), Prefs::block())
+ )
+ )
+// lesson + word type must ALWAYS match
+// (and there must be a word on both sides)
+ && compareLesson ((CompType) Prefs::compType(Prefs::EnumType::Lesson), expr->getLesson(), lessonitems, act_lesson)
+ && compareType ((CompType) Prefs::compType(Prefs::EnumType::WordType), expr->getType(index), Prefs::typeItem())
+ && !expr->getOriginal().stripWhiteSpace().isEmpty()
+ && !expr->getTranslation(index).stripWhiteSpace().isEmpty()
+ )
+ return true;
+ else
+ return false;
+
+}
+
+
+QuerySelection QueryManager::select(kvoctrainDoc *doc, int act_lesson, int idx, QString type)
+{
+ QuerySelection random;
+ random.resize(doc->numLessons()+1);
+ for (int i = 0; i < doc->numEntries(); i++)
+ doc->getEntry(i)->setInQuery(false);
+
+ // selecting might take rather long
+ int ent_no = 0;
+ int ent_percent = doc->numEntries() / 100;
+ float f_ent_percent = doc->numEntries() / 100.0;
+ emit doc->progressChanged(doc, 0);
+
+ for (int i = 0; i < doc->numEntries(); i++) {
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit doc->progressChanged(doc, int (ent_no / f_ent_percent));
+
+ kvoctrainExpr *expr = doc->getEntry(i);
+ if (expr->isActive() && validate (expr, act_lesson, idx, type)) {
+ random[expr->getLesson()].push_back (QueryEntryRef(expr, i));
+ expr->setInQuery(true);
+ }
+ }
+
+ // remove empty lesson elements
+ for (int i = (int) random.size()-1; i >= 0; i--)
+ if (random[i].size() == 0)
+ random.erase(random.begin() + i);
+
+ return random;
+}
+
+
+bool QueryManager::validate(kvoctrainExpr *expr, int act_lesson, int idx, QString query_type)
+{
+ QString qtype;
+ int pos = query_type.find (QM_TYPE_DIV);
+ if (pos >= 0)
+ qtype = query_type.left (pos);
+ else
+ qtype = query_type;
+
+ QString expr_type = expr->getType(idx);
+ bool type_ok = false;
+ if (qtype == QM_NOUN) {
+ type_ok = expr_type == QM_NOUN QM_TYPE_DIV QM_NOUN_S
+ || expr_type == QM_NOUN QM_TYPE_DIV QM_NOUN_M
+ || expr_type == QM_NOUN QM_TYPE_DIV QM_NOUN_F;
+
+ }
+ else if (qtype == QM_VERB) {
+ type_ok = ( expr_type == QM_VERB
+ || expr_type == QM_VERB QM_TYPE_DIV QM_VERB_IRR
+ || expr_type == QM_VERB QM_TYPE_DIV QM_VERB_REG
+ )
+ && expr->getConjugation(idx).numEntries() > 0;
+
+ }
+ else if (qtype == QM_ADJ) {
+ type_ok = expr_type == QM_ADJ
+ && !expr->getComparison(idx).isEmpty();
+ }
+ else
+ return false;
+
+ if (compareLesson ((CompType) Prefs::compType(Prefs::EnumType::Lesson), expr->getLesson(),
+ lessonitems, act_lesson)
+ && type_ok) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+QuerySelection QueryManager::select(kvoctrainDoc *doc, int act_lesson, int idx, QueryType type)
+{
+ QuerySelection random;
+ random.resize(doc->numLessons()+1);
+ for (int i = 0; i < doc->numEntries(); i++)
+ doc->getEntry(i)->setInQuery(false);
+
+ // selecting might take rather long
+ int ent_no = 0;
+ int ent_percent = doc->numEntries() / 100;
+ float f_ent_percent = doc->numEntries() / 100.0;
+ emit doc->progressChanged(doc, 0);
+
+ for (int i = 0; i < doc->numEntries(); i++) {
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit doc->progressChanged(doc, int (ent_no / f_ent_percent));
+
+ kvoctrainExpr *expr = doc->getEntry(i);
+ if (expr->isActive() && validate (expr, act_lesson, idx, type)) {
+ random[expr->getLesson()].push_back (QueryEntryRef(expr, i));
+ expr->setInQuery(true);
+ }
+ }
+
+ // remove empty lesson elements
+ for (int i = (int) random.size()-1; i >= 0; i--)
+ if (random[i].size() == 0)
+ random.erase(random.begin() + i);
+
+ return random;
+}
+
+
+bool QueryManager::validate(kvoctrainExpr *expr, int act_lesson, int idx, QueryType query_type)
+{
+ bool type_ok = false;
+ if (query_type == QT_Synonym) {
+ type_ok = !expr->getSynonym(idx).stripWhiteSpace().isEmpty();
+ }
+ else if (query_type == QT_Antonym) {
+ type_ok = !expr->getAntonym(idx).stripWhiteSpace().isEmpty();
+ }
+ else if (query_type == QT_Paraphrase) {
+ type_ok = !expr->getParaphrase(idx).stripWhiteSpace().isEmpty();
+ }
+ else if (query_type == QT_Example) {
+ type_ok = !expr->getExample(idx).stripWhiteSpace().isEmpty();
+ }
+
+ if (compareLesson ((CompType) Prefs::compType(Prefs::EnumType::Lesson), expr->getLesson(),
+ lessonitems, act_lesson)
+ && type_ok)
+ return true;
+
+ return false;
+}
+
+
+QString QueryManager::compStr(Prefs::EnumCompType::type type)
+{
+ QString str = "???";
+ switch (type)
+ {
+ case DontCare: str = i18n("Do not Care"); break;
+ case WorseThan: str = i18n("Worse Than"); break;
+ case WorseEqThan: str = i18n("Equal/Worse Than"); break;
+ case MoreThan: str = i18n(">"); break;
+ case MoreEqThan: str = i18n(">="); break;
+ case BetterEqThan: str = i18n("Equal/Better Than"); break;
+ case BetterThan: str = i18n("Better Than"); break;
+ case LessEqThan: str = i18n("<="); break;
+ case LessThan: str = i18n("<"); break;
+
+ case EqualTo : str = i18n("Equal To"); break;
+ case NotEqual: str = i18n("Not Equal"); break;
+
+ case OneOf : str = i18n("Contained In"); break;
+ case NotOneOf: str = i18n("Not Contained In"); break;
+
+ case Within : str = i18n("Within Last"); break;
+ case Before : str = i18n("Before"); break;
+ case NotQueried: str = i18n("Not Queried"); break;
+
+ case Current : return i18n("Current Lesson"); break;
+ case NotAssigned: return i18n("Not Assigned"); break;
+ default:
+ ;
+ }
+ return str;
+}
+
+
+QString QueryManager::gradeStr (int i)
+{
+ switch (i) {
+ case KV_NORM_GRADE: return i18n(KV_NORM_TEXT); break;
+ case KV_LEV1_GRADE: return i18n(KV_LEV1_TEXT); break;
+ case KV_LEV2_GRADE: return i18n(KV_LEV2_TEXT); break;
+ case KV_LEV3_GRADE: return i18n(KV_LEV3_TEXT); break;
+ case KV_LEV4_GRADE: return i18n(KV_LEV4_TEXT); break;
+ case KV_LEV5_GRADE: return i18n(KV_LEV5_TEXT); break;
+ case KV_LEV6_GRADE: return i18n(KV_LEV6_TEXT); break;
+ case KV_LEV7_GRADE: return i18n(KV_LEV7_TEXT); break;
+ default: return i18n(KV_LEV1_TEXT); break;
+ }
+}
+
+
+vector<TypeRelation> QueryManager::getRelation (bool only_maintypes)
+{
+ vector<TypeRelation> vec;
+ for (int i = 0; i < (int) userTypes.size(); i++) {
+ QString s;
+ s.setNum(i+1);
+ s.insert(0, QM_USER_TYPE);
+ vec.push_back(TypeRelation(s, userTypes[i]));
+ }
+
+
+ t_type_rel *type = InternalTypeRelations;
+ while (type->short_ref != 0) {
+ if (!only_maintypes || strstr (type->short_ref, QM_TYPE_DIV) == 0)
+ vec.push_back(TypeRelation(type->short_ref, i18n(type->long_ref)));
+ type++;
+ }
+
+ return vec;
+}
+
+
+QString QueryManager::typeStr (const QString id)
+{
+ if (id.left(1) == QM_USER_TYPE) {
+ QString num = id;
+ num.remove (0, 1);
+ int i = num.toInt()-1;
+ if (i >= 0 && i < (int) userTypes.size() )
+ return userTypes[i];
+ else
+ return QString::null;
+ }
+ else {
+ t_type_rel *type = InternalTypeRelations;
+ while (type->short_ref != 0) {
+ if (type->short_ref == id)
+ return i18n(type->long_ref);
+ type++;
+ }
+ }
+ return QString::null;
+}
+
+
+bool QueryManager::compareBlocking (int grade, int date, bool use_it)
+{
+ time_t cmp = Prefs::blockItem(grade);
+ if (grade == KV_NORM_GRADE || cmp == 0 || !use_it) // don't care || all off
+ return true;
+ else {
+ time_t now = time(0);
+ return date+cmp < now;
+ }
+}
+
+
+bool QueryManager::compareExpiring (int grade, int date, bool use_it)
+{
+ time_t cmp = Prefs::expireItem(grade);
+ if (grade == KV_NORM_GRADE || cmp == 0 || !use_it) // don't care || all off
+ return false;
+ else {
+ time_t now = time(0);
+ return date+cmp < now;
+ }
+}
+
+
+bool QueryManager::compareDate (CompType type, time_t qd, time_t limit)
+{
+ time_t now = time(0);
+ bool erg = true;
+ switch (type) {
+ case DontCare: erg = true;
+ break;
+
+ case Before: erg = qd == 0 || qd < now-limit; // never queried or older date
+ break;
+
+ case Within: erg = qd >= now-limit; // newer date
+ break;
+
+ case NotQueried: erg = qd == 0;
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+bool QueryManager::compareQuery (CompType type, int qgrade, int limit)
+{
+ bool erg = true;
+ switch (type) {
+ case DontCare: erg = true;
+ break;
+
+ case MoreThan: erg = qgrade > limit; // sel has higher query count
+ break;
+
+ case MoreEqThan: erg = qgrade >= limit;
+ break;
+
+ case EqualTo: erg = qgrade == limit;
+ break;
+
+ case NotEqual: erg = qgrade != limit;
+ break;
+
+ case LessEqThan: erg = qgrade <= limit; // sel has less count
+ break;
+
+ case LessThan: erg = qgrade < limit;
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+bool QueryManager::compareBad (CompType type, int bcount, int limit)
+{
+ bool erg = true;
+ switch (type) {
+ case DontCare: erg = true;
+ break;
+
+ case MoreThan: erg = bcount > limit; // sel has higher bad count
+ break;
+
+ case MoreEqThan: erg = bcount >= limit;
+ break;
+
+ case EqualTo: erg = bcount == limit;
+ break;
+
+ case NotEqual: erg = bcount != limit;
+ break;
+
+ case LessEqThan: erg = bcount <= limit; // sel has less count
+ break;
+
+ case LessThan: erg = bcount < limit;
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+bool QueryManager::compareGrade (CompType type, grade_t qgrade, grade_t limit)
+{
+ bool erg = true;
+ switch (type) {
+ case DontCare: erg = true;
+ break;
+
+ case WorseThan: erg = qgrade < limit; // sel has worse grade
+ break;
+
+ case WorseEqThan: erg = qgrade <= limit;
+ break;
+
+ case EqualTo: erg = qgrade == limit;
+ break;
+
+ case NotEqual: erg = qgrade != limit;
+ break;
+
+ case BetterEqThan: erg = qgrade >= limit; // sel has better grade
+ break;
+
+ case BetterThan: erg = qgrade > limit;
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+bool QueryManager::compareType (CompType type, const QString & exprtype, const QString & limit)
+{
+ bool erg = true;
+ switch (type) {
+ case DontCare: erg = true;
+ break;
+
+ case EqualTo: erg = getMainType(exprtype) == getMainType(limit); // type is same
+ break;
+
+ case NotEqual: erg = getMainType(exprtype) != getMainType(limit); // other type
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+bool QueryManager::compareLesson (CompType type, int less, const vector<int> &limit, int current)
+{
+ bool erg = true;
+ switch (type) {
+ case DontCare:
+ erg = true;
+ break;
+
+ case OneOf:
+ {
+ erg = false;
+ for (int i = 0; !erg && i < (int) limit.size(); i++)
+ if (limit[i] == less)
+ erg = true;
+ }
+ break;
+
+ case NotOneOf:
+ {
+ erg = true;
+ for (int i = 0; erg && i < (int) limit.size(); i++)
+ if (limit[i] == less)
+ erg = false;
+ }
+ break;
+
+ case Current:
+ erg = less == current;
+ break;
+
+ case NotAssigned:
+ erg = less == 0;
+ break;
+
+ default:
+ ;
+ }
+ return erg;
+}
+
+
+void QueryManager::setTypeNames (vector<QString> names)
+{
+ userTypes = names;
+}
+
+
+void QueryManager::setLessonItemStr (const QString & indices)
+{
+ int pos;
+ QString indices_copy = indices;
+ lessonitems.clear();
+ while ((pos = indices_copy.find(' ')) >= 0) {
+ QString s = indices_copy.left(pos);
+ indices_copy.remove(0, pos+1);
+ lessonitems.push_back(s.toInt());
+ }
+ if (indices_copy.length() != 0) {
+ lessonitems.push_back(indices_copy.toInt());
+ }
+}
+
+
+QString QueryManager::lessonItemStr() const
+{
+ QString s, ret;
+ for (int i = 0; i < (int) lessonitems.size(); i++) {
+ s.setNum (lessonitems[i]);
+ if (i != 0)
+ ret += ' ';
+ ret += s;
+ }
+ return ret;
+}
+
diff --git a/kvoctrain/kvoctrain/kvt-core/QueryManager.h b/kvoctrain/kvoctrain/kvt-core/QueryManager.h
new file mode 100644
index 00000000..07567d22
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/QueryManager.h
@@ -0,0 +1,223 @@
+/***************************************************************************
+
+ manage queries
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Jul 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 QueryManager_included
+#define QueryManager_included
+
+#include <vector>
+using namespace std;
+
+#include "kvoctraindoc.h"
+#include "prefs.h"
+
+class kvoctrainDoc;
+class KConfig;
+class kvoctrainExpr;
+class Prefs;
+
+// internal types, indented are subtypes
+
+#define QM_VERB "v" // go
+#define QM_VERB_IRR "ir"
+#define QM_VERB_REG "re"
+#define QM_NOUN "n" // table, coffee
+#define QM_NOUN_F "f"
+#define QM_NOUN_M "m"
+#define QM_NOUN_S "s"
+#define QM_NAME "nm"
+#define QM_ART "ar" // article
+#define QM_ART_DEF "def" // definite a/an
+#define QM_ART_IND "ind" // indefinite the
+#define QM_ADJ "aj" // adjective expensive, good
+#define QM_ADV "av" // adverb today, strongly
+#define QM_PRON "pr" // pronoun you, she
+#define QM_PRON_POS "pos" // possessive my, your
+#define QM_PRON_PER "per" // personal
+#define QM_PHRASE "ph"
+#define QM_NUM "num" // numeral
+#define QM_NUM_ORD "ord" // ordinal first, second
+#define QM_NUM_CARD "crd" // cardinal one, two
+#define QM_INFORMAL "ifm"
+#define QM_FIG "fig"
+#define QM_CON "con" // conjuncton and, but
+#define QM_PREP "pre" // preposition behind, between
+#define QM_QUEST "qu" // question who, what
+
+// type delimiters
+
+#define QM_USER_TYPE "#" // designates number of user type
+#define QM_TYPE_DIV ":" // divide main from subtype
+
+//enum kvq_timeout_t { kvq_notimeout, kvq_show, kvq_cont };
+
+enum QueryType { QT_Random, QT_Multiple,
+ QT_Articles, QT_Conjugation, QT_Comparison,
+ QT_Synonym, QT_Antonym, QT_Example, QT_Paraphrase };
+
+
+class TypeRelation
+{
+ public:
+
+ TypeRelation (const QString & _short, const QString & _long)
+ : shortId (_short), longId(_long) {}
+
+ QString shortStr() const { return shortId; }
+ QString longStr() const { return longId; }
+
+ protected:
+
+ QString shortId, longId;
+};
+
+
+struct QueryEntryRef {
+ QueryEntryRef (kvoctrainExpr *_exp,
+ int _nr)
+ : exp(_exp), nr(_nr) {}
+
+
+ kvoctrainExpr *exp;
+ int nr;
+};
+
+typedef vector<vector<QueryEntryRef> > QuerySelection;
+
+class QueryManager
+{
+ public:
+ // don´t change the order/remove one of these,
+ // just APPEND new types
+ enum CompType { DontCare,
+ MoreEqThan, MoreThan,
+ Before, Within,
+ WorseThan, WorseEqThan,
+ EqualTo, NotEqual,
+ LessEqThan, LessThan,
+ BetterThan, BetterEqThan,
+ Current, NotAssigned, NotQueried,
+ Auto_Time, Auto_Count,
+ OneOf, NotOneOf
+ };
+
+ QueryManager ();
+
+ //void loadConfig (KConfig *);
+ //void saveConfig (KConfig *);
+
+ static vector<TypeRelation> getRelation (bool only_maintypes);
+ static void setTypeNames (vector<QString> names);
+ static QString getSubType (const QString & type);
+ static QString getMainType (const QString & type);
+
+ static QString compStr(Prefs::EnumCompType::type type);
+ static QString gradeStr(int i);
+ static QString typeStr(const QString id);
+
+ void setLessonItems(vector<int> indices) { lessonitems = indices; }
+ void setLessonItemStr(const QString & indices);
+ //void setDateItem (time_t time) { dateitem = time; }
+ //void setQueryItem (int query) { queryitem = query; }
+ //void setBadItem (int bad) { baditem = bad; }
+ //void setTypeItem (const QString & type) { typeitem = type; }
+ //void setGradeItem (grade_t grade) { gradeitem = grade; }
+ //void setBlockItem (int item, int grade);
+ //void setExpireItem (int item, int grade);
+
+ vector<int> lessonItems() const { return lessonitems; }
+ QString lessonItemStr() const;
+ //time_t dateItem () const { return dateitem; }
+ //int queryItem () const { return queryitem; }
+ //int badItem () const { return baditem; }
+ //QString typeItem () const { return typeitem; }
+ //grade_t gradeItem () const { return gradeitem; }
+ //int blockItem (int grade) const;
+ //int expireItem (int grade) const;
+
+ //void setDateComp (CompType time) { datecomp = time; }
+ //void setLessonComp (CompType less) { lessoncomp = less; }
+ //void setQueryComp (CompType query) { querycomp = query; }
+ //void setBadComp (CompType bad) { badcomp = bad; }
+ //void setTypeComp (CompType type) { typecomp = type; }
+ //void setGradeComp (CompType grade) { gradecomp = grade; }
+
+ //CompType dateComp () const { return datecomp; }
+ //CompType lessonComp () const { return lessoncomp; }
+ //CompType queryComp () const { return querycomp; }
+ //CompType badComp () const { return badcomp; }
+ //CompType typeComp () const { return typecomp; }
+ //CompType gradeComp () const { return gradecomp; }
+
+ bool validate(kvoctrainExpr *expr, int act_lesson,
+ int oindex, int tindex);
+
+ QuerySelection select(kvoctrainDoc*, int act_lesson,
+ int oindex, int tindex);
+
+ bool validate(kvoctrainExpr *expr, int act_lesson,
+ int index, QString type);
+
+ QuerySelection select(kvoctrainDoc*, int act_lesson,
+ int index, QString type);
+
+ bool validate(kvoctrainExpr *expr, int act_lesson,
+ int index, QueryType type);
+
+ QuerySelection select(kvoctrainDoc*, int act_lesson,
+ int index, QueryType type);
+
+ protected:
+
+ bool compareBlocking (int grade, int limit, bool use_it);
+ bool compareExpiring (int grade, int limit, bool use_it);
+ bool compareDate (CompType, time_t, time_t);
+ bool compareQuery (CompType, int, int);
+ bool compareBad (CompType, int, int);
+ bool compareGrade (CompType, grade_t, grade_t);
+ bool compareType (CompType, const QString &, const QString &);
+ bool compareLesson (CompType type, int less, const vector<int> &limit, int current);
+
+ /* CompType typecomp,
+ querycomp,
+ badcomp,
+ gradecomp,
+ lessoncomp,
+ datecomp;*/
+
+ //time_t dateitem;
+ //int queryitem,
+ // baditem;
+ //QString typeitem;
+ //grade_t gradeitem;
+ vector<int> lessonitems;
+
+ //vector<int> blockItems,
+ // expireItems;
+
+ private:
+ static vector<QString> userTypes;
+};
+
+#endif // QueryManager_included
diff --git a/kvoctrain/kvoctrain/kvt-core/UsageManager.cpp b/kvoctrain/kvoctrain/kvt-core/UsageManager.cpp
new file mode 100644
index 00000000..7f98665a
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/UsageManager.cpp
@@ -0,0 +1,155 @@
+/***************************************************************************
+
+ manage usage labels
+
+ -----------------------------------------------------------------------
+
+ begin : Fri Mar 31 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "UsageManager.h"
+
+#include <klocale.h>
+
+
+#include <iostream>
+#include <vector>
+using namespace std;
+
+vector<QString> UsageManager::userUsages;
+
+// user usages are strings like this: #1
+
+struct internalRelation_t
+{
+ const char *ident,
+ *context,
+ *shortid,
+ *longId;
+};
+
+#ifndef I18N_NOOP2
+#define I18N_NOOP2(context, str) context, str
+#endif
+
+static internalRelation_t InternalUsageRelations [] =
+{
+ { UL_AM, 0, I18N_NOOP("Am."), I18N_NOOP("Americanism")},
+ { UL_ABBR, 0, I18N_NOOP("abbr."), I18N_NOOP("abbreviation")},
+ { UL_ANAT, 0, I18N_NOOP("anat."), I18N_NOOP("anatomy")},
+ { UL_ASTR, 0, I18N_NOOP("astr."), I18N_NOOP("astronomy")},
+ { UL_BIOL, 0, I18N_NOOP("biol."), I18N_NOOP("biology")},
+ { UL_BS, 0, I18N_NOOP("b.s."), I18N_NOOP("bad sense")},
+ { UL_CONTP, 0, I18N_NOOP("contp."), I18N_NOOP("contemptuously")},
+ { UL_ECCL, 0, I18N_NOOP("eccl."), I18N_NOOP("ecclesiastical")},
+ { UL_FIG, 0, I18N_NOOP("fig."), I18N_NOOP("figuratively")},
+ { UL_GEOL, 0, I18N_NOOP("geol."), I18N_NOOP("geology")},
+ { UL_HIST, 0, I18N_NOOP("hist."), I18N_NOOP("historical")},
+ { UL_ICHT, 0, I18N_NOOP("icht."), I18N_NOOP("ichthyology")},
+ { UL_IFML, 0, I18N_NOOP("ifml."), I18N_NOOP("informal")},
+ { UL_IRONIC, 0, I18N_NOOP("iro."), I18N_NOOP("ironic")},
+ { UL_IRR, 0, I18N_NOOP("irr."), I18N_NOOP("irregular")},
+ { UL_LIT, 0, I18N_NOOP("lit."), I18N_NOOP("literary")},
+ { UL_META, 0, I18N_NOOP("metall."), I18N_NOOP("metallurgy")},
+ { UL_METEO, 0, I18N_NOOP("meteor."), I18N_NOOP("meteorology")},
+ { UL_MIN, 0, I18N_NOOP("min."), I18N_NOOP("mineralogy")},
+ { UL_MOT, 0, I18N_NOOP("mot."), I18N_NOOP("motoring")},
+ { UL_MOUNT, 0, I18N_NOOP("mount."), I18N_NOOP("mountaineering")},
+ { UL_MYT, 0, I18N_NOOP("myth."), I18N_NOOP("mythology")},
+ { UL_NPR, 0, I18N_NOOP2("abbreviation: proper name", "npr."), I18N_NOOP("proper name")},
+ { UL_OPT, 0, I18N_NOOP("opt."), I18N_NOOP("optics")},
+ { UL_ORN, 0, I18N_NOOP("orn."), I18N_NOOP("ornithology")},
+ { UL_OS, 0, I18N_NOOP("o.s."), I18N_NOOP("oneself")},
+ { UL_P, 0, I18N_NOOP("pers."), I18N_NOOP("person")},
+ { UL_PARL, 0, I18N_NOOP("parl."), I18N_NOOP("parliamentary")},
+ { UL_PHARM, 0, I18N_NOOP("pharm."), I18N_NOOP("pharmacy")},
+ { UL_PHLS, 0, I18N_NOOP("phls."), I18N_NOOP("philosophy")},
+ { UL_PHOT, 0, I18N_NOOP("phot."), I18N_NOOP("photography")},
+ { UL_PHYS, 0, I18N_NOOP("phys."), I18N_NOOP("physics")},
+ { UL_PHYSIOL, 0, I18N_NOOP("physiol."), I18N_NOOP("physiology")},
+ { UL_PL, 0, I18N_NOOP("pl."), I18N_NOOP("plural")},
+ { UL_POET, 0, I18N_NOOP("poet."), I18N_NOOP("poetry")},
+ { UL_POL, 0, I18N_NOOP("pol."), I18N_NOOP("politics")},
+ { UL_PROV, 0, I18N_NOOP("prov."), I18N_NOOP("provincialism")},
+ { UL_PSYCH, 0, I18N_NOOP("psych."), I18N_NOOP("psychology")},
+ { UL_RHET, 0, I18N_NOOP("rhet."), I18N_NOOP("rhetoric")},
+ { UL_SURV, 0, I18N_NOOP("surv."), I18N_NOOP("surveying")},
+ { UL_TEL, 0, I18N_NOOP("tel."), I18N_NOOP("telegraphy")},
+ { UL_TELEPH, 0, I18N_NOOP("teleph."), I18N_NOOP("telephony")},
+ { UL_THEA, 0, I18N_NOOP("thea."), I18N_NOOP("theater")},
+ { UL_TYP, 0, I18N_NOOP("typ."), I18N_NOOP("typography")},
+ { UL_UNIV, 0, I18N_NOOP("univ."), I18N_NOOP("university")},
+ { UL_VET, 0, I18N_NOOP("vet."), I18N_NOOP("veterinary medicine")},
+ { UL_ZO, 0, I18N_NOOP("zo."), I18N_NOOP("zoology")},
+//{ UL_, 0, I18N_NOOP(""), I18N_NOOP("")},
+ { 0, 0, 0, 0 } // the end
+};
+
+
+UsageManager::UsageManager ()
+{
+}
+
+
+vector<UsageRelation> UsageManager::getRelation ()
+{
+ vector<UsageRelation> vec;
+ for (int i = 0; i < (int) userUsages.size(); i++) {
+ QString s;
+ s.setNum(i+1);
+ s.insert(0, UL_USER_USAGE);
+ vec.push_back(UsageRelation(s, userUsages[i], userUsages[i]));
+ }
+
+ internalRelation_t *usage = InternalUsageRelations;
+ while (usage->ident != 0) {
+ QString s;
+ if (usage->context == 0)
+ s = i18n(usage->shortid);
+ else
+ s = i18n(usage->context, usage->shortid);
+ vec.push_back(UsageRelation(usage->ident,
+ s,
+ i18n(usage->longId)));
+ usage++;
+ }
+
+ return vec;
+}
+
+
+bool UsageManager::contains (const QString& label, const QString& collection)
+{
+ QString s = collection;
+ int pos;
+ while ((pos = s.find(UL_USAGE_DIV)) >= 0) {
+ if (s.left(pos) == label)
+ return true;
+ s.remove (0, pos+1);
+ }
+
+ return s == label;
+}
+
+
+void UsageManager::setUsageNames (vector<QString> names)
+{
+ userUsages = names;
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/UsageManager.h b/kvoctrain/kvoctrain/kvt-core/UsageManager.h
new file mode 100644
index 00000000..e49a6c85
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/UsageManager.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+
+ manage usage labels
+
+ -----------------------------------------------------------------------
+
+ begin : Sun Dec 19 11:26:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 UsageManager_included
+#define UsageManager_included
+
+#include <vector>
+using namespace std;
+
+#include "kvoctraindoc.h"
+
+class kvoctrainDoc;
+class KConfig;
+class kvoctrainExpr;
+
+// internal usage labels, never change !
+
+#define UL_AM "Am"
+#define UL_ABBR "abbr"
+#define UL_ANAT "anat"
+#define UL_ASTR "astr"
+#define UL_BIOL "biol"
+#define UL_BS "bs"
+#define UL_CONTP "contp"
+#define UL_ECCL "eccl"
+#define UL_FIG "fig"
+#define UL_GEOL "geol"
+#define UL_HIST "hist"
+#define UL_ICHT "icht"
+#define UL_IFML "ifm"
+#define UL_IRONIC "iro"
+#define UL_IRR "irr"
+#define UL_LIT "lit"
+#define UL_META "metal"
+#define UL_METEO "meteo"
+#define UL_MIN "miner"
+#define UL_MOT "mot"
+#define UL_MOUNT "mount"
+#define UL_MYT "myth"
+#define UL_NPR "npr"
+#define UL_OPT "opt"
+#define UL_ORN "orn"
+#define UL_OS "os"
+#define UL_P "p"
+#define UL_PARL "parl"
+#define UL_PHARM "pharm"
+#define UL_PHLS "phls"
+#define UL_PHOT "phot"
+#define UL_PHYS "phys"
+#define UL_PHYSIOL "physio"
+#define UL_PL "pl"
+#define UL_POET "poet"
+#define UL_POL "pol"
+#define UL_PROV "prov"
+#define UL_PSYCH "psych"
+#define UL_RHET "rhet"
+#define UL_SURV "surv"
+#define UL_TEL "telg"
+#define UL_TELEPH "telph"
+#define UL_THEA "thea"
+#define UL_TYP "typo"
+#define UL_UNIV "univ"
+#define UL_VET "vet"
+#define UL_ZO "zoo"
+
+// usage delimiters
+#define UL_USER_USAGE "#" // designates number of user type
+#define UL_USAGE_DIV ":" // divide different labels
+
+struct UsageRelation
+{
+ public:
+
+ UsageRelation (const QString & id, const QString & shorty, const QString & longy)
+ :ident(id), shortId(shorty), longId(longy) {}
+
+ QString identStr() const { return ident; }
+ QString shortStr() const { return shortId; }
+ QString longStr() const { return longId; }
+
+ protected:
+ QString ident,
+ shortId,
+ longId;
+};
+
+
+class UsageManager
+{
+ public:
+
+ UsageManager ();
+
+ static bool contains (const QString& label, const QString& collection);
+ static vector<UsageRelation> getRelation ();
+ static void setUsageNames (vector<QString> names);
+
+ protected:
+
+ private:
+ static vector<QString> userUsages;
+};
+
+#endif // UsageManager_included
diff --git a/kvoctrain/kvoctrain/kvt-core/grammarmanager.cpp b/kvoctrain/kvoctrain/kvt-core/grammarmanager.cpp
new file mode 100644
index 00000000..2c789890
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/grammarmanager.cpp
@@ -0,0 +1,503 @@
+/***************************************************************************
+
+ manage grammar parts (articles, conjugation)
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Nov 27 09:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2004-2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "grammarmanager.h"
+
+#include <klocale.h>
+
+Conjugation::conjug_name_t
+Conjugation::names [] =
+{
+ { CONJ_SIMPLE_PRESENT, I18N_NOOP("Simple Present") },
+ { CONJ_PRESENT_PROGR, I18N_NOOP("Preset Progressive") },
+ { CONJ_PRESENT_PERFECT, I18N_NOOP("Preset Perfect") },
+
+ { CONJ_SIMPLE_PAST, I18N_NOOP("Simple Past") },
+ { CONJ_PAST_PROGR, I18N_NOOP("Past Progressive") },
+ { CONJ_PAST_PARTICIPLE, I18N_NOOP("Past Participle") },
+
+ { CONJ_FUTURE, I18N_NOOP("Future") }
+};
+
+
+vector<QString> Conjugation::userTenses;
+
+
+//================================================================
+
+Comparison::Comparison (
+ const QString &l1,
+ const QString &l2,
+ const QString &l3
+ )
+{
+ setL1 (l1);
+ setL2 (l2);
+ setL3 (l3);
+}
+
+
+bool Comparison::isEmpty() const
+{
+ return ls1.stripWhiteSpace().isEmpty()
+ && ls2.stripWhiteSpace().isEmpty()
+ && ls3.stripWhiteSpace().isEmpty();
+}
+
+
+void Comparison::clear()
+{
+ ls1 = "";
+ ls2 = "";
+ ls3 = "";
+}
+
+
+//=================================================================
+
+
+Article::Article
+ (const QString &fem_def, const QString &fem_indef,
+ const QString &mal_def, const QString &mal_indef,
+ const QString &nat_def, const QString &nat_indef
+ )
+{
+ setFemale (fem_def, fem_indef);
+ setMale (mal_def, mal_indef);
+ setNatural (nat_def, nat_indef);
+}
+
+
+void Article::setFemale
+ (const QString &def, const QString &indef)
+{
+ fem_def = def;
+ fem_indef = indef;
+}
+
+
+void Article::setMale
+ (const QString &def, const QString &indef)
+{
+ mal_def = def;
+ mal_indef = indef;
+}
+
+
+void Article::setNatural
+ (const QString &def, const QString &indef)
+{
+ nat_def = def;
+ nat_indef = indef;
+}
+
+
+void Article::female
+ (QString &def, QString &indef) const
+{
+ def = fem_def;
+ indef = fem_indef;
+}
+
+
+void Article::male
+ (QString &def, QString &indef) const
+{
+ def = mal_def;
+ indef = mal_indef;
+}
+
+
+void Article::natural
+ (QString &def, QString &indef) const
+{
+ def = nat_def;
+ indef = nat_indef;
+}
+
+
+
+//==============================================================
+
+
+int Conjugation::numEntries() const
+{
+ return conjugations.size();
+}
+
+
+vector<TenseRelation> Conjugation::getRelation ()
+{
+ vector<TenseRelation> vec;
+
+ for (int i = 0; i < numInternalNames(); i++) {
+ vec.push_back(TenseRelation(names[i].abbrev,
+ i18n(names[i].name)));
+ }
+
+ for (int i = 0; i < (int) userTenses.size(); i++) {
+ QString s;
+ s.setNum(i+1);
+ s.insert(0, UL_USER_TENSE);
+ vec.push_back(TenseRelation(s, userTenses[i]));
+ }
+
+ return vec;
+}
+
+
+void Conjugation::setTenseNames (vector<QString> names)
+{
+ userTenses = names;
+}
+
+
+QString Conjugation::getName (const QString &abbrev)
+{
+ if (abbrev.length() >= 2 && abbrev[0] == QString(UL_USER_TENSE)) {
+ QString s = abbrev;
+ s.remove(0, 1);
+ int i = s.toInt() - 1;
+
+ if (i < (int) userTenses.size() )
+ return userTenses[i];
+ else
+ return "";
+ }
+ else {
+ for (int i = 0; i < (int) numInternalNames(); i++)
+ if (names[i].abbrev == abbrev) {
+ return i18n(names[i].name);
+ }
+ }
+
+ return "";
+}
+
+
+QString Conjugation::getName (int idx)
+{
+ if (idx < numInternalNames() )
+ return i18n(names[idx].name);
+
+ else if (idx < numTenses() )
+ return userTenses[idx-numInternalNames()];
+
+ else
+ return "";
+}
+
+
+QString Conjugation::getAbbrev (const QString &name)
+{
+ for (int i = 0; i < (int) userTenses.size(); i++)
+ if (userTenses[i] == name) {
+ QString s;
+ s.setNum(i+1);
+ s.insert(0, UL_USER_TENSE);
+ return s;
+ }
+
+ for (int i = 0; i < (int) numInternalNames(); i++)
+ if (names[i].name == name)
+ return names[i].abbrev;
+
+ return "";
+}
+
+
+QString Conjugation::getAbbrev (int idx)
+{
+ if (idx < numInternalNames() )
+ return names[idx].abbrev;
+
+ else if (idx < numTenses() ) {
+ QString s;
+ s.setNum(idx-numInternalNames()+1);
+ s.insert(0, UL_USER_TENSE);
+ return s;
+ }
+
+ else
+ return "";
+}
+
+
+int Conjugation::numInternalNames()
+{
+ return sizeof(names) / sizeof(names[0]);
+}
+
+
+int Conjugation::numTenses()
+{
+ return numInternalNames()+userTenses.size();
+}
+
+
+QString Conjugation::getType (int idx)
+{
+ if (idx >= (int) conjugations.size() )
+ return "";
+
+ return conjugations[idx].type;
+}
+
+
+void Conjugation::setType (int idx, const QString & type)
+{
+ if (idx >= (int) conjugations.size() )
+ return;
+
+ conjugations[idx].type = type;
+}
+
+
+void Conjugation::cleanUp ()
+{
+ for (int i = (int)conjugations.size()-1; i >= 0; i--) {
+ const conjug_t *ctp = &conjugations[i];
+ if ( ctp->pers1_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers2_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_m_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_f_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_n_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers1_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers2_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_m_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_f_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_n_plur.stripWhiteSpace().isEmpty()
+ )
+ conjugations.erase(conjugations.begin() + i);
+ }
+}
+
+
+bool Conjugation::isEmpty (int idx)
+{
+ if (idx < (int) conjugations.size()) {
+ const conjug_t *ctp = &conjugations[idx];
+ return ctp->pers1_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers2_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_m_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_f_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers3_n_sing.stripWhiteSpace().isEmpty()
+ && ctp->pers1_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers2_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_m_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_f_plur.stripWhiteSpace().isEmpty()
+ && ctp->pers3_n_plur.stripWhiteSpace().isEmpty();
+ }
+ return true;
+}
+
+
+#define _GET_CON_(elem, type, default) \
+ for (int i = 0; i < (int) conjugations.size(); i++) \
+ if (conjugations[i].type == type) \
+ return conjugations[i].elem; \
+ return default;
+
+
+bool Conjugation::pers3SingularCommon(const QString &type) const
+{
+ _GET_CON_(s3common, type, false);
+}
+
+
+bool Conjugation::pers3PluralCommon(const QString &type) const
+{
+ _GET_CON_(p3common, type, false);
+}
+
+
+QString Conjugation::pers1Singular
+ (const QString &type) const
+{
+ _GET_CON_(pers1_sing, type, "");
+}
+
+
+QString Conjugation::pers2Singular
+ (const QString &type) const
+{
+ _GET_CON_(pers2_sing, type, "");
+}
+
+
+QString Conjugation::pers3FemaleSingular
+ (const QString &type) const
+{
+ _GET_CON_(pers3_f_sing, type, "");
+}
+
+
+QString Conjugation::pers3MaleSingular
+ (const QString &type) const
+{
+ _GET_CON_(pers3_m_sing, type, "");
+}
+
+
+QString Conjugation::pers3NaturalSingular
+ (const QString &type) const
+{
+ _GET_CON_(pers3_n_sing, type, "");
+}
+
+
+QString Conjugation::pers1Plural
+ (const QString &type) const
+{
+ _GET_CON_(pers1_plur, type, "");
+}
+
+
+QString Conjugation::pers2Plural
+ (const QString &type) const
+{
+ _GET_CON_(pers2_plur, type, "");
+}
+
+
+QString Conjugation::pers3FemalePlural
+ (const QString &type) const
+{
+ _GET_CON_(pers3_f_plur, type, "");
+}
+
+
+QString Conjugation::pers3MalePlural
+ (const QString &type) const
+{
+ _GET_CON_(pers3_m_plur, type, "");
+}
+
+
+QString Conjugation::pers3NaturalPlural
+ (const QString &type) const
+{
+ _GET_CON_(pers3_n_plur, type, "");
+}
+
+
+#undef _GET_CON_
+
+
+#define _SET_CON_(elem, type, str) \
+ for (int i = 0; i < (int) conjugations.size(); i++) \
+ if (conjugations[i].type == type) { \
+ conjugations[i].elem = str; \
+ return; \
+ } \
+ conjug_t ct; \
+ ct.type = type; \
+ ct.elem = str; \
+ conjugations.push_back(ct);
+
+
+void Conjugation::setPers3PluralCommon(const QString &type, bool f)
+{
+ _SET_CON_(p3common, type, f);
+}
+
+
+void Conjugation::setPers3SingularCommon(const QString &type, bool f)
+{
+ _SET_CON_(s3common, type, f);
+}
+
+
+void Conjugation::setPers1Singular
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers1_sing, type, str);
+}
+
+
+void Conjugation::setPers2Singular
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers2_sing, type, str);
+}
+
+
+void Conjugation::setPers3FemaleSingular
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_f_sing, type, str);
+}
+
+
+void Conjugation::setPers3MaleSingular
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_m_sing, type, str);
+}
+
+
+void Conjugation::setPers3NaturalSingular
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_n_sing, type, str);
+}
+
+
+void Conjugation::setPers1Plural
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers1_plur, type, str);
+}
+
+
+void Conjugation::setPers2Plural
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers2_plur, type, str);
+}
+
+
+void Conjugation::setPers3FemalePlural
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_f_plur, type, str);
+}
+
+
+void Conjugation::setPers3MalePlural
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_m_plur, type, str);
+}
+
+
+void Conjugation::setPers3NaturalPlural
+ (const QString &type, const QString &str)
+{
+ _SET_CON_(pers3_n_plur, type, str);
+}
+
+#undef _SET_CON_
+
diff --git a/kvoctrain/kvoctrain/kvt-core/grammarmanager.h b/kvoctrain/kvoctrain/kvt-core/grammarmanager.h
new file mode 100644
index 00000000..1b9cfe76
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/grammarmanager.h
@@ -0,0 +1,215 @@
+/***************************************************************************
+
+ manage grammer parts (articles, conjugation)
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Nov 27 09:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 grammarmanager_included
+#define grammarmanager_included
+
+#include <qstring.h>
+
+#include <vector>
+using namespace std;
+
+#define CONJ_SIMPLE_PRESENT "PrSi" // I live at home what you frequently do
+#define CONJ_PRESENT_PROGR "PrPr" // I am working what you currently are doing
+#define CONJ_PRESENT_PERFECT "PrPe" // I have cleaned tell, #that# something has happened
+
+#define CONJ_SIMPLE_PAST "PaSi" // the train left 2 min ago when did it happen
+#define CONJ_PAST_PROGR "PaPr" // it was raining what happen at a given time in the past
+#define CONJ_PAST_PARTICIPLE "PaPa" // I cleaned tell, #that# it happened
+
+#define CONJ_FUTURE "FuSi"
+
+#define CONJ_PREFIX "--" // definition of prefixes (I, you, ..)
+
+#define UL_USER_TENSE "#" // designates number of user tense
+
+class Article
+{
+
+public:
+
+ Article() {}
+
+ Article (
+ const QString &fem_def, const QString &fem_indef,
+ const QString &mal_def, const QString &mal_indef,
+ const QString &nat_def, const QString &nat_indef
+ );
+
+ void setFemale (const QString &def, const QString &indef);
+ void setMale (const QString &def, const QString &indef);
+ void setNatural (const QString &def, const QString &indef);
+
+ void female (QString &def, QString &indef) const;
+ void male (QString &def, QString &indef) const;
+ void natural (QString &def, QString &indef) const;
+
+protected:
+
+ QString fem_def, fem_indef,
+ mal_def, mal_indef,
+ nat_def, nat_indef;
+};
+
+
+class Comparison
+{
+
+public:
+
+ Comparison() {}
+
+ Comparison (
+ const QString &l1,
+ const QString &l2,
+ const QString &l3
+ );
+
+ void setL1 (const QString &s) { ls1 = s; }
+ void setL2 (const QString &s) { ls2 = s; }
+ void setL3 (const QString &s) { ls3 = s; }
+
+ QString l1 () const { return ls1; }
+ QString l2 () const { return ls2; }
+ QString l3 () const { return ls3; }
+
+ bool isEmpty() const;
+ void clear();
+
+protected:
+
+ QString ls1, ls2, ls3;
+};
+
+
+class TenseRelation
+{
+ public:
+
+ TenseRelation (const QString & _short, const QString & _long)
+ : shortId (_short), longId(_long) {}
+
+ inline QString shortStr() const { return shortId; }
+ inline QString longStr() const { return longId; }
+
+ protected:
+
+ QString shortId, longId;
+};
+
+
+class Conjugation
+{
+
+public:
+
+ Conjugation () {}
+
+ int numEntries() const;
+
+ static vector<TenseRelation> getRelation ();
+ static void setTenseNames (vector<QString> names);
+
+ static QString getName (const QString &abbrev);
+ static QString getName (int index);
+ static QString getAbbrev (const QString &name);
+ static QString getAbbrev (int index);
+ static int numInternalNames();
+ static int numTenses();
+
+ QString getType (int index);
+ void setType (int index, const QString & type);
+ void cleanUp();
+ bool isEmpty (int idx);
+
+ QString pers1Singular(const QString &type) const;
+ QString pers2Singular(const QString &type) const;
+ bool pers3SingularCommon(const QString &type) const;
+ QString pers3FemaleSingular(const QString &type) const;
+ QString pers3MaleSingular(const QString &type) const;
+ QString pers3NaturalSingular(const QString &type) const;
+
+ QString pers1Plural(const QString &type) const;
+ QString pers2Plural(const QString &type) const;
+ bool pers3PluralCommon(const QString &type) const;
+ QString pers3FemalePlural(const QString &type) const;
+ QString pers3MalePlural(const QString &type) const;
+ QString pers3NaturalPlural(const QString &type) const;
+
+ void setPers1Singular(const QString &type, const QString &str);
+ void setPers2Singular(const QString &type, const QString &str);
+ void setPers3SingularCommon(const QString &type, bool f);
+ void setPers3FemaleSingular(const QString &type, const QString &str);
+ void setPers3MaleSingular(const QString &type, const QString &str);
+ void setPers3NaturalSingular(const QString &type, const QString &str);
+
+ void setPers1Plural(const QString &type, const QString &str);
+ void setPers2Plural(const QString &type, const QString &str);
+ void setPers3PluralCommon(const QString &type, bool f);
+ void setPers3FemalePlural(const QString &type, const QString &str);
+ void setPers3MalePlural(const QString &type, const QString &str);
+ void setPers3NaturalPlural(const QString &type, const QString &str);
+
+private:
+
+ struct conjug_t {
+
+ conjug_t() {
+ p3common = false;
+ s3common = false;
+ }
+
+ QString type;
+ bool p3common,
+ s3common;
+ QString pers1_sing,
+ pers2_sing,
+ pers3_m_sing,
+ pers3_f_sing,
+ pers3_n_sing,
+ pers1_plur,
+ pers2_plur,
+ pers3_m_plur,
+ pers3_f_plur,
+ pers3_n_plur;
+ };
+
+ struct conjug_name_t {
+ const char *abbrev;
+ const char *name;
+ };
+
+protected:
+
+ vector<conjug_t> conjugations;
+
+ static conjug_name_t names [];
+ static vector<QString> userTenses;
+};
+
+
+#endif // grammarmanager_included
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_csv.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_csv.cpp
new file mode 100644
index 00000000..851e0ea9
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_csv.cpp
@@ -0,0 +1,243 @@
+/***************************************************************************
+
+ maintain a document in text format
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Sep 06 11:00:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <klocale.h>
+
+#include "kvoctrain.h"
+
+#include <qtextcodec.h>
+
+#include <vector>
+using namespace std;
+
+bool kvoctrainDoc::saveTypeNameCsv (QTextStream &)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::loadTypeNameCsv (QTextStream &)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::saveLessonCsv (QTextStream &)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::loadLessonCsv (QTextStream &)
+{
+ return true;
+}
+
+bool kvoctrainDoc::saveToCsv (QTextStream& os, QString &)
+{
+ QString separator = Prefs::separator();
+
+ saveTypeNameCsv (os);
+ saveLessonCsv (os);
+
+ int ent_no = 0;
+ int ent_percent = (int) vocabulary.size () / 100;
+ float f_ent_percent = (int) vocabulary.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ os << i18n("! Title:") << separator << getTitle() << "\n";
+ os << i18n("! Author:") << separator << getAuthor() << "\n";
+
+ vector <int> csv_order = kvoctrainApp::getCsvOrder(this);
+
+ vector<kvoctrainExpr>::const_iterator first = vocabulary.begin ();
+ QString exp;
+
+ os.setCodec(QTextCodec::codecForName("UTF-8"));
+ while (first != vocabulary.end ()) {
+
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, ent_no / (int) f_ent_percent);
+
+ exp = "";
+ // now concat columns according to paste-order
+ bool sep = false;
+ for (int i = 0; i < (int) csv_order.size(); i++) {
+ if (!sep)
+ sep = true;
+ else
+ exp += separator;
+
+ if (csv_order[i] >= 0) {
+ if (csv_order[i] == 0)
+ exp += (*first).getOriginal();
+ else
+ exp += (*first).getTranslation(csv_order[i]);
+ }
+ }
+
+ if (!exp.isEmpty())
+ os << exp << "\n";
+
+ first++;
+ }
+
+ setModified (false);
+ return os.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::loadFromCsv (QTextStream& is)
+{
+ QString separator = Prefs::separator();
+ QStringList lang_order = Prefs::pasteOrder();
+
+ langs.clear();
+ vocabulary.clear();
+ loadTypeNameCsv (is);
+ loadLessonCsv (is);
+
+ // autodetect utf8
+ // FIXME: provide choice for Latinx?
+ is.setCodec(QTextCodec::codecForName("ISO 8859-1"));
+ is.setEncoding(QTextStream::Latin1);
+
+ int size = is.device()->size ();
+ int ln = size / 20 / 100; // assume each line about 20 chars
+ float f_ent_percent = size / 100.0;
+ emit progressChanged (this, 0);
+
+ bool utf8_mode = false;
+ int lang_num = 0;
+ for (int l = 0; !is.eof(); l++) {
+ QString s = is.readLine();
+
+ // autodetect utf8
+ if (!utf8_mode) {
+ for (int i = 0; !utf8_mode && i < (int) s.length(); ++i) {
+ ushort trigger = s[i].unicode();
+ if (trigger >= 0x80) {
+ int remain = s.length() - i;
+ if ((trigger & 0xE0) == 0xC0){ // 110x xxxx
+ if ( (remain > 1)
+ && (s[i+1].unicode() & 0xC0) == 0x80)
+ utf8_mode = true;
+ }
+ else if ((trigger & 0xF0) == 0xE0) { // 1110 xxxx
+ if ( remain > 2
+ && s[i+1].unicode() & 0xC0 == 0x80
+ && s[i+2].unicode() & 0xC0 == 0x80)
+ utf8_mode = true;
+ }
+ else if ((trigger & 0xF8) == 0xF0) { // 1111 0xxx
+ if ( remain > 3
+ && s[i+1].unicode() & 0xC0 == 0x80
+ && s[i+2].unicode() & 0xC0 == 0x80
+ && s[i+3].unicode() & 0xC0 == 0x80)
+ utf8_mode = true;
+ }
+ else if ((trigger & 0xFC) == 0xF8) { // 1111 10xx
+ if ( remain > 4
+ && s[i+1].unicode() & 0xC0 == 0x80
+ && s[i+2].unicode() & 0xC0 == 0x80
+ && s[i+3].unicode() & 0xC0 == 0x80
+ && s[i+4].unicode() & 0xC0 == 0x80)
+ utf8_mode = true;
+ }
+ else if ((trigger & 0xFE) == 0xFC) { // 1111 110x
+ if ( remain > 5
+ && s[i+1].unicode() & 0xC0 == 0x80
+ && s[i+2].unicode() & 0xC0 == 0x80
+ && s[i+3].unicode() & 0xC0 == 0x80
+ && s[i+4].unicode() & 0xC0 == 0x80
+ && s[i+5].unicode() & 0xC0 == 0x80)
+ utf8_mode = true;
+ }
+ }
+ }
+
+ if (utf8_mode) {
+ is.setCodec(QTextCodec::codecForName("UTF-8"));
+ is.setEncoding(QTextStream::UnicodeUTF8);
+ s = QString::fromUtf8(s.ascii());
+ }
+
+ }
+
+ ln--;
+ if (ln <= 0) {
+ ln = size / 20 / 100; // assume each line about 20 chars
+ emit progressChanged(this, is.device()->at() / (int) f_ent_percent);
+ }
+
+ // similar in kva_clip.cpp::slotEditPaste()
+
+ if (!s.stripWhiteSpace().isEmpty()) {
+ kvoctrainExpr bucket (s, separator);
+ kvoctrainExpr expr;
+ // now move columns according to paste-order
+ for (int i = 0; i < bucket.numTranslations()+1; i++) {
+ lang_num = QMAX (lang_num, bucket.numTranslations()+1);
+ if (i == 0)
+ expr.setOriginal(bucket.getOriginal());
+ else {
+ QString ts = bucket.getTranslation(i);
+ expr.setTranslation(i, ts);
+ }
+ }
+ appendEntry (&expr);
+ }
+ }
+
+ for (int j = 0; j < lang_num; j++) {
+ if (j < (int) lang_order.count() ) {
+ langs.push_back((lang_order)[j]);
+ }
+ else {
+ if (j == 0)
+ langs.push_back("org");
+ else {
+ QString s;
+ s.setNum(j);
+ s.insert(0, "trans");
+ langs.push_back(s);
+ }
+ }
+ }
+ setModified (false);
+ return is.device()->status() == IO_Ok;
+}
+
+
+void kvoctrainDoc::errorCsv (int /*line*/, const QString &text )
+{
+ unknown_elem = true;
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Error in csv file"));
+ QString msg = text;
+ KMessageBox::error( 0, msg, s);
+ QApplication::restoreOverrideCursor();
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_lex.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_lex.cpp
new file mode 100644
index 00000000..feb160cf
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_lex.cpp
@@ -0,0 +1,395 @@
+/***************************************************************************
+
+ maintain a *.lex document (vocabulary trainer for Win)
+
+ -----------------------------------------------------------------------
+
+ begin : Sat Sep 04 11:00:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "kvoctraindoc.h"
+
+
+#include <vector>
+using namespace std;
+
+#define LEX_MAX_ATTR 20
+#define LEX_MAX_LESSON 9
+
+/* sample for a lex-file
+
+Vocabulary Trainer V5.0
+LEX|Deutsch|Englisch| 259 260 1 1 1 0 0 268 0 1 1 1 1 145 6 23 1999 255 1 1 653 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 1 1 0 0 |
+-11 700
+System
+Energie- und Automatisierungstechnik. V. Manuela Lutz. Danke.
+1 1 der die das|he she it|
+1 1 eine einer eines einen einem|has have had is be|
+1 1 er sie es|his him her its|
+1 1 wir ihr euch|in to into on at too|
+1 1 in an auf bei|the a an|
+1 1 zu um zur zum|out by with of off|
+1 1 ist sind seid|something someone some|
+1 1 dies dieser dieses|under below|
+1 1 ||
+1 1 ||
+der die das ein eine einer eines einen einem|the a an|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+Sachgebiete|
+|
+|
+|
+|
+|
+|
+|
+|
+32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
+1 0 255 255 255 255 255 255 0 0 1 Abbildung||||mapping||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+1 0 255 255 255 255 255 255 0 0 1 Abblendkappe||||anti-dazzle device||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+...
+*/
+
+
+static QString extract (QString &line)
+{
+ QString ret;
+ int lim = line.find ("|");
+ if (lim < 0) {
+ ret = line;
+ line = "";
+ }
+ else {
+ ret = line.left(lim);
+ line.remove (0, lim+1);
+ }
+
+ return ret;
+}
+
+
+bool kvoctrainDoc::saveTypeNameLex (QTextStream &os)
+{
+ int i;
+ for (i = 0; i < (int) type_descr.size() && i < LEX_MAX_ATTR; i++)
+ os << getTypeName(i) << "|\n";
+
+ while (i++ < LEX_MAX_ATTR)
+ os << "|\n";
+
+ return os.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::loadTypeNameLex (QTextStream &is)
+{
+ QString s;
+ QString attr;
+
+ type_descr.clear();
+
+ for (int i = 0; i < LEX_MAX_ATTR; i++) {
+ s = is.readLine();
+ attr = extract (s);
+/*
+ if (attr.stripWhiteSpace().isEmpty()) {
+ attr.setNum (i+1);
+ attr.insert (0, "#");
+ }
+*/
+ type_descr.push_back (attr);
+ }
+
+ return is.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::saveLessonLex (QTextStream &os)
+{
+ int i;
+ for (i = 0; i < (int) lesson_descr.size() && i < LEX_MAX_LESSON; i++)
+ os << lesson_descr[i] << "|\n";
+
+ while (i++ < LEX_MAX_LESSON)
+ os << "|\n";
+
+ return os.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::loadLessonLex (QTextStream &is)
+{
+ QString s;
+ QString lesson;
+
+ lesson_descr.clear();
+
+ for (int i = 0; i < LEX_MAX_LESSON; i++) {
+ s = is.readLine();
+ lesson = extract (s);
+ if (lesson.stripWhiteSpace().isEmpty()) {
+ lesson = "#" + QString::number(i+1);
+ }
+ lesson_descr.push_back (lesson);
+ }
+
+ return is.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::saveToLex (QTextStream& os, QString & /*title*/)
+{
+ os << LEX_IDENT_50 "\n";
+ os << "LEX|" << getOriginalIdent() << "|" << getIdent(1) << "|"
+ << "259 260 1 1 1 0 0 268 0 1 1 1 1 ";
+ os << (int) vocabulary.size();
+ os << " 9 5 1999 255 1 1 653 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 1 1 0 0 |#3" << "\n";
+ os << "-11 700 0 0 0 0 0 0 0 0 0 0" << "\n";
+ os << "System\n";
+ os << getTitle() << "\n";
+ os << "1 1 der die das|he she it|" << "\n";
+ os << "1 1 eine einer eines einen einem|has have had is be|" << "\n";
+ os << "1 1 er sie es|his him her its|" << "\n";
+ os << "1 1 wir ihr euch|in to into on at too|" << "\n";
+ os << "1 1 in an auf bei|the a an|" << "\n";
+ os << "1 1 zu um zur zum|out by with of off|" << "\n";
+ os << "1 1 ist sind seid|something someone some|" << "\n";
+ os << "1 1 dies dieser dieses|under below|" << "\n";
+ os << "1 1 ||" << "\n";
+ os << "1 1 ||" << "\n";
+ os << "der die das ein eine einer eines einen einem|the a an|" << "\n";
+
+ if (!saveTypeNameLex (os))
+ return false;
+
+ if (!saveLessonLex (os))
+ return false;
+
+ os << "32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32" << "\n";
+
+ int ent_no = 0;
+ int ent_percent = (int) vocabulary.size () / 100;
+ float f_ent_percent = (int) vocabulary.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ vector<kvoctrainExpr>::const_iterator first = vocabulary.begin ();
+ while (first != vocabulary.end ()) {
+
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, int(ent_no / f_ent_percent));
+
+ os << "0" // type
+ << " " << "255 255 255 255 255 255 255"
+ << " " << QMIN (2, (*first).getGrade(false))
+ << " " << QMIN (2, (*first).getGrade(true))
+ << " " << (*first).getLesson()
+ << " " << (*first).getOriginal()
+ << " " << "||||" // synonyms
+ << (*first).getTranslation(1)
+ << "||||" // synonyms
+ << "||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
+ << "\n";
+
+ first++;
+ }
+
+ setModified (false);
+ return os.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::loadFromLex (QTextStream& is)
+{
+
+ langs.clear();
+ vocabulary.clear();
+ QString version,
+ info1,
+ s_dummy,
+ title,
+ f_keys,
+ ident,
+ orgID,
+ transID;
+
+ int i_dummy,
+ type,
+ f_grade,
+ t_grade,
+ lesson;
+
+ int lines = 10000000;
+
+ version = is.readLine();
+ info1 = is.readLine();
+ ident = extract (info1);
+
+ orgID = extract (info1);
+ if (orgID.isEmpty())
+ orgID = "original";
+
+ transID = extract (info1);
+ if (transID.isEmpty())
+ transID = "translation";
+
+ if (ident != "LEX" || version != LEX_IDENT_50) {
+ errorLex (1, "invalid file format");
+ return false;
+ }
+
+ // first two chars usually give language code:
+ // english ==> en
+ // Deutsch ==> de
+ // italano ==> it
+
+ langs.push_back (orgID.left(2).lower());
+ langs.push_back (transID.left(2).lower());
+
+ QTextStream params (info1, IO_ReadOnly);
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> i_dummy;
+ params >> lines;
+
+ s_dummy = is.readLine(); // Font
+ s_dummy = is.readLine(); // Font
+ title = is.readLine();
+ setTitle (title);
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+ s_dummy = is.readLine();
+
+ if (!loadTypeNameLex (is))
+ return false;
+
+ if (!loadLessonLex (is))
+ return false;
+
+ f_keys = is.readLine();
+
+ int ent_percent = (int) lines / 100;
+ float f_ent_percent = (int) lines / 100.0;
+ emit progressChanged(this, 0);
+
+ for (int i = 0; !is.eof() && i < lines; i++) {
+ if (ent_percent != 0 && (i % ent_percent) == 0 ) {
+ emit progressChanged(this, int(i / f_ent_percent));
+ }
+
+ is >> type;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> i_dummy;
+ is >> t_grade;
+ is >> f_grade;
+ is >> lesson;
+
+ QString line = is.readLine();
+ QString s;
+
+ QString original = extract (line);
+ for (int i = 0; i < 3; i++) {
+ s = extract (line);
+ if (!s.isEmpty())
+ original += ", " +s;
+ }
+
+ QString translation = extract (line);
+ for (int i = 0; i < 3; i++) {
+ s = extract (line);
+ if (!s.isEmpty())
+ translation += ", " +s;
+ }
+
+/* ignore rest
+ >> "||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
+ >> "\n";
+*/
+ kvoctrainExpr kve (original);
+ kve.setGrade (1, t_grade, false);
+ kve.setGrade (1, f_grade, true);
+ kve.setLesson (lesson);
+ kve.addTranslation (translation);
+
+// FIXME: convert attribute to word type ?
+
+ vocabulary.push_back(kve);
+
+ }
+
+ setModified (false);
+ return is.device()->status() == IO_Ok;
+}
+
+
+void kvoctrainDoc::errorLex (int /*line*/, const QString &text )
+{
+ unknown_elem = true;
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Error in lex file"));
+ QString msg = text;
+ KMessageBox::error(0, msg, s);
+ QApplication::restoreOverrideCursor();
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml1.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml1.cpp
new file mode 100644
index 00000000..4aea5283
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml1.cpp
@@ -0,0 +1,888 @@
+/***************************************************************************
+
+ read big body of a kvtml document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "QueryManager.h"
+#include "UsageManager.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+bool kvoctrainDoc::extract_T_DESCR_attr (XmlReader &xml,
+ XmlElement &elem, int &no)
+{
+ no = 0;
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+ if ((*first).name () == KV_LESS_NO)
+ no = (*first).intValue();
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "descr", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_T_GROUP_attr (XmlReader &xml,
+ XmlElement &elem)
+{
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+/*
+ if ((*first).name () == KV_SIZEHINT)
+ width = (*first).intValue();
+ else */ {
+ if (!unknownAttribute(xml.lineNumber(), "type", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::loadTypeNameKvtMl (XmlElement elem, XmlReader& xml)
+{
+ bool endOfGroup = false;
+ QString s;
+ type_descr.clear();
+
+ if (!extract_T_GROUP_attr (xml, elem))
+ return false;
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_TYPE_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TYPE_GRP));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+ else if (elem.tag () == KV_TYPE_DESC && !elem.isEndTag() ) {
+ int no;
+ if (!extract_T_DESCR_attr (xml, elem, no))
+ return false;
+
+ if (!xml.readElement (elem)) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ s = xml.getText();
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ else if (elem.tag() != KV_TYPE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TYPE_DESC));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != KV_TYPE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TYPE_DESC));
+ return false;
+ }
+
+ s = "";
+ }
+ type_descr.push_back (s);
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::loadTenseNameKvtMl (XmlElement elem, XmlReader& xml)
+{
+ bool endOfGroup = false;
+ QString s;
+ tense_descr.clear();
+
+ if (!extract_T_GROUP_attr (xml, elem))
+ return false;
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_TENSE_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TENSE_GRP));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+ else if (elem.tag () == KV_TENSE_DESC && !elem.isEndTag() ) {
+ int no;
+ if (!extract_T_DESCR_attr (xml, elem, no))
+ return false;
+
+ if (!xml.readElement (elem)) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ s = xml.getText();
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ else if (elem.tag() != KV_TENSE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TENSE_DESC));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != KV_TENSE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TENSE_DESC));
+ return false;
+ }
+
+ s = "";
+ }
+ tense_descr.push_back (s);
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::loadUsageNameKvtMl (XmlElement elem, XmlReader& xml)
+{
+ bool endOfGroup = false;
+ QString s;
+ usage_descr.clear();
+
+ if (!extract_T_GROUP_attr (xml, elem))
+ return false;
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_USAGE_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_USAGE_GRP));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+ else if (elem.tag () == KV_USAGE_DESC && !elem.isEndTag() ) {
+ int no;
+ if (!extract_T_DESCR_attr (xml, elem, no))
+ return false;
+
+ if (!xml.readElement (elem)) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ s = xml.getText();
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ else if (elem.tag() != KV_USAGE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_USAGE_DESC));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != KV_USAGE_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_USAGE_DESC));
+ return false;
+ }
+
+ s = "";
+ }
+ usage_descr.push_back (s);
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_O_T_attr (
+ XmlReader &xml,
+ XmlElement &elem,
+ QString &lang,
+ grade_t &grade, grade_t &rev_grade,
+ int &count, int &rev_count,
+ time_t &date, time_t &rev_date,
+ QString &remark,
+ int &bcount, int &rev_bcount,
+ QString &query_id,
+ QString &pronunce,
+ int &width,
+ QString &type,
+ QString &faux_ami_f,
+ QString &faux_ami_t,
+ QString &synonym,
+ QString &example,
+ QString &antonym,
+ QString &usage,
+ QString &paraphrase)
+{
+ grade = KV_NORM_GRADE;
+ rev_grade = KV_NORM_GRADE;
+ count = 0;
+ rev_count = 0;
+ bcount = 0;
+ rev_bcount = 0;
+ date = 0;
+ rev_date = 0;
+ remark = "";
+ lang = "";
+ query_id = "";
+ pronunce = "";
+ faux_ami_t = "";
+ faux_ami_f = "";
+ synonym = "";
+ example = "";
+ usage = "";
+ paraphrase = "";
+ antonym = "";
+ width = -1;
+//type = exprtype
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ int pos;
+ while (first != elem.attributes ().end ()) {
+
+ if ((*first).name () == KV_LANG)
+ lang = (*first).stringValue();
+
+ else if ((*first).name () == KV_SIZEHINT)
+ width = (*first).intValue();
+
+ else if ((*first).name () == KV_CHARSET) {
+ }
+
+ else if ((*first).name () == KV_GRADE) {
+ QString s = (*first).stringValue();
+
+ if ((pos = s.find(';')) >= 1) {
+ grade = s.left(pos).toInt();
+ rev_grade = s.mid(pos+1, s.length()).toInt();
+ }
+ else
+ grade = s.toInt();
+ }
+
+ else if ((*first).name () == KV_COUNT) {
+ QString s = (*first).stringValue();
+ if ((pos = s.find(';')) >= 1) {
+ count = s.left(pos).toInt();
+ rev_count = s.mid(pos+1, s.length()).toInt();
+ }
+ else
+ count = s.toInt();
+ }
+
+ else if ((*first).name () == KV_BAD) {
+ QString s = (*first).stringValue();
+ if ((pos = s.find(';')) >= 1) {
+ bcount = s.left(pos).toInt();
+ rev_bcount = s.mid(pos+1, s.length()).toInt();
+ } else
+ bcount = s.toInt();
+ }
+
+ else if ((*first).name () == KV_DATE) {
+ QString s = (*first).stringValue();
+ if ((pos = s.find(';')) >= 1) {
+ date = s.left(pos).toInt();
+ rev_date = s.mid(pos+1, s.length()).toInt();
+ }
+ else {
+ date = s.toInt();
+ }
+ }
+
+ else if ((*first).name () == KV_DATE2) {
+ QString s = (*first).stringValue();
+ if ((pos = s.find(';')) >= 1) {
+ date = decompressDate (s.left(pos));
+ rev_date = decompressDate (s.mid(pos+1, s.length()));
+ }
+ else {
+ date = decompressDate (s);
+ }
+ }
+
+ else if ((*first).name () == KV_REMARK) {
+ remark = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_FAUX_AMI_F) {
+ faux_ami_f = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_FAUX_AMI_T) {
+ faux_ami_t = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_SYNONYM) {
+ synonym = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_EXAMPLE) {
+ example = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_USAGE) {
+ usage = (*first).stringValue();
+
+ if (usage.length() != 0 && usage.left(1) == UL_USER_USAGE) {
+ int num = QMIN(usage.mid (1, 40).toInt(), 1000); // paranioa check
+ if( num > (int) usage_descr.size() ) { // description missing ?
+ QString s;
+ for (int i = usage_descr.size(); i < num; i++) {
+ s.setNum (i+1);
+ s.insert (0, "#"); // invent descr according to number
+ usage_descr.push_back (s);
+ }
+ }
+ }
+ }
+
+ else if ((*first).name () == KV_PARAPHRASE) {
+ paraphrase = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_ANTONYM) {
+ antonym = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_EXPRTYPE) {
+ type = (*first).stringValue();
+ if (type == "1")
+ type = QM_VERB;
+ else if (type == "2") // convert from pre-0.5 versions
+ type = QM_NOUN;
+ else if (type == "3")
+ type = QM_NAME;
+
+ if (type.length() != 0 && type.left(1) == QM_USER_TYPE) {
+ int num = QMIN(type.mid (1, 40).toInt(), 1000); // paranoia check
+ if( num > (int) type_descr.size() ) { // description missing ?
+ QString s;
+ for (int i = type_descr.size(); i < num; i++) {
+ s.setNum (i+1);
+ s.insert (0, "#"); // invent descr according to number
+ type_descr.push_back (s);
+ }
+ }
+ }
+ }
+
+ else if ((*first).name () == KV_PRONUNCE) {
+ pronunce = (*first).stringValue();
+ }
+
+ else if ((*first).name () == KV_QUERY) {
+ query_id = (*first).stringValue();
+ }
+
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "o> or <t", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_KVT_E_attr (
+ XmlReader& xml,
+ XmlElement &elem,
+ int &lesson,
+ bool &sel,
+ bool &active,
+ QString &type)
+{
+ lesson = 0;
+ sel = false;
+ active = true;
+ type = "";
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+ if ((*first).name () == KV_LESS_MEMBER)
+ lesson = (*first).intValue();
+ else if ((*first).name () == KV_SELECTED)
+ sel = (*first).intValue() != 0;
+ else if ((*first).name () == KV_INACTIVE)
+ active = !(*first).intValue() != 0;
+ else if ((*first).name () == KV_EXPRTYPE) {
+ type = (*first).stringValue();
+ if (type == "1")
+ type = QM_VERB;
+ else if (type == "2") // convert from pre-0.5 versions
+ type = QM_NOUN;
+ else if (type == "3")
+ type = QM_NAME;
+
+ if (type.length() != 0 && type.left(1) == QM_USER_TYPE) {
+ int num = QMIN(type.mid (1, 40).toInt(), 1000); // paranoia check
+ if( num > (int) type_descr.size() ) { // description missing ?
+ QString s;
+ for (int i = type_descr.size(); i < num; i++) {
+ s.setNum (i+1);
+ s.insert (0, "#"); // invent descr according to number
+ type_descr.push_back (s);
+ }
+ }
+ }
+ }
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "e", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::loadComparison (Comparison &comp, XmlElement elem,
+ XmlReader &xml)
+/*
+ <comparison>
+ <l1>good</l1>
+ <l2>better</l2>
+ <l3>best</l3>
+ </comparison>
+*/
+{
+ bool endOfGroup = false;
+ QString s;
+ comp.clear();
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_COMPARISON_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+
+ else if (elem.tag () == KV_COMP_L1 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_COMP_L1, xml, elem, s))
+ return false;
+ comp.setL1(s);
+ }
+
+ else if (elem.tag () == KV_COMP_L2 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_COMP_L2, xml, elem, s))
+ return false;
+ comp.setL2(s);
+ }
+
+ else if (elem.tag () == KV_COMP_L3 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_COMP_L3, xml, elem, s))
+ return false;
+ comp.setL3(s);
+ }
+
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::loadMultipleChoice (MultipleChoice &mc, XmlElement elem,
+ XmlReader &xml)
+/*
+ <multiplechoice>
+ <mc1>good</mc1>
+ <mc2>better</mc2>
+ <mc3>best</mc3>
+ <mc4>best 2</mc4>
+ <mc5>best 3</mc5>
+ </multiplechoice>
+*/
+
+{
+ bool endOfGroup = false;
+ QString s;
+ mc.clear();
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_MULTIPLECHOICE_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+
+ else if (elem.tag () == KV_MC_1 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_MC_1, xml, elem, s))
+ return false;
+ mc.setMC1(s);
+ }
+
+ else if (elem.tag () == KV_MC_2 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_MC_2, xml, elem, s))
+ return false;
+ mc.setMC2(s);
+ }
+
+ else if (elem.tag () == KV_MC_3 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_MC_3, xml, elem, s))
+ return false;
+ mc.setMC3(s);
+ }
+
+ else if (elem.tag () == KV_MC_4 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_MC_4, xml, elem, s))
+ return false;
+ mc.setMC4(s);
+ }
+
+ else if (elem.tag () == KV_MC_5 && !elem.isEndTag() ) {
+ if (!extract_simple_tag (KV_MC_5, xml, elem, s))
+ return false;
+ mc.setMC5(s);
+ }
+
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ mc.normalize();
+ return true;
+}
+
+
+bool kvoctrainDoc::parseBody_kvtml (XmlElement elem, XmlReader& xml)
+{
+ bool endOfBody = false;
+ bool lessgroup = false;
+ bool optgroup = false;
+ bool attrgroup = false;
+ bool tensegroup = false;
+ bool usagegroup = false;
+ bool articlegroup = false;
+ bool conjuggroup = false;
+
+ int ent_no = 0;
+ int ent_percent = (int) lines / 100;
+ float f_ent_percent = (int) lines / 100.0;
+ if (lines != 0)
+ emit progressChanged(this, 0);
+
+ do {
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag () == KV_DOCTYPE) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfBody = true;
+ }
+
+ else if (elem.tag () == KV_LESS_GRP && !elem.isEndTag() ) {
+ if (lessgroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ lessgroup = true;
+ if (!loadLessonKvtMl (elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_ARTICLE_GRP && !elem.isEndTag() ) {
+ if (articlegroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ articlegroup = true;
+ if (!loadArticleKvtMl (elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_CONJUG_GRP && !elem.isEndTag() ) {
+ if (conjuggroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ conjuggroup = true;
+ if (!loadConjugKvtMl (conjugations, KV_CON_ENTRY, elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_OPTION_GRP && !elem.isEndTag() ) {
+ if (optgroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ optgroup = true;
+ if (!loadOptionsKvtMl (elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_TYPE_GRP && !elem.isEndTag() ) {
+ if (attrgroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ attrgroup = true;
+ if (!loadTypeNameKvtMl (elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_TENSE_GRP && !elem.isEndTag() ) {
+ if (tensegroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ tensegroup = true;
+ if (!loadTenseNameKvtMl (elem, xml))
+ return false;
+// Conjugation::setTenseNames(tense_descr);
+ }
+
+ else if (elem.tag () == KV_USAGE_GRP && !elem.isEndTag() ) {
+ if (usagegroup) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ usagegroup = true;
+ if (!loadUsageNameKvtMl (elem, xml))
+ return false;
+ }
+
+ else if (elem.tag () == KV_EXPR && !elem.isEndTag() ) {
+ // found expression <e>
+
+ if (lines != 0) {
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, int(ent_no / f_ent_percent));
+ }
+ if (!parseBody_e (elem, xml)) return false;
+ }
+
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag());
+ return false;
+ }
+ }
+
+ } while (! endOfBody);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::unknownAttribute (int line, const QString &name,
+ const QString &attr )
+{
+ if (unknown_attr) // show dialog only once
+ return true; // proceed
+
+ unknown_attr = true;
+
+ QString ln = i18n("File:\t%1\nLine:\t%2\n").arg(URL().path()).arg(line);
+
+ QString format = i18n(
+ "Your document contains an unknown attribute <%1> " // keep trailing space
+ "in tag <%2>.\n"
+ "Maybe your version of KVocTrain is too old, "
+ "or the document is damaged.\n"
+ "If you proceed and save afterwards you are likely to lose data;\n"
+ "do you want to proceed anyway?\n"
+ );
+ QString msg = format.arg(attr).arg(name);
+
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Unknown attribute"));
+ bool result = (KMessageBox::warningContinueCancel(0, ln+msg, s) == KMessageBox::Continue);
+ QApplication::restoreOverrideCursor();
+ return result;
+}
+
+
+void kvoctrainDoc::unknownElement (int line, const QString &elem )
+{
+ unknown_elem = true;
+
+ QString ln = i18n("File:\t%1\nLine:\t%2\n").arg(URL().path()).arg(line);
+
+ QString format = i18n(
+ "Your document contains an unknown tag <%1>. " // keep trailing space
+ "Maybe your version of KVocTrain is too old, "
+ "or the document is damaged.\n"
+ "Loading is aborted because KVocTrain cannot "
+ "read documents with unknown elements.\n"
+ );
+ QString msg = format.arg(elem);
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Unknown element"));
+ KMessageBox::sorry(0, ln+msg, s);
+ QApplication::restoreOverrideCursor();
+}
+
+
+void kvoctrainDoc::errorKvtMl (int line, const QString &text )
+{
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Error"));
+ QString ln = i18n("File:\t%1\nLine:\t%2\n").arg(URL().path()).arg(line);
+
+ QString msg = text;
+ KMessageBox::error(0, ln+msg, s);
+ QApplication::restoreOverrideCursor();
+}
+
+
+void kvoctrainDoc::warningKvtMl (int line, const QString &text )
+{
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Warning"));
+ QString ln = i18n("File:\t%1\nLine:\t%2\n").arg(URL().path()).arg(line);
+ QString msg = text;
+ KMessageBox::information(0, ln+msg, s);
+ QApplication::restoreOverrideCursor();
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml2.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml2.cpp
new file mode 100644
index 00000000..8179bfa6
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_rb_kvtml2.cpp
@@ -0,0 +1,464 @@
+/***************************************************************************
+
+ read big body of a kvtml document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "QueryManager.h"
+
+#include <klocale.h>
+
+
+bool kvoctrainDoc::parseBody_e (XmlElement elem, XmlReader& xml)
+{
+ grade_t grade,
+ r_grade;
+ int qcount,
+ r_qcount;
+ int bcount,
+ r_bcount;
+ QString remark;
+ QString pronunce;
+ time_t qdate,
+ r_qdate;
+ bool inquery;
+ bool active;
+ QString lang;
+ QString textstr;
+ QString exprtype;
+ bool org_found = false;
+ QString q_org,
+ q_trans;
+ QString query_id;
+ kvoctrainExpr expr;
+ int lesson;
+ int width;
+ QString type;
+ QString faux_ami_f;
+ QString faux_ami_t;
+ QString synonym;
+ QString example;
+ QString antonym;
+ QString usage;
+ QString paraphrase;
+ vector<Conjugation> conjug;
+ Comparison comparison;
+ MultipleChoice mc;
+
+ if (!extract_KVT_E_attr (xml, elem, lesson, inquery, active, exprtype))
+ return false;
+
+ if (lesson
+ && lesson > (int) lesson_descr.size() ) { // description missing ?
+ QString s;
+ for (int i = lesson_descr.size(); i < lesson; i++) {
+ s.setNum (i+1);
+ s.insert (0, "#"); // invent descr according to number
+ lesson_descr.push_back (s);
+ }
+ }
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == KV_EXPR && !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+
+ unsigned int count = 0;
+ org_found = false;
+ while (elem.tag() != KV_EXPR) {
+
+ // now want "original" and one or more "translations"
+
+ // found original <o>
+
+ if (elem.tag() == KV_ORG && !elem.isEndTag() ) {
+ if (org_found) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("repeated occurrence of tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ org_found = true;
+
+ type = exprtype;
+ if (!extract_O_T_attr (
+ xml,
+ elem,
+ lang,
+ grade, r_grade,
+ qcount, r_qcount,
+ qdate, r_qdate,
+ remark,
+ bcount, r_bcount,
+ query_id,
+ pronunce,
+ width,
+ type,
+ faux_ami_t,
+ faux_ami_f,
+ synonym,
+ example,
+ antonym,
+ usage,
+ paraphrase))
+ return false;
+
+
+ if (vocabulary.size() == 0) { // only accept in first entry
+ if (width >= 0)
+ setSizeHint (count, width);
+
+ if (query_id == KV_O)
+ q_org = lang;
+
+ if (query_id == KV_T)
+ q_trans = lang;
+ }
+
+ if (langs.size() == 0) { // first entry
+ if (lang.isEmpty()) // no definition in first entry
+ lang = "original";
+ langs.push_back(lang);
+
+ }
+ else {
+ if (lang != langs[0] && !lang.isEmpty()) { // different originals ?
+ errorKvtMl (xml.lineNumber(),
+ i18n("ambiguous definition of language code"));
+ return false;
+ }
+ }
+ count = 0;
+
+//========================================
+// FIXME:: make loop for this
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag () == KV_CONJUG_GRP && !elem.isEndTag() ) {
+ if (!loadConjugKvtMl (conjug, (QString) KV_CON_TYPE, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ comparison.clear();
+ if (elem.tag () == KV_COMPARISON_GRP && !elem.isEndTag() ) {
+ if (!loadComparison (comparison, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ mc.clear();
+ if (elem.tag () == KV_MULTIPLECHOICE_GRP && !elem.isEndTag() ) {
+ if (!loadMultipleChoice (mc, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ textstr = xml.getText();
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() != KV_ORG || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_ORG));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != KV_ORG || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_ORG));
+ return false;
+ }
+ textstr = "";
+ }
+
+//========================================
+
+ expr = kvoctrainExpr (textstr);
+ expr.setLesson (lesson);
+ expr.setInQuery(inquery);
+ expr.setActive(active);
+
+ if (conjug.size() > 0) {
+ expr.setConjugation(0, conjug[0]);
+ conjug.clear();
+ }
+ if (!comparison.isEmpty()) {
+ expr.setComparison(0, comparison);
+ comparison.clear();
+ }
+ if (!mc.isEmpty()) {
+ expr.setMultipleChoice(0, mc);
+ mc.clear();
+ }
+ if (!remark.isEmpty() )
+ expr.setRemark (0, remark);
+ if (!pronunce.isEmpty() )
+ expr.setPronunce (0, pronunce);
+ if (!type.isEmpty() )
+ expr.setType(0, type);
+ if (!synonym.isEmpty() )
+ expr.setSynonym(0, synonym);
+ if (!example.isEmpty() )
+ expr.setExample(0, example);
+ if (!usage.isEmpty() )
+ expr.setUsageLabel(0, usage);
+ if (!paraphrase.isEmpty() )
+ expr.setParaphrase(0, paraphrase);
+ if (!antonym.isEmpty() )
+ expr.setAntonym(0, antonym);
+ }
+
+ // found translation <t>
+
+ else if (elem.tag() == KV_TRANS && !elem.isEndTag() ) {
+ if (!org_found) { // must be preceded by "original"
+ errorKvtMl (xml.lineNumber(),
+ i18n("starting tag <%1> is missing").arg(KV_ORG));
+ return false;
+ }
+
+ count++;
+ type = exprtype;
+ if (!extract_O_T_attr (
+ xml,
+ elem,
+ lang,
+ grade, r_grade,
+ qcount, r_qcount,
+ qdate, r_qdate,
+ remark,
+ bcount, r_bcount,
+ query_id,
+ pronunce,
+ width,
+ type,
+ faux_ami_f,
+ faux_ami_t,
+ synonym,
+ example,
+ antonym,
+ usage,
+ paraphrase))
+ return false;
+
+ if (vocabulary.size() == 0) { // only accept in first entry
+ if (width >= 0)
+ setSizeHint (count, width);
+
+ if (query_id == KV_O)
+ q_org = lang;
+
+ if (query_id == KV_T)
+ q_trans = lang;
+
+ }
+
+ if (langs.size() <= count) { // new translation
+ if (lang.isEmpty()) { // no definition in first entry ?
+ lang.setNum (langs.size() );
+ lang.insert (0, "translation ");
+ }
+ langs.push_back(lang);
+
+ }
+ else {
+ if (lang != langs[count] && !lang.isEmpty()) { // different language ?
+ errorKvtMl (xml.lineNumber(),
+ i18n("ambiguous definition of language code"));
+ return false;
+ }
+ }
+
+//========================================
+// FIXME:: make loop for this
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag () == KV_CONJUG_GRP && !elem.isEndTag() ) {
+ if (!loadConjugKvtMl (conjug, (QString) KV_CON_TYPE, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ comparison.clear();
+ if (elem.tag () == KV_COMPARISON_GRP && !elem.isEndTag() ) {
+ if (!loadComparison (comparison, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ mc.clear();
+ if (elem.tag () == KV_MULTIPLECHOICE_GRP && !elem.isEndTag() ) {
+ if (!loadMultipleChoice (mc, elem, xml))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+
+ textstr = "";
+ if (elem.tag() == "#PCDATA") { // element data
+ textstr = xml.getText();
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() != KV_TRANS || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TRANS));
+ return false;
+ }
+ // expr ...
+ }
+ else {
+ if (elem.tag() != KV_TRANS || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_TRANS));
+ return false;
+ }
+ textstr = "";
+ }
+
+//========================================
+
+ if (!org_found) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("starting tag <%1> is missing").arg(KV_ORG));
+ return false;
+ }
+/*
+ if (qcount == 0) {
+ grade = KV_NORM_GRADE;
+ }
+
+ if (r_qcount == 0) {
+ r_grade = KV_NORM_GRADE;
+ }
+*/
+ expr.addTranslation (textstr, grade, r_grade);
+ expr.setQueryCount (count, qcount, false);
+ expr.setQueryCount (count, r_qcount, true);
+ expr.setBadCount (count, bcount, false);
+ expr.setBadCount (count, r_bcount, true);
+ expr.setQueryDate (count, qdate, false);
+ expr.setQueryDate (count, r_qdate, true);
+
+ if (conjug.size() > 0) {
+ expr.setConjugation(count, conjug[0]);
+ conjug.clear();
+ }
+ if (!comparison.isEmpty()) {
+ expr.setComparison(count, comparison);
+ comparison.clear();
+ }
+ if (!mc.isEmpty()) {
+ expr.setMultipleChoice(count, mc);
+ mc.clear();
+ }
+ if (!type.isEmpty() )
+ expr.setType (count, type);
+ if (!remark.isEmpty() )
+ expr.setRemark (count, remark);
+ if (!pronunce.isEmpty() )
+ expr.setPronunce (count, pronunce);
+ if (!faux_ami_f.isEmpty() )
+ expr.setFauxAmi (count, faux_ami_f, false);
+ if (!faux_ami_t.isEmpty() )
+ expr.setFauxAmi (count, faux_ami_t, true);
+ if (!synonym.isEmpty() )
+ expr.setSynonym (count, synonym);
+ if (!example.isEmpty() )
+ expr.setExample (count, example);
+ if (!usage.isEmpty() )
+ expr.setUsageLabel (count, usage);
+ if (!paraphrase.isEmpty() )
+ expr.setParaphrase (count, paraphrase);
+ if (!antonym.isEmpty() )
+ expr.setAntonym (count, antonym);
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag());
+ return false;
+ }
+ }
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ }
+ if (numEntries() == 0)
+ setQueryLang (q_org, q_trans);
+ vocabulary.push_back (expr);
+
+ return true;
+}
+
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_rh_kvtml.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_rh_kvtml.cpp
new file mode 100644
index 00000000..e6588675
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_rh_kvtml.cpp
@@ -0,0 +1,856 @@
+/***************************************************************************
+
+ read header parts of a kvtml document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "QueryManager.h"
+
+#include <klocale.h>
+
+#include <qtextcodec.h>
+
+bool kvoctrainDoc::loadFromKvtMl (QTextStream& is)
+{
+ // important, first action
+ // switch to actual encoding afterwards, otherwise blocked
+ is.setCodec(QTextCodec::codecForName("UTF-8"));
+ is.setEncoding(QTextStream::UnicodeUTF8);
+
+ langs.clear();
+ vocabulary.clear();
+ XmlReader xml (is);
+
+ if (! xml.validHeader ()) {
+ errorKvtMl (xml.lineNumber(), i18n("invalid xml file header") );
+ return false;
+ }
+
+ generator = "";
+ cols = 0;
+ lines = 0;
+ doctitle = "";
+ author = "";
+ license = "";
+ doc_remark = "";
+ XmlElement elem;
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag () != KV_DOCTYPE) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("Tag <%1> was expected "
+ "but tag <%2> was read." ).arg(KV_DOCTYPE).arg(elem.tag()));
+ return false;
+ }
+
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ doctitle = i18n("Untitled");
+ while (first != elem.attributes ().end ()) {
+
+ if ((*first).name () == KV_ENCODING) {
+
+ if ((*first).stringValue().upper() == (QString)"UTF-8" ) {
+ is.setCodec(QTextCodec::codecForName("UTF-8"));
+ is.setEncoding(QTextStream::UnicodeUTF8);
+ }
+ else if ((*first).stringValue().upper() == (QString)"8BIT" ) { // old compatibility mode
+ is.setCodec(QTextCodec::codecForName("ISO 8859-1"));
+ is.setEncoding(QTextStream::Latin1);
+ }
+ else {
+ is.setCodec(QTextCodec::codecForName("ISO 8859-1"));
+ is.setEncoding(QTextStream::Latin1);
+ QString format = i18n("Unknown document encoding \"%1\" was encountered.\n\n"
+ "It will be ignored. Encoding is now \"%2\".");
+ QString msg =format.arg((*first).stringValue ().upper()).arg("ISO 8859-1");
+ warningKvtMl (xml.lineNumber(), msg);
+ }
+
+ }
+ else if ((*first).name () == KV_TITLE) {
+ doctitle = (*first).stringValue ();
+ }
+ else if ((*first).name () == KV_AUTHOR) {
+ author = (*first).stringValue ();
+ }
+ else if ((*first).name () == KV_LICENSE) {
+ license = (*first).stringValue ();
+ }
+ else if ((*first).name () == KV_DOC_REM) {
+ doc_remark = (*first).stringValue ();
+ }
+ else if ((*first).name () == KV_GENERATOR) {
+ generator = (*first).stringValue ();
+ int pos = generator.findRev (KVD_VERS_PREFIX);
+ if (pos >= 0) {
+ doc_version = generator;
+ doc_version.remove (0, pos+2);
+ }
+ }
+ else if ((*first).name () == KV_COLS) {
+ cols = (*first).intValue ();
+ }
+ else if ((*first).name () == KV_LINES) {
+ lines = (*first).intValue ();
+ }
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "kvtml", (*first).name ()))
+ return false;
+ }
+
+ first++;
+ }
+
+ bool result = parseBody_kvtml (elem, xml); // read vocabulary
+
+ setModified (false);
+ return result;
+}
+
+
+bool kvoctrainDoc::extract_L_DESCR_attr (XmlReader &xml,
+ XmlElement &elem, int &no,
+ bool &isCurr, bool &inQuery)
+{
+ no = 0;
+ isCurr = false;
+ inQuery = false;
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+ if ((*first).name () == KV_LESS_NO)
+ no = (*first).intValue();
+ else if ((*first).name () == KV_LESS_CURR)
+ isCurr = (*first).intValue() != 0;
+ else if ((*first).name () == KV_LESS_QUERY)
+ inQuery = (*first).intValue() != 0;
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "descr", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::check_Empty_attr (QString tag_name,
+ XmlReader &xml,
+ XmlElement &elem)
+{
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ if (first != elem.attributes ().end ()) {
+ if (!unknownAttribute(xml.lineNumber(), tag_name, (*first).name ()))
+ return false;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_simple_tag (QString tag_name,
+ XmlReader& xml,
+ XmlElement &elem,
+ QString &data,
+ bool check_it)
+{
+ if (check_it)
+ if (!check_Empty_attr (tag_name, xml, elem))
+ return false;
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ data = xml.getText();
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+ else if (elem.tag() != tag_name || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(), i18n("expected ending tag <%1>").arg(tag_name));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != tag_name || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(), i18n("expected ending tag <%1>").arg(tag_name));
+ return false;
+ }
+ data = "";
+ }
+
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_CON_E_attr (XmlReader& xml,
+ XmlElement &elem,
+ QString &lang)
+{
+ lang = "";
+
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+
+ if ((*first).name () == KV_LANG)
+ lang = (*first).stringValue();
+
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "e", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::loadArticleKvtMl (XmlElement elem, XmlReader& xml)
+
+/*
+ <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>
+*/
+
+{
+ bool endOfGroup = false;
+ bool inEntry = false;
+ QString s;
+ articles.clear();
+
+ if (!check_Empty_attr (KV_ARTICLE_GRP, xml, elem))
+ return false;
+
+ QString fem_def,
+ mal_def,
+ nat_def,
+ fem_indef,
+ mal_indef,
+ nat_indef;
+ QString lang;
+ int count = 0;
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_ARTICLE_GRP) {
+ if (inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ARTICLE_GRP));
+ return false;
+ }
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_ARTICLE_GRP));
+ return false;
+ }
+ else
+ endOfGroup = true;
+ }
+ else if (elem.tag () == KV_ART_ENTRY) {
+ if (! elem.isEndTag ()) {
+ if (inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_ENTRY));
+ return false;
+ }
+ inEntry = true;
+
+ if (!extract_CON_E_attr (xml, elem, lang) )
+ return false;
+
+ if ((int)langs.size() <= count) { // first entry
+ if (lang.isEmpty()) // no definition in first entry
+ lang = "original";
+ langs.push_back(lang);
+ }
+ else {
+ if (lang != langs[count] && !lang.isEmpty()) { // different originals ?
+ errorKvtMl (xml.lineNumber(),
+ i18n("ambiguous definition of language code"));
+ return false;
+ }
+ }
+ fem_def = "";
+ mal_def = "";
+ nat_def = "";
+ fem_indef = "";
+ mal_indef = "";
+ nat_indef = "";
+ }
+ else {
+ count++;
+ inEntry = false;
+ articles.push_back (Article(fem_def, fem_indef,
+ mal_def, mal_indef,
+ nat_def, nat_indef));
+ }
+ }
+ else if (elem.tag () == KV_ART_FD && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_FD));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_FD, xml, elem, fem_def))
+ return false;
+ }
+ else if (elem.tag () == KV_ART_FI && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_FI));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_FI, xml, elem, fem_indef))
+ return false;
+ }
+ else if (elem.tag () == KV_ART_MD && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_MD));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_MD, xml, elem, mal_def))
+ return false;
+ }
+ else if (elem.tag () == KV_ART_MI && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_MI));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_MI, xml, elem, mal_indef))
+ return false;
+ }
+ else if (elem.tag () == KV_ART_ND && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_ND));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_ND, xml, elem, nat_def))
+ return false;
+ }
+ else if (elem.tag () == KV_ART_NI && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_ART_NI));
+ return false;
+ }
+ if (!extract_simple_tag (KV_ART_NI, xml, elem, nat_indef))
+ return false;
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_T_attr (XmlReader &xml,
+ XmlElement &elem,
+ QString &name)
+{
+ name = "";
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+
+ if ((*first).name () == KV_CON_NAME)
+ name = (*first).stringValue();
+
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "e", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_BOOL_attr (
+ XmlReader &xml,
+ XmlElement &elem,
+ const QString &tag_name,
+ const QString &attr_name,
+ bool &flag)
+{
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+ if ((*first).name () == attr_name)
+ flag = (bool) (*first).intValue();
+ else {
+ if (!unknownAttribute(xml.lineNumber(), tag_name, (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::loadConjugKvtMl (vector<Conjugation> &curr_conjug,
+ const QString &entry_tag,
+ XmlElement elem, XmlReader& xml)
+
+/*
+ <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>he</s3f>
+ <s3m>she</s3m>
+ <s3n>it</s3n>
+ <p1>we</p1>
+ <p2>you</p2>
+ <p3f>they</p3f>
+ <p3m>they</p3m>
+ <p3n>they</p3n>
+ </e>
+ </conjugation>
+
+ <conjugation> and 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>
+*/
+
+{
+ bool endOfGroup = false;
+ bool inEntry = false;
+ QString s;
+
+ curr_conjug.clear();
+
+ if (!check_Empty_attr (KV_CONJUG_GRP, xml, elem))
+ return false;
+
+ bool p3_common,
+ s3_common;
+ QString pers1_sing,
+ pers2_sing,
+ pers3_m_sing,
+ pers3_f_sing,
+ pers3_n_sing,
+ pers1_plur,
+ pers2_plur,
+ pers3_m_plur,
+ pers3_f_plur,
+ pers3_n_plur;
+
+ QString lang;
+ QString type;
+ int count = 0;
+ curr_conjug.push_back (Conjugation());
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_CONJUG_GRP) {
+ if (inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CONJUG_GRP));
+ return false;
+ }
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfGroup = true;
+ }
+ else if (elem.tag () == entry_tag) {
+ if (! elem.isEndTag ()) {
+ if (inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(entry_tag));
+ return false;
+ }
+ inEntry = true;
+
+ if (entry_tag == KV_CON_ENTRY) {
+ type = CONJ_PREFIX;
+ if (!extract_CON_E_attr (xml, elem, lang) )
+ return false;
+
+ if ((int)langs.size() <= count) { // first entry
+ if (lang.isEmpty()) // no definition in first entry
+ lang = "original";
+ langs.push_back(lang);
+ }
+ else {
+ if (lang != langs[count] && !lang.isEmpty()) { // different originals ?
+ errorKvtMl (xml.lineNumber(),
+ i18n("ambiguous definition of language code"));
+ return false;
+ }
+ }
+ }
+ else if (entry_tag == KV_CON_TYPE) {
+ if (!extract_T_attr (xml, elem, type))
+ return false;
+ if (type.length() != 0 && type.left(1) == UL_USER_TENSE) {
+ int num = QMIN(type.mid (1, 40).toInt(), 1000); // paranoia check
+ if( num > (int) tense_descr.size() ) { // description missing ?
+ QString s;
+ for (int i = tense_descr.size(); i < num; i++) {
+ s.setNum (i+1);
+ s.insert (0, "#"); // invent descr according to number
+ tense_descr.push_back (s);
+ }
+ }
+ }
+ }
+
+ pers1_sing = "";
+ pers2_sing = "";
+ pers3_m_sing = "";
+ pers3_f_sing = "";
+ pers3_n_sing = "";
+ pers1_plur = "";
+ pers2_plur = "";
+ pers3_m_plur = "";
+ pers3_f_plur = "";
+ pers3_n_plur = "";
+ p3_common = false;
+ s3_common = false;
+ }
+ else {
+ inEntry = false;
+ if (entry_tag == KV_CON_ENTRY)
+ while (count+1 > (int) curr_conjug.size() )
+ curr_conjug.push_back (Conjugation());
+
+ curr_conjug[count].setPers3SingularCommon(type, s3_common);
+ curr_conjug[count].setPers3PluralCommon(type, p3_common);
+ curr_conjug[count].setPers1Singular(type, pers1_sing);
+ curr_conjug[count].setPers2Singular(type, pers2_sing);
+ curr_conjug[count].setPers3FemaleSingular(type, pers3_f_sing);
+ curr_conjug[count].setPers3MaleSingular(type, pers3_m_sing);
+ curr_conjug[count].setPers3NaturalSingular(type, pers3_n_sing);
+ curr_conjug[count].setPers1Plural(type, pers1_plur);
+ curr_conjug[count].setPers2Plural(type, pers2_plur);
+ curr_conjug[count].setPers3FemalePlural(type, pers3_f_plur);
+ curr_conjug[count].setPers3MalePlural(type, pers3_m_plur);
+ curr_conjug[count].setPers3NaturalPlural(type, pers3_n_plur);
+
+ if (entry_tag == KV_CON_ENTRY)
+ count++;
+ }
+ }
+ else if (elem.tag () == KV_CON_P1S && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P1S));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P1S, xml, elem, pers1_sing) )
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P2S && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P2S));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P2S, xml, elem, pers2_sing))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3SF && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3SF));
+ return false;
+ }
+
+ if (!extract_BOOL_attr (xml, elem,KV_CON_P3SF, KV_CONJ_COMMON,
+ s3_common))
+ return false;
+
+ if (!extract_simple_tag (KV_CON_P3SF, xml, elem, pers3_f_sing, false))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3SM && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3SM));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P3SM, xml, elem, pers3_m_sing))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3SN && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3SN));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P3SN, xml, elem, pers3_n_sing))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P1P && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P1P));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P1P, xml, elem, pers1_plur) )
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P2P && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P2P));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P2P, xml, elem, pers2_plur))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3PF && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3PF));
+ return false;
+ }
+
+ if (!extract_BOOL_attr (xml, elem, KV_CON_P3PF, KV_CONJ_COMMON,
+ p3_common))
+ return false;
+
+ if (!extract_simple_tag (KV_CON_P3PF, xml, elem, pers3_f_plur, false))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3PM && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3PM));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P3PM, xml, elem, pers3_m_plur))
+ return false;
+ }
+ else if (elem.tag () == KV_CON_P3PN && !elem.isEndTag() ) {
+ if (!inEntry) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("disallowed occurrence of tag <%1>").arg(KV_CON_P3PN));
+ return false;
+ }
+ if (!extract_simple_tag (KV_CON_P3PN, xml, elem, pers3_n_plur))
+ return false;
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::extract_L_GROUP_attr (XmlReader &xml,
+ XmlElement &elem,
+ int &width)
+{
+ width = 0;
+ list<XmlAttribute>::const_iterator first = elem.attributes ().begin ();
+ while (first != elem.attributes ().end ()) {
+ if ((*first).name () == KV_SIZEHINT)
+ width = (*first).intValue();
+ else {
+ if (!unknownAttribute(xml.lineNumber(), "lesson", (*first).name ()))
+ return false;
+ }
+ first++;
+ }
+ return true;
+}
+
+
+bool kvoctrainDoc::loadLessonKvtMl (XmlElement elem, XmlReader& xml)
+{
+ bool endOfGroup = false;
+ QString s;
+ bool isCurr;
+ bool inQuery = false;
+ lesson_descr.clear();
+ int width;
+
+ if (!extract_L_GROUP_attr (xml, elem, width))
+ return false;
+ setSizeHint (-1, width);
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_LESS_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+ else if (elem.tag () == KV_LESS_DESC && !elem.isEndTag() ) {
+ int no;
+ if (!extract_L_DESCR_attr (xml, elem, no, isCurr, inQuery))
+ return false;
+
+ lessons_in_query.push_back(inQuery);
+
+ if (isCurr && no != 0)
+ setCurrentLesson (no);
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() == "#PCDATA") { // element data
+ s = xml.getText();
+
+ if (! xml.readElement (elem) ) {
+ errorKvtMl (xml.lineNumber(), i18n("I/O failure") );
+ return false;
+ }
+
+ if (elem.tag() != KV_LESS_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_LESS_DESC));
+ return false;
+ }
+ }
+ else {
+ if (elem.tag() != KV_LESS_DESC || !elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(KV_LESS_DESC));
+ return false;
+ }
+ s = "";
+ }
+ lesson_descr.push_back (s);
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
+
+bool kvoctrainDoc::loadOptionsKvtMl (XmlElement elem, XmlReader& xml)
+{
+ bool endOfGroup = false;
+ QString s;
+
+ do {
+ if (! xml.readElement (elem))
+ break;
+
+ if (elem.tag () == KV_OPTION_GRP) {
+ if (! elem.isEndTag ()) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("expected ending tag <%1>").arg(elem.tag()));
+ return false;
+ }
+ else
+ endOfGroup = true;
+
+ }
+ else if (elem.tag () == KV_OPT_SORT) {
+ sort_allowed = true;
+
+ if (!extract_BOOL_attr (xml, elem, KV_OPTION_GRP, KV_BOOL_FLAG,
+ sort_allowed))
+ return false;
+
+ }
+ else {
+ if (elem.isEndTag() ) {
+ errorKvtMl (xml.lineNumber(),
+ i18n("unexpected ending tag <%1>" ).arg(elem.tag()));
+ return false;
+ }
+ else {
+ unknownElement (xml.lineNumber(), elem.tag() );
+ return false;
+ }
+ }
+ } while (! endOfGroup);
+
+ return true;
+}
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_vcb.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_vcb.cpp
new file mode 100644
index 00000000..2dfde3fe
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_vcb.cpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+
+ maintain a document in vocabbox format
+
+ -----------------------------------------------------------------------
+
+ begin : Thr Mar 23 21:00:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2004 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <klocale.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+
+#include "kvoctraindoc.h"
+#include "kvoctraincore.h"
+
+
+
+bool kvoctrainDoc::saveTypeNameVcb (QTextStream &/*os*/)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::loadTypeNameVcb (QTextStream &/*is*/)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::saveLessonVcb (QTextStream &/*os*/)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::loadLessonVcb (QTextStream &/*is*/)
+{
+ return true;
+}
+
+
+bool kvoctrainDoc::saveToVcb (QTextStream& os, QString &/*title*/)
+{
+ saveTypeNameVcb (os);
+ saveLessonVcb (os);
+
+ int ent_no = 0;
+ int ent_percent = (int) vocabulary.size () / 100;
+ float f_ent_percent = (int) vocabulary.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ vector<kvoctrainExpr>::const_iterator first = vocabulary.begin ();
+ while (first != vocabulary.end ()) {
+
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, int(ent_no / f_ent_percent));
+
+ QString s, exp;
+
+ exp = (*first).getOriginal()+VCB_SEPARATOR;
+ exp += (*first).getTranslation(1)+VCB_SEPARATOR;
+
+ exp += (*first).gradeStr (1, false)+VCB_SEPARATOR;
+ exp += (*first).gradeStr (1, true)+VCB_SEPARATOR;
+ s.setNum ((*first).getQueryDate (1, false));
+ exp += s+VCB_SEPARATOR;
+ s.setNum ((*first).getQueryDate (1, true));
+ exp += s;
+
+ os << exp << "\n";
+
+ first++;
+ }
+
+ setModified (false);
+ return os.device()->status() == IO_Ok;
+}
+
+
+bool kvoctrainDoc::loadFromVcb (QTextStream& is)
+{
+
+ langs.clear();
+ vocabulary.clear();
+ loadTypeNameVcb (is);
+ loadLessonVcb (is);
+
+ int size = is.device()->size ();
+ int ln = size / 40 / 100; // assume each line about 40 chars
+ float f_ent_percent = size / 100.0;
+ emit progressChanged (this, 0);
+
+ for (int l = 0; !is.eof(); l++) {
+ QString s = is.readLine();
+
+ ln--;
+ if (ln <= 0) {
+ ln = size / 40 / 100; // assume each line about 40 chars
+ emit progressChanged(this, int(is.device()->at() / f_ent_percent));
+ }
+
+ if (!s.stripWhiteSpace().isEmpty()) {
+ QString o, t;
+ grade_t ograde = KV_LEV1_GRADE,
+ tgrade = KV_LEV1_GRADE;
+ size_t odate = time(0),
+ tdate = time(0);
+
+ int pos = s.find (VCB_SEPARATOR);
+ if (pos >= 0) {
+ o = s.left(pos);
+ s.remove (0, pos+QString(VCB_SEPARATOR).length());
+ }
+
+ pos = s.find (VCB_SEPARATOR);
+ if (pos >= 0) {
+ t = s.left(pos);
+ s.remove (0, pos+QString(VCB_SEPARATOR).length());
+ }
+ else {
+ t = s;
+ }
+
+ pos = s.find (VCB_SEPARATOR);
+ if (pos >= 0) {
+ ograde = s.left(pos).toInt();
+ s.remove (0, pos+QString(VCB_SEPARATOR).length());
+ }
+
+ pos = s.find (VCB_SEPARATOR);
+ if (pos >= 0) {
+ tgrade = s.left(pos).toInt();
+ s.remove (0, pos+QString(VCB_SEPARATOR).length());
+ }
+
+ pos = s.find (VCB_SEPARATOR);
+ if (pos >= 0) {
+ odate = s.left(pos).toInt();
+ s.remove (0, pos+QString(VCB_SEPARATOR).length());
+ }
+
+ if (s.stripWhiteSpace().length() > 0) {
+ tdate = s.toInt();
+ }
+
+ kvoctrainExpr bucket;
+ bucket.setOriginal(o);
+ bucket.addTranslation(t);
+
+ bucket.setGrade(1, ograde, false);
+ if (ograde != 0)
+ bucket.setQueryCount(1, 1, false);
+
+ bucket.setGrade(1, tgrade, true);
+ if (tgrade != 0)
+ bucket.setQueryCount(1, 1, true);
+
+ bucket.setQueryDate(1, odate, false);
+ bucket.setQueryDate(1, tdate, true);
+
+ appendEntry (&bucket);
+ }
+ }
+
+ langs.push_back("en");
+ langs.push_back("en");
+
+ setModified (false);
+ return is.device()->status() == IO_Ok;
+}
+
+
+void kvoctrainDoc::errorVcb (int /*line*/, const QString &text )
+{
+ unknown_elem = true;
+ QApplication::setOverrideCursor( arrowCursor, true );
+ QString s = kapp->makeStdCaption(i18n("Error in vocabbox file"));
+ QString msg = text;
+ KMessageBox::error(0, msg, s);
+ QApplication::restoreOverrideCursor();
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_voc.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_voc.cpp
new file mode 100644
index 00000000..e99c2e31
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_voc.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+
+ maintain a document in Vokabletrainer format
+
+ -----------------------------------------------------------------------
+
+ begin : Wed Jun 15 19:32:00 PDT 2005
+
+ copyright : (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <klocale.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+#include "kvoctraindoc.h"
+#include "kvoctraincore.h"
+
+
+bool kvoctrainDoc::loadFromVoc(QTextStream& is)
+{
+ author = "http://www.vokabeln.de"; //DO NOT translate
+
+ langs.clear();
+ vocabulary.clear();
+ lesson_descr.clear();
+
+ QString title,
+ lang1,
+ lang2,
+ expression,
+ original,
+ translation,
+ lessonDescr,
+ temp;
+
+ int i,
+ wordCount,
+ lesson;
+
+ int lines = 10000;
+
+ QStringList titles,
+ languages,
+ words;
+
+ bool keepGoing = true;
+
+ while (keepGoing)
+ {
+ temp = is.readLine();
+ keepGoing = !(temp.find("\",") > 0);
+ title.append(temp);
+ if (keepGoing)
+ title.append(" ");
+ }
+
+ titles = QStringList::split("\",", title);
+ doctitle = titles[0].mid(1);
+ wordCount = titles[1].section(',', 0, 0).toInt();
+
+ is.readLine();
+ is.readLine();
+
+ lang1 = is.readLine();
+ languages = QStringList::split("\",", lang1);
+
+ langs.push_back(languages[0].mid(1));
+ langs.push_back(languages[1].mid(1));
+
+ keepGoing = true;
+ while (keepGoing)
+ keepGoing = !(is.readLine().find("8. Lernhilfe") > 0); //DO NOT translate
+
+ for (i = 0; i <= 14; i++)
+ is.readLine();
+
+ for (i = 0; i < wordCount - 1; i++)
+ {
+ int c = 0;
+ expression.setLength(0);
+
+ while (c < 2)
+ {
+ temp = is.readLine();
+ c+= temp.contains("\",");
+ expression.append(temp);
+ if (c < 2)
+ expression.append(" ");
+ }
+
+ words = QStringList::split("\",", expression);
+ original = words[0].mid(1);
+ translation = words[1].mid(1);
+ lesson = words[2].toInt();
+
+ kvoctrainExpr kve;
+ kve.setOriginal(original);
+ kve.setGrade(1, 0, false);
+ kve.setGrade(1, 0, true);
+ kve.setLesson(lesson);
+ kve.addTranslation(translation);
+
+ vocabulary.push_back(kve);
+
+ is.readLine();
+ is.readLine();
+ }
+
+ is.readLine();
+ is.readLine();
+ is.readLine();
+
+ for (int i = 0; !is.eof() && i < lines; i++)
+ {
+ lessonDescr = is.readLine();
+ lessonDescr = lessonDescr.mid(1, lessonDescr.length() - 2);
+ if (!lessonDescr.isEmpty())
+ lesson_descr.push_back(lessonDescr);
+ else
+ break;
+ is.readLine();
+ }
+
+ setModified(false);
+ doc_url.setFileName(i18n("Untitled"));
+ return is.device()->status() == IO_Ok;
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvd_wkvtml.cpp b/kvoctrain/kvoctrain/kvt-core/kvd_wkvtml.cpp
new file mode 100644
index 00000000..af0ba06d
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvd_wkvtml.cpp
@@ -0,0 +1,960 @@
+/***************************************************************************
+
+ write a kvtml document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "kvoctraincore.h"
+#include "QueryManager.h"
+
+#include <kdebug.h>
+
+#include <qtextcodec.h>
+
+bool kvoctrainDoc::saveTypeNameKvtMl (XmlWriter &xml)
+{
+ if (type_descr.size() == 0)
+ return true;
+
+ xml.writeText(" ");
+ xml.startTag (KV_TYPE_GRP, true, false, true);
+
+ for (int lfn = 0; lfn < (int) type_descr.size(); lfn++) {
+ if (!type_descr[lfn].isNull() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_TYPE_DESC, false);
+ xml.addAttribute (KV_TYPE_NO, lfn+1 );
+ xml.closeTag();
+ xml.writeText (type_descr[lfn]);
+ xml.endTag (KV_TYPE_DESC, true);
+ }
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_TYPE_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveTenseNameKvtMl (XmlWriter &xml)
+{
+ if (tense_descr.size() == 0)
+ return true;
+
+ xml.writeText(" ");
+ xml.startTag (KV_TENSE_GRP, true, false, true);
+
+ for (int lfn = 0; lfn < (int) tense_descr.size(); lfn++) {
+ if (!tense_descr[lfn].isNull() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_TENSE_DESC, false);
+ xml.addAttribute (KV_TENSE_NO, lfn+1 );
+ xml.closeTag();
+ xml.writeText (tense_descr[lfn]);
+ xml.endTag (KV_TENSE_DESC, true);
+ }
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_TENSE_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveUsageNameKvtMl (XmlWriter &xml)
+{
+ if (usage_descr.size() == 0)
+ return true;
+
+ xml.writeText(" ");
+ xml.startTag (KV_USAGE_GRP, true, false, true);
+
+ for (int lfn = 0; lfn < (int) usage_descr.size(); lfn++) {
+ if (!usage_descr[lfn].isNull() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_USAGE_DESC, false);
+ xml.addAttribute (KV_USAGE_NO, lfn+1 );
+ xml.closeTag();
+ xml.writeText (usage_descr[lfn]);
+ xml.endTag (KV_USAGE_DESC, true);
+ }
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_USAGE_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveLessonKvtMl (XmlWriter &xml)
+{
+ if (lesson_descr.size() == 0)
+ return true;
+
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_LESS_GRP, false);
+ xml.addAttribute (KV_SIZEHINT, getSizeHint (-1));
+ xml.closeTag(false, true);
+
+ for (int lfn = 0; lfn < (int) lesson_descr.size(); lfn++) {
+ if (!lesson_descr[lfn].isNull() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_LESS_DESC, false);
+ xml.addAttribute (KV_LESS_NO, lfn+1 );
+ if (getCurrentLesson() == lfn+1)
+ xml.addAttribute (KV_LESS_CURR, (QString) "1" );
+ if (lfn < (int) lessons_in_query.size() && lessons_in_query[lfn])
+ xml.addAttribute (KV_LESS_QUERY, (QString) "1" );
+ xml.closeTag();
+ xml.writeText (lesson_descr[lfn]);
+ xml.endTag (KV_LESS_DESC, true);
+ }
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_LESS_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveConjug (const Conjugation &curr_conjug, QString type,
+ XmlWriter &xml, QString identstr)
+{
+ bool linefeed = type == CONJ_PREFIX;
+ if (linefeed)
+ identstr+" ";
+ else
+ identstr = "";
+
+ if (!curr_conjug.pers1Singular(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P1S, true, false, false);
+ xml.writeText (curr_conjug.pers1Singular(type));
+ xml.endTag (KV_CON_P1S, linefeed);
+ }
+
+ if (!curr_conjug.pers2Singular(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P2S, true, false, false);
+ xml.writeText (curr_conjug.pers2Singular(type));
+ xml.endTag (KV_CON_P2S, linefeed);
+ }
+
+ bool common = curr_conjug.pers3SingularCommon(type);
+ if (!curr_conjug.pers3FemaleSingular(type).isEmpty()
+ || common) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3SF, false, false, false);
+ if (common)
+ xml.addAttribute (KV_CONJ_COMMON, common);
+ xml.closeTag(false, false);
+ xml.writeText (curr_conjug.pers3FemaleSingular(type));
+ xml.endTag (KV_CON_P3SF, linefeed);
+ }
+
+ if (!curr_conjug.pers3MaleSingular(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3SM, true, false, false);
+ xml.writeText (curr_conjug.pers3MaleSingular(type));
+ xml.endTag (KV_CON_P3SM, linefeed);
+ }
+
+ if (!curr_conjug.pers3NaturalSingular(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3SN, true, false, false);
+ xml.writeText (curr_conjug.pers3NaturalSingular(type));
+ xml.endTag (KV_CON_P3SN, linefeed);
+ }
+
+ if (!curr_conjug.pers1Plural(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P1P, true, false, false);
+ xml.writeText (curr_conjug.pers1Plural(type));
+ xml.endTag (KV_CON_P1P, linefeed);
+ }
+
+ if (!curr_conjug.pers2Plural(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P2P, true, false, false);
+ xml.writeText (curr_conjug.pers2Plural(type));
+ xml.endTag (KV_CON_P2P, linefeed);
+ }
+
+ common = curr_conjug.pers3PluralCommon(type);
+ if (!curr_conjug.pers3FemalePlural(type).isEmpty()
+ || common) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3PF, false, false, false);
+ if (common)
+ xml.addAttribute (KV_CONJ_COMMON, common);
+ xml.closeTag(false, false);
+ xml.writeText (curr_conjug.pers3FemalePlural(type));
+ xml.endTag (KV_CON_P3PF, linefeed);
+ }
+
+ if (!curr_conjug.pers3MalePlural(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3PM, true, false, false);
+ xml.writeText (curr_conjug.pers3MalePlural(type));
+ xml.endTag (KV_CON_P3PM, linefeed);
+ }
+
+ if (!curr_conjug.pers3NaturalPlural(type).isEmpty() ) {
+ xml.writeText(identstr);
+ xml.startTag (KV_CON_P3PN, true, false, false);
+ xml.writeText (curr_conjug.pers3NaturalPlural(type));
+ xml.endTag (KV_CON_P3PN, linefeed);
+ }
+
+ return true;
+
+}
+
+bool kvoctrainDoc::saveConjugHeader(vector<Conjugation> &curr_conjug,
+ XmlWriter &xml)
+{
+/*
+ <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;
+
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_CONJUG_GRP, false);
+ xml.closeTag(false, true);
+
+ QString def, indef, s;
+ for (int ent = 0; ent < QMIN((int) curr_conjug.size(), numLangs()); ent++) {
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_CON_ENTRY, false);
+
+ if (ent == 0) {
+ s = getOriginalIdent().stripWhiteSpace();
+ if (s.isEmpty() )
+ s = "original";
+ }
+ else {
+ s = getIdent(ent).stripWhiteSpace();
+ if (s.isEmpty() ) {
+ s.setNum (ent);
+ s.insert (0, "translation ");
+ }
+ }
+ xml.addAttribute (KV_LANG, s);
+ xml.closeTag(false, true);
+
+ if (!saveConjug (curr_conjug[ent], CONJ_PREFIX, xml, " ") )
+ return false;
+
+ xml.writeText(" ");
+ xml.endTag (KV_CON_ENTRY, true);
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_CONJUG_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveComparison (const Comparison &comp,
+ XmlWriter &xml, int ident)
+
+/*
+ <comparison>
+ <l1>good</l1>
+ <l2>better</l2>
+ <l3>best</l3>
+ </comparison>
+*/
+
+{
+ if (comp.isEmpty())
+ return true;
+
+ xml.writeText("\n");
+ QString identstr;
+ identstr.fill (' ', ident+1);
+
+ xml.writeText(identstr);
+ xml.startTag (KV_COMPARISON_GRP, false);
+ xml.closeTag(false, true);
+ xml.writeText(identstr+" ");
+
+ if (!comp.l1().isEmpty() ) {
+ xml.startTag (KV_COMP_L1, true, false, false);
+ xml.writeText (comp.l1());
+ xml.endTag (KV_COMP_L1, false);
+ }
+
+ if (!comp.l2().isEmpty() ) {
+ xml.startTag (KV_COMP_L2, true, false, false);
+ xml.writeText (comp.l2());
+ xml.endTag (KV_COMP_L2, false);
+ }
+
+ if (!comp.l3().isEmpty() ) {
+ xml.startTag (KV_COMP_L3, true, false, false);
+ xml.writeText (comp.l3());
+ xml.endTag (KV_COMP_L3, false);
+ }
+
+ xml.writeText("\n"+identstr);
+ xml.endTag (KV_COMPARISON_GRP, true);
+ xml.writeText(identstr); // indent next element
+ return true;
+}
+
+
+bool kvoctrainDoc::saveMultipleChoice (const MultipleChoice &mc,
+ XmlWriter &xml, int ident)
+
+/*
+ <multiplechoice>
+ <mc1>good</mc1>
+ <mc2>better</mc2>
+ <mc3>best</mc3>
+ <mc4>best 2</mc4>
+ <mc5>best 3</mc5>
+ </multiplechoice>
+*/
+
+{
+ if (mc.isEmpty())
+ return true;
+
+ xml.writeText("\n");
+ QString identstr;
+ identstr.fill (' ', ident+1);
+
+ xml.writeText(identstr);
+ xml.startTag (KV_MULTIPLECHOICE_GRP, false);
+ xml.closeTag(false, true);
+ xml.writeText(identstr+" ");
+
+ if (!mc.mc1().isEmpty() ) {
+ xml.startTag (KV_MC_1, true, false, false);
+ xml.writeText (mc.mc1());
+ xml.endTag (KV_MC_1, false);
+ }
+
+ if (!mc.mc2().isEmpty() ) {
+ xml.startTag (KV_MC_2, true, false, false);
+ xml.writeText (mc.mc2());
+ xml.endTag (KV_MC_2, false);
+ }
+
+ if (!mc.mc3().isEmpty() ) {
+ xml.startTag (KV_MC_3, true, false, false);
+ xml.writeText (mc.mc3());
+ xml.endTag (KV_MC_3, false);
+ }
+
+ if (!mc.mc4().isEmpty() ) {
+ xml.startTag (KV_MC_4, true, false, false);
+ xml.writeText (mc.mc4());
+ xml.endTag (KV_MC_4, false);
+ }
+
+ if (!mc.mc5().isEmpty() ) {
+ xml.startTag (KV_MC_5, true, false, false);
+ xml.writeText (mc.mc5());
+ xml.endTag (KV_MC_5, false);
+ }
+
+ xml.writeText("\n"+identstr);
+ xml.endTag (KV_MULTIPLECHOICE_GRP, true);
+ xml.writeText(identstr); // indent next element
+ return true;
+}
+
+
+bool kvoctrainDoc::saveConjugEntry (Conjugation &curr_conjug,
+ XmlWriter &xml,
+ int ident)
+
+/*
+ <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.numEntries() == 0 )
+ return true;
+
+ QString identstr;
+ identstr.fill (' ', ident+1);
+ xml.writeText("\n");
+
+ xml.writeText(identstr); // indent entry a bit
+ xml.startTag (KV_CONJUG_GRP, false);
+ xml.closeTag(false, true);
+
+ QString def, indef, s;
+ QString type;
+ for (int lfn = 0; lfn < (int) curr_conjug.numEntries(); lfn++) {
+ xml.writeText(identstr+" "); // indent entry a bit
+ xml.startTag (KV_CON_TYPE, false);
+ type = curr_conjug.getType(lfn);
+ xml.addAttribute (KV_CON_NAME, type);
+ xml.closeTag(false, false);
+
+ if (!saveConjug (curr_conjug, curr_conjug.getType(lfn), xml, identstr) )
+ return false;
+
+ xml.endTag (KV_CON_TYPE, true);
+ }
+
+ xml.writeText(identstr);
+ xml.endTag (KV_CONJUG_GRP, true);
+ xml.writeText(identstr); // indent next element
+ return true;
+}
+
+
+bool kvoctrainDoc::saveArticleKvtMl (XmlWriter &xml)
+
+/*
+ <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 (articles.size() == 0)
+ return true;
+
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_ARTICLE_GRP, false);
+ xml.closeTag(false, true);
+
+ QString def, indef, s;
+ for (int lfn = 0; lfn < QMIN((int) articles.size(), numLangs()); lfn++) {
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_ART_ENTRY, false);
+ if (lfn == 0) {
+ s = getOriginalIdent().stripWhiteSpace();
+ if (s.isEmpty() )
+ s = "original";
+ }
+ else {
+ s = getIdent(lfn).stripWhiteSpace();
+ if (s.isEmpty() ) {
+ s.setNum (lfn);
+ s.insert (0, "translation ");
+ }
+ }
+ xml.addAttribute (KV_LANG, s);
+ xml.closeTag(false, true);
+
+ articles[lfn].female(def, indef);
+ if (!def.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_FD, true, false, false);
+ xml.writeText (def);
+ xml.endTag (KV_ART_FD, true);
+ }
+ if (!indef.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_FI, true, false, false);
+ xml.writeText (indef);
+ xml.endTag (KV_ART_FI, true);
+ }
+
+ articles[lfn].male(def, indef);
+ if (!def.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_MD, true, false, false);
+ xml.writeText (def);
+ xml.endTag (KV_ART_MD, true);
+ }
+ if (!indef.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_MI, true, false, false);
+ xml.writeText (indef);
+ xml.endTag (KV_ART_MI, true);
+ }
+
+ articles[lfn].natural(def, indef);
+ if (!def.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_ND, true, false, false);
+ xml.writeText (def);
+ xml.endTag (KV_ART_ND, true);
+ }
+ if (!indef.isEmpty() ) {
+ xml.writeText(" ");
+ xml.startTag (KV_ART_NI, true, false, false);
+ xml.writeText (indef);
+ xml.endTag (KV_ART_NI, true);
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_ART_ENTRY, true);
+ xml.writeText("");
+ }
+
+ xml.writeText(" ");
+ xml.endTag (KV_ARTICLE_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveOptionsKvtMl (XmlWriter &xml)
+{
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_OPTION_GRP, false);
+ xml.closeTag(false, true);
+
+ xml.writeText(" ");
+ xml.startTag (KV_OPT_SORT, false);
+ xml.addAttribute (KV_BOOL_FLAG, sort_allowed );
+ xml.closeTag (true, true);
+
+ xml.writeText(" ");
+ xml.endTag (KV_OPTION_GRP, true);
+ xml.writeText("\n");
+ return true;
+}
+
+
+bool kvoctrainDoc::saveToKvtMl (QTextStream& os, QString &title) {
+ bool first_expr = true;
+
+ os.setCodec(QTextCodec::codecForName("UTF-8"));
+
+ XmlWriter xml (os);
+ xml.setAutoEndl (false);
+
+ xml.startTag ("!DOCTYPE", false);
+ xml.writeText (" kvtml SYSTEM \"kvoctrain.dtd\"");
+ xml.closeTag (false, true);
+
+ xml.startTag ("!--", false, true, true);
+ xml.writeText ("\nThis is a machine generated file.\n"
+ "Be careful when editing here.\n"
+ "\n"
+ "Short definition:\n"
+ "\n"
+ "lesson lesson group\n"
+ " desc name\n"
+ " %no its index\n"
+ " %query is in query selection\n"
+ " %current is current lesson\n"
+ "type type group\n"
+ " desc name\n"
+ " %no its index\n"
+ "e entry of dictionary\n"
+ " %s is selected\n"
+ " %m lesson member\n"
+ " %t common expression type\n"
+ " o original\n"
+ " %q in query (\"o\" is given, \"t\" is wanted)\n"
+ " %l language code\n"
+ " %r remark\n"
+ " %p pronunciation\n"
+ " %width column width\n"
+ " %t expression type (see QueryManager.h)\n"
+ " %tf false friend from\n"
+ " %ff false friend to\n"
+ " %a antonym\n"
+ " %y synonym\n"
+ " %x example\n"
+ " %u usage label\n"
+ " %h paraphrase\n"
+ " t translation ..\n"
+ " %q in query (\"t\" is given, \"o\" is wanted)\n"
+ " %l language code\n"
+ " %r remark\n"
+ " %p pronunciation\n"
+ " %width column width\n"
+ " %t expression type\n"
+ " %tf false friend from\n"
+ " %ff false friend to\n"
+ " %a antonym\n"
+ " %y synonym\n"
+ " %x example\n"
+ " %u usage label\n"
+ " %h paraphrase\n"
+ "\n"
+ " %d last query date (from;to)\n"
+ " %w dito, compressed and deprecated\n"
+ " %g grade (from;to)\n"
+ " %c count (from;to)\n"
+ " %b bad count (from;to)\n"
+ "\n"
+ "\nValid xml means:\n"
+ " - Close all tags\n"
+ " - Keep proper hierarchy\n"
+ " - All attributes are quoted\n"
+ "--");
+ xml.closeTag (false, true);
+
+ xml.writeText ("\n ");
+ xml.startTag (KV_DOCTYPE, false);
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_ENCODING, (QString)"UTF-8");
+ xml.writeText ("\n ");
+
+ xml.addAttribute (KV_GENERATOR, (QString) "kvoctrain" KVD_VERS_PREFIX KVOCTRAIN_VERSION_STRING);
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_COLS, numLangs() );
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_LINES, numEntries() );
+ if (!title.isEmpty()) {
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_TITLE, getTitle() );
+ doctitle = title;
+ }
+ else if (!doctitle.isEmpty()) {
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_TITLE, doctitle);
+ }
+
+ if (!author.isEmpty()) {
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_AUTHOR, getAuthor() );
+ }
+
+ if (!license.isEmpty()) {
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_LICENSE, getLicense() );
+ }
+
+ if (!doc_remark.isEmpty()) {
+ xml.writeText ("\n ");
+ xml.addAttribute (KV_DOC_REM, getDocRemark() );
+ }
+
+ xml.closeTag (false, true);
+ xml.writeText ("\n");
+
+ if (!saveLessonKvtMl(xml))
+ return false;
+
+ if (!saveArticleKvtMl(xml))
+ return false;
+
+ if (!saveConjugHeader(conjugations, xml))
+ return false;
+
+ if (!saveOptionsKvtMl(xml))
+ return false;
+
+ if (!saveTypeNameKvtMl(xml))
+ return false;
+
+ if (!saveTenseNameKvtMl(xml))
+ return false;
+
+ if (!saveUsageNameKvtMl(xml))
+ return false;
+
+ QString q_org, q_trans;
+ vector<kvoctrainExpr>::const_iterator first = vocabulary.begin ();
+ getQueryLang (q_org, q_trans);
+
+ int ent_no = 0;
+ int ent_percent = (int) vocabulary.size () / 100;
+ float f_ent_percent = (int) vocabulary.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ while (first != vocabulary.end ()) {
+ xml.writeText(" "); // indent entry a bit
+ xml.startTag (KV_EXPR, false);
+
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, ent_no / (int) f_ent_percent);
+
+ if ((*first).getLesson() != 0) { // entry belongs to lesson x
+ QString ls;
+ int lm = (*first).getLesson();
+ if (lm > (int) lesson_descr.size() ) { // should not be
+ kdError() << "index of lesson member too high: " << lm << endl;
+ lm = 0;
+ }
+ ls.setNum (lm);
+ xml.addAttribute (KV_LESS_MEMBER, ls);
+ }
+
+ if ((*first).isInQuery()) { // entry was selected for query
+ xml.addAttribute (KV_SELECTED, (QString) "1");
+ }
+
+ if (!(*first).isActive()) { // entry was inactive
+ xml.addAttribute (KV_INACTIVE, (QString) "1");
+ }
+
+ if ((*first).uniqueType() && !(*first).getType(0).isEmpty()) {
+ xml.addAttribute (KV_EXPRTYPE, (*first).getType(0));
+ }
+
+ xml.closeTag ();
+ xml.startTag (KV_ORG, false);
+ if (first_expr) { // save space, only tell language in first entry
+ QString s;
+ s.setNum (getSizeHint (0));
+ xml.addAttribute (KV_SIZEHINT, s);
+
+ s = getOriginalIdent().stripWhiteSpace();
+ if (s.isEmpty() )
+ s = "original";
+ xml.addAttribute (KV_LANG, s);
+ if (s == q_org)
+ xml.addAttribute (KV_QUERY, (QString) KV_O);
+ else if (s == q_trans)
+ xml.addAttribute (KV_QUERY, (QString) KV_T);
+
+ }
+
+ if (!(*first).getRemark(0).isEmpty() ) {
+ xml.addAttribute (KV_REMARK, (*first).getRemark(0));
+ }
+
+ if (!(*first).getSynonym(0).isEmpty() ) {
+ xml.addAttribute (KV_SYNONYM, (*first).getSynonym(0));
+ }
+
+ if (!(*first).getExample(0).isEmpty() ) {
+ xml.addAttribute (KV_EXAMPLE, (*first).getExample(0));
+ }
+
+ if (!(*first).getUsageLabel(0).isEmpty() ) {
+ xml.addAttribute (KV_USAGE, (*first).getUsageLabel(0));
+ }
+
+ if (!(*first).getParaphrase(0).isEmpty() ) {
+ xml.addAttribute (KV_PARAPHRASE, (*first).getParaphrase(0));
+ }
+
+ if (!(*first).getAntonym(0).isEmpty() ) {
+ xml.addAttribute (KV_ANTONYM, (*first).getAntonym(0));
+ }
+
+ if (!(*first).getPronunce(0).isEmpty() ) {
+ xml.addAttribute (KV_PRONUNCE, (*first).getPronunce(0));
+ }
+
+ if (!(*first).uniqueType() && !(*first).getType(0).isEmpty()) {
+ xml.addAttribute (KV_EXPRTYPE, (*first).getType(0));
+ }
+
+ xml.closeTag ();
+
+ if (!saveMultipleChoice ((*first).getMultipleChoice(0), xml, 1))
+ return false;
+
+ QString s;
+ QString entype = s = (*first).getType(0);
+ int pos = s.find (QM_TYPE_DIV);
+ if (pos >= 0)
+ entype = s.left (pos);
+ else
+ entype = s;
+
+ if ( entype == QM_VERB
+ && (*first).getConjugation(0).numEntries() > 0) {
+ Conjugation conj = (*first).getConjugation(0);
+ if (!saveConjugEntry(conj, xml, 1))
+ return false;
+ }
+ else if (entype == QM_ADJ
+ && !(*first).getComparison(0).isEmpty()) {
+ Comparison comp = (*first).getComparison(0);
+ if (!saveComparison (comp, xml, 1))
+ return false;
+ }
+
+ xml.writeText( (*first).getOriginal());
+ xml.endTag (KV_ORG);
+
+ int trans = 1;
+ while (trans < (int)langs.size()) {
+ xml.startTag (KV_TRANS, false);
+ if (first_expr) { // save space, only tell language in first entry
+ QString s;
+ s.setNum (getSizeHint (trans));
+ xml.addAttribute (KV_SIZEHINT, s);
+
+ s = getIdent(trans).stripWhiteSpace();
+ if (s.isEmpty() ) {
+ s.setNum (trans);
+ s.insert (0, "translation ");
+ }
+ xml.addAttribute (KV_LANG, s);
+ if (s == q_org)
+ xml.addAttribute (KV_QUERY, (QString) KV_O);
+ else if (s == q_trans)
+ xml.addAttribute (KV_QUERY, (QString) KV_T);
+ }
+
+ QString s1, s2;
+
+ if ((*first).getGrade(trans, false) != 0
+ ||(*first).getGrade(trans, true) != 0) {
+ xml.addAttribute (KV_GRADE, (*first).gradeStr(trans, false)
+ +';'
+ +(*first).gradeStr(trans, true));
+ }
+
+ if ((*first).getQueryCount(trans, false) != 0
+ ||(*first).getQueryCount(trans, true) != 0) {
+ s1.setNum((*first).getQueryCount(trans, false));
+ s2.setNum((*first).getQueryCount(trans, true));
+ xml.addAttribute (KV_COUNT, s1 +';' +s2);
+ }
+
+ if ((*first).getBadCount(trans, false) != 0
+ ||(*first).getBadCount(trans, true) != 0) {
+ s1.setNum((*first).getBadCount(trans, false));
+ s2.setNum((*first).getBadCount(trans, true));
+ xml.addAttribute (KV_BAD, s1 +';' +s2);
+ }
+
+ if ((*first).getQueryDate(trans, false) != 0
+ ||(*first).getQueryDate(trans, true) != 0) {
+ s1.setNum((*first).getQueryDate(trans, false));
+ s2.setNum((*first).getQueryDate(trans, true));
+ xml.addAttribute (KV_DATE, s1 +';' +s2);
+ }
+
+ if (!(*first).getRemark(trans).isEmpty() ) {
+ xml.addAttribute (KV_REMARK, (*first).getRemark(trans));
+ }
+
+ if (!(*first).getFauxAmi(trans, false).isEmpty() ) {
+ xml.addAttribute (KV_FAUX_AMI_F, (*first).getFauxAmi(trans, false));
+ }
+
+ if (!(*first).getFauxAmi(trans, true).isEmpty() ) {
+ xml.addAttribute (KV_FAUX_AMI_T, (*first).getFauxAmi(trans, true));
+ }
+
+ if (!(*first).getSynonym(trans).isEmpty() ) {
+ xml.addAttribute (KV_SYNONYM, (*first).getSynonym(trans));
+ }
+
+ if (!(*first).getExample(trans).isEmpty() ) {
+ xml.addAttribute (KV_EXAMPLE, (*first).getExample(trans));
+ }
+
+ if (!(*first).getUsageLabel(trans).isEmpty() ) {
+ xml.addAttribute (KV_USAGE, (*first).getUsageLabel(trans));
+ }
+
+ if (!(*first).getParaphrase(trans).isEmpty() ) {
+ xml.addAttribute (KV_PARAPHRASE, (*first).getParaphrase(trans));
+ }
+
+ if (!(*first).getAntonym(trans).isEmpty() ) {
+ xml.addAttribute (KV_ANTONYM, (*first).getAntonym(trans));
+ }
+
+ if (!(*first).getPronunce(trans).isEmpty() ) {
+ xml.addAttribute (KV_PRONUNCE, (*first).getPronunce(trans));
+ }
+
+ if (!(*first).uniqueType() && !(*first).getType(trans).isEmpty()) {
+ xml.addAttribute (KV_EXPRTYPE, (*first).getType(trans));
+ }
+
+ xml.closeTag ();
+
+ // only save conjugations when type == verb
+
+ if (!saveMultipleChoice ((*first).getMultipleChoice(trans), xml, 1))
+ return false;
+
+ QString s;
+ QString entype = s = (*first).getType(0);
+ int pos = s.find (QM_TYPE_DIV);
+ if (pos >= 0)
+ entype = s.left (pos);
+ else
+ entype = s;
+
+ if ( entype == QM_VERB
+ && (*first).getConjugation(trans).numEntries() > 0) {
+ Conjugation conj = (*first).getConjugation(trans);
+ if (!saveConjugEntry(conj, xml, 1+trans))
+ return false;
+ }
+
+ if ( entype == QM_ADJ
+ && !(*first).getComparison(trans).isEmpty()) {
+ Comparison comp = (*first).getComparison(trans);
+ if (!saveComparison (comp, xml, 1+trans))
+ return false;
+ }
+
+ xml.writeText((*first).getTranslation(trans));
+ xml.endTag (KV_TRANS);
+ trans++;
+ }
+ xml.endTag (KV_EXPR, true);
+ first++;
+ first_expr = false;
+ }
+ xml.endTag (KV_DOCTYPE, true);
+
+ setModified (false);
+ return os.device()->status() == IO_Ok;
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvoctraincore.h b/kvoctrain/kvoctrain/kvt-core/kvoctraincore.h
new file mode 100644
index 00000000..365882c6
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvoctraincore.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+
+ common #defines for kvoctrain core
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Nov 25 10:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 KVOCTRAINCORE_H
+#define KVOCTRAINCORE_H
+
+///////////////////////////////////////////////////////////////////
+// Config file entries
+
+#define CFG_MODIFIED "Modified"
+#define CFG_FILENAME "Filename"
+#define CFG_TITLE "Title"
+
+#define CFG_APPEARANCE "Appearance"
+#define CFG_XMLOPS_R "XmlOps_R"
+#define CFG_XMLOPS_W "XmlOps_W"
+#define CFG_XMLOPS_S "XmlOps_S"
+#define CFG_IPA_FSIZE "IPAFontSize"
+#define CFG_IPA_FFAMILY "IPAFontFamily"
+#define CFG_FSIZE "FontSize"
+#define CFG_FFAMILY "FontFamily"
+#define CFG_FCHARSET "FontCharSet"
+#define CFG_SHOW_TOOLBAR "ShowToolbar"
+#define CFG_SHOW_STATUSBAR "ShowStatusbar"
+#define CFG_TOOLBAR_POS "ToolBar_Pos"
+
+#define CFG_GENERAL "General"
+#define CFG_LASTFILE "LastFile"
+#define CFG_PASTEORDER "PasteOrder"
+#define CFG_ENTRIESLESSON "EntriesPerLesson"
+#define CFG_HEADER_RESIZER "HeaderResizer"
+#define CFG_AUTOSAVEOPT "AutoSaveOptions"
+#define CFG_ENTRYAUTOAPPLY "EntryAutomaticApply"
+
+#define CFG_LESSONSIZE "LessonSize"
+
+#define CFG_QUERYPROP "QueryProperties"
+#define CFG_QUERYMODE "QueryMode"
+#define CFG_DEFTRANS "DefaultTranslation"
+#define CFG_DEFORG "DefaultOriginal"
+
+#define CFG_NUMLANGSET "NumLangSet"
+#define CFG_L_SHORT "ShortId"
+#define CFG_L_SHORT2 "Short2Id"
+# define CFG_L_LANG "LongId_KDE2"
+# define CFG_L_PIXMAP "Pixmap_KDE2"
+#define CFG_L_KBLAYOUT "KeyboardLayout"
+#define CFG_L_FONT "Font"
+#define CFG_L_STDFONT "SpecialFont"
+
+#define CFG_QUERYMANAG "QueryManager"
+#define CFG_QM_DATE_ITEM "DateItem"
+#define CFG_QM_DATE_COMP "DateComp"
+#define CFG_QM_QUERY_ITEM "QueryItem"
+#define CFG_QM_QUERY_COMP "QueryComp"
+#define CFG_QM_BAD_ITEM "BadItem"
+#define CFG_QM_BAD_COMP "BadComp"
+#define CFG_QM_TYPE_ITEM "TypeItem"
+#define CFG_QM_TYPE_COMP "TypeComp"
+#define CFG_QM_GRADE_ITEM "GradeItem"
+#define CFG_QM_GRADE_COMP "GradeComp"
+#define CFG_QM_LESSON_ITEM "LessonItem"
+#define CFG_QM_LESSON_COMP "LessonComp"
+#define CFG_QM_BLOCK_ITEM "BlockItem"
+#define CFG_QM_EXPIRE_ITEM "ExpireItem"
+
+#define CFG_QUERY_PRESETTING "QueryPreSettings"
+#define CFG_QP_NUM "NumPreSetting"
+#define CFG_QP_NAME "Name"
+#define CFG_QP_THRESH "Threshhold"
+#define CFG_QP_BLOCK "Blocking"
+#define CFG_QP_QUERY "Query"
+
+#define KVTML_EXT "kvtml"
+#define VT5_LEX_EXT "lex"
+#define QVOCAB_EXT "qvo"
+#define VCB_EXT "vocab"
+#define KVL_EXT "vl"
+#define CSV_EXT "csv"
+#define TXT_EXT "txt"
+
+#define VCB_SEPARATOR "__"
+
+#define MAX_LESSON 25
+#define THRESH_LESSON KV_MIN_GRADE
+#define MAX_LANGSET 100
+
+#define KVTLIB_DEBUG_AREA 12003
+#define KVOCTRAIN_VERSION_STRING "0.8.3" // maybe split KVTLIB_VERSION/KVAPP_VERSION
+
+#endif // KVOCTRAINCORE_H
diff --git a/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.cpp b/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.cpp
new file mode 100644
index 00000000..f2701bed
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.cpp
@@ -0,0 +1,1061 @@
+/***************************************************************************
+
+
+ maintain a kvoctrain document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+ email : kvoctrain@ewald-arnold.de
+
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "kvoctraindoc.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+#include <qfileinfo.h>
+#include <qregexp.h>
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+using namespace std;
+
+#include <iostream>
+
+#include <float.h>
+
+#include "kvoctraincore.h"
+#include "prefs.h"
+
+//********************************************************
+// kvoctrainDoc
+//********************************************************
+
+void kvoctrainDoc::setVersion (const QString & vers)
+{
+ doc_version = vers;
+}
+
+
+void kvoctrainDoc::getVersion(int &, int &, int &)
+{
+}
+
+
+void kvoctrainDoc::Init ()
+{
+
+ setVersion (QString::fromUtf8(KVOCTRAIN_VERSION_STRING));
+ lesson_descr.clear();
+ type_descr.clear();
+ tense_descr.clear();
+ langs.clear();
+ extraSizehints.clear();
+ sizehints.clear();
+ vocabulary.clear();
+ dirty = false;
+ sort_allowed = true;
+ unknown_attr = false;
+ unknown_elem = false;
+ sort_lesson = false;
+ for (int i = 0; i < (int) langs.size(); i++)
+ sort_lang.push_back(false);
+ setCurrentLesson (0);
+ queryorg = "";
+ querytrans = "";
+ doc_url.setFileName(i18n("Untitled"));
+ doctitle = "";
+ author = "";
+}
+
+
+kvoctrainDoc::kvoctrainDoc(QObject *parent, const KURL& url)
+{
+ Init();
+ if (!url.isEmpty())
+ doc_url = url;
+
+ connect( this, SIGNAL(progressChanged(kvoctrainDoc*,int)), parent, SLOT(slotProgress(kvoctrainDoc*,int)) );
+
+ QString tmpfile;
+ if (KIO::NetAccess::download( url, tmpfile, 0 ))
+ {
+ QFile f(tmpfile);
+ if (!f.open(IO_ReadOnly))
+ {
+ KMessageBox::error(0, i18n("<qt>Cannot open file<br><b>%1</b></qt>").arg(url.path()));
+ return;
+ }
+
+ FileType ft = detectFT(tmpfile);
+
+ bool read = false;
+ while (!read) {
+
+ QApplication::setOverrideCursor( waitCursor );
+ switch (ft) {
+ case kvtml:
+ {
+ QTextStream is (&f);
+ read = loadFromKvtMl (is);
+ }
+ break;
+
+ case vt_lex:
+ {
+ QTextStream is (&f);
+ read = loadFromLex (is);
+ }
+ break;
+
+ case vt_vcb:
+ {
+ QTextStream is (&f);
+ read = loadFromVcb (is);
+ }
+ break;
+
+ case vt_voc:
+ {
+ QTextStream is (&f);
+ read = loadFromVoc(is);
+ }
+ break;
+
+ case csv:
+ {
+ QTextStream is(&f);
+ read = loadFromCsv(is);
+ }
+ break;
+
+ default:
+ {
+ QTextStream is (&f);
+ read = loadFromKvtMl (is);
+ }
+ }
+
+ QApplication::restoreOverrideCursor();
+
+ if (!read) {
+ if (unknown_attr || unknown_elem ) {
+ Init();
+ return;
+ }
+ QString format = i18n("Could not load \"%1\"\nDo you want to try again?");
+ QString msg = format.arg(url.path());
+ int result = KMessageBox::warningContinueCancel(0, msg,
+ kapp->makeStdCaption(i18n("I/O Failure")),
+ i18n("&Retry"));
+ if ( result == KMessageBox::Cancel ) {
+ Init();
+ return;
+ }
+ }
+ }
+ f.close();
+ KIO::NetAccess::removeTempFile( tmpfile );
+ }
+}
+
+
+kvoctrainDoc::~kvoctrainDoc()
+{
+}
+
+
+bool kvoctrainDoc::saveAs (QObject *parent, const KURL & url, QString title, FileType ft)
+{
+ connect( this, SIGNAL(progressChanged(kvoctrainDoc*,int)), parent, SLOT(slotProgress(kvoctrainDoc*,int)) );
+
+ KURL tmp (url);
+ if (title == i18n("Untitled"))
+ title = QString::null;
+ if (title == doc_url.fileName())
+ title = QString::null;
+
+ if (ft == automatic)
+ {
+ if (tmp.path().right(strlen("." KVTML_EXT)) == "." KVTML_EXT)
+ ft = kvtml;
+ else if (tmp.path().right(strlen("." VT5_LEX_EXT)) == "." VT5_LEX_EXT)
+ ft = vt_lex;
+ else if (tmp.path().right(strlen("." VCB_EXT)) == "." VCB_EXT)
+ ft = vt_vcb;
+ else if (tmp.path().right(strlen("." CSV_EXT)) == "." CSV_EXT)
+ ft = csv;
+ else
+ {
+ tmp.setFileName(tmp.path() + "." KVTML_EXT);
+ ft = kvtml;
+ }
+ }
+
+ bool saved = false;
+ while (!saved)
+ {
+
+ QFile f(tmp.path());
+
+ if (!f.open(IO_WriteOnly))
+ {
+ KMessageBox::error(0, i18n("<qt>Cannot write to file<br><b>%1</b></qt>").arg(tmp.path()));
+ return false;
+ }
+
+ QApplication::setOverrideCursor( waitCursor );
+ switch (ft) {
+ case kvtml: {
+ QTextStream os( &f ); // serialize using f
+ saved = saveToKvtMl(os, title);
+ }
+ break;
+
+ case vt_lex: {
+ QTextStream os( &f ); // serialize using f
+ saved = saveToLex(os, title);
+ }
+ break;
+
+ case vt_vcb: {
+ QTextStream os( &f ); // serialize using f
+ saved = saveToVcb(os, title);
+ }
+ break;
+
+ case csv: {
+ QTextStream os( &f ); // serialize using f
+ saved = saveToCsv(os, title);
+ }
+ break;
+
+ default: {
+ kdError() << "kvcotrainDoc::saveAs(): unknown filetype" << endl;
+ }
+ break;
+ }
+ f.close();
+ QApplication::restoreOverrideCursor();
+
+ if (!saved) {
+ QString format = i18n("Could not save \"%1\"\nDo you want to try again?");
+ QString msg = format.arg(tmp.path());
+ int result = KMessageBox::warningContinueCancel(0, msg,
+ kapp->makeStdCaption(i18n("I/O Failure")),
+ i18n("&Retry"));
+ if ( result == KMessageBox::Cancel ) return false;
+ }
+ }
+ doc_url = tmp;
+ dirty = false;
+ emit docModified(false);
+ return true;
+}
+
+
+kvoctrainExpr *kvoctrainDoc::getEntry(int index)
+{
+ if (index < 0 || index >= (int)vocabulary.size() )
+ return 0;
+ else
+ return &vocabulary[index];
+}
+
+
+void kvoctrainDoc::removeEntry(int index)
+{
+ if (index >= 0 && index < (int)vocabulary.size() )
+ vocabulary.erase (vocabulary.begin() + index);
+}
+
+
+int kvoctrainDoc::findIdent (const QString &lang) const
+{
+ vector<QString>::const_iterator first = langs.begin();
+ int count = 0;
+ while (first != langs.end()) {
+ if ( *first == lang)
+ return count;
+ first++;
+ count++;
+ }
+ return -1;
+}
+
+
+QString kvoctrainDoc::getIdent (int index) const
+{
+ if (index >= (int)langs.size() || index < 1 )
+ return "";
+ else
+ return langs[index];
+}
+
+
+void kvoctrainDoc::setIdent (int idx, const QString &id)
+{
+ if (idx < (int)langs.size() && idx >= 1 ) {
+ langs[idx] = id;
+ }
+}
+
+
+QString kvoctrainDoc::getTypeName (int index) const
+{
+ if (index >= (int)type_descr.size())
+ return "";
+ else
+ return type_descr[index];
+}
+
+
+void kvoctrainDoc::setTypeName (int idx, QString &id)
+{
+ if (idx >= (int)type_descr.size())
+ for (int i = (int)type_descr.size(); i <= idx; i++)
+ type_descr.push_back ("");
+
+ type_descr[idx] = id;
+}
+
+
+QString kvoctrainDoc::getTenseName (int index) const
+{
+ if (index >= (int)tense_descr.size())
+ return "";
+ else
+ return tense_descr[index];
+}
+
+
+void kvoctrainDoc::setTenseName (int idx, QString &id)
+{
+ if (idx >= (int)tense_descr.size())
+ for (int i = (int)tense_descr.size(); i <= idx; i++)
+ tense_descr.push_back ("");
+
+ tense_descr[idx] = id;
+}
+
+
+QString kvoctrainDoc::getUsageName (int index) const
+{
+ if (index >= (int)usage_descr.size())
+ return "";
+ else
+ return usage_descr[index];
+}
+
+
+void kvoctrainDoc::setUsageName (int idx, QString &id)
+{
+ if (idx >= (int)usage_descr.size())
+ for (int i = (int)usage_descr.size(); i <= idx; i++)
+ usage_descr.push_back ("");
+
+ usage_descr[idx] = id;
+}
+
+
+void kvoctrainDoc::setConjugation (int idx, const Conjugation &con)
+{
+ if ( idx < 0) return;
+
+ // extend conjugation with empty elements
+ if ((int)conjugations.size() <= idx )
+ for (int i = conjugations.size(); i < idx+1; i++)
+ conjugations.push_back (Conjugation());
+
+ conjugations[idx] = con;
+}
+
+
+Conjugation kvoctrainDoc::getConjugation (int idx) const
+{
+ if (idx >= (int)conjugations.size() || idx < 0) {
+ return Conjugation();
+ }
+ else {
+ return conjugations[idx];
+ }
+}
+
+
+void kvoctrainDoc::setArticle (int idx, const Article &art)
+{
+ if ( idx < 0) return;
+
+ // extend conjugation with empty elements
+ if ((int)articles.size() <= idx )
+ for (int i = articles.size(); i < idx+1; i++)
+ articles.push_back (Article());
+
+ articles[idx] = art;
+}
+
+
+Article kvoctrainDoc::getArticle (int idx) const
+{
+ if (idx >= (int)articles.size() || idx < 0) {
+ return Article();
+ }
+ else {
+ return articles[idx];
+ }
+}
+
+
+int kvoctrainDoc::getSizeHint (int idx) const
+{
+ if (idx < 0) {
+ idx = -idx;
+ if (idx >= (int)extraSizehints.size() )
+ return 80; // make a good guess about column size
+ else {
+// cout << "gsh " << idx << " " << extraSizehints[idx] << endl;
+ return extraSizehints[idx];
+ }
+ }
+ else {
+ if (idx >= (int)sizehints.size() )
+ return 150; // make a good guess about column size
+ else {
+// cout << "gsh " << idx << " " << sizehints[idx] << endl;
+ return sizehints[idx];
+ }
+ }
+}
+
+
+void kvoctrainDoc::setSizeHint (int idx, const int width)
+{
+// cout << "ssh " << idx << " " << width << endl;
+ if (idx < 0) {
+ idx = -idx;
+ if (idx >= (int)extraSizehints.size()) {
+ for (int i = (int)extraSizehints.size(); i <= idx; i++)
+ extraSizehints.push_back (80);
+ }
+ extraSizehints[idx] = width;
+
+ }
+ else {
+ if (idx >= (int)sizehints.size()) {
+ for (int i = (int)sizehints.size(); i <= idx; i++)
+ sizehints.push_back (150);
+ }
+ sizehints[idx] = width;
+ }
+}
+
+
+class eraseTrans : public unary_function<kvoctrainExpr, void>
+{
+
+public:
+
+ eraseTrans (int idx)
+ : index (idx) {}
+
+ void operator() (kvoctrainExpr& x) const
+ {
+ x.removeTranslation(index);
+ }
+
+ private:
+ int index;
+};
+
+
+void kvoctrainDoc::removeIdent (int index)
+{
+ if (index < (int)langs.size() && index >= 1 ) {
+ langs.erase(langs.begin() + index);
+ for_each (vocabulary.begin(), vocabulary.end(), eraseTrans(index));
+ }
+}
+
+
+QString kvoctrainDoc::getOriginalIdent () const
+{
+ if (langs.size() > 0)
+ return langs[0];
+ else
+ return "";
+}
+
+
+void kvoctrainDoc::setOriginalIdent (const QString &id)
+{
+ if (langs.size() > 0) {
+ langs[0] = id;
+ }
+}
+
+
+class sortByOrg : public binary_function<kvoctrainExpr, kvoctrainExpr, bool>
+{
+
+public:
+
+ sortByOrg (bool _dir)
+ : dir (_dir) {}
+
+ bool operator() (const kvoctrainExpr& x, const kvoctrainExpr& y) const
+ {
+ return
+ !dir
+ ? (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) < 0)
+ : (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) > 0);
+ }
+
+ private:
+ bool dir;
+};
+
+
+class sortByLessonAndOrg_alpha
+ : public binary_function<kvoctrainExpr, kvoctrainExpr, bool>
+{
+
+public:
+
+ sortByLessonAndOrg_alpha (bool _dir, kvoctrainDoc &_doc)
+ : dir (_dir), doc(_doc) {}
+
+ bool operator() (const kvoctrainExpr& x, const kvoctrainExpr& y) const
+ {
+ if (x.getLesson() != y.getLesson() )
+ return
+ !dir
+ ? (QString::compare(doc.getLessonDescr(x.getLesson()).upper(),
+ doc.getLessonDescr(y.getLesson()).upper() ) < 0)
+ : (QString::compare(doc.getLessonDescr(x.getLesson()).upper(),
+ doc.getLessonDescr(y.getLesson()).upper() ) > 0);
+ else
+ return
+ !dir
+ ? (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) < 0)
+ : (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) > 0);
+ }
+
+ private:
+ bool dir;
+ kvoctrainDoc &doc;
+};
+
+
+class sortByLessonAndOrg_index
+ : public binary_function<kvoctrainExpr, kvoctrainExpr, bool>
+{
+
+public:
+
+ sortByLessonAndOrg_index (bool _dir, kvoctrainDoc &_doc)
+ : dir (_dir), doc(_doc) {}
+
+ bool operator() (const kvoctrainExpr& x, const kvoctrainExpr& y) const
+ {
+ if (x.getLesson() != y.getLesson() )
+ return
+ !dir
+ ? x.getLesson() < y.getLesson()
+ : y.getLesson() < x.getLesson();
+ else
+ return
+ !dir
+ ? (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) < 0)
+ : (QString::compare(x.getOriginal().upper(),
+ y.getOriginal().upper() ) > 0);
+ }
+
+ private:
+ bool dir;
+ kvoctrainDoc &doc;
+};
+
+
+class sortByTrans : public binary_function<kvoctrainExpr, kvoctrainExpr, bool>
+{
+
+public:
+
+ sortByTrans (int i, bool _dir)
+ : index(i), dir (_dir) {}
+
+ bool operator() (const kvoctrainExpr& x, const kvoctrainExpr& y) const
+ {
+ return
+ !dir
+ ? (QString::compare(x.getTranslation(index).upper(),
+ y.getTranslation(index).upper() ) < 0)
+ : (QString::compare(x.getTranslation(index).upper(),
+ y.getTranslation(index).upper() ) > 0);
+ }
+
+ private:
+ int index;
+ bool dir;
+};
+
+
+bool kvoctrainDoc::sort (int index)
+{
+ if (!sort_allowed)
+ return false;
+
+ if (index >= numLangs())
+ return false;
+
+ if (sort_lang.size() < langs.size())
+ for (int i = sort_lang.size(); i < (int) langs.size(); i++)
+ sort_lang.push_back(false);
+
+ if (index == 0)
+ std::sort (vocabulary.begin(), vocabulary.end(), sortByOrg(sort_lang[0]));
+ else
+ std::sort (vocabulary.begin(), vocabulary.end(), sortByTrans(index, sort_lang[index]));
+ sort_lang[index] = !sort_lang[index];
+ return sort_lang[index];
+}
+
+
+bool kvoctrainDoc::sortByLesson_alpha ()
+{
+ if (!sort_allowed)
+ return false;
+
+ std::sort (vocabulary.begin(), vocabulary.end(), sortByLessonAndOrg_alpha(sort_lesson, *this ));
+ sort_lesson = !sort_lesson;
+ return sort_lesson;
+}
+
+
+bool kvoctrainDoc::sortByLesson_index ()
+{
+ if (!sort_allowed)
+ return false;
+
+ if (sort_lang.size() < langs.size())
+ for (int i = sort_lang.size(); i < (int) langs.size(); i++)
+ sort_lang.push_back(false);
+
+ std::sort (vocabulary.begin(), vocabulary.end(), sortByLessonAndOrg_index(sort_lesson, *this ));
+ sort_lesson = !sort_lesson;
+ sort_lang[0] = sort_lesson;
+ return sort_lesson;
+}
+
+
+class resetAll : public unary_function<kvoctrainExpr, void>
+{
+
+public:
+
+ resetAll (int less)
+ : lesson(less) {}
+
+ void operator() (kvoctrainExpr& x)
+ {
+ for (int i = 0; i <= x.numTranslations(); i++) {
+ if (lesson == 0 || lesson == x.getLesson() ) {
+ x.setGrade(i, KV_NORM_GRADE, false);
+ x.setGrade(i, KV_NORM_GRADE, true);
+ x.setQueryCount (i, 0, true);
+ x.setQueryCount (i, 0, false);
+ x.setBadCount (i, 0, true);
+ x.setBadCount (i, 0, false);
+ x.setQueryDate (i, 0, true);
+ x.setQueryDate (i, 0, false);
+ }
+ }
+ }
+ private:
+ int lesson;
+};
+
+
+class resetOne : public unary_function<kvoctrainExpr, void>
+{
+
+public:
+
+ resetOne (int idx, int less)
+ : index (idx), lesson(less) {}
+
+ void operator() (kvoctrainExpr& x)
+ {
+ if (lesson == 0 || lesson == x.getLesson() ) {
+ x.setGrade(index, KV_NORM_GRADE, false);
+ x.setGrade(index, KV_NORM_GRADE, true);
+ x.setQueryCount (index, 0, true);
+ x.setQueryCount (index, 0, false);
+ x.setBadCount (index, 0, true);
+ x.setBadCount (index, 0, false);
+ x.setQueryDate (index, 0, true);
+ x.setQueryDate (index, 0, false);
+ }
+ }
+
+ private:
+ int index;
+ int lesson;
+};
+
+
+void kvoctrainDoc::resetEntry (int index, int lesson)
+{
+ if (index < 0)
+ for_each (vocabulary.begin(), vocabulary.end(), resetAll(lesson) );
+ else
+ for_each (vocabulary.begin(), vocabulary.end(), resetOne(index, lesson) );
+}
+
+
+QString kvoctrainDoc::getLessonDescr(int idx) const
+{
+ if (idx == 0)
+ return i18n("<no lesson>");
+
+ if (idx <= 0 || idx > (int) lesson_descr.size() )
+ return "";
+
+ return lesson_descr[idx-1];
+}
+
+
+vector<int> kvoctrainDoc::getLessonsInQuery() const
+{
+ vector<int> iqvec;
+ for (unsigned i = 0; i < lessons_in_query.size(); i++)
+ if (lessons_in_query[i]) {
+ iqvec.push_back(i+1); // Offset <no lesson>
+// cout << "getliq: " << i+1 << endl;
+ }
+ return iqvec;
+}
+
+
+void kvoctrainDoc::setLessonsInQuery(vector<int> lesson_iq)
+{
+ lessons_in_query.clear();
+ for (unsigned i = 0; i < lesson_descr.size(); i++)
+ lessons_in_query.push_back(false);
+
+ for (unsigned i = 0; i < lesson_iq.size(); i++)
+ if (lesson_iq[i] <= (int) lessons_in_query.size() ) {
+ lessons_in_query[lesson_iq[i]-1] = true; // Offset <no lesson>
+// cout << "setliq: " << lesson_iq[i] << " " << i << endl;
+ }
+}
+
+
+QString kvoctrainDoc::getTitle() const
+{
+ if (doctitle.isEmpty())
+ return doc_url.fileName();
+ else
+ return doctitle;
+}
+
+
+QString kvoctrainDoc::getAuthor() const
+{
+ return author;
+}
+
+
+QString kvoctrainDoc::getLicense() const
+{
+ return license;
+}
+
+
+QString kvoctrainDoc::getDocRemark() const
+{
+ return doc_remark;
+}
+
+
+void kvoctrainDoc::setTitle(const QString & title)
+{
+ doctitle = title.stripWhiteSpace();
+}
+
+
+void kvoctrainDoc::setAuthor(const QString & s)
+{
+ author = s.stripWhiteSpace();
+}
+
+
+void kvoctrainDoc::setLicense(const QString & s)
+{
+ license = s.stripWhiteSpace();
+}
+
+
+void kvoctrainDoc::setDocRemark(const QString & s)
+{
+ doc_remark = s.stripWhiteSpace();
+}
+
+
+int kvoctrainDoc::search(QString substr, int id,
+ int first, int last,
+ bool word_start,
+ bool)
+{
+ if (last >= numEntries()
+ || last < 0 )
+ last = numEntries();
+
+ if (first < 0)
+ first = 0;
+
+ for (int i = first; i < last; i++) {
+ if (word_start) {
+
+ for (id = 0; id <= numLangs(); id++)
+ {
+ if (id == 0)
+ {
+ if (getEntry(i)->getOriginal().find (substr, 0, false) == 0) // case insensitive
+ return i;
+ } else {
+ if (getEntry(i)->getTranslation(id).find (substr, 0, false) == 0) // case insensitive
+ return i;
+ }
+ }
+ }
+ else {
+ for (id = 0; id <= numLangs(); id++){
+
+ if (id == 0)
+ {
+ if (getEntry(i)->getOriginal().find (substr, 0, false) > -1) // case insensitive
+ return i;
+ } else {
+ if (getEntry(i)->getTranslation(id).find (substr, 0, false) > -1) // case insensitive
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+#define _OFFSET 0x40
+#define _BITMASK 0x3F
+#define _BITUSED 6
+
+QString kvoctrainDoc::compressDate(unsigned long l) const
+{
+ if (l == 0)
+ return "";
+
+ QString res;
+ if (l <= KVD_ZERO_TIME)
+ l = 1;
+ else
+ l -= KVD_ZERO_TIME;
+ while (l != 0) {
+ char c = _OFFSET + (l & _BITMASK);
+ res.insert (0, c);
+ l >>= _BITUSED;
+ }
+ return res;
+}
+
+
+unsigned long kvoctrainDoc::decompressDate(QString s) const
+{
+ if (s.isEmpty())
+ return 0;
+
+ long res = 0;
+ unsigned incr = 0;
+ for (int i = s.length()-1; i >= 0; i--) {
+ char c = s.local8Bit()[i];
+ res += ((c - _OFFSET) & _BITMASK) << incr ;
+ incr += _BITUSED;
+ }
+ return res > 48 ? res+KVD_ZERO_TIME : 0; // early bug with "0"
+}
+
+
+kvoctrainDoc::FileType kvoctrainDoc::detectFT(const QString &filename)
+{
+ QFile f( filename );
+ if (!f.open( IO_ReadOnly ))
+ return csv;
+
+ QDataStream is( &f );
+
+ Q_INT8 c1, c2, c3, c4, c5;
+ is >> c1
+ >> c2
+ >> c3
+ >> c4
+ >> c5; // guess filetype by first x bytes
+
+ QTextStream ts (&f);
+ QString line;
+ line = ts.readLine();
+ line.insert (0, c5);
+ line.insert (0, c4);
+ line.insert (0, c3);
+ line.insert (0, c2);
+ line.insert (0, c1);
+ f.close();
+
+ bool stat = is.device()->status();
+ if (stat != IO_Ok)
+ return kvd_none;
+ if (c1 == '<' && c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l')
+ return kvtml;
+
+ if (line.find (VCB_SEPARATOR) >= 0)
+ return vt_vcb;
+
+ if (line == LEX_IDENT_50)
+ return vt_lex;
+
+ if (c1 == '"' && (line.contains('"') == 1 || line.contains(QRegExp("\",[0-9]"))))
+ return vt_voc;
+
+ return csv;
+}
+
+
+class expRef {
+
+public:
+
+ expRef (kvoctrainExpr *_exp, int _idx)
+ {
+ idx = _idx;
+ exp = _exp;
+ }
+
+ bool operator< (const expRef& y) const
+ {
+ QString s1 = exp->getOriginal();
+ QString s2 = y.exp->getOriginal();
+ int cmp = QString::compare(s1.upper(), s2.upper());
+ if (cmp != 0)
+ return cmp < 0;
+
+ for (int i = 1; i < (int) exp->numTranslations(); i++) {
+
+ s1 = exp->getTranslation(i);
+ s2 = y.exp->getTranslation(i);
+ cmp = QString::compare(s1.upper(), s2.upper() );
+ if (cmp != 0)
+ return cmp < 0;
+ }
+ return cmp < 0;
+ }
+
+ int idx;
+ kvoctrainExpr *exp;
+};
+
+
+int kvoctrainDoc::cleanUp()
+{
+ int count = 0;
+ kvoctrainExpr *kve1, *kve2;
+ vector<expRef> shadow;
+ vector<int> to_delete;
+
+ for (int i = 0; i < (int) vocabulary.size(); i++)
+ shadow.push_back (expRef (getEntry(i), i));
+ std::sort(shadow.begin(), shadow.end());
+
+#ifdef CLEAN_BUG
+ ofstream sso ("shadow.out");
+ for (int i = shadow.size()-1; i > 0; i--) {
+ kve1 = shadow[i].exp;
+ sso << kve1->getOriginal() << " ";
+ for (int l = 1; l < (int) numLangs(); l++ )
+ sso << kve1->getTranslation(l) << " ";
+ sso << endl;
+ }
+#endif
+
+ int ent_no = 0;
+ int ent_percent = vocabulary.size () / 100;
+ float f_ent_percent = vocabulary.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ for (int i = shadow.size()-1; i > 0; i--) {
+ kve1 = shadow[i].exp;
+ kve2 = shadow[i-1].exp;
+
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, (int)((ent_no / f_ent_percent) / 2.0));
+
+ bool equal = true;
+ if (kve1->getOriginal() == kve2->getOriginal() ) {
+ for (int l = 1; equal && l < (int) numLangs(); l++ )
+ if (kve1->getTranslation(l) != kve2->getTranslation(l))
+ equal = false;
+
+ if (equal) {
+ to_delete.push_back(shadow[i-1].idx);
+ count++;
+ }
+ }
+ }
+
+ // removing might take very long
+ ent_no = 0;
+ ent_percent = to_delete.size () / 100;
+ f_ent_percent = to_delete.size () / 100.0;
+ emit progressChanged(this, 0);
+
+ std::sort (to_delete.begin(), to_delete.end() );
+ for (int i = (int) to_delete.size()-1; i >= 0; i--) {
+ ent_no++;
+ if (ent_percent != 0 && (ent_no % ent_percent) == 0 )
+ emit progressChanged(this, (int)(50 + ent_no / f_ent_percent / 2.0));
+#ifdef CLEAN_BUG
+ sso << getEntry(to_delete[i])->getOriginal() << endl;
+#endif
+ removeEntry (to_delete[i]);
+ setModified();
+ }
+
+ return count;
+}
+#include "kvoctraindoc.moc"
diff --git a/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.h b/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.h
new file mode 100644
index 00000000..d0defb5a
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvoctraindoc.h
@@ -0,0 +1,747 @@
+/***************************************************************************
+
+ maintain a kvoctrain document
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 KVOCTRAINDOC_H
+#define KVOCTRAINDOC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qobject.h>
+
+#include <kurl.h>
+
+#include "kvoctrainexpr.h"
+
+#include "kvt-xml/XmlReader.h"
+#include "kvt-xml/XmlWriter.h"
+
+#define KVD_ZERO_TIME 934329599 // 1999-08-10 23:59:59, never change
+#define KVD_VERS_PREFIX " v" // kvoctrain v0.1.0
+
+/** XML tags and attribute names */
+
+#define KV_DOCTYPE "kvtml" // doctype
+#define KV_TITLE "title" // doc title
+#define KV_AUTHOR "author" // doc author
+#define KV_LICENSE "license" // doc license
+#define KV_DOC_REM "remark" // doc remark
+#define KV_LINES "lines" // entries
+#define KV_GENERATOR "generator" // who generated the doc
+#define KV_COLS "cols" // columns
+#define KV_ENCODING "encoding" // document encoding (obsolete!)
+
+#define KV_EXPR "e" // entry for one expression
+#define KV_ORG "o" // original expression in specified language
+#define KV_TRANS "t" // translated expression in specified language
+#define KV_LANG "l" // language: en, de, it, fr ...
+#define KV_QUERY "q" // query: org or translation
+#define KV_O "o" // org
+#define KV_T "t" // translation
+#define KV_GRADE "g" // grade of knowledge: 0=well known, x=not known for x times
+#define KV_LESS_MEMBER "m" // member of lesson 1 .. x
+#define KV_COUNT "c" // number of times queried
+#define KV_SIZEHINT "width" // recommended column width
+#define KV_CHARSET "charset" // recommended charset (obsolete!)
+#define KV_BAD "b" // number of times failed
+#define KV_DATE "d" // last query date
+#define KV_DATE2 "w" // last query date, compressed format
+#define KV_REMARK "r" // remark for this entry
+#define KV_FAUX_AMI_F "ff" // false friend of this entry from org
+#define KV_FAUX_AMI_T "tf" // false friend of this entry to org
+#define KV_SYNONYM "y" // synonym (same meaning) of expr
+#define KV_ANTONYM "a" // antonym (oppositite) of expr
+#define KV_PRONUNCE "p" // how to pronunce this expression
+#define KV_SELECTED "s" // entry selected for queries
+#define KV_INACTIVE "i" // entry inactive (for queries)
+#define KV_EXPRTYPE "t" // type of expression
+#define KV_EXAMPLE "x" // example string with word
+#define KV_USAGE "u" // usage label
+#define KV_PARAPHRASE "h" // paraphrase for expression
+
+/*
+ <type>
+ <desc no="1">My type 1</desc>
+ <desc no="2">My type 2</desc>
+ </type>
+*/
+
+#define KV_TYPE_GRP "type" // type descriptor group
+#define KV_TYPE_DESC "desc" // type descriptor
+#define KV_TYPE_NO "no" // type descriptor number
+
+/*
+ <usage>
+ <desc no="1">My usage 1</desc>
+ <desc no="2">My usage 2</desc>
+ </type>
+*/
+
+#define KV_USAGE_GRP "usage" // usage descriptor group
+#define KV_USAGE_DESC "desc" // usage descriptor
+#define KV_USAGE_NO "no" // usage descriptor number
+
+/*
+ <lesson width="138">
+ <desc no="1">Lesson #1</desc>
+ <desc no="2" query="1">Lesson #2</desc>
+ </lesson>
+*/
+
+#define KV_LESS_GRP "lesson" // lesson descriptor group
+#define KV_LESS_CURR "current" // is current lesson
+#define KV_LESS_DESC "desc" // lesson descriptor
+#define KV_LESS_QUERY "query" // lesson contained in query
+#define KV_LESS_NO "no" // lesson descriptor number
+
+/*
+ <tense>
+ <desc no="1">user tense #1</desc>
+ <desc no="2">user tense #2</desc>
+ </tense>
+*/
+
+#define KV_TENSE_GRP "tense" // tense descriptor group
+#define KV_TENSE_DESC "desc" // tense descriptor
+#define KV_TENSE_NO "no" // tense descriptor number
+
+/*
+ <options>
+ <sort on="1"/>
+ </options>
+*/
+
+#define KV_OPTION_GRP "options" // internal options group
+#define KV_OPT_SORT "sort" // allow sorting
+#define KV_BOOL_FLAG "on" // general boolean flag
+
+/*
+ <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>
+*/
+
+#define KV_ARTICLE_GRP "article" // article descriptor group
+#define KV_ART_ENTRY "e" // article entry
+#define KV_ART_FD "fd" // female definite
+#define KV_ART_MD "md" // male definite
+#define KV_ART_ND "nd" // natural definite
+#define KV_ART_FI "fi" // female indefinite
+#define KV_ART_MI "mi" // male indefinite
+#define KV_ART_NI "ni" // natural indefinite
+
+/*
+ <comparison>
+ <l1>good</l1>
+ <l2>better</l2>
+ <l3>best</l3>
+ </comparison>
+*/
+
+#define KV_COMPARISON_GRP "comparison" // comparison descriptor group
+#define KV_COMP_L1 "l1" // base form
+#define KV_COMP_L2 "l2" // next form
+#define KV_COMP_L3 "l3" // last form
+
+/*
+ <multiplechoice>
+ <mc1>good</mc1>
+ <mc2>better</mc2>
+ <mc3>best</mc3>
+ <mc4>best 2</mc4>
+ <mc5>best 3</mc5>
+ </multiplechoice>
+*/
+
+#define KV_MULTIPLECHOICE_GRP "multiplechoice" // multiple choice descriptor group
+#define KV_MC_1 "mc1" // choice 1
+#define KV_MC_2 "mc2" // choice 2
+#define KV_MC_3 "mc3" // choice 3
+#define KV_MC_4 "mc4" // choice 4
+#define KV_MC_5 "mc5" // choice 5
+
+/*
+ <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 in subsequent <e>-tags
+ <s2>you<2>
+ <s3f>he</s3f>
+ <s3m>she</s3m>
+ <s3n>it</s3n>
+ <p1>we</p1>
+ <p2>you</p2>
+ <p3f>they</p3f>
+ <p3m>they</p3m>
+ <p3n>they</p3n>
+ </e>
+ </conjugation>
+
+ <conjugation> and 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>
+*/
+
+#define KV_CONJUG_GRP "conjugation" // conjugation descriptor group
+#define KV_CON_ENTRY "e" // conjugation entry (header)
+#define KV_CON_TYPE "t" // conjugation type (voc entries)
+#define KV_CON_NAME "n" // conjugation type name (voc entries)
+#define KV_CON_P1S "s1" // 1. person singular
+#define KV_CON_P2S "s2" // 2. person singular
+#define KV_CON_P3SF "s3f" // 3. person singular female
+#define KV_CON_P3SM "s3m" // 3. person singular male
+#define KV_CON_P3SN "s3n" // 3. person singular natural
+#define KV_CON_P1P "p1" // 1. person plural
+#define KV_CON_P2P "p2" // 2. person plural
+#define KV_CON_P3PF "p3f" // 3. person plural female
+#define KV_CON_P3PM "p3m" // 3. person plural male
+#define KV_CON_P3PN "p3n" // 3. person plural natural
+#define KV_CONJ_COMMON "common" // female contains common for all three
+
+#define LEX_IDENT_50 "Vocabulary Trainer V5.0"
+
+
+class QTextStream;
+class QStringList;
+class MultipleChoice;
+
+/*************************************************************
+ * This class contains the expressions of your vocabulary
+ ************************************************************/
+
+class kvoctrainDoc : public QObject
+{
+ Q_OBJECT
+ public:
+
+ enum FileType { kvd_none, automatic,
+ kvtml,
+ kvtbin,
+ vt_lex, vt_vcb, csv, vt_voc /*, kvoclearn, qvocab*/ };
+
+ /** Constructor for the fileclass of the application
+ *
+ * @param obj calling object
+ * @param url URL of file to parse
+ */
+ kvoctrainDoc(QObject* obj, const KURL& url);
+
+ /** Destructor for the fileclass of the application */
+ ~kvoctrainDoc();
+
+ /** indicates that doc is (not) modified
+ *
+ * @param dirty new state
+ */
+ inline void setModified (bool _dirty = true) { emit docModified(dirty = _dirty); }
+
+ /** appends another entry at the end
+ *
+ * @param expr expression to append
+ */
+ inline void appendEntry (kvoctrainExpr *expr)
+ { vocabulary.push_back (*expr); dirty = true; }
+
+ /** removes entry from doc
+ *
+ * @param index index of entry
+ */
+ void removeEntry (int index);
+
+ /** sorts vocabulary alphabetically
+ *
+ * @param index index expression
+ * @result direction of sorting: true = ascending
+ */
+ bool sort (int index);
+
+ /** removes equal entries (orig + all translations)
+ *
+ * @result number of removed entries
+ */
+ int cleanUp();
+
+ /** sorts vocabulary by lesson indices
+ * @result direction of sorting: true = ascending
+ */
+ bool sortByLesson_index ();
+
+ /** sorts vocabulary by lesson name
+ * @result direction of sorting: true = ascending
+ */
+ bool sortByLesson_alpha ();
+
+ /** enables sorting
+ */
+ inline void allowSorting(bool allow) { sort_allowed = allow; }
+
+ /** enables sorting
+ */
+ inline bool isAllowedSorting() { return sort_allowed; }
+
+ /** returns the modification state of the doc */
+ inline bool isModified () const { return dirty; }
+
+ /** returns original´s identifier
+ */
+ QString getOriginalIdent () const;
+
+ /** set original´s identifier
+ */
+ void setOriginalIdent (const QString &id);
+
+ /** returns identifier of translation x
+ *
+ * @param index number of translation 1..x
+ * @result ident string: de=german, en=englisch, ..
+ */
+ QString getIdent (int index) const;
+
+ /** sets identifier of translation
+ *
+ * @param index number of translation 1..x
+ * @param lang ident string: de=german, en=englisch, ..
+ */
+ void setIdent (int index, const QString &lang);
+
+ /** removes identifier an the according translation in all entries
+ *
+ * @param index number of translation 1..x
+ */
+ void removeIdent (int index);
+
+ /** determines if given translation is available and where
+ *
+ * @param lang identifier of language
+ * @result index of translation, 0=original, -1=none
+ */
+ int findIdent (const QString &lang) const;
+
+ /** returns attribute string
+ *
+ * @param index number of attribute
+ * @result string
+ */
+ QString getTypeName (int index) const;
+
+ /** sets attribute string
+ *
+ * @param index number of attribute
+ * @param str name of attribute
+ */
+ void setTypeName (int index, QString &str);
+
+ /** gets descr of types */
+ inline vector<QString> getTypeDescr() const { return type_descr; }
+
+ /** sets descr of types */
+ inline void setTypeDescr(vector<QString> names) { type_descr = names; }
+
+ /** returns tense string
+ *
+ * @param index number of tense
+ * @result string
+ */
+ QString getTenseName (int index) const;
+
+ /** sets tense string
+ *
+ * @param index number of tense
+ * @param str name of tense
+ */
+ void setTenseName (int index, QString &str);
+
+ /** gets descr of tenses */
+ inline vector<QString> getTenseDescr() const { return tense_descr; }
+
+ /** sets descr of tenses */
+ inline void setTenseDescr(vector<QString> names) { tense_descr = names; }
+
+ /** returns usage string
+ *
+ * @param index number of usage
+ * @result string
+ */
+ QString getUsageName (int index) const;
+
+ /** sets usage string
+ *
+ * @param index number of usage
+ * @param str name of usage
+ */
+ void setUsageName (int index, QString &str);
+
+ /** gets descr of usages */
+ inline vector<QString> getUsageDescr() const { return usage_descr; }
+
+ /** sets descr of usages */
+ inline void setUsageDescr(vector<QString> names) { usage_descr = names; }
+
+
+ /** saves the data under the given name
+ *
+ * @param url if url is empty (or NULL) actual name is preserved
+ * @result true if successful
+ */
+ bool saveAs (QObject *parent, const KURL & url, QString title, FileType ft);
+
+ /** returns count of entries
+ */
+ inline int numEntries() const { return vocabulary.size(); }
+
+ /** sets grades to KV_NORM_GRADE, counts to 0 ...
+ *
+ * @param index index of language 0..x, -1 = all
+ * @param lesson lesson id, if this is 0 all lesson are affected,
+ * otherwise only matching numbers
+ */
+ void resetEntry (int index = -1, int lesson = 0);
+
+ /** returns count of different languages
+ */
+ inline int numLangs() const { return langs.size(); } // org + translations
+
+ /** append new lang ident
+ */
+ inline void appendLang(const QString & id) { langs.push_back(id); }
+
+ /** returns pointer to expression object x
+ *
+ * @param index index of desired entry
+ * @result pointer to object or NULL if index out of range
+ */
+ kvoctrainExpr *getEntry(int index);
+
+ /** search substring in vocabulary (case insensitive always)
+ *
+ * @param substr partial string to search
+ * @param id which language to search: 0=org, 1..x=translation
+ * @param first index from where to start
+ * @param last index of last entry, -1 goes till end
+ * @param word_start false: search partial string,
+ * true:always from beginning of word
+ * @param tolerant
+ * @result index of found entry, -1 if none
+ */
+ int search(QString substr, int id,
+ int first=0, int last=-1, bool word_start = false, bool tolerant=false);
+
+ /** returns url of xml file */
+ inline KURL URL() const {return doc_url; }
+
+ /** sets url of xml file */
+ inline void setURL(const KURL& url) {doc_url = url;}
+
+ /** returns title of xml file */
+ QString getTitle() const;
+
+ /** returns author of file */
+ QString getAuthor() const;
+
+ /** returns license of file */
+ QString getLicense() const;
+
+ /** returns remark of file */
+ QString getDocRemark() const;
+
+ inline void getQueryLang(QString &org, QString &trans) const
+ { org = queryorg; trans = querytrans; }
+
+ inline void setQueryLang(const QString &org, const QString &trans)
+ { queryorg = org; querytrans = trans; }
+
+ /** sets title of xml file */
+ void setTitle(const QString & title);
+
+ /** sets author of file */
+ void setAuthor(const QString & author);
+
+ /** sets license of file */
+ void setLicense(const QString & license);
+
+ /** sets remark of file */
+ void setDocRemark(const QString & rem);
+
+ /** gets version of loaded file */
+ void getVersion(int &major, int &minor, int &patch);
+
+ /** returns current lesson index */
+ inline int getCurrentLesson() const { return current_lesson; }
+
+ /** sets current lesson index
+ * @param lesson index of lesson
+ */
+ inline void setCurrentLesson(int lesson) { current_lesson = lesson; }
+
+ /** returns descr of lesson */
+ QString getLessonDescr(int index) const;
+
+ /** returns lessons in current query */
+ vector<int> getLessonsInQuery() const;
+
+ /** sets lessons in current query */
+ void setLessonsInQuery(vector<int>);
+
+ inline vector<QString> getLessonDescr() const { return lesson_descr; }
+
+ inline int numLessons () const {return (int) lesson_descr.size(); }
+
+ /** sets descr of lesson */
+ inline void setLessonDescr(vector<QString> names) { lesson_descr = names; }
+
+ /** returns pointer to conjugations if available
+ *
+ * @param index index of translation
+ */
+ Conjugation getConjugation(int index) const;
+
+ /** sets conjugations
+ *
+ * @param index index of translation
+ * @param con conjugation block
+ */
+ void setConjugation(int index, const Conjugation &con);
+
+ /** returns pointer to articles if available
+ *
+ * @param index index of translation
+ */
+ Article getArticle(int index) const;
+
+ /** sets articles
+ *
+ * @param index index of translation
+ * @param art article block
+ */
+ void setArticle(int index, const Article &art);
+
+ /** compress date */
+ QString compressDate(unsigned long) const;
+
+ /** decompress date */
+ unsigned long decompressDate(QString) const;
+
+ /** returns recommended size
+ *
+ * @param index number of expr, -1 = lesson
+ * @result width of column
+ */
+ int getSizeHint (int index) const;
+
+ /** sets recommended size
+ *
+ * @param index number of expr, -1 = lesson
+ * @param width width of column
+ */
+ void setSizeHint (int index, const int width);
+
+ bool unknownAttribute (int line, const QString &name, const QString &attr);
+ void unknownElement (int line, const QString &elem );
+ void errorKvtMl (int line, const QString &text );
+ void warningKvtMl (int line, const QString &text );
+
+ void errorLex (int line, const QString &text );
+
+ void errorCsv (int line, const QString &text );
+
+ FileType detectFT(const QString &filename);
+
+ friend class QueryManager;
+
+signals:
+ void progressChanged (kvoctrainDoc *, int curr_percent);
+ void docModified (bool mod);
+
+protected:
+
+ void Init();
+
+ /** sets version of loaded file */
+ void setVersion(const QString & ver);
+
+ bool saveToKvtMl (QTextStream& os, QString &title);
+ bool loadFromKvtMl (QTextStream& is);
+ bool parseBody_kvtml (XmlElement elem, XmlReader& xml);
+ bool parseBody_e (XmlElement elem, XmlReader& xml);
+ bool extract_simple_tag (QString tag_name, XmlReader& xml,
+ XmlElement &elem, QString &data,
+ bool check_empty = true);
+
+ bool extract_T_GROUP_attr (XmlReader &xml,
+ XmlElement &elem);
+ bool extract_T_DESCR_attr (XmlReader &xml,
+ XmlElement &elem, int &no);
+ bool extract_O_T_attr (XmlReader &xml,
+ XmlElement &elem,
+ QString &lang,
+ grade_t &grade, grade_t &rev_grade,
+ int &count, int &rev_count,
+ time_t &date, time_t &rev_date,
+ QString &remark,
+ int &bcount, int &rev_bcount,
+ QString &query_id,
+ QString &pronunce,
+ int &width,
+ QString &type,
+ QString &faux_ami_f,
+ QString &faux_ami_t,
+ QString &synonym,
+ QString &example,
+ QString &antonym,
+ QString &usage,
+ QString &paraphrase);
+ bool extract_L_DESCR_attr (XmlReader &xml,
+ XmlElement &elem, int &no,
+ bool &isCurr, bool &inQuery);
+ bool extract_KVT_E_attr (XmlReader& xml,
+ XmlElement &elem,
+ int &lesson,
+ bool &sel,
+ bool &active,
+ QString &type);
+ bool check_Empty_attr (QString tag_name,
+ XmlReader &xml,
+ XmlElement &elem);
+ bool extract_CON_E_attr (XmlReader& xml,
+ XmlElement &elem,
+ QString &lang);
+ bool extract_T_attr (XmlReader &xml,
+ XmlElement &elem,
+ QString &name);
+ bool extract_BOOL_attr (XmlReader &xml,
+ XmlElement &elem,
+ const QString &tag_name,
+ const QString &attr_name,
+ bool &flag);
+ bool extract_L_GROUP_attr (XmlReader &xml,
+ XmlElement &elem,
+ int &width);
+
+ bool saveLessonKvtMl (XmlWriter &xml);
+ bool loadLessonKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveTypeNameKvtMl (XmlWriter &xml);
+ bool loadTypeNameKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveTenseNameKvtMl (XmlWriter &xml);
+ bool loadTenseNameKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveUsageNameKvtMl (XmlWriter &xml);
+ bool loadUsageNameKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveOptionsKvtMl (XmlWriter &xml);
+ bool loadOptionsKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveArticleKvtMl (XmlWriter &xml);
+ bool loadArticleKvtMl (XmlElement elem, XmlReader& xml);
+ bool saveConjugHeader (vector<Conjugation> &curr_conjug,
+ XmlWriter &xml);
+ bool saveConjug (const Conjugation &curr_conjug, QString type,
+ XmlWriter &xml, QString identstr);
+ bool saveConjugEntry (Conjugation &curr_conjug,
+ XmlWriter &xml, int ident);
+ bool loadConjugKvtMl (vector<Conjugation> &curr_conjug, const QString &entry_tag,
+ XmlElement elem, XmlReader& xml);
+
+ bool saveComparison (const Comparison &comp, XmlWriter &xml, int ident);
+ bool loadComparison (Comparison &comp, XmlElement elem, XmlReader &xml);
+
+ bool saveMultipleChoice(const MultipleChoice &mc, XmlWriter &xml, int ident);
+ bool loadMultipleChoice(MultipleChoice &mc, XmlElement elem, XmlReader &xml);
+
+ bool saveToLex (QTextStream& os, QString &title);
+ bool loadFromLex (QTextStream& is);
+ bool loadLessonLex (QTextStream& is);
+ bool saveLessonLex (QTextStream& os);
+ bool saveTypeNameLex (QTextStream& os);
+ bool loadTypeNameLex (QTextStream& is);
+
+ bool saveToCsv (QTextStream& os, QString &title);
+ bool loadFromCsv (QTextStream& is);
+ bool loadLessonCsv (QTextStream& is);
+ bool saveLessonCsv (QTextStream& os);
+ bool saveTypeNameCsv (QTextStream& os);
+ bool loadTypeNameCsv (QTextStream& is);
+
+ bool saveTypeNameVcb (QTextStream &os);
+ bool loadTypeNameVcb (QTextStream &is);
+ bool saveLessonVcb (QTextStream &os);
+ bool loadLessonVcb (QTextStream &is);
+ bool saveToVcb (QTextStream& os, QString &title);
+ bool loadFromVcb (QTextStream& is);
+ bool loadFromVoc(QTextStream& is);
+ void errorVcb (int line, const QString &text );
+
+ private:
+ bool dirty;
+ KURL doc_url;
+ vector<bool> sort_lang;
+ bool sort_lesson;
+ bool unknown_attr;
+ bool unknown_elem;
+ bool sort_allowed;
+
+ // save these to document
+ vector<QString> langs; //0= origin, 1,.. translations
+ int cols,
+ lines;
+ int current_lesson;
+ vector<int> extraSizehints;
+ vector<int> sizehints;
+ QString generator;
+ QString queryorg,
+ querytrans;
+ vector<kvoctrainExpr> vocabulary;
+ vector<bool> lessons_in_query;
+ vector<QString> lesson_descr;
+ vector<QString> type_descr;
+ vector<QString> tense_descr;
+ vector<QString> usage_descr;
+ QString doctitle;
+ QString author;
+ QString license;
+ QString doc_remark;
+ QString doc_version;
+
+ vector<Article> articles;
+ vector<Conjugation> conjugations;
+};
+
+
+#endif // KVOCTRAINDOC_H
diff --git a/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.cpp b/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.cpp
new file mode 100644
index 00000000..2faba172
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.cpp
@@ -0,0 +1,799 @@
+/***************************************************************************
+
+ maintain a kvoctrain expression
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "kvoctrainexpr.h"
+
+void kvoctrainExpr::Init()
+{
+ grades.push_back(KV_NORM_GRADE);
+ rev_grades.push_back(KV_NORM_GRADE);
+ inquery = false;
+ active = true;
+ qcounts.push_back(0);
+ rev_qcounts.push_back(0);
+ bcounts.push_back(0);
+ rev_bcounts.push_back(0);
+ qdates.push_back(0);
+ rev_qdates.push_back(0);
+ lesson = 0;
+}
+
+
+kvoctrainExpr::kvoctrainExpr (QString &expr, int _lesson)
+{
+ Init();
+ setOriginal(expr.stripWhiteSpace() );
+ lesson = _lesson;
+}
+
+
+kvoctrainExpr::kvoctrainExpr ()
+{
+ Init();
+}
+
+
+kvoctrainExpr::kvoctrainExpr (QString &s, QString separator, int _lesson)
+{
+ Init();
+ QString se;
+ lesson = _lesson;
+
+ if (separator.length() ) {
+ int pos = s.find(separator);
+
+ if (pos == -1) {
+ setOriginal(s.stripWhiteSpace());
+ }
+ else {
+ se = s.left(pos).stripWhiteSpace();
+ setOriginal(se);
+ s.remove (0, pos+separator.length() );
+// s.stripWhiteSpace();
+
+ // gather all translations
+ while ((pos = s.find(separator)) != -1) {
+ se = s.left(pos).stripWhiteSpace();
+ addTranslation(se, KV_NORM_GRADE, KV_NORM_GRADE);
+ s.remove (0, pos+separator.length() );
+// s.stripWhiteSpace();
+ }
+ addTranslation(s.stripWhiteSpace(), KV_NORM_GRADE, KV_NORM_GRADE);
+ }
+ }
+}
+
+
+kvoctrainExpr::~kvoctrainExpr()
+{
+}
+
+
+int kvoctrainExpr::numTranslations() const
+{
+ return translations.size();
+}
+
+
+QString kvoctrainExpr::getRemark (int idx) const
+{
+ if (idx >= (int)remarks.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return remarks[idx];
+ }
+}
+
+
+void kvoctrainExpr::setRemark (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend remarks with empty strings if necessary
+ if ((int)remarks.size() <= idx )
+ for (int i = remarks.size(); i < idx+1; i++)
+ remarks.push_back ("");
+
+ remarks[idx] = expr.stripWhiteSpace();
+}
+
+
+void kvoctrainExpr::setFauxAmi (int idx, const QString & expr, bool rev_ami)
+{
+ if (idx < 1) return;
+
+ if (rev_ami) {
+ // extend friend with empty strings if necessary
+ if ((int)rev_fauxAmi.size() <= idx )
+ for (int i = rev_fauxAmi.size(); i < idx+1; i++)
+ rev_fauxAmi.push_back ("");
+
+ rev_fauxAmi[idx] = expr.stripWhiteSpace();
+
+ }
+ else {
+ // extend friend with empty strings if necessary
+ if ((int)fauxAmi.size() <= idx )
+ for (int i = fauxAmi.size(); i < idx+1; i++)
+ fauxAmi.push_back ("");
+
+ fauxAmi[idx] = expr.stripWhiteSpace();
+ }
+}
+
+
+QString kvoctrainExpr::getFauxAmi (int idx, bool rev_ami) const
+{
+ if (rev_ami) {
+ if (idx >= (int)rev_fauxAmi.size() || idx < 1 ) {
+ return "";
+ }
+
+ return rev_fauxAmi[idx];
+ }
+
+ if (idx >= (int)fauxAmi.size() || idx < 1 ) {
+ return "";
+ }
+
+ return fauxAmi[idx];
+}
+
+
+void kvoctrainExpr::setSynonym (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend synonym with empty strings if necessary
+ if ((int)synonym.size() <= idx )
+ for (int i = synonym.size(); i < idx+1; i++)
+ synonym.push_back ("-");
+
+ synonym[idx] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::getSynonym (int idx) const
+{
+ if (idx >= (int)synonym.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return synonym[idx];
+ }
+}
+
+
+void kvoctrainExpr::setExample (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend exampls with empty strings if necessary
+ if ((int)example.size() <= idx )
+ for (int i = example.size(); i < idx+1; i++)
+ example.push_back ("");
+
+ example[idx] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::getExample (int idx) const
+{
+ if (idx >= (int)example.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return example[idx];
+ }
+}
+
+
+void kvoctrainExpr::setUsageLabel (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend labels with empty strings if necessary
+ if ((int)usageLabels.size() <= idx )
+ for (int i = usageLabels.size(); i < idx+1; i++)
+ usageLabels.push_back ("");
+
+ usageLabels[idx] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::getUsageLabel (int idx) const
+{
+ if (idx >= (int)usageLabels.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return usageLabels[idx];
+ }
+}
+
+
+void kvoctrainExpr::setParaphrase (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend phrase with empty strings if necessary
+ if ((int) paraphrases.size() <= idx )
+ for (int i = paraphrases.size(); i < idx+1; i++)
+ paraphrases.push_back ("");
+
+ paraphrases[idx] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::getParaphrase (int idx) const
+{
+ if (idx >= (int)paraphrases.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return paraphrases[idx];
+ }
+}
+
+
+void kvoctrainExpr::setAntonym (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend antonym with empty strings if necessary
+ if ((int)antonym.size() <= idx )
+ for (int i = antonym.size(); i < idx+1; i++)
+ antonym.push_back ("");
+
+ antonym[idx] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::getAntonym (int idx) const
+{
+ if (idx >= (int)antonym.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return antonym[idx];
+ }
+}
+
+
+void kvoctrainExpr::setConjugation (int idx, const Conjugation &con)
+{
+ if ( idx < 0) return;
+
+ // extend conjugation with empty elements
+ if ((int)conjugations.size() <= idx )
+ for (int i = conjugations.size(); i < idx+1; i++)
+ conjugations.push_back (Conjugation());
+
+ conjugations[idx] = con;
+}
+
+
+Conjugation kvoctrainExpr::getConjugation (int idx) const
+{
+ if (idx >= (int)conjugations.size() || idx < 0) {
+ return Conjugation();
+ }
+ else {
+ return conjugations[idx];
+ }
+}
+
+
+void kvoctrainExpr::setComparison (int idx, const Comparison &con)
+{
+ if ( idx < 0) return;
+
+ // extend comparison with empty elements
+ if ((int)comparisons.size() <= idx )
+ for (int i = comparisons.size(); i < idx+1; i++)
+ comparisons.push_back (Comparison());
+
+ comparisons[idx] = con;
+}
+
+
+Comparison kvoctrainExpr::getComparison (int idx) const
+{
+ if (idx >= (int)comparisons.size() || idx < 0) {
+ return Comparison();
+ }
+ else {
+ return comparisons[idx];
+ }
+}
+
+
+void kvoctrainExpr::setMultipleChoice (int idx, const MultipleChoice &mc)
+{
+ if ( idx < 0) return;
+
+ // extend comparison with empty elements
+ if ((int)mcs.size() <= idx )
+ for (int i = mcs.size(); i < idx+1; i++)
+ mcs.push_back (MultipleChoice());
+
+ mcs[idx] = mc;
+}
+
+
+MultipleChoice kvoctrainExpr::getMultipleChoice (int idx) const
+{
+ if (idx >= (int)mcs.size() || idx < 0) {
+ return MultipleChoice();
+ }
+ else {
+ return mcs[idx];
+ }
+}
+
+
+QString kvoctrainExpr::getPronunce (int idx) const
+{
+ if (idx >= (int)pronunces.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return pronunces[idx];
+ }
+}
+
+
+void kvoctrainExpr::setPronunce (int idx, const QString & expr)
+{
+ if ( idx < 0) return;
+
+ // extend with empty strings if necessary
+ if ((int)pronunces.size() <= idx )
+ for (int i = pronunces.size(); i < idx+1; i++)
+ pronunces.push_back ("");
+
+ pronunces[idx] = expr.stripWhiteSpace();
+}
+
+
+void kvoctrainExpr::addTranslation (QString expr,
+ grade_t grade, grade_t rev_grade)
+{
+ if (grade > KV_MAX_GRADE)
+ grade = KV_MAX_GRADE;
+
+ if (rev_grade > KV_MAX_GRADE)
+ rev_grade = KV_MAX_GRADE;
+
+ grades.push_back (grade);
+ rev_grades.push_back (rev_grade);
+ translations.push_back (expr.stripWhiteSpace());
+}
+
+
+QString kvoctrainExpr::getTranslation (int idx) const
+{
+ if (idx > (int)translations.size() || idx < 1)
+ return "";
+ else
+ return translations[idx-1];
+}
+
+
+void kvoctrainExpr::removeTranslation (int idx)
+{
+ if (idx <= 0)
+ return;
+
+ if (idx <= numTranslations())
+ translations.erase (translations.begin() + idx-1);
+
+ if (idx < (int)remarks.size() )
+ remarks.erase (remarks.begin() + idx);
+
+ if (idx < (int)conjugations.size() )
+ conjugations.erase (conjugations.begin() + idx);
+
+ if (idx < (int)comparisons.size() )
+ comparisons.erase (comparisons.begin() + idx);
+
+ if (idx < (int)fauxAmi.size() )
+ fauxAmi.erase (fauxAmi.begin() + idx);
+
+ if (idx < (int)rev_fauxAmi.size() )
+ rev_fauxAmi.erase (rev_fauxAmi.begin() + idx);
+
+ if (idx < (int)synonym.size() )
+ synonym.erase (synonym.begin() + idx);
+
+ if (idx < (int)example.size() )
+ example.erase (example.begin() + idx);
+
+ if (idx < (int)usageLabels.size() )
+ usageLabels.erase (usageLabels.begin() + idx);
+
+ if (idx < (int)paraphrases.size() )
+ paraphrases.erase (paraphrases.begin() + idx);
+
+ if (idx < (int)antonym.size() )
+ antonym.erase (antonym.begin() + idx);
+
+ if (idx < (int)exprtypes.size() )
+ exprtypes.erase (exprtypes.begin() + idx);
+
+ if (idx < (int)pronunces.size() )
+ pronunces.erase (pronunces.begin() + idx);
+
+ if (idx < (int)grades.size() )
+ grades.erase (grades.begin() + idx);
+
+ if (idx < (int)rev_grades.size() )
+ rev_grades.erase (rev_grades.begin() + idx);
+
+ if (idx < (int)qcounts.size() )
+ qcounts.erase (qcounts.begin() + idx);
+
+ if (idx < (int)rev_qcounts.size() )
+ rev_qcounts.erase (rev_qcounts.begin() + idx);
+
+ if (idx < (int)bcounts.size() )
+ bcounts.erase (bcounts.begin() + idx);
+
+ if (idx < (int)rev_bcounts.size() )
+ rev_bcounts.erase (rev_bcounts.begin() + idx);
+
+ if (idx < (int)qdates.size() )
+ qdates.erase (qdates.begin() + idx);
+
+ if (idx < (int)rev_qdates.size() )
+ rev_qdates.erase (rev_qdates.begin() + idx);
+}
+
+
+void kvoctrainExpr::setTranslation (int idx, const QString & expr)
+{
+ if ( idx <= 0) return;
+
+ // extend translations with empty strings if necessary
+ if ((int)translations.size() < idx )
+ for (int i = translations.size(); i < idx; i++)
+ translations.push_back ("");
+
+// if (idx <= (int)translations.size())
+ translations[idx-1] = expr.stripWhiteSpace();
+}
+
+
+QString kvoctrainExpr::gradeStr (int idx, bool rev_grade) const
+{
+ QString s;
+ s.setNum(getGrade(idx, rev_grade));
+ return s;
+}
+
+
+grade_t kvoctrainExpr::getGrade (int idx, bool rev_grade) const
+{
+ if (rev_grade) {
+ if (idx >= (int)rev_grades.size() || idx < 1 ) {
+ return KV_NORM_GRADE;
+ }
+ else if (rev_grades[idx] > KV_MAX_GRADE) {
+ return KV_MAX_GRADE;
+ }
+
+ return rev_grades[idx];
+
+ }
+ else {
+ if (idx >= (int)grades.size() || idx < 1 ) {
+ return KV_NORM_GRADE;
+ }
+ else if (grades[idx] > KV_MAX_GRADE) {
+ return KV_MAX_GRADE;
+ }
+
+ return grades[idx];
+ }
+}
+
+
+void kvoctrainExpr::setGrade (int idx, grade_t grade, bool rev_grade)
+{
+ if (idx < 1) return;
+
+ if (grade > KV_MAX_GRADE)
+ grade = KV_MAX_GRADE;
+ if (grade < KV_MIN_GRADE)
+ grade = KV_MIN_GRADE;
+
+ if (rev_grade) {
+ // extend rev grades with standard grade if necessary
+ if ((int)rev_grades.size() <= idx )
+ for (int i = rev_grades.size(); i <= idx; i++) {
+ rev_grades.push_back (KV_NORM_GRADE);
+ }
+ rev_grades[idx] = grade;
+ }
+ else {
+ // extend grades with standard grade if necessary
+ if ((int)grades.size() <= idx )
+ for (int i = grades.size(); i <= idx; i++) {
+ grades.push_back (KV_NORM_GRADE);
+ }
+ grades[idx] = grade;
+ }
+}
+
+
+void kvoctrainExpr::incGrade (int idx, bool rev_grade)
+{
+ if (idx < 1) return;
+
+ if (rev_grade) {
+ // extend rev grades with standard grade if necessary
+ if ((int)rev_grades.size() <= idx )
+ for (int i = rev_grades.size(); i <= idx; i++) {
+ rev_grades.push_back (KV_NORM_GRADE);
+ }
+ if (rev_grades[idx] < KV_MAX_GRADE)
+ rev_grades[idx]++;
+ }
+ else {
+ // extend grades with standard grade if necessary
+ if ((int)grades.size() <= idx )
+ for (int i = grades.size(); i <= idx; i++) {
+ grades.push_back (KV_NORM_GRADE);
+ }
+ if (grades[idx] < KV_MAX_GRADE)
+ grades[idx]++;
+ }
+}
+
+
+void kvoctrainExpr::decGrade (int idx, bool rev_grade)
+{
+ if (idx < 1) return;
+
+ if (rev_grade) {
+ // extend rev grades with standard grade if necessary
+ if ((int)rev_grades.size() <= idx )
+ for (int i = rev_grades.size(); i <= idx; i++) {
+ rev_grades.push_back (KV_NORM_GRADE);
+ }
+ if (rev_grades[idx] > KV_MIN_GRADE)
+ rev_grades[idx]--;
+ }
+ else {
+ // extend grades with standard grade if necessary
+ if ((int)grades.size() <= idx )
+ for (int i = grades.size(); i <= idx; i++) {
+ grades.push_back (KV_NORM_GRADE);
+ }
+ if (grades[idx] > KV_MIN_GRADE)
+ grades[idx]--;
+ }
+}
+
+
+count_t kvoctrainExpr::getQueryCount (int idx, bool rev_count) const
+{
+ if (rev_count) {
+ if (idx >= (int)rev_qcounts.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return rev_qcounts[idx];
+ }
+
+ if (idx >= (int)qcounts.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return qcounts[idx];
+}
+
+
+void kvoctrainExpr::setQueryCount (int idx, count_t count, bool rev_count)
+{
+ if (idx < 1) return;
+
+ if (rev_count) {
+ // extend rev counts with 0 if necessary
+ if ((int)rev_qcounts.size() <= idx )
+ for (int i = rev_qcounts.size(); i <= idx; i++) {
+ rev_qcounts.push_back (0);
+ }
+
+ rev_qcounts[idx] = count;
+
+ }
+ else {
+ // extend counts with 0 if necessary
+ if ((int)qcounts.size() <= idx )
+ for (int i = qcounts.size(); i <= idx; i++) {
+ qcounts.push_back (0);
+ }
+ qcounts[idx] = count;
+ }
+}
+
+
+count_t kvoctrainExpr::getBadCount (int idx, bool rev_count) const
+{
+ if (rev_count) {
+ if (idx >= (int)rev_bcounts.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return rev_bcounts[idx];
+ }
+
+ if (idx >= (int)bcounts.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return bcounts[idx];
+}
+
+
+void kvoctrainExpr::setBadCount (int idx, count_t count, bool rev_count)
+{
+ if (idx < 1) return;
+
+ if (rev_count) {
+ // extend rev counts with 0 if necessary
+ if ((int)rev_bcounts.size() <= idx )
+ for (int i = rev_bcounts.size(); i <= idx; i++) {
+ rev_bcounts.push_back (0);
+ }
+
+ rev_bcounts[idx] = count;
+
+ }
+ else {
+ // extend counts with 0 if necessary
+ if ((int)bcounts.size() <= idx )
+ for (int i = bcounts.size(); i <= idx; i++) {
+ bcounts.push_back (0);
+ }
+ bcounts[idx] = count;
+ }
+}
+
+
+time_t kvoctrainExpr::getQueryDate (int idx, bool rev_date) const
+{
+ if (rev_date) {
+ if (idx >= (int)rev_qdates.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return rev_qdates[idx];
+ }
+
+ if (idx >= (int)qdates.size() || idx < 1 ) {
+ return 0;
+ }
+
+ return qdates[idx];
+}
+
+
+void kvoctrainExpr::setQueryDate (int idx, time_t date, bool rev_date)
+{
+ if (idx < 1) return;
+
+ if (rev_date) {
+ // extend rev dates with 0 if necessary
+ if ((int)rev_qdates.size() <= idx )
+ for (int i = rev_qdates.size(); i <= idx; i++) {
+ rev_qdates.push_back (0);
+ }
+
+ rev_qdates[idx] = date;
+
+ }
+ else {
+ // extend dates with 0 if necessary
+ if ((int)qdates.size() <= idx )
+ for (int i = qdates.size(); i <= idx; i++) {
+ qdates.push_back (0);
+ }
+ qdates[idx] = date;
+ }
+}
+
+
+bool kvoctrainExpr::uniqueType () const
+{
+ bool unique = true;
+ QString type0 = getType(0);
+ for (int i = 1; i < numTranslations(); i++)
+ if (type0 != getType(i) )
+ unique = false;
+ return unique;
+}
+
+
+QString kvoctrainExpr::getType (int idx) const
+{
+ if (idx >= (int)exprtypes.size() || idx < 0) {
+ return "";
+ }
+ else {
+ return exprtypes[idx];
+ }
+}
+
+
+int kvoctrainExpr::getLesson () const
+{
+ return lesson;
+}
+
+void kvoctrainExpr::incQueryCount (int index, bool rev_count)
+{
+ setQueryCount (index, getQueryCount(index, rev_count)+1, rev_count);
+}
+
+
+void kvoctrainExpr::incBadCount (int index, bool rev_count)
+{
+ setBadCount (index, getBadCount(index, rev_count)+1, rev_count);
+}
+
+
+void kvoctrainExpr::setOriginal ( const QString & expr)
+{
+ origin = expr;
+}
+
+
+QString kvoctrainExpr::getOriginal () const
+{
+ return origin;
+}
+
+
+void kvoctrainExpr::setLesson (int l)
+{
+ lesson = l;
+}
+
+
+void kvoctrainExpr::setType (int idx, const QString &type)
+{
+ if ( idx < 0) return;
+
+ // extend types with empty strings if necessary
+ if ((int)exprtypes.size() <= idx )
+ for (int i = exprtypes.size(); i < idx+1; i++)
+ exprtypes.push_back ("");
+
+ exprtypes[idx] = type.stripWhiteSpace();
+}
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.h b/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.h
new file mode 100644
index 00000000..ecdefa4d
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvoctrainexpr.h
@@ -0,0 +1,465 @@
+/***************************************************************************
+
+ maintain a kvoctrain expression
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
+ (C) 2001 The KDE-EDU team
+ (C) 2005 Peter Hedlund <peter.hedlund@kdemail.net>
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 KVOCTRAINEXPR_H
+#define KVOCTRAINEXPR_H
+
+#include <klocale.h>
+
+#define KV_MAX_GRADE 7
+#define KV_MIN_GRADE 0
+
+#define KV_NORM_GRADE 0 // not queried yet
+#define KV_NORM_COLOR Qt::black
+static const char *KV_NORM_TEXT = I18N_NOOP("Not Queried Yet");
+
+#define KV_LEV1_GRADE 1
+static const char *KV_LEV1_TEXT = I18N_NOOP("Level 1");
+
+#define KV_LEV2_GRADE 2
+static const char *KV_LEV2_TEXT = I18N_NOOP("Level 2");
+
+#define KV_LEV3_GRADE 3
+static const char *KV_LEV3_TEXT = I18N_NOOP("Level 3");
+
+#define KV_LEV4_GRADE 4
+static const char *KV_LEV4_TEXT = I18N_NOOP("Level 4");
+
+#define KV_LEV5_GRADE 5
+static const char *KV_LEV5_TEXT = I18N_NOOP("Level 5");
+
+#define KV_LEV6_GRADE 6
+static const char *KV_LEV6_TEXT = I18N_NOOP("Level 6");
+
+#define KV_LEV7_GRADE 7
+static const char *KV_LEV7_TEXT = I18N_NOOP("Level 7");
+
+#include <time.h>
+#include <vector>
+using namespace std;
+
+#include "grammarmanager.h"
+#include "MultipleChoice.h"
+
+typedef signed char grade_t;
+typedef unsigned short count_t;
+
+/***************************************************************
+ * This class contains one expression as original or in one
+ * translations
+ **************************************************************/
+
+class kvoctrainExpr
+{
+ public:
+
+ /** default constructor for an expression in different languages
+ */
+ ~kvoctrainExpr ();
+
+ kvoctrainExpr ();
+
+ kvoctrainExpr (QString &s, QString separator, int lesson = 0);
+
+ /** Constructor for an expression in different languages
+ *
+ * @param expr expression
+ */
+ kvoctrainExpr (QString &expr, int lesson = 0);
+
+ /** adds a new translation of this entry
+ * @param expr translation
+ * @param grade grade of knowledge of this translation
+ * @param rev_grade dito, in opposite direction
+ */
+ void addTranslation (QString expr, grade_t grade=KV_NORM_GRADE,
+ grade_t rev_grade=KV_NORM_GRADE);
+
+ /** removes translation
+ *
+ * @param index number of translation 1..x
+ */
+ void removeTranslation (int index);
+
+ /** returns index of lesson (0 = none)
+ */
+ int getLesson () const;
+
+ /** sets index of lesson (0 = none)
+ */
+ void setLesson (int l);
+
+ /** returns original expression of this entry
+ */
+ QString getOriginal () const;
+
+ /** sets original expression of this entry
+ */
+ void setOriginal (const QString & expr);
+
+ /** returns number of max. translations of all expressions
+ */
+ int numTranslations() const;
+
+ /** returns flag if entry is "selected" for queries
+ */
+ bool isInQuery() const {return inquery; }
+
+ /** set entry "selected"
+ */
+ void setInQuery(bool flag = true) { inquery = flag; }
+
+ /** returns flag if entry is activated for queries
+ */
+ bool isActive() const {return active; }
+
+ /** set entry active (enabled for queries)
+ */
+ void setActive(bool flag = true) { active = flag; }
+
+ /** returns translation of this expression
+ *
+ * @param index number of translation
+ * @result expression or "" if no translation available
+ */
+ QString getTranslation (int index) const;
+
+ /** sets translation of this expression
+ *
+ * @param index number of translation
+ * @param expr expression of this index
+ */
+ void setTranslation (int index, const QString & expr);
+
+ /** sets remark of this expression
+ *
+ * @param index index of expression
+ * @param expr remark of this index
+ */
+ void setPronunce (int index, const QString & expr);
+
+ /** returns pronunciation of this expression
+ *
+ * @param index index of expression
+ * @result pronunciation or "" if none available
+ */
+ QString getPronunce (int index) const;
+
+ /** returns remarks of this expression
+ *
+ * @param index index of expression
+ * @result remark or "" if no remark available
+ */
+ QString getRemark (int index) const;
+
+ /** sets remark of this expression
+ *
+ * @param index index of expression
+ * @param expr remark of this index
+ */
+ void setRemark (int index, const QString & expr);
+
+
+ /** sets false friend of this expression
+ *
+ * @param index index of expression
+ * @param expr false friend of this index
+ * @param rev_grade dito, in opposite direction
+ */
+ void setFauxAmi (int index, const QString & expr, bool rev_ami = false);
+
+
+ /** returns false friend of this expression
+ *
+ * @param index index of expression
+ * @param rev_grade dito, in opposite direction
+ * @result false friend or "" if no string available
+ */
+ QString getFauxAmi (int index, bool rev_ami = false) const;
+
+ /** sets synonym this expression
+ *
+ * @param index index of expression
+ * @param expr synonym of this index
+ */
+ void setSynonym (int index, const QString & expr);
+
+
+ /** returns synonym of this expression
+ *
+ * @param index index of expression
+ * @result synonym or "" if no string available
+ */
+ QString getSynonym (int index) const;
+
+ /** sets example this expression
+ *
+ * @param index index of expression
+ * @param expr example of this index
+ */
+ void setExample (int index, const QString & expr);
+
+
+ /** returns example of this expression
+ *
+ * @param index index of expression
+ * @result example or "" if no string available
+ */
+ QString getExample (int index) const;
+
+ /** sets usage label this expression
+ *
+ * @param index index of expression
+ * @param usage usage label of this index
+ */
+ void setUsageLabel (int index, const QString & usage);
+
+
+ /** returns usage label of this expression
+ *
+ * @param index index of expression
+ * @result usage or "" if no string available
+ */
+ QString getUsageLabel (int index) const;
+
+ /** sets paraphrase of this expression
+ *
+ * @param index index of expression
+ * @param usage paraphrase of this index
+ */
+ void setParaphrase (int index, const QString & usage);
+
+
+ /** returns paraphrase of this expression
+ *
+ * @param index index of expression
+ * @result paraphrase or "" if no string available
+ */
+ QString getParaphrase (int index) const;
+
+ /** sets antonym this expression
+ *
+ * @param index index of expression
+ * @param expr antonym of this index
+ */
+ void setAntonym (int index, const QString & expr);
+
+
+ /** returns antonym of this expression
+ *
+ * @param index index of expression
+ * @result antonym or "" if no string available
+ */
+ QString getAntonym (int index) const;
+
+ /** returns type of this expression
+ *
+ * @result type or "" if no type available
+ */
+ QString getType (int index) const;
+
+ /** all langs have same type ?
+ *
+ * @result true if all have same type
+ */
+ bool uniqueType () const;
+
+ /** sets type of this expression
+ *
+ * @param index index of type
+ * @param type type of this expression ("" = none)
+ */
+ void setType (int index, const QString &type);
+
+ /** returns grade of given translation as string
+ *
+ * @param index index of expression
+ * @param rev_grade dito, in opposite direction
+ * @result number of knowlegde: 0=known, x=numbers not knows
+ */
+ QString gradeStr (int index, bool rev_grade = false) const;
+
+ /** sets grade of given translation
+ *
+ * @param index index of translation
+ * @param grade number of knowlegde: 0=known, x=numbers not knows
+ */
+ void setGrade (int index, grade_t grade, bool rev_grade = false);
+
+ /** returns grade of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_grade dito, in opposite direction
+ * @result number of knowlegde: 0=known, x=numbers not knows
+ */
+ grade_t getGrade (int index, bool rev_grade = false) const;
+
+ /** increments grade of given translation
+ *
+ * @param index index of translation
+ * @param rev_grade dito, in opposite direction
+ */
+ void incGrade (int index, bool rev_grade = false);
+
+ /** decrements grade of given translation
+ *
+ * @param index index of translation
+ * @param rev_grade dito, in opposite direction
+ */
+ void decGrade (int index, bool rev_grade = false);
+
+ /** returns last query date of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_date dito, in opposite direction
+ */
+ time_t getQueryDate (int index, bool rev_date = false) const;
+
+ /** set last query date of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_date dito, in opposite direction
+ */
+ void setQueryDate (int index, time_t date, bool rev_date = false);
+
+ /** returns conjugations if available
+ *
+ * @param index index of translation
+ */
+ Conjugation getConjugation(int index) const;
+
+ /** sets conjugations
+ *
+ * @param index index of translation
+ * @param con conjugation block
+ */
+ void setConjugation(int index, const Conjugation &con);
+
+ /** returns comparison if available
+ *
+ * @param index index of translation
+ */
+ Comparison getComparison(int index) const;
+
+ /** sets comparison
+ *
+ * @param index index of translation
+ * @param con comparison block
+ */
+ void setComparison(int index, const Comparison &comp);
+
+ /** returns multiple choice if available
+ *
+ * @param index index of multiple choice
+ */
+ MultipleChoice getMultipleChoice(int index) const;
+
+ /** sets multiple choice
+ *
+ * @param index index of translation
+ * @param con multiple choice block
+ */
+ void setMultipleChoice(int index, const MultipleChoice &mc);
+
+ /** returns query count of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ count_t getQueryCount (int index, bool rev_count = false) const;
+
+ /** set query count of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ void setQueryCount (int index, count_t count, bool rev_count = false);
+
+ /** returns bad query count of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ count_t getBadCount (int index, bool rev_count = false) const;
+
+ /** set bad query count of given translation as int
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ void setBadCount (int index, count_t count, bool rev_count = false);
+
+ /** increment bad query count of given translation by 1
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ void incBadCount (int index, bool rev_count = false);
+
+ /** increment query count of given translation by 1
+ *
+ * @param index index of translation
+ * @param rev_count dito, in opposite direction
+ */
+ void incQueryCount (int index, bool rev_count = false);
+
+ protected:
+
+ void Init();
+
+ private:
+ QString origin;
+
+ // all these vectors must be deleted in removeTranslation()
+ vector<QString> exprtypes;
+ vector<QString> translations;
+ vector<QString> remarks;
+ vector<QString> usageLabels;
+ vector<QString> paraphrases;
+ vector<QString> fauxAmi;
+ vector<QString> rev_fauxAmi;
+ vector<QString> synonym;
+ vector<QString> example;
+ vector<QString> antonym;
+ vector<QString> pronunces;
+ vector<grade_t> grades;
+ vector<grade_t> rev_grades;
+ vector<count_t> qcounts;
+ vector<count_t> rev_qcounts;
+ vector<count_t> bcounts;
+ vector<count_t> rev_bcounts;
+ vector<time_t> qdates;
+ vector<time_t> rev_qdates;
+ vector<Conjugation> conjugations;
+ vector<Comparison> comparisons;
+ vector<MultipleChoice> mcs;
+
+ int lesson;
+ bool inquery;
+ bool active;
+};
+
+#endif // KVOCTRAINEXPR_H
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/Makefile.am b/kvoctrain/kvoctrain/kvt-core/kvt-xml/Makefile.am
new file mode 100644
index 00000000..f44e9fea
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/Makefile.am
@@ -0,0 +1,10 @@
+INCLUDES = -I$(top_srcdir)/kvoctrain \
+ -I$(top_srcdir)/kvoctrain/kvoctrain \
+ $(all_includes)
+
+noinst_LTLIBRARIES = libkvtxml.la
+
+libkvtxml_la_SOURCES = XmlReader.cpp XmlTokenizer.cpp XmlElement.cpp XmlWriter.cpp
+
+# CLEANFILES += *~ # This breaks badly with automake 1.5
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.cpp b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.cpp
new file mode 100644
index 00000000..7b070c4f
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.cpp
@@ -0,0 +1,99 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+ -----------------------------------------------------------------------
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as
+ published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdlib.h>
+#include "XmlElement.h"
+
+XmlAttribute::XmlAttribute (const KOXML_STRING& n, const KOXML_STRING& v) :
+ aname (n), value (v) {
+}
+
+
+XmlAttribute::XmlAttribute (const XmlAttribute& attr) :
+ aname (attr.aname), value (attr.value) {
+}
+
+XmlAttribute::~XmlAttribute () {
+}
+
+
+XmlAttribute& XmlAttribute::operator= (const XmlAttribute& attr) {
+ aname = attr.aname;
+ value = attr.value;
+ return *this;
+}
+
+
+float XmlAttribute::floatValue () const {
+#ifndef KOXML_USE_STL
+ return atof (value.local8Bit());
+#else
+ return atof (value.data());
+#endif
+}
+
+
+int XmlAttribute::intValue () const {
+#ifndef KOXML_USE_STL
+ return atoi (value.local8Bit());
+#else
+ return atoi (value.data());
+#endif
+}
+
+
+XmlElement::XmlElement () {
+ closed = false;
+ endTag = false;
+}
+
+
+XmlElement::XmlElement (const XmlElement& elem) :
+ tagId (elem.tagId), closed (elem.closed), endTag (elem.endTag),
+ attribs (elem.attribs) {
+}
+
+
+XmlElement::~XmlElement () {
+}
+
+
+void XmlElement::reset () {
+ tagId = "";
+ closed = false;
+ endTag = false;
+ attribs.erase (attribs.begin (), attribs.end ());
+}
+
+
+XmlElement& XmlElement::operator= (const XmlElement& elem) {
+ tagId = elem.tagId;
+ closed = elem.closed;
+ endTag = elem.endTag;
+ attribs = elem.attribs;
+ return *this;
+}
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.h b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.h
new file mode 100644
index 00000000..50bb8e42
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlElement.h
@@ -0,0 +1,156 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+*/
+
+#ifndef XmlElement_h_
+#define XmlElement_h_
+
+#include "koxml_config.h"
+#include <list>
+
+/**
+ * An instance of XmlAttribute represents an attribute of
+ * XML elements. It provides methods for accessing the attribute
+ * value.
+ *
+ * @short A class for representing attributes of XML elements.
+ * @author Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de), modifications: Ewald Arnold (kvoctrain@ewald-arnold.de)
+ * @version 2000/07/02
+ */
+class XmlAttribute {
+public:
+ /**
+ * Construct an attribute from the given name and value.
+ *
+ * @param n The name of the attribute.
+ * @param v The attribute value.
+ */
+ XmlAttribute (const KOXML_STRING& n, const KOXML_STRING& v);
+
+ /**
+ * Copy constructor.
+ */
+ XmlAttribute (const XmlAttribute& attr);
+
+ /**
+ * Destructor.
+ */
+ ~XmlAttribute ();
+
+ /**
+ * The assignment operator.
+ */
+ XmlAttribute& operator= (const XmlAttribute& attr);
+
+ /**
+ * Return the name of the attribute.
+ *
+ * @return The attribute name.
+ */
+ inline const KOXML_STRING& name () const { return aname; }
+
+ /**
+ * Return a string representation of the attribute value.
+ *
+ * @return The attribute value as string.
+ */
+ inline const KOXML_STRING& stringValue () const { return value; }
+
+ /**
+ * Return a float representation of the attribute value.
+ *
+ * @return The attribute value as float.
+ */
+ float floatValue () const;
+
+ /**
+ * Return a integer representation of the attribute value.
+ *
+ * @return The attribute value as integer.
+ */
+ int intValue () const;
+
+private:
+ KOXML_STRING aname, value;
+};
+
+/**
+ * An instance of XmlElement represents an element (object) of a XML
+ * document. The elements consists of the tag (element ID) and a list
+ * of attributes.
+ *
+ * @short A class for representing XML elements.
+ * @author Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de), modifications: Ewald Arnold (kvoctrain@ewald-arnold.de)
+ * @version 2000/07/02
+ */
+class XmlElement {
+friend class XmlReader;
+public:
+ /**
+ * Construct a new XML element.
+ */
+ XmlElement ();
+
+ /**
+ * Copy constructor.
+ */
+ XmlElement (const XmlElement& elem);
+
+ /**
+ * Destructor.
+ */
+ ~XmlElement ();
+
+ void reset ();
+
+ /**
+ * The assignment operator.
+ */
+ XmlElement& operator= (const XmlElement& elem);
+
+ /**
+ * Return the ID of the element.
+ *
+ * @return The element ID.
+ */
+ inline const KOXML_STRING& tag () const { return tagId; }
+
+ /**
+ * Return the attributes of the element.
+ * @see XmlAttribute
+ *
+ * @return The list of attributes.
+ */
+ inline const std::list<XmlAttribute>& attributes () const { return attribs; }
+
+ /**
+ * Return @p true if the element is closed.
+ *
+ * @return @p true for a closed element.
+ */
+ inline bool isClosed () const { return closed; }
+
+ /**
+ * Return @p true if the element is an end tag.
+ *
+ * @return @p true for an end tag.
+ */
+ inline bool isEndTag () const { return endTag; }
+
+private:
+ KOXML_STRING tagId;
+ bool closed;
+ bool endTag;
+ std::list<XmlAttribute> attribs;
+};
+
+#endif
+
+
+
+
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.cpp b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.cpp
new file mode 100644
index 00000000..819d79a6
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.cpp
@@ -0,0 +1,264 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+ -----------------------------------------------------------------------
+
+ -----------------------------------------------------------------------
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as
+ published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <iostream>
+using namespace std;
+#include "XmlReader.h"
+
+XmlReader::XmlReader (KOXML_ISTREAM& is)
+ : tokenizer (is)
+{
+}
+
+XmlReader::~XmlReader () {
+}
+
+bool XmlReader::validHeader () {
+ // Check for: <? xml version="1.0" ?>
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Lt)
+ return false;
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_QSign)
+ return false;
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
+ return false;
+ else if (tokenizer.element () != "xml")
+ return false;
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
+ return false;
+ else if (tokenizer.element () != "version")
+ return false;
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Eq)
+ return false;
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_String)
+ return false;
+ else if (tokenizer.element () != "1.0")
+ return false;
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_QSign)
+ return false;
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Gt)
+ return false;
+
+ // Check for: <(!)doctype symbol system string>
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Lt)
+ return false;
+
+ XmlTokenizer::Token token = tokenizer.nextToken ();
+ if (token == XmlTokenizer::Tok_Exclam)
+ token = tokenizer.nextToken ();
+
+ if (token != XmlTokenizer::Tok_Symbol)
+ return false;
+ else if (tokenizer.element().lower() != "doctype")
+ return false;
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
+ return false;
+ s_dtype = tokenizer.element ();
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Symbol)
+ return false;
+ else if (tokenizer.element().lower() != "system")
+ return false;
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_String)
+ return false;
+ s_dtd = tokenizer.element ();
+
+ if (tokenizer.nextToken () != XmlTokenizer::Tok_Gt)
+ return false;
+
+ return true;
+}
+
+const KOXML_STRING& XmlReader::doctype () const {
+ return s_dtype;
+}
+
+const KOXML_STRING& XmlReader::dtd () const {
+ return s_dtd;
+}
+
+const KOXML_STRING& XmlReader::getText () {
+ return text;
+}
+
+bool XmlReader::readElement (XmlElement& elem) {
+ XmlTokenizer::Token tok;
+ bool result = false;
+ bool ready = false;
+
+ elem.reset ();
+
+ while (! ready) {
+ tok = tokenizer.nextToken ();
+ if (tok == XmlTokenizer::Tok_Lt) {
+ tok = tokenizer.nextToken ();
+ if (tok == XmlTokenizer::Tok_Comment) {
+ // skip comment
+ }
+ else {
+ if (tok == XmlTokenizer::Tok_Slash)
+ result = parseEndElement (elem);
+ else if (tok == XmlTokenizer::Tok_Symbol)
+ result = parseElement (tokenizer.element (), elem);
+ else if (tok == XmlTokenizer::Tok_EOF)
+ result = false;
+ ready = true;
+ }
+ }
+ else if (tok == XmlTokenizer::Tok_Text) {
+ elem.tagId = "#PCDATA";
+ text = tokenizer.element ();
+ result = true;
+ ready = true;
+ }
+ else
+ return false;
+ }
+ return result;
+}
+
+bool XmlReader::parseEndElement (XmlElement& elem) {
+ bool result = false;
+
+ XmlTokenizer::Token tok = tokenizer.nextToken ();
+ if (tok == XmlTokenizer::Tok_Symbol) {
+ KOXML_STRING tag = tokenizer.element ();
+ tok = tokenizer.nextToken ();
+ if (tok == XmlTokenizer::Tok_Gt) {
+ elem.tagId = tag;
+ elem.endTag = true;
+ elem.closed = true;
+ result = true;
+ }
+ }
+ return result;
+}
+
+bool XmlReader::parseElement (const KOXML_STRING& id, XmlElement& elem) {
+ KOXML_STRING tag = id;
+ bool closed = false;
+ std::list<XmlAttribute> attrib_list;
+
+ XmlTokenizer::Token tok = tokenizer.nextToken ();
+ while (tok != XmlTokenizer::Tok_Gt) {
+ if (tok == XmlTokenizer::Tok_Slash) {
+ if (closed)
+ return false;
+ else
+ closed = true;
+ }
+ else if (tok == XmlTokenizer::Tok_Symbol) {
+ if (! attrib_list.empty () || closed)
+ return false;
+ tokenizer.unget ();
+ if (! readAttributes (attrib_list))
+ return false;
+ }
+ else
+ return false;
+
+ tok = tokenizer.nextToken ();
+ }
+ elem.tagId = tag;
+ elem.endTag = false;
+ elem.closed = closed;
+ elem.attribs = attrib_list;
+ return true;
+}
+
+bool XmlReader::readAttributes (std::list<XmlAttribute>& attrib_list) {
+ XmlTokenizer::Token tok = tokenizer.nextToken ();
+
+ while (tok != XmlTokenizer::Tok_Gt) {
+ if (tok == XmlTokenizer::Tok_Symbol) {
+ KOXML_STRING id = tokenizer.element ();
+ if (tokenizer.nextToken () == XmlTokenizer::Tok_Eq) {
+ if (tokenizer.nextToken () == XmlTokenizer::Tok_String) {
+
+ // un-escape dangerous characters in reverted order
+ KOXML_STRING val = tokenizer.element();
+ int pos = 0;
+ while ((pos = val.find("&quot;", pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 6);
+ KOXML_STRING_INSERT( val, pos, "\"");
+ pos += 1; // skip "
+ }
+ pos = 0;
+ while ((pos = val.find("&lf;", pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 4);
+ KOXML_STRING_INSERT( val, pos, "\r");
+ pos += 1; // skip \r
+ }
+ pos = 0;
+ while ((pos = val.find("&nl;", pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 4);
+ KOXML_STRING_INSERT( val, pos, "\n");
+ pos += 1; // skip \n
+ }
+ pos = 0;
+ while ((pos = val.find("&lt;", pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 4);
+ KOXML_STRING_INSERT( val, pos, "<");
+ pos += 1; // skip <
+ }
+ pos = 0;
+ while ((pos = val.find ("&amp;", pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos+1, 4);
+ pos += 1; // skip &
+ }
+
+ XmlAttribute attrib (id, val);
+ attrib_list.push_back (attrib);
+ }
+ else {
+ cerr << "invalid attribute value" << endl;
+ return false;
+ }
+ }
+ else {
+ cerr << "missing '='" << endl;
+ return false;
+ }
+ }
+ else if (tok == XmlTokenizer::Tok_Slash) {
+ break;
+ }
+ else {
+ cerr << "invalid attribute name: " << (int) tok << endl;
+ return false;
+ }
+ tok = tokenizer.nextToken ();
+ }
+ tokenizer.unget ();
+ return true;
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.h b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.h
new file mode 100644
index 00000000..0c7904af
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlReader.h
@@ -0,0 +1,104 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+*/
+
+#ifndef XmlReader_h_
+#define XmlReader_h_
+
+#include "XmlElement.h"
+#include "XmlTokenizer.h"
+
+class KOXML_ISTREAM;
+
+/**
+ * The XMLReader class supports reading elements from a XML stream.
+ *
+ * @short A class for reading XML elements from a stream.
+ * @author Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de), modifications: Ewald Arnold (kvoctrain@ewald-arnold.de)
+ * @version 2000/07/02
+ */
+class XmlReader {
+public:
+ /**
+ * Construct a XmlReader instance for the given input stream.
+ *
+ * @param is The open input stream.
+ */
+ XmlReader (KOXML_ISTREAM& is);
+
+ /**
+ * Desctructor
+ */
+ ~XmlReader ();
+
+ /**
+ * Check the input stream for a valid XML header.
+ * A header should look like
+ * <pre>
+ * <?xml version="1.0"?>
+ * <!doctype dtype system dtd>
+ * </pre>
+ * where @p dtype and @p dtd are simple strings.
+ *
+ * @return @p true if the header conforms to XML, otherwise
+ * @p false.
+ */
+ bool validHeader ();
+
+ /**
+ * Return the document type.
+ *
+ * @return The name of the document type.
+ */
+ const KOXML_STRING& doctype () const;
+
+ /**
+ * Return the name of the document type definition.
+ *
+ * @return The name of the DTD.
+ */
+ const KOXML_STRING& dtd () const;
+
+ /**
+ * Read a XML element from the stream. If the content is plain text
+ * (no tag), an element with the pseudo ID @p #PCDATA is returned
+ * and the text is available via method getText.
+ *
+ * @see #getText
+ *
+ * @param elem The XML element which is initialized by the method.
+ * @return @p true for successful reading.
+ */
+ bool readElement (XmlElement& elem);
+
+ /**
+ * Read plain text from the stream.
+ *
+ * @return The text as a string.
+ */
+ const KOXML_STRING& getText ();
+
+ /**
+ * Returns current line number
+ *
+ * @return The current line number
+ */
+ inline int lineNumber() { return tokenizer.lineNumber(); }
+
+protected:
+ bool parseEndElement (XmlElement& elem);
+ bool parseElement (const KOXML_STRING& id, XmlElement& elem);
+ bool readAttributes (std::list<XmlAttribute>& attrib_list);
+
+private:
+ XmlTokenizer tokenizer;
+ KOXML_STRING s_dtype,
+ s_dtd;
+ KOXML_STRING text;
+};
+
+#endif
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.cpp b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.cpp
new file mode 100644
index 00000000..b2fde685
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.cpp
@@ -0,0 +1,411 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+ -----------------------------------------------------------------------
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as
+ published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "XmlTokenizer.h"
+#include <ctype.h>
+
+XmlTokenizer::XmlTokenizer (KOXML_ISTREAM& is) :
+ last_chars (""), istrm (is), use_last (false), is_open (false), lineno(1) {
+}
+
+XmlTokenizer::~XmlTokenizer () {
+}
+
+
+/*
+bool XmlTokenizer::hasMoreTokens () {
+ return ! istrm.eof ();
+}
+*/
+
+void XmlTokenizer::skipWhitespace () {
+ KOXML_CHAR c;
+ do {
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+ if (! isspace (c)) {
+ putback (c);
+ return;
+ }
+ else if (istrm.eof ())
+ return;
+ } while (1);
+}
+
+
+void XmlTokenizer::putback (KOXML_CHAR c) {
+ last_chars += c;
+}
+
+
+KOXML_CHAR XmlTokenizer::readchar () {
+
+ KOXML_CHAR c;
+
+ if (last_chars.length() > 0) {
+ c = last_chars[0];
+ KOXML_STRING_REMOVE (last_chars, 0, 1);
+ }
+ else {
+
+# ifndef KOXML_USE_STL
+ istrm >> c;
+# else
+ istrm.get(c);
+# endif
+ }
+
+ return c;
+}
+
+
+void XmlTokenizer::unget () {
+ use_last = true;
+}
+
+XmlTokenizer::Token XmlTokenizer::nextToken () {
+ KOXML_CHAR c;
+
+ if (use_last) {
+ use_last = false;
+ return last_tok;
+ }
+
+ skipWhitespace ();
+ if (istrm.eof ())
+ return last_tok = Tok_EOF;
+
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+
+ if (!is_open) {
+ if (c != '<') {
+ putback (c);
+ return last_tok = readText ();
+ }
+ }
+ switch (c) {
+ case '<':
+ is_open = true;
+ return last_tok = Tok_Lt;
+ break;
+ case '>':
+ is_open = false;
+ return last_tok = Tok_Gt;
+ break;
+ case '?':
+ return last_tok = Tok_QSign;
+ break;
+ case '/':
+ return last_tok = Tok_Slash;
+ break;
+ case '=':
+ return last_tok = Tok_Eq;
+ break;
+ case '(':
+ return last_tok = Tok_LParen;
+ break;
+ case ')':
+ return last_tok = Tok_RParen;
+ break;
+ case '[':
+ return last_tok = Tok_LBracket;
+ break;
+ case ']':
+ return last_tok = Tok_RBracket;
+ break;
+ case '|':
+ return last_tok = Tok_Bar;
+ break;
+ case '*':
+ return last_tok = Tok_Asterisk;
+ break;
+ case '+':
+ return last_tok = Tok_Plus;
+ break;
+ case ',':
+ return last_tok = Tok_Comma;
+ break;
+ case ';':
+ return last_tok = Tok_Semicolon;
+ break;
+ case '%':
+ return last_tok = Tok_Percent;
+ break;
+ case '#':
+ return last_tok = Tok_NSign;
+ break;
+ case '\'':
+ return last_tok = Tok_Apostr;
+ break;
+ case '"':
+ // String einlesen
+ return last_tok = readString ();
+ break;
+ default:
+ if (is_open) {
+ if (isalpha (c) || isdigit (c)) {
+ // Symbol (Element oder Attributbezeichner)
+ putback (c);
+ return last_tok = readSymbol ();
+ }
+ else if (c == '!') {
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+ putback (c);
+ if (c == '-')
+ return last_tok = readComment ();
+ else
+ return last_tok = Tok_Exclam;
+ }
+ else {
+ return last_tok = Tok_Invalid;
+ }
+ }
+ else {
+ putback (c);
+ return last_tok = readText ();
+ }
+ break;
+ }
+}
+
+
+const KOXML_STRING& XmlTokenizer::element () {
+ return elem;
+}
+
+
+XmlTokenizer::Token XmlTokenizer::readSymbol () {
+ KOXML_CHAR c;
+ elem = "";
+
+ while (1) {
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+ if (istrm.eof () || isspace (c))
+ // Symbol ist abgeschlossen
+ break;
+ else if (c == '=' || c == '/' || c == '>' || c == '?' || c == '|' ||
+ c == ')' || c == '\'' || c == ',' || c == ';') {
+ // Symbol ist abgeschlossen, das gelesene Zeichen wird
+ // aber noch benoetigt
+ putback (c);
+ break;
+ }
+ else if (isalnum (c) || c == '-' || (c == '_' && elem.length () > 0))
+ // korrektes Zeichen -> anhaengen
+// elem += tolower (c); ?????????
+ elem += c;
+ else {
+ // Zeichen nicht erlaubt ?
+ return Tok_Invalid;
+ }
+ }
+ // alle Grossbuchstaben in Kleinbuchstaben aendern !!!!
+ return Tok_Symbol;
+}
+
+
+XmlTokenizer::Token XmlTokenizer::readString () {
+ KOXML_CHAR c;
+ elem = "";
+
+ while (1) {
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+
+ if (istrm.eof ())
+ // String ist noch nicht abgeschlossen
+ return Tok_Invalid;
+ else if (c == '\\') {
+ // naechstes Zeichen quoten
+ }
+ else if (c == '"') {
+ // String ist abgeschlossen
+ return Tok_String;
+ }
+ else
+ elem += c;
+ }
+}
+
+XmlTokenizer::Token XmlTokenizer::readComment () {
+ KOXML_CHAR c1, c2;
+ elem = "";
+
+ c1 = readchar ();
+ if (c1 == '\n')
+ lineno++;
+ c2 = readchar ();
+ if (c2 == '\n')
+ lineno++;
+
+ if (c1 != '-' || c2 != '-' || istrm.eof ())
+ return Tok_Invalid;
+
+ while (1) {
+ c1 = readchar ();
+ if (istrm.eof ())
+ return Tok_Invalid;
+ else if (c1 == '\n')
+ lineno++;
+ else if (c1 == '>')
+ return Tok_Comment;
+ else
+ elem += c1;
+ }
+}
+
+XmlTokenizer::Token XmlTokenizer::readText () {
+ KOXML_CHAR c;
+ elem = "";
+
+ while (1) {
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+
+ if (istrm.eof ())
+ return Tok_EOF;
+ else if (c == '<') {
+ putback (c);
+ return Tok_Text;
+ }
+ else if (c == '&') {
+ KOXML_STRING s;
+ while (c != ';') {
+ s += c;
+ c = readchar ();
+ if (c == '\n')
+ lineno++;
+ if (istrm.eof ())
+ return Tok_EOF;
+ }
+ if (s == "&lt")
+ elem += "<";
+ else if (s == "&gt")
+ elem += ">";
+ else if (s == "&amp")
+ elem += "&";
+ else if (s == "&lf")
+ elem += "\r";
+ else if (s == "&nl")
+ elem += "\n";
+// entities ?
+// elem += "[" + s +";]";
+ }
+ else
+ elem += c;
+ }
+}
+
+#ifdef TEST
+int main (int argc, char** argv) {
+ XmlTokenizer::Token tok;
+
+ XmlTokenizer tokenizer (cin);
+
+ while ((tok = tokenizer.nextToken ()) != XmlTokenizer::Tok_EOF) {
+ switch (tok) {
+ case XmlTokenizer::Tok_Exclam:
+ cout << "! ";
+ break;
+ case XmlTokenizer::Tok_Bar:
+ cout << "| ";
+ break;
+ case XmlTokenizer::Tok_LParen:
+ cout << "( ";
+ break;
+ case XmlTokenizer::Tok_RParen:
+ cout << ") ";
+ break;
+ case XmlTokenizer::Tok_LBracket:
+ cout << "[ ";
+ break;
+ case XmlTokenizer::Tok_RBracket:
+ cout << "] ";
+ break;
+ case XmlTokenizer::Tok_Plus:
+ cout << "+ ";
+ break;
+ case XmlTokenizer::Tok_Asterisk:
+ cout << "* ";
+ break;
+ case XmlTokenizer::Tok_Comma:
+ cout << ", ";
+ break;
+ case XmlTokenizer::Tok_Semicolon:
+ cout << "; ";
+ break;
+ case XmlTokenizer::Tok_NSign:
+ cout << "# ";
+ break;
+ case XmlTokenizer::Tok_Apostr:
+ cout << "' ";
+ break;
+ case XmlTokenizer::Tok_Percent:
+ cout << "% ";
+ break;
+ case XmlTokenizer::Tok_Lt:
+ cout << "< ";
+ break;
+ case XmlTokenizer::Tok_Gt:
+ cout << "> ";
+ break;
+ case XmlTokenizer::Tok_QSign:
+ cout << "? ";
+ break;
+ case XmlTokenizer::Tok_Slash:
+ cout << "/ ";
+ break;
+ case XmlTokenizer::Tok_Eq:
+ cout << "= ";
+ break;
+ case XmlTokenizer::Tok_Symbol:
+ cout << "SYMBOL(" << tokenizer.element () << ") ";
+ break;
+ case XmlTokenizer::Tok_String:
+ cout << "STRING(" << tokenizer.element () << ") ";
+ break;
+ case XmlTokenizer::Tok_Comment:
+ cout << "COMMENT > ";
+ break;
+ case XmlTokenizer::Tok_Text:
+ cout << "TEXT(" << tokenizer.element () << ") ";
+ break;
+ default:
+ cout << "INVALID(" << tok << ")" << endl;
+ return 1;
+ break;
+ }
+ }
+}
+#endif
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.h b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.h
new file mode 100644
index 00000000..d78b6c7e
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlTokenizer.h
@@ -0,0 +1,108 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+*/
+
+#ifndef XmlTokenizer_h_
+#define XmlTokenizer_h_
+
+#include "koxml_config.h"
+
+/**
+ * The XMLTokenizer class allows an application to break a XML stream
+ * into tokens.
+ *
+ * @short A class for tokenizing an XML stream.
+ * @author Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de), modifications: Ewald Arnold (kvoctrain@ewald-arnold.de)
+ * @version 2000/07/02
+ */
+class XmlTokenizer {
+public:
+ /**
+ * The expected tokens for a XML stream.
+ */
+ enum Token { Tok_Invalid, /* 0 */
+ Tok_EOF, /* 1 */
+ Tok_Symbol, /* 2 */
+ Tok_String, /* 3 */
+ Tok_Text, /* 4 */
+ Tok_Comment, /* 5 */
+ Tok_Lt, /* < 6 */
+ Tok_Gt, /* > 7 */
+ Tok_QSign, /* ? 8 */
+ Tok_Eq, /* = 9 */
+ Tok_Slash, /* / 10 */
+ Tok_Exclam, /* ! 11 */
+ Tok_Bar, /* | 12 */
+ Tok_LParen, /* ( 13 */
+ Tok_RParen, /* ) 14 */
+ Tok_LBracket, /* [ 15 */
+ Tok_RBracket, /* ] 16 */
+ Tok_Plus, /* + 17 */
+ Tok_Asterisk, /* * 18 */
+ Tok_Comma, /* , 19 */
+ Tok_Semicolon,/* ; 20 */
+ Tok_NSign, /* # 21 */
+ Tok_Apostr, /* ' 22 */
+ Tok_Percent /* % 23 */
+ };
+
+ /**
+ * Create a XmlTokenizer instance for the given input stream.
+ *
+ * @param is The open input stream for reading.
+ */
+ XmlTokenizer (KOXML_ISTREAM& is);
+
+ /**
+ * Destructor.
+ */
+ ~XmlTokenizer ();
+
+ /**
+ * Return the next token from the stream.
+ * @return The next token from the stream.
+ */
+ Token nextToken ();
+
+ /**
+ * Return the string representation of the current token.
+ *
+ * @return The string representation.
+ */
+ const KOXML_STRING& element ();
+
+ KOXML_CHAR readchar ();
+ void putback (KOXML_CHAR c);
+
+ /**
+ * Cause the next call to method @p nextToken of this tokenizer
+ * to return the current token.
+ */
+ void unget ();
+
+ inline int lineNumber() { return lineno; }
+
+protected:
+ void skipWhitespace ();
+ Token readString ();
+ Token readSymbol ();
+ Token readText ();
+ Token readComment ();
+
+private:
+// QIODevice *strm;
+ KOXML_STRING last_chars;
+ KOXML_ISTREAM &istrm;
+ KOXML_STRING elem;
+ Token last_tok;
+ bool use_last;
+ bool is_open;
+ int lineno;
+};
+
+#endif
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.cpp b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.cpp
new file mode 100644
index 00000000..38dfdbf2
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.cpp
@@ -0,0 +1,253 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+ -----------------------------------------------------------------------
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as
+ published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "XmlWriter.h"
+
+XmlWriter::XmlWriter (KOXML_OSTREAM& os)
+ : strm (os)
+{
+ autoendl = true;
+ isapo = false;
+ apo = 0;
+ strm << "<?xml version=\"1.0\"?>" << endl; // "encoding=UTF8"
+}
+
+
+XmlWriter::~XmlWriter () {
+ flush ();
+}
+
+
+void XmlWriter::startTag (KOXML_STRING id, bool closeIt, bool empty, bool eol)
+{
+ if (!id) return;
+
+ strm << "<" << id;
+ if (!empty) {
+ lastTags.push (id);
+ }
+
+ if (closeIt) {
+ if (empty)
+ strm << "/";
+ strm << ">";
+ if (eol || autoendl) {
+ isapo = false;
+ apo = 0;
+ strm << endl;
+ }
+ }
+}
+
+
+void XmlWriter::endTag (KOXML_STRING id, bool eol)
+{
+ strm << "</";
+ if (id.length() != 0)
+ strm << id;
+ else {
+ KOXML_STRING tag = lastTags.top ();
+ lastTags.pop ();
+ strm << tag;
+ }
+ strm << ">";
+ if (eol || autoendl) {
+ isapo = false;
+ apo = 0;
+ strm << endl;
+ }
+}
+
+void XmlWriter::closeTag (bool empty, bool eol)
+{
+ if (empty) {
+ strm << "/";
+ lastTags.pop ();
+ }
+ strm << ">";
+ if (eol || autoendl) {
+ isapo = false;
+ apo = 0;
+ strm << endl;
+ }
+}
+
+
+void XmlWriter::setAutoEndl (const bool flag)
+{
+ autoendl = flag;
+}
+
+
+void XmlWriter::endline()
+{
+ isapo = false;
+ apo = 0;
+ strm << endl;
+}
+
+
+void XmlWriter::addAttribute (KOXML_STRING name, const KOXML_STRING& value)
+{
+ if (!name) return;
+
+ KOXML_STRING val = value;
+ // escape dangerous characters in sgml-style
+ int pos = 0;
+ while ((pos = val.find ('&', pos)) >= 0) {
+ KOXML_STRING_INSERT( val, pos+1, "amp;");
+ pos += 5; // skip &amp;
+ }
+ pos = 0;
+ while ((pos = val.find ('<', pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 1);
+ KOXML_STRING_INSERT( val, pos, "&lt;");
+ pos += 4; // skip &nl;
+ }
+ pos = 0;
+ while ((pos = val.find ('\n', pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 1);
+ KOXML_STRING_INSERT( val, pos, "&nl;");
+ pos += 4; // skip &nl;
+ }
+ pos = 0;
+ while ((pos = val.find ('\r', pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 1);
+ KOXML_STRING_INSERT( val, pos+1, "lf;");
+ pos += 4; // skip &lf;
+ }
+ pos = 0;
+ while ((pos = val.find ('\"', pos)) >= 0) {
+ KOXML_STRING_REMOVE( val, pos, 1);
+ KOXML_STRING_INSERT( val, pos, "&quot;");
+ pos += 6; // skip &qout;
+ }
+
+ strm << " ";
+ strm << name << "=\"";
+ strm << val;
+ strm << "\"";
+}
+
+
+void XmlWriter::addAttribute (KOXML_STRING name, int value)
+{
+ if (name.length() == 0)
+ return;
+
+ strm << " ";
+ strm << name << "=\"";
+ strm << value;
+ strm << "\"";
+}
+
+
+void XmlWriter::addAttribute (KOXML_STRING name, float value)
+{
+ if (name.length() == 0)
+ return;
+
+ strm << " ";
+ strm << name << "=\"";
+ strm << value;
+ strm << "\"";
+}
+
+
+void XmlWriter::addAttribute (KOXML_STRING name, double value)
+{
+ if (name.length() == 0)
+ return;
+
+ strm << " ";
+ strm << name << "=\"";
+ strm << value;
+ strm << "\"";
+}
+
+
+void XmlWriter::writeText (KOXML_STRING c)
+{
+ int i = 0;
+ while (i < (int) c.length()) {
+ if (c[i] == '<')
+ strm << "&lt;";
+ else if (c[i] == '&')
+ strm << "&amp;";
+ else if (c[i] == '>')
+ strm << "&gt;";
+ else if (c[i] == '\"' || c[i] == '\'' || c[i] == '`') {
+ strm << c[i];
+ if (isapo) {
+ if (apo == c[i])
+ isapo = false;
+ }
+ else {
+ isapo = true;
+ apo = c[i];
+ }
+ }
+ else if (c[i] == '\n') {
+ if (isapo)
+ strm << "&nl;";
+ else
+ strm << c[i];
+ }
+ else if (c[i] == '\r') {
+ if (isapo)
+ strm << "&lf;";
+ else
+ strm << c[i];
+ }
+ else
+ strm << c[i];
+ i++;
+ }
+}
+
+
+void XmlWriter::indent (int i)
+{
+ for (; i > 0; i--)
+ strm << " ";
+}
+
+
+void XmlWriter::writeTag (KOXML_STRING s)
+{
+ strm << "<"
+ << s
+ << ">";
+}
+
+
+void XmlWriter::flush ()
+{
+#ifndef KOXML_USE_STL
+ stream()->flush ();
+#else
+ strm.flush();
+#endif
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.h b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.h
new file mode 100644
index 00000000..d73bce59
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/XmlWriter.h
@@ -0,0 +1,187 @@
+/* -*- C++ -*-
+
+ This file is part of KIllustrator.
+ Copyright (C) 1998 Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+ modified for kvoctrain by Ewald Arnold kvoctrain@ewald-arnold.dein April ´99
+
+*/
+
+#ifndef XmlWriter_h_
+#define XmlWriter_h_
+
+#if defined(stack)
+#undef stack
+#endif
+
+#include <stack>
+#include <vector>
+using namespace std;
+
+#include "koxml_config.h"
+
+class KOXML_OSTREAM;
+/**
+ * The XMLWriter class provides support for writing XML streams.
+ * It contains methods for output XML elements with attributes.
+ *
+ * Sample code:
+ * <pre>
+ * KOXML_OSTREAM os (fname);
+ * XmlWriter xml (os); // writes the XML header
+ *
+ * xml.startTag ("head"); // writes &lt;head&gt;
+ *
+ * // write &lt;layout format="a4" orientation="landscape"&gt;
+ * xml.startTag ("layout", false);
+ * xml.addAttribute ("format", "a4");
+ * xml.addAttribute ("orientation", "landscape");
+ * xml.closeTag (true);
+ * </pre>
+ *
+ * @short A helper class for writing XML.
+ * @author Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de), modifications: Ewald Arnold (kvoctrain@ewald-arnold.de)
+ * @version 2000/07/02
+
+ */
+class XmlWriter {
+public:
+ /**
+ * Create a XmlWriter instance for the given output stream.
+ *
+ * @param os The open output stream for writing.
+ */
+ XmlWriter (KOXML_OSTREAM& os);
+
+ /**
+ * Desctructor.
+ */
+ ~XmlWriter ();
+
+ /**
+ * Write an element with the given ID to the XML stream. Attributes
+ * can be added later.
+ *
+ * @param id The element ID.
+ * @param closeIt If @p true the tag is closed by >,
+ * otherwise not.
+ * @param empty If @p true an empty element is written, which
+ * is closed by />.
+ * @param eol If @p true an eol char is appended
+ * even if autoendl is false
+ */
+ void startTag (KOXML_STRING id, bool closeIt = true, bool empty = false, bool eol = false);
+
+ /**
+ * Write the end tag according to the given element ID or to the
+ * last opened element.
+ *
+ * @param id The element ID. If @p "" the last opened
+ * element is ended. (default).
+ * @param eol If @p true an eol char is appended
+ * even if autoendl is false
+ */
+ void endTag (KOXML_STRING id = "", bool eol = false);
+
+ /**
+ * flag, indicating to automatically append end-of-line character after
+ * closing bracket
+ *
+ * @param autoflag If @p true, append eol character. Otherwise caller has to do it
+ */
+ void setAutoEndl (const bool autoflag = true);
+
+ /**
+ * append end-of-line char to stream
+ */
+ void endline ();
+
+ /**
+ * Close the current open element.
+ *
+ * @param empty If @p true an empty element is closed.
+ * @param eol If @p true an eol char is appended
+ * even if autoendl is false
+ */
+ void closeTag (bool empty = false, bool eol = false);
+
+ /**
+ * Add an attribute with the given value to the current element.
+ * This method doesn't check, if an element is open.
+ *
+ * @param name The attribute name.
+ * @param value The string value of the attribute.
+ */
+ void addAttribute (KOXML_STRING name, const KOXML_STRING& value);
+
+ /**
+ * Add an attribute with the given value to the current element.
+ * This method doesn't check, if an element is open.
+ *
+ * @param name The attribute name.
+ * @param value The integer value of the attribute.
+ */
+ void addAttribute (KOXML_STRING name, int value);
+
+ /**
+ * Add an attribute with the given value to the current element.
+ * This method doesn't check, if an element is open.
+ *
+ * @param name The attribute name.
+ * @param value The float value od the attribute.
+ */
+ void addAttribute (KOXML_STRING name, float value);
+
+ /**
+ * Add an attribute with the given value to the current element.
+ * This method doesn't check, if an element is open.
+ *
+ * @param name The attribute name.
+ * @param value The double value of the attribute.
+ */
+ void addAttribute (KOXML_STRING name, double value);
+
+ /**
+ * Write text to the XML stream. The method encodes the special
+ * characters @p <, @p > and @p &.
+ *
+ * @param s The text.
+ */
+ void writeText (KOXML_STRING s);
+
+ /**
+ * Write a tag to the XML stream.
+ *
+ * @param s The tag without the brackets.
+ */
+ void writeTag (KOXML_STRING s);
+
+ /**
+ * indents next text string with some spaces
+ *
+ * @param i number of spaces to indent
+ */
+ void indent (int i);
+
+ /**
+ * Flush the XML output stream.
+ */
+ void flush ();
+
+#ifndef KOXML_USE_STL
+ /**
+ * Get the raw output stream.
+ */
+ inline QIODevice *stream () { return strm.device(); }
+#endif
+
+private:
+ stack<KOXML_STRING, vector<KOXML_STRING> > lastTags;
+
+ KOXML_OSTREAM &strm;
+ bool autoendl;
+ bool isapo;
+ KOXML_CHAR apo;
+};
+
+#endif
diff --git a/kvoctrain/kvoctrain/kvt-core/kvt-xml/koxml_config.h b/kvoctrain/kvoctrain/kvt-core/kvt-xml/koxml_config.h
new file mode 100644
index 00000000..2f0daecb
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/kvt-xml/koxml_config.h
@@ -0,0 +1,47 @@
+//#define KOXML_USE_STL
+
+/*
+ -----------------------------------------------------------------------
+
+ -----------------------------------------------------------------------
+*/
+
+#ifndef KOXML_USE_STL
+
+# include <qtextstream.h>
+# define KOXML_ISTREAM QTextStream
+# define KOXML_OSTREAM QTextStream
+
+# include <qstring.h>
+# define KOXML_STRING QString
+
+// Unicode character
+# define KOXML_CHAR QChar
+
+# define KOXML_STRING_REMOVE( string_var, pos, count) string_var.remove (pos, count)
+# define KOXML_STRING_INSERT( string_var, pos, str) string_var.insert(pos, str)
+
+#else
+
+# include <iostream>
+using namespace std;
+# define KOXML_ISTREAM istream
+# define KOXML_OSTREAM ostream
+
+# define KOXML_CHAR char // evtl. wchar
+
+////////////////////////////////////////////////////////
+//evtl. an MFC o.ä. anpassen
+#ifdef __MFC_STRING_BENUTZT__
+
+#else
+
+# include <string>
+# define KOXML_STRING string // evtl. wstring
+
+# define KOXML_STRING_REMOVE( string_var, pos, count) string_var.erase (pos, count)
+# define KOXML_STRING_INSERT( string_var, pos, str) string_var.insert(pos, (string)str)
+
+#endif
+
+#endif
diff --git a/kvoctrain/kvoctrain/kvt-core/langset.cpp b/kvoctrain/kvoctrain/kvt-core/langset.cpp
new file mode 100644
index 00000000..644878e7
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/langset.cpp
@@ -0,0 +1,220 @@
+/***************************************************************************
+
+ properties for a language
+
+ -----------------------------------------------------------------------
+
+ begin : Wed Jun 30 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 "langset.h"
+
+// void LangSet::addSet (QString _shortId, QString _longId,
+// QString _PixMapFile, const QString& keyboardLayout)
+// {
+// LangDef def;
+// def.shortId = _shortId;
+// def.shortId2 = "";
+// def.longId = _longId;
+// def.PixMapFile = _PixMapFile;
+// def.keyboardLayout = keyboardLayout;
+// langs.push_back (def);
+// }
+
+
+void LangSet::addSet (QString _shortId, QString _longId,
+ QString _PixMapFile, const QString& _shortId2,
+ const QString& keyboardLayout)
+
+{
+ LangDef def;
+ def.shortId = _shortId;
+ def.shortId2 = _shortId2;
+ def.longId = _longId;
+ def.PixMapFile = _PixMapFile;
+ def.keyboardLayout = keyboardLayout;
+ langs.push_back (def);
+}
+
+
+void LangSet::appendSet(const LangSet &set)
+{
+ for (int i = 0; i < (int) set.size(); ++i) {
+ addSet(set.langs[i].shortId, set.langs[i].longId, set.langs[i].PixMapFile,
+ set.langs[i].shortId2, set.langs[i].keyboardLayout);
+ }
+}
+
+
+void LangSet::clear()
+{
+ langs.clear();
+}
+
+
+void LangSet::erase (int idx)
+{
+ if (idx >= 0 && idx < (int) langs.size() )
+ langs.erase (langs.begin() + idx);
+}
+
+
+QString LangSet::shortId (int index) const
+{
+ if (index >= 0 && index < (int) langs.size() )
+ return langs[index].shortId;
+
+ return QString::null;
+}
+
+
+QString LangSet::shortId2 (int index) const
+{
+ if (index >= 0 && index < (int) langs.size() )
+ return langs[index].shortId2;
+
+ return QString::null;
+}
+
+
+QString LangSet::longId (int index) const
+{
+ if (index >= 0 && index < (int) langs.size() )
+ return langs[index].longId;
+
+ return QString::null;
+}
+
+
+QString LangSet::PixMapFile (int index) const
+{
+ if (index >= 0 && index < (int) langs.size() )
+ return langs[index].PixMapFile;
+ return "";
+}
+
+QString LangSet::keyboardLayout (int index) const
+{
+ if (index >= 0 && index < (int) langs.size()) {
+ return langs[index].keyboardLayout;
+ }
+ else {
+ return QString::null;
+ }
+}
+
+
+QString LangSet::findShortId (const QString &_longId) const
+{
+ if (_longId.isEmpty())
+ return "";
+
+ for (int i = 0; i < (int) langs.size(); i++ )
+ if (_longId == langs[i].longId)
+ return langs[i].shortId;
+
+ return QString::null;
+}
+
+
+QString LangSet::findLongId (const QString &_shortId) const
+{
+ if (_shortId.isEmpty())
+ return "";
+
+ for (int i = 0; i < (int) langs.size(); i++ )
+ if ( _shortId == langs[i].shortId
+ || _shortId == langs[i].shortId2)
+ return langs[i].longId;
+
+ return QString::null;
+}
+
+
+int LangSet::indexShortId (QString _shortId) const
+{
+ if (_shortId.isEmpty())
+ return -1;
+
+ for (int i = 0; i < (int) langs.size(); i++) {
+ if ( langs[i].shortId == _shortId
+ ||langs[i].shortId2 == _shortId )
+ return i;
+ }
+ return -1;
+}
+
+
+int LangSet::indexLongId (QString _longId) const
+{
+ if (_longId.isEmpty())
+ return -1;
+
+ for (int i = 0; i < (int) langs.size(); i++) {
+ if (langs[i].longId == _longId)
+ return i;
+ }
+ return -1;
+}
+
+
+int LangSet::indexPixMapFile (QString PixMapFile) const
+{
+ int id = -1;
+ for (int i = 0; i < (int) langs.size(); i++)
+ if (langs[i].PixMapFile == PixMapFile)
+ id = i;
+ return id;
+}
+
+void LangSet::setShortId (const QString & s, int index)
+{
+ if (index < (int) langs.size() )
+ langs[index].shortId = s;
+}
+
+
+void LangSet::setShortId2 (const QString & s, int index)
+{
+ if (index < (int) langs.size() )
+ langs[index].shortId2 = s;
+}
+
+
+void LangSet::setLongId (const QString & s, int index)
+{
+ if (index < (int) langs.size() )
+ langs[index].longId = s;
+}
+
+
+void LangSet::setPixMapFile (const QString & s, int index)
+{
+ if (index < (int) langs.size() )
+ langs[index].PixMapFile = s;
+}
+
+void LangSet::setKeyboardLayout(const QString& layout, int index)
+{
+ if (index < (int) langs.size()) {
+ langs[index].keyboardLayout = layout;
+ }
+}
diff --git a/kvoctrain/kvoctrain/kvt-core/langset.h b/kvoctrain/kvoctrain/kvt-core/langset.h
new file mode 100644
index 00000000..f0da2a5a
--- /dev/null
+++ b/kvoctrain/kvoctrain/kvt-core/langset.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+
+ properties for a language
+
+ -----------------------------------------------------------------------
+
+ begin : Thu Mar 11 20:50:53 MET 1999
+
+ copyright : (C) 1999-2001 Ewald Arnold
+ (C) 2001 The KDE-EDU team
+
+ email : kvoctrain@ewald-arnold.de
+
+ -----------------------------------------------------------------------
+
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * 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 langset_h
+#define langset_h
+
+#include <vector>
+using namespace std;
+
+#include <qstring.h>
+
+
+class LangSet
+{
+ public:
+
+ LangSet () {}
+
+ void addSet (QString shortId, QString longId, QString PixMapFile,
+ const QString& shortId2 = QString::null,
+ const QString& keyboardLayout = QString::null);
+
+/* void addSet (QString shortId, QString shortId2, QString longId, */
+/* QString PixMapFile, */
+/* const QString& keyboardLayout = QString::null); */
+
+ void appendSet(const LangSet &set);
+
+ unsigned int size () const { return langs.size(); }
+ void erase (int idx);
+ void clear ();
+
+ QString shortId (int index) const;
+ QString shortId2 (int index) const;
+ QString longId (int index) const;
+ QString PixMapFile (int index) const;
+ QString keyboardLayout (int index) const;
+
+ int indexShortId (QString shortId) const;
+ int indexLongId (QString longId) const;
+ int indexPixMapFile (QString PixMapFile) const;
+ // doesn't make sense for keyboard layouts since there is no 1-to-1 relation to languages
+
+ void setShortId (const QString & shortId, int index);
+ void setShortId2 (const QString & shortId2, int index);
+ void setLongId (const QString & longId, int index);
+ void setPixMapFile (const QString & PixMapFile, int index);
+ void setKeyboardLayout(const QString & layout, int index);
+
+ QString findShortId (const QString & longId) const;
+ QString findLongId (const QString & shortId) const;
+
+ private:
+
+ struct LangDef {
+ QString shortId,
+ shortId2,
+ longId,
+ PixMapFile,
+ keyboardLayout;
+ };
+
+ vector<LangDef> langs;
+};
+
+
+#endif // langset_h