LibKEduVocDocument

keduvockvtml2reader.cpp
1/*
2 * read a KEduVocDocument from a KVTML file
3 * SPDX-FileCopyrightText: 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
4 * SPDX-FileCopyrightText: 2005 Eric Pignet <eric at erixpage.com>
5 * SPDX-FileCopyrightText: 2007 Peter Hedlund <peter.hedlund@kdemail.net>
6 * SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org>
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include "keduvockvtml2reader.h"
11
12#include <KLocalizedString>
13#include <QDir>
14#include <QIODevice>
15#include <QList>
16#include <QTextStream>
17
18#include "keduvoccommon_p.h"
19#include "keduvockvtmlreader.h"
20#include "keduvocleitnerbox.h"
21#include "keduvoclesson.h"
22#include "keduvocwordtype.h"
23#include "kvtml2defs.h"
24
25#include <QDebug>
26
28 : m_inputFile(&file)
29{
30}
31
33{
34 QTextStream ts(m_inputFile);
35 QString line1(ts.readLine());
36 QString line2(ts.readLine());
37
38 m_inputFile->seek(0);
39 return ((line1.startsWith(QLatin1String("<?xml"))) && (line2.indexOf(KVTML_TAG, 0) > 0));
40}
41
46
48{
49 m_doc = &doc;
50
51 QDomDocument domDoc(QStringLiteral("KEduVocDocument"));
52
53 if (!domDoc.setContent(m_inputFile, &m_errorMessage))
55
56 QDomElement domElementKvtml = domDoc.documentElement();
57 if (domElementKvtml.tagName() != KVTML_TAG) {
58 m_errorMessage = i18n("This is not a KDE Vocabulary document.");
60 }
61
62 if (domElementKvtml.attribute(KVTML_VERSION).toFloat() < 2.0) {
63 // read the file with the old format
64
65 // first reset the file to the beginning
66 m_inputFile->seek(0);
67 KEduVocKvtmlReader oldFormat(*m_inputFile);
68
69 // get the return value
70 KEduVocDocument::ErrorCode retval = oldFormat.read(doc);
71
72 // pass the errormessage up
73 m_errorMessage = oldFormat.errorMessage();
74 return retval;
75 }
76
77 //-------------------------------------------------------------------------
78 // Information
79 //-------------------------------------------------------------------------
80
81 QDomElement info = domElementKvtml.firstChildElement(KVTML_INFORMATION);
82 if (!info.isNull()) {
83 if (!readInformation(info))
85 }
86
87 bool result = readGroups(domElementKvtml); // read sub-groups
88
90}
91
92bool KEduVocKvtml2Reader::readInformation(QDomElement &informationElement)
93{
94 // read the generator
95 QDomElement currentElement = informationElement.firstChildElement(KVTML_GENERATOR);
96 if (!currentElement.isNull()) {
97 m_doc->setGenerator(currentElement.text());
98 // add the version if it's there
99 int pos = m_doc->generator().lastIndexOf(KVD_VERS_PREFIX);
100 if (pos >= 0) {
101 m_doc->setVersion(m_doc->generator().remove(0, pos + 2));
102 }
103 }
104
105 // read the title
106 currentElement = informationElement.firstChildElement(KVTML_TITLE);
107 if (!currentElement.isNull()) {
108 m_doc->setTitle(currentElement.text());
109 }
110
111 // read the author
112 currentElement = informationElement.firstChildElement(KVTML_AUTHOR);
113 if (!currentElement.isNull()) {
114 m_doc->setAuthor(currentElement.text());
115 }
116
117 currentElement = informationElement.firstChildElement(KVTML_AUTHORCONTACT);
118 if (!currentElement.isNull()) {
119 m_doc->setAuthorContact(currentElement.text());
120 }
121
122 // read the license
123 currentElement = informationElement.firstChildElement(KVTML_LICENSE);
124 if (!currentElement.isNull()) {
125 m_doc->setLicense(currentElement.text());
126 }
127
128 // read the comment
129 currentElement = informationElement.firstChildElement(KVTML_COMMENT);
130 if (!currentElement.isNull()) {
131 m_doc->setDocumentComment(currentElement.text());
132 }
133
134 // read the category
135 currentElement = informationElement.firstChildElement(KVTML_CATEGORY);
136 if (!currentElement.isNull()) {
137 m_doc->setCategory(currentElement.text());
138 }
139
140 return true;
141}
142
143bool KEduVocKvtml2Reader::readGroups(QDomElement &domElementParent)
144{
145 bool result = false;
146
147 QDomElement groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);
148
149 QDomElement currentElement;
150
151 // ensure backwards compatibility - in kde 4.1 and earlier tenses were direct properties of the document class.
152 // now they are moved into the individual identifiers
153 QStringList tensesCompability;
154 groupElement = groupElement.firstChildElement(KVTML_TENSES);
155 if (!groupElement.isNull()) {
156 tensesCompability = readTenses(groupElement);
157 }
158
159 groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);
160 if (!groupElement.isNull()) {
161 QDomNodeList entryList = groupElement.elementsByTagName(KVTML_IDENTIFIER);
162 if (entryList.length() <= 0) {
163 m_errorMessage = i18n("missing identifier elements from identifiers tag");
164 return false;
165 }
166
167 for (int i = 0; i < entryList.count(); ++i) {
168 currentElement = entryList.item(i).toElement();
169 if (currentElement.parentNode() == groupElement) {
170 result = readIdentifier(currentElement);
171 if (!result) {
172 return false;
173 }
174 if (!tensesCompability.isEmpty()) {
175 m_doc->identifier(i).setTenseList(tensesCompability);
176 }
177 }
178 }
179 }
180
181 groupElement = domElementParent.firstChildElement(KVTML_ENTRIES);
182 if (!groupElement.isNull()) {
183 QDomNodeList entryList = groupElement.elementsByTagName(KVTML_ENTRY);
184 for (int i = 0; i < entryList.count(); ++i) {
185 currentElement = entryList.item(i).toElement();
186 if (currentElement.parentNode() == groupElement) {
187 result = readEntry(currentElement);
188 if (!result)
189 return false;
190 }
191 }
192 }
193
194 readSynonymsAntonymsFalseFriends(domElementParent);
195
196 groupElement = domElementParent.firstChildElement(KVTML_WORDTYPES);
197 if (!groupElement.isNull()) {
198 readChildWordTypes(m_doc->wordTypeContainer(), groupElement);
199 }
200
201 groupElement = domElementParent.firstChildElement(KVTML_LEITNERBOXES);
202 if (!groupElement.isNull()) {
203 readLeitner(m_doc->leitnerContainer(), groupElement);
204 }
205
206 groupElement = domElementParent.firstChildElement(KVTML_LESSONS);
207 if (!groupElement.isNull()) {
208 readChildLessons(m_doc->lesson(), groupElement);
209 }
210
211 // Additional cleanup: Put orphaned entries without a lesson into a default lesson.
212 KEduVocLesson *defaultLesson = new KEduVocLesson(i18n("Default Lesson"), m_doc->lesson());
213
214 // now make sure we don't have any orphan entries
215 foreach (KEduVocExpression *entry, m_allEntries) {
216 if (!entry->lesson()) {
217 defaultLesson->appendEntry(entry);
218 }
219 }
220
221 if (defaultLesson->entryCount() > 0) {
222 m_doc->lesson()->appendChildContainer(defaultLesson);
223 } else {
224 delete defaultLesson;
225 }
226
227 return true;
228}
229
230bool KEduVocKvtml2Reader::readIdentifier(QDomElement &identifierElement)
231{
232 bool result = true;
233 int id = identifierElement.attribute(KVTML_ID).toInt(&result);
234 if (!result) {
235 m_errorMessage = i18n("identifier missing id");
236 return false;
237 }
238
239 // generate empty identifiers in the doc
240 for (int i = m_doc->identifierCount(); i <= id; i++) {
242 }
243
244 // the first element, create the identifier, even if empty
245 QDomElement currentElement = identifierElement.firstChildElement(KVTML_NAME);
246 m_doc->identifier(id).setName(currentElement.text());
247
248 currentElement = identifierElement.firstChildElement(KVTML_LOCALE);
249 m_doc->identifier(id).setLocale(currentElement.text());
250
251 currentElement = identifierElement.firstChildElement(KVTML_IDENTIFIERTYPE);
252 if (!currentElement.isNull()) {
253 // TODO: do something with the type
254 }
255
256 // read sub-parts
257 currentElement = identifierElement.firstChildElement(KVTML_ARTICLE);
258 if (!currentElement.isNull()) {
259 readArticle(currentElement, id);
260 }
261
262 currentElement = identifierElement.firstChildElement(KVTML_PERSONALPRONOUNS);
263 if (!currentElement.isNull()) {
264 KEduVocPersonalPronoun personalPronoun;
265 readPersonalPronoun(currentElement, personalPronoun);
266 m_doc->identifier(id).setPersonalPronouns(personalPronoun);
267 }
268
269 QStringList tenses = readTenses(identifierElement);
270
271 m_doc->identifier(id).setTenseList(tenses);
272
273 return result;
274}
275
276bool KEduVocKvtml2Reader::readEntry(QDomElement &entryElement)
277{
278 QDomElement currentElement;
279 bool result = true;
280
281 // get entry id
282 int id = entryElement.attribute(KVTML_ID).toInt(&result);
283 if (!result) {
284 m_errorMessage = i18n("entry missing id");
285 return false;
286 }
287
289
290 // read info tags: inactive, inquery, and sizehint
291 currentElement = entryElement.firstChildElement(KVTML_DEACTIVATED);
292 if (!currentElement.isNull()) {
293 // set the active state of the expression
294 if (currentElement.text() == KVTML_TRUE) {
295 expr->setActive(false);
296 } else {
297 expr->setActive(true);
298 }
299 }
300
301 // read translation children
302 QDomNodeList translationList = entryElement.elementsByTagName(KVTML_TRANSLATION);
303
304 for (int i = 0; i < translationList.count(); ++i) {
305 currentElement = translationList.item(i).toElement();
306 if (currentElement.parentNode() == entryElement) {
307 result = readTranslation(currentElement, expr, i);
308 if (!result)
309 return false;
310 }
311 }
312
313 if (expr->translationIndices().size() == 0) {
314 qDebug() << "Found entry with no words in it." << id;
315 expr->setTranslation(0, QString());
316 }
317
318 Q_ASSERT(expr);
319
320 // TODO: probably should insert at id position with a check to see if it exists
321 // may be useful for detecting corrupt documents
322 m_allEntries[id] = expr;
323 return result;
324}
325
326bool KEduVocKvtml2Reader::readTranslation(QDomElement &translationElement, KEduVocExpression *expr, int index)
327{
328 // read the text, grade, declension and conjugation
329 expr->translation(index)->fromKVTML2(translationElement);
330 QDomElement currentElement;
331
332 // article grade
333 currentElement = translationElement.firstChildElement(KVTML_ARTICLE);
334 if (!currentElement.isNull()) {
335 KEduVocText article;
336 article.fromKVTML2(currentElement);
337 expr->translation(index)->setArticle(article);
338 }
339
340 // comparisons
341 currentElement = translationElement.firstChildElement(KVTML_COMPARISON);
342 if (!currentElement.isNull()) {
343 readComparison(currentElement, expr->translation(index));
344 }
345
346 // multiple choice
347 currentElement = translationElement.firstChildElement(KVTML_MULTIPLECHOICE);
348 if (!currentElement.isNull()) {
349 readMultipleChoice(currentElement, expr->translation(index));
350 }
351
352 // image
353 currentElement = translationElement.firstChildElement(KVTML_IMAGE);
354 if (!currentElement.isNull()) {
355 QUrl imageUrl(currentElement.text());
356 if (imageUrl.isLocalFile() && QDir::isRelativePath(imageUrl.toLocalFile())) {
357 imageUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + imageUrl.toLocalFile());
358 }
359 expr->translation(index)->setImageUrl(imageUrl);
360 }
361
362 // sound
363 currentElement = translationElement.firstChildElement(KVTML_SOUND);
364 if (!currentElement.isNull()) {
365 QUrl soundUrl(currentElement.text());
366 if (soundUrl.isLocalFile() && QDir::isRelativePath(soundUrl.toLocalFile())) {
367 soundUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + soundUrl.toLocalFile());
368 }
369 expr->translation(index)->setSoundUrl(soundUrl);
370 }
371
372 return true;
373}
374
375bool KEduVocKvtml2Reader::readChildLessons(KEduVocLesson *parentLesson, QDomElement &lessonElement)
376{
377 QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
378 while (!currentElement.isNull()) {
379 readLesson(parentLesson, currentElement);
380 currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
381 }
382 return true;
383}
384
385bool KEduVocKvtml2Reader::readLesson(KEduVocLesson *parentLesson, QDomElement &lessonElement)
386{
387 //<name>Lesson name</name>
388 QDomElement currentElement = lessonElement.firstChildElement(KVTML_NAME);
389 KEduVocLesson *lesson = new KEduVocLesson(currentElement.text(), parentLesson);
390 parentLesson->appendChildContainer(lesson);
391
392 readChildLessons(lesson, lessonElement);
393
394 //<query>true</query>
395 currentElement = lessonElement.firstChildElement(KVTML_INPRACTICE);
396 lesson->setInPractice(currentElement.text() == KVTML_TRUE);
397
398 //<entry id="123"/>
399 currentElement = lessonElement.firstChildElement(KVTML_ENTRY);
400 while (!currentElement.isNull()) {
401 bool result = false;
402 int entryId = currentElement.attribute(KVTML_ID).toInt(&result);
403 if (result) {
404 if (m_allEntries[entryId]) {
405 lesson->appendEntry(m_allEntries[entryId]);
406 }
407 }
408 currentElement = currentElement.nextSiblingElement(KVTML_ENTRY);
409 }
410 return true;
411}
412
413bool KEduVocKvtml2Reader::readSynonymsAntonymsFalseFriends(QDomElement &rootElement)
414{
415 QDomElement pairElement;
416 for (int type = KEduVocTranslation::Synonym; type <= KEduVocTranslation::FalseFriend; type++) {
417 switch (type) {
418 case KEduVocTranslation::Synonym:
419 pairElement = rootElement.firstChildElement(KVTML_SYNONYM);
420 break;
421 case KEduVocTranslation::Antonym:
422 pairElement = rootElement.firstChildElement(KVTML_ANTONYM);
423 break;
424 case KEduVocTranslation::FalseFriend:
425 pairElement = rootElement.firstChildElement(KVTML_FALSEFRIEND);
426 break;
427 }
428 // pair
429 pairElement = pairElement.firstChildElement(KVTML_PAIR);
430 while (!pairElement.isNull()) {
431 //<entry id="123"/>
432 QDomElement entryElement = pairElement.firstChildElement(KVTML_ENTRY);
433 int firstEntryId = entryElement.attribute(KVTML_ID).toInt();
434
435 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
436 int firstTranslationId = translationElement.attribute(KVTML_ID).toInt();
437
438 // second entry
439 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
440 int secondEntryId = entryElement.attribute(KVTML_ID).toInt();
441 translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
442 int secondTranslationId = translationElement.attribute(KVTML_ID).toInt();
443
444 // pair them up
445 KEduVocTranslation *first = m_allEntries[firstEntryId]->translation(firstTranslationId);
446 KEduVocTranslation *second = m_allEntries[secondEntryId]->translation(secondTranslationId);
447
448 switch (type) {
449 case KEduVocTranslation::Synonym:
450 first->addSynonym(second);
451 second->addSynonym(first);
452 break;
453 case KEduVocTranslation::Antonym:
454 first->addAntonym(second);
455 second->addAntonym(first);
456 break;
457 case KEduVocTranslation::FalseFriend:
458 first->addFalseFriend(second);
459 second->addFalseFriend(first);
460 break;
461 }
462 pairElement = pairElement.nextSiblingElement(KVTML_PAIR);
463 }
464 }
465 return true;
466}
467
468bool KEduVocKvtml2Reader::readArticle(QDomElement &articleElement, int identifierNum)
469/*
470 <article>
471 <singular>
472 <definite>
473 <male>der</male>
474 <female>die</female>
475 <neutral>das</neutral>
476 </definite>
477 <indefinite>
478 <male>ein</male>
479 <female>eine</female>
480 <neutral>ein</neutral>
481 </indefinite>
482 </singular>
483 <dual>
484 </dual>
485 </article>
486*/
487{
489 numbers[0] = KEduVocWordFlag::Singular;
490 numbers[1] = KEduVocWordFlag::Dual;
491 numbers[2] = KEduVocWordFlag::Plural;
493 genders[0] = KEduVocWordFlag::Masculine;
494 genders[1] = KEduVocWordFlag::Feminine;
495 genders[2] = KEduVocWordFlag::Neuter;
497 defs[0] = KEduVocWordFlag::Definite;
498 defs[1] = KEduVocWordFlag::Indefinite;
499
500 for (int num = 0; num <= 2; ++num) {
501 QDomElement numberElement = articleElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[num]);
502 if (!numberElement.isNull()) {
503 // definite
504 for (int def = 0; def <= 1; ++def) {
505 QDomElement defElement = numberElement.firstChildElement(KVTML_GRAMMATICAL_DEFINITENESS[def]);
506 if (!defElement.isNull()) {
507 // male
508 for (int gen = 0; gen <= 2; ++gen) {
509 QDomElement genderElement = defElement.firstChildElement(KVTML_GRAMMATICAL_GENDER[gen]);
510 if (!genderElement.isNull()) {
511 m_doc->identifier(identifierNum).article().setArticle(genderElement.text(), numbers[num] | defs[def] | genders[gen]);
512 }
513 }
514 }
515 }
516 }
517 }
518
519 return true;
520}
521
522bool KEduVocKvtml2Reader::readChildWordTypes(KEduVocWordType *parentContainer, QDomElement &lessonElement)
523{
524 QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
525 while (!currentElement.isNull()) {
526 readWordType(parentContainer, currentElement);
527 currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
528 }
529 return true;
530}
531
532bool KEduVocKvtml2Reader::readLeitner(KEduVocLeitnerBox *parentContainer, QDomElement &leitnerParentElement)
533{
534 QDomElement leitnerElement = leitnerParentElement.firstChildElement(KVTML_CONTAINER);
535 while (!leitnerElement.isNull()) {
536 QString name = leitnerElement.firstChildElement(KVTML_NAME).text();
537
538 KEduVocLeitnerBox *leitner = new KEduVocLeitnerBox(name, parentContainer);
539 parentContainer->appendChildContainer(leitner);
540 // for leitner we only allow a flat list, no sub boxes.
541
542 // read entries
543 QDomElement entryElement = leitnerElement.firstChildElement(KVTML_ENTRY);
544 while (!entryElement.isNull()) {
545 // read <entry id="123"></entryid>
546 int entryId = entryElement.attribute(KVTML_ID).toInt();
547 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
548 while (!translationElement.isNull()) {
549 // <translation id="234"/>
550 int translationId = translationElement.attribute(KVTML_ID).toInt();
551 m_allEntries.value(entryId)->translation(translationId)->setLeitnerBox(leitner);
552 translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
553 }
554 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
555 }
556 leitnerElement = leitnerElement.nextSiblingElement(KVTML_CONTAINER);
557 }
558 return true;
559}
560
561bool KEduVocKvtml2Reader::readWordType(KEduVocWordType *parentContainer, QDomElement &typeElement)
562{
563 // set type and specialtype
564 QString typeName = typeElement.firstChildElement(KVTML_NAME).text();
565
566 KEduVocWordType *wordTypeContainer = new KEduVocWordType(typeName, parentContainer);
567 parentContainer->appendChildContainer(wordTypeContainer);
568
569 QString specialType = typeElement.firstChildElement(KVTML_SPECIALWORDTYPE).text();
570 if (!specialType.isEmpty()) {
571 // get the localized version
572 if (specialType == KVTML_SPECIALWORDTYPE_NOUN) {
573 wordTypeContainer->setWordType(KEduVocWordFlag::Noun);
574 }
575 if (specialType == KVTML_SPECIALWORDTYPE_VERB) {
576 wordTypeContainer->setWordType(KEduVocWordFlag::Verb);
577 }
578 if (specialType == KVTML_SPECIALWORDTYPE_ADVERB) {
579 wordTypeContainer->setWordType(KEduVocWordFlag::Adverb);
580 }
581 if (specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE) {
582 wordTypeContainer->setWordType(KEduVocWordFlag::Adjective);
583 }
584 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_MALE) {
585 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine);
586 }
587 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE) {
588 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine);
589 }
590 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL) {
591 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter);
592 }
593 if (specialType == KVTML_SPECIALWORDTYPE_CONJUNCTION) {
594 wordTypeContainer->setWordType(KEduVocWordFlag::Conjunction);
595 }
596 } // special type
597
598 // read entries
599 QDomElement entryElement = typeElement.firstChildElement(KVTML_ENTRY);
600 while (!entryElement.isNull()) {
601 // read <entry id="123"></entryid>
602 int entryId = entryElement.attribute(KVTML_ID).toInt();
603 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
604 while (!translationElement.isNull()) {
605 // <translation id="234"/>
606 int translationId = translationElement.attribute(KVTML_ID).toInt();
607 m_allEntries.value(entryId)->translation(translationId)->setWordType(wordTypeContainer);
608 translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
609 }
610 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
611 }
612
613 readChildWordTypes(wordTypeContainer, typeElement);
614
615 return true;
616}
617
618QStringList KEduVocKvtml2Reader::readTenses(QDomElement &tensesElement)
619{
620 QStringList tenses;
621
622 QDomNodeList tenseNodes = tensesElement.elementsByTagName(KVTML_TENSE);
623 for (int i = 0; i < tenseNodes.count(); ++i) {
624 QDomElement currentElement = tenseNodes.item(i).toElement();
625 if (currentElement.parentNode() == tensesElement) {
626 tenses.append(currentElement.text());
627 }
628 }
629
630 return tenses;
631}
632
633bool KEduVocKvtml2Reader::readComparison(QDomElement &domElementParent, KEduVocTranslation *translation)
634/*
635 <comparison>
636 <comparative>better</comparative>
637 <superlative>best</superlative>
638 </comparison>
639*/
640{
641 QDomElement currentElement;
642
643 currentElement = domElementParent.firstChildElement(KVTML_COMPARATIVE);
644 if (!currentElement.isNull()) {
645 KEduVocText comparative;
646 comparative.fromKVTML2(currentElement);
647
648 // be compatible for KDE < 4.5
649 if (comparative.text().isEmpty()) {
650 comparative.setText(currentElement.text());
651 }
652 translation->setComparativeForm(comparative);
653 }
654
655 currentElement = domElementParent.firstChildElement(KVTML_SUPERLATIVE);
656 if (!currentElement.isNull()) {
657 KEduVocText superlative;
658 superlative.fromKVTML2(currentElement);
659
660 // be compatible for KDE < 4.5
661 if (superlative.text().isEmpty()) {
662 superlative.setText(currentElement.text());
663 }
664 translation->setSuperlativeForm(superlative);
665 }
666 return true;
667}
668
669bool KEduVocKvtml2Reader::readMultipleChoice(QDomElement &multipleChoiceElement, KEduVocTranslation *translation)
670/*
671 <multiplechoice>
672 <choice>good</choice>
673 <choice>better</choice>
674 <choice>best</choice>
675 <choice>best 2</choice>
676 <choice>best 3</choice>
677 </multiplechoice>
678*/
679{
680 QDomElement currentElement;
681 QDomNodeList choiceNodes = multipleChoiceElement.elementsByTagName(KVTML_CHOICE);
682 for (int i = 0; i < choiceNodes.count(); ++i) {
683 currentElement = choiceNodes.item(i).toElement();
684 if (currentElement.parentNode() == multipleChoiceElement) {
685 QStringList choices = translation->getMultipleChoice();
686 choices.append(currentElement.text());
687 translation->setMultipleChoice(choices);
688 }
689 }
690 return true;
691}
692
693bool KEduVocKvtml2Reader::readPersonalPronoun(QDomElement &pronounElement, KEduVocPersonalPronoun &pronoun)
694{
695 pronoun.setMaleFemaleDifferent(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_MALE_FEMALE_DIFFERENT).isNull());
696 pronoun.setNeutralExists(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_NEUTRAL_EXISTS).isNull());
697 pronoun.setDualExists(!pronounElement.firstChildElement(KVTML_DUAL_EXISTS).isNull());
698
699 QDomElement personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[0]);
700 if (!personElement.isNull()) {
701 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Singular);
702 }
703
704 personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[1]);
705 if (!personElement.isNull()) {
706 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Dual);
707 }
708
709 personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[2]);
710 if (!personElement.isNull()) {
711 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Plural);
712 }
713 return true;
714}
715
716bool KEduVocKvtml2Reader::readPersonalPronounChild(QDomElement &personElement, KEduVocPersonalPronoun &pronoun, KEduVocWordFlags number)
717{
719 persons[0] = KEduVocWordFlag::First;
720 persons[1] = KEduVocWordFlag::Second;
721 persons[2] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Masculine);
722 persons[3] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Feminine);
723 persons[4] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Neuter);
724
725 for (int person = 0; person < 5; person++) {
726 QDomElement currentElement = personElement.firstChildElement(KVTML_GRAMMATICAL_PERSON[person]);
727 pronoun.setPersonalPronoun(currentElement.text(), persons[person] | number);
728 }
729
730 return true;
731}
732
733#include "moc_keduvockvtml2reader.cpp"
The primary entry point to the hierarchy of objects describing vocabularies.
void setGenerator(const QString &generator)
Sets the generator of the file.
int appendIdentifier(const KEduVocIdentifier &identifier=KEduVocIdentifier())
Appends a new identifier (usually a language)
int identifierCount() const
void setTitle(const QString &title)
Set the title of the file.
void setDocumentComment(const QString &comment)
Set the comment of the file.
void setAuthor(const QString &author)
Set the author of the file.
KEduVocWordType * wordTypeContainer()
Returns the root word type object.
KEduVocLesson * lesson()
Get the lesson root object.
ErrorCode
the return code when opening/saving
@ InvalidXml
malformed xml or bad file formatting
@ FileTypeUnknown
unknown file type
@ FileReaderFailed
file reader failed
KEduVocLeitnerBox * leitnerContainer()
Returns the root Leitner container.
KEduVocIdentifier & identifier(int index)
Returns the identifier of translation index.
void setLicense(const QString &license)
Set the license of the file.
void setCategory(const QString &category)
Set the category of the file.
FileType
known vocabulary file types
@ Kvtml
Kvtml 2.0.
QString generator() const
void setAuthorContact(const QString &authorContact)
Set the author contact info.
void setVersion(const QString &ver)
Sets version of the loaded file.
This class contains one vocabulary expression as an original with one or more translations.
void setTranslation(int index, const QString &expression)
Add a translation to this expression.
KEduVocLesson * lesson() const
return the lesson
void setActive(bool flag=true)
set entry active (enabled for queries)
KEduVocTranslation * translation(int index)
Get a pointer to the translation.
Class to store meta information about a language or any other category in the vocabulary.
KEduVocArticle & article() const
Articles (a, the in English, el, la,... in Spanish)
void setPersonalPronouns(const KEduVocPersonalPronoun &pronouns)
Sets personal pronouns.
void setLocale(const QString &name)
Set the locale.
void setName(const QString &name)
Set the name.
bool isParsable() override
Can this reader parse this file.
KEduVocDocument::ErrorCode read(KEduVocDocument &doc) override
Parse file and write into doc.
KEduVocDocument::FileType fileTypeHandled() override
returns the KEduVocDocument::FileType that this reader handles
KEduVocKvtml2Reader(QIODevice &file)
constructor
Reader for KVTML 1.0.
virtual QString errorMessage() const
an error message.
virtual KEduVocDocument::ErrorCode read(KEduVocDocument &doc)
Parse file and write into doc.
Leitner Boxes are an alternative grading system.
class to store information about a lesson
int entryCount(EnumEntriesRecursive recursive=NotRecursive) override
get the number of entries in the lesson
void appendEntry(KEduVocExpression *entry)
append an entry to the lesson
The conjugation of a verb.
A text in vocabulary documents.
Definition keduvoctext.h:50
QString text() const
The translation as string (the word itself)
void setText(const QString &expr)
Sets the translation.
void setSoundUrl(const QUrl &url)
Set the sound url for this translation.
QStringList getMultipleChoice() const
Returns multiple choice if available.
void addAntonym(KEduVocTranslation *antonym)
Add a antonym.
void addFalseFriend(KEduVocTranslation *falseFriend)
Add a false friend.
void setMultipleChoice(const QStringList &choices)
Sets multiple choice.
void addSynonym(KEduVocTranslation *synonym)
Add a synonym.
void fromKVTML2(QDomElement &parent)
void setImageUrl(const QUrl &url)
Set the image url for this translation.
class to store translation word types
void setWordType(KEduVocWordFlags flags)
assignment operator
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
KIOCORE_EXPORT QString number(KIO::filesize_t size)
QString name(StandardAction id)
KOSM_EXPORT const char * typeName(Type type)
bool isRelativePath(const QString &path)
QDomElement documentElement() const const
ParseResult setContent(QAnyStringView text, ParseOptions options)
QString attribute(const QString &name, const QString &defValue) const const
QDomNodeList elementsByTagName(const QString &tagname) const const
QString tagName() const const
QString text() const const
QDomElement firstChildElement(const QString &tagName, const QString &namespaceURI) const const
bool isNull() const const
QDomElement nextSiblingElement(const QString &tagName, const QString &namespaceURI) const const
QDomNode parentNode() const const
QDomElement toElement() const const
int count() const const
QDomNode item(int index) const const
int length() const const
virtual bool seek(qint64 pos)
void append(QList< T > &&value)
bool isEmpty() const const
qsizetype size() const const
T value(const Key &key, const T &defaultValue) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
float toFloat(bool *ok) const const
int toInt(bool *ok, int base) const const
QString readLine(qint64 maxlen)
RemoveFilename
QString toString(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:55:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.