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 <QTextStream>
14 #include <QList>
15 #include <QIODevice>
16 #include <QDir>
17
18 #include "keduvoclesson.h"
19 #include "keduvocleitnerbox.h"
20 #include "keduvocwordtype.h"
21 #include "kvtml2defs.h"
22 #include "keduvockvtmlreader.h"
23 #include "keduvoccommon_p.h"
24
25 #include <QDebug>
26
KEduVocKvtml2Reader(QIODevice & file)27 KEduVocKvtml2Reader::KEduVocKvtml2Reader(QIODevice & file)
28 : m_inputFile( &file )
29 {
30 }
31
isParsable()32 bool KEduVocKvtml2Reader::isParsable()
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")) )
40 && ( line2.indexOf( KVTML_TAG, 0 ) > 0 ) );
41 }
42
fileTypeHandled()43 KEduVocDocument::FileType KEduVocKvtml2Reader::fileTypeHandled()
44 {
45 return KEduVocDocument::Kvtml;
46 }
47
read(KEduVocDocument & doc)48 KEduVocDocument::ErrorCode KEduVocKvtml2Reader::read(KEduVocDocument &doc)
49 {
50 m_doc = &doc;
51
52 QDomDocument domDoc( QStringLiteral("KEduVocDocument") );
53
54 if ( !domDoc.setContent( m_inputFile, &m_errorMessage ) )
55 return KEduVocDocument::InvalidXml;
56
57 QDomElement domElementKvtml = domDoc.documentElement();
58 if ( domElementKvtml.tagName() != KVTML_TAG ) {
59 m_errorMessage = i18n( "This is not a KDE Vocabulary document." );
60 return KEduVocDocument::FileTypeUnknown;
61 }
62
63 if ( domElementKvtml.attribute( KVTML_VERSION ).toFloat() < 2.0 ) {
64 // read the file with the old format
65
66 // first reset the file to the beginning
67 m_inputFile->seek( 0 );
68 KEduVocKvtmlReader oldFormat( *m_inputFile );
69
70 // get the return value
71 KEduVocDocument::ErrorCode retval = oldFormat.read( doc );
72
73 // pass the errormessage up
74 m_errorMessage = oldFormat.errorMessage();
75 return retval;
76 }
77
78 //-------------------------------------------------------------------------
79 // Information
80 //-------------------------------------------------------------------------
81
82 QDomElement info = domElementKvtml.firstChildElement( KVTML_INFORMATION );
83 if ( !info.isNull() ) {
84 if ( !readInformation( info ) )
85 return KEduVocDocument::FileReaderFailed;
86 }
87
88 bool result = readGroups( domElementKvtml ); // read sub-groups
89
90 return result ? KEduVocDocument::NoError : KEduVocDocument::FileReaderFailed;
91 }
92
readInformation(QDomElement & informationElement)93 bool KEduVocKvtml2Reader::readInformation( QDomElement &informationElement )
94 {
95 // read the generator
96 QDomElement currentElement = informationElement.firstChildElement( KVTML_GENERATOR );
97 if ( !currentElement.isNull() ) {
98 m_doc->setGenerator( currentElement.text() );
99 // add the version if it's there
100 int pos = m_doc->generator().lastIndexOf( KVD_VERS_PREFIX );
101 if ( pos >= 0 ) {
102 m_doc->setVersion( m_doc->generator().remove( 0, pos + 2 ) );
103 }
104 }
105
106 // read the title
107 currentElement = informationElement.firstChildElement( KVTML_TITLE );
108 if ( !currentElement.isNull() ) {
109 m_doc->setTitle( currentElement.text() );
110 }
111
112 // read the author
113 currentElement = informationElement.firstChildElement( KVTML_AUTHOR );
114 if ( !currentElement.isNull() ) {
115 m_doc->setAuthor( currentElement.text() );
116 }
117
118 currentElement = informationElement.firstChildElement( KVTML_AUTHORCONTACT );
119 if ( !currentElement.isNull() ) {
120 m_doc->setAuthorContact( currentElement.text() );
121 }
122
123 // read the license
124 currentElement = informationElement.firstChildElement( KVTML_LICENSE );
125 if ( !currentElement.isNull() ) {
126 m_doc->setLicense( currentElement.text() );
127 }
128
129 // read the comment
130 currentElement = informationElement.firstChildElement( KVTML_COMMENT );
131 if ( !currentElement.isNull() ) {
132 m_doc->setDocumentComment( currentElement.text() );
133 }
134
135 // read the category
136 currentElement = informationElement.firstChildElement( KVTML_CATEGORY );
137 if ( !currentElement.isNull() ) {
138 m_doc->setCategory( currentElement.text() );
139 }
140
141 return true;
142 }
143
readGroups(QDomElement & domElementParent)144 bool KEduVocKvtml2Reader::readGroups( QDomElement &domElementParent )
145 {
146 bool result = false;
147
148 QDomElement groupElement = domElementParent.firstChildElement( KVTML_IDENTIFIERS );
149
150 QDomElement currentElement;
151
152 // ensure backwards compatibility - in kde 4.1 and earlier tenses were direct properties of the document class.
153 // now they are moved into the individual identifiers
154 QStringList tensesCompability;
155 groupElement = groupElement.firstChildElement( KVTML_TENSES );
156 if ( !groupElement.isNull() ) {
157 tensesCompability = readTenses( groupElement );
158 }
159
160 groupElement = domElementParent.firstChildElement( KVTML_IDENTIFIERS );
161 if ( !groupElement.isNull() ) {
162 QDomNodeList entryList = groupElement.elementsByTagName( KVTML_IDENTIFIER );
163 if ( entryList.length() <= 0 ) {
164 m_errorMessage = i18n( "missing identifier elements from identifiers tag" );
165 return false;
166 }
167
168 for ( int i = 0; i < entryList.count(); ++i ) {
169 currentElement = entryList.item( i ).toElement();
170 if ( currentElement.parentNode() == groupElement ) {
171 result = readIdentifier( currentElement );
172 if ( !result ) {
173 return false;
174 }
175 if (!tensesCompability.isEmpty()) {
176 m_doc->identifier(i).setTenseList(tensesCompability);
177 }
178 }
179 }
180 }
181
182 groupElement = domElementParent.firstChildElement( KVTML_ENTRIES );
183 if ( !groupElement.isNull() ) {
184 QDomNodeList entryList = groupElement.elementsByTagName( KVTML_ENTRY );
185 for ( int i = 0; i < entryList.count(); ++i ) {
186 currentElement = entryList.item( i ).toElement();
187 if ( currentElement.parentNode() == groupElement ) {
188 result = readEntry( currentElement );
189 if ( !result )
190 return false;
191 }
192 }
193 }
194
195 readSynonymsAntonymsFalseFriends( domElementParent );
196
197 groupElement = domElementParent.firstChildElement( KVTML_WORDTYPES );
198 if ( !groupElement.isNull() ) {
199 readChildWordTypes( m_doc->wordTypeContainer(), groupElement );
200 }
201
202 groupElement = domElementParent.firstChildElement( KVTML_LEITNERBOXES );
203 if ( !groupElement.isNull() ) {
204 readLeitner( m_doc->leitnerContainer(), groupElement );
205 }
206
207 groupElement = domElementParent.firstChildElement( KVTML_LESSONS );
208 if ( !groupElement.isNull() ) {
209 readChildLessons(m_doc->lesson(), groupElement);
210 }
211
212 // Additional cleanup: Put orphaned entries without a lesson into a default lesson.
213 KEduVocLesson *defaultLesson = new KEduVocLesson(i18n("Default Lesson"), m_doc->lesson());
214
215 // now make sure we don't have any orphan entries
216 foreach (KEduVocExpression * entry, m_allEntries) {
217 if (!entry->lesson())
218 {
219 defaultLesson->appendEntry(entry);
220 }
221 }
222
223 if (defaultLesson->entryCount() > 0)
224 {
225 m_doc->lesson()->appendChildContainer(defaultLesson);
226 } else {
227 delete defaultLesson;
228 }
229
230 return true;
231 }
232
233
readIdentifier(QDomElement & identifierElement)234 bool 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++ ) {
245 m_doc->appendIdentifier( KEduVocIdentifier() );
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
readEntry(QDomElement & entryElement)280 bool 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
292 KEduVocExpression *expr = new KEduVocExpression;
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
readTranslation(QDomElement & translationElement,KEduVocExpression * expr,int index)330 bool KEduVocKvtml2Reader::readTranslation( QDomElement &translationElement,
331 KEduVocExpression *expr, int index )
332 {
333 // read the text, grade, declension and conjugation
334 expr->translation(index)->fromKVTML2(translationElement);
335 QDomElement currentElement;
336
337 // article grade
338 currentElement = translationElement.firstChildElement( KVTML_ARTICLE );
339 if ( !currentElement.isNull() ) {
340 KEduVocText article;
341 article.fromKVTML2(currentElement);
342 expr->translation(index)->setArticle(article);
343 }
344
345 // comparisons
346 currentElement = translationElement.firstChildElement( KVTML_COMPARISON );
347 if ( !currentElement.isNull() ) {
348 readComparison( currentElement, expr->translation(index) );
349 }
350
351 // multiple choice
352 currentElement = translationElement.firstChildElement( KVTML_MULTIPLECHOICE );
353 if ( !currentElement.isNull() ) {
354 readMultipleChoice( currentElement, expr->translation(index) );
355 }
356
357 // image
358 currentElement = translationElement.firstChildElement( KVTML_IMAGE );
359 if ( !currentElement.isNull() ) {
360 QUrl imageUrl(currentElement.text());
361 if (imageUrl.isLocalFile() && QDir::isRelativePath(imageUrl.toLocalFile())) {
362 imageUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + imageUrl.toLocalFile());
363 }
364 expr->translation(index)->setImageUrl(imageUrl);
365 }
366
367 // sound
368 currentElement = translationElement.firstChildElement( KVTML_SOUND );
369 if ( !currentElement.isNull() ) {
370 QUrl soundUrl(currentElement.text());
371 if (soundUrl.isLocalFile() && QDir::isRelativePath(soundUrl.toLocalFile())) {
372 soundUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + soundUrl.toLocalFile());
373 }
374 expr->translation(index)->setSoundUrl(soundUrl);
375 }
376
377 return true;
378 }
379
readChildLessons(KEduVocLesson * parentLesson,QDomElement & lessonElement)380 bool KEduVocKvtml2Reader::readChildLessons( KEduVocLesson* parentLesson, QDomElement &lessonElement )
381 {
382 QDomElement currentElement = lessonElement.firstChildElement( KVTML_CONTAINER );
383 while ( !currentElement.isNull() ) {
384 readLesson(parentLesson, currentElement);
385 currentElement = currentElement.nextSiblingElement( KVTML_CONTAINER );
386 }
387 return true;
388 }
389
readLesson(KEduVocLesson * parentLesson,QDomElement & lessonElement)390 bool KEduVocKvtml2Reader::readLesson( KEduVocLesson* parentLesson, QDomElement &lessonElement )
391 {
392 //<name>Lesson name</name>
393 QDomElement currentElement = lessonElement.firstChildElement( KVTML_NAME );
394 KEduVocLesson * lesson = new KEduVocLesson(currentElement.text(), parentLesson);
395 parentLesson->appendChildContainer( lesson );
396
397 readChildLessons( lesson, lessonElement );
398
399 //<query>true</query>
400 currentElement = lessonElement.firstChildElement( KVTML_INPRACTICE );
401 lesson->setInPractice(currentElement.text() == KVTML_TRUE);
402
403 //<entry id="123"/>
404 currentElement = lessonElement.firstChildElement( KVTML_ENTRY );
405 while ( !currentElement.isNull() ) {
406 bool result = false;
407 int entryId = currentElement.attribute( KVTML_ID ).toInt( &result );
408 if(result) {
409 if (m_allEntries[entryId]) {
410 lesson->appendEntry( m_allEntries[entryId] );
411 }
412 }
413 currentElement = currentElement.nextSiblingElement( KVTML_ENTRY );
414 }
415 return true;
416 }
417
readSynonymsAntonymsFalseFriends(QDomElement & rootElement)418 bool KEduVocKvtml2Reader::readSynonymsAntonymsFalseFriends( QDomElement &rootElement )
419 {
420 QDomElement pairElement;
421 for(int type = KEduVocTranslation::Synonym; type <= KEduVocTranslation::FalseFriend; type++) {
422 switch (type) {
423 case KEduVocTranslation::Synonym:
424 pairElement= rootElement.firstChildElement( KVTML_SYNONYM );
425 break;
426 case KEduVocTranslation::Antonym:
427 pairElement= rootElement.firstChildElement( KVTML_ANTONYM );
428 break;
429 case KEduVocTranslation::FalseFriend:
430 pairElement= rootElement.firstChildElement( KVTML_FALSEFRIEND );
431 break;
432 }
433 // pair
434 pairElement = pairElement.firstChildElement( KVTML_PAIR );
435 while ( !pairElement.isNull() ) {
436 //<entry id="123"/>
437 QDomElement entryElement = pairElement.firstChildElement( KVTML_ENTRY );
438 int firstEntryId = entryElement.attribute( KVTML_ID ).toInt();
439
440 QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
441 int firstTranslationId = translationElement.attribute( KVTML_ID ).toInt();
442
443 // second entry
444 entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
445 int secondEntryId = entryElement.attribute( KVTML_ID ).toInt();
446 translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
447 int secondTranslationId = translationElement.attribute( KVTML_ID ).toInt();
448
449 // pair them up
450 KEduVocTranslation *first = m_allEntries[firstEntryId]->translation(firstTranslationId);
451 KEduVocTranslation *second = m_allEntries[secondEntryId]->translation(secondTranslationId);
452
453 switch (type) {
454 case KEduVocTranslation::Synonym:
455 first->addSynonym(second);
456 second->addSynonym(first);
457 break;
458 case KEduVocTranslation::Antonym:
459 first->addAntonym(second);
460 second->addAntonym(first);
461 break;
462 case KEduVocTranslation::FalseFriend:
463 first->addFalseFriend(second);
464 second->addFalseFriend(first);
465 break;
466 }
467 pairElement = pairElement.nextSiblingElement( KVTML_PAIR );
468 }
469 }
470 return true;
471 }
472
readArticle(QDomElement & articleElement,int identifierNum)473 bool KEduVocKvtml2Reader::readArticle( QDomElement &articleElement, int identifierNum )
474 /*
475 <article>
476 <singlular>
477 <definite>
478 <male>der</male>
479 <female>die</female>
480 <neutral>das</neutral>
481 </definite>
482 <indefinite>
483 <male>ein</male>
484 <female>eine</female>
485 <neutral>ein</neutral>
486 </indefinite>
487 </singular>
488 <dual>
489 </dual>
490 </article>
491 */
492 {
493 QMap<int, KEduVocWordFlag::Flags> numbers;
494 numbers[0] = KEduVocWordFlag::Singular;
495 numbers[1] = KEduVocWordFlag::Dual;
496 numbers[2] = KEduVocWordFlag::Plural;
497 QMap<int, KEduVocWordFlag::Flags> genders;
498 genders[0] = KEduVocWordFlag::Masculine;
499 genders[1] = KEduVocWordFlag::Feminine;
500 genders[2] = KEduVocWordFlag::Neuter;
501 QMap<int, KEduVocWordFlag::Flags> defs;
502 defs[0] = KEduVocWordFlag::Definite;
503 defs[1] = KEduVocWordFlag::Indefinite;
504
505 for ( int num = 0; num <= 2; ++num) {
506 QDomElement numberElement = articleElement.firstChildElement( KVTML_GRAMMATICAL_NUMBER[num] );
507 if (!numberElement.isNull()) {
508 // definite
509 for ( int def = 0; def <= 1; ++def ) {
510 QDomElement defElement = numberElement.firstChildElement( KVTML_GRAMMATICAL_DEFINITENESS[def] );
511 if (!defElement.isNull()) {
512 // male
513 for ( int gen = 0; gen <= 2; ++gen ) {
514 QDomElement genderElement = defElement.firstChildElement( KVTML_GRAMMATICAL_GENDER[gen] );
515 if (!genderElement.isNull()) {
516 m_doc->identifier(identifierNum).article().setArticle( genderElement.text(), numbers[num] | defs[def] | genders[gen]);
517 }
518 }
519 }
520 }
521 }
522 }
523
524 return true;
525 }
526
527
readChildWordTypes(KEduVocWordType * parentContainer,QDomElement & lessonElement)528 bool KEduVocKvtml2Reader::readChildWordTypes(KEduVocWordType* parentContainer, QDomElement &lessonElement)
529 {
530 QDomElement currentElement = lessonElement.firstChildElement( KVTML_CONTAINER );
531 while ( !currentElement.isNull() ) {
532 readWordType(parentContainer, currentElement);
533 currentElement = currentElement.nextSiblingElement( KVTML_CONTAINER );
534 }
535 return true;
536 }
537
readLeitner(KEduVocLeitnerBox * parentContainer,QDomElement & leitnerParentElement)538 bool KEduVocKvtml2Reader::readLeitner( KEduVocLeitnerBox* parentContainer, QDomElement &leitnerParentElement )
539 {
540 QDomElement leitnerElement = leitnerParentElement.firstChildElement( KVTML_CONTAINER );
541 while ( !leitnerElement.isNull() ) {
542 QString name = leitnerElement.firstChildElement( KVTML_NAME ).text();
543
544 KEduVocLeitnerBox * leitner = new KEduVocLeitnerBox(name, parentContainer);
545 parentContainer->appendChildContainer(leitner);
546 // for leitner we only allow a flat list, no sub boxes.
547
548 // read entries
549 QDomElement entryElement = leitnerElement.firstChildElement( KVTML_ENTRY );
550 while ( !entryElement.isNull() ) {
551 // read <entry id="123"></entryid>
552 int entryId = entryElement.attribute( KVTML_ID ).toInt();
553 QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
554 while( !translationElement.isNull() ) {
555 // <translation id="234"/>
556 int translationId = translationElement.attribute( KVTML_ID ).toInt();
557 m_allEntries.value(entryId)->translation(translationId)->setLeitnerBox(leitner);
558 translationElement = translationElement.nextSiblingElement( KVTML_TRANSLATION );
559 }
560 entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
561 }
562 leitnerElement = leitnerElement.nextSiblingElement( KVTML_CONTAINER );
563 }
564 return true;
565 }
566
readWordType(KEduVocWordType * parentContainer,QDomElement & typeElement)567 bool KEduVocKvtml2Reader::readWordType( KEduVocWordType* parentContainer, QDomElement &typeElement )
568 {
569 // set type and specialtype
570 QString typeName =
571 typeElement.firstChildElement( KVTML_NAME ).text();
572
573 KEduVocWordType * wordTypeContainer = new KEduVocWordType(typeName, parentContainer);
574 parentContainer->appendChildContainer(wordTypeContainer);
575
576 QString specialType = typeElement.firstChildElement( KVTML_SPECIALWORDTYPE ).text();
577 if ( !specialType.isEmpty() ) {
578 // get the localized version
579 if ( specialType == KVTML_SPECIALWORDTYPE_NOUN ) {
580 wordTypeContainer->setWordType(KEduVocWordFlag::Noun);
581 }
582 if ( specialType == KVTML_SPECIALWORDTYPE_VERB ) {
583 wordTypeContainer->setWordType(KEduVocWordFlag::Verb);
584 }
585 if ( specialType == KVTML_SPECIALWORDTYPE_ADVERB ) {
586 wordTypeContainer->setWordType(KEduVocWordFlag::Adverb);
587 }
588 if ( specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE ) {
589 wordTypeContainer->setWordType(KEduVocWordFlag::Adjective);
590 }
591 if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_MALE ) {
592 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine);
593 }
594 if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE ) {
595 wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine);
596 }
597 if ( specialType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL ) {
598 wordTypeContainer->setWordType(KEduVocWordFlag::Noun| KEduVocWordFlag::Neuter);
599 }
600 if ( specialType == KVTML_SPECIALWORDTYPE_CONJUNCTION ) {
601 wordTypeContainer->setWordType(KEduVocWordFlag::Conjunction);
602 }
603 } // special type
604
605 // read entries
606 QDomElement entryElement = typeElement.firstChildElement( KVTML_ENTRY );
607 while ( !entryElement.isNull() ) {
608 // read <entry id="123"></entryid>
609 int entryId = entryElement.attribute( KVTML_ID ).toInt();
610 QDomElement translationElement = entryElement.firstChildElement( KVTML_TRANSLATION );
611 while( !translationElement.isNull() ) {
612 // <translation id="234"/>
613 int translationId = translationElement.attribute( KVTML_ID ).toInt();
614 m_allEntries.value(entryId)->translation(translationId)->setWordType(wordTypeContainer);
615 translationElement = translationElement.nextSiblingElement( KVTML_TRANSLATION );
616 }
617 entryElement = entryElement.nextSiblingElement( KVTML_ENTRY );
618 }
619
620 readChildWordTypes(wordTypeContainer, typeElement);
621
622 return true;
623 }
624
readTenses(QDomElement & tensesElement)625 QStringList KEduVocKvtml2Reader::readTenses( QDomElement &tensesElement )
626 {
627 QStringList tenses;
628
629 QDomNodeList tenseNodes = tensesElement.elementsByTagName( KVTML_TENSE );
630 for ( int i = 0; i < tenseNodes.count(); ++i ) {
631 QDomElement currentElement = tenseNodes.item( i ).toElement();
632 if ( currentElement.parentNode() == tensesElement ) {
633 tenses.append( currentElement.text() );
634 }
635 }
636
637 return tenses;
638 }
639
readComparison(QDomElement & domElementParent,KEduVocTranslation * translation)640 bool KEduVocKvtml2Reader::readComparison( QDomElement &domElementParent, KEduVocTranslation* translation )
641 /*
642 <comparison>
643 <comparative>better</comparative>
644 <superlative>best</superlative>
645 </comparison>
646 */
647 {
648 QDomElement currentElement;
649
650 currentElement = domElementParent.firstChildElement( KVTML_COMPARATIVE );
651 if ( !currentElement.isNull() )
652 {
653 KEduVocText comparative;
654 comparative.fromKVTML2(currentElement);
655
656 // be compatible for KDE < 4.5
657 if (comparative.text().isEmpty()) {
658 comparative.setText(currentElement.text());
659 }
660 translation->setComparativeForm(comparative);
661 }
662
663 currentElement = domElementParent.firstChildElement( KVTML_SUPERLATIVE );
664 if ( !currentElement.isNull() )
665 {
666 KEduVocText superlative;
667 superlative.fromKVTML2(currentElement);
668
669 // be compatible for KDE < 4.5
670 if (superlative.text().isEmpty()) {
671 superlative.setText(currentElement.text());
672 }
673 translation->setSuperlativeForm(superlative);
674 }
675 return true;
676 }
677
readMultipleChoice(QDomElement & multipleChoiceElement,KEduVocTranslation * translation)678 bool KEduVocKvtml2Reader::readMultipleChoice( QDomElement &multipleChoiceElement, KEduVocTranslation* translation )
679 /*
680 <multiplechoice>
681 <choice>good</choice>
682 <choice>better</choice>
683 <choice>best</choice>
684 <choice>best 2</choice>
685 <choice>best 3</choice>
686 </multiplechoice>
687 */
688 {
689 QDomElement currentElement;
690 QDomNodeList choiceNodes = multipleChoiceElement.elementsByTagName( KVTML_CHOICE );
691 for ( int i = 0; i < choiceNodes.count(); ++i )
692 {
693 currentElement = choiceNodes.item( i ).toElement();
694 if ( currentElement.parentNode() == multipleChoiceElement ) {
695 QStringList choices = translation->getMultipleChoice();
696 choices.append(currentElement.text());
697 translation->setMultipleChoice(choices);
698 }
699 }
700 return true;
701 }
702
703
readPersonalPronoun(QDomElement & pronounElement,KEduVocPersonalPronoun & pronoun)704 bool KEduVocKvtml2Reader::readPersonalPronoun(QDomElement & pronounElement, KEduVocPersonalPronoun & pronoun)
705 {
706 pronoun.setMaleFemaleDifferent(!pronounElement.firstChildElement(
707 KVTML_THIRD_PERSON_MALE_FEMALE_DIFFERENT).isNull());
708 pronoun.setNeutralExists( !pronounElement.firstChildElement(
709 KVTML_THIRD_PERSON_NEUTRAL_EXISTS).isNull() );
710 pronoun.setDualExists( !pronounElement.firstChildElement(
711 KVTML_DUAL_EXISTS).isNull() );
712
713 QDomElement personElement = pronounElement.firstChildElement( KVTML_GRAMMATICAL_NUMBER[0] );
714 if ( !personElement.isNull() ) {
715 readPersonalPronounChild( personElement, pronoun, KEduVocWordFlag::Singular );
716 }
717
718 personElement = pronounElement.firstChildElement( KVTML_GRAMMATICAL_NUMBER[1] );
719 if ( !personElement.isNull() ) {
720 readPersonalPronounChild( personElement, pronoun, KEduVocWordFlag::Dual );
721 }
722
723 personElement = pronounElement.firstChildElement( KVTML_GRAMMATICAL_NUMBER[2] );
724 if ( !personElement.isNull() ) {
725 readPersonalPronounChild( personElement, pronoun, KEduVocWordFlag::Plural );
726 }
727 return true;
728 }
729
730
readPersonalPronounChild(QDomElement & personElement,KEduVocPersonalPronoun & pronoun,KEduVocWordFlags number)731 bool KEduVocKvtml2Reader::readPersonalPronounChild(QDomElement & personElement, KEduVocPersonalPronoun & pronoun, KEduVocWordFlags number)
732 {
733 QMap<int, KEduVocWordFlag::Flags> persons;
734 persons[0] = KEduVocWordFlag::First;
735 persons[1] = KEduVocWordFlag::Second;
736 persons[2] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Masculine);
737 persons[3] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Feminine);
738 persons[4] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Neuter);
739
740
741
742 for (int person = 0; person < 5; person++) {
743 QDomElement currentElement = personElement.firstChildElement( KVTML_GRAMMATICAL_PERSON[person] );
744 pronoun.setPersonalPronoun( currentElement.text(), persons[person] | number );
745 }
746
747 return true;
748 }
749