File indexing completed on 2024-04-21 03:48:22

0001 /*
0002  * Vocabulary Expression Translation for KDE Edu
0003  * SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org>
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "keduvoctranslation.h"
0008 
0009 #include "keduvocdeclension.h"
0010 #include "keduvockvtml2writer.h"
0011 #include "keduvocleitnerbox.h"
0012 #include "keduvocwordtype.h"
0013 #include "kvtml2defs.h"
0014 
0015 class KEduVocTranslation::KEduVocTranslationPrivate
0016 {
0017 public:
0018     KEduVocTranslationPrivate(KEduVocExpression *parent);
0019 
0020     ~KEduVocTranslationPrivate();
0021 
0022     KEduVocExpression *m_entry;
0023 
0024     /// Type of a word noun, verb, adjective etc
0025     KEduVocWordType *m_wordType;
0026 
0027     /// Leitner box of the translation.
0028     KEduVocLeitnerBox *m_leitnerBox;
0029 
0030     /// A comment giving additional information.
0031     QString m_comment;
0032     /// A hint, to make guessing the word easier.
0033     QString m_hint;
0034     /// Paraphrase
0035     QString m_paraphrase;
0036     /// An example
0037     QString m_example;
0038     /// Pronunciation
0039     QString m_pronunciation;
0040     /// Image url
0041     QUrl m_imageUrl;
0042     /// Sound url
0043     QUrl m_soundUrl;
0044 
0045     /// When creating multiple choice tests, these are possible answers. (otherwise other words are added randomly)
0046     QStringList m_multipleChoice;
0047 
0048     /// Conjugations of a word (I go, you go, he goes... boring in english)
0049     QMap<QString, KEduVocConjugation> m_conjugations;
0050 
0051     /// The comparison forms of adjectives and adverbs: (fast), faster, fastest
0052     KEduVocText *m_comparative;
0053     KEduVocText *m_superlative;
0054 
0055     /// The grade of an article. The text part should not be used.
0056     KEduVocText *m_articleGrade;
0057 
0058     KEduVocDeclension *m_declension;
0059 
0060     // connections to other translations
0061     /// Synonyms for a word: sick and ill, student and pupil
0062     QList<KEduVocTranslation *> m_synonyms;
0063     /// An antonym - the opposite: hot - cold
0064     QList<KEduVocTranslation *> m_antonyms;
0065     /// List of false friends
0066     QList<KEduVocTranslation *> m_falseFriends;
0067 };
0068 
0069 KEduVocTranslation::KEduVocTranslationPrivate::KEduVocTranslationPrivate(KEduVocExpression *parent)
0070 {
0071     m_entry = parent;
0072     m_wordType = nullptr;
0073     m_leitnerBox = nullptr;
0074     m_declension = nullptr;
0075 
0076     m_comparative = nullptr;
0077     m_superlative = nullptr;
0078     m_articleGrade = nullptr;
0079 }
0080 
0081 KEduVocTranslation::KEduVocTranslationPrivate::~KEduVocTranslationPrivate()
0082 {
0083     delete m_declension;
0084 }
0085 
0086 KEduVocTranslation::KEduVocTranslation(KEduVocExpression *entry)
0087     : d(new KEduVocTranslationPrivate(entry))
0088 {
0089 }
0090 
0091 KEduVocTranslation::KEduVocTranslation(KEduVocExpression *entry, const QString &translation)
0092     : d(new KEduVocTranslationPrivate(entry))
0093 {
0094     setText(translation.simplified());
0095 }
0096 
0097 KEduVocTranslation::KEduVocTranslation(const KEduVocTranslation &other)
0098     : KEduVocText(other)
0099     ,
0100     // set the entry to 0, the translation will be put into a copied entry by the expression copy constructor
0101     d(new KEduVocTranslationPrivate(nullptr))
0102 {
0103     // better no word type copy as this is pointer copying
0104     // will not work as this is not added to the word type container!
0105     //  d->m_wordType = other.d->m_wordType;
0106     //  d->m_leitnerBox = translation.d->m_leitnerBox;
0107     d->m_comment = other.d->m_comment;
0108     d->m_paraphrase = other.d->m_paraphrase;
0109     d->m_example = other.d->m_example;
0110     d->m_pronunciation = other.d->m_pronunciation;
0111     d->m_conjugations = other.d->m_conjugations;
0112     d->m_comparative = other.d->m_comparative;
0113     d->m_superlative = other.d->m_superlative;
0114     d->m_multipleChoice = other.d->m_multipleChoice;
0115     d->m_imageUrl = other.d->m_imageUrl;
0116     d->m_soundUrl = other.d->m_soundUrl;
0117     //  no copies of the following for now. we don't know enough to also add this as synonym/etc
0118     //  d->m_synonyms = other.d->m_synonyms;
0119     //  d->m_antonyms = other.d->m_antonyms;
0120     //  d->m_falseFriends = other.d->m_falseFriends;
0121     if (other.d->m_declension) {
0122         d->m_declension = new KEduVocDeclension(*other.d->m_declension);
0123     }
0124 }
0125 
0126 KEduVocTranslation::~KEduVocTranslation()
0127 {
0128     setWordType(nullptr);
0129     setLeitnerBox(nullptr);
0130     foreach (KEduVocTranslation *synonym, d->m_synonyms) {
0131         synonym->removeSynonym(this);
0132     }
0133     foreach (KEduVocTranslation *antonym, d->m_antonyms) {
0134         antonym->removeAntonym(this);
0135     }
0136     foreach (KEduVocTranslation *falseFriend, d->m_falseFriends) {
0137         falseFriend->removeFalseFriend(this);
0138     }
0139     delete d;
0140 }
0141 
0142 bool KEduVocTranslation::operator==(const KEduVocTranslation &translation) const
0143 {
0144     return KEduVocText::operator==(translation) && d->m_wordType == translation.d->m_wordType && d->m_leitnerBox == translation.d->m_leitnerBox
0145         && d->m_comment == translation.d->m_comment && d->m_paraphrase == translation.d->m_paraphrase && d->m_example == translation.d->m_example
0146         && d->m_pronunciation == translation.d->m_pronunciation && d->m_imageUrl == translation.d->m_imageUrl && d->m_soundUrl == translation.d->m_soundUrl
0147         && d->m_comparative == translation.d->m_comparative && d->m_superlative == translation.d->m_superlative
0148         && d->m_multipleChoice == translation.d->m_multipleChoice && d->m_synonyms == translation.d->m_synonyms && d->m_antonyms == translation.d->m_antonyms
0149         && d->m_falseFriends == translation.d->m_falseFriends && d->m_conjugations == translation.d->m_conjugations;
0150     /// @todo check and include declensions d->m_declension == translation.d->m_declension;
0151 }
0152 
0153 KEduVocTranslation &KEduVocTranslation::operator=(const KEduVocTranslation &translation)
0154 {
0155     KEduVocText::operator=(translation);
0156     d->m_entry = translation.d->m_entry;
0157     //     d->m_wordType = translation.d->m_wordType;
0158     //     d->m_leitnerBox = translation.d->m_leitnerBox;
0159     d->m_comment = translation.d->m_comment;
0160     d->m_paraphrase = translation.d->m_paraphrase;
0161     d->m_example = translation.d->m_example;
0162     d->m_pronunciation = translation.d->m_pronunciation;
0163     d->m_imageUrl = translation.d->m_imageUrl;
0164     d->m_soundUrl = translation.d->m_soundUrl;
0165     d->m_comparative = translation.d->m_comparative;
0166     d->m_superlative = translation.d->m_superlative;
0167     d->m_multipleChoice = translation.d->m_multipleChoice;
0168     d->m_falseFriends = translation.d->m_falseFriends;
0169     d->m_synonyms = translation.d->m_synonyms;
0170     d->m_antonyms = translation.d->m_antonyms;
0171     d->m_conjugations = translation.d->m_conjugations;
0172     if (translation.d->m_declension) {
0173         d->m_declension = new KEduVocDeclension(*translation.d->m_declension);
0174     }
0175 
0176     return *this;
0177 }
0178 
0179 QString KEduVocTranslation::comment() const
0180 {
0181     return d->m_comment;
0182 }
0183 
0184 void KEduVocTranslation::setComment(const QString &expr)
0185 {
0186     d->m_comment = expr.simplified();
0187 }
0188 
0189 void KEduVocTranslation::addFalseFriend(KEduVocTranslation *falseFriend)
0190 {
0191     d->m_falseFriends.append(falseFriend);
0192 }
0193 
0194 void KEduVocTranslation::removeFalseFriend(KEduVocTranslation *falseFriend)
0195 {
0196     d->m_falseFriends.removeAt(d->m_falseFriends.indexOf(falseFriend));
0197 }
0198 
0199 QList<KEduVocTranslation *> KEduVocTranslation::falseFriends() const
0200 {
0201     return d->m_falseFriends;
0202 }
0203 
0204 void KEduVocTranslation::addSynonym(KEduVocTranslation *synonym)
0205 {
0206     d->m_synonyms.append(synonym);
0207 }
0208 
0209 void KEduVocTranslation::removeSynonym(KEduVocTranslation *synonym)
0210 {
0211     d->m_synonyms.removeAt(d->m_synonyms.indexOf(synonym));
0212 }
0213 
0214 QList<KEduVocTranslation *> KEduVocTranslation::synonyms() const
0215 {
0216     return d->m_synonyms;
0217 }
0218 
0219 void KEduVocTranslation::addAntonym(KEduVocTranslation *antonym)
0220 {
0221     d->m_antonyms.append(antonym);
0222 }
0223 
0224 QList<KEduVocTranslation *> KEduVocTranslation::antonyms() const
0225 {
0226     return d->m_antonyms;
0227 }
0228 
0229 void KEduVocTranslation::removeAntonym(KEduVocTranslation *antonym)
0230 {
0231     d->m_antonyms.removeAt(d->m_antonyms.indexOf(antonym));
0232 }
0233 
0234 void KEduVocTranslation::setExample(const QString &expr)
0235 {
0236     d->m_example = expr.simplified();
0237 }
0238 
0239 QString KEduVocTranslation::example() const
0240 {
0241     return d->m_example;
0242 }
0243 
0244 void KEduVocTranslation::setParaphrase(const QString &expr)
0245 {
0246     d->m_paraphrase = expr.simplified();
0247 }
0248 
0249 QString KEduVocTranslation::paraphrase() const
0250 {
0251     return d->m_paraphrase;
0252 }
0253 
0254 void KEduVocTranslation::setConjugation(const QString &tense, const KEduVocConjugation &con)
0255 {
0256     d->m_conjugations[tense] = con;
0257 }
0258 
0259 KEduVocConjugation &KEduVocTranslation::conjugation(const QString &tense)
0260 {
0261     return d->m_conjugations[tense];
0262 }
0263 
0264 KEduVocConjugation KEduVocTranslation::getConjugation(const QString &tense) const
0265 {
0266     if (d->m_conjugations.contains(tense)) {
0267         return d->m_conjugations[tense];
0268     }
0269     return KEduVocConjugation();
0270 }
0271 
0272 QStringList &KEduVocTranslation::multipleChoice()
0273 {
0274     return d->m_multipleChoice;
0275 }
0276 
0277 QStringList KEduVocTranslation::getMultipleChoice() const
0278 {
0279     return d->m_multipleChoice;
0280 }
0281 
0282 void KEduVocTranslation::setMultipleChoice(const QStringList &choices)
0283 {
0284     d->m_multipleChoice = choices;
0285 }
0286 
0287 QString KEduVocTranslation::pronunciation() const
0288 {
0289     return d->m_pronunciation;
0290 }
0291 
0292 void KEduVocTranslation::setPronunciation(const QString &expr)
0293 {
0294     d->m_pronunciation = expr.simplified();
0295 }
0296 
0297 QStringList KEduVocTranslation::conjugationTenses() const
0298 {
0299     return d->m_conjugations.keys();
0300 }
0301 
0302 QMap<QString, KEduVocConjugation> KEduVocTranslation::conjugations() const
0303 {
0304     return d->m_conjugations;
0305 }
0306 
0307 void KEduVocTranslation::setConjugations(const QMap<QString, KEduVocConjugation> &conjugations)
0308 {
0309     d->m_conjugations = conjugations;
0310 }
0311 
0312 /** get the sound url for this translation if it exists */
0313 QUrl KEduVocTranslation::soundUrl()
0314 {
0315     return d->m_soundUrl;
0316 }
0317 
0318 /** set the sound url for this translation
0319  * @param url               url of the sound file */
0320 void KEduVocTranslation::setSoundUrl(const QUrl &url)
0321 {
0322     d->m_soundUrl = url;
0323 }
0324 
0325 /** get the image url for this translation if it exists */
0326 QUrl KEduVocTranslation::imageUrl()
0327 {
0328     return d->m_imageUrl;
0329 }
0330 
0331 /** set the image url for this translation
0332  * @param url               url of the image
0333  */
0334 void KEduVocTranslation::setImageUrl(const QUrl &url)
0335 {
0336     d->m_imageUrl = url;
0337 }
0338 
0339 KEduVocWordType *KEduVocTranslation::wordType() const
0340 {
0341     if (d) {
0342         return d->m_wordType;
0343     } else {
0344         return nullptr;
0345     }
0346 }
0347 
0348 void KEduVocTranslation::setWordType(KEduVocWordType *wordType)
0349 {
0350     if (d->m_wordType) {
0351         d->m_wordType->removeTranslation(this);
0352     }
0353     if (wordType) {
0354         wordType->addTranslation(this);
0355     }
0356     d->m_wordType = wordType;
0357 }
0358 
0359 KEduVocLeitnerBox *KEduVocTranslation::leitnerBox() const
0360 {
0361     return d->m_leitnerBox;
0362 }
0363 
0364 void KEduVocTranslation::setLeitnerBox(KEduVocLeitnerBox *leitnerBox)
0365 {
0366     if (d->m_leitnerBox) {
0367         d->m_leitnerBox->removeTranslation(this);
0368     }
0369     if (leitnerBox) {
0370         leitnerBox->addTranslation(this);
0371     }
0372     d->m_leitnerBox = leitnerBox;
0373 }
0374 
0375 KEduVocExpression *KEduVocTranslation::entry()
0376 {
0377     return d->m_entry;
0378 }
0379 
0380 QString KEduVocTranslation::comparative() const
0381 {
0382     if (d->m_comparative) {
0383         return d->m_comparative->text();
0384     }
0385     return QString();
0386 }
0387 
0388 void KEduVocTranslation::setComparative(const QString &comparative)
0389 {
0390     if (!d->m_comparative) {
0391         d->m_comparative = new KEduVocText(comparative);
0392     } else {
0393         d->m_comparative->setText(comparative);
0394     }
0395 }
0396 
0397 QString KEduVocTranslation::superlative() const
0398 {
0399     if (d->m_superlative) {
0400         return d->m_superlative->text();
0401     }
0402     return QString();
0403 }
0404 
0405 void KEduVocTranslation::setSuperlative(const QString &superlative)
0406 {
0407     if (!d->m_superlative) {
0408         d->m_superlative = new KEduVocText(superlative);
0409     } else {
0410         d->m_superlative->setText(superlative);
0411     }
0412 }
0413 
0414 KEduVocText KEduVocTranslation::comparativeForm() const
0415 {
0416     if (!d->m_comparative) {
0417         return KEduVocText();
0418     }
0419     KEduVocText t(*(d->m_comparative));
0420     return t;
0421 }
0422 
0423 void KEduVocTranslation::setComparativeForm(const KEduVocText &comparative)
0424 {
0425     if (!d->m_comparative) {
0426         d->m_comparative = new KEduVocText();
0427     }
0428     *(d->m_comparative) = comparative;
0429 }
0430 
0431 KEduVocText KEduVocTranslation::superlativeForm() const
0432 {
0433     if (!d->m_superlative) {
0434         return KEduVocText();
0435     }
0436     KEduVocText t(*d->m_superlative);
0437     return t;
0438 }
0439 
0440 void KEduVocTranslation::setSuperlativeForm(const KEduVocText &superlative)
0441 {
0442     if (!d->m_superlative) {
0443         d->m_superlative = new KEduVocText();
0444     }
0445     *d->m_superlative = superlative;
0446 }
0447 
0448 KEduVocText KEduVocTranslation::article() const
0449 {
0450     if (!d->m_articleGrade) {
0451         return KEduVocText();
0452     }
0453     KEduVocText t(*d->m_articleGrade);
0454     return t;
0455 }
0456 
0457 void KEduVocTranslation::setArticle(const KEduVocText &article)
0458 {
0459     if (!d->m_articleGrade) {
0460         d->m_articleGrade = new KEduVocText();
0461     }
0462     *d->m_articleGrade = article;
0463 }
0464 
0465 KEduVocDeclension *KEduVocTranslation::declension()
0466 {
0467     return d->m_declension;
0468 }
0469 
0470 void KEduVocTranslation::setDeclension(KEduVocDeclension *declension)
0471 {
0472     // remove the old declension object
0473     delete d->m_declension;
0474     d->m_declension = declension;
0475 }
0476 
0477 void KEduVocTranslation::toKVTML2(QDomElement &parent)
0478 {
0479     // text and grade
0480     KEduVocText::toKVTML2(parent);
0481 
0482     // declension
0483     if (d->m_declension) {
0484         d->m_declension->toKVTML2(parent);
0485     }
0486 
0487     // conjugation
0488     foreach (const QString &tense, conjugationTenses()) {
0489         QDomElement conjugationElement = parent.ownerDocument().createElement(KVTML_CONJUGATION);
0490         getConjugation(tense).toKVTML2(conjugationElement, tense);
0491         if (conjugationElement.hasChildNodes()) {
0492             parent.appendChild(conjugationElement);
0493         }
0494     }
0495 
0496     // <comment>
0497     KEduVocKvtml2Writer::appendTextElement(parent, KVTML_COMMENT, comment());
0498 
0499     // <pronunciation>
0500     KEduVocKvtml2Writer::appendTextElement(parent, KVTML_PRONUNCIATION, pronunciation());
0501 
0502     // <example>
0503     KEduVocKvtml2Writer::appendTextElement(parent, KVTML_EXAMPLE, example());
0504 
0505     // <paraphrase>
0506     KEduVocKvtml2Writer::appendTextElement(parent, KVTML_PARAPHRASE, paraphrase());
0507 
0508     ///@todo synonyms, antonyms
0509     ///@todo false friends
0510 }
0511 
0512 void KEduVocTranslation::fromKVTML2(QDomElement &parent)
0513 {
0514     KEduVocText::fromKVTML2(parent);
0515 
0516     setDeclension(KEduVocDeclension::fromKVTML2(parent));
0517 
0518     setComment(parent.firstChildElement(KVTML_COMMENT).text());
0519 
0520     setPronunciation(parent.firstChildElement(KVTML_PRONUNCIATION).text());
0521 
0522     //<example></example>
0523     setExample(parent.firstChildElement(KVTML_EXAMPLE).text());
0524 
0525     //<paraphrase></paraphrase>
0526     setParaphrase(parent.firstChildElement(KVTML_PARAPHRASE).text());
0527 
0528     // conjugations
0529     QDomElement conjugationElement = parent.firstChildElement(KVTML_CONJUGATION);
0530     while (!conjugationElement.isNull()) {
0531         QDomElement tenseElement = conjugationElement.firstChildElement(KVTML_TENSE);
0532         QString tense = tenseElement.text();
0533         KEduVocConjugation *conjugation = KEduVocConjugation::fromKVTML2(conjugationElement);
0534         setConjugation(tense, *conjugation);
0535         delete conjugation;
0536         conjugationElement = conjugationElement.nextSiblingElement(KVTML_CONJUGATION);
0537     }
0538 
0539     ///@todo synonyms, antonym
0540     ///@todo false friends
0541 }
0542 
0543 void KEduVocTranslation::setEntry(KEduVocExpression *entry)
0544 {
0545     d->m_entry = entry;
0546 }