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