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 const QDomDocument::ParseResult parseResult = domDoc.setContent(m_inputFile);
54 if (!parseResult) {
55 qDebug() << "Unable to load document.Parse error in line " << parseResult.errorLine << ", col " << parseResult.errorColumn << ": "
56 << qPrintable(parseResult.errorMessage);
58 }
59
60 QDomElement domElementKvtml = domDoc.documentElement();
61 if (domElementKvtml.tagName() != KVTML_TAG) {
62 m_errorMessage = i18n("This is not a KDE Vocabulary document.");
64 }
65
66 if (domElementKvtml.attribute(KVTML_VERSION).toFloat() < 2.0) {
67 // read the file with the old format
68
69 // first reset the file to the beginning
70 m_inputFile->seek(0);
71 KEduVocKvtmlReader oldFormat(*m_inputFile);
72
73 // get the return value
74 KEduVocDocument::ErrorCode retval = oldFormat.read(doc);
75
76 // pass the errormessage up
77 m_errorMessage = oldFormat.errorMessage();
78 return retval;
79 }
80
81 //-------------------------------------------------------------------------
82 // Information
83 //-------------------------------------------------------------------------
84
85 QDomElement info = domElementKvtml.firstChildElement(KVTML_INFORMATION);
86 if (!info.isNull()) {
87 if (!readInformation(info))
89 }
90
91 bool result = readGroups(domElementKvtml); // read sub-groups
92
94}
95
96bool KEduVocKvtml2Reader::readInformation(QDomElement &informationElement)
97{
98 // read the generator
99 QDomElement currentElement = informationElement.firstChildElement(KVTML_GENERATOR);
100 if (!currentElement.isNull()) {
101 m_doc->setGenerator(currentElement.text());
102 // add the version if it's there
103 int pos = m_doc->generator().lastIndexOf(KVD_VERS_PREFIX);
104 if (pos >= 0) {
105 m_doc->setVersion(m_doc->generator().remove(0, pos + 2));
106 }
107 }
108
109 // read the title
110 currentElement = informationElement.firstChildElement(KVTML_TITLE);
111 if (!currentElement.isNull()) {
112 m_doc->setTitle(currentElement.text());
113 }
114
115 // read the author
116 currentElement = informationElement.firstChildElement(KVTML_AUTHOR);
117 if (!currentElement.isNull()) {
118 m_doc->setAuthor(currentElement.text());
119 }
120
121 currentElement = informationElement.firstChildElement(KVTML_AUTHORCONTACT);
122 if (!currentElement.isNull()) {
123 m_doc->setAuthorContact(currentElement.text());
124 }
125
126 // read the license
127 currentElement = informationElement.firstChildElement(KVTML_LICENSE);
128 if (!currentElement.isNull()) {
129 m_doc->setLicense(currentElement.text());
130 }
131
132 // read the comment
133 currentElement = informationElement.firstChildElement(KVTML_COMMENT);
134 if (!currentElement.isNull()) {
135 m_doc->setDocumentComment(currentElement.text());
136 }
137
138 // read the category
139 currentElement = informationElement.firstChildElement(KVTML_CATEGORY);
140 if (!currentElement.isNull()) {
141 m_doc->setCategory(currentElement.text());
142 }
143
144 return true;
145}
146
147bool KEduVocKvtml2Reader::readGroups(QDomElement &domElementParent)
148{
149 bool result = false;
150
151 QDomElement groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);
152
153 QDomElement currentElement;
154
155 // ensure backwards compatibility - in kde 4.1 and earlier tenses were direct properties of the document class.
156 // now they are moved into the individual identifiers
157 QStringList tensesCompability;
158 groupElement = groupElement.firstChildElement(KVTML_TENSES);
159 if (!groupElement.isNull()) {
160 tensesCompability = readTenses(groupElement);
161 }
162
163 groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);
164 if (!groupElement.isNull()) {
165 QDomNodeList entryList = groupElement.elementsByTagName(KVTML_IDENTIFIER);
166 if (entryList.length() <= 0) {
167 m_errorMessage = i18n("missing identifier elements from identifiers tag");
168 return false;
169 }
170
171 for (int i = 0; i < entryList.count(); ++i) {
172 currentElement = entryList.item(i).toElement();
173 if (currentElement.parentNode() == groupElement) {
174 result = readIdentifier(currentElement);
175 if (!result) {
176 return false;
177 }
178 if (!tensesCompability.isEmpty()) {
179 m_doc->identifier(i).setTenseList(tensesCompability);
180 }
181 }
182 }
183 }
184
185 groupElement = domElementParent.firstChildElement(KVTML_ENTRIES);
186 if (!groupElement.isNull()) {
187 QDomNodeList entryList = groupElement.elementsByTagName(KVTML_ENTRY);
188 for (int i = 0; i < entryList.count(); ++i) {
189 currentElement = entryList.item(i).toElement();
190 if (currentElement.parentNode() == groupElement) {
191 result = readEntry(currentElement);
192 if (!result)
193 return false;
194 }
195 }
196 }
197
198 readSynonymsAntonymsFalseFriends(domElementParent);
199
200 groupElement = domElementParent.firstChildElement(KVTML_WORDTYPES);
201 if (!groupElement.isNull()) {
202 readChildWordTypes(m_doc->wordTypeContainer(), groupElement);
203 }
204
205 groupElement = domElementParent.firstChildElement(KVTML_LEITNERBOXES);
206 if (!groupElement.isNull()) {
207 readLeitner(m_doc->leitnerContainer(), groupElement);
208 }
209
210 groupElement = domElementParent.firstChildElement(KVTML_LESSONS);
211 if (!groupElement.isNull()) {
212 readChildLessons(m_doc->lesson(), groupElement);
213 }
214
215 // Additional cleanup: Put orphaned entries without a lesson into a default lesson.
216 KEduVocLesson *defaultLesson = new KEduVocLesson(i18n("Default Lesson"), m_doc->lesson());
217
218 // now make sure we don't have any orphan entries
219 foreach (KEduVocExpression *entry, m_allEntries) {
220 if (!entry->lesson()) {
221 defaultLesson->appendEntry(entry);
222 }
223 }
224
225 if (defaultLesson->entryCount() > 0) {
226 m_doc->lesson()->appendChildContainer(defaultLesson);
227 } else {
228 delete defaultLesson;
229 }
230
231 return true;
232}
233
234bool KEduVocKvtml2Reader::readIdentifier(QDomElement &identifierElement)
235{
236 bool result = true;
237 int id = identifierElement.attribute(KVTML_ID).toInt(&result);
238 if (!result) {
239 m_errorMessage = i18n("identifier missing id");
240 return false;
241 }
242
243 // generate empty identifiers in the doc
244 for (int i = m_doc->identifierCount(); i <= id; i++) {
246 }
247
248 // the first element, create the identifier, even if empty
249 QDomElement currentElement = identifierElement.firstChildElement(KVTML_NAME);
250 m_doc->identifier(id).setName(currentElement.text());
251
252 currentElement = identifierElement.firstChildElement(KVTML_LOCALE);
253 m_doc->identifier(id).setLocale(currentElement.text());
254
255 currentElement = identifierElement.firstChildElement(KVTML_IDENTIFIERTYPE);
256 if (!currentElement.isNull()) {
257 // TODO: do something with the type
258 }
259
260 // read sub-parts
261 currentElement = identifierElement.firstChildElement(KVTML_ARTICLE);
262 if (!currentElement.isNull()) {
263 readArticle(currentElement, id);
264 }
265
266 currentElement = identifierElement.firstChildElement(KVTML_PERSONALPRONOUNS);
267 if (!currentElement.isNull()) {
268 KEduVocPersonalPronoun personalPronoun;
269 readPersonalPronoun(currentElement, personalPronoun);
270 m_doc->identifier(id).setPersonalPronouns(personalPronoun);
271 }
272
273 QStringList tenses = readTenses(identifierElement);
274
275 m_doc->identifier(id).setTenseList(tenses);
276
277 return result;
278}
279
280bool KEduVocKvtml2Reader::readEntry(QDomElement &entryElement)
281{
282 QDomElement currentElement;
283 bool result = true;
284
285 // get entry id
286 int id = entryElement.attribute(KVTML_ID).toInt(&result);
287 if (!result) {
288 m_errorMessage = i18n("entry missing id");
289 return false;
290 }
291
293
294 // read info tags: inactive, inquery, and sizehint
295 currentElement = entryElement.firstChildElement(KVTML_DEACTIVATED);
296 if (!currentElement.isNull()) {
297 // set the active state of the expression
298 if (currentElement.text() == KVTML_TRUE) {
299 expr->setActive(false);
300 } else {
301 expr->setActive(true);
302 }
303 }
304
305 // read translation children
306 QDomNodeList translationList = entryElement.elementsByTagName(KVTML_TRANSLATION);
307
308 for (int i = 0; i < translationList.count(); ++i) {
309 currentElement = translationList.item(i).toElement();
310 if (currentElement.parentNode() == entryElement) {
311 result = readTranslation(currentElement, expr, i);
312 if (!result)
313 return false;
314 }
315 }
316
317 if (expr->translationIndices().size() == 0) {
318 qDebug() << "Found entry with no words in it." << id;
319 expr->setTranslation(0, QString());
320 }
321
322 Q_ASSERT(expr);
323
324 // TODO: probably should insert at id position with a check to see if it exists
325 // may be useful for detecting corrupt documents
326 m_allEntries[id] = expr;
327 return result;
328}
329
330bool KEduVocKvtml2Reader::readTranslation(QDomElement &translationElement, KEduVocExpression *expr, int index)
331{
332 // read the text, grade, declension and conjugation
333 expr->translation(index)->fromKVTML2(translationElement);
334 QDomElement currentElement;
335
336 // article grade
337 currentElement = translationElement.firstChildElement(KVTML_ARTICLE);
338 if (!currentElement.isNull()) {
339 KEduVocText article;
340 article.fromKVTML2(currentElement);
341 expr->translation(index)->setArticle(article);
342 }
343
344 // comparisons
345 currentElement = translationElement.firstChildElement(KVTML_COMPARISON);
346 if (!currentElement.isNull()) {
347 readComparison(currentElement, expr->translation(index));
348 }
349
350 // multiple choice
351 currentElement = translationElement.firstChildElement(KVTML_MULTIPLECHOICE);
352 if (!currentElement.isNull()) {
353 readMultipleChoice(currentElement, expr->translation(index));
354 }
355
356 // image
357 currentElement = translationElement.firstChildElement(KVTML_IMAGE);
358 if (!currentElement.isNull()) {
359 QUrl imageUrl(currentElement.text());
360 if (imageUrl.isLocalFile() && QDir::isRelativePath(imageUrl.toLocalFile())) {
361 imageUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + imageUrl.toLocalFile());
362 }
363 expr->translation(index)->setImageUrl(imageUrl);
364 }
365
366 // sound
367 currentElement = translationElement.firstChildElement(KVTML_SOUND);
368 if (!currentElement.isNull()) {
369 QUrl soundUrl(currentElement.text());
370 if (soundUrl.isLocalFile() && QDir::isRelativePath(soundUrl.toLocalFile())) {
371 soundUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + soundUrl.toLocalFile());
372 }
373 expr->translation(index)->setSoundUrl(soundUrl);
374 }
375
376 return true;
377}
378
379bool KEduVocKvtml2Reader::readChildLessons(KEduVocLesson *parentLesson, QDomElement &lessonElement)
380{
381 QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
382 while (!currentElement.isNull()) {
383 readLesson(parentLesson, currentElement);
384 currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
385 }
386 return true;
387}
388
389bool KEduVocKvtml2Reader::readLesson(KEduVocLesson *parentLesson, QDomElement &lessonElement)
390{
391 //<name>Lesson name</name>
392 QDomElement currentElement = lessonElement.firstChildElement(KVTML_NAME);
393 KEduVocLesson *lesson = new KEduVocLesson(currentElement.text(), parentLesson);
394 parentLesson->appendChildContainer(lesson);
395
396 readChildLessons(lesson, lessonElement);
397
398 //<query>true</query>
399 currentElement = lessonElement.firstChildElement(KVTML_INPRACTICE);
400 lesson->setInPractice(currentElement.text() == KVTML_TRUE);
401
402 //<entry id="123"/>
403 currentElement = lessonElement.firstChildElement(KVTML_ENTRY);
404 while (!currentElement.isNull()) {
405 bool result = false;
406 int entryId = currentElement.attribute(KVTML_ID).toInt(&result);
407 if (result) {
408 if (m_allEntries[entryId]) {
409 lesson->appendEntry(m_allEntries[entryId]);
410 }
411 }
412 currentElement = currentElement.nextSiblingElement(KVTML_ENTRY);
413 }
414 return true;
415}
416
417bool KEduVocKvtml2Reader::readSynonymsAntonymsFalseFriends(QDomElement &rootElement)
418{
419 QDomElement pairElement;
420 for (int type = KEduVocTranslation::Synonym; type <= KEduVocTranslation::FalseFriend; type++) {
421 switch (type) {
422 case KEduVocTranslation::Synonym:
423 pairElement = rootElement.firstChildElement(KVTML_SYNONYM);
424 break;
425 case KEduVocTranslation::Antonym:
426 pairElement = rootElement.firstChildElement(KVTML_ANTONYM);
427 break;
428 case KEduVocTranslation::FalseFriend:
429 pairElement = rootElement.firstChildElement(KVTML_FALSEFRIEND);
430 break;
431 }
432 // pair
433 pairElement = pairElement.firstChildElement(KVTML_PAIR);
434 while (!pairElement.isNull()) {
435 //<entry id="123"/>
436 QDomElement entryElement = pairElement.firstChildElement(KVTML_ENTRY);
437 int firstEntryId = entryElement.attribute(KVTML_ID).toInt();
438
439 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
440 int firstTranslationId = translationElement.attribute(KVTML_ID).toInt();
441
442 // second entry
443 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
444 int secondEntryId = entryElement.attribute(KVTML_ID).toInt();
445 translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
446 int secondTranslationId = translationElement.attribute(KVTML_ID).toInt();
447
448 // pair them up
449 KEduVocTranslation *first = m_allEntries[firstEntryId]->translation(firstTranslationId);
450 KEduVocTranslation *second = m_allEntries[secondEntryId]->translation(secondTranslationId);
451
452 switch (type) {
453 case KEduVocTranslation::Synonym:
454 first->addSynonym(second);
455 second->addSynonym(first);
456 break;
457 case KEduVocTranslation::Antonym:
458 first->addAntonym(second);
459 second->addAntonym(first);
460 break;
461 case KEduVocTranslation::FalseFriend:
462 first->addFalseFriend(second);
463 second->addFalseFriend(first);
464 break;
465 }
466 pairElement = pairElement.nextSiblingElement(KVTML_PAIR);
467 }
468 }
469 return true;
470}
471
472bool KEduVocKvtml2Reader::readArticle(QDomElement &articleElement, int identifierNum)
473/*
474 <article>
475 <singular>
476 <definite>
477 <male>der</male>
478 <female>die</female>
479 <neutral>das</neutral>
480 </definite>
481 <indefinite>
482 <male>ein</male>
483 <female>eine</female>
484 <neutral>ein</neutral>
485 </indefinite>
486 </singular>
487 <dual>
488 </dual>
489 </article>
490*/
491{
493 numbers[0] = KEduVocWordFlag::Singular;
494 numbers[1] = KEduVocWordFlag::Dual;
495 numbers[2] = KEduVocWordFlag::Plural;
497 genders[0] = KEduVocWordFlag::Masculine;
498 genders[1] = KEduVocWordFlag::Feminine;
499 genders[2] = KEduVocWordFlag::Neuter;
501 defs[0] = KEduVocWordFlag::Definite;
502 defs[1] = KEduVocWordFlag::Indefinite;
503
504 for (int num = 0; num <= 2; ++num) {
505 QDomElement numberElement = articleElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[num]);
506 if (!numberElement.isNull()) {
507 // definite
508 for (int def = 0; def <= 1; ++def) {
509 QDomElement defElement = numberElement.firstChildElement(KVTML_GRAMMATICAL_DEFINITENESS[def]);
510 if (!defElement.isNull()) {
511 // male
512 for (int gen = 0; gen <= 2; ++gen) {
513 QDomElement genderElement = defElement.firstChildElement(KVTML_GRAMMATICAL_GENDER[gen]);
514 if (!genderElement.isNull()) {
515 m_doc->identifier(identifierNum).article().setArticle(genderElement.text(), numbers[num] | defs[def] | genders[gen]);
516 }
517 }
518 }
519 }
520 }
521 }
522
523 return true;
524}
525
526bool KEduVocKvtml2Reader::readChildWordTypes(KEduVocWordType *parentContainer, QDomElement &lessonElement)
527{
528 QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
529 while (!currentElement.isNull()) {
530 readWordType(parentContainer, currentElement);
531 currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
532 }
533 return true;
534}
535
536bool KEduVocKvtml2Reader::readLeitner(KEduVocLeitnerBox *parentContainer, QDomElement &leitnerParentElement)
537{
538 QDomElement leitnerElement = leitnerParentElement.firstChildElement(KVTML_CONTAINER);
539 while (!leitnerElement.isNull()) {
540 QString name = leitnerElement.firstChildElement(KVTML_NAME).text();
541
542 KEduVocLeitnerBox *leitner = new KEduVocLeitnerBox(name, parentContainer);
543 parentContainer->appendChildContainer(leitner);
544 // for leitner we only allow a flat list, no sub boxes.
545
546 // read entries
547 QDomElement entryElement = leitnerElement.firstChildElement(KVTML_ENTRY);
548 while (!entryElement.isNull()) {
549 // read <entry id="123"></entryid>
550 int entryId = entryElement.attribute(KVTML_ID).toInt();
551 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
552 while (!translationElement.isNull()) {
553 // <translation id="234"/>
554 int translationId = translationElement.attribute(KVTML_ID).toInt();
555 m_allEntries.value(entryId)->translation(translationId)->setLeitnerBox(leitner);
556 translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
557 }
558 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
559 }
560 leitnerElement = leitnerElement.nextSiblingElement(KVTML_CONTAINER);
561 }
562 return true;
563}
564
565bool KEduVocKvtml2Reader::readWordType(KEduVocWordType *parentContainer, QDomElement &typeElement)
566{
567 // set type and specialtype
568 QString typeName = typeElement.firstChildElement(KVTML_NAME).text();
569
570 KEduVocWordType *wordTypeContainer = new KEduVocWordType(typeName, parentContainer);
571 parentContainer->appendChildContainer(wordTypeContainer);
572
573 QString specialType = typeElement.firstChildElement(KVTML_SPECIALWORDTYPE).text();
574 if (!specialType.isEmpty()) {
575 // get the localized version
576 if (specialType == KVTML_SPECIALWORDTYPE_NOUN) {
577 wordTypeContainer->setWordType(KEduVocWordFlag::Noun);
578 }
579 if (specialType == KVTML_SPECIALWORDTYPE_VERB) {
580 wordTypeContainer->setWordType(KEduVocWordFlag::Verb);
581 }
582 if (specialType == KVTML_SPECIALWORDTYPE_ADVERB) {
583 wordTypeContainer->setWordType(KEduVocWordFlag::Adverb);
584 }
585 if (specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE) {
586 wordTypeContainer->setWordType(KEduVocWordFlag::Adjective);
587 }
588 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_MALE) {
589 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine);
590 }
591 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE) {
592 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine);
593 }
594 if (specialType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL) {
595 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter);
596 }
597 if (specialType == KVTML_SPECIALWORDTYPE_CONJUNCTION) {
598 wordTypeContainer->setWordType(KEduVocWordFlag::Conjunction);
599 }
600 } // special type
601
602 // read entries
603 QDomElement entryElement = typeElement.firstChildElement(KVTML_ENTRY);
604 while (!entryElement.isNull()) {
605 // read <entry id="123"></entryid>
606 int entryId = entryElement.attribute(KVTML_ID).toInt();
607 QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
608 while (!translationElement.isNull()) {
609 // <translation id="234"/>
610 int translationId = translationElement.attribute(KVTML_ID).toInt();
611 m_allEntries.value(entryId)->translation(translationId)->setWordType(wordTypeContainer);
612 translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
613 }
614 entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
615 }
616
617 readChildWordTypes(wordTypeContainer, typeElement);
618
619 return true;
620}
621
622QStringList KEduVocKvtml2Reader::readTenses(QDomElement &tensesElement)
623{
624 QStringList tenses;
625
626 QDomNodeList tenseNodes = tensesElement.elementsByTagName(KVTML_TENSE);
627 for (int i = 0; i < tenseNodes.count(); ++i) {
628 QDomElement currentElement = tenseNodes.item(i).toElement();
629 if (currentElement.parentNode() == tensesElement) {
630 tenses.append(currentElement.text());
631 }
632 }
633
634 return tenses;
635}
636
637bool KEduVocKvtml2Reader::readComparison(QDomElement &domElementParent, KEduVocTranslation *translation)
638/*
639 <comparison>
640 <comparative>better</comparative>
641 <superlative>best</superlative>
642 </comparison>
643*/
644{
645 QDomElement currentElement;
646
647 currentElement = domElementParent.firstChildElement(KVTML_COMPARATIVE);
648 if (!currentElement.isNull()) {
649 KEduVocText comparative;
650 comparative.fromKVTML2(currentElement);
651
652 // be compatible for KDE < 4.5
653 if (comparative.text().isEmpty()) {
654 comparative.setText(currentElement.text());
655 }
656 translation->setComparativeForm(comparative);
657 }
658
659 currentElement = domElementParent.firstChildElement(KVTML_SUPERLATIVE);
660 if (!currentElement.isNull()) {
661 KEduVocText superlative;
662 superlative.fromKVTML2(currentElement);
663
664 // be compatible for KDE < 4.5
665 if (superlative.text().isEmpty()) {
666 superlative.setText(currentElement.text());
667 }
668 translation->setSuperlativeForm(superlative);
669 }
670 return true;
671}
672
673bool KEduVocKvtml2Reader::readMultipleChoice(QDomElement &multipleChoiceElement, KEduVocTranslation *translation)
674/*
675 <multiplechoice>
676 <choice>good</choice>
677 <choice>better</choice>
678 <choice>best</choice>
679 <choice>best 2</choice>
680 <choice>best 3</choice>
681 </multiplechoice>
682*/
683{
684 QDomElement currentElement;
685 QDomNodeList choiceNodes = multipleChoiceElement.elementsByTagName(KVTML_CHOICE);
686 for (int i = 0; i < choiceNodes.count(); ++i) {
687 currentElement = choiceNodes.item(i).toElement();
688 if (currentElement.parentNode() == multipleChoiceElement) {
689 QStringList choices = translation->getMultipleChoice();
690 choices.append(currentElement.text());
691 translation->setMultipleChoice(choices);
692 }
693 }
694 return true;
695}
696
697bool KEduVocKvtml2Reader::readPersonalPronoun(QDomElement &pronounElement, KEduVocPersonalPronoun &pronoun)
698{
699 pronoun.setMaleFemaleDifferent(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_MALE_FEMALE_DIFFERENT).isNull());
700 pronoun.setNeutralExists(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_NEUTRAL_EXISTS).isNull());
701 pronoun.setDualExists(!pronounElement.firstChildElement(KVTML_DUAL_EXISTS).isNull());
702
703 QDomElement personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[0]);
704 if (!personElement.isNull()) {
705 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Singular);
706 }
707
708 personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[1]);
709 if (!personElement.isNull()) {
710 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Dual);
711 }
712
713 personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[2]);
714 if (!personElement.isNull()) {
715 readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Plural);
716 }
717 return true;
718}
719
720bool KEduVocKvtml2Reader::readPersonalPronounChild(QDomElement &personElement, KEduVocPersonalPronoun &pronoun, KEduVocWordFlags number)
721{
723 persons[0] = KEduVocWordFlag::First;
724 persons[1] = KEduVocWordFlag::Second;
725 persons[2] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Masculine);
726 persons[3] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Feminine);
727 persons[4] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Neuter);
728
729 for (int person = 0; person < 5; person++) {
730 QDomElement currentElement = personElement.firstChildElement(KVTML_GRAMMATICAL_PERSON[person]);
731 pronoun.setPersonalPronoun(currentElement.text(), persons[person] | number);
732 }
733
734 return true;
735}
736
737#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...)
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
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 Nov 22 2024 12:06:56 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.