File indexing completed on 2024-04-21 03:48:21
0001 /* 0002 * export a KEduVocDocument to a KVTML file 0003 * SPDX-FileCopyrightText: 2007 Jeremy Whiting <jpwhiting@kde.org> 0004 * SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org> 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #include "keduvockvtml2writer.h" 0008 0009 #include <QTextStream> 0010 0011 #include <QDebug> 0012 #include <QDir> 0013 0014 #include "keduvocdocument.h" 0015 #include "keduvocexpression.h" 0016 #include "keduvocleitnerbox.h" 0017 #include "keduvoclesson.h" 0018 #include "keduvocwordtype.h" 0019 #include "kvtml2defs.h" 0020 #include <kio/global.h> 0021 0022 KEduVocKvtml2Writer::KEduVocKvtml2Writer(QFile *file) 0023 { 0024 // the file must be already open 0025 m_outputFile = file; 0026 } 0027 0028 bool KEduVocKvtml2Writer::writeDoc(KEduVocDocument *doc, const QString &generator) 0029 { 0030 if (createXmlDocument(doc, generator)) { 0031 QTextStream ts(m_outputFile); 0032 m_domDoc.save(ts, 2); 0033 return true; 0034 } 0035 return false; 0036 } 0037 0038 QByteArray KEduVocKvtml2Writer::toByteArray(KEduVocDocument *doc, const QString &generator) 0039 { 0040 if (createXmlDocument(doc, generator)) { 0041 return m_domDoc.toByteArray(); 0042 } 0043 return QByteArray(); 0044 } 0045 0046 bool KEduVocKvtml2Writer::createXmlDocument(KEduVocDocument *doc, const QString &generator) 0047 { 0048 m_doc = doc; 0049 0050 m_domDoc = QDomDocument(QStringLiteral("kvtml PUBLIC \"kvtml2.dtd\" \"http://edu.kde.org/kvtml/kvtml2.dtd\"")); 0051 m_domDoc.appendChild(m_domDoc.createProcessingInstruction(QStringLiteral("xml"), QStringLiteral("version=\"1.0\" encoding=\"UTF-8\""))); 0052 QDomElement domElementKvtml = m_domDoc.createElement(QStringLiteral("kvtml")); 0053 m_domDoc.appendChild(domElementKvtml); 0054 0055 domElementKvtml.setAttribute(KVTML_VERSION, (QString)QStringLiteral("2.0")); 0056 0057 // information group 0058 QDomElement currentElement = m_domDoc.createElement(KVTML_INFORMATION); 0059 writeInformation(currentElement, generator); 0060 domElementKvtml.appendChild(currentElement); 0061 0062 // identifiers 0063 currentElement = m_domDoc.createElement(KVTML_IDENTIFIERS); 0064 writeIdentifiers(currentElement); 0065 domElementKvtml.appendChild(currentElement); 0066 0067 // entries 0068 currentElement = m_domDoc.createElement(KVTML_ENTRIES); 0069 if (!writeEntries(currentElement)) { 0070 // at least one entry is required! 0071 return false; 0072 } 0073 domElementKvtml.appendChild(currentElement); 0074 0075 // lessons 0076 currentElement = m_domDoc.createElement(KVTML_LESSONS); 0077 writeLessons(m_doc->lesson(), currentElement); 0078 if (currentElement.hasChildNodes()) { 0079 domElementKvtml.appendChild(currentElement); 0080 } 0081 0082 // types 0083 currentElement = m_domDoc.createElement(KVTML_WORDTYPES); 0084 writeWordTypes(currentElement, m_doc->wordTypeContainer()); 0085 if (currentElement.hasChildNodes()) { 0086 domElementKvtml.appendChild(currentElement); 0087 } 0088 0089 // leitner boxes 0090 currentElement = m_domDoc.createElement(KVTML_LEITNERBOXES); 0091 writeLeitnerBoxes(currentElement, m_doc->leitnerContainer()); 0092 if (currentElement.hasChildNodes()) { 0093 domElementKvtml.appendChild(currentElement); 0094 } 0095 0096 writeSynonymAntonymFalseFriend(domElementKvtml); 0097 0098 m_domDoc.appendChild(domElementKvtml); 0099 0100 return true; 0101 } 0102 0103 bool KEduVocKvtml2Writer::writeInformation(QDomElement &informationElement, const QString &generator) 0104 { 0105 QDomElement currentElement; 0106 QDomText textNode; 0107 0108 // generator 0109 informationElement.appendChild(newTextElement(KVTML_GENERATOR, generator)); 0110 0111 // title 0112 if (!m_doc->title().isEmpty()) { 0113 informationElement.appendChild(newTextElement(KVTML_TITLE, m_doc->title())); 0114 } 0115 0116 // author 0117 if (!m_doc->author().isEmpty()) { 0118 informationElement.appendChild(newTextElement(KVTML_AUTHOR, m_doc->author())); 0119 } 0120 0121 // author contact (mail/homepage) 0122 if (!m_doc->authorContact().isEmpty()) { 0123 informationElement.appendChild(newTextElement(KVTML_AUTHORCONTACT, m_doc->authorContact())); 0124 } 0125 0126 // license 0127 if (!m_doc->license().isEmpty()) { 0128 informationElement.appendChild(newTextElement(KVTML_LICENSE, m_doc->license())); 0129 } 0130 0131 // comment 0132 if (!m_doc->documentComment().isEmpty()) { 0133 informationElement.appendChild(newTextElement(KVTML_COMMENT, m_doc->documentComment())); 0134 } 0135 0136 QDate today = QDate::currentDate(); 0137 informationElement.appendChild(newTextElement(KVTML_DATE, today.toString(QStringLiteral("yyyy-MM-dd")))); 0138 0139 // category 0140 if (!m_doc->category().isEmpty()) { 0141 informationElement.appendChild(newTextElement(KVTML_CATEGORY, m_doc->category())); 0142 } 0143 0144 return true; 0145 } 0146 0147 bool KEduVocKvtml2Writer::writeIdentifiers(QDomElement &identifiersElement) 0148 { 0149 for (int i = 0; i < m_doc->identifierCount(); ++i) { 0150 // create the node 0151 QDomElement identifier = m_domDoc.createElement(KVTML_IDENTIFIER); 0152 0153 // set the id 0154 identifier.setAttribute(KVTML_ID, QString::number(i)); 0155 0156 // record the identifier as the locale for now 0157 // TODO: when support for more parts of the identifier is in the document class (name, type, etc.) store those here as well 0158 identifier.appendChild(newTextElement(KVTML_NAME, m_doc->identifier(i).name())); 0159 0160 identifier.appendChild(newTextElement(KVTML_LOCALE, m_doc->identifier(i).locale())); 0161 0162 // record articles 0163 QDomElement article = m_domDoc.createElement(KVTML_ARTICLE); 0164 writeArticle(article, i); 0165 if (article.hasChildNodes()) { 0166 identifier.appendChild(article); 0167 } 0168 0169 // record personalpronouns 0170 QDomElement personalpronouns = m_domDoc.createElement(KVTML_PERSONALPRONOUNS); 0171 writePersonalPronoun(personalpronouns, m_doc->identifier(i).personalPronouns()); 0172 if (personalpronouns.hasChildNodes()) { 0173 identifier.appendChild(personalpronouns); 0174 } 0175 0176 // tenses 0177 foreach (const QString &tense, m_doc->identifier(i).tenseList()) { 0178 if (!(tense.isNull())) { 0179 identifier.appendChild(newTextElement(KVTML_TENSE, tense)); 0180 } 0181 } 0182 // add this identifier to the group 0183 identifiersElement.appendChild(identifier); 0184 } 0185 return true; 0186 } 0187 0188 bool KEduVocKvtml2Writer::writeLessons(KEduVocLesson *parentLesson, QDomElement &lessonsElement) 0189 { 0190 // iterate over child lessons. 0191 // the first time this is called with the root lesson which does not have a <lesson> entry. 0192 for (int i = 0; i < parentLesson->childContainerCount(); i++) { 0193 KEduVocLesson *lesson = static_cast<KEduVocLesson *>(parentLesson->childContainer(i)); 0194 // make lesson element 0195 QDomElement thisLessonElement = m_domDoc.createElement(KVTML_CONTAINER); 0196 0197 // add a name 0198 thisLessonElement.appendChild(newTextElement(KVTML_NAME, lesson->name())); 0199 0200 // add a inquery tag 0201 if (lesson->inPractice()) { 0202 thisLessonElement.appendChild(newTextElement(KVTML_INPRACTICE, KVTML_TRUE)); 0203 } 0204 0205 // child lessons 0206 writeLessons(lesson, thisLessonElement); 0207 0208 // child entries 0209 foreach (KEduVocExpression *entry, lesson->entries()) { 0210 QDomElement entryElement = m_domDoc.createElement(KVTML_ENTRY); 0211 entryElement.setAttribute(KVTML_ID, QString::number(m_allEntries.indexOf(entry))); 0212 thisLessonElement.appendChild(entryElement); 0213 } 0214 lessonsElement.appendChild(thisLessonElement); 0215 } 0216 return true; 0217 } 0218 0219 void KEduVocKvtml2Writer::writeSynonymAntonymFalseFriend(QDomElement &parentElement) 0220 { 0221 QList<KEduVocTranslation *> currentList; 0222 QDomElement synonymElement; 0223 // synonym, antonym, false friend 0224 for (int type = KEduVocTranslation::Synonym; type <= KEduVocTranslation::FalseFriend; type++) { 0225 switch (type) { 0226 case KEduVocTranslation::Synonym: 0227 synonymElement = m_domDoc.createElement(KVTML_SYNONYM); 0228 currentList = m_synonyms; 0229 break; 0230 case KEduVocTranslation::Antonym: 0231 synonymElement = m_domDoc.createElement(KVTML_ANTONYM); 0232 currentList = m_antonyms; 0233 break; 0234 case KEduVocTranslation::FalseFriend: 0235 synonymElement = m_domDoc.createElement(KVTML_FALSEFRIEND); 0236 currentList = m_falseFriends; 0237 break; 0238 } 0239 0240 while (!currentList.isEmpty()) { 0241 // after writing a translation, remove it from the list 0242 KEduVocTranslation *translation = currentList.takeFirst(); 0243 0244 QDomElement relatedElement; 0245 QList<KEduVocTranslation *> list; 0246 switch (type) { 0247 case KEduVocTranslation::Synonym: 0248 list = translation->synonyms(); 0249 break; 0250 case KEduVocTranslation::Antonym: 0251 list = translation->antonyms(); 0252 break; 0253 case KEduVocTranslation::FalseFriend: 0254 list = translation->falseFriends(); 0255 break; 0256 } 0257 foreach (KEduVocTranslation *synonym, list) { 0258 // if it is not in the list it has already been written and we can move on 0259 if (currentList.contains(synonym)) { 0260 relatedElement = m_domDoc.createElement(KVTML_PAIR); 0261 0262 // fill the entry element but only add later if it is valid 0263 QDomElement entryElement = m_domDoc.createElement(KVTML_ENTRY); 0264 entryElement.setAttribute(KVTML_ID, QString::number(m_allEntries.indexOf(translation->entry()))); 0265 // find out which id that is... silly 0266 foreach (int index, translation->entry()->translationIndices()) { 0267 if (translation->entry()->translation(index) == translation) { 0268 // create <translation id="123"> 0269 QDomElement translationElement = m_domDoc.createElement(KVTML_TRANSLATION); 0270 translationElement.setAttribute(KVTML_ID, QString::number(index)); 0271 entryElement.appendChild(translationElement); 0272 break; 0273 } 0274 } 0275 0276 relatedElement.appendChild(entryElement); 0277 0278 QDomElement partnerElement = m_domDoc.createElement(KVTML_ENTRY); 0279 partnerElement.setAttribute(KVTML_ID, QString::number(m_allEntries.indexOf(synonym->entry()))); 0280 // find out which id that is 0281 foreach (int index, synonym->entry()->translationIndices()) { 0282 if (synonym->entry()->translation(index) == synonym) { 0283 // create <translation id="123"> 0284 QDomElement translationElement = m_domDoc.createElement(KVTML_TRANSLATION); 0285 translationElement.setAttribute(KVTML_ID, QString::number(index)); 0286 partnerElement.appendChild(translationElement); 0287 break; 0288 } 0289 } 0290 relatedElement.appendChild(partnerElement); 0291 synonymElement.appendChild(relatedElement); 0292 } 0293 } 0294 } 0295 if (synonymElement.hasChildNodes()) { 0296 parentElement.appendChild(synonymElement); 0297 } 0298 } // iterate over types 0299 } 0300 /* 0301 bool KEduVocKvtml2Writer::writeRelated(QDomElement & parentElement, QList< KEduVocTranslation * > relatedList) 0302 { 0303 foreach (KEduVocTranslation* synonym, translation->synonyms()) { 0304 QDomElement entryElement = m_domDoc.createElement( KVTML_ENTRY ); 0305 entryElement.setAttribute( KVTML_ID, QString::number(m_allEntries.indexOf(translation->entry())) ); 0306 0307 // find out which id that is... silly 0308 foreach(int index, translation->entry()->translationIndices()) { 0309 if (translation->entry()->translation(index) == translation) { 0310 // create <translation id="123"> 0311 QDomElement translationElement = m_domDoc.createElement( KVTML_TRANSLATION ); 0312 translationElement.setAttribute( KVTML_ID, QString::number(index) ); 0313 entryElement.appendChild(translationElement); 0314 } 0315 } 0316 parentElement.appendChild( entryElement ); 0317 } 0318 }*/ 0319 0320 bool KEduVocKvtml2Writer::writeArticle(QDomElement &articleElement, int language) 0321 { 0322 ///@todo only write if not empty 0323 QMap<int, KEduVocWordFlag::Flags> numbers; 0324 numbers[0] = KEduVocWordFlag::Singular; 0325 numbers[1] = KEduVocWordFlag::Dual; 0326 numbers[2] = KEduVocWordFlag::Plural; 0327 QMap<int, KEduVocWordFlag::Flags> genders; 0328 genders[0] = KEduVocWordFlag::Masculine; 0329 genders[1] = KEduVocWordFlag::Feminine; 0330 genders[2] = KEduVocWordFlag::Neuter; 0331 QMap<int, KEduVocWordFlag::Flags> defs; 0332 defs[0] = KEduVocWordFlag::Definite; 0333 defs[1] = KEduVocWordFlag::Indefinite; 0334 0335 for (int num = 0; num <= 2; num++) { 0336 QDomElement numberElement = m_domDoc.createElement(KVTML_GRAMMATICAL_NUMBER[num]); 0337 0338 for (int def = 0; def <= 1; def++) { 0339 QDomElement defElement = m_domDoc.createElement(KVTML_GRAMMATICAL_DEFINITENESS[def]); 0340 0341 for (int gen = 0; gen <= 2; gen++) { 0342 QString articleString = m_doc->identifier(language).article().article(numbers[num] | genders[gen] | defs[def]); 0343 if (!articleString.isEmpty()) { 0344 defElement.appendChild(newTextElement(KVTML_GRAMMATICAL_GENDER[gen], articleString)); 0345 } 0346 } 0347 if (defElement.hasChildNodes()) { 0348 numberElement.appendChild(defElement); 0349 } 0350 } 0351 if (numberElement.hasChildNodes()) { 0352 articleElement.appendChild(numberElement); 0353 } 0354 } 0355 return true; 0356 } 0357 0358 bool KEduVocKvtml2Writer::writeWordTypes(QDomElement &typesElement, KEduVocWordType *parentContainer) 0359 { 0360 foreach (KEduVocContainer *container, parentContainer->childContainers()) { 0361 KEduVocWordType *wordType = static_cast<KEduVocWordType *>(container); 0362 0363 QDomElement typeDefinitionElement = m_domDoc.createElement(KVTML_CONTAINER); 0364 typeDefinitionElement.appendChild(newTextElement(KVTML_NAME, wordType->name())); 0365 0366 if (wordType->wordType().testFlag(KEduVocWordFlag::Noun)) { 0367 if (wordType->wordType().testFlag(KEduVocWordFlag::Masculine)) 0368 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_MALE)); 0369 0370 else if (wordType->wordType().testFlag(KEduVocWordFlag::Feminine)) 0371 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_FEMALE)); 0372 0373 else if (wordType->wordType().testFlag(KEduVocWordFlag::Neuter)) 0374 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL)); 0375 else 0376 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_NOUN)); 0377 } else if (wordType->wordType().testFlag(KEduVocWordFlag::Verb)) 0378 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_VERB)); 0379 0380 else if (wordType->wordType().testFlag(KEduVocWordFlag::Adjective)) 0381 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_ADJECTIVE)); 0382 0383 else if (wordType->wordType().testFlag(KEduVocWordFlag::Adverb)) 0384 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_ADVERB)); 0385 0386 else if (wordType->wordType().testFlag(KEduVocWordFlag::Conjunction)) 0387 typeDefinitionElement.appendChild(newTextElement(KVTML_SPECIALWORDTYPE, KVTML_SPECIALWORDTYPE_CONJUNCTION)); 0388 0389 // child entries 0390 0391 // child entries 0392 foreach (KEduVocExpression *entry, wordType->entries()) { 0393 QDomElement entryElement = m_domDoc.createElement(KVTML_ENTRY); 0394 entryElement.setAttribute(KVTML_ID, QString::number(m_allEntries.indexOf(entry))); 0395 for (int translation = 0; translation < m_doc->identifierCount(); translation++) { 0396 if (entry->translation(translation)->wordType() == wordType) { 0397 QDomElement translationElement = m_domDoc.createElement(KVTML_TRANSLATION); 0398 // create <translation id="123"> 0399 translationElement.setAttribute(KVTML_ID, QString::number(translation)); 0400 // append both 0401 entryElement.appendChild(translationElement); 0402 } 0403 } 0404 typeDefinitionElement.appendChild(entryElement); 0405 } 0406 0407 writeWordTypes(typeDefinitionElement, wordType); 0408 0409 typesElement.appendChild(typeDefinitionElement); 0410 } 0411 return true; 0412 } 0413 0414 bool KEduVocKvtml2Writer::writeLeitnerBoxes(QDomElement &leitnerParentElement, KEduVocLeitnerBox *parentContainer) 0415 { 0416 foreach (KEduVocContainer *container, parentContainer->childContainers()) { 0417 KEduVocLeitnerBox *leitnerBox = static_cast<KEduVocLeitnerBox *>(container); 0418 0419 QDomElement containerElement = m_domDoc.createElement(KVTML_CONTAINER); 0420 containerElement.appendChild(newTextElement(KVTML_NAME, leitnerBox->name())); 0421 0422 // child entries 0423 foreach (KEduVocExpression *entry, leitnerBox->entries()) { 0424 QDomElement entryElement = m_domDoc.createElement(KVTML_ENTRY); 0425 entryElement.setAttribute(KVTML_ID, QString::number(m_allEntries.indexOf(entry))); 0426 for (int translation = 0; translation < m_doc->identifierCount(); translation++) { 0427 if (entry->translation(translation)->leitnerBox() == leitnerBox) { 0428 QDomElement translationElement = m_domDoc.createElement(KVTML_TRANSLATION); 0429 // create <translation id="123"> 0430 translationElement.setAttribute(KVTML_ID, QString::number(translation)); 0431 // append both 0432 entryElement.appendChild(translationElement); 0433 } 0434 } 0435 containerElement.appendChild(entryElement); 0436 } 0437 0438 leitnerParentElement.appendChild(containerElement); 0439 } 0440 return true; 0441 } 0442 0443 bool KEduVocKvtml2Writer::writeEntries(QDomElement &entriesElement) 0444 { 0445 m_allEntries = m_doc->lesson()->entries(KEduVocLesson::Recursive); 0446 0447 // loop through entries 0448 for (int i = 0; i < m_allEntries.count(); ++i) { 0449 KEduVocExpression *thisEntry = m_allEntries.value(i); 0450 0451 // write entry tag 0452 QDomElement entryElement = m_domDoc.createElement(KVTML_ENTRY); 0453 0454 // add id 0455 entryElement.setAttribute(KVTML_ID, QString::number(i)); 0456 0457 // write deactivated 0458 if (!thisEntry->isActive()) { 0459 entryElement.appendChild(newTextElement(KVTML_DEACTIVATED, KVTML_TRUE)); 0460 } 0461 0462 // loop through translations 0463 foreach (int trans, thisEntry->translationIndices()) { 0464 // write translations 0465 QDomElement translation = m_domDoc.createElement(KVTML_TRANSLATION); 0466 translation.setAttribute(KVTML_ID, QString::number(trans)); 0467 writeTranslation(translation, thisEntry->translation(trans)); 0468 entryElement.appendChild(translation); 0469 } 0470 // add this entry to the entriesElement 0471 entriesElement.appendChild(entryElement); 0472 } 0473 return true; 0474 } 0475 0476 bool KEduVocKvtml2Writer::writeTranslation(QDomElement &translationElement, KEduVocTranslation *translation) 0477 { 0478 // so far only for KEduVocWord - text and grades 0479 translation->toKVTML2(translationElement); 0480 0481 // comparison 0482 if (!(translation->comparativeForm().text().isEmpty() || translation->superlativeForm().text().isEmpty())) { 0483 qDebug() << "Write comp"; 0484 QDomElement comparisonElement = m_domDoc.createElement(KVTML_COMPARISON); 0485 translationElement.appendChild(comparisonElement); 0486 0487 QDomElement comparativeElement = m_domDoc.createElement(KVTML_COMPARATIVE); 0488 comparisonElement.appendChild(comparativeElement); 0489 translation->comparativeForm().toKVTML2(comparativeElement); 0490 0491 QDomElement superlativeElement = m_domDoc.createElement(KVTML_SUPERLATIVE); 0492 comparisonElement.appendChild(superlativeElement); 0493 translation->superlativeForm().toKVTML2(superlativeElement); 0494 } 0495 0496 if (translation->article().practiceCount() != 0) { 0497 QDomElement articleElement = m_domDoc.createElement(KVTML_ARTICLE); 0498 translation->article().toKVTML2(articleElement); 0499 translationElement.appendChild(articleElement); 0500 } 0501 0502 // multiplechoice 0503 if (!translation->getMultipleChoice().isEmpty()) { 0504 QDomElement multipleChoiceElement = m_domDoc.createElement(KVTML_MULTIPLECHOICE); 0505 writeMultipleChoice(multipleChoiceElement, translation); 0506 translationElement.appendChild(multipleChoiceElement); 0507 } 0508 0509 // image 0510 if (!translation->imageUrl().isEmpty()) { 0511 QString urlString; 0512 const QUrl docDirUrl = m_doc->url().adjusted(QUrl::RemoveFilename); 0513 if (docDirUrl.isParentOf(translation->imageUrl())) { 0514 // try to save as relative url 0515 const QDir dir(docDirUrl.toLocalFile()); 0516 urlString = QUrl::fromLocalFile(dir.relativeFilePath(translation->imageUrl().toLocalFile())).url(); 0517 } else { 0518 urlString = translation->imageUrl().url(); 0519 } 0520 translationElement.appendChild(newTextElement(KVTML_IMAGE, urlString)); 0521 } 0522 0523 // sound 0524 if (!translation->soundUrl().isEmpty()) { 0525 QString urlString; 0526 const QUrl docDirUrl = m_doc->url().adjusted(QUrl::RemoveFilename); 0527 if (docDirUrl.isParentOf(translation->soundUrl())) { 0528 // try to save as relative url 0529 const QDir dir(docDirUrl.toLocalFile()); 0530 urlString = QUrl::fromLocalFile(dir.relativeFilePath(translation->soundUrl().toLocalFile())).url(); 0531 } else { 0532 urlString = translation->soundUrl().url(); 0533 } 0534 translationElement.appendChild(newTextElement(KVTML_SOUND, urlString)); 0535 } 0536 0537 // synonym, antonym, false friend 0538 // add to the list if it has any, write later since we want them separate 0539 if (!translation->synonyms().isEmpty()) { 0540 m_synonyms.append(translation); 0541 } 0542 if (!translation->antonyms().isEmpty()) { 0543 m_antonyms.append(translation); 0544 } 0545 if (!translation->falseFriends().isEmpty()) { 0546 m_falseFriends.append(translation); 0547 } 0548 return true; 0549 } 0550 0551 ///@todo write false friends 0552 // <falsefriend fromid="0"></falsefriend> 0553 // loop through the identifiers 0554 // for ( int i = 0; i < m_doc->identifierCount(); ++i ) { 0555 // // see if this identifier has a falsefriend in this translation 0556 // QString thisFriend = translation->falseFriend( i ); 0557 // if ( !thisFriend.isEmpty() ) { 0558 // // if so, create it, and set the fromid to i 0559 // QDomElement thisFriendElement = newTextElement( KVTML_FALSEFRIEND, thisFriend ); 0560 // thisFriendElement.setAttribute( KVTML_FROMID, QString::number( i ) ); 0561 // translationElement.appendChild( thisFriendElement ); 0562 // } 0563 // } 0564 0565 bool KEduVocKvtml2Writer::writeMultipleChoice(QDomElement &multipleChoiceElement, KEduVocTranslation *translation) 0566 /* 0567 <multiplechoice> 0568 <choice>good</choice> 0569 <choice>better</choice> 0570 <choice>best</choice> 0571 <choice>best 2</choice> 0572 <choice>best 3</choice> 0573 </multiplechoice> 0574 */ 0575 { 0576 foreach (const QString &choice, translation->getMultipleChoice()) { 0577 multipleChoiceElement.appendChild(newTextElement(KVTML_CHOICE, choice)); 0578 } 0579 return true; 0580 } 0581 0582 QDomElement KEduVocKvtml2Writer::newTextElement(const QString &elementName, const QString &text) 0583 { 0584 QDomElement retval = m_domDoc.createElement(elementName); 0585 QDomText textNode = m_domDoc.createTextNode(text); 0586 retval.appendChild(textNode); 0587 return retval; 0588 } 0589 0590 bool KEduVocKvtml2Writer::writePersonalPronoun(QDomElement &pronounElement, const KEduVocPersonalPronoun &pronoun) 0591 { 0592 // general pronoun properties 0593 if (pronoun.maleFemaleDifferent()) { 0594 pronounElement.appendChild(m_domDoc.createElement(KVTML_THIRD_PERSON_MALE_FEMALE_DIFFERENT)); 0595 } 0596 if (pronoun.neutralExists()) { 0597 pronounElement.appendChild(m_domDoc.createElement(KVTML_THIRD_PERSON_NEUTRAL_EXISTS)); 0598 } 0599 if (pronoun.dualExists()) { 0600 pronounElement.appendChild(m_domDoc.createElement(KVTML_DUAL_EXISTS)); 0601 } 0602 0603 QMap<int, KEduVocWordFlag::Flags> numbers; 0604 numbers[0] = KEduVocWordFlag::Singular; 0605 numbers[1] = KEduVocWordFlag::Dual; 0606 numbers[2] = KEduVocWordFlag::Plural; 0607 QMap<int, KEduVocWordFlag::Flags> persons; 0608 persons[0] = KEduVocWordFlag::First; 0609 persons[1] = KEduVocWordFlag::Second; 0610 persons[2] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Masculine); 0611 persons[3] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Feminine); 0612 persons[4] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Neuter); 0613 0614 // the actual pronouns 0615 for (int num = 0; num < 3; num++) { 0616 QDomElement numberElement = m_domDoc.createElement(KVTML_GRAMMATICAL_NUMBER[num]); 0617 for (int person = 0; person < 5; person++) { 0618 QString pronounString = pronoun.personalPronoun(numbers[num] | persons[person]); 0619 if (!pronounString.isEmpty()) { 0620 numberElement.appendChild(newTextElement(KVTML_GRAMMATICAL_PERSON[person], pronounString)); 0621 } 0622 } 0623 if (numberElement.hasChildNodes()) { 0624 pronounElement.appendChild(numberElement); 0625 } 0626 } 0627 return true; 0628 } 0629 0630 void KEduVocKvtml2Writer::appendTextElement(QDomElement &parent, const QString &elementName, const QString &text) 0631 { 0632 // empty will never be written 0633 if (text.isEmpty()) { 0634 return; 0635 } 0636 0637 QDomDocument domDoc = parent.ownerDocument(); 0638 QDomElement element = domDoc.createElement(elementName); 0639 parent.appendChild(element); 0640 QDomText textNode = domDoc.createTextNode(text); 0641 element.appendChild(textNode); 0642 }