diff options
Diffstat (limited to 'kanagram/src')
43 files changed, 10242 insertions, 0 deletions
diff --git a/kanagram/src/Makefile.am b/kanagram/src/Makefile.am new file mode 100644 index 00000000..40096ec0 --- /dev/null +++ b/kanagram/src/Makefile.am @@ -0,0 +1,43 @@ +if include_ARTS +artslib = -lartskde +else +artslib = +endif + +# set the include path for X, qt and KDE +INCLUDES = $(all_includes) + +# these are the headers for your project +noinst_HEADERS = kanagram.h kanagramgame.h fontutils.h vocabsettings.h vocabedit.h vocabsettingswidget.h vocabeditwidget.h mainsettingswidget.h mainsettings.h newstuffwidget.h newstuffdialog.h newstuff.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: rc.cpp + $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kanagram.pot + +KDE_ICON = AUTO + +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = kanagram + +# the application source, library search path, and link libraries +kanagram_SOURCES = main.cpp kanagram.cpp kanagramgame.cpp fontutils.cpp kanagramsettings.kcfgc mainsettingswidget.ui vocabsettingswidget.ui vocabeditwidget.ui mainsettings.cpp vocabsettings.cpp vocabedit.cpp keduvocdocument.cpp keduvocexpression.cpp keduvockvtmlreader.cpp keduvockvtmlwriter.cpp leitnerbox.cpp leitnersystem.cpp multiplechoice.cpp grammarmanager.cpp leitnersystemview.cpp newstuffwidget.ui newstuffdialog.cpp newstuff.cpp +kanagram_LDFLAGS = $(KDE_RPATH) $(all_libraries) +kanagram_LDADD = $(LIB_KDEUI) $(LIB_KNEWSTUFF) $(LIB_KIO) $(artslib) + +kde_kcfg_DATA=kanagram.kcfg + + +# this is where the desktop file will go +xdg_apps_DATA = kanagram.desktop + +# this is where the shell's XML-GUI resource file goes +# TODO does this app need an ui.rc ? If it does put it here +# shellrcdir = $(kde_datadir)/kanagram +# shellrc_DATA = kanagramui.rc diff --git a/kanagram/src/fontutils.cpp b/kanagram/src/fontutils.cpp new file mode 100644 index 00000000..320f501f --- /dev/null +++ b/kanagram/src/fontutils.cpp @@ -0,0 +1,24 @@ +/*************************************************************************** + * Copyright (C) 2005 by Albert Astals Cid <tsdgeos@terra.es> * + * * + * 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 <qpainter.h> + +#include "fontutils.h" + +int fontUtils::fontSize(QPainter &p, const QString &s1, int w, int h) +{ + QRect aux1; + QFont f = p.font(); + f.setPointSize(28); + p.setFont(f); + + aux1 = p.boundingRect(QRect(), Qt::AlignAuto, s1); + + return QMIN(w * 28 / aux1.width(), h * 28 / aux1.height()); +} diff --git a/kanagram/src/fontutils.h b/kanagram/src/fontutils.h new file mode 100644 index 00000000..b6bc9c97 --- /dev/null +++ b/kanagram/src/fontutils.h @@ -0,0 +1,18 @@ +/*************************************************************************** + * Copyright (C) 2005 by Albert Astals Cid <tsdgeos@terra.es> * + * * + * 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 FONTUTILS_H +#define FONTUTILS_H + +namespace fontUtils +{ + int fontSize(QPainter &p, const QString &s1, int w, int h); +} + +#endif diff --git a/kanagram/src/grammarmanager.cpp b/kanagram/src/grammarmanager.cpp new file mode 100644 index 00000000..dd526fd5 --- /dev/null +++ b/kanagram/src/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("Present Progressive") }, + { CONJ_PRESENT_PERFECT, I18N_NOOP("Present 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/kanagram/src/grammarmanager.h b/kanagram/src/grammarmanager.h new file mode 100644 index 00000000..1b9cfe76 --- /dev/null +++ b/kanagram/src/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/kanagram/src/kanagram.cpp b/kanagram/src/kanagram.cpp new file mode 100644 index 00000000..088453a2 --- /dev/null +++ b/kanagram/src/kanagram.cpp @@ -0,0 +1,787 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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 <config.h> + +#include <qcursor.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qtimer.h> +#include <qstring.h> +#include <qfontmetrics.h> +#include <qdir.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kconfig.h> +#include <khelpmenu.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> +#include <kconfigdialog.h> +#include <kconfigskeleton.h> +#include <krandomsequence.h> +#include <kdebug.h> + +#include "kanagram.h" +#include "kanagramsettings.h" +#include "mainsettings.h" +#include "vocabsettings.h" +#include "newstuff.h" + +static const char* m_textRevealWord = I18N_NOOP("reveal word"); +static const char* m_textHint = I18N_NOOP("hint"); + +Kanagram::Kanagram() : QWidget(0, 0, WStaticContents | WNoAutoErase), m_overNext(false), m_overConfig(false), m_overHelp(false), m_overQuit(false), m_overReveal(false), m_overHint(false), m_overUp(false), m_overHintBox(false), m_showHint(false) +{ + m_game = new KanagramGame(this); + + m_back = new QPixmap(locate("appdata", "images/kanagram.png")); + m_aboutKDEOverlay = new QPixmap(locate("appdata", "images/kicon.png")); + m_aboutKDEOverlayOver = new QPixmap(locate("appdata", "images/kiconover.png")); + m_aboutAppOverlay = new QPixmap(locate("appdata", "images/appicon.png")); + m_aboutAppOverlayOver = new QPixmap(locate("appdata", "images/appiconover.png")); + m_handbookOverlay = new QPixmap(locate("appdata", "images/handbookicon.png")); + m_handbookOverlayOver = new QPixmap(locate("appdata", "images/handbookiconover.png")); + m_card = new QPixmap(locate("appdata", "images/card.png")); + + m_next = new QPixmap(locate("appdata", "images/next.png")); + m_nextOver = new QPixmap(locate("appdata", "images/nextover.png")); + m_config = new QPixmap(locate("appdata", "images/config.png")); + m_configOver = new QPixmap(locate("appdata", "images/configover.png")); + m_help = new QPixmap(locate("appdata", "images/help.png")); + m_helpOver = new QPixmap(locate("appdata", "images/helpover.png")); + m_quit = new QPixmap(locate("appdata", "images/quit.png")); + m_quitOver = new QPixmap(locate("appdata", "images/quitover.png")); + + m_up = new QPixmap(locate("appdata", "images/up.png")); + m_upOver = new QPixmap(locate("appdata", "images/upover.png")); + m_upDisabled = new QPixmap(locate("appdata", "images/updisabled.png")); + + m_nextRect = QRect(477, 31, 134, 76); + m_configRect = QRect(477, 122, 134, 76); + m_helpRect = QRect(477, 212, 134, 76); + m_quitRect = QRect(453, 352, 182, 104); + + m_hintBoxRect = QRect(446, 207, 171, 85); + m_upRect = QRect(341, 425, 55, 33); + m_aboutKDERect = QRect(567, 213, 44, 44); + m_aboutAppRect = QRect(522, 213, 44, 44); + m_handbookRect = QRect(478, 213, 44, 44); + m_arrowRect = QRect(380, 134, 13, 20); + m_logoRect = QRect(76, 24, 297, 50); + + //blackboardRect intentionally wrong to make sure fonts align correctly + m_blackboardRect = QRect(41, 116, 366, 255); + + setupRects(); + + setMouseTracking(true); + setFixedSize(650, 471); + show(); + + m_chalkColor = QColor(155, 155, 155); + m_chalkHighlightColor = QColor(255, 255, 255); + m_fillColor = QColor(45, 45, 45); + m_fontColor = QColor(55, 55, 55); + m_fontHighlightColor = QColor(99, 99, 99); + + loadSettings(); + + m_hintTimer = new QTimer(this); + + m_helpMenu = new KHelpMenu(this, kapp->aboutData()); + + m_inputBox = new QLineEdit(this); + m_inputBox->setGeometry(QRect(52, 427, 273, 29)); + m_inputBox->setFrame(false); + + connect(m_inputBox, SIGNAL(returnPressed()), this, SLOT(checkWord())); + connect(m_hintTimer, SIGNAL(timeout()), this, SLOT(hideHint())); + connect(m_inputBox, SIGNAL(textChanged(const QString &)), this, SLOT(update())); + + QFont f = QFont(); + f.setPointSize(17); + m_inputBox->setFont(f); + m_inputBox->show(); + + m_font = KGlobalSettings::generalFont(); + + //Initialize the sound server + #ifndef WITHOUT_ARTS + m_artsDispatcher = new KArtsDispatcher(); + m_artsServer = new KArtsServer(); + m_artsFactory = new KDE::PlayObjectFactory(m_artsServer->server()); + #endif +} + +Kanagram::~Kanagram() +{ +} + +void Kanagram::loadSettings() +{ + QString hideTime = KanagramSettings::hintHideTime(); + if(hideTime[0].isDigit()) + m_hintHideTime = hideTime[0].digitValue(); + else + m_hintHideTime = 0; + + m_useSounds = KanagramSettings::useSounds(); + m_useStandardFonts = KanagramSettings::useStandardFonts(); + + if(m_useStandardFonts) + { + m_blackboardFont = KGlobalSettings::generalFont(); + m_arrow = new QPixmap(locate("appdata", "images/basicarrow.png")); + m_arrowOver = new QPixmap(locate("appdata", "images/basicarrowover.png")); + } + else + { + m_blackboardFont = QFont("squeaky chalk sound"); + m_arrow = new QPixmap(locate("appdata", "images/arrow.png")); + m_arrowOver = new QPixmap(locate("appdata", "images/arrowover.png")); + } + + m_game->refreshVocabList(); +} + +void Kanagram::setupRects() +{ + QPainter tmpp(this); + QFont font = m_blackboardFont; + font.setPointSize(14); + font.setBold(true); + tmpp.setFont(font); + int yOffset = 0; + //set appropriate yOffset for different fonts + if(m_useStandardFonts) yOffset = 6; + QRect r = innerRect(m_blackboardRect, 6, yOffset); + m_hintRect = tmpp.boundingRect(r, Qt::AlignBottom|Qt::AlignLeft, i18n(m_textHint)); + m_revealRect = tmpp.boundingRect(r, Qt::AlignBottom|Qt::AlignRight, i18n(m_textRevealWord)); + tmpp.end(); +} + +void Kanagram::paintEvent(QPaintEvent *) +{ + QPixmap buf(width(), height()); + QPainter p(&buf); + + p.drawPixmap(0, 0, *m_back); + + if(m_overNext) + p.drawPixmap(525, 38, *m_nextOver); + else + p.drawPixmap(525, 38, *m_next); + if(m_overConfig) + p.drawPixmap(525, 130, *m_configOver); + else + p.drawPixmap(525, 130, *m_config); + if(m_overHelp) + p.drawPixmap(525, 218, *m_helpOver); + else + p.drawPixmap(525, 218, *m_help); + if(m_overQuit) + p.drawPixmap(520, 362, *m_quitOver); + else + p.drawPixmap(520, 362, *m_quit); + + //draw main Anagram + drawTextNew(p, m_game->getAnagram(), Qt::AlignCenter, 10, 10, m_blackboardRect, true, 28); + + int yOffset = 0; + //set appropriate yOffset for different fonts + if(m_useStandardFonts) yOffset = 6; + //draw text using appropriate yOffset + drawTextNew(p, i18n(m_textRevealWord), Qt::AlignBottom | Qt::AlignRight, 6, yOffset, m_blackboardRect, m_overReveal, 14); + drawTextNew(p, i18n(m_textHint), Qt::AlignBottom | Qt::AlignLeft, 6, yOffset, m_blackboardRect, m_overHint, 14); + + //draw vocab switcher + drawSwitcher(p, 9, 8); + + p.setPen(QPen(black, 3)); + + //Draw the border of the input box + QRect borderRect = m_inputBox->geometry(); + borderRect.setLeft(borderRect.left() - 2); + borderRect.setTop(borderRect.top() - 2); + borderRect.setWidth(borderRect.width() + 2 * 1); + borderRect.setHeight(borderRect.height() + 2 * 1); + p.drawRoundRect(borderRect, 10, 5); + + //Draw the border of the Up arrow + borderRect = m_upRect; + p.fillRect(borderRect, m_fillColor); + p.drawRoundRect(borderRect, 10, 5); + + if(m_overUp && m_inputBox->text() != "") + p.drawPixmap(350, 431, *m_upOver); + else if(m_inputBox->text() == "") + p.drawPixmap(350, 431, *m_upDisabled); + else + p.drawPixmap(350, 431, *m_up); + + if(m_showHint) + { + p.drawPixmap(439, 204, *m_hintOverlay); + QFont f = QFont(m_font); + f.setWeight(QFont::Bold); + f.setPointSize(10); + p.setFont(f); + p.drawText(459, 217, 148, 67, WordBreak | AlignCenter, m_game->getHint()); + } + + if(m_overHelp && !m_showHint) + { + p.drawPixmap(456, 275, *m_card); + if(m_overAboutApp) + { + p.drawPixmap(522, 213, *m_aboutAppOverlay); + drawHelpText(p, i18n("About Kanagram")); + } + else + p.drawPixmap(522, 213, *m_aboutAppOverlayOver); + if(m_overAboutKDE) + { + p.drawPixmap(567, 213, *m_aboutKDEOverlay); + drawHelpText(p, i18n("About KDE")); + } + else + p.drawPixmap(567, 213, *m_aboutKDEOverlayOver); + if(m_overHandbook) + { + p.drawPixmap(478, 213, *m_handbookOverlay); + drawHelpText(p, i18n("Kanagram Handbook")); + } + else + p.drawPixmap(478, 213, *m_handbookOverlayOver); + } + else if(m_overNext) + { + p.drawPixmap(456, 275, *m_card); + drawHelpText(p, i18n("Next Word")); + } + else if(m_overConfig) + { + p.drawPixmap(456, 275, *m_card); + drawHelpText(p, i18n("Configure Kanagram")); + } + else if(m_overQuit) + { + p.drawPixmap(456, 275, *m_card); + drawHelpText(p, i18n("Quit Kanagram")); + } + + bitBlt(this, 0, 0, &buf); +} + +void Kanagram::drawHelpText(QPainter &p, QString text) +{ + p.save(); + QFont font = m_font; + font.setPointSize(12); + p.setFont(font); + p.rotate(-3.29); + p.setPen(black); + p.drawText(450, 340, text.section(' ', 0, 0)); + p.drawText(450, 360, text.section(' ', 1)); + p.restore(); +} + +void Kanagram::drawSwitcherText(QPainter &p, QString text) +{ + p.save(); + QFont font = m_blackboardFont; + font.setPointSize(14); + QFontMetrics fm(font); + int width = fm.width(text); + int height = fm.height(); + m_switcherRect = QRect(380 - width, 150 - height, width, height); + p.setFont(font); + if(!m_overSwitcher) + p.setPen(m_chalkColor); + else + p.setPen(m_chalkHighlightColor); + p.drawText(380 - width, 150, text); + p.restore(); +} + +void Kanagram::drawSwitcher(QPainter &p, const int xMargin, const int yMargin) +{ + const int padding = 5; + QString text = m_game->getDocTitle(); + QFont font = m_blackboardFont; + font.setPointSize(14); + QFontMetrics fm(font); + QRect r = innerRect(m_blackboardRect, xMargin, yMargin); + r.normalize(); + r.moveBy(- padding - (m_overSwitcher ? m_arrowOver : m_arrow )->width(), yMargin); + r.setHeight( (m_overSwitcher ? m_arrowOver : m_arrow )->height()); + m_switcherRect = p.boundingRect(r, Qt::AlignVCenter|Qt::AlignRight, text); + p.setFont(font); + if (m_overSwitcher) + { + p.setPen(m_chalkHighlightColor); + p.drawPixmap(m_switcherRect.right() + padding, m_switcherRect.top(), *m_arrowOver); + } + else + { + p.setPen(m_chalkColor); + p.drawPixmap(m_switcherRect.right() + padding, m_switcherRect.top(), *m_arrow); + } + m_switcherRect.moveBy(0, -2); + p.drawText(m_switcherRect, Qt::AlignVCenter|Qt::AlignRight, text); +} + +QRect Kanagram::innerRect(const QRect &rect, const int xMargin, const int yMargin) +{ + QRect r = rect; + + if (xMargin>0) + { + r.setWidth(r.width() - 2 * xMargin); + r.moveBy(xMargin, 0); + } + if (yMargin>0) + { + r.setHeight(r.height() - 2 * yMargin); + r.moveBy(0, yMargin); + } + + return r; +} + +void Kanagram::mousePressEvent(QMouseEvent *e) +{ + + if (m_nextRect.contains(e->pos())) + { + hideHint(); + m_game->nextAnagram(); + if(m_useSounds) play("chalk.ogg"); + m_inputBox->unsetPalette(); + update(); + } + + if(m_configRect.contains(e->pos())) + { + showSettings(); + } + + if(m_quitRect.contains(e->pos())) + { + kapp->quit(); + } + + if(m_revealRect.contains(e->pos())) + { + m_game->restoreWord(); + update(); + } + + if(m_logoRect.contains(e->pos())) + { + m_helpMenu->aboutApplication(); + } + + if(!m_showHint && m_overHelp) + { + if(m_handbookRect.contains(e->pos())) + { + m_helpMenu->appHelpActivated(); + } + + if(m_aboutKDERect.contains(e->pos())) + { + m_helpMenu->aboutKDE(); + } + + if(m_aboutAppRect.contains(e->pos())) + { + m_helpMenu->aboutApplication(); + } + } + + if(m_hintBoxRect.contains(e->pos())) + { + hideHint(); + } + + if(m_switcherRect.contains(e->pos()) || m_arrowRect.contains(e->pos())) + { + if(!(e->button() == RightButton)) + m_game->nextVocab(); + else + m_game->previousVocab(); + hideHint(); + m_game->nextAnagram(); + if(m_useSounds) play("chalk.ogg"); + KanagramSettings::setDefaultVocab(m_game->getFilename()); + KanagramSettings::writeConfig(); + update(); + } + + if(m_hintRect.contains(e->pos())) + { + if(m_showHint == true) m_showHint = false; + else + { + if(m_hintHideTime) + { + m_hintTimer->start(m_hintHideTime * 1000, TRUE); + } + m_showHint = true; + randomHintImage(); + } + update(); + } + + if(m_upRect.contains(e->pos()) && m_inputBox->text() != "") + { + if(m_inputBox->text().lower().stripWhiteSpace() == m_game->getWord()) + { + if(m_useSounds) play("right.ogg"); + m_inputBox->setPaletteBackgroundColor(QColor(0, 255, 0)); + QTimer::singleShot(1000, this, SLOT(resetInputBox())); + m_inputBox->clear(); + hideHint(); + m_game->nextAnagram(); + update(); + } + else + { + if(m_useSounds) play("wrong.ogg"); + m_inputBox->setPaletteBackgroundColor(QColor(255, 0, 0)); + QTimer::singleShot(1000, this, SLOT(resetInputBox())); + m_inputBox->clear(); + update(); + } + } +} + +void Kanagram::mouseMoveEvent(QMouseEvent *e) +{ + updateButtonHighlighting(e->pos()); +} + +void Kanagram::updateButtonHighlighting(const QPoint &p) +{ + bool haveToUpdate; + haveToUpdate = false; + + if (m_nextRect.contains(p)) + { + if (!m_overNext) + { + m_overNext = true; + haveToUpdate = true; + } + } + else if (m_overNext) + { + m_overNext = false; + haveToUpdate = true; + } + + if(m_configRect.contains(p)) + { + if(!m_overConfig) + { + m_overConfig = true; + haveToUpdate = true; + } + } + else if(m_overConfig) + { + m_overConfig = false; + haveToUpdate = true; + } + + if(m_helpRect.contains(p)) + { + if(!m_overHelp) + { + m_overHelp = true; + haveToUpdate = true; + } + } + else if(m_overHelp) + { + m_overHelp = false; + haveToUpdate = true; + } + + if(m_quitRect.contains(p)) + { + if(!m_overQuit) + { + m_overQuit = true; + haveToUpdate = true; + } + } + else if(m_overQuit) + { + m_overQuit = false; + haveToUpdate = true; + } + + if(m_hintRect.contains(p)) + { + if(!m_overHint) + { + m_overHint = true; + haveToUpdate = true; + } + } + else if(m_overHint) + { + m_overHint = false; + haveToUpdate = true; + } + + if(m_hintBoxRect.contains(p)) + { + if(!m_overHintBox) + { + m_overHintBox = true; + haveToUpdate = true; + } + } + else if(m_overHintBox) + { + m_overHintBox = false; + haveToUpdate = true; + } + + if(m_revealRect.contains(p)) + { + if(!m_overReveal) + { + m_overReveal = true; + haveToUpdate = true; + } + } + else if(m_overReveal) + { + m_overReveal = false; + haveToUpdate = true; + } + + if(m_upRect.contains(p)) + { + if(!m_overUp) + { + m_overUp = true; + haveToUpdate = true; + } + } + else if(m_overUp) + { + m_overUp = false; + haveToUpdate = true; + } + + if(m_switcherRect.contains(p) || m_arrowRect.contains(p)) + { + if(!m_overSwitcher) + { + m_overSwitcher = true; + haveToUpdate = true; + } + } + else if(m_overSwitcher) + { + m_overSwitcher = false; + haveToUpdate = true; + } + + if(m_aboutAppRect.contains(p)) + { + if(!m_overAboutApp) + { + m_overAboutApp = true; + haveToUpdate = true; + } + } + else if(m_overAboutApp) + { + m_overAboutApp = false; + haveToUpdate = true; + } + + if(!m_showHint) + { + if(m_handbookRect.contains(p)) + { + if(!m_overHandbook) + { + m_overHandbook = true; + haveToUpdate = true; + } + } + else if(m_overHandbook) + { + m_overHandbook = false; + haveToUpdate = true; + } + + if(m_aboutKDERect.contains(p)) + { + if(!m_overAboutKDE) + { + m_overAboutKDE = true; + haveToUpdate = true; + } + } + else if(m_overAboutKDE) + { + m_overAboutKDE = false; + haveToUpdate = true; + } + } + + if(m_overAboutKDE || m_overHandbook || m_overSwitcher || m_overNext || m_overQuit || m_overConfig || m_overReveal || m_overHint || (m_overUp && m_inputBox->text() != "") || m_overAboutApp || m_overHintBox) + this->setCursor(PointingHandCursor); + else + this->unsetCursor(); + + if (haveToUpdate) update(); +} + +void Kanagram::drawText(QPainter &p, const QString &text, const QPoint ¢er, bool withMargin, int xMargin, int yMargin, QRect *rect, bool highlight, int fontSize) +{ + QRect r; + QFont font = m_blackboardFont; + font.setPointSize(fontSize); + font.setBold(true); + p.setFont(font); + + r = p.boundingRect(QRect(), Qt::AlignAuto, text); + r = QRect(0, 0, r.width() + xMargin, r.height() + yMargin); + r.moveBy(center.x() - r.width() / 2, center.y() - r.height() / 2); + + if (withMargin) + { + p.fillRect(r, m_fillColor); + p.setPen(QPen(black, 3)); + p.drawRoundRect(r.left(), r.top(), r.width(), r.height(), 15, 15); + } + + if (!highlight) p.setPen(m_chalkColor); + else p.setPen(m_chalkHighlightColor); + p.drawText(r, Qt::AlignCenter, text); + + if(rect) *rect = r; +} + +void Kanagram::drawTextNew(QPainter &p, const QString &text, int textAlign, int xMargin, int yMargin, const QRect &rect, bool highlight, int fontSize) +{ + QRect r = innerRect(rect, xMargin, yMargin); + QFont font = m_blackboardFont; + font.setPointSize(fontSize); + font.setBold(true); + p.setFont(font); + + const bool withMargin = false; + if (withMargin) + { + p.fillRect(r, m_fillColor); + p.setPen(QPen(black, 3)); + p.drawRoundRect(r.left(), r.top(), r.width(), r.height(), 15, 15); + } + + if (highlight) + p.setPen(m_chalkHighlightColor); + else + p.setPen(m_chalkColor); + p.drawText(r, textAlign, text); +} + +void Kanagram::checkWord() +{ + QPoint p = m_upRect.topLeft() + QPoint( 1, 1 ); + QMouseEvent *e = new QMouseEvent( QEvent::MouseButtonPress, p, Qt::LeftButton, Qt::NoButton ); + mousePressEvent(e); +} + +void Kanagram::randomHintImage() +{ + unsigned long imageNum = m_randomImage.getLong(8); + QString dir = "images/eyes" + QString::number(imageNum + 1) + ".png"; + m_hintOverlay = new QPixmap(locate("appdata", dir)); +} + +void Kanagram::showSettings() +{ + if(KConfigDialog::showDialog("settings")) + return; + + KConfigDialog *configDialog = new KConfigDialog( this, "settings", KanagramSettings::self() ); + configDialog->addPage( new MainSettings( configDialog ), i18n( "General" ), "configure" ); + m_vocabSettings = new VocabSettings( configDialog ); + configDialog->addPage( m_vocabSettings, i18n("Vocabularies"), "edit" ); + configDialog->addPage( new NewStuff( configDialog ), i18n("New Stuff"), "knewstuff" ); + connect(configDialog, SIGNAL(settingsChanged()), this, SLOT(loadSettings())); + connect(configDialog, SIGNAL(applyClicked()), this, SLOT(refreshVocabularies())); + configDialog->exec(); + delete configDialog; +} + +void Kanagram::hideHint() +{ + if(m_showHint == true) m_showHint = false; + update(); +} + +void Kanagram::resetInputBox() +{ + m_inputBox->unsetPalette(); +} + +void Kanagram::refreshVocabularies() +{ + kdDebug() << "Refreshing vocab list..." << endl; + m_game->refreshVocabList(); + m_game->nextVocab(); + hideHint(); + m_game->nextAnagram(); + if(m_useSounds) play("chalk.ogg"); + KanagramSettings::setDefaultVocab(m_game->getFilename()); + KanagramSettings::writeConfig(); + m_vocabSettings->refreshView(); +} + +void Kanagram::play(QString filename) +{ + #ifndef WITHOUT_ARTS + KDE::PlayObject *playobj = m_artsFactory->createPlayObject(locate("appdata", "sounds/" + filename), true); + playobj->play(); + #else + (void)filename; + #endif +} + +#include "kanagram.moc" diff --git a/kanagram/src/kanagram.desktop b/kanagram/src/kanagram.desktop new file mode 100644 index 00000000..1cbaf73c --- /dev/null +++ b/kanagram/src/kanagram.desktop @@ -0,0 +1,120 @@ +[Desktop Entry] +Name=Kanagram +Name[bn]=কে-অ্যানাগ্রাম +Name[cy]=blinKen +Name[eo]=Kanagramo +Name[hr]=KAnagram +Name[ne]=कानाग्राम +Exec=kanagram +Icon=kanagram +Type=Application +DocPath=kanagram/index.html +Comment=KDE Letter Order Game +Comment[be]=Гульня з перамяшчэннем літар +Comment[bg]=Игра за подредба на букви +Comment[bn]=কে.ডি.ই. উপস্থাপিত অক্ষর সাজানোর খেলা +Comment[bs]=KDE igra slaganja slova +Comment[ca]=Joc d'ordenació de lletres per a KDE +Comment[cs]=Hra uspořádání písmen pro KDE +Comment[csb]=Gra w ùkłôdanié słów +Comment[da]=Bogstavsrækkefølgesspil for KDE +Comment[de]=Ein KDE-Spiel, bei dem Buchstaben sortiert werden +Comment[el]=Παιχνίδι σειράς γραμμάτων του KDE +Comment[eo]=KDE literordiga ludo +Comment[es]=Juego de ordenación de letras para KDE +Comment[et]=KDE tähtede järjestamise mäng +Comment[eu]=Letren ordenaren jokoa +Comment[fa]=بازی ترتیب حروف KDE +Comment[fi]=Kirjainten järjestyspeli +Comment[fr]=Remettre les lettres dans le bon ordre +Comment[gl]=Xogo de Ordenar Letras de KDE +Comment[he]=משחק סידור מילים של KDE +Comment[hr]=KDE igra premještanja slova +Comment[hu]=KDE-alapú szókirakó játék +Comment[it]=Gioco di anagrammi per KDE +Comment[ja]=KDE 回文ゲーム +Comment[ka]=KDE ასოების გადალაგების თამაში +Comment[km]=ល្បែងតម្រៀបអក្សររបស់ KDE +Comment[ms]=Permainan Susun Huruf KDE +Comment[nb]=Ordlek med bokstavrekkefølge +Comment[nds]=KDE-Bookstavenspeel +Comment[ne]=KDE अक्षर क्रम खेल +Comment[nl]=Letters ordenen +Comment[nn]=Bokstavordningsspel for KDE +Comment[pl]=Gra w układanie liter dla KDE +Comment[pt]=Jogo de Ordenação de Letras do KDE +Comment[pt_BR]= Jogo do KDE de ordenação de letras +Comment[ru]=Игра с перестановкой букв +Comment[sk]=KDE hra o usporiadaní písmen +Comment[sl]=Igra vrstnega reda črk +Comment[sr]=Игра редоследа слова за KDE +Comment[sr@Latn]=Igra redosleda slova za KDE +Comment[sv]=Bokstavsordningsspel för KDE +Comment[tr]=Harf Sıralama Oyunu +Comment[uk]=Гра з впорядкування літер +Comment[vi]=Trò chơi Sắp xếp Chữ cái KDE +Comment[zh_CN]=KDE 字母顺序游戏 +Comment[zh_TW]=KDE 字母排序遊戲 +GenericName=Letter Order Game +GenericName[af]=Lettervolgorde Speletjie +GenericName[ar]=لعبة ترتيب الاحرف +GenericName[be]=Гульня з перамяшчэннем літар +GenericName[bg]=Игра за подредба на букви +GenericName[bn]=অক্ষর সাজানোর খেলা +GenericName[bs]=Igra slaganja slova +GenericName[ca]=Joc d'ordenació de lletres +GenericName[cs]=Hra uspořádání písmen +GenericName[csb]=Gra w ùkłôdanié słów +GenericName[cy]=Gêm Trefn Llythrennau +GenericName[da]=Bogstavrækkefølgespil +GenericName[de]=Spielerisches Sortieren von Buchstaben +GenericName[el]=Παιχνίδι σειράς γραμμάτων +GenericName[eo]=Literordiga ludo +GenericName[es]=Juego de ordenación de letras +GenericName[et]=Tähtede järjestamine +GenericName[eu]=Letren ordenaren jokoa +GenericName[fa]=بازی ترتیب حرف +GenericName[fi]=Kirjainten järjestyspeli +GenericName[fr]=Remettre les lettres dans le bon ordre +GenericName[gl]=Xogo de Ordenar Letras +GenericName[he]=משחק סידור מילים +GenericName[hi]=अक्षर अनुक्रम खेल +GenericName[hr]=Igra rasporeda slova +GenericName[hu]=Szókirakó játék +GenericName[is]=Stafaröðunarleikur +GenericName[it]=Gioco di anagrammi +GenericName[ja]=回文ゲーム +GenericName[ka]=ასოების გადალაგება +GenericName[km]=ល្បែងតម្រៀបអក្សរ +GenericName[lt]=Raidžių rūšiavimo žaidimas +GenericName[lv]=Burtu Kārtības Spēle +GenericName[mk]=Игра за пишување писма +GenericName[mn]=Үсэг цэгцлэх тоглоом +GenericName[ms]=Permainan Susun Huruf +GenericName[nb]=Ordlek med bokstavrekkefølge +GenericName[nds]=Bookstaven ornen +GenericName[ne]=अक्षर क्रम खेल +GenericName[nl]=Letters ordenen +GenericName[nn]=Bokstavordningsspel +GenericName[nso]=Papadi ya Otara ya Lengwalo +GenericName[pl]=Gra w układanie słów +GenericName[pt]=Jogo de Ordenação de Letras +GenericName[pt_BR]= Um Jogo de ordenação de letras +GenericName[ru]=Игра с перестановкой букв +GenericName[se]=Bustávvaortnetspeallu +GenericName[sk]=Hra o usporiadaní písmen +GenericName[sl]=Igra vrstnega reda črk +GenericName[sr]=Игра редоследа слова +GenericName[sr@Latn]=Igra redosleda slova +GenericName[sv]=Bokstavsordningsspel +GenericName[ta]=எழுத்துவரிசை விளையாட்டு +GenericName[tg]=Бозии Тартиби Ҳарф +GenericName[tr]=Harf Sıralama Oyunu +GenericName[uk]=Гра з впорядкування літер +GenericName[ven]=Mutambo uno humbelwa nga lunwalo +GenericName[vi]=Trò chơi Sắp xếp Chữ cái +GenericName[xh]=Umdlalo Wolungelanisa Unobumba +GenericName[zh_CN]=字母顺序游戏 +GenericName[zh_TW]=字母排序遊戲 +GenericName[zu]=Umdlalo Wokulandelanisa Kwencwadi +Categories=Qt;KDE;Education;Languages; diff --git a/kanagram/src/kanagram.h b/kanagram/src/kanagram.h new file mode 100644 index 00000000..689495b8 --- /dev/null +++ b/kanagram/src/kanagram.h @@ -0,0 +1,134 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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. * + ***************************************************************************/ + +#ifndef KANAGRAM_H +#define KANAGRAM_H + +#include <config.h> + +#include <qwidget.h> +#include <qlineedit.h> + +#include <kxmlguiclient.h> + +#ifndef WITHOUT_ARTS +#include <arts/kartsdispatcher.h> +#include <arts/kartsserver.h> +#include <arts/kplayobject.h> +#include <arts/kplayobjectfactory.h> +#else +class KArtsDispatcher; +class KArtsServer; +namespace KDE +{ + class PlayObjectFactory; +} +#endif + +#include "kanagramgame.h" + +#include <iostream> + +using namespace std; + +class KHelpMenu; +class KConfigDialog; +class KRandomSequence; +class KanagramGame; +class VocabSettings; + +class Kanagram : public QWidget +{ +Q_OBJECT + public: + Kanagram(); + ~Kanagram(); + + private slots: + void checkWord(); + void loadSettings(); + void hideHint(); + void resetInputBox(); + void refreshVocabularies(); + + private: + void drawText(QPainter &p, const QString &text, const QPoint ¢er, bool withMargin, int xMargin, int yMargin, QRect *rect, bool highlight, int fontSize = 18); + void drawTextNew(QPainter &p, const QString &text, int textAlign, int xMargin, int yMargin, const QRect &rect, bool highlight, int fontSize = 18); + + void setupRects(); + + void play(QString filename); + + void paintEvent(QPaintEvent *); + + void mousePressEvent(QMouseEvent *e); + + void mouseMoveEvent(QMouseEvent *e); + + void updateButtonHighlighting(const QPoint &p); + + void randomHintImage(); + + void showSettings(); + + void drawHelpText(QPainter &p, QString text); + + void drawSwitcherText(QPainter &p, QString text); + void drawSwitcher(QPainter &p, const int xMargin, const int yMargin); + + QRect innerRect(const QRect &rect, const int xMargin, const int yMargin); + + KanagramGame *m_game; + + QPixmap *m_back, *m_hintOverlay, *m_aboutKDEOverlay, *m_aboutAppOverlay, *m_handbookOverlay, *m_aboutKDEOverlayOver, *m_aboutAppOverlayOver, *m_handbookOverlayOver, *m_card, *m_arrow, *m_arrowOver, *m_next, *m_nextOver, *m_config, *m_configOver, *m_help, *m_helpOver, *m_quit, *m_quitOver, *m_up, *m_upOver, *m_upDisabled; + + //Deprecated + //QRect m_newWordRect, m_settingsRect, m_helpRect, m_quitRect; + + QRect m_nextRect, m_configRect, m_helpRect, m_quitRect, m_revealRect, m_hintRect, m_upRect, m_aboutKDERect, m_aboutAppRect, m_handbookRect, m_switcherRect, m_arrowRect, m_logoRect, m_hintBoxRect, m_blackboardRect; + + bool m_overNext, m_overConfig, m_overHelp, m_overQuit, m_overReveal, m_overHint, m_overUp, m_overAboutKDE, m_overAboutApp, m_overHandbook, m_overSwitcher, m_overHintBox; + + bool m_showHint; + + QColor m_fillColor, m_fontColor, m_fontHighlightColor, m_chalkColor, m_chalkHighlightColor; + + //Values for settings + int m_hintHideTime; + bool m_useSounds, m_useStandardFonts; + + QFont m_blackboardFont, m_font; + + KHelpMenu *m_helpMenu; + + QLineEdit *m_inputBox; + + VocabSettings *m_vocabSettings; + + KRandomSequence m_randomImage; + + QTimer *m_hintTimer; + + KArtsDispatcher *m_artsDispatcher; + KArtsServer *m_artsServer; + KDE::PlayObjectFactory *m_artsFactory; +}; + +#endif diff --git a/kanagram/src/kanagram.kcfg b/kanagram/src/kanagram.kcfg new file mode 100644 index 00000000..8681545f --- /dev/null +++ b/kanagram/src/kanagram.kcfg @@ -0,0 +1,26 @@ +<kcfgfile name="kanagramrc"> +<group name="kanagram"> +<entry name="hintHideTime" type="String"> + <label>This setting allows you to set how long Kanagram's hint bubble is shown.</label> + <default>5 seconds</default> +</entry> +<entry name="useSounds" type="Bool"> + <label>Turns sounds on/off.</label> + <default>true</default> +</entry> +<entry name="useStandardFonts" type="Bool"> + <label>Uses a standard font for the chalkboard/interface.</label> + <default>false</default> +</entry> +<entry name="defaultVocab" type="Path"> + <label>Set the default vocabulary</label> + <default></default> +</entry> +<entry name="dataLanguage" type="String"> + <label>Set the default translation</label> + <default></default> +</entry> +<entry name="justGotFont" type="Bool"> +</entry> +</group> +</kcfgfile> diff --git a/kanagram/src/kanagramgame.cpp b/kanagram/src/kanagramgame.cpp new file mode 100644 index 00000000..318c285e --- /dev/null +++ b/kanagram/src/kanagramgame.cpp @@ -0,0 +1,209 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * Portions of this code taken from KMessedWords by Reuben Sutton * + * * + * 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. * + * * + * 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 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 <qfile.h> + +#include <kurl.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <klocale.h> + +#include "kanagramgame.h" +#include "keduvocdocument.h" +#include "kanagramsettings.h" + +#include <stdlib.h> + +KanagramGame::KanagramGame(QWidget* parent) : m_index(0) +{ + m_parent = parent; + loadDefaultVocab(); +} + +KanagramGame::~KanagramGame() +{ +} + +void KanagramGame::checkFile() +{ + if (!QFile::exists(locate("appdata", m_filename))) { + QString msg = i18n("File %1 cannot be found.\n Please ensure that Kanagram is properly installed.") + .arg(m_filename); + KMessageBox::sorry(m_parent, msg, i18n("Error")); + exit(0); + } +} + +void KanagramGame::loadDefaultVocab() +{ + m_filename = KanagramSettings::defaultVocab(); + if (m_filename.isEmpty()) + { + // first run + m_filename = locate("appdata", "data/" + KanagramSettings::dataLanguage() + "/objects.kvtml"); + if (m_filename.isEmpty()) + { + refreshVocabList(); + nextVocab(); + } + } + + kdDebug() << "in game " << m_filename <<endl; + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(locate("appdata", m_filename)), false); + m_docTitle = doc->getTitle(); + kdDebug() << m_docTitle <<endl; //Animals + nextAnagram(); +} + +void KanagramGame::refreshVocabList() +{ + m_fileList = KGlobal::dirs()->findAllResources("appdata", "data/" + KanagramSettings::dataLanguage() + "/*.kvtml"); + //nextVocab(); + m_index = findIndex(); +} + +int KanagramGame::findIndex() +{ + //this m_filename is wrong + //you have to use KanagramSettings::defaultVocab() instead of m_filename which is used for something else + kdDebug() <<"m_filename " << m_filename << "\n" << endl; + int tempIndex = 0; + for(uint i = 0; i < m_fileList.size(); i++) + { + kdDebug() <<"m_file " << m_fileList[i]<<endl; + if(m_filename == m_fileList[i]) + { + tempIndex = i; + } + } + kdDebug() << "index founded " << tempIndex <<endl; + return tempIndex; +} + +void KanagramGame::previousVocab() +{ + m_index--; + if(m_index < 0) + m_index = m_fileList.size() - 1; + m_filename = m_fileList[m_index]; + checkFile(); + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(locate("appdata", m_filename)), false); + m_docTitle = doc->getTitle(); + m_answeredWords.clear(); +} + +void KanagramGame::nextVocab() +{ + m_index++; + if((uint)m_index >= m_fileList.size()) + m_index = 0; + m_filename = m_fileList[m_index]; + checkFile(); + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(locate("appdata", m_filename)), false); + m_docTitle = doc->getTitle(); + m_answeredWords.clear(); +} + +void KanagramGame::nextAnagram() +{ + checkFile(); + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(locate("appdata", m_filename)), false); + int totalWords = doc->numEntries(); + int wordNumber = m_random.getLong(totalWords); + if(doc->numEntries() == (int)m_answeredWords.size()) + { + m_answeredWords.clear(); + } + while(m_answeredWords.findIndex(doc->getEntry(wordNumber)->getOriginal()) != -1) + { + wordNumber = m_random.getLong(totalWords); + } + m_originalWord = doc->getEntry(wordNumber)->getOriginal(); + m_answeredWords.append(m_originalWord); + m_anagram = createAnagram(m_originalWord); + m_hint = doc->getEntry(wordNumber)->getRemark(0); +} + +QString KanagramGame::getDocTitle() +{ + return m_docTitle; +} + +QString KanagramGame::getFilename() +{ + if(m_fileList.empty()) + return m_filename; + else + return m_fileList[m_index]; +} + +QString KanagramGame::getAnagram() +{ + return m_anagram; +} + +QString KanagramGame::getHint() +{ + return m_hint; +} + +QString KanagramGame::getWord() +{ + return m_originalWord; +} + +void KanagramGame::restoreWord() +{ + m_anagram = m_originalWord; +} + +QString KanagramGame::createAnagram(QString original) +{ + QStringList objData = QStringList::split(QString(""), original); + QString insaneData; + int count; + + for(int i=0; count = objData.count(); i++) + { + int objChunk; + if((i == 0) && (count > 1)) + objChunk = 1 + m_random.getLong(count - 1); + else + objChunk = m_random.getLong(count); + + QStringList::Iterator it = objData.at(objChunk); + QString sd = *it; + objData.remove(it); + if (insaneData.isEmpty()) + insaneData = sd; + else + insaneData += sd; + } + return insaneData; +} + +#include "kanagramgame.moc" diff --git a/kanagram/src/kanagramgame.h b/kanagram/src/kanagramgame.h new file mode 100644 index 00000000..940fbd57 --- /dev/null +++ b/kanagram/src/kanagramgame.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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. * + ***************************************************************************/ + +#ifndef KANAGRAMGAME_H +#define KANAGRAMGAME_H + +#include <qobject.h> + +#include <kstandarddirs.h> +#include <krandomsequence.h> + +class QWidget; + +class KanagramGame : public QObject +{ +Q_OBJECT + public: + KanagramGame(QWidget *parent); + ~KanagramGame(); + void refreshVocabList(); + void loadDefaultVocab(); + int findIndex(); + void nextAnagram(); + void nextVocab(); + void previousVocab(); + QString getAnagram(); + QString getHint(); + QString getWord(); + void restoreWord(); + QString getDocTitle(); + QString getFilename(); + private: + QString createAnagram(QString original); + void checkFile(); + QWidget *m_parent; + KRandomSequence m_random; + QString m_anagram; + QString m_hint; + QString m_originalWord; + + int m_index; + QStringList m_fileList; + QStringList m_answeredWords; + QString m_docTitle; + QString m_filename; +}; + +#endif diff --git a/kanagram/src/kanagramsettings.kcfgc b/kanagram/src/kanagramsettings.kcfgc new file mode 100644 index 00000000..49630279 --- /dev/null +++ b/kanagram/src/kanagramsettings.kcfgc @@ -0,0 +1,4 @@ +File=kanagram.kcfg +ClassName=KanagramSettings +Mutators=true +Singleton=true diff --git a/kanagram/src/keduvocdocument.cpp b/kanagram/src/keduvocdocument.cpp new file mode 100644 index 00000000..1af38f5a --- /dev/null +++ b/kanagram/src/keduvocdocument.cpp @@ -0,0 +1,1111 @@ +/*************************************************************************** + Vocabulary Document for KDE Edu + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Peter Hedlung + email : 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 "keduvocdocument.h" + +#include <kapplication.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kio/netaccess.h> + +#include <qfileinfo.h> + +#include <algorithm> +#include <functional> +#include <vector> +using namespace std; + +#include <iostream> + +#include <float.h> + +#include "keduvockvtmlwriter.h" +#include "keduvockvtmlreader.h" +#include "leitnersystem.h" +//#include "prefs.h" + +//******************************************************** +// KEduVocDocument +//******************************************************** + +KEduVocDocument::KEduVocDocument(QObject * /*parent*/) +{ + Init(); +} + + +KEduVocDocument::~KEduVocDocument() +{ +} + + +void KEduVocDocument::setVersion (const QString & vers) +{ + doc_version = vers; +} + + +void KEduVocDocument::getVersion(int &, int &, int &) +{ +} + + +void KEduVocDocument::Init () +{ + lesson_descr.clear(); + type_descr.clear(); + tense_descr.clear(); + langs.clear(); + sort_lang.clear(); + extraSizehints.clear(); + sizehints.clear(); + vocabulary.clear(); + dirty = false; + sort_allowed = true; + unknown_attr = false; + unknown_elem = false; + sort_lesson = false; + setCurrentLesson (0); + queryorg = ""; + querytrans = ""; + doc_url.setFileName(i18n("Untitled")); + doctitle = ""; + author = ""; + + activeLeitnerSystem = false; + leitnerSystem = 0; +} + + +bool KEduVocDocument::open(const KURL& url, bool /*append*/) +{ + Init(); + if (!url.isEmpty()) + doc_url = url; + + // TODO EPT connect( this, SIGNAL(progressChanged(KEduVocDocument*,int)), parent, SLOT(slotProgress(KEduVocDocument*,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 false; + } + + FileType ft = detectFT(url.path()); + + bool read = false; + while (!read) { + + QApplication::setOverrideCursor( waitCursor ); + switch (ft) { + case kvtml: + { + KEduVocKvtmlReader kvtmlReader(&f); + read = kvtmlReader.readDoc(this); + } + break; + + case vt_lex: + { + QTextStream is (&f); + //TODO read = loadFromLex (is); + } + break; + + case vt_vcb: + { + QTextStream is (&f); + //TODO read = loadFromVcb (is); + } + break; + + case csv: + { + QTextStream is(&f); + //TODO read = loadFromCsv(is); + } + break; + + default: + { + KEduVocKvtmlReader kvtmlReader(&f); + read = kvtmlReader.readDoc(this); + } + } + + QApplication::restoreOverrideCursor(); + + if (!read) { + if (unknown_attr || unknown_elem ) { + Init(); + return false; + } + // TODO new readers provide an explicite error message + // the two messages should be merged + 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 false; + } + } + } + f.close(); + KIO::NetAccess::removeTempFile( tmpfile ); + } + return true; +} + + +bool KEduVocDocument::saveAs(QObject * /*parent*/, const KURL & url, FileType ft, const QString & generator) +{ +// connect( this, SIGNAL(progressChanged(KEduVocDocument*,int)), parent, SLOT(slotProgress(KEduVocDocument*,int)) ); + + KURL tmp (url); + + 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: { + KEduVocKvtmlWriter kvtmlWriter(&f); + saved = kvtmlWriter.writeDoc(this, generator); + } + break; + + case vt_lex: { + QTextStream os( &f ); // serialize using f + //TODO saved = saveToLex(os, title); + } + break; + + case vt_vcb: { + QTextStream os( &f ); // serialize using f + //TODO saved = saveToVcb(os, title); + } + break; + + case csv: { + QTextStream os( &f ); // serialize using f + //TODO saved = saveToCsv(os, title); + } + break; + + default: { + kdError() << "kvcotrainDoc::saveAs(): unknown filetype" << endl; + } + break; + } + f.close(); + QApplication::restoreOverrideCursor(); + + if (!saved) { + // TODO new writers provide an explicite error message + // the two messages should be merged + 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; +} + + +KEduVocExpression *KEduVocDocument::getEntry(int index) +{ + if (index < 0 || index >= (int)vocabulary.size() ) + return 0; + else + return &vocabulary[index]; +} + + +void KEduVocDocument::removeEntry(int index) +{ + if (index >= 0 && index < (int)vocabulary.size() ) + vocabulary.erase (vocabulary.begin() + index); +} + + +int KEduVocDocument::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 KEduVocDocument::getIdent (int index) const +{ + if (index >= (int)langs.size() || index < 1 ) + return ""; + else + return langs[index]; +} + + +void KEduVocDocument::setIdent (int idx, const QString &id) +{ + if (idx < (int)langs.size() && idx >= 1 ) { + langs[idx] = id; + } +} + + +QString KEduVocDocument::getTypeName (int index) const +{ + if (index >= (int)type_descr.size()) + return ""; + else + return type_descr[index]; +} + + +void KEduVocDocument::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 KEduVocDocument::getTenseName (int index) const +{ + if (index >= (int)tense_descr.size()) + return ""; + else + return tense_descr[index]; +} + + +void KEduVocDocument::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 KEduVocDocument::getUsageName (int index) const +{ + if (index >= (int)usage_descr.size()) + return ""; + else + return usage_descr[index]; +} + + +void KEduVocDocument::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 KEduVocDocument::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 KEduVocDocument::getConjugation (int idx) const +{ + if (idx >= (int)conjugations.size() || idx < 0) { + return Conjugation(); + } + else { + return conjugations[idx]; + } +} + + +void KEduVocDocument::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 KEduVocDocument::getArticle (int idx) const +{ + if (idx >= (int)articles.size() || idx < 0) { + return Article(); + } + else { + return articles[idx]; + } +} + + +int KEduVocDocument::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 KEduVocDocument::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<KEduVocExpression, void> +{ + +public: + + eraseTrans (int idx) + : index (idx) {} + + void operator() (KEduVocExpression& x) const + { + x.removeTranslation(index); + } + + private: + int index; +}; + + +void KEduVocDocument::removeIdent (int index) +{ + if (index < (int)langs.size() && index >= 1 ) { + langs.erase(langs.begin() + index); + for_each (vocabulary.begin(), vocabulary.end(), eraseTrans(index)); + } +} + + +QString KEduVocDocument::getOriginalIdent () const +{ + if (langs.size() > 0) + return langs[0]; + else + return ""; +} + + +void KEduVocDocument::setOriginalIdent (const QString &id) +{ + if (langs.size() > 0) { + langs[0] = id; + } +} + + +class sortByOrg : public binary_function<KEduVocExpression, KEduVocExpression, bool> +{ + +public: + + sortByOrg (bool _dir) + : dir (_dir) {} + + bool operator() (const KEduVocExpression& x, const KEduVocExpression& 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<KEduVocExpression, KEduVocExpression, bool> +{ + +public: + + sortByLessonAndOrg_alpha (bool _dir, KEduVocDocument &_doc) + : dir (_dir), doc(_doc) {} + + bool operator() (const KEduVocExpression& x, const KEduVocExpression& 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; + KEduVocDocument &doc; +}; + + +class sortByLessonAndOrg_index + : public binary_function<KEduVocExpression, KEduVocExpression, bool> +{ + +public: + + sortByLessonAndOrg_index (bool _dir, KEduVocDocument &_doc) + : dir (_dir), doc(_doc) {} + + bool operator() (const KEduVocExpression& x, const KEduVocExpression& 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; + KEduVocDocument &doc; +}; + + +class sortByTrans : public binary_function<KEduVocExpression, KEduVocExpression, bool> +{ + +public: + + sortByTrans (int i, bool _dir) + : index(i), dir (_dir) {} + + bool operator() (const KEduVocExpression& x, const KEduVocExpression& 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 KEduVocDocument::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 KEduVocDocument::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 KEduVocDocument::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; +} + +bool KEduVocDocument::leitnerSystemActive() +{ + return activeLeitnerSystem; +} + +void KEduVocDocument::setLeitnerSystemActive( bool yes ) +{ + if( yes ) + { + if( leitnerSystem == 0 ) + createStandardLeitnerSystem(); //if nothing is loaded yet + + activeLeitnerSystem = true; + } + else if( !yes ) + activeLeitnerSystem = false; +} + +void KEduVocDocument::createStandardLeitnerSystem() +{ + LeitnerSystem* tmpSystem = new LeitnerSystem(); + QString name = "Standard"; + + tmpSystem->setSystemName( name ); + tmpSystem->insertBox( "Box 1" ); + tmpSystem->insertBox( "Box 2" ); + tmpSystem->insertBox( "Box 3" ); + tmpSystem->insertBox( "Box 4" ); + tmpSystem->insertBox( "Box 5" ); + + tmpSystem->setCorrectBox( "Box 1", "Box 2" ); + tmpSystem->setWrongBox( "Box 1", "Box 1" ); + + tmpSystem->setCorrectBox( "Box 2", "Box 3" ); + tmpSystem->setWrongBox( "Box 2", "Box 1" ); + + tmpSystem->setCorrectBox( "Box 3", "Box 4" ); + tmpSystem->setWrongBox( "Box 3", "Box 1" ); + + tmpSystem->setCorrectBox( "Box 4", "Box 5" ); + tmpSystem->setWrongBox( "Box 4", "Box 1" ); + + tmpSystem->setCorrectBox( "Box 5", "Box 1" ); + tmpSystem->setWrongBox( "Box 5", "Box 1" ); + + leitnerSystem = tmpSystem; +} + +void KEduVocDocument::setLeitnerSystem( LeitnerSystem* system ) +{ + leitnerSystem = system; + + /*KWordQuizApp* app = (KWordQuizApp*) parent(); + app->slotLeitnerSystem();*/ +} + +LeitnerSystem* KEduVocDocument::getLeitnerSystem() +{ + return leitnerSystem; +} + + +class resetAll : public unary_function<KEduVocExpression, void> +{ + +public: + + resetAll (int less) + : lesson(less) {} + + void operator() (KEduVocExpression& 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<KEduVocExpression, void> +{ + +public: + + resetOne (int idx, int less) + : index (idx), lesson(less) {} + + void operator() (KEduVocExpression& 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 KEduVocDocument::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 KEduVocDocument::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> KEduVocDocument::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 KEduVocDocument::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 KEduVocDocument::getTitle() const +{ + if (doctitle.isEmpty()) + return doc_url.fileName(); + else + return doctitle; +} + + +QString KEduVocDocument::getAuthor() const +{ + return author; +} + + +QString KEduVocDocument::getLicense() const +{ + return license; +} + + +QString KEduVocDocument::getDocRemark() const +{ + return doc_remark; +} + + +void KEduVocDocument::setTitle(const QString & title) +{ + doctitle = title.stripWhiteSpace(); +} + + +void KEduVocDocument::setAuthor(const QString & s) +{ + author = s.stripWhiteSpace(); +} + + +void KEduVocDocument::setLicense(const QString & s) +{ + license = s.stripWhiteSpace(); +} + + +void KEduVocDocument::setDocRemark(const QString & s) +{ + doc_remark = s.stripWhiteSpace(); +} + + +int KEduVocDocument::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; + + if (id >= numLangs() + || last < first + ) + return -1; + + if (id == 0) { + for (int i = first; i < last; i++) { + if (word_start) { + if (getEntry(i)->getOriginal().find (substr, 0, false) == 0) // case insensitive + return i; + } + else { + if (getEntry(i)->getOriginal().find (substr, 0, false) > -1) // case insensitive + return i; + } + } + } + else { + for (int i = first; i < last; i++) { + if (word_start) { + if (getEntry(i)->getTranslation(id).find (substr, 0, false) == 0) // 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 KEduVocDocument::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 KEduVocDocument::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" +} + + +KEduVocDocument::FileType KEduVocDocument::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; + + return csv; +} + + +class expRef { + +public: + + expRef (KEduVocExpression *_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; + KEduVocExpression *exp; +}; + + +int KEduVocDocument::cleanUp() +{ + int count = 0; + KEduVocExpression *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 "keduvocdocument.moc" diff --git a/kanagram/src/keduvocdocument.h b/kanagram/src/keduvocdocument.h new file mode 100644 index 00000000..4e48e21b --- /dev/null +++ b/kanagram/src/keduvocdocument.h @@ -0,0 +1,687 @@ +/*************************************************************************** + Vocabulary Document for KDE Edu + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Peter Hedlung + email : 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 KEDUVOCDOCUMENT_H +#define KEDUVOCDOCUMENT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qobject.h> + +#include <kurl.h> + +#include "keduvocexpression.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" + +#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 "__" + +class QTextStream; +class QStringList; +class MultipleChoice; +class LeitnerSystem; + +/************************************************************* + * This class contains the expressions of your vocabulary + ************************************************************/ + +class KEduVocDocument : public QObject +{ + Q_OBJECT + friend class KEduVocKvtmlWriter; + friend class KEduVocKvtmlReader; + + public: + + enum FileType { kvd_none, automatic, + kvtml, + kvtbin, + vt_lex, vt_vcb, csv /*, kvoclearn, qvocab*/ }; + + /** Constructor for the fileclass of the application + * + * @param obj calling object + */ + KEduVocDocument(QObject* obj); + + /** Destructor for the fileclass of the application */ + ~KEduVocDocument(); + + /** 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 (KEduVocExpression *expr) + { vocabulary.push_back (*expr); dirty = true; } + + /** insert an entry + * + * @param expr expression to append + * @param index index of entry + */ + inline void insertEntry(KEduVocExpression *expr, int index) + { vocabulary.insert(vocabulary.begin()+index, *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 originals identifier + */ + QString getOriginalIdent () const; + + /** set originals 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; } + + /** open a document file + * + * @param url + * @result true if successful + */ + bool open(const KURL& url, bool append); + + /** 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, FileType ft, const QString & generator); + + /** 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 + */ + KEduVocExpression *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 leitnerSystemActive(); + void setLeitnerSystemActive(bool yes); + void createStandardLeitnerSystem(); + void setLeitnerSystem( LeitnerSystem* system ); + LeitnerSystem* getLeitnerSystem(); + + 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 (KEduVocDocument *, int curr_percent); + void docModified (bool mod); + +protected: + + void Init(); + + /** sets version of loaded file */ + void setVersion(const QString & ver); + + /* TODO + 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); + 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<KEduVocExpression> 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; + + LeitnerSystem* leitnerSystem; + bool activeLeitnerSystem; +}; + + +#endif // KEDUVOCDOCUMENT_H diff --git a/kanagram/src/keduvocexpression.cpp b/kanagram/src/keduvocexpression.cpp new file mode 100644 index 00000000..9ac29894 --- /dev/null +++ b/kanagram/src/keduvocexpression.cpp @@ -0,0 +1,792 @@ +/*************************************************************************** + Vocabulary Expression for KDE Edu + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Peter Hedlung + email : 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 "keduvocexpression.h" + +void KEduVocExpression::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; +} + + +KEduVocExpression::KEduVocExpression (QString &expr, int _lesson) +{ + Init(); + setOriginal(expr.stripWhiteSpace() ); + lesson = _lesson; +} + + +KEduVocExpression::KEduVocExpression () +{ + Init(); +} + + +KEduVocExpression::KEduVocExpression (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); + } + } +} + + +KEduVocExpression::~KEduVocExpression() +{ +} + + +int KEduVocExpression::numTranslations() const +{ + return translations.size(); +} + + +QString KEduVocExpression::getRemark (int idx) const +{ + if (idx >= (int)remarks.size() || idx < 0) { + return ""; + } + else { + return remarks[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::getSynonym (int idx) const +{ + if (idx >= (int)synonym.size() || idx < 0) { + return ""; + } + else { + return synonym[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getExample (int idx) const +{ + if (idx >= (int)example.size() || idx < 0) { + return ""; + } + else { + return example[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getUsageLabel (int idx) const +{ + if (idx >= (int)usageLabels.size() || idx < 0) { + return ""; + } + else { + return usageLabels[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getParaphrase (int idx) const +{ + if (idx >= (int)paraphrases.size() || idx < 0) { + return ""; + } + else { + return paraphrases[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getAntonym (int idx) const +{ + if (idx >= (int)antonym.size() || idx < 0) { + return ""; + } + else { + return antonym[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getConjugation (int idx) const +{ + if (idx >= (int)conjugations.size() || idx < 0) { + return Conjugation(); + } + else { + return conjugations[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getComparison (int idx) const +{ + if (idx >= (int)comparisons.size() || idx < 0) { + return Comparison(); + } + else { + return comparisons[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::getMultipleChoice (int idx) const +{ + if (idx >= (int)mcs.size() || idx < 0) { + return MultipleChoice(); + } + else { + return mcs[idx]; + } +} + + +QString KEduVocExpression::getPronunce (int idx) const +{ + if (idx >= (int)pronunces.size() || idx < 0) { + return ""; + } + else { + return pronunces[idx]; + } +} + + +void KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::getTranslation (int idx) const +{ + if (idx > (int)translations.size() || idx < 1) + return ""; + else + return translations[idx-1]; +} + + +void KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::gradeStr (int idx, bool rev_grade) const +{ + QString s; + s.setNum(getGrade(idx, rev_grade)); + return s; +} + + +grade_t KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::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 KEduVocExpression::getType (int idx) const +{ + if (idx >= (int)exprtypes.size() || idx < 0) { + return ""; + } + else { + return exprtypes[idx]; + } +} + + +int KEduVocExpression::getLesson () const +{ + return lesson; +} + +void KEduVocExpression::incQueryCount (int index, bool rev_count) +{ + setQueryCount (index, getQueryCount(index, rev_count)+1, rev_count); +} + + +void KEduVocExpression::incBadCount (int index, bool rev_count) +{ + setBadCount (index, getBadCount(index, rev_count)+1, rev_count); +} + + +void KEduVocExpression::setOriginal ( const QString & expr) +{ + origin = expr; +} + + +QString KEduVocExpression::getOriginal () const +{ + return origin; +} + + +void KEduVocExpression::setLesson (int l) +{ + lesson = l; +} + + +void KEduVocExpression::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/kanagram/src/keduvocexpression.h b/kanagram/src/keduvocexpression.h new file mode 100644 index 00000000..64b2233b --- /dev/null +++ b/kanagram/src/keduvocexpression.h @@ -0,0 +1,456 @@ +/*************************************************************************** + Vocabulary Expression for KDE Edu + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Peter Hedlung + email : 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 KEDUVOCEXPRESSION_H +#define KEDUVOCEXPRESSION_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 +#define KV_NORM_TEXT I18N_NOOP("Not Queried Yet") + +#define KV_LEV1_GRADE 1 +#define KV_LEV1_TEXT I18N_NOOP("Level 1") + +#define KV_LEV2_GRADE 2 +#define KV_LEV2_TEXT I18N_NOOP("Level 2") + +#define KV_LEV3_GRADE 3 +#define KV_LEV3_TEXT I18N_NOOP("Level 3") + +#define KV_LEV4_GRADE 4 +#define KV_LEV4_TEXT I18N_NOOP("Level 4") + +#define KV_LEV5_GRADE 5 +#define KV_LEV5_TEXT I18N_NOOP("Level 5") + +#define KV_LEV6_GRADE 6 +#define KV_LEV6_TEXT I18N_NOOP("Level 6") + +#define KV_LEV7_GRADE 7 +#define 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 KEduVocExpression +{ + public: + + /** default constructor for an expression in different languages + */ + ~KEduVocExpression (); + + KEduVocExpression (); + + KEduVocExpression (QString &s, QString separator, int lesson = 0); + + /** Constructor for an expression in different languages + * + * @param expr expression + */ + KEduVocExpression (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 // KEduVocExpression_H + diff --git a/kanagram/src/keduvockvtmlreader.cpp b/kanagram/src/keduvockvtmlreader.cpp new file mode 100644 index 00000000..13e6f53a --- /dev/null +++ b/kanagram/src/keduvockvtmlreader.cpp @@ -0,0 +1,1695 @@ +/*************************************************************************** + read a KEduVocDocument from a KVTML file + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Eric Pignet + email : eric at erixpage.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <qdom.h> +#include <qtextstream.h> + +#include "keduvockvtmlreader.h" +#include "keduvocdocument.h" + +KEduVocKvtmlReader::KEduVocKvtmlReader(QFile *file) +{ + // the file must be already open + m_inputFile = file; +} + +KEduVocKvtmlReader::~KEduVocKvtmlReader() +{ +} + + +bool KEduVocKvtmlReader::readLesson(QDomElement &domElementParent) +{ + QString s; + m_doc->lesson_descr.clear(); + + //------------------------------------------------------------------------- + // Attributes + //------------------------------------------------------------------------- + + QDomAttr domAttrWidth = domElementParent.attributeNode(KV_SIZEHINT); + if (!domAttrWidth.isNull()) + m_doc->setSizeHint(-1, domAttrWidth.value().toInt()); + + //------------------------------------------------------------------------- + // Children + //------------------------------------------------------------------------- + + QDomElement domElementChild = domElementParent.firstChild().toElement(); + + while (!domElementChild.isNull()) + { + if (domElementChild.tagName() == KV_LESS_DESC) + { + //----------- + // Attributes + + int no = 0; + bool isCurr = false; + + QDomAttr domAttrNo = domElementChild.attributeNode(KV_LESS_NO); + if (!domAttrNo.isNull()) + no = domAttrNo.value().toInt(); + + QDomAttr domAttrCurrent = domElementChild.attributeNode(KV_LESS_CURR); + if (!domAttrCurrent.isNull()) + isCurr = domAttrCurrent.value().toInt() != 0; + + if (isCurr && no != 0) + m_doc->setCurrentLesson(no); + + QDomAttr domAttrQuery = domElementChild.attributeNode(KV_LESS_QUERY); + if (!domAttrQuery.isNull()) + m_doc->lessons_in_query.push_back(domAttrQuery.value().toInt() != 0); + else + m_doc->lessons_in_query.push_back(false); + + //----- + // Text + + s = domElementChild.text(); + if (s.isNull()) + s = ""; + m_doc->lesson_descr.push_back(s); + } + else + { + domErrorUnknownElement(domElementChild.tagName()); + return false; + } + + domElementChild = domElementChild.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readArticle(QDomElement &domElementParent) +/* + <article> + <e l="de"> lang determines also lang order in entries !! + <fi>eine</fi> which must NOT differ + <fd>die</fd> + <mi>ein</mi> + <md>der</md> + <ni>ein</ni> + <nd>das</nd> + </e> + </article> +*/ +{ + bool endOfGroup = false; + bool inEntry = false; + int count = 0; + QString s; + m_doc->articles.clear(); + + QDomElement domElementEntry = domElementParent.firstChild().toElement(); + + while (!domElementEntry.isNull()) + { + if (domElementEntry.tagName() != KV_ART_ENTRY) + { + domError(i18n("expected tag <%1>").arg(KV_ART_ENTRY)); + return false; + } + + //---------- + // Attribute + + QString lang; + QDomAttr domAttrLang = domElementEntry.attributeNode(KV_LANG); + + if ((int)m_doc->langs.size() <= count) + { + // first entry + if (!domAttrLang.isNull()) // no definition in first entry + lang = domAttrLang.value(); + else + lang = "original"; + m_doc->langs.push_back(lang); + } + else + { + if (!domAttrLang.isNull() && domAttrLang.value() != m_doc->langs[count]) + { + // different originals ? + domError(i18n("ambiguous definition of language code")); + return false; + } + } + + //--------- + // Children + + QString fem_def = ""; + QString mal_def = ""; + QString nat_def = ""; + QString fem_indef = ""; + QString mal_indef = ""; + QString nat_indef = ""; + + QDomElement domElementEntryChild = domElementEntry.firstChild().toElement(); + while (!domElementEntryChild.isNull()) + { + if (domElementEntryChild.tagName() == KV_ART_FD) + { + fem_def = domElementEntryChild.text(); + if (fem_def.isNull()) + fem_def = ""; + } + else if (domElementEntryChild.tagName() == KV_ART_FI) + { + fem_indef = domElementEntryChild.text(); + if (fem_indef.isNull()) + fem_indef = ""; + } + else if (domElementEntryChild.tagName() == KV_ART_MD) + { + mal_def = domElementEntryChild.text(); + if (mal_def.isNull()) + mal_def = ""; + } + else if (domElementEntryChild.tagName() == KV_ART_MI) + { + mal_indef = domElementEntryChild.text(); + if (mal_indef.isNull()) + mal_indef = ""; + } + else if (domElementEntryChild.tagName() == KV_ART_ND) + { + nat_def = domElementEntryChild.text(); + if (nat_def.isNull()) + nat_def = ""; + } + else if (domElementEntryChild.tagName() == KV_ART_NI) + { + nat_indef = domElementEntryChild.text(); + if (nat_indef.isNull()) + nat_indef = ""; + } + else + { + domErrorUnknownElement(domElementEntryChild.tagName()); + return false; + } + + domElementEntryChild = domElementEntryChild.nextSibling().toElement(); + } + + m_doc->articles.push_back(Article( fem_def, fem_indef, + mal_def, mal_indef, + nat_def, nat_indef)); + + domElementEntry = domElementEntry.nextSibling().toElement(); + count++; + } + + return true; +} + + +bool KEduVocKvtmlReader::readConjug(QDomElement &domElementParent, + vector<Conjugation> &curr_conjug, + const QString &entry_tag) +/* + <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> +*/ +{ + QString s; + + curr_conjug.clear(); + + 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()); + + QDomElement domElementConjugChild = domElementParent.firstChild().toElement(); + while (!domElementConjugChild.isNull()) + { + if (domElementConjugChild.tagName() == KV_CON_ENTRY) + { + type = CONJ_PREFIX; + + //---------- + // Attribute + + QString lang; + QDomAttr domAttrLang = domElementConjugChild.attributeNode(KV_LANG); + + if ((int)m_doc->langs.size() <= count) + { + // first entry + if (!domAttrLang.isNull()) // no definition in first entry + lang = domAttrLang.value(); + else + lang = "original"; + m_doc->langs.push_back(lang); + } + else + { + if (!domAttrLang.isNull() && domAttrLang.value() != m_doc->langs[count]) + { + // different originals ? + domError(i18n("ambiguous definition of language code")); + return false; + } + } + } + else if (domElementConjugChild.tagName() == KV_CON_TYPE) + { + //---------- + // Attribute + + QDomAttr domAttrLang = domElementConjugChild.attributeNode(KV_CON_NAME); + type = domAttrLang.value(); + if (type.isNull()) + type = ""; + + if (type.length() != 0 && type.left(1) == UL_USER_TENSE) + { + int num = QMIN(type.mid (1, 40).toInt(), 1000); // paranoia check + if( num > (int) m_doc->tense_descr.size() ) + { + // description missing ? + QString s; + for (int i = m_doc->tense_descr.size(); i < num; i++) + { + s.setNum (i+1); + s.insert (0, "#"); // invent descr according to number + m_doc->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; + + QDomElement domElementConjugGrandChild = domElementConjugChild.firstChild().toElement(); + while (!domElementConjugGrandChild.isNull()) + { + if (domElementConjugGrandChild.tagName() == KV_CON_P1S) + { + pers1_sing = domElementConjugGrandChild.text(); + if (pers1_sing.isNull()) + pers1_sing = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P2S) + { + pers2_sing = domElementConjugGrandChild.text(); + if (pers2_sing.isNull()) + pers2_sing = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3SF) + { + QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON); + if (!domAttrCommon.isNull()) + s3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails + + pers3_f_sing = domElementConjugGrandChild.text(); + if (pers3_f_sing.isNull()) + pers3_f_sing = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3SM) + { + pers3_m_sing = domElementConjugGrandChild.text(); + if (pers3_m_sing.isNull()) + pers3_m_sing = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3SN) + { + pers3_n_sing = domElementConjugGrandChild.text(); + if (pers3_n_sing.isNull()) + pers3_n_sing = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P1P) + { + pers1_plur = domElementConjugGrandChild.text(); + if (pers1_plur.isNull()) + pers1_plur = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P2P) + { + pers2_plur = domElementConjugGrandChild.text(); + if (pers2_plur.isNull()) + pers2_plur = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3PF) + { + QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON); + if (!domAttrCommon.isNull()) + p3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails + + pers3_f_plur = domElementConjugGrandChild.text(); + if (pers3_f_plur.isNull()) + pers3_f_plur = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3PM) + { + pers3_m_plur = domElementConjugGrandChild.text(); + if (pers3_m_plur.isNull()) + pers3_m_plur = ""; + } + else if (domElementConjugGrandChild.tagName() == KV_CON_P3PN) + { + pers3_n_plur = domElementConjugGrandChild.text(); + if (pers3_n_plur.isNull()) + pers3_n_plur = ""; + } + else + { + domErrorUnknownElement(domElementConjugGrandChild.tagName()); + return false; + } + + domElementConjugGrandChild = domElementConjugGrandChild.nextSibling().toElement(); + } + + if (domElementConjugChild.tagName() == 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 (domElementConjugChild.tagName() == KV_CON_ENTRY) + count++; + + domElementConjugChild = domElementConjugChild.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readOptions(QDomElement &domElementParent) +{ + QDomElement domElementSort = domElementParent.firstChild().toElement(); + while (!domElementSort.isNull()) + { + if (domElementSort.tagName() == KV_OPT_SORT) + { + m_doc->sort_allowed = true; + QDomAttr domAttrOn = domElementSort.attributeNode(KV_BOOL_FLAG); + if (!domAttrOn.isNull()) + { + bool ok = true; + m_doc->sort_allowed = domAttrOn.value().toInt(&ok); // returns 0 if the conversion fails + if (!ok) + m_doc->sort_allowed = true; + } + } + + domElementSort = domElementSort.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readType(QDomElement &domElementParent) +{ + QString s; + m_doc->type_descr.clear(); + + QDomElement domElementDesc = domElementParent.firstChild().toElement(); + + while (!domElementDesc.isNull()) + { + if (domElementDesc.tagName() == KV_TYPE_DESC) + { + //----------- + // Attributes + + int no = 0; + bool isCurr = false; + + QDomAttr domAttrNo = domElementDesc.attributeNode(KV_TYPE_NO); + if (!domAttrNo.isNull()) + no = domAttrNo.value().toInt(); + + // TODO use 'no' to sort types + // but 'no' seems useless, since types are already ordered by their position in the XML doc + + s = domElementDesc.text(); + if (s.isNull()) + s = ""; + + m_doc->type_descr.push_back (s); + } + else + { + domErrorUnknownElement(domElementDesc.tagName()); + return false; + } + + domElementDesc = domElementDesc.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readTense(QDomElement &domElementParent) +{ + QString s; + m_doc->tense_descr.clear(); + + QDomElement domElementDesc = domElementParent.firstChild().toElement(); + + while (!domElementDesc.isNull()) + { + if (domElementDesc.tagName() == KV_TENSE_DESC) + { + //----------- + // Attributes + + int no = 0; + bool isCurr = false; + + QDomAttr domAttrNo = domElementDesc.attributeNode(KV_TENSE_NO); + if (!domAttrNo.isNull()) + no = domAttrNo.value().toInt(); + + // TODO use 'no' to sort tenses + // but 'no' seems useless, since tenses are already ordered by their position in the XML doc + + s = domElementDesc.text(); + if (s.isNull()) + s = ""; + + m_doc->tense_descr.push_back (s); + } + else + { + domErrorUnknownElement(domElementDesc.tagName()); + return false; + } + + domElementDesc = domElementDesc.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readUsage(QDomElement &domElementParent) +{ + QString s; + m_doc->usage_descr.clear(); + + QDomElement domElementDesc = domElementParent.firstChild().toElement(); + + while (!domElementDesc.isNull()) + { + if (domElementDesc.tagName() == KV_USAGE_DESC) + { + //----------- + // Attributes + + int no = 0; + bool isCurr = false; + + QDomAttr domAttrNo = domElementDesc.attributeNode(KV_USAGE_NO); + if (!domAttrNo.isNull()) + no = domAttrNo.value().toInt(); + + // TODO use 'no' to sort usages + // but 'no' seems useless, since usages are already ordered by their position in the XML doc + + s = domElementDesc.text(); + if (s.isNull()) + s = ""; + + m_doc->usage_descr.push_back (s); + } + else + { + domErrorUnknownElement(domElementDesc.tagName()); + return false; + } + + domElementDesc = domElementDesc.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readComparison(QDomElement &domElementParent, + Comparison &comp) +/* + <comparison> + <l1>good</l1> + <l2>better</l2> + <l3>best</l3> + </comparison> +*/ +{ + QString s; + comp.clear(); + + QDomElement domElementComparisonChild = domElementParent.firstChild().toElement(); + while (!domElementComparisonChild.isNull()) + { + if (domElementComparisonChild.tagName() == KV_COMP_L1) + { + s = domElementComparisonChild.text(); + if (s.isNull()) + s = ""; + comp.setL1(s); + } + + else if (domElementComparisonChild.tagName() == KV_COMP_L2) + { + s = domElementComparisonChild.text(); + if (s.isNull()) + s = ""; + comp.setL2(s); + } + + else if (domElementComparisonChild.tagName() == KV_COMP_L3) + { + s = domElementComparisonChild.text(); + if (s.isNull()) + s = ""; + comp.setL3(s); + } + + else + { + domErrorUnknownElement(domElementComparisonChild.tagName()); + return false; + } + + domElementComparisonChild = domElementComparisonChild.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readMultipleChoice(QDomElement &domElementParent, + MultipleChoice &mc) +/* + <multiplechoice> + <mc1>good</mc1> + <mc2>better</mc2> + <mc3>best</mc3> + <mc4>best 2</mc4> + <mc5>best 3</mc5> + </multiplechoice> +*/ + +{ + QString s; + mc.clear(); + + QDomElement domElementChild = domElementParent.firstChild().toElement(); + while (!domElementChild.isNull()) + { + if (domElementChild.tagName() == KV_MC_1) + { + s = domElementChild.text(); + if (s.isNull()) + s = ""; + mc.setMC1(s); + } + + else if (domElementChild.tagName() == KV_MC_2) + { + s = domElementChild.text(); + if (s.isNull()) + s = ""; + mc.setMC2(s); + } + + else if (domElementChild.tagName() == KV_MC_3) + { + s = domElementChild.text(); + if (s.isNull()) + s = ""; + mc.setMC3(s); + } + + else if (domElementChild.tagName() == KV_MC_4) + { + s = domElementChild.text(); + if (s.isNull()) + s = ""; + mc.setMC4(s); + } + + else if (domElementChild.tagName() == KV_MC_5) + { + s = domElementChild.text(); + if (s.isNull()) + s = ""; + mc.setMC5(s); + } + + else + { + domErrorUnknownElement(domElementChild.tagName()); + return false; + } + + domElementChild = domElementChild.nextSibling().toElement(); + } + + mc.normalize(); + return true; +} + + +bool KEduVocKvtmlReader::readExpressionChildAttributes( QDomElement &domElementExpressionChild, + 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 ¶phrase) +{ + int pos; + + lang = ""; + QDomAttr domAttrLang = domElementExpressionChild.attributeNode(KV_LANG); + if (!domAttrLang.isNull()) + lang = domAttrLang.value(); + + width = -1; + QDomAttr domAttrWidth = domElementExpressionChild.attributeNode(KV_SIZEHINT); + if (!domAttrWidth.isNull()) + width = domAttrWidth.value().toInt(); + + grade = KV_NORM_GRADE; + rev_grade = KV_NORM_GRADE; + QDomAttr domAttrGrade = domElementExpressionChild.attributeNode(KV_LANG); + if (!domAttrGrade.isNull()) + { + QString s = domAttrGrade.value(); + if ((pos = s.find(';')) >= 1) + { + grade = s.left(pos).toInt(); + rev_grade = s.mid(pos+1, s.length()).toInt(); + } + else + grade = s.toInt(); + } + + count = 0; + rev_count = 0; + QDomAttr domAttrCount = domElementExpressionChild.attributeNode(KV_COUNT); + if (!domAttrCount.isNull()) + { + QString s = domAttrCount.value(); + if ((pos = s.find(';')) >= 1) + { + count = s.left(pos).toInt(); + rev_count = s.mid(pos+1, s.length()).toInt(); + } + else + count = s.toInt(); + } + + bcount = 0; + rev_bcount = 0; + QDomAttr domAttrBad = domElementExpressionChild.attributeNode(KV_BAD); + if (!domAttrBad.isNull()) + { + QString s = domAttrBad.value(); + if ((pos = s.find(';')) >= 1) + { + bcount = s.left(pos).toInt(); + rev_bcount = s.mid(pos+1, s.length()).toInt(); + } + else + bcount = s.toInt(); + } + + date = 0; + rev_date = 0; + QDomAttr domAttrDate = domElementExpressionChild.attributeNode(KV_DATE); + if (!domAttrDate.isNull()) + { + QString s = domAttrDate.value(); + if ((pos = s.find(';')) >= 1) + { + date = s.left(pos).toInt(); + rev_date = s.mid(pos+1, s.length()).toInt(); + } + else + date = s.toInt(); + } + + QDomAttr domAttrDate2 = domElementExpressionChild.attributeNode(KV_DATE2); + if (!domAttrDate2.isNull()) + { + QString s = domAttrDate2.value(); + if ((pos = s.find(';')) >= 1) + { + date = m_doc->decompressDate(s.left(pos)); + rev_date = m_doc->decompressDate(s.mid(pos+1, s.length())); + } + else + date = m_doc->decompressDate(s); + } + + remark = ""; + QDomAttr domAttrRemark = domElementExpressionChild.attributeNode(KV_REMARK); + if (!domAttrRemark.isNull()) + remark = domAttrRemark.value(); + + faux_ami_f = ""; + QDomAttr domAttrFauxAmiF = domElementExpressionChild.attributeNode(KV_FAUX_AMI_F); + if (!domAttrFauxAmiF.isNull()) + faux_ami_f = domAttrFauxAmiF.value(); + + faux_ami_t = ""; + QDomAttr domAttrFauxAmiT = domElementExpressionChild.attributeNode(KV_FAUX_AMI_T); + if (!domAttrFauxAmiT.isNull()) + faux_ami_t = domAttrFauxAmiT.value(); + + synonym = ""; + QDomAttr domAttrSynonym = domElementExpressionChild.attributeNode(KV_SYNONYM); + if (!domAttrSynonym.isNull()) + synonym = domAttrSynonym.value(); + + example = ""; + QDomAttr domAttrExample = domElementExpressionChild.attributeNode(KV_EXAMPLE); + if (!domAttrExample.isNull()) + example = domAttrExample.value(); + + usage = ""; + QDomAttr domAttrUsage = domElementExpressionChild.attributeNode(KV_USAGE); + if (!domAttrUsage.isNull()) + { + usage = domAttrUsage.value(); + if (usage.length() != 0 && usage.left(1) == UL_USER_USAGE) + { + int num = QMIN(usage.mid (1, 40).toInt(), 1000); // paranioa check + if( num > (int) m_doc->usage_descr.size() ) + { + // description missing ? + QString s; + for (int i = m_doc->usage_descr.size(); i < num; i++) + { + s.setNum (i+1); + s.insert (0, "#"); // invent descr according to number + m_doc->usage_descr.push_back (s); + } + } + } + } + + paraphrase = ""; + QDomAttr domAttrParaphrase = domElementExpressionChild.attributeNode(KV_PARAPHRASE); + if (!domAttrParaphrase.isNull()) + paraphrase = domAttrParaphrase.value(); + + antonym = ""; + QDomAttr domAttrAntonym = domElementExpressionChild.attributeNode(KV_ANTONYM); + if (!domAttrAntonym.isNull()) + antonym = domAttrAntonym.value(); + + QDomAttr domAttrExprType = domElementExpressionChild.attributeNode(KV_EXPRTYPE); + if (!domAttrExprType.isNull()) + { + type = domAttrExprType.value(); + 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) m_doc->type_descr.size() ) + { + // description missing ? + QString s; + for (int i = m_doc->type_descr.size(); i < num; i++) + { + s.setNum (i+1); + s.insert (0, "#"); // invent descr according to number + m_doc->type_descr.push_back (s); + } + } + } + } + + pronunce = ""; + QDomAttr domAttrPronunce = domElementExpressionChild.attributeNode(KV_PRONUNCE); + if (!domAttrPronunce.isNull()) + pronunce = domAttrPronunce.value(); + + query_id = ""; + QDomAttr domAttrQuery = domElementExpressionChild.attributeNode(KV_QUERY); + if (!domAttrQuery.isNull()) + query_id = domAttrQuery.value(); + + return true; +} + + +bool KEduVocKvtmlReader::readExpression(QDomElement &domElementParent) +{ + 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; + KEduVocExpression expr; + int lesson = 0; + 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; + + //------------------------------------------------------------------------- + // Attributes + //------------------------------------------------------------------------- + + QDomAttr domAttrMember = domElementParent.attributeNode(KV_LESS_MEMBER); + if (!domAttrMember.isNull()) + lesson = domAttrMember.value().toInt(); + + QDomAttr domAttrSelected = domElementParent.attributeNode(KV_SELECTED); + if (!domAttrSelected.isNull()) + inquery = domAttrSelected.value().toInt(); + else + inquery = false; + + QDomAttr domAttrInactive = domElementParent.attributeNode(KV_INACTIVE); + if (!domAttrInactive.isNull()) + active = !domAttrInactive.value().toInt(); + else + active = false; + + QDomAttr domAttrType = domElementParent.attributeNode(KV_EXPRTYPE); + if (!domAttrType.isNull()) + { + exprtype = !domAttrType.value().toInt(); + if (exprtype == "1") + exprtype = QM_VERB; + else if (exprtype == "2") // convert from pre-0.5 versions + exprtype = QM_NOUN; + else if (exprtype == "3") + exprtype = QM_NAME; + + if (exprtype.length() != 0 && exprtype.left(1) == QM_USER_TYPE) + { + int num = QMIN(exprtype.mid (1, 40).toInt(), 1000); // paranoia check + if( num > (int) m_doc->type_descr.size() ) + { + // description missing ? + QString s; + for (int i = m_doc->type_descr.size(); i < num; i++) + { + s.setNum (i+1); + s.insert (0, "#"); // invent descr according to number + m_doc->type_descr.push_back (s); + } + } + } + } + + if (lesson && lesson > (int) m_doc->lesson_descr.size() ) + { + // description missing ? + QString s; + for (int i = m_doc->lesson_descr.size(); i < lesson; i++) + { + s.setNum (i+1); + s.insert (0, "#"); // invent descr according to number + m_doc->lesson_descr.push_back (s); + } + } + + //------------------------------------------------------------------------- + // Child 'Original' + //------------------------------------------------------------------------- + + // now want "original" and one or more "translations" + + QDomElement domElementExpressionChild = domElementParent.firstChild().toElement(); + + unsigned int count = 0; + org_found = false; + + if (domElementExpressionChild.tagName() != KV_ORG) + { + // must be preceded by "original" + domError(i18n("starting tag <%1> is missing").arg(KV_ORG)); + return false; + } + + // found original <o> + + org_found = true; + + type = exprtype; + + //----------- + // Attributes + + if (!readExpressionChildAttributes( domElementExpressionChild, + 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 (m_doc->vocabulary.size() == 0) + { + // only accept in first entry + if (width >= 0) + m_doc->setSizeHint (count, width); + + if (query_id == KV_O) + q_org = lang; + + if (query_id == KV_T) + q_trans = lang; + } + + if (m_doc->langs.size() == 0) + { + // first entry + if (lang.isEmpty()) // no definition in first entry + lang = "original"; + m_doc->langs.push_back(lang); + + } + else + { + if (lang != m_doc->langs[0] && !lang.isEmpty()) + { + // different originals ? + domError(i18n("ambiguous definition of language code")); + return false; + } + } + count = 0; + + //--------- + // Children + + bool bConjug = false; + bool bComparison = false; + bool bMultipleChoice = false; + + QDomElement domElementOriginalChild = domElementExpressionChild.firstChild().toElement(); + while (!domElementOriginalChild.isNull()) + { + if (domElementOriginalChild.tagName() == KV_CONJUG_GRP) + { + if (bConjug) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bConjug = true; + conjug.clear(); + if (!readConjug(domElementOriginalChild, conjug, (QString) KV_CON_TYPE)) + return false; + } + + else if (domElementOriginalChild.tagName() == KV_COMPARISON_GRP) + { + if (bComparison) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bComparison = true; + comparison.clear(); + if (!readComparison(domElementOriginalChild, comparison)) + return false; + } + + else if (domElementOriginalChild.tagName() == KV_MULTIPLECHOICE_GRP) + { + if (bMultipleChoice) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bMultipleChoice = true; + mc.clear(); + if (!readMultipleChoice(domElementOriginalChild, mc)) + return false; + } + + else + { + domErrorUnknownElement(domElementOriginalChild.tagName()); + return false; + } + + domElementOriginalChild = domElementOriginalChild.nextSibling().toElement(); + } + + textstr = domElementExpressionChild.lastChild().toText().data(); + if (textstr.isNull()) + textstr = ""; + + expr = KEduVocExpression(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); + + + //------------------------------------------------------------------------- + // Children 'Translation' + //------------------------------------------------------------------------- + + domElementExpressionChild = domElementExpressionChild.nextSibling().toElement(); + + while (!domElementExpressionChild.isNull()) + { + if (domElementExpressionChild.tagName() != KV_TRANS) + { + // "original" must be followed by "translations" + domError(i18n("starting tag <%1> is missing").arg(KV_TRANS)); + return false; + } + + // found translation <t> + + count++; + type = exprtype; + + //----------- + // Attributes + + if (!readExpressionChildAttributes( domElementExpressionChild, + 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 (m_doc->vocabulary.size() == 0) + { + // only accept in first entry + if (width >= 0) + m_doc->setSizeHint (count, width); + + if (query_id == KV_O) + q_org = lang; + + if (query_id == KV_T) + q_trans = lang; + + } + + if (m_doc->langs.size() <= count) + { + // new translation + if (lang.isEmpty()) + { + // no definition in first entry ? + lang.setNum (m_doc->langs.size() ); + lang.insert (0, "translation "); + } + m_doc->langs.push_back(lang); + + } + else + { + if (lang != m_doc->langs[count] && !lang.isEmpty()) + { // different language ? + domError(i18n("ambiguous definition of language code")); + return false; + } + } + + //--------- + // Children + + bool bConjug = false; + bool bComparison = false; + bool bMultipleChoice = false; + + QDomElement domElementOriginalChild = domElementExpressionChild.firstChild().toElement(); + while (!domElementOriginalChild.isNull()) + { + if (domElementOriginalChild.tagName() == KV_CONJUG_GRP) + { + if (bConjug) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bConjug = true; + conjug.clear(); + if (!readConjug(domElementOriginalChild, conjug, (QString) KV_CON_TYPE)) + return false; + } + + else if (domElementOriginalChild.tagName() == KV_COMPARISON_GRP) + { + if (bComparison) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bComparison = true; + comparison.clear(); + if (!readComparison(domElementOriginalChild, comparison)) + return false; + } + + else if (domElementOriginalChild.tagName() == KV_MULTIPLECHOICE_GRP) + { + if (bMultipleChoice) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementOriginalChild.tagName())); + return false; + } + bMultipleChoice = true; + mc.clear(); + if (!readMultipleChoice(domElementOriginalChild, mc)) + return false; + } + + else + { + domErrorUnknownElement(domElementOriginalChild.tagName()); + return false; + } + + domElementOriginalChild = domElementOriginalChild.nextSibling().toElement(); + } + + textstr = domElementExpressionChild.lastChild().toText().data(); + if (textstr.isNull()) + textstr = ""; + + /* + 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); + + domElementExpressionChild = domElementExpressionChild.nextSibling().toElement(); + } + if (m_doc->numEntries() == 0) + m_doc->setQueryLang(q_org, q_trans); + m_doc->vocabulary.push_back(expr); + + return true; +} + + +bool KEduVocKvtmlReader::readBody(QDomElement &domElementParent) +{ + 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) m_doc->lines / 100; + float f_ent_percent = (int) m_doc->lines / 100.0; +/* TODO EPT +if (lines != 0) + emit progressChanged(this, 0); +*/ + + QDomElement domElementChild = domElementParent.firstChild().toElement(); + + while (!domElementChild.isNull()) + { + if (domElementChild.tagName() == KV_LESS_GRP) + { + if (lessgroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + lessgroup = true; + if (!readLesson(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_ARTICLE_GRP) + { + if (articlegroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + articlegroup = true; + if (!readArticle(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_CONJUG_GRP) + { + if (conjuggroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + conjuggroup = true; + if (!readConjug(domElementChild, m_doc->conjugations, KV_CON_ENTRY)) + return false; + } + + else if (domElementChild.tagName() == KV_OPTION_GRP) + { + if (optgroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + optgroup = true; + if (!readOptions(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_TYPE_GRP) + { + if (attrgroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + attrgroup = true; + if (!readType(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_TENSE_GRP) + { + if (tensegroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + tensegroup = true; + if (!readTense(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_USAGE_GRP) + { + if (usagegroup) + { + domError(i18n("repeated occurrence of tag <%1>").arg(domElementChild.tagName())); + return false; + } + usagegroup = true; + if (!readUsage(domElementChild)) + return false; + } + + else if (domElementChild.tagName() == KV_EXPR) + { + /* TODO EPT + if (lines != 0) + { + ent_no++; + if (ent_percent != 0 && (ent_no % ent_percent) == 0 ) + emit progressChanged(this, int(ent_no / f_ent_percent)); + }*/ + if (!readExpression(domElementChild)) + return false; + } + + else + { + domErrorUnknownElement(domElementChild.tagName()); + return false; + } + + domElementChild = domElementChild.nextSibling().toElement(); + } + + return true; +} + + +bool KEduVocKvtmlReader::readDoc(KEduVocDocument *doc) +{ + m_doc = doc; + + QDomDocument domDoc("Kvtml" ); + QString errorMsg; + if( !domDoc.setContent( m_inputFile, &errorMsg ) ) + { + domError(errorMsg); + return false; + } + + m_doc->langs.clear(); + m_doc->vocabulary.clear(); + + m_doc->generator = ""; + m_doc->cols = 0; + m_doc->lines = 0; + m_doc->doctitle = ""; + m_doc->author = ""; + m_doc->license = ""; + m_doc->doc_remark = ""; + + + QDomElement domElementKvtml = domDoc.documentElement(); + if( domElementKvtml.tagName() != KV_DOCTYPE ) + { + domError(i18n("Tag <%1> was expected " + "but tag <%2> was read." ).arg(KV_DOCTYPE).arg(domElementKvtml.tagName())); + return false; + } + + //------------------------------------------------------------------------- + // Attributes + //------------------------------------------------------------------------- + + QDomAttr domAttrEncoding = domElementKvtml.attributeNode(KV_ENCODING); + if (!domAttrEncoding.isNull()) + { + // TODO handle old encodings + // Qt DOM API autodetects encoding, so is there anything to do ? + } + + QDomAttr domAttrTitle = domElementKvtml.attributeNode(KV_TITLE); + if (!domAttrTitle.isNull()) + { + m_doc->doctitle = domAttrTitle.value(); + } + + QDomAttr domAttrAuthor = domElementKvtml.attributeNode(KV_AUTHOR); + if (!domAttrAuthor.isNull()) + { + m_doc->author = domAttrAuthor.value(); + } + + QDomAttr domAttrLicence = domElementKvtml.attributeNode(KV_LICENSE); + if (!domAttrLicence.isNull()) + { + m_doc->license = domAttrLicence.value(); + } + + QDomAttr domAttrRemark = domElementKvtml.attributeNode(KV_DOC_REM); + if (!domAttrRemark.isNull()) + { + m_doc->doc_remark = domAttrRemark.value(); + } + + QDomAttr domAttrGenerator = domElementKvtml.attributeNode(KV_GENERATOR); + if (!domAttrGenerator.isNull()) + { + m_doc->generator = domAttrGenerator.value(); + int pos = m_doc->generator.findRev (KVD_VERS_PREFIX); + if (pos >= 0) + { + m_doc->doc_version = m_doc->generator; + m_doc->doc_version.remove (0, pos+2); + } + } + + QDomAttr domAttrCols = domElementKvtml.attributeNode(KV_COLS); + if (!domAttrCols.isNull()) + { + m_doc->cols = domAttrCols.value().toInt(); + } + + QDomAttr domAttrLines = domElementKvtml.attributeNode(KV_LINES); + if (!domAttrLines.isNull()) + { + m_doc->lines = domAttrLines.value().toInt(); + } + + + //------------------------------------------------------------------------- + // Children + //------------------------------------------------------------------------- + + bool result = readBody(domElementKvtml); // read vocabulary + + // TODO EPT setModified (false); + return result; +} + + +void KEduVocKvtmlReader::domErrorUnknownElement(const QString &elem) +{ + QString ln = i18n("File:\t%1\n").arg(m_doc->URL().path()); + + 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 KEduVocKvtmlReader::domError(const QString &text ) +{ + QApplication::setOverrideCursor( arrowCursor, true ); + QString s = kapp->makeStdCaption(i18n("Error")); + QString ln = i18n("File:\t%1\n").arg(m_doc->URL().path()); + QString msg = text; + KMessageBox::error(0, ln+msg, s); + QApplication::restoreOverrideCursor(); +} + diff --git a/kanagram/src/keduvockvtmlreader.h b/kanagram/src/keduvockvtmlreader.h new file mode 100644 index 00000000..9d902183 --- /dev/null +++ b/kanagram/src/keduvockvtmlreader.h @@ -0,0 +1,121 @@ +/*************************************************************************** + read a KEduVocDocument from a KVTML file + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Eric Pignet + email : eric at erixpage.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KEDUVOCKVTMLREADER_H +#define KEDUVOCKVTMLREADER_H + +#include <qfile.h> +#include <qdom.h> + +#include "keduvocdocument.h" +#include "grammarmanager.h" +#include "multiplechoice.h" + +class KEduVocDocument; + +// 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 + +// usage delimiters (also declared in UsageManager.h) + +#define UL_USER_USAGE "#" // designates number of user type + +/** +@author Eric Pignet +*/ +class KEduVocKvtmlReader : public QObject +{ +public: + KEduVocKvtmlReader(QFile *file); + ~KEduVocKvtmlReader(); + + bool readDoc(KEduVocDocument *doc); + + bool readLesson(QDomElement &domElementParent); + bool readArticle(QDomElement &domElementParent); + bool readConjug(QDomElement &domElementParent, + vector<Conjugation> &curr_conjug, + const QString &entry_tag); + bool readOptions(QDomElement &domElementParent); + bool readType(QDomElement &domElementParent); + bool readTense(QDomElement &domElementParent); + bool readUsage(QDomElement &domElementParent); + bool readComparison(QDomElement &domElementParent, + Comparison &comp); + bool readMultipleChoice(QDomElement &domElementParent, + MultipleChoice &mc); + bool readExpressionChildAttributes( QDomElement &domElementExpressionChild, + 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 ¶phrase); + bool readExpression(QDomElement &domElementParent); + bool readBody(QDomElement &domElementParent); + + void domErrorUnknownElement(const QString &elem); + void domError(const QString &text ); + +private: + QFile *m_inputFile; + KEduVocDocument *m_doc; +}; + +#endif diff --git a/kanagram/src/keduvockvtmlwriter.cpp b/kanagram/src/keduvockvtmlwriter.cpp new file mode 100644 index 00000000..c859d828 --- /dev/null +++ b/kanagram/src/keduvockvtmlwriter.cpp @@ -0,0 +1,949 @@ +/*************************************************************************** + export a KEduVocDocument to a KVTML file + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Eric Pignet + email : eric at erixpage.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <kdebug.h> +#include <qdom.h> +#include <qtextstream.h> + +#include "keduvockvtmlwriter.h" +#include "keduvocdocument.h" + +KEduVocKvtmlWriter::KEduVocKvtmlWriter(QFile *file) +{ + // the file must be already open + m_outputFile = file; +} + +KEduVocKvtmlWriter::~KEduVocKvtmlWriter() +{ +} + +bool KEduVocKvtmlWriter::saveTypeNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent) +{ + if (m_doc->type_descr.size() == 0) + return true; + + QDomElement domElementType = domDoc.createElement(KV_TYPE_GRP); + + for (int lfn = 0; lfn < (int) m_doc->type_descr.size(); lfn++) + { + if (!(m_doc->type_descr[lfn].isNull()) ) + { + QDomElement domElementDesc = domDoc.createElement(KV_TYPE_DESC); + QDomText domTextDesc = domDoc.createTextNode(m_doc->type_descr[lfn]); + + domElementDesc.setAttribute(KV_TYPE_NO, lfn+1); + domElementDesc.appendChild(domTextDesc); + domElementType.appendChild(domElementDesc); + } + } + + domElementParent.appendChild(domElementType); + return true; +} + + +bool KEduVocKvtmlWriter::saveTenseNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent) +{ + if (m_doc->tense_descr.size() == 0) + return true; + + QDomElement domElementTense = domDoc.createElement(KV_TENSE_GRP); + + for (int lfn = 0; lfn < (int) m_doc->tense_descr.size(); lfn++) + { + if (!(m_doc->tense_descr[lfn].isNull()) ) { + QDomElement domElementDesc = domDoc.createElement(KV_TENSE_DESC); + QDomText domTextDesc = domDoc.createTextNode(m_doc->tense_descr[lfn]); + + domElementDesc.setAttribute(KV_TENSE_NO, lfn+1); + domElementDesc.appendChild(domTextDesc); + domElementTense.appendChild(domElementDesc); + } + } + + domElementParent.appendChild(domElementTense); + return true; +} + + +bool KEduVocKvtmlWriter::saveUsageNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent) +{ + if (m_doc->usage_descr.size() == 0) + return true; + + QDomElement domElementUsage = domDoc.createElement(KV_USAGE_GRP); + + for (int lfn = 0; lfn < (int) m_doc->usage_descr.size(); lfn++) + { + if (!(m_doc->usage_descr[lfn].isNull()) ) + { + QDomElement domElementDesc = domDoc.createElement(KV_USAGE_DESC); + QDomText domTextDesc = domDoc.createTextNode(m_doc->usage_descr[lfn]); + + domElementDesc.setAttribute(KV_USAGE_NO, lfn+1); + domElementDesc.appendChild(domTextDesc); + domElementUsage.appendChild(domElementDesc); + } + } + + domElementParent.appendChild(domElementUsage); + return true; +} + + +bool KEduVocKvtmlWriter::saveLessonKvtMl (QDomDocument &domDoc, QDomElement &domElementParent) +{ + if (m_doc->lesson_descr.size() == 0) + return true; + + QDomElement domElementLesson = domDoc.createElement(KV_LESS_GRP); + domElementLesson.setAttribute(KV_SIZEHINT, m_doc->getSizeHint(-1)); + + for (int lfn = 0; lfn < (int) m_doc->lesson_descr.size(); lfn++) + { + if (!(m_doc->lesson_descr[lfn].isNull()) ) + { + QDomElement domElementDesc = domDoc.createElement(KV_LESS_DESC); + QDomText domTextDesc = domDoc.createTextNode(m_doc->lesson_descr[lfn]); + + domElementDesc.setAttribute(KV_LESS_NO, lfn+1); + if (m_doc->getCurrentLesson() == lfn+1) + domElementDesc.setAttribute (KV_LESS_CURR, 1); + if (lfn < (int) m_doc->lessons_in_query.size() && m_doc->lessons_in_query[lfn]) + domElementDesc.setAttribute (KV_LESS_QUERY, 1); + + domElementDesc.appendChild(domTextDesc); + domElementLesson.appendChild(domElementDesc); + } + } + + domElementParent.appendChild(domElementLesson); + return true; +} + + +bool KEduVocKvtmlWriter::saveConjug(QDomDocument &domDoc, QDomElement &domElementParent, + const Conjugation &curr_conjug, QString type) +{ + if (!curr_conjug.pers1Singular(type).isEmpty() ) + { + QDomElement domElementP1s = domDoc.createElement(KV_CON_P1S); + QDomText domTextP1s = domDoc.createTextNode(curr_conjug.pers1Singular(type)); + + domElementP1s.appendChild(domTextP1s); + domElementParent.appendChild(domElementP1s); + } + + if (!curr_conjug.pers2Singular(type).isEmpty() ) + { + QDomElement domElementP2s = domDoc.createElement(KV_CON_P2S); + QDomText domTextP2s = domDoc.createTextNode(curr_conjug.pers2Singular(type)); + + domElementP2s.appendChild(domTextP2s); + domElementParent.appendChild(domElementP2s); + } + + if (!curr_conjug.pers3FemaleSingular(type).isEmpty() || + curr_conjug.pers3SingularCommon(type)) + { + QDomElement domElementP3sf = domDoc.createElement(KV_CON_P3SF); + QDomText domTextP3sf = domDoc.createTextNode(curr_conjug.pers3FemaleSingular(type)); + + if (curr_conjug.pers3SingularCommon(type)) + domElementP3sf.setAttribute(KV_CONJ_COMMON, 1); + + domElementP3sf.appendChild(domTextP3sf); + domElementParent.appendChild(domElementP3sf); + } + + if (!curr_conjug.pers3MaleSingular(type).isEmpty() ) + { + QDomElement domElementP3sm = domDoc.createElement(KV_CON_P3SM); + QDomText domTextP3sm = domDoc.createTextNode(curr_conjug.pers3MaleSingular(type)); + + domElementP3sm.appendChild(domTextP3sm); + domElementParent.appendChild(domElementP3sm); + } + + if (!curr_conjug.pers3NaturalSingular(type).isEmpty() ) + { + QDomElement domElementP3sn = domDoc.createElement(KV_CON_P3SN); + QDomText domTextP3sn = domDoc.createTextNode(curr_conjug.pers3NaturalSingular(type)); + + domElementP3sn.appendChild(domTextP3sn); + domElementParent.appendChild(domElementP3sn); + } + + if (!curr_conjug.pers1Plural(type).isEmpty() ) + { + QDomElement domElementP1p = domDoc.createElement(KV_CON_P1P); + QDomText domTextP1p = domDoc.createTextNode(curr_conjug.pers1Plural(type)); + + domElementP1p.appendChild(domTextP1p); + domElementParent.appendChild(domElementP1p); + } + + if (!curr_conjug.pers2Plural(type).isEmpty() ) + { + QDomElement domElementP2p = domDoc.createElement(KV_CON_P2P); + QDomText domTextP2p = domDoc.createTextNode(curr_conjug.pers2Plural(type)); + + domElementP2p.appendChild(domTextP2p); + domElementParent.appendChild(domElementP2p); + } + + if (!curr_conjug.pers3FemalePlural(type).isEmpty() || + curr_conjug.pers3PluralCommon(type)) + { + QDomElement domElementP3pf = domDoc.createElement(KV_CON_P3PF); + QDomText domTextP3pf = domDoc.createTextNode(curr_conjug.pers3FemalePlural(type)); + + if (curr_conjug.pers3PluralCommon(type)) + domElementP3pf.setAttribute(KV_CONJ_COMMON, 1); + + domElementP3pf.appendChild(domTextP3pf); + domElementParent.appendChild(domElementP3pf); + } + + if (!curr_conjug.pers3MalePlural(type).isEmpty() ) + { + QDomElement domElementP3pm = domDoc.createElement(KV_CON_P3PM); + QDomText domTextP3pm = domDoc.createTextNode(curr_conjug.pers3MalePlural(type)); + + domElementP3pm.appendChild(domTextP3pm); + domElementParent.appendChild(domElementP3pm); + } + + if (!curr_conjug.pers3NaturalPlural(type).isEmpty() ) + { + QDomElement domElementP3pn = domDoc.createElement(KV_CON_P3PN); + QDomText domTextP3pn = domDoc.createTextNode(curr_conjug.pers3NaturalPlural(type)); + + domElementP3pn.appendChild(domTextP3pn); + domElementParent.appendChild(domElementP3pn); + } + + return true; +} + +bool KEduVocKvtmlWriter::saveConjugHeader(QDomDocument &domDoc, QDomElement &domElementParent, + vector<Conjugation> &curr_conjug) +{ +/* + <conjugation> used in header for definiton of "prefix" + <e l="de"> lang determines also lang order in entries !! + <s1>I</s1> which must NOT differ + <s2>you<2> + <s3f common="0">he</s3f> + <s3m>she</s3m> + <s3n>it</s3n> + <p1>we</p1> + <p2>you</p2> + <p3f common="1">they</p3f> + <p3m>they</p3m> + <p3n>they</p3n> + </e> + </conjugation> + +*/ + if (curr_conjug.size() == 0) + return true; + + QDomElement domElementConjug = domDoc.createElement(KV_CONJUG_GRP); + QString s; + + for (int ent = 0; ent < QMIN((int) curr_conjug.size(), m_doc->numLangs()); ent++) + { + QDomElement domElementEntry = domDoc.createElement(KV_CON_ENTRY); + + if (ent == 0) + { + s = m_doc->getOriginalIdent().stripWhiteSpace(); //EPT le Ident doit �re superflu + if (s.isEmpty() ) + s = "original"; + } + else + { + s = m_doc->getIdent(ent).stripWhiteSpace(); + if (s.isEmpty() ) + { + s.setNum(ent); + s.insert(0, "translation "); + } + } + domElementEntry.setAttribute(KV_LANG, s); + + if (!saveConjug (domDoc, domElementEntry, curr_conjug[ent], CONJ_PREFIX)) + return false; + + domElementConjug.appendChild(domElementEntry); + } + + domElementParent.appendChild(domElementConjug); + return true; +} + + +bool KEduVocKvtmlWriter::saveComparison(QDomDocument &domDoc, QDomElement &domElementParent, + const Comparison &comp) +/* + <comparison> + <l1>good</l1> + <l2>better</l2> + <l3>best</l3> + </comparison> +*/ +{ + if (comp.isEmpty()) + return true; + + QDomElement domElementComparison = domDoc.createElement(KV_COMPARISON_GRP); + + if (!comp.l1().isEmpty() ) + { + QDomElement domElementL1 = domDoc.createElement(KV_COMP_L1); + QDomText domTextL1 = domDoc.createTextNode(comp.l1()); + + domElementL1.appendChild(domTextL1); + domElementComparison.appendChild(domElementL1); + } + + if (!comp.l2().isEmpty() ) + { + QDomElement domElementL2 = domDoc.createElement(KV_COMP_L2); + QDomText domTextL2 = domDoc.createTextNode(comp.l2()); + + domElementL2.appendChild(domTextL2); + domElementComparison.appendChild(domElementL2); + } + + if (!comp.l3().isEmpty() ) + { + QDomElement domElementL3 = domDoc.createElement(KV_COMP_L3); + QDomText domTextL3 = domDoc.createTextNode(comp.l3()); + + domElementL3.appendChild(domTextL3); + domElementComparison.appendChild(domElementL3); + } + + domElementParent.appendChild(domElementComparison); + return true; +} + + +bool KEduVocKvtmlWriter::saveMultipleChoice(QDomDocument &domDoc, QDomElement &domElementParent, + const MultipleChoice &mc) +/* + <multiplechoice> + <mc1>good</mc1> + <mc2>better</mc2> + <mc3>best</mc3> + <mc4>best 2</mc4> + <mc5>best 3</mc5> + </multiplechoice> +*/ +{ + if (mc.isEmpty()) + return true; + + QDomElement domElementMC = domDoc.createElement(KV_MULTIPLECHOICE_GRP); + + if (!mc.mc1().isEmpty() ) + { + QDomElement domElementMC1 = domDoc.createElement(KV_MC_1); + QDomText domTextMC1 = domDoc.createTextNode(mc.mc1()); + + domElementMC1.appendChild(domTextMC1); + domElementMC.appendChild(domElementMC1); + } + + if (!mc.mc2().isEmpty() ) + { + QDomElement domElementMC2 = domDoc.createElement(KV_MC_2); + QDomText domTextMC2 = domDoc.createTextNode(mc.mc2()); + + domElementMC2.appendChild(domTextMC2); + domElementMC.appendChild(domElementMC2); + } + + if (!mc.mc3().isEmpty() ) + { + QDomElement domElementMC3 = domDoc.createElement(KV_MC_3); + QDomText domTextMC3 = domDoc.createTextNode(mc.mc3()); + + domElementMC3.appendChild(domTextMC3); + domElementMC.appendChild(domElementMC3); + } + + if (!mc.mc4().isEmpty() ) + { + QDomElement domElementMC4 = domDoc.createElement(KV_MC_4); + QDomText domTextMC4 = domDoc.createTextNode(mc.mc4()); + + domElementMC4.appendChild(domTextMC4); + domElementMC.appendChild(domElementMC4); + } + + if (!mc.mc5().isEmpty() ) + { + QDomElement domElementMC5 = domDoc.createElement(KV_MC_5); + QDomText domTextMC5 = domDoc.createTextNode(mc.mc5()); + + domElementMC5.appendChild(domTextMC5); + domElementMC.appendChild(domElementMC5); + } + + domElementParent.appendChild(domElementMC); + return true; +} + + +bool KEduVocKvtmlWriter::saveConjugEntry( QDomDocument &domDoc, QDomElement &domElementParent, + Conjugation &curr_conjug) +/* + <conjugation> in entry for definition of tenses of (irreg.) verbs + <t n="sipa"> + <s1>go</s1> + <s2>go</s2> + <s3f>goes</s3f> + <s3m>goes</s3m> + <s3n>goes</s3n> + <p1>go</p1> + <p2>go</p2> + <p3f>go</p3f> + <p3m>go</p3m> + <p3n>go</p3n> + </t> + </conjugation> +*/ +{ + curr_conjug.cleanUp(); + if (curr_conjug.numEntries() == 0 ) + return true; + + QDomElement domElementConjug = domDoc.createElement(KV_CONJUG_GRP); + QString type; + + for (int lfn = 0; lfn < (int) curr_conjug.numEntries(); lfn++) + { + QDomElement domElementType = domDoc.createElement(KV_CON_TYPE); + + type = curr_conjug.getType(lfn); + domElementType.setAttribute(KV_CON_NAME, type); + + if (!saveConjug (domDoc, domElementType, curr_conjug, curr_conjug.getType(lfn)) ) + return false; + + domElementConjug.appendChild(domElementType); + } + + domElementParent.appendChild(domElementConjug); + return true; +} + + +bool KEduVocKvtmlWriter::saveArticleKvtMl(QDomDocument &domDoc, QDomElement &domElementParent) +/* + <article> + <e l="de"> lang determines also lang order in entries !! + <fi>eine</fi> which must NOT differ + <fd>die</fd> + <mi>ein</mi> + <md>der</md> + <ni>ein</ni> + <nd>das</nd> + </e> + </article> +*/ +{ + if (m_doc->articles.size() == 0) + return true; + + QDomElement domElementArticle = domDoc.createElement(KV_ARTICLE_GRP); + QString def, indef, s; + + for (int lfn = 0; lfn < QMIN((int) m_doc->articles.size(), m_doc->numLangs()); lfn++) + { + QDomElement domElementEntry = domDoc.createElement(KV_ART_ENTRY); + if (lfn == 0) + { + s = m_doc->getOriginalIdent().stripWhiteSpace(); + if (s.isEmpty() ) + s = "original"; + } + else + { + s = m_doc->getIdent(lfn).stripWhiteSpace(); + if (s.isEmpty() ) + { + s.setNum(lfn); + s.insert(0, "translation "); + } + } + domElementEntry.setAttribute(KV_LANG, s); + + m_doc->articles[lfn].female(def, indef); + if (!def.isEmpty() ) + { + QDomElement domElementFD = domDoc.createElement(KV_ART_FD); + QDomText domTextFD = domDoc.createTextNode(def); + + domElementFD.appendChild(domTextFD); + domElementEntry.appendChild(domElementFD); + } + if (!indef.isEmpty() ) + { + QDomElement domElementFI = domDoc.createElement(KV_ART_FI); + QDomText domTextFI = domDoc.createTextNode(indef); + + domElementFI.appendChild(domTextFI); + domElementEntry.appendChild(domElementFI); + } + + m_doc->articles[lfn].male(def, indef); + if (!def.isEmpty() ) + { + QDomElement domElementMD = domDoc.createElement(KV_ART_MD); + QDomText domTextMD = domDoc.createTextNode(def); + + domElementMD.appendChild(domTextMD); + domElementEntry.appendChild(domElementMD); + } + if (!indef.isEmpty() ) + { + QDomElement domElementMI = domDoc.createElement(KV_ART_MI); + QDomText domTextMI = domDoc.createTextNode(indef); + + domElementMI.appendChild(domTextMI); + domElementEntry.appendChild(domElementMI); + } + + m_doc->articles[lfn].natural(def, indef); + if (!def.isEmpty() ) + { + QDomElement domElementND = domDoc.createElement(KV_ART_ND); + QDomText domTextND = domDoc.createTextNode(def); + + domElementND.appendChild(domTextND); + domElementEntry.appendChild(domElementND); + } + if (!indef.isEmpty() ) + { + QDomElement domElementNI = domDoc.createElement(KV_ART_NI); + QDomText domTextNI = domDoc.createTextNode(indef); + + domElementNI.appendChild(domTextNI); + domElementEntry.appendChild(domElementNI); + } + + domElementArticle.appendChild(domElementEntry); + } + + domElementParent.appendChild(domElementArticle); + return true; +} + + +bool KEduVocKvtmlWriter::saveOptionsKvtMl(QDomDocument &domDoc, QDomElement &domElementParent) +{ + QDomElement domElementOption = domDoc.createElement(KV_OPTION_GRP); + QDomElement domElementSort = domDoc.createElement(KV_OPT_SORT); + + domElementSort.setAttribute(KV_BOOL_FLAG, (m_doc->sort_allowed?1:0)); + domElementOption.appendChild(domElementSort); + + domElementParent.appendChild(domElementOption); + return true; +} + + +bool KEduVocKvtmlWriter::writeDoc(KEduVocDocument *doc, const QString &generator) +{ + bool first_expr = true; + + m_doc = doc; + + QDomDocument domDoc( "KEduVocDocument" ); + QDomElement domElementKvtml = domDoc.createElement( "kvtml" ); + + QString head( "<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE kvtml SYSTEM \"kvoctrain.dtd\">" ); + domDoc.setContent( head ); + + QDomComment domComment = domDoc.createComment(QString( + "\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")); + + domDoc.appendChild(domComment); + + domElementKvtml.setAttribute(KV_ENCODING, (QString)"UTF-8"); + + domElementKvtml.setAttribute(KV_GENERATOR, generator); + domElementKvtml.setAttribute(KV_COLS, m_doc->numLangs() ); + domElementKvtml.setAttribute(KV_LINES, m_doc->numEntries() ); + + if (!m_doc->doctitle.isEmpty()) + domElementKvtml.setAttribute(KV_TITLE, m_doc->doctitle); + + if (!m_doc->author.isEmpty()) + domElementKvtml.setAttribute(KV_AUTHOR, m_doc->getAuthor() ); + + if (!m_doc->license.isEmpty()) + domElementKvtml.setAttribute(KV_LICENSE, m_doc->getLicense() ); + + if (!m_doc->doc_remark.isEmpty()) + domElementKvtml.setAttribute(KV_DOC_REM, m_doc->getDocRemark() ); + + if (!saveLessonKvtMl(domDoc, domElementKvtml)) + return false; + + if (!saveArticleKvtMl(domDoc, domElementKvtml)) + return false; + + if (!saveConjugHeader(domDoc, domElementKvtml, m_doc->conjugations)) + return false; + + if (!saveOptionsKvtMl(domDoc, domElementKvtml)) + return false; + + if (!saveTypeNameKvtMl(domDoc, domElementKvtml)) + return false; + + if (!saveTenseNameKvtMl(domDoc, domElementKvtml)) + return false; + + if (!saveUsageNameKvtMl(domDoc, domElementKvtml)) + return false; + + QString q_org, q_trans; + vector<KEduVocExpression>::const_iterator first = m_doc->vocabulary.begin (); + m_doc->getQueryLang(q_org, q_trans); + + int ent_no = 0; + int ent_percent = (int) m_doc->vocabulary.size () / 100; + float f_ent_percent = (int) m_doc->vocabulary.size () / 100.0; +//TODO emit progressChanged(this, 0); + + while (first != m_doc->vocabulary.end ()) + { + QDomElement domElementExpression = domDoc.createElement(KV_EXPR); + + ent_no++; + if (ent_percent != 0 && (ent_no % ent_percent) == 0 ) +//TODO 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) m_doc->lesson_descr.size() ) + { + // should not be + kdError() << "index of lesson member too high: " << lm << endl; + lm = 0; + } + ls.setNum (lm); + domElementExpression.setAttribute (KV_LESS_MEMBER, ls); + } + + if ((*first).isInQuery()) + { + // entry was selected for query + domElementExpression.setAttribute (KV_SELECTED, (QString) "1"); + } + + if (!(*first).isActive()) + { + // entry was inactive + domElementExpression.setAttribute (KV_INACTIVE, (QString) "1"); + } + + if ((*first).uniqueType() && !(*first).getType(0).isEmpty()) + { + domElementExpression.setAttribute (KV_EXPRTYPE, (*first).getType(0)); + } + + QDomElement domElementOriginal = domDoc.createElement(KV_ORG); + if (first_expr) + { + // save space, only tell language in first entry + QString s; + s.setNum (m_doc->getSizeHint (0)); + domElementOriginal.setAttribute(KV_SIZEHINT, s); + + s = m_doc->getOriginalIdent().stripWhiteSpace(); + if (s.isEmpty() ) + s = "original"; + domElementOriginal.setAttribute (KV_LANG, s); + if (s == q_org) + domElementOriginal.setAttribute(KV_QUERY, (QString) KV_O); + else if (s == q_trans) + domElementOriginal.setAttribute(KV_QUERY, (QString) KV_T); + + } + + if (!(*first).getRemark(0).isEmpty() ) + domElementOriginal.setAttribute(KV_REMARK, (*first).getRemark(0)); + + if (!(*first).getSynonym(0).isEmpty() ) + domElementOriginal.setAttribute(KV_SYNONYM, (*first).getSynonym(0)); + + if (!(*first).getExample(0).isEmpty() ) + domElementOriginal.setAttribute(KV_EXAMPLE, (*first).getExample(0)); + + if (!(*first).getUsageLabel(0).isEmpty() ) + domElementOriginal.setAttribute(KV_USAGE, (*first).getUsageLabel(0)); + + if (!(*first).getParaphrase(0).isEmpty() ) + domElementOriginal.setAttribute(KV_PARAPHRASE, (*first).getParaphrase(0)); + + if (!(*first).getAntonym(0).isEmpty() ) + domElementOriginal.setAttribute(KV_ANTONYM, (*first).getAntonym(0)); + + if (!(*first).getPronunce(0).isEmpty() ) + domElementOriginal.setAttribute(KV_PRONUNCE, (*first).getPronunce(0)); + + if (!(*first).uniqueType() && !(*first).getType(0).isEmpty()) + domElementOriginal.setAttribute(KV_EXPRTYPE, (*first).getType(0)); + + if (!saveMultipleChoice(domDoc, domElementOriginal, (*first).getMultipleChoice(0))) + 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(domDoc, domElementOriginal, conj)) + return false; + } + else if (entype == QM_ADJ + && !(*first).getComparison(0).isEmpty()) + { + Comparison comp = (*first).getComparison(0); + if (!saveComparison(domDoc, domElementOriginal, comp)) + return false; + } + + QDomText domTextOriginal = domDoc.createTextNode((*first).getOriginal()); + domElementOriginal.appendChild(domTextOriginal); + domElementExpression.appendChild(domElementOriginal); + + int trans = 1; + while (trans < (int)m_doc->langs.size()) + { + QDomElement domElementTranslation = domDoc.createElement(KV_TRANS); + if (first_expr) + { + // save space, only tell language in first entry + QString s; + s.setNum (m_doc->getSizeHint (trans)); + domElementTranslation.setAttribute(KV_SIZEHINT, s); + + s = m_doc->getIdent(trans).stripWhiteSpace(); + if (s.isEmpty() ) + { + s.setNum (trans); + s.insert (0, "translation "); + } + domElementTranslation.setAttribute(KV_LANG, s); + if (s == q_org) + domElementTranslation.setAttribute(KV_QUERY, (QString) KV_O); + else if (s == q_trans) + domElementTranslation.setAttribute(KV_QUERY, (QString) KV_T); + } + + QString s1, s2; + + if ((*first).getGrade(trans, false) != 0 + ||(*first).getGrade(trans, true) != 0) + { + domElementTranslation.setAttribute(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)); + domElementTranslation.setAttribute(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)); + domElementTranslation.setAttribute(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)); + domElementTranslation.setAttribute(KV_DATE, s1 +';' +s2); + } + + if (!(*first).getRemark(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_REMARK, (*first).getRemark(trans)); + + if (!(*first).getFauxAmi(trans, false).isEmpty() ) + domElementTranslation.setAttribute(KV_FAUX_AMI_F, (*first).getFauxAmi(trans, false)); + + if (!(*first).getFauxAmi(trans, true).isEmpty() ) + domElementTranslation.setAttribute(KV_FAUX_AMI_T, (*first).getFauxAmi(trans, true)); + + if (!(*first).getSynonym(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_SYNONYM, (*first).getSynonym(trans)); + + if (!(*first).getExample(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_EXAMPLE, (*first).getExample(trans)); + + if (!(*first).getUsageLabel(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_USAGE, (*first).getUsageLabel(trans)); + + if (!(*first).getParaphrase(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_PARAPHRASE, (*first).getParaphrase(trans)); + + if (!(*first).getAntonym(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_ANTONYM, (*first).getAntonym(trans)); + + if (!(*first).getPronunce(trans).isEmpty() ) + domElementTranslation.setAttribute(KV_PRONUNCE, (*first).getPronunce(trans)); + + if (!(*first).uniqueType() && !(*first).getType(trans).isEmpty()) + domElementTranslation.setAttribute(KV_EXPRTYPE, (*first).getType(trans)); + + // only save conjugations when type == verb + + if (!saveMultipleChoice(domDoc, domElementTranslation, (*first).getMultipleChoice(trans))) + 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(domDoc, domElementTranslation, conj)) + return false; + } + + if (entype == QM_ADJ + && !(*first).getComparison(trans).isEmpty()) + { + Comparison comp = (*first).getComparison(trans); + if (!saveComparison(domDoc, domElementTranslation, comp)) + return false; + } + + QDomText domTextTranslation = domDoc.createTextNode((*first).getTranslation(trans)); + domElementTranslation.appendChild(domTextTranslation); + domElementExpression.appendChild(domElementTranslation); + + trans++; + } + + domElementKvtml.appendChild(domElementExpression); + + first++; + first_expr = false; + } + + domDoc.appendChild(domElementKvtml); + + QTextStream ts( m_outputFile ); + ts.setEncoding( QTextStream::UnicodeUTF8 ); + ts << domDoc.toString(); + +// TODO setModified (false); + return true; + +} + diff --git a/kanagram/src/keduvockvtmlwriter.h b/kanagram/src/keduvockvtmlwriter.h new file mode 100644 index 00000000..dd9e6a78 --- /dev/null +++ b/kanagram/src/keduvockvtmlwriter.h @@ -0,0 +1,99 @@ +/*************************************************************************** + export a KEduVocDocument to a KVTML file + ----------------------------------------------------------------------- + copyright : (C) 1999-2001 Ewald Arnold + (C) 2001 The KDE-EDU team + (C) 2005 Eric Pignet + email : eric at erixpage.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KEDUVOCKVTMLWRITER_H +#define KEDUVOCKVTMLWRITER_H + +#include <qfile.h> +#include <qdom.h> + +//#include "keduvocdocument.h" +#include "grammarmanager.h" +#include "multiplechoice.h" + +class KEduVocDocument; + +// 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 + +/** +@author Eric Pignet +*/ +class KEduVocKvtmlWriter +{ +public: + KEduVocKvtmlWriter(QFile *file); + ~KEduVocKvtmlWriter(); + + bool writeDoc(KEduVocDocument *doc, const QString &generator); + + bool saveLessonKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveTypeNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveTenseNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveUsageNameKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveOptionsKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveArticleKvtMl (QDomDocument &domDoc, QDomElement &domElementParent); + bool saveConjugHeader (QDomDocument &domDoc, QDomElement &domElementParent, + vector<Conjugation> &curr_conjug); + bool saveConjug (QDomDocument &domDoc, QDomElement &domElementParent, + const Conjugation &curr_conjug, QString type); + bool saveConjugEntry (QDomDocument &domDoc, QDomElement &domElementParent, + Conjugation &curr_conjug); + + bool saveComparison (QDomDocument &domDoc, QDomElement &domElementParent, + const Comparison &comp); + + bool saveMultipleChoice(QDomDocument &domDoc, QDomElement &domElementParent, + const MultipleChoice &mc); + +private: + QFile *m_outputFile; + KEduVocDocument *m_doc; +}; + +#endif diff --git a/kanagram/src/leitnerbox.cpp b/kanagram/src/leitnerbox.cpp new file mode 100644 index 00000000..5a86d1fb --- /dev/null +++ b/kanagram/src/leitnerbox.cpp @@ -0,0 +1,70 @@ +// +// C++ Implementation: leitnerbox +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "leitnerbox.h" + +LeitnerBox::LeitnerBox() +{ +} + + +LeitnerBox::~LeitnerBox() +{ +} + +int LeitnerBox::getVocabCount() +{ + return m_vocabCount; +} + +void LeitnerBox::setVocabCount( int count ) +{ + m_vocabCount = count; +} + +const QString& LeitnerBox::getBoxName() const +{ + return m_name; +} + +LeitnerBox* LeitnerBox::getCorrectWordBox() +{ + return m_correctWordBox; +} + +LeitnerBox* LeitnerBox::getWrongWordBox() +{ + return m_wrongWordBox; +} + +void LeitnerBox::setBoxName( const QString& name ) +{ + m_name = name; +} + +void LeitnerBox::setCorrectWordBox( LeitnerBox* correctWordBox ) +{ + m_correctWordBox = correctWordBox; +} + +void LeitnerBox::setWrongWordBox( LeitnerBox* wrongWordBox ) +{ + m_wrongWordBox = wrongWordBox; +} + +bool LeitnerBox::operator ==( const LeitnerBox& a ) const +{ + if( a.getBoxName() == getBoxName() ) + return true; + else + return false; +} + diff --git a/kanagram/src/leitnerbox.h b/kanagram/src/leitnerbox.h new file mode 100644 index 00000000..bf20d6a6 --- /dev/null +++ b/kanagram/src/leitnerbox.h @@ -0,0 +1,49 @@ +// +// C++ Interface: leitnerbox +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef LEITNERBOX_H +#define LEITNERBOX_H + +#include <qstring.h> + +/** +@author Martin Pfeiffer +*/ +class LeitnerBox +{ +public: + LeitnerBox(); + + ~LeitnerBox(); + + void setCorrectWordBox( LeitnerBox* ); //sets the correct word box + void setWrongWordBox( LeitnerBox* ); //sets the wrong word box + void setBoxName( const QString& ); //sets the boxes name + + void setVocabCount( int count ); + int getVocabCount(); + + LeitnerBox* getCorrectWordBox(); + LeitnerBox* getWrongWordBox(); + const QString& getBoxName() const; + + bool operator == ( const LeitnerBox& a ) const; + +private: + QString m_name; + + int m_vocabCount; + + LeitnerBox* m_wrongWordBox; + LeitnerBox* m_correctWordBox; +}; + +#endif diff --git a/kanagram/src/leitnersystem.cpp b/kanagram/src/leitnersystem.cpp new file mode 100644 index 00000000..3f633526 --- /dev/null +++ b/kanagram/src/leitnersystem.cpp @@ -0,0 +1,192 @@ +// +// C++ Implementation: leitnersystem +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "leitnersystem.h" +#include <kdebug.h> + +LeitnerSystem::LeitnerSystem(QValueList<LeitnerBox>& boxes, QString name) +{ + if( !boxes.empty() ) + m_boxes = boxes; + + if( name.isNull() ) + m_systemName = name; +} + +LeitnerSystem::LeitnerSystem() +{ +} + +LeitnerSystem::~LeitnerSystem() +{ +} + +QStringList LeitnerSystem::getBoxNameList() +{ + QStringList boxNameList; + QValueList<LeitnerBox>::iterator it; + + + for(it = m_boxes.begin(); it != m_boxes.end(); ++it) + { + boxNameList.append((*it).getBoxName()); + } + + return boxNameList; +} + +int LeitnerSystem::getNumberOfBoxes() +{ + return m_boxes.count(); +} + +LeitnerBox* LeitnerSystem::getBoxWithNumber( int number ) +{ + return &m_boxes[ number ]; +} + +LeitnerBox* LeitnerSystem::getBoxWithName( const QString& name ) +{ + QValueList<LeitnerBox>::iterator it; + + for(it = m_boxes.begin(); it != m_boxes.end(); ++it) + { + if((*it).getBoxName() == name) + return &(*it); + } + + return 0; +} + +QString& LeitnerSystem::getSystemName() +{ + return m_systemName; +} + +const QString& LeitnerSystem::getNextBox( QString& previousBox ) +{ + for( int i = 0; i < m_boxes.count(); i++ ) + { + if( m_boxes[i].getVocabCount() > 0 ) + return getBox( i ); + } + + return QString::null; +} + +const QString& LeitnerSystem::getCorrectBox( int box ) +{ + return m_boxes[ box ].getCorrectWordBox()->getBoxName(); +} + +const QString& LeitnerSystem::getWrongBox( int box ) +{ + return m_boxes[ box ].getWrongWordBox()->getBoxName(); +} + +int LeitnerSystem::getWrongBoxNumber( int box ) +{ + return getNumber( m_boxes[ box ].getWrongWordBox() ); +} + +int LeitnerSystem::getCorrectBoxNumber( int box ) +{ + return getNumber( m_boxes[ box ].getCorrectWordBox() ); +} + +void LeitnerSystem::deleteBox( int box ) +{ + m_boxes.remove( m_boxes.at( box ) ); +} + +void LeitnerSystem::deleteBox( LeitnerBox* box ) +{ + m_boxes.remove( *box ); +} + +bool LeitnerSystem::insertBox( const QString& name, int correctWordBox, int wrongWordBox ) +{ + if( getBoxNameList().contains( name ) != 0 ) + return false; + + LeitnerBox tmpBox; + tmpBox.setBoxName( name ); + tmpBox.setCorrectWordBox( getBoxWithNumber( correctWordBox ) ); + tmpBox.setWrongWordBox( getBoxWithNumber( wrongWordBox ) ); + + m_boxes.append( tmpBox ); + return true; +} + +void LeitnerSystem::setSystemName( const QString& name ) +{ + m_systemName = name; +} + +int LeitnerSystem::getNumber( LeitnerBox* box ) +{ + if( m_boxes.findIndex( *box ) == -1 ) + kdDebug() << "muhaha" << endl; + return m_boxes.findIndex( *box ); +} + +bool LeitnerSystem::setBoxName( int box, const QString& name ) +{ + if( getBoxWithName( name ) == 0 || getBoxWithName( name ) == getBoxWithNumber( box ) ) + { + getBoxWithNumber( box )->setBoxName( name ); + + return true; + } + else + return false; +} + +bool LeitnerSystem::setBoxName( LeitnerBox* box, const QString& name ) +{ + if( getBoxWithName( name ) == 0 || getBoxWithName( name ) == box ) + { + box->setBoxName( name ); + + return true; + } + else + return false; +} + +bool LeitnerSystem::insertBox( const QString& name ) +{ + if( getBoxNameList().contains( name ) != 0 ) + return false; + + LeitnerBox tmpBox; + tmpBox.setBoxName( name ); + //tmpBox.setVocabCount( count ); + + m_boxes.append( tmpBox ); + return true; +} + +void LeitnerSystem::setCorrectBox( const QString& box, const QString& correctWordBox ) +{ + getBoxWithName( box )->setCorrectWordBox( getBoxWithName( correctWordBox ) ); +} + +void LeitnerSystem::setWrongBox( const QString& box, const QString& wrongWordBox ) +{ + getBoxWithName( box )->setWrongWordBox( getBoxWithName( wrongWordBox ) ); +} + +const QString& LeitnerSystem::getBox( int i ) +{ + return getBoxWithNumber( i )->getBoxName(); +} + diff --git a/kanagram/src/leitnersystem.h b/kanagram/src/leitnersystem.h new file mode 100644 index 00000000..87e583d9 --- /dev/null +++ b/kanagram/src/leitnersystem.h @@ -0,0 +1,67 @@ +// +// C++ Interface: leitnersystem +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include "leitnerbox.h" + +#ifndef LEITNERSYSTEM_H +#define LEITNERSYSTEM_H + + +/** +@author Martin Pfeiffer +*/ +class LeitnerSystem +{ +public: + LeitnerSystem(); + LeitnerSystem( QValueList<LeitnerBox>& boxes, QString name ); + + ~LeitnerSystem(); + + int getNumberOfBoxes(); //returns the number of boxes in the system + QStringList getBoxNameList(); //returns a list with the boxes names + + QString& getSystemName(); //returns the systems name + void setSystemName( const QString& name ); //sets the systems name + + LeitnerBox* getBoxWithNumber( int number ); //returns box by number + LeitnerBox* getBoxWithName( const QString& name );//returns box by name + int getNumber( LeitnerBox* box ); + const QString& getBox( int i ); + + const QString& getNextBox( QString& previousBox ); //returns the next box for the next question + + const QString& getCorrectBox( int box ); //returns the correct word box of "int box" + const QString& getWrongBox( int box ); //returns the wrong word box of "int box" + int getWrongBoxNumber( int box ); + int getCorrectBoxNumber( int box ); + void setCorrectBox( const QString& box, const QString& correctWordBox ); + void setWrongBox( const QString& box, const QString& wrongWordBox ); + bool setBoxName( int box, const QString& name ); + bool setBoxName( LeitnerBox* box, const QString& name ); + + //inserts a box with number, name, correct and wrong word box + bool insertBox( const QString& name, int correctWordBox, int wrongWordBox ); + bool insertBox( const QString& name ); + void deleteBox( int box ); + void deleteBox( LeitnerBox* box ); + +private: + QString m_systemName; //the systems name + + QValueList<LeitnerBox> m_boxes; +}; + +#endif diff --git a/kanagram/src/leitnersystemview.cpp b/kanagram/src/leitnersystemview.cpp new file mode 100644 index 00000000..f8736471 --- /dev/null +++ b/kanagram/src/leitnersystemview.cpp @@ -0,0 +1,216 @@ +// +// C++ Implementation: leitnersystemview +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "leitnersystemview.h" + +#include "leitnersystem.h" +//#include "kwordquiz.h" + +#include <stdlib.h> +#include <kiconloader.h> +#include <qpainter.h> + +#include <kdebug.h> + +LeitnerSystemView::LeitnerSystemView(QWidget * parent, const char* name, WFlags f) + : QScrollView(parent, name, f) +{ + m_highlightedBox = -1; +} + + +LeitnerSystemView::~LeitnerSystemView() +{ +} + +void LeitnerSystemView::drawSystem(QPainter* p) +{ + kdDebug() << "drawSystem( )" << endl; + + + //einarbeiten von m_selectedBox... aus prefLeitner + + m_imageY = height() / 2 - 32; + + //draw the boxes' icons + for(int i = 0; i < m_leitnerSystem->getNumberOfBoxes(); i++) + { + if(i == m_highlightedBox) + { + //p->drawPixmap(12 + i * 64 + i*10, m_imageY, KGlobal::iconLoader()->loadIcon("leitnerbox", KIcon::Panel)); + p->drawRect(12 + i * 64 + i*10, m_imageY,64,64); + p->fillRect(12 + i * 64 + i*10, m_imageY,64,64, QBrush(red)); + } + else + { //for each box 74 = 64(pixmap) + 10(distance between two boxes) + //p->drawPixmap(12 + i * 74, m_imageY, KGlobal::iconLoader()->loadIcon("leitnerbox", KIcon::Panel)); + p->drawRect(12 + i * 64 + i*10, m_imageY,64,64); + } + } +} + +void LeitnerSystemView::drawConnections(QPainter* p) +{ + //dist = number of boxes that are in between the two boxes + //width = width of the rect for the arc + int dist, width = 0; + int numberOfBoxes = m_leitnerSystem->getNumberOfBoxes(); + + p->setPen( QPen(green, 2) ); + + //paint the connections for the correct word boxes, above the boxes + for(int i = 0; i < numberOfBoxes; i++) + { + dist = m_leitnerSystem->getCorrectBoxNumber( i ) - i; + + if(dist <= 0) + { + // (dist*(-1) -1)*64 == for each box in between take 64 + // dist*(-1)*10 == the gaps in between + // 2*22; 2*21 == the distances of the endings on the picture + width = (dist*(-1) -1)*64 + dist*(-1)*10 + 2*22 + 2*21; + + p->drawArc( 12 + (dist+i)*74 + 21, m_imageY-(width/3), width, /*(height()/2 - 12-32) *2*/ width/3*2, 0, 180*16); + } + else + { + width = (dist-1)*64 + dist*10 + 2*21; + p->drawArc(12 + i*74 + 21+22 ,m_imageY-(width/3) , width, /*(height()/2 - 12-32) *2*/width/3*2, 0, 180*16); + } + + } + + //paint the connections for the wrong word boxes, below the boxes + p->setPen(QPen(red, 2)); + + for(int i = 0; i < numberOfBoxes; i++) + { + dist = m_leitnerSystem->getWrongBoxNumber( i ) - i; + + if(dist <= 0) + { + width = (dist*(-1) -1)*64 + dist*(-1)*10 + 2*22 + 2*21; + p->drawArc(12+ (dist+i)*74 + 21 ,m_imageY+64-width/3 , width, width/3*2 , 180*16, 180*16); + } + else + { + width = (dist-1)*64 + dist*10 + 2*21; + p->drawArc(12 + i*74 + 21+22 ,m_imageY+64-width/3 , width, width/3*2, 180*16, 180*16); + } + } + +} + +void LeitnerSystemView::setSystem(LeitnerSystem* leitnersystem) +{ + m_leitnerSystem = leitnersystem; + + //calculate the new sizes + calculateSize(); + updateContents(); + //repaint + //update(); + //QPainter* p = new QPainter(this); + //drawContents( p, 0, 0, 0, 0 ); +} + +void LeitnerSystemView::highlightBox(int box) +{ + m_highlightedBox = box; + updateContents(); +} + +void LeitnerSystemView::drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph) +{ + kdDebug() << "drawContents" << endl; + p->eraseRect(0,0,width(),height()); + + drawSystem( p ); + + drawConnections( p ); +} + +void LeitnerSystemView::calculateSize() +{ + //margin = 12 + //distance between boxes = 10 + //boxes = 64*64 + + int numberOfBoxes = m_leitnerSystem->getNumberOfBoxes(); + QString x; + int height, dist, tmpMaxC, tmpMaxW; + tmpMaxC = 0; + tmpMaxW = 0; + height = 0; + + for(int i = 0; i < numberOfBoxes; i++) + { + dist = m_leitnerSystem->getCorrectBoxNumber( i ) - i; + + if( abs(dist) >= abs(tmpMaxC) ) + tmpMaxC = dist; + + dist = m_leitnerSystem->getWrongBoxNumber( i ) - i; + + if( abs(dist) >= abs(tmpMaxW) ) + tmpMaxW = dist; + } + + if( tmpMaxC <= 0 ) + height += (( abs(tmpMaxC) -1)*64 + abs(tmpMaxC)*10 + 2*22 + 2*21)/3; + else + height += (( tmpMaxC-1)*64 + tmpMaxC*10 + 2*21)/3; + + if( tmpMaxW <= 0 ) + height += (( abs(tmpMaxW) -1)*64 + abs(tmpMaxW)*10 + 2*22 + 2*21)/3; + else + height += (( tmpMaxW-1)*64 + tmpMaxW*10 + 2*21)/3; + + height += 24+64; + + resizeContents( numberOfBoxes * 64 + (numberOfBoxes - 1)*10 + 2 * 12, height ); + setMinimumSize( numberOfBoxes * 64 + (numberOfBoxes - 1)*10 + 2 * 12, height ); +} + +void LeitnerSystemView::mousePressEvent(QMouseEvent* e) +{ + kdDebug() << "mouseClick" << endl; + //if the user has clicked into a box + if(e->y() > m_imageY && e->y() < m_imageY + 64 && e->x() < width()-13) + { + int d = (e->x()-12)/74; + + if((e->x()-12-74*d) <= 64) + { + //signal for prefLeitner to set the comboboxes to the clicked box + emit boxClicked( d ); + m_highlightedBox = d; + + updateContents(); + } + else + { + emit boxClicked( -1 ); + m_highlightedBox = -1; + + updateContents(); + } + } + else + { + emit boxClicked( -1 ); + m_highlightedBox = -1; + + updateContents(); + } +} + + diff --git a/kanagram/src/leitnersystemview.h b/kanagram/src/leitnersystemview.h new file mode 100644 index 00000000..be52bc0b --- /dev/null +++ b/kanagram/src/leitnersystemview.h @@ -0,0 +1,57 @@ +// +// C++ Interface: leitnersystemview +// +// Description: +// +// +// Author: Martin Pfeiffer <martin-pfeiffer-bensheim@web.de>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef LEITNERSYSTEMVIEW_H +#define LEITNERSYSTEMVIEW_H + +#include <qscrollview.h> +#include <qpixmap.h> + +class LeitnerSystem; + + +/** +@author Martin Pfeiffer +*/ + +class LeitnerSystemView : public QScrollView +{ + Q_OBJECT + +public: + LeitnerSystemView(QWidget* parent = 0, const char* name = 0, WFlags f = 0); + + ~LeitnerSystemView(); + + void setSystem(LeitnerSystem* system); //set a new system to view on + void highlightBox(int box); //highlight a box + +signals: + void boxClicked(int box); //is emited if the user clicks on a box + +protected: + virtual void drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph); + virtual void mousePressEvent(QMouseEvent* e); + +private: + LeitnerSystem* m_leitnerSystem; //the system which is shown + + void drawSystem(QPainter*); //paints the boxes + void drawConnections(QPainter*); //paints the arrows between the boxes + void calculateSize(); + + //QRect m_viewArea; + int m_imageY; //high border of the images + int m_distPixmap; + int m_highlightedBox; //the box which is currently highlighted +}; + +#endif diff --git a/kanagram/src/main.cpp b/kanagram/src/main.cpp new file mode 100644 index 00000000..ec0265b4 --- /dev/null +++ b/kanagram/src/main.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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 <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kprocess.h> +#include <kstandarddirs.h> + +#include "kanagram.h" +#include "kanagramsettings.h" + +int main(int argc, char *argv[]) +{ + KAboutData about("kanagram", I18N_NOOP("Kanagram"), "0.1", I18N_NOOP("An anagram game"), KAboutData::License_GPL, "© 2005 Joshua Keel\n© 2005 Danny Allen"); + about.addAuthor("Joshua Keel", I18N_NOOP("Coding"), "joshuakeel@gmail.com"); + about.addAuthor("Danny Allen", I18N_NOOP("Design, Graphics and many Vocabularies"), "danny@dannyallen.co.uk"); + about.addCredit("Artemiy Pavlov", I18N_NOOP("Sound effects"), 0, "http://artemiolabs.com"); + KCmdLineArgs::init(argc, argv, &about); + KApplication app; + app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); + + KanagramSettings::setJustGotFont(false); + QFont f("squeaky chalk sound"); + if (!QFontInfo(f).exactMatch()) + { + KanagramSettings::setUseStandardFonts(true); + } + if (KanagramSettings::dataLanguage().isEmpty()) + { + QStringList userLanguagesCode = KGlobal::locale()->languageList(); + QStringList::const_iterator itEnd = userLanguagesCode.end(); + QStringList::const_iterator it = userLanguagesCode.begin(); + for ( ; it != itEnd; ++it) + { + QStringList mdirs = KGlobal::dirs()->findDirs("appdata", "data/" + *it); + if (!mdirs.isEmpty()) break; + } + if (it == itEnd) KanagramSettings::setDataLanguage("en"); + else KanagramSettings::setDataLanguage(*it); + } + + app.setTopWidget(new Kanagram()); + return app.exec(); +} + diff --git a/kanagram/src/mainsettings.cpp b/kanagram/src/mainsettings.cpp new file mode 100644 index 00000000..660a1c5c --- /dev/null +++ b/kanagram/src/mainsettings.cpp @@ -0,0 +1,161 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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 <qdir.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qpushbutton.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kconfigdialog.h> +#include <kmessagebox.h> +#include <kio/netaccess.h> + +#include "mainsettings.h" +#include "kanagramsettings.h" + +MainSettings::MainSettings(QWidget *parent) : MainSettingsWidget(parent) +{ + m_parent = (KConfigDialog*)parent; + + connect(parent, SIGNAL(applyClicked()), this, SLOT(slotChangeTranslation())); + connect(cboxTranslation, SIGNAL(activated(int)), this, SLOT(slotUpdateParent())); + + setupTranslations(); + + QStringList languageNames = m_languageCodeMap.keys(); + languageNames.sort(); + cboxTranslation->insertStringList(languageNames); + + //the language code/name + KConfig entry(locate("locale", "all_languages")); + QString code = KanagramSettings::dataLanguage(); + entry.setGroup(code); + if (code == "sr") + cboxTranslation->setCurrentText(entry.readEntry("Name")+" ("+i18n("Cyrillic")+")"); + else if (code == "sr@Latn") + { + entry.setGroup("sr"); + cboxTranslation->setCurrentText(entry.readEntry("Name")+" ("+i18n("Latin")+")"); + } + else + cboxTranslation->setCurrentText(entry.readEntry("Name")); + + QFont f("squeaky chalk sound"); + if (KanagramSettings::justGotFont()) + { + getFontsButton->hide(); + kcfg_useStandardFonts->setEnabled(false); + } + else + { + if (!QFontInfo(f).exactMatch()) + { + kcfg_useStandardFonts->setEnabled(false); + connect(getFontsButton, SIGNAL(pressed()), this, SLOT(getAndInstallFont())); + } + else + { + getFontsButton->hide(); + } + } +} + +MainSettings::~MainSettings() +{ +} + +void MainSettings::slotUpdateParent() +{ + m_parent->enableButtonApply(true); +} + +void MainSettings::setupTranslations() +{ + m_languageCodeMap.clear(); + QStringList languages, temp_languages; + + //the program scans in kdereview/data/ to see what languages data is found + QStringList mdirs = KGlobal::dirs()->findDirs("appdata", "data/"); + + if (mdirs.isEmpty()) return; + + for (QStringList::const_iterator it = mdirs.begin(); it != mdirs.end(); ++it ) + { + QDir dir(*it); + temp_languages = dir.entryList(QDir::Dirs, QDir::Name); + temp_languages.remove("."); + temp_languages.remove(".."); + for (QStringList::const_iterator it2 = temp_languages.begin(); it2 != temp_languages.end(); ++it2 ) + { + if (!languages.contains(*it2)) languages.append(*it2); + } + } + + if (languages.isEmpty()) + return; + + //the language code/name + KConfig entry(locate("locale", "all_languages")); + const QStringList::ConstIterator itEnd = languages.end(); + for (QStringList::ConstIterator it = languages.begin(); it != itEnd; ++it) { + entry.setGroup(*it); + if (*it == "sr") + m_languageCodeMap.insert(entry.readEntry("Name")+" ("+i18n("Cyrillic")+")", "sr"); + else if (*it == "sr@Latn") + { + entry.setGroup("sr"); + m_languageCodeMap.insert(entry.readEntry("Name") + " ("+i18n("Latin")+")", "sr@Latn"); + } + else + m_languageCodeMap.insert(entry.readEntry("Name"), *it); + } +} + +void MainSettings::getAndInstallFont() +{ + bool success = KIO::NetAccess::copy("http://www.kde-edu.org/kanagram/chalk.ttf", "fonts:/Personal/", 0); + if (success) + { + getFontsButton->hide(); + KMessageBox::information(this, i18n("Please restart Kanagram to activate the new font.")); + kcfg_useStandardFonts->setChecked(false); + KanagramSettings::setUseStandardFonts(false); + KanagramSettings::setJustGotFont(true); + KanagramSettings::writeConfig(); + } + else + { + KMessageBox::error(this, i18n("The font could not be installed. Please check that you are properly connected to the Internet.")); + } +} + +void MainSettings::slotChangeTranslation() +{ + kdDebug() << "Writing new default language: " << m_languageCodeMap[cboxTranslation->currentText()] << endl; + KanagramSettings::setDataLanguage(m_languageCodeMap[cboxTranslation->currentText()]); + KanagramSettings::writeConfig(); +} + +#include "mainsettings.moc" diff --git a/kanagram/src/mainsettings.h b/kanagram/src/mainsettings.h new file mode 100644 index 00000000..3763a047 --- /dev/null +++ b/kanagram/src/mainsettings.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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. * + ***************************************************************************/ + + +#ifndef MAINSETTINGS_H +#define MAINSETTINGS_H + +#include "mainsettingswidget.h" + +class KConfigDialog; + +class MainSettings : public MainSettingsWidget +{ +Q_OBJECT + public: + MainSettings(QWidget *parent); + ~MainSettings(); + + public slots: + void slotChangeTranslation(); + void slotUpdateParent(); + + private slots: + void getAndInstallFont(); + + private: + QMap<QString, QString> m_languageCodeMap; + void setupTranslations(); + + KConfigDialog *m_parent; +}; + +#endif + diff --git a/kanagram/src/mainsettingswidget.ui b/kanagram/src/mainsettingswidget.ui new file mode 100644 index 00000000..ef9d017e --- /dev/null +++ b/kanagram/src/mainsettingswidget.ui @@ -0,0 +1,182 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MainSettingsWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>MainSettingsWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>281</width> + <height>239</height> + </rect> + </property> + <property name="caption"> + <string>General</string> + </property> + <property name="whatsThis" stdset="0"> + <string>This setting allows you to set the length of time that Kanagram's hint bubble is shown.</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Hints</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Auto-hide hints after:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Do Not Auto-Hide Hints</string> + </property> + </item> + <item> + <property name="text"> + <string>3 Seconds</string> + </property> + </item> + <item> + <property name="text"> + <string>5 Seconds</string> + </property> + </item> + <item> + <property name="text"> + <string>7 Seconds</string> + </property> + </item> + <item> + <property name="text"> + <string>9 Seconds</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_hintHideTime</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Vocabulary Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Play using:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cboxTranslation</cstring> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cboxTranslation</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_useStandardFonts</cstring> + </property> + <property name="text"> + <string>Use standard fonts</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Uses a standard font for the chalkboard/interface.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>getFontsButton</cstring> + </property> + <property name="text"> + <string>Get Chalk Font</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_useSounds</cstring> + </property> + <property name="text"> + <string>Use sou&nds</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Turns sounds on/off.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<tabstops> + <tabstop>kcfg_hintHideTime</tabstop> + <tabstop>kcfg_useSounds</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kanagram/src/multiplechoice.cpp b/kanagram/src/multiplechoice.cpp new file mode 100644 index 00000000..b27350c3 --- /dev/null +++ b/kanagram/src/multiplechoice.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + + manage multiple choice suggestions for queries + + ----------------------------------------------------------------------- + + begin : Mon Oct 29 18:09:29 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 "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/kanagram/src/multiplechoice.h b/kanagram/src/multiplechoice.h new file mode 100644 index 00000000..6a0b0500 --- /dev/null +++ b/kanagram/src/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 <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 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/kanagram/src/newstuff.cpp b/kanagram/src/newstuff.cpp new file mode 100644 index 00000000..19c28272 --- /dev/null +++ b/kanagram/src/newstuff.cpp @@ -0,0 +1,29 @@ +#include "newstuff.h" + +#include <qwidget.h> +#include <qpushbutton.h> + +#include <kdebug.h> +#include <knewstuff/downloaddialog.h> +#include <knewstuff/knewstuff.h> +#include <klocale.h> + +#include "kanagramsettings.h" +#include "newstuffdialog.h" + +NewStuff::NewStuff(QWidget *parent) : NewStuffWidget(parent) +{ + connect(btnGetNew, SIGNAL(clicked()), this, SLOT(slotGetNewVocabs())); +} + +NewStuff::~NewStuff() +{ +} + +void NewStuff::slotGetNewVocabs() +{ + NewStuffDialog *nsd = new NewStuffDialog(); + nsd->download(); +} + +#include "newstuff.moc" diff --git a/kanagram/src/newstuff.h b/kanagram/src/newstuff.h new file mode 100644 index 00000000..2429cca7 --- /dev/null +++ b/kanagram/src/newstuff.h @@ -0,0 +1,18 @@ +#ifndef NEWSTUFF_H +#define NEWSTUFF_H + +#include "newstuffwidget.h" + +class NewStuff : public NewStuffWidget +{ +Q_OBJECT + public: + NewStuff(QWidget *parent); + ~NewStuff(); + + private slots: + void slotGetNewVocabs(); +}; + +#endif + diff --git a/kanagram/src/newstuffdialog.cpp b/kanagram/src/newstuffdialog.cpp new file mode 100644 index 00000000..d58ad56d --- /dev/null +++ b/kanagram/src/newstuffdialog.cpp @@ -0,0 +1,35 @@ +#include "newstuffdialog.h" + +#include <knewstuff/knewstuff.h> +#include <knewstuff/entry.h> +#include <klocale.h> +#include <kio/netaccess.h> +#include <kurl.h> +#include <kstandarddirs.h> + +#include "kanagramsettings.h" + +NewStuffDialog::NewStuffDialog() : KNewStuff("kanagram/vocabulary", "http://kde-edu.org/kanagram/" + KanagramSettings::dataLanguage() + ".xml") +{ +} + +NewStuffDialog::~NewStuffDialog() +{ +} + +bool NewStuffDialog::install(const QString &fileName) +{ + return false; +} + +QString NewStuffDialog::downloadDestination(KNS::Entry *entry) +{ + QString fileName = entry->payload().path(); + fileName = fileName.section('/', -1); + return KGlobal::dirs()->saveLocation("data", "kanagram/data/" + KanagramSettings::dataLanguage()) + fileName; +} + +bool NewStuffDialog::createUploadFile(const QString &fileName) +{ + return false; +} diff --git a/kanagram/src/newstuffdialog.h b/kanagram/src/newstuffdialog.h new file mode 100644 index 00000000..f0441623 --- /dev/null +++ b/kanagram/src/newstuffdialog.h @@ -0,0 +1,17 @@ +#ifndef NEWSTUFFDIALOG_H +#define NEWSTUFFDIALOG_H + +#include <knewstuff/knewstuff.h> + +class NewStuffDialog : public KNewStuff +{ + public: + NewStuffDialog(); + ~NewStuffDialog(); + bool install(const QString &fileName); + bool createUploadFile(const QString &fileName); + QString downloadDestination(KNS::Entry *entry); +}; + +#endif + diff --git a/kanagram/src/newstuffwidget.ui b/kanagram/src/newstuffwidget.ui new file mode 100644 index 00000000..f1b1bb23 --- /dev/null +++ b/kanagram/src/newstuffwidget.ui @@ -0,0 +1,62 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>NewStuffWidget</class> +<widget class="QDialog"> + <property name="name"> + <cstring>NewStuffWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>347</width> + <height>301</height> + </rect> + </property> + <property name="caption"> + <string>New Stuff</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Kanagram allows you to download +new data from the Internet. + +If you are connected to the Internet, press +the button to get new vocabulary files.</string> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="2" column="0"> + <property name="name"> + <cstring>btnGetNew</cstring> + </property> + <property name="text"> + <string>Download New Vocabularies</string> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kanagram/src/vocabedit.cpp b/kanagram/src/vocabedit.cpp new file mode 100644 index 00000000..7079e566 --- /dev/null +++ b/kanagram/src/vocabedit.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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 "vocabedit.h" + +#include <qpushbutton.h> +#include <qlistbox.h> +#include <qlineedit.h> +#include <qfile.h> +#include <qstring.h> +#include <qvaluevector.h> + +#include <kstandarddirs.h> +#include <kglobal.h> +#include <kurl.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <klocale.h> + +#include "keduvocdocument.h" +#include "keduvocexpression.h" +#include "vocabsettings.h" +#include "kanagramsettings.h" + + +VocabEdit::VocabEdit(QWidget *parent, QString fileName) : VocabEditWidget(parent), m_fileName("") +{ + if(fileName != "") + { + m_fileName = fileName; + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(m_fileName), false); + for(int i = 0; i < doc->numEntries(); i++) + { + KEduVocExpression expr = *doc->getEntry(i); + m_vocabList.append(expr); + lboxWords->insertItem(doc->getEntry(i)->getOriginal()); + } + txtVocabName->setText(doc->getTitle()); + txtDescription->setText(doc->getDocRemark()); + } + + connect(btnSave, SIGNAL(clicked()), this, SLOT(slotSave())); + connect(btnNewWord, SIGNAL(clicked()), this, SLOT(slotNewWord())); + connect(btnRemoveWord, SIGNAL(clicked()), this, SLOT(slotRemoveWord())); + connect(btnClose, SIGNAL(clicked()), this, SLOT(slotClose())); + + connect(txtWord, SIGNAL(textChanged(const QString &)), this, SLOT(slotWordTextChanged(const QString &))); + connect(txtHint, SIGNAL(textChanged(const QString &)), this, SLOT(slotHintTextChanged(const QString &))); + + //Connect the name and description boxes to a general textChanged slot, so that we can keep track of + //whether they've been changed or not + connect(txtVocabName, SIGNAL(textChanged(const QString &)), this, SLOT(slotTextChanged(const QString &))); + connect(txtDescription, SIGNAL(textChanged(const QString &)), this, SLOT(slotTextChanged(const QString &))); + + connect(lboxWords, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); + + //Has anything in the dialog changed? + m_textChanged = false; +} + +VocabEdit::~VocabEdit() +{ +} + +void VocabEdit::slotSave() +{ + KEduVocDocument *doc = new KEduVocDocument(this); + doc->setTitle(txtVocabName->text()); + doc->setDocRemark(txtDescription->text()); + for(uint i = 0; i < m_vocabList.size(); i++) + { + doc->appendEntry(&m_vocabList[i]); + } + + QString fileName; + if(m_fileName == "") + { + fileName = KGlobal::dirs()->saveLocation("data", "kanagram/data/" + KanagramSettings::dataLanguage()) + txtVocabName->text().lower().replace(" ", "") + ".kvtml"; + } + else + { + fileName = m_fileName; + } + doc->saveAs(this, KURL(fileName), KEduVocDocument::automatic, "kanagram"); + + VocabSettings *settings = (VocabSettings*)this->parentWidget(); + settings->refreshView(); + + if(m_textChanged) + m_textChanged = false; +} + +void VocabEdit::slotClose() +{ + //Has anything in the dialog changed? + if(m_textChanged && lboxWords->count() > 0) + { + int code = KMessageBox::warningYesNo(this, i18n("Would you like to save your changes?"), i18n("Save Changes Dialog")); + if(code == KMessageBox::Yes) + { + slotSave(); + close(); + } + else + close(); + } + else + close(); +} + +void VocabEdit::slotNewWord() +{ + lboxWords->insertItem("New Item"); + KEduVocExpression expr = KEduVocExpression(); + m_vocabList.append(expr); + + if(m_textChanged == false) + m_textChanged = true; +} + +void VocabEdit::slotSelectionChanged() +{ + //A little hack to make things work right + disconnect(txtWord, SIGNAL(textChanged(const QString &)), this, SLOT(slotWordTextChanged(const QString &))); + disconnect(txtHint, SIGNAL(textChanged(const QString &)), this, SLOT(slotHintTextChanged(const QString &))); + if(lboxWords->currentItem() >= 0) + { + txtWord->setText(m_vocabList[lboxWords->currentItem()].getOriginal()); + txtHint->setText(m_vocabList[lboxWords->currentItem()].getRemark(0)); + } + connect(txtWord, SIGNAL(textChanged(const QString &)), this, SLOT(slotWordTextChanged(const QString &))); + connect(txtHint, SIGNAL(textChanged(const QString &)), this, SLOT(slotHintTextChanged(const QString &))); +} + +void VocabEdit::slotWordTextChanged(const QString &changes) +{ + //Make sure there actually is a currentItem() + if(lboxWords->currentItem() != -1) + { + m_vocabList[lboxWords->currentItem()].setOriginal(changes); + lboxWords->changeItem(changes, lboxWords->currentItem()); + } + + if(m_textChanged == false) + m_textChanged = true; +} + +void VocabEdit::slotHintTextChanged(const QString &changes) +{ + //Make sure there actually is a currentItem() + if(lboxWords->currentItem() != -1) + m_vocabList[lboxWords->currentItem()].setRemark(0, changes); + + if(m_textChanged == false) + m_textChanged = true; +} + +void VocabEdit::slotTextChanged(const QString &changes) +{ + //Make sure we know when text has been modified and not saved, so we + //can notify the user + if(m_textChanged == false) + m_textChanged = true; + + //Make gcc happy + (void)changes; +} + +void VocabEdit::slotRemoveWord() +{ + if (lboxWords->count()) { + m_vocabList.erase(m_vocabList.begin() + lboxWords->currentItem()); + lboxWords->removeItem(lboxWords->currentItem()); + } + + if(m_textChanged == false) + m_textChanged = true; +} + +#include "vocabedit.moc" diff --git a/kanagram/src/vocabedit.h b/kanagram/src/vocabedit.h new file mode 100644 index 00000000..342f71cb --- /dev/null +++ b/kanagram/src/vocabedit.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joshua Keel * + * joshuakeel@gmail.com * + * * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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 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. * + ***************************************************************************/ + + +#ifndef VOCABEDIT_H +#define VOCABEDIT_H + +#include "vocabeditwidget.h" + +#include <qvaluevector.h> + +class KEduVocExpression; + +class VocabEdit : public VocabEditWidget +{ +Q_OBJECT + public: + VocabEdit(QWidget *parent); + VocabEdit(QWidget *parent, QString fileName); + ~VocabEdit(); + + public slots: + void slotSave(); + void slotClose(); + void slotNewWord(); + void slotRemoveWord(); + void slotSelectionChanged(); + void slotWordTextChanged(const QString &changes); + void slotHintTextChanged(const QString &changes); + void slotTextChanged(const QString &changes); + + private: + QValueVector<KEduVocExpression> m_vocabList; + QString m_fileName; + bool m_textChanged; +}; + +#endif + diff --git a/kanagram/src/vocabeditwidget.ui b/kanagram/src/vocabeditwidget.ui new file mode 100644 index 00000000..d4d1229d --- /dev/null +++ b/kanagram/src/vocabeditwidget.ui @@ -0,0 +1,228 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>VocabEditWidget</class> +<widget class="QDialog"> + <property name="name"> + <cstring>VocabEditWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>394</width> + <height>369</height> + </rect> + </property> + <property name="caption"> + <string>Vocabulary Editor</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnSave</cstring> + </property> + <property name="text"> + <string>Save</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnClose</cstring> + </property> + <property name="text"> + <string>Close</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Description:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>txtDescription</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The description of the vocabulary. If you're creating a new vocabulary, add a description so that users of your vocabulary will know what kinds of words it contains.</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>txtVocabName</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Vocabulary name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>txtVocabName</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The name of the vocabulary you are editing.</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>txtDescription</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnRemoveWord</cstring> + </property> + <property name="text"> + <string>Remove Word</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Removes the selected word.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnNewWord</cstring> + </property> + <property name="text"> + <string>New Word</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Creates a new word.</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QListBox"> + <property name="name"> + <cstring>lboxWords</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The list of words in the vocabulary.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Word:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>txtWord</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The selected word. This box allows you to edit the selected word.</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>txtHint</cstring> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>txtWord</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Hint:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>txtHint</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>The selected hint. Add a hint to aid in guessing the word.</string> + </property> + </widget> + </grid> + </widget> + </vbox> + </widget> + </grid> + </widget> + </grid> +</widget> +<tabstops> + <tabstop>txtVocabName</tabstop> + <tabstop>txtDescription</tabstop> + <tabstop>btnRemoveWord</tabstop> + <tabstop>btnNewWord</tabstop> + <tabstop>txtWord</tabstop> + <tabstop>txtHint</tabstop> + <tabstop>btnSave</tabstop> + <tabstop>btnClose</tabstop> + <tabstop>lboxWords</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kanagram/src/vocabsettings.cpp b/kanagram/src/vocabsettings.cpp new file mode 100644 index 00000000..c7b41ba7 --- /dev/null +++ b/kanagram/src/vocabsettings.cpp @@ -0,0 +1,93 @@ +#include "vocabsettings.h" +#include "vocabedit.h" + +#include <qpushbutton.h> + +#include <kdebug.h> +#include <kstandarddirs.h> +#include <qstringlist.h> +#include <qlistview.h> +#include <qvaluevector.h> +#include <qfile.h> +#include <qfileinfo.h> + +#include <kurl.h> + +#include "keduvocdocument.h" +#include "kanagramsettings.h" + +VocabSettings::VocabSettings(QWidget *parent) : VocabSettingsWidget(parent) +{ + connect(btnCreateNew, SIGNAL(clicked()), this, SLOT(slotCreateNew())); + connect(btnEdit, SIGNAL(clicked()), this, SLOT(slotEdit())); + connect(btnDelete, SIGNAL(clicked()), this, SLOT(slotDelete())); + connect(lviewVocab, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotSelectionChanged(QListViewItem *))); + + refreshView(); +} + +VocabSettings::~VocabSettings() +{ +} + +void VocabSettings::refreshView() +{ + lviewVocab->clear(); + + m_fileList = KGlobal::dirs()->findAllResources("appdata", "data/" + KanagramSettings::dataLanguage() + "/" + "*.kvtml"); + for(uint i = 0; i < m_fileList.size(); i++) + { + KEduVocDocument *doc = new KEduVocDocument(this); + doc->open(KURL(m_fileList[i]), false); + QListViewItem *item = new QListViewItem(lviewVocab, 0); + item->setText( 0, doc->getTitle() ); + item->setText( 1, doc->getDocRemark() ); + m_itemMap[item] = i; + } +} + +void VocabSettings::slotEdit() +{ + if(lviewVocab->selectedItem()) + { + int index = m_itemMap[lviewVocab->selectedItem()]; + VocabEdit *vocabEdit = new VocabEdit(this, m_fileList[index]); + vocabEdit->show(); + } +} + +void VocabSettings::slotDelete() +{ + if(lviewVocab->selectedItem()) + { + int index = m_itemMap[lviewVocab->selectedItem()]; + /*bool itWorked = */QFile::remove(m_fileList[index]); + } + + refreshView(); +} + +void VocabSettings::slotCreateNew() +{ + VocabEdit *vocabEdit = new VocabEdit(this, ""); + vocabEdit->show(); +} + +void VocabSettings::slotSelectionChanged(QListViewItem *item) +{ + int index = m_itemMap[item]; + QFileInfo info = QFileInfo(m_fileList[index]); + if(!info.isWritable()) + { + btnDelete->setEnabled(false); + btnEdit->setEnabled(false); + } + else + { + btnDelete->setEnabled(true); + btnEdit->setEnabled(true); + } +} + +#include "vocabsettings.moc" + diff --git a/kanagram/src/vocabsettings.h b/kanagram/src/vocabsettings.h new file mode 100644 index 00000000..d321ee2f --- /dev/null +++ b/kanagram/src/vocabsettings.h @@ -0,0 +1,26 @@ +#ifndef VOCABSETTINGS_H +#define VOCABSETTINGS_H + +#include "vocabsettingswidget.h" + +class VocabSettings : public VocabSettingsWidget +{ +Q_OBJECT + public: + VocabSettings(QWidget *parent); + ~VocabSettings(); + void refreshView(); + + private: + QStringList m_fileList; + QMap<const QListViewItem*, int> m_itemMap; + + private slots: + void slotCreateNew(); + void slotEdit(); + void slotDelete(); + void slotSelectionChanged(QListViewItem *item); +}; + +#endif + diff --git a/kanagram/src/vocabsettingswidget.ui b/kanagram/src/vocabsettingswidget.ui new file mode 100644 index 00000000..b329da4e --- /dev/null +++ b/kanagram/src/vocabsettingswidget.ui @@ -0,0 +1,117 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>VocabSettingsWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>VocabSettingsWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>456</width> + <height>338</height> + </rect> + </property> + <property name="caption"> + <string>Vocabularies</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnCreateNew</cstring> + </property> + <property name="text"> + <string>Create New</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Creates a new vocabulary.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnEdit</cstring> + </property> + <property name="text"> + <string>Edit</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Edits the selected vocabulary.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnDelete</cstring> + </property> + <property name="text"> + <string>Delete</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Deletes the selected vocabulary.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QListView"> + <column> + <property name="text"> + <string>Title</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Description</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>lviewVocab</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + <property name="whatsThis" stdset="0"> + <string>The list of installed vocabularies.</string> + </property> + </widget> + </vbox> + </widget> + </grid> +</widget> +<slots> + <slot>createNew()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> |