LibKEduVocDocument

keduvockvtmlreader.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 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include "keduvockvtmlreader.h"
11
12#include <KLocalizedString>
13#include <QIODevice>
14#include <QTextStream>
15
16#include <QDebug>
17#include <QLocale>
18
19#include "keduvoccommon_p.h"
20#include "keduvoclesson.h"
21#include "keduvocwordtype.h"
22#include "kvtmldefs.h"
23
25 : m_inputFile(&file)
26{
27 m_errorMessage = QLatin1String("");
28 qDebug() << "KEduVocKvtmlReader for kvtml version 1 files started.";
29}
30
32{
33 QTextStream ts(m_inputFile);
34 QString line1(ts.readLine());
35 QString line2(ts.readLine());
36
37 m_inputFile->seek(0);
38 return ((line1.startsWith(QLatin1String("<?xml"))) && (line2.indexOf(KV_DOCTYPE, 0) > 0));
39}
40
42{
43 m_doc = &doc;
44 m_cols = 0;
45 m_lines = 0;
46
47 QDomDocument domDoc(QStringLiteral("KEduVocDocument"));
48
49 const QDomDocument::ParseResult parseResult = domDoc.setContent(m_inputFile);
50 if (!parseResult) {
51 qDebug() << "Unable to load document.Parse error in line " << parseResult.errorLine << ", col " << parseResult.errorColumn << ": "
52 << qPrintable(parseResult.errorMessage);
54 }
55
56 QDomElement domElementKvtml = domDoc.documentElement();
57 if (domElementKvtml.tagName() != KV_DOCTYPE) {
58 m_errorMessage = i18n("This is not a KDE Vocabulary document.");
60 }
61
62 //-------------------------------------------------------------------------
63 // Attributes
64 //-------------------------------------------------------------------------
65
66 QDomAttr documentAttribute;
67 documentAttribute = domElementKvtml.attributeNode(KV_ENCODING);
68 if (!documentAttribute.isNull()) {
69 // TODO handle old encodings
70 // Qt DOM API autodetects encoding, so is there anything to do ?
71 }
72
73 documentAttribute = domElementKvtml.attributeNode(KV_TITLE);
74 if (!documentAttribute.isNull())
75 m_doc->setTitle(documentAttribute.value());
76
77 documentAttribute = domElementKvtml.attributeNode(KV_AUTHOR);
78 if (!documentAttribute.isNull())
79 m_doc->setAuthor(documentAttribute.value());
80
81 documentAttribute = domElementKvtml.attributeNode(KV_LICENSE);
82 if (!documentAttribute.isNull())
83 m_doc->setLicense(documentAttribute.value());
84
85 documentAttribute = domElementKvtml.attributeNode(KV_DOC_REM);
86 if (!documentAttribute.isNull())
87 m_doc->setDocumentComment(documentAttribute.value());
88
89 documentAttribute = domElementKvtml.attributeNode(KV_GENERATOR);
90 if (!documentAttribute.isNull()) {
91 m_doc->setGenerator(documentAttribute.value());
92 int pos = m_doc->generator().lastIndexOf(KVD_VERS_PREFIX);
93 if (pos >= 0)
94 m_doc->setVersion(m_doc->generator().remove(0, pos + 2));
95 }
96
97 documentAttribute = domElementKvtml.attributeNode(KV_COLS);
98 if (!documentAttribute.isNull())
99 m_cols = documentAttribute.value().toInt(); /// currently not used anywhere
100
101 documentAttribute = domElementKvtml.attributeNode(KV_LINES);
102 if (!documentAttribute.isNull())
103 m_lines = documentAttribute.value().toInt();
104
105 //-------------------------------------------------------------------------
106 // Children
107 //-------------------------------------------------------------------------
108
109 bool result = readBody(domElementKvtml); // read vocabulary
110
112}
113
114bool KEduVocKvtmlReader::readBody(QDomElement &domElementParent)
115{
116 bool result = false;
117
118 QDomElement currentElement;
119
120 currentElement = domElementParent.firstChildElement(KV_LESS_GRP);
121 if (!currentElement.isNull()) {
122 result = readLesson(currentElement);
123 if (!result)
124 return false;
125 }
126
127 currentElement = domElementParent.firstChildElement(KV_ARTICLE_GRP);
128 if (!currentElement.isNull()) {
129 result = readArticle(currentElement);
130 if (!result)
131 return false;
132 }
133
134 currentElement = domElementParent.firstChildElement(KV_CONJUG_GRP);
135 if (!currentElement.isNull()) {
136 int count = 0;
137
138 QDomElement domElementConjugChild = currentElement.firstChildElement(KV_CON_ENTRY);
139 while (!domElementConjugChild.isNull()) {
140 QString lang;
141 QDomAttr domAttrLang = domElementConjugChild.attributeNode(KV_LANG); // "l"
142 // make sure, the identifier is there
143 if (!addLanguage(count, domAttrLang.value())) {
144 return false;
145 }
146
147 KEduVocPersonalPronoun pronouns;
148 if (!readPersonalPronouns(domElementConjugChild, pronouns)) {
149 return false;
150 }
151 m_doc->identifier(count).setPersonalPronouns(pronouns);
152
153 count++;
154
155 domElementConjugChild = domElementConjugChild.nextSiblingElement(KV_CON_ENTRY);
156 }
157 }
158
159 // initialize the list of predefined types
160 m_compability.setupWordTypes(m_doc->wordTypeContainer());
161
162 currentElement = domElementParent.firstChildElement(KV_TYPE_GRP);
163 if (!currentElement.isNull()) {
164 result = readType(currentElement);
165 if (!result)
166 return false;
167 }
168
169 currentElement = domElementParent.firstChildElement(KV_TENSE_GRP);
170 if (!currentElement.isNull()) {
171 result = readTense(currentElement);
172 if (!result)
173 return false;
174 }
175
176 QDomNodeList entryList = domElementParent.elementsByTagName(KV_EXPR);
177 if (entryList.length() <= 0)
178 return false;
179
180 for (int i = 0; i < entryList.count(); ++i) {
181 currentElement = entryList.item(i).toElement();
182 if (currentElement.parentNode() == domElementParent) {
183 result = readExpression(currentElement);
184 if (!result)
185 return false;
186 }
187 }
188
189 for (int i = 0; i < m_doc->identifierCount(); i++) {
190 m_doc->identifier(i).setTenseList(m_compability.documentTenses());
191 }
192
193 return true;
194}
195
196bool KEduVocKvtmlReader::readLesson(QDomElement &domElementParent)
197{
198 QString s;
199 QDomAttr attribute;
200 QDomElement currentElement;
201
202 //-------------------------------------------------------------------------
203 // Children
204 //-------------------------------------------------------------------------
205
206 QDomNodeList entryList = domElementParent.elementsByTagName(KV_LESS_DESC);
207 if (entryList.length() <= 0)
208 return false;
209
210 for (int i = 0; i < entryList.count(); ++i) {
211 currentElement = entryList.item(i).toElement();
212 if (currentElement.parentNode() == domElementParent) {
213 int no = -1;
214
215 attribute = currentElement.attributeNode(KV_LESS_NO);
216 if (!attribute.isNull()) {
217 no = attribute.value().toInt();
218 }
219
220 bool inQuery = false;
221 attribute = currentElement.attributeNode(KV_LESS_QUERY);
222 if (!attribute.isNull()) {
223 inQuery = (attribute.value().toInt() != 0);
224 }
225
226 s = currentElement.text();
227 KEduVocLesson *lesson = new KEduVocLesson(s, m_doc->lesson());
228 lesson->setInPractice(inQuery);
229 m_doc->lesson()->appendChildContainer(lesson);
230 if (m_doc->lesson()->childContainerCount() != no - 1) {
231 qDebug() << "Warning! Lesson order may be confused. Are all lessons in order in the file?";
232 }
233 }
234 }
235
236 return true;
237}
238
239bool KEduVocKvtmlReader::readArticle(QDomElement &domElementParent)
240/*
241 <article>
242 <e l="de"> lang determines also lang order in entries !!
243 <fi>eine</fi> which must NOT differ
244 <fd>die</fd>
245 <mi>ein</mi>
246 <md>der</md>
247 <ni>ein</ni>
248 <nd>das</nd>
249 </e>
250 </article>
251*/
252{
253 QString s;
254 QDomAttr attribute;
255 QDomElement currentElement;
256 QDomElement article;
257
258 QDomNodeList entryList = domElementParent.elementsByTagName(KV_ART_ENTRY);
259 if (entryList.length() <= 0)
260 return false;
261
262 for (int i = 0; i < entryList.count(); ++i) {
263 // qDebug() << "KEduVocKvtmlReader::readArticle() read " << entryList.count() << " articles. ";
264 currentElement = entryList.item(i).toElement();
265 if (currentElement.parentNode() == domElementParent) {
266 QString lang;
267 attribute = currentElement.attributeNode(KV_LANG);
268
269 if (!addLanguage(i, attribute.value())) {
270 return false;
271 }
272
273 //---------
274 // Children
275
276 QString fem_def = QLatin1String("");
277 QString mal_def = QLatin1String("");
278 QString nat_def = QLatin1String("");
279 QString fem_indef = QLatin1String("");
280 QString mal_indef = QLatin1String("");
281 QString nat_indef = QLatin1String("");
282
283 article = currentElement.firstChildElement(KV_ART_FD);
284 if (!article.isNull()) {
285 fem_def = article.text();
286 if (fem_def.isNull())
287 fem_def = QLatin1String("");
288 }
289
290 article = currentElement.firstChildElement(KV_ART_FI);
291 if (!article.isNull()) {
292 fem_indef = article.text();
293 if (fem_indef.isNull())
294 fem_indef = QLatin1String("");
295 }
296
297 article = currentElement.firstChildElement(KV_ART_MD);
298 if (!article.isNull()) {
299 mal_def = article.text();
300 if (mal_def.isNull())
301 mal_def = QLatin1String("");
302 }
303
304 article = currentElement.firstChildElement(KV_ART_MI);
305 if (!article.isNull()) {
306 mal_indef = article.text();
307 if (mal_indef.isNull())
308 mal_indef = QLatin1String("");
309 }
310
311 article = currentElement.firstChildElement(KV_ART_ND);
312 if (!article.isNull()) {
313 nat_def = article.text();
314 if (nat_def.isNull())
315 nat_def = QLatin1String("");
316 }
317
318 article = currentElement.firstChildElement(KV_ART_NI);
319 if (!article.isNull()) {
320 nat_indef = article.text();
321 if (nat_indef.isNull())
322 nat_indef = QLatin1String("");
323 }
324
325 KEduVocArticle article;
326 article.setArticle(mal_def, KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine);
327 article.setArticle(fem_def, KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine);
328 article.setArticle(nat_def, KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter);
329 article.setArticle(mal_indef, KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine);
330 article.setArticle(fem_indef, KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine);
331 article.setArticle(nat_indef, KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter);
332 m_doc->identifier(i).setArticle(article);
333 }
334 }
335
336 return true;
337}
338
339bool KEduVocKvtmlReader::readTranslationConjugations(QDomElement &domElementParent, KEduVocTranslation *translation)
340{
341 QString tense;
342
343 QDomElement domElementConjugChild = domElementParent.firstChildElement(KV_CON_TYPE);
344 while (!domElementConjugChild.isNull()) {
345 // "n" == is the type is the tense
346 QDomAttr domAttrLang = domElementConjugChild.attributeNode(KV_CON_NAME);
347 QString oldShortTense = domAttrLang.value();
348
349 tense = m_compability.tenseFromKvtml1(oldShortTense);
350 KEduVocConjugation conjugation;
351 readConjugation(domElementConjugChild, conjugation);
352 translation->setConjugation(tense, conjugation);
353
354 domElementConjugChild = domElementConjugChild.nextSiblingElement(KV_CON_TYPE);
355 } // while -> next tense, count++
356 return true;
357}
358
359bool KEduVocKvtmlReader::readConjugation(QDomElement &domElementParent, KEduVocConjugation &conjugation)
360/*
361 <conjugation> used in header for definition of "prefix"
362 <e l="de"> lang determines also lang order in entries !!
363 <s1>I</s1> which must NOT differ
364 <s2>you<2>
365 <s3f>he</s3f>
366 <s3m>she</s3m>
367 <s3n>it</s3n>
368 <p1>we</p1>
369 <p2>you</p2>
370 <p3f>they</p3f>
371 <p3m>they</p3m>
372 <p3n>they</p3n>
373 </e>
374 </conjugation>
375
376 <conjugation> and in entry for definition of tenses of (irreg.) verbs
377 <t n="sipa">
378 <s1>go</s1>
379 <s2>go</s2>
380 <s3f>goes</s3f>
381 <s3m>goes</s3m>
382 <s3n>goes</s3n>
383 <p1>go</p1>
384 <p2>go</p2>
385 <p3f>go</p3f>
386 <p3m>go</p3m>
387 <p3n>go</p3n>
388 </t>
389 </conjugation>
390*/
391{
392 // QString s;
393 bool p3_common;
394 bool s3_common;
395 QString pers1_sing;
396 QString pers2_sing;
397 QString pers3_m_sing;
398 QString pers3_f_sing;
399 QString pers3_n_sing;
400 QString pers1_plur;
401 QString pers2_plur;
402 QString pers3_m_plur;
403 QString pers3_f_plur;
404 QString pers3_n_plur;
405
406 p3_common = false;
407 s3_common = false;
408
409 // get the individual entries for persons...
410 QDomElement domElementConjugGrandChild = domElementParent.firstChild().toElement();
411 while (!domElementConjugGrandChild.isNull()) {
412 if (domElementConjugGrandChild.tagName() == KV_CON_P1S) {
413 pers1_sing = domElementConjugGrandChild.text();
414 } else if (domElementConjugGrandChild.tagName() == KV_CON_P2S) {
415 pers2_sing = domElementConjugGrandChild.text();
416 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SF) {
417 QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON);
418 if (!domAttrCommon.isNull())
419 s3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails
420 pers3_f_sing = domElementConjugGrandChild.text();
421
422 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SM) {
423 pers3_m_sing = domElementConjugGrandChild.text();
424
425 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SN) {
426 pers3_n_sing = domElementConjugGrandChild.text();
427
428 } else if (domElementConjugGrandChild.tagName() == KV_CON_P1P) {
429 pers1_plur = domElementConjugGrandChild.text();
430
431 } else if (domElementConjugGrandChild.tagName() == KV_CON_P2P) {
432 pers2_plur = domElementConjugGrandChild.text();
433
434 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PF) {
435 QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON);
436 if (!domAttrCommon.isNull())
437 p3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails
438
439 pers3_f_plur = domElementConjugGrandChild.text();
440
441 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PM) {
442 pers3_m_plur = domElementConjugGrandChild.text();
443
444 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PN) {
445 pers3_n_plur = domElementConjugGrandChild.text();
446
447 } else {
448 return false;
449 }
450
451 domElementConjugGrandChild = domElementConjugGrandChild.nextSibling().toElement();
452 } // while - probably to be sure, because the persons could be in any order.
453 // I guess this goes over only one set, such as:
454 // <s1>traigo</s1><s2>traes</s2><s3fcommon="1">trae</s3f>
455 // <p1>traemos</p1><p2>traéis</p2><p3f common="1">traen</p3f>
456 // until no elements are left in that soup.
457
458 // now set the data: [count] - number of conjug?
459 // type - the tense?
460 // finally the person
461
462 const KEduVocWordFlags numS = KEduVocWordFlag::Singular;
463 const KEduVocWordFlags numP = KEduVocWordFlag::Plural;
464
465 conjugation.setConjugation(pers1_sing, KEduVocWordFlag::First | numS);
466 conjugation.setConjugation(pers2_sing, KEduVocWordFlag::Second | numS);
467 conjugation.setConjugation(pers1_plur, KEduVocWordFlag::First | numP);
468 conjugation.setConjugation(pers2_plur, KEduVocWordFlag::Second | numP);
469
470 if (s3_common) {
471 conjugation.setConjugation(pers3_f_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | KEduVocWordFlag::Singular);
472 } else {
473 conjugation.setConjugation(pers3_m_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | KEduVocWordFlag::Singular);
474 conjugation.setConjugation(pers3_f_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | KEduVocWordFlag::Singular);
475 conjugation.setConjugation(pers3_n_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | KEduVocWordFlag::Singular);
476 }
477
478 if (p3_common) {
479 conjugation.setConjugation(pers3_f_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | KEduVocWordFlag::Plural);
480 } else {
481 conjugation.setConjugation(pers3_m_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | KEduVocWordFlag::Plural);
482 conjugation.setConjugation(pers3_f_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | KEduVocWordFlag::Plural);
483 conjugation.setConjugation(pers3_n_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | KEduVocWordFlag::Plural);
484 }
485
486 return true;
487}
488
489bool KEduVocKvtmlReader::readPersonalPronouns(QDomElement &domElementParent, KEduVocPersonalPronoun &pronouns)
490{
491 // QString s;
492 bool p3_common;
493 bool s3_common;
494 QString pers1_sing;
495 QString pers2_sing;
496 QString pers3_m_sing;
497 QString pers3_f_sing;
498 QString pers3_n_sing;
499 QString pers1_plur;
500 QString pers2_plur;
501 QString pers3_m_plur;
502 QString pers3_f_plur;
503 QString pers3_n_plur;
504
505 p3_common = false;
506 s3_common = false;
507
508 // get the individual entries for persons...
509 QDomElement domElementConjugGrandChild = domElementParent.firstChild().toElement();
510 while (!domElementConjugGrandChild.isNull()) {
511 if (domElementConjugGrandChild.tagName() == KV_CON_P1S) {
512 pers1_sing = domElementConjugGrandChild.text();
513 } else if (domElementConjugGrandChild.tagName() == KV_CON_P2S) {
514 pers2_sing = domElementConjugGrandChild.text();
515 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SF) {
516 QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON);
517 if (!domAttrCommon.isNull())
518 s3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails
519 pers3_f_sing = domElementConjugGrandChild.text();
520
521 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SM) {
522 pers3_m_sing = domElementConjugGrandChild.text();
523
524 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3SN) {
525 pers3_n_sing = domElementConjugGrandChild.text();
526
527 } else if (domElementConjugGrandChild.tagName() == KV_CON_P1P) {
528 pers1_plur = domElementConjugGrandChild.text();
529
530 } else if (domElementConjugGrandChild.tagName() == KV_CON_P2P) {
531 pers2_plur = domElementConjugGrandChild.text();
532
533 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PF) {
534 QDomAttr domAttrCommon = domElementConjugGrandChild.attributeNode(KV_CONJ_COMMON);
535 if (!domAttrCommon.isNull())
536 p3_common = domAttrCommon.value().toInt(); // returns 0 if the conversion fails
537
538 pers3_f_plur = domElementConjugGrandChild.text();
539
540 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PM) {
541 pers3_m_plur = domElementConjugGrandChild.text();
542
543 } else if (domElementConjugGrandChild.tagName() == KV_CON_P3PN) {
544 pers3_n_plur = domElementConjugGrandChild.text();
545
546 } else {
547 return false;
548 }
549
550 domElementConjugGrandChild = domElementConjugGrandChild.nextSibling().toElement();
551 } // while - probably to be sure, because the persons could be in any order.
552 // I guess this goes over only one set, such as:
553 // <s1>traigo</s1><s2>traes</s2><s3fcommon="1">trae</s3f>
554 // <p1>traemos</p1><p2>traéis</p2><p3f common="1">traen</p3f>
555 // until no elements are left in that soup.
556
557 // now set the data: [count] - number of conjug?
558 // type - the tense?
559 // finally the person
560
561 KEduVocWordFlags numS = KEduVocWordFlag::Singular;
562 pronouns.setMaleFemaleDifferent(false);
563 pronouns.setPersonalPronoun(pers1_sing, KEduVocWordFlag::First | numS);
564 pronouns.setPersonalPronoun(pers2_sing, KEduVocWordFlag::Second | numS);
565
566 // used to have common in female
567 if (s3_common) {
568 pronouns.setPersonalPronoun(pers3_f_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS);
569 } else {
570 pronouns.setPersonalPronoun(pers3_m_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS);
571 pronouns.setPersonalPronoun(pers3_f_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS);
572 pronouns.setPersonalPronoun(pers3_n_sing, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS);
573 pronouns.setMaleFemaleDifferent(true);
574 }
575
576 KEduVocWordFlags numP = KEduVocWordFlag::Plural;
577
578 pronouns.setPersonalPronoun(pers1_plur, KEduVocWordFlag::First | numP);
579 pronouns.setPersonalPronoun(pers2_plur, KEduVocWordFlag::Second | numP);
580 if (p3_common) {
581 pronouns.setPersonalPronoun(pers3_f_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP);
582 } else {
583 pronouns.setPersonalPronoun(pers3_m_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP);
584 pronouns.setPersonalPronoun(pers3_f_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP);
585 pronouns.setPersonalPronoun(pers3_n_plur, KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP);
586 pronouns.setMaleFemaleDifferent(true);
587 }
588
589 return true;
590}
591
592bool KEduVocKvtmlReader::readType(QDomElement &domElementParent)
593{
594 QString s;
595 QDomElement currentElement;
596
597 QDomNodeList entryList = domElementParent.elementsByTagName(KV_TYPE_DESC);
598 if (entryList.length() <= 0)
599 return false;
600
601 for (int i = 0; i < entryList.count(); ++i) {
602 currentElement = entryList.item(i).toElement();
603 if (currentElement.parentNode() == domElementParent) {
604 // We need to even add empty elements since the old system relied on
605 // the order. So "type1" "" "type2" should be just like that.
606
607 qDebug() << "Adding old self defined type: " << currentElement.text();
608 // add the type to the list of available types
609 KEduVocWordType *type = new KEduVocWordType(currentElement.text(), m_doc->wordTypeContainer());
610 m_doc->wordTypeContainer()->appendChildContainer(type);
611
612 // from this the #1 are transformed to something sensible again
613 m_oldSelfDefinedTypes.append(currentElement.text());
614 }
615 }
616
617 return true;
618}
619
620bool KEduVocKvtmlReader::readTense(QDomElement &domElementParent)
621{
622 QDomElement currentElement;
623
624 currentElement = domElementParent.firstChildElement(KV_TENSE_DESC);
625 while (!currentElement.isNull()) {
626 qDebug() << "Reading user defined tense description: " << currentElement.text();
627 m_compability.addUserdefinedTense(currentElement.text());
628 currentElement = currentElement.nextSiblingElement(KV_TENSE_DESC);
629 }
630 return true;
631}
632
633bool KEduVocKvtmlReader::readComparison(QDomElement &domElementParent, KEduVocTranslation *translation)
634/*
635 <comparison>
636 <l1>good</l1> --- this one is dead as it always has to be the word itself
637 <l2>better</l2>
638 <l3>best</l3>
639 </comparison>
640*/
641{
642 QDomElement currentElement;
643
644 currentElement = domElementParent.firstChildElement(KV_COMP_L2);
645 translation->setComparativeForm(currentElement.text());
646
647 currentElement = domElementParent.firstChildElement(KV_COMP_L3);
648 translation->setSuperlativeForm(currentElement.text());
649
650 return true;
651}
652
653bool KEduVocKvtmlReader::readMultipleChoice(QDomElement &domElementParent, KEduVocTranslation *translation)
654/*
655 <multiplechoice>
656 <mc1>good</mc1>
657 <mc2>better</mc2>
658 <mc3>best</mc3>
659 <mc4>best 2</mc4>
660 <mc5>best 3</mc5>
661 </multiplechoice>
662*/
663
664{
665 QDomElement currentElement;
666 QStringList choices = translation->getMultipleChoice();
667
668 currentElement = domElementParent.firstChildElement(KV_MC_1);
669 if (!currentElement.isNull()) {
670 choices.append(currentElement.text());
671 }
672
673 currentElement = domElementParent.firstChildElement(KV_MC_2);
674 if (!currentElement.isNull()) {
675 choices.append(currentElement.text());
676 }
677
678 currentElement = domElementParent.firstChildElement(KV_MC_3);
679 if (!currentElement.isNull()) {
680 choices.append(currentElement.text());
681 }
682
683 currentElement = domElementParent.firstChildElement(KV_MC_4);
684 if (!currentElement.isNull()) {
685 choices.append(currentElement.text());
686 }
687
688 currentElement = domElementParent.firstChildElement(KV_MC_5);
689 if (!currentElement.isNull()) {
690 choices.append(currentElement.text());
691 }
692
693 translation->setMultipleChoice(choices);
694
695 return true;
696}
697
698bool KEduVocKvtmlReader::readExpressionChildAttributes(QDomElement &domElementExpressionChild,
699 QString &lang,
700 grade_t &grade,
701 grade_t &rev_grade,
702 int &count,
703 int &rev_count,
704 QDateTime &date,
705 QDateTime &rev_date,
706 QString &remark,
707 int &bcount,
708 int &rev_bcount,
709 QString &query_id,
710 QString &pronunciation,
711 int &width,
712 QString &type,
713 QString &faux_ami_f,
714 QString &faux_ami_t,
715 QString &synonym,
716 QString &example,
717 QString &antonym,
718 QSet<QString> &usages,
719 QString &paraphrase)
720{
721 Q_UNUSED(usages)
722 int pos;
723 QDomAttr attribute;
724
725 lang = QLatin1String("");
726 attribute = domElementExpressionChild.attributeNode(KV_LANG);
727 if (!attribute.isNull())
728 lang = attribute.value();
729
730 width = -1;
731 attribute = domElementExpressionChild.attributeNode(KV_SIZEHINT);
732 if (!attribute.isNull())
733 width = attribute.value().toInt();
734
735 grade = KV_NORM_GRADE;
736 rev_grade = KV_NORM_GRADE;
737 attribute = domElementExpressionChild.attributeNode(KV_GRADE);
738 if (!attribute.isNull()) {
739 QString s = attribute.value();
740 if ((pos = s.indexOf(';')) >= 1) {
741 grade = QStringView(s).left(pos).toInt();
742 rev_grade = QStringView(s).mid(pos + 1, s.length()).toInt();
743 } else
744 grade = s.toInt();
745 }
746
747 count = 0;
748 rev_count = 0;
749 attribute = domElementExpressionChild.attributeNode(KV_COUNT);
750 if (!attribute.isNull()) {
751 QString s = attribute.value();
752 if ((pos = s.indexOf(';')) >= 1) {
753 count = QStringView(s).left(pos).toInt();
754 rev_count = QStringView(s).mid(pos + 1, s.length()).toInt();
755 } else
756 count = s.toInt();
757 }
758
759 bcount = 0;
760 rev_bcount = 0;
761 attribute = domElementExpressionChild.attributeNode(KV_BAD);
762 if (!attribute.isNull()) {
763 QString s = attribute.value();
764 if ((pos = s.indexOf(';')) >= 1) {
765 bcount = QStringView(s).left(pos).toInt();
766 rev_bcount = QStringView(s).mid(pos + 1, s.length()).toInt();
767 } else
768 bcount = s.toInt();
769 }
770
772 rev_date = QDateTime::fromSecsSinceEpoch(0);
773 attribute = domElementExpressionChild.attributeNode(KV_DATE);
774 if (!attribute.isNull()) {
775 QString s = attribute.value();
776 if ((pos = s.indexOf(';')) >= 1) {
777 date = QDateTime::fromSecsSinceEpoch(QStringView(s).left(pos).toInt());
778 rev_date = QDateTime::fromSecsSinceEpoch(QStringView(s).mid(pos + 1, s.length()).toInt());
779 } else
781 }
782
783 attribute = domElementExpressionChild.attributeNode(KV_DATE2);
784 if (!attribute.isNull()) {
785 // this format is deprecated and ignored.
786 }
787
788 remark = QLatin1String("");
789 attribute = domElementExpressionChild.attributeNode(KV_REMARK);
790 if (!attribute.isNull())
791 remark = attribute.value();
792
793 faux_ami_f = QLatin1String("");
794 attribute = domElementExpressionChild.attributeNode(KV_FAUX_AMI_F);
795 if (!attribute.isNull())
796 faux_ami_f = attribute.value();
797
798 faux_ami_t = QLatin1String("");
799 attribute = domElementExpressionChild.attributeNode(KV_FAUX_AMI_T);
800 if (!attribute.isNull())
801 faux_ami_t = attribute.value();
802
803 synonym = QLatin1String("");
804 attribute = domElementExpressionChild.attributeNode(KV_SYNONYM);
805 if (!attribute.isNull())
806 synonym = attribute.value();
807
808 example = QLatin1String("");
809 attribute = domElementExpressionChild.attributeNode(KV_EXAMPLE);
810 if (!attribute.isNull())
811 example = attribute.value();
812
813 paraphrase = QLatin1String("");
814 attribute = domElementExpressionChild.attributeNode(KV_PARAPHRASE);
815 if (!attribute.isNull())
816 paraphrase = attribute.value();
817
818 antonym = QLatin1String("");
819 attribute = domElementExpressionChild.attributeNode(KV_ANTONYM);
820 if (!attribute.isNull())
821 antonym = attribute.value();
822
823 // this is all done by reference - so we have to care about "type" :(
824 attribute = domElementExpressionChild.attributeNode(KV_EXPRTYPE);
825 if (!attribute.isNull()) {
826 type = attribute.value();
827 }
828
829 pronunciation = QLatin1String("");
830 attribute = domElementExpressionChild.attributeNode(KV_PRONUNCE);
831 if (!attribute.isNull())
832 pronunciation = attribute.value();
833
834 query_id = QLatin1String("");
835 attribute = domElementExpressionChild.attributeNode(KV_QUERY);
836 if (!attribute.isNull())
837 query_id = attribute.value();
838
839 return true;
840}
841
843{
844 grade_t grade;
845 grade_t r_grade;
846 int qcount;
847 int r_qcount;
848 int bcount;
849 int r_bcount;
850 QString remark;
851 QString pronunciation;
852 QDateTime qdate;
853 QDateTime r_qdate;
854 // bool inquery;
855 bool active;
856 QString lang;
857 QString textstr;
858 QString q_org;
859 QString q_trans;
860 QString query_id;
861 int width;
862 QString type;
863 QString faux_ami_f;
864 QString faux_ami_t;
865 QString synonym;
866 QString example;
867 QString antonym;
868 QSet<QString> usage;
869 QString paraphrase;
870
871 QDomAttr attribute;
872 QDomElement currentElement;
873 QDomElement currentChild;
874
875 int lessonNumber = -1;
876
877 //-------------------------------------------------------------------------
878 // Attributes
879 //-------------------------------------------------------------------------
880
881 attribute = domElementParent.attributeNode(KV_LESS_MEMBER);
882 if (!attribute.isNull()) {
883 // we start counting from 0 in new documents
884 lessonNumber = attribute.value().toInt() - 1;
885 if (lessonNumber > m_doc->lesson()->childContainerCount()) {
886 ///@todo can this happen? does it need a while loop?
887 // it's from a lesson that hasn't been added yet
888 // so make sure this lesson is in the document
889 qDebug() << "Warning: lesson > m_doc->lessonCount() in readExpression.";
890
891 KEduVocLesson *lesson = new KEduVocLesson(i18nc("A generic name for a new lesson and its number.", "Lesson %1", lessonNumber), m_doc->lesson());
892 m_doc->lesson()->appendChildContainer(lesson);
893 }
894 }
895
896 attribute = domElementParent.attributeNode(KV_SELECTED);
897 // if ( !attribute.isNull() )
898 // inquery = attribute.value() == "1" ? true : false;
899 // else
900 // inquery = false;
901
902 attribute = domElementParent.attributeNode(KV_INACTIVE);
903 if (!attribute.isNull())
904 active = attribute.value() == QLatin1Char('1') ? false : true;
905 else
906 active = true;
907
908 // this is all done by reference - so we have to care about "type" :(
909 attribute = domElementParent.attributeNode(KV_EXPRTYPE);
910 if (!attribute.isNull()) {
911 type = attribute.value();
912 }
913
914 //-------------------------------------------------------------------------
915 // Children 'Translation'
916 //-------------------------------------------------------------------------
917
918 // QDomNodeList translationList = domElementParent.elementsByTagName(KV_TRANS);
919
920 // count which translation we are on
921 int i = 0;
922
923 // kvtml 1: we always have an original element (required)
924 currentElement = domElementParent.firstChildElement(KV_ORG);
925 if (currentElement.isNull()) { // sanity check
926 m_errorMessage = i18n("Data for original language missing");
927 return false;
928 }
929
930 KEduVocExpression *entry = nullptr;
931
932 while (!currentElement.isNull()) {
933 //-----------
934 // Attributes
935 //-----------
936
937 // read attributes - the order of the query grades is interchanged!
938 if (i == 0
939 && !readExpressionChildAttributes(currentElement,
940 lang,
941 grade,
942 r_grade,
943 qcount,
944 r_qcount,
945 qdate,
946 r_qdate,
947 remark,
948 bcount,
949 r_bcount,
950 query_id,
951 pronunciation,
952 width,
953 type,
954 faux_ami_t,
955 faux_ami_f,
956 synonym,
957 example,
958 antonym,
959 usage,
960 paraphrase)) {
961 return false;
962 }
963
964 if (i != 0
965 && !readExpressionChildAttributes(currentElement,
966 lang,
967 grade,
968 r_grade,
969 qcount,
970 r_qcount,
971 qdate,
972 r_qdate,
973 remark,
974 bcount,
975 r_bcount,
976 query_id,
977 pronunciation,
978 width,
979 type,
980 faux_ami_f,
981 faux_ami_t,
982 synonym,
983 example,
984 antonym,
985 usage,
986 paraphrase)) {
987 return false;
988 }
989
990 //---------
991 // Children
992
993 textstr = currentElement.lastChild().toText().data();
994
995 if (i == 0) {
996 entry = new KEduVocExpression(textstr);
997 entry->setActive(active);
998 if (lessonNumber != -1) {
999 static_cast<KEduVocLesson *>(m_doc->lesson()->childContainer(lessonNumber))->appendEntry(entry);
1000 } else {
1001 m_doc->lesson()->appendEntry(entry);
1002 }
1003 } else {
1004 entry->setTranslation(i, textstr);
1005 }
1006
1007 if (m_doc->lesson()->entries(KEduVocLesson::Recursive).count() == 1) { // this is because in kvtml the languages are saved in the FIRST ENTRY ONLY.
1008 // new translation
1009 if (!addLanguage(i, lang)) {
1010 return false;
1011 }
1012 }
1013
1014 // better make sure, translation(i) already exists...
1015 currentChild = currentElement.firstChildElement(KV_CONJUG_GRP);
1016 if (!currentChild.isNull()) {
1017 if (!readTranslationConjugations(currentChild, entry->translation(i))) {
1018 return false;
1019 }
1020 }
1021
1022 currentChild = currentElement.firstChildElement(KV_MULTIPLECHOICE_GRP);
1023 if (!currentChild.isNull()) {
1024 if (!readMultipleChoice(currentChild, entry->translation(i))) {
1025 return false;
1026 }
1027 }
1028
1029 currentChild = currentElement.firstChildElement(KV_COMPARISON_GRP);
1030 if (!currentChild.isNull()) {
1031 if (!readComparison(currentChild, entry->translation(i))) {
1032 return false;
1033 }
1034 }
1035
1036 if (!type.isEmpty()) {
1037 KEduVocWordType *wordType = m_compability.typeFromOldFormat(m_doc->wordTypeContainer(), type);
1038 entry->translation(i)->setWordType(wordType);
1039 }
1040
1041 if (!remark.isEmpty())
1042 entry->translation(i)->setComment(remark);
1043 if (!pronunciation.isEmpty())
1044 entry->translation(i)->setPronunciation(pronunciation);
1045
1046 ///@todo include false friends from kvtml-1 again?
1047 // if ( !faux_ami_f.isEmpty() )
1048 // entry->translation( i )->setFalseFriend( 0, faux_ami_f );
1049 // if ( !faux_ami_t.isEmpty() )
1050 // entry->translation( 0 )->setFalseFriend( i, faux_ami_t );
1051 ///@todo include synonyms from kvtml-1 again?
1052 // if ( !synonym.isEmpty() )
1053 // entry->translation( i )->setSynonym( synonym );
1054 // if ( !antonym.isEmpty() )
1055 // entry->translation( i )->setAntonym( antonym );
1056
1057 if (!example.isEmpty())
1058 entry->translation(i)->setExample(example);
1059 if (!paraphrase.isEmpty())
1060 entry->translation(i)->setParaphrase(paraphrase);
1061
1062 if (i != 0) {
1063 entry->translation(i)->setGrade(grade);
1064 entry->translation(0)->setGrade(r_grade);
1065 entry->translation(i)->setPracticeCount(qcount);
1066 entry->translation(0)->setPracticeCount(r_qcount);
1067 entry->translation(i)->setBadCount(bcount);
1068 entry->translation(0)->setBadCount(r_bcount);
1069 entry->translation(i)->setPracticeDate(qdate);
1070 entry->translation(0)->setPracticeDate(r_qdate);
1071 }
1072
1073 // Next translation
1074 currentElement = currentElement.nextSiblingElement(KV_TRANS);
1075 i++;
1076 }
1077
1078 return true;
1079}
1080
1081bool KEduVocKvtmlReader::addLanguage(int languageId, const QString &locale)
1082{
1083 if (m_doc->identifierCount() <= languageId) {
1084 m_doc->appendIdentifier();
1085 // first entry
1086 if (!locale.isEmpty()) { // no definition in first entry
1087 m_doc->identifier(languageId).setLocale(locale);
1088
1089 QString languageName;
1090 // when using from qt-only apps this would crash (converter)
1091 languageName = QLocale::languageToString(QLocale(locale).language());
1092 if (languageName.isEmpty()) {
1093 languageName = locale;
1094 }
1095
1096 m_doc->identifier(languageId).setName(languageName);
1097 qDebug() << "addLanguage( " << languageId << ", " << locale << "): " << languageName;
1098 }
1099 } else {
1100 if (!locale.isEmpty()) {
1101 if (locale != m_doc->identifier(languageId).locale()) {
1102 // different originals ?
1103 m_errorMessage = i18n("Ambiguous definition of language code");
1104 return false;
1105 }
1106 }
1107 }
1108 return true;
1109}
1110
1111#include "moc_keduvockvtmlreader.cpp"
Class representing the articles of a language.
The conjugation of a verb.
void setConjugation(const KEduVocText &conjugation, KEduVocWordFlags flags)
Updates or creates the conjugation object for the given word flags.
int childContainerCount() const
Find a child container.
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
KEduVocIdentifier & identifier(int index)
Returns the identifier of translation index.
void setLicense(const QString &license)
Set the license of the file.
QString generator() const
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.
void setActive(bool flag=true)
set entry active (enabled for queries)
KEduVocTranslation * translation(int index)
Get a pointer to the translation.
void setPersonalPronouns(const KEduVocPersonalPronoun &pronouns)
Sets personal pronouns.
void setLocale(const QString &name)
Set the locale.
QString locale() const
The locale of the contents: en, de, es, ...
void setArticle(const KEduVocArticle &article)
Sets the articles for this identifier.
void setName(const QString &name)
Set the name.
virtual bool isParsable()
Can this reader parse this file.
bool readExpression(QDomElement &domElementParent)
KEduVocKvtmlReader(QIODevice &file)
constructor
virtual KEduVocDocument::ErrorCode read(KEduVocDocument &doc)
Parse file and write into doc.
bool addLanguage(int languageId, const QString &language)
Attempt to add a language/locale.
class to store information about a lesson
QList< KEduVocExpression * > entries(EnumEntriesRecursive recursive=NotRecursive) override
get a list of all entries in the lesson
void appendEntry(KEduVocExpression *entry)
append an entry to the lesson
The conjugation of a verb.
void setPracticeCount(count_t count)
set how often this entry has been practiced as int
void setBadCount(count_t count)
set bad query count as int
void setPracticeDate(const QDateTime &date)
Set last query date.
void setGrade(grade_t grade)
sets the grade
void setExample(const QString &expression)
Sets example this expression.
QStringList getMultipleChoice() const
Returns multiple choice if available.
void setConjugation(const QString &tense, const KEduVocConjugation &conjugation)
adds conjugations or replaces them, if they exist.
void setMultipleChoice(const QStringList &choices)
Sets multiple choice.
void setParaphrase(const QString &expression)
Sets paraphrase of this expression.
void setWordType(KEduVocWordType *wordType)
Sets the word type of this expression.
void setPronunciation(const QString &expression)
Sets the pronunciation of this expression.
void setComment(const QString &expr)
Sets comment of this expression.
class to store translation word types
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
QDateTime fromSecsSinceEpoch(qint64 secs)
QString value() const const
QString data() const const
QDomElement documentElement() const const
ParseResult setContent(QAnyStringView text, ParseOptions options)
QDomAttr attributeNode(const QString &name)
QDomNodeList elementsByTagName(const QString &tagname) const const
QString tagName() const const
QString text() const const
QDomNode firstChild() const const
QDomElement firstChildElement(const QString &tagName, const QString &namespaceURI) const const
bool isNull() const const
QDomNode lastChild() const const
QDomNode nextSibling() const const
QDomElement nextSiblingElement(const QString &tagName, const QString &namespaceURI) const const
QDomNode parentNode() const const
QDomElement toElement() const const
QDomText toText() 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)
qsizetype count() const const
QString languageToString(Language language)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
int toInt(bool *ok, int base) const const
QStringView left(qsizetype length) const const
QStringView mid(qsizetype start, qsizetype length) const const
int toInt(bool *ok, int base) const const
QTextStream & left(QTextStream &stream)
QString readLine(qint64 maxlen)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:15:30 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.