File indexing completed on 2022-11-22 13:01:10

0001 /*
0002     SPDX-FileCopyrightText: 2008 Frederik Gladhorn <gladhorn@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "languagepropertiespage.h"
0007 
0008 #include "documentproperties.h"
0009 #include "languagesettings.h"
0010 #include <KMessageBox>
0011 
0012 #include <KLocalizedString>
0013 #include <QCheckBox>
0014 #include <QDBusInterface>
0015 #include <QDBusReply>
0016 #include <QDebug>
0017 #include <QInputDialog>
0018 #include <QLabel>
0019 #include <QLineEdit>
0020 #include <sonnet/speller.h>
0021 
0022 #include <KEduVocDocument>
0023 #include <KEduVocExpression>
0024 #include <KEduVocLesson>
0025 
0026 #include <parleydocument.h>
0027 
0028 #define TENSE_TAG ". "
0029 
0030 LanguagePropertiesPage::LanguagePropertiesPage(KEduVocDocument *doc, int identifierIndex, QWidget *parent)
0031     : QWidget(parent)
0032     , m_doc(doc)
0033     , m_identifierIndex(identifierIndex)
0034 {
0035     setupUi(this);
0036 
0037     connect(localeComboBox, QOverload<const QString &>::of(&KComboBox::currentTextChanged), this, &LanguagePropertiesPage::localeChanged);
0038     connect(downloadGrammarButton, &QPushButton::clicked, this, &LanguagePropertiesPage::downloadGrammar);
0039 
0040     // qmap automatically sorts by keys
0041     QMap<QString, QString> languageCodeMap = DocumentProperties::localeLangsMap();
0042 
0043     // add the language, but also it's code as data
0044     for (auto iter = languageCodeMap.cbegin(); iter != languageCodeMap.cend(); ++iter) {
0045         localeComboBox->addItem(iter.key(), iter.value());
0046     }
0047 
0048     if (m_identifierIndex < m_doc->identifierCount()) {
0049         localeComboBox->setCurrentIndex(localeComboBox->findData(m_doc->identifier(m_identifierIndex).locale()));
0050 
0051         identifierNameLineEdit->setText(m_doc->identifier(m_identifierIndex).name());
0052     }
0053 
0054     int index = (m_identifierIndex < m_doc->identifierCount() ? m_identifierIndex : 0);
0055     LanguageSettings settings(m_doc->identifier(index).locale());
0056     settings.load();
0057 
0058     // fonts
0059     editorFont->setFont(settings.editorFont());
0060     practiceFont->setFont(settings.practiceFont());
0061 
0062     // keyboard layout
0063     // try to talk to kxbk - get a list of keyboard layouts
0064     QDBusInterface kxbk(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"));
0065     QDBusReply<QStringList> reply = kxbk.call(QStringLiteral("getLayoutsList"));
0066     if (reply.isValid()) {
0067         QStringList layouts = reply;
0068         layouts.prepend(QString());
0069         keyboardLayoutComboBox->clear();
0070         keyboardLayoutComboBox->addItems(layouts);
0071         keyboardLayoutComboBox->setEnabled(true);
0072 
0073         QDBusReply<QString> currentLayout = kxbk.call(QStringLiteral("getCurrentLayout"));
0074         keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(currentLayout));
0075         if (m_identifierIndex < m_doc->identifierCount()) {
0076             if (!settings.keyboardLayout().isEmpty()) {
0077                 keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(settings.keyboardLayout()));
0078             }
0079         }
0080     } else {
0081         qDebug() << "kxkb dbus error";
0082         keyboardLayoutComboBox->setEnabled(false);
0083         keyboardLayoutComboBox->addItem(i18n("No KDE keyboard selector found."));
0084     }
0085 
0086     Sonnet::Speller speller;
0087     QMap<QString, QString> dicts = speller.availableDictionaries();
0088     QMap<QString, QString>::const_iterator iter = dicts.constBegin();
0089     while (iter != dicts.constEnd()) {
0090         spellcheckerComboBox->addItem(iter.key(), iter.value());
0091         ++iter;
0092     }
0093     spellcheckerComboBox->model()->sort(0);
0094     spellcheckerComboBox->setCurrentIndex(spellcheckerComboBox->findData(settings.spellChecker()));
0095     loadGrammarFromDocument();
0096 }
0097 
0098 void LanguagePropertiesPage::setLanguageIdentifierIndex(int newIndex)
0099 {
0100     m_identifierIndex = newIndex;
0101 }
0102 
0103 namespace DocumentHelper
0104 {
0105 void fetchGrammar(KEduVocDocument *doc, int languageIndex);
0106 }
0107 
0108 void LanguagePropertiesPage::downloadGrammar()
0109 {
0110     DocumentHelper::fetchGrammar(m_doc, m_identifierIndex);
0111     loadGrammarFromDocument();
0112 }
0113 
0114 void LanguagePropertiesPage::loadGrammarFromDocument()
0115 {
0116     if (m_identifierIndex < m_doc->identifierCount()) {
0117         // articles
0118         KEduVocArticle articles = m_doc->identifier(m_identifierIndex).article();
0119 
0120         def_male->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine));
0121         indef_male->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine));
0122 
0123         def_female->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine));
0124         indef_female->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine));
0125 
0126         def_natural->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter));
0127         indef_natural->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter));
0128 
0129         def_male_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine));
0130         indef_male_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine));
0131 
0132         def_female_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine));
0133         indef_female_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine));
0134 
0135         def_natural_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter));
0136         indef_natural_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter));
0137 
0138         // personal pronouns
0139         const KEduVocWordFlags numS = KEduVocWordFlag::Singular;
0140         const KEduVocWordFlags numD = KEduVocWordFlag::Dual;
0141         const KEduVocWordFlags numP = KEduVocWordFlag::Plural;
0142 
0143         KEduVocPersonalPronoun pronoun = m_doc->identifier(m_identifierIndex).personalPronouns();
0144 
0145         first_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numS));
0146         second_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numS));
0147         thirdM_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS));
0148         thirdF_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS));
0149         thirdN_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS));
0150 
0151         dualFirstLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numD));
0152         dualSecondLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numD));
0153         dualThirdMaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD));
0154         dualThirdFemaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD));
0155         dualThirdNeutralLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numD));
0156 
0157         first_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numP));
0158         second_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numP));
0159         thirdM_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP));
0160         thirdF_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP));
0161         thirdN_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP));
0162 
0163         maleFemaleDifferCheckBox->setChecked(pronoun.maleFemaleDifferent());
0164         neutralCheckBox->setChecked(pronoun.neutralExists());
0165         dualCheckBox->setChecked(pronoun.dualExists());
0166     }
0167 
0168     // update shown labels etc...
0169     updateCheckBoxes();
0170 
0171     connect(maleFemaleDifferCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes);
0172     connect(neutralCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes);
0173     connect(dualCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes);
0174 
0175     // tenses
0176     connect(tenseList, &QListWidget::currentRowChanged, this, &LanguagePropertiesPage::slotTenseChosen);
0177     connect(deleteButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotDeleteTense);
0178     connect(modifyButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotModifyTense);
0179     connect(newButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotNewTense);
0180 
0181     if (m_identifierIndex < m_doc->identifierCount()) {
0182         int i = 1;
0183         const QStringList tenses = m_doc->identifier(m_identifierIndex).tenseList();
0184         for (const QString &tenseName : tenses) {
0185             tenseList->addItem(QStringLiteral("%1").arg(i++, 2).append(TENSE_TAG).append(tenseName));
0186             tenseIndex.append(i);
0187         }
0188     }
0189 
0190     m_currentTense = 0;
0191     if (tenseList->count() > 0) {
0192         tenseList->setCurrentRow(m_currentTense);
0193     }
0194 
0195     modifyButton->setEnabled(tenseList->count() > 0);
0196     deleteButton->setEnabled(tenseList->count() > 0);
0197     tenseList->setFocus();
0198 }
0199 
0200 void LanguagePropertiesPage::accept()
0201 {
0202     if (!isEnabled()) {
0203         // disabled pages are deleted languages
0204         return;
0205     }
0206 
0207     // general
0208     QString locale = localeComboBox->itemData(localeComboBox->currentIndex()).toString();
0209 
0210     // if no locales are found (kdebase not installed?) at least fall back to using the language name as locale.
0211     if (locale.isEmpty()) {
0212         locale = identifierNameLineEdit->text();
0213     }
0214     m_doc->identifier(m_identifierIndex).setLocale(locale);
0215     m_doc->identifier(m_identifierIndex).setName(identifierNameLineEdit->text());
0216 
0217     LanguageSettings settings(locale);
0218 
0219     settings.setEditorFont(editorFont->font());
0220     settings.setPracticeFont(practiceFont->font());
0221 
0222     if (keyboardLayoutComboBox->isEnabled()) {
0223         settings.setKeyboardLayout(keyboardLayoutComboBox->currentText());
0224     }
0225     int index = spellcheckerComboBox->currentIndex();
0226     settings.setSpellChecker(spellcheckerComboBox->itemData(index).toString());
0227     settings.save();
0228 
0229     // articles
0230     const KEduVocWordFlag::Flags artSing = KEduVocWordFlag::Singular;
0231     //    const KEduVocWordFlag::Flags artDual = KEduVocWordFlag::Dual;
0232     const KEduVocWordFlag::Flags artPlur = KEduVocWordFlag::Plural;
0233 
0234     const KEduVocWordFlag::Flags artDef = KEduVocWordFlag::Definite;
0235     const KEduVocWordFlag::Flags artIndef = KEduVocWordFlag::Indefinite;
0236 
0237     KEduVocArticle article;
0238 
0239     article.setArticle(def_male->text(), artSing | artDef | KEduVocWordFlag::Masculine);
0240     article.setArticle(indef_male->text(), artSing | artIndef | KEduVocWordFlag::Masculine);
0241     article.setArticle(def_female->text(), artSing | artDef | KEduVocWordFlag::Feminine);
0242     article.setArticle(indef_female->text(), artSing | artIndef | KEduVocWordFlag::Feminine);
0243     article.setArticle(def_natural->text(), artSing | artDef | KEduVocWordFlag::Neuter);
0244     article.setArticle(indef_natural->text(), artSing | artIndef | KEduVocWordFlag::Neuter);
0245 
0246     article.setArticle(def_male_plural->text(), artPlur | artDef | KEduVocWordFlag::Masculine);
0247     article.setArticle(indef_male_plural->text(), artPlur | artIndef | KEduVocWordFlag::Masculine);
0248     article.setArticle(def_female_plural->text(), artPlur | artDef | KEduVocWordFlag::Feminine);
0249     article.setArticle(indef_female_plural->text(), artPlur | artIndef | KEduVocWordFlag::Feminine);
0250     article.setArticle(def_natural_plural->text(), artPlur | artDef | KEduVocWordFlag::Neuter);
0251     article.setArticle(indef_natural_plural->text(), artPlur | artIndef | KEduVocWordFlag::Neuter);
0252 
0253     m_doc->identifier(m_identifierIndex).setArticle(article);
0254 
0255     // personal pronouns
0256     KEduVocPersonalPronoun pronoun;
0257     const KEduVocWordFlags numS = KEduVocWordFlag::Singular;
0258     const KEduVocWordFlags numD = KEduVocWordFlag::Dual;
0259     const KEduVocWordFlags numP = KEduVocWordFlag::Plural;
0260 
0261     pronoun.setPersonalPronoun(first_singular->text(), KEduVocWordFlag::First | numS);
0262     pronoun.setPersonalPronoun(second_singular->text(), KEduVocWordFlag::Second | numS);
0263     pronoun.setPersonalPronoun(thirdM_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS);
0264     pronoun.setPersonalPronoun(thirdF_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS);
0265     pronoun.setPersonalPronoun(thirdN_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS);
0266 
0267     pronoun.setPersonalPronoun(dualFirstLineEdit->text(), KEduVocWordFlag::First | numD);
0268     pronoun.setPersonalPronoun(dualSecondLineEdit->text(), KEduVocWordFlag::Second | numD);
0269     pronoun.setPersonalPronoun(dualThirdMaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD);
0270     pronoun.setPersonalPronoun(dualThirdFemaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD);
0271     pronoun.setPersonalPronoun(dualThirdNeutralLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numD);
0272 
0273     pronoun.setPersonalPronoun(first_plural->text(), KEduVocWordFlag::First | numP);
0274     pronoun.setPersonalPronoun(second_plural->text(), KEduVocWordFlag::Second | numP);
0275     pronoun.setPersonalPronoun(thirdM_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP);
0276     pronoun.setPersonalPronoun(thirdF_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP);
0277     pronoun.setPersonalPronoun(thirdN_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP);
0278 
0279     pronoun.setMaleFemaleDifferent(maleFemaleDifferCheckBox->isChecked());
0280     pronoun.setNeutralExists(neutralCheckBox->isChecked());
0281     pronoun.setDualExists(dualCheckBox->isChecked());
0282 
0283     m_doc->identifier(m_identifierIndex).setPersonalPronouns(pronoun);
0284 
0285     // tenses
0286     QStringList tenses;
0287 
0288     QString str;
0289     for (int i = 0; i < (int)tenseList->count(); i++) {
0290         str = tenseList->item(i)->text();
0291         tenses.append(str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length()));
0292     }
0293 
0294     m_doc->identifier(m_identifierIndex).setTenseList(tenses);
0295 }
0296 
0297 void LanguagePropertiesPage::updateCheckBoxes()
0298 {
0299     bool maleFemale = maleFemaleDifferCheckBox->isChecked();
0300     bool neutral = neutralCheckBox->isChecked();
0301     bool dual = dualCheckBox->isChecked();
0302 
0303     neutralCheckBox->setVisible(maleFemale);
0304     male_c_label->setVisible(maleFemale);
0305     female_c_label->setVisible(maleFemale);
0306     thirdM_singular->setVisible(maleFemale);
0307     thirdF_singular->setVisible(maleFemale);
0308     thirdM_plural->setVisible(maleFemale);
0309     thirdF_plural->setVisible(maleFemale);
0310 
0311     dualLabel->setVisible(dual);
0312     dualFirstLineEdit->setVisible(dual);
0313     dualSecondLineEdit->setVisible(dual);
0314 
0315     dualThirdMaleLineEdit->setVisible(dual && maleFemale);
0316     dualThirdFemaleLineEdit->setVisible(dual && maleFemale);
0317 
0318     if (!maleFemale) {
0319         natural_c_label->setVisible(false);
0320         thirdN_singular->setVisible(true);
0321         thirdN_plural->setVisible(true);
0322         dualThirdNeutralLineEdit->setVisible(dual);
0323     } else {
0324         natural_c_label->setVisible(neutral);
0325         thirdN_singular->setVisible(neutral);
0326         thirdN_plural->setVisible(neutral);
0327         dualThirdNeutralLineEdit->setVisible(dual && neutral);
0328     }
0329 }
0330 
0331 void LanguagePropertiesPage::localeChanged(const QString &locale)
0332 {
0333     identifierNameLineEdit->setText(locale);
0334 }
0335 
0336 // ************** TENSES *********************
0337 
0338 void LanguagePropertiesPage::slotTenseChosen(int index)
0339 {
0340     m_currentTense = index;
0341 }
0342 
0343 void LanguagePropertiesPage::slotNewTense()
0344 {
0345     bool ok;
0346     QString getTense = QInputDialog::getText(this, i18n("Tense Name"), i18n("Enter name of tense:"), QLineEdit::Normal, QString(), &ok);
0347     if (!ok) {
0348         return;
0349     }
0350 
0351     int i = tenseList->count() + 1;
0352     tenseList->addItem(QStringLiteral("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified()));
0353     tenseIndex.append(-(i - 1));
0354 
0355     m_currentTense = tenseList->count();
0356     tenseList->setCurrentRow(i - 1);
0357     modifyButton->setEnabled(true);
0358     deleteButton->setEnabled(true);
0359 }
0360 
0361 void LanguagePropertiesPage::slotModifyTense()
0362 {
0363     if (tenseList->count() != 0 && (int)tenseList->count() > m_currentTense) {
0364         QString str = tenseList->item(m_currentTense)->text();
0365         str = str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length());
0366 
0367         bool ok;
0368         QString getTense = QInputDialog::getText(this, i18n("Tense Name"), i18n("Enter name of tense:"), QLineEdit::Normal, str, &ok);
0369         if (!ok)
0370             return;
0371 
0372         int i = m_currentTense + 1;
0373         tenseList->item(m_currentTense)->setText(QStringLiteral("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified()));
0374     }
0375 }
0376 
0377 void LanguagePropertiesPage::updateListBox(int start)
0378 {
0379     QString str;
0380     for (int i = start; i < (int)tenseList->count(); i++) {
0381         str = tenseList->item(i)->text();
0382         str = str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length());
0383         tenseList->item(i)->setText(QStringLiteral("%1").arg(i + 1, 2).append(TENSE_TAG).append(str));
0384     }
0385 }
0386 
0387 void LanguagePropertiesPage::slotDeleteTense()
0388 {
0389     int act = m_currentTense;
0390     if (tenseList->count() > 0 && (int)tenseList->count() > act) {
0391         QString t = tenseList->item(act)->text();
0392 
0393         const QList<KEduVocExpression *> entries = m_doc->lesson()->entries(KEduVocLesson::Recursive);
0394         for (KEduVocExpression *exp : entries) {
0395             for (int lang = 0; lang < m_doc->identifierCount(); lang++) {
0396                 if (exp->translation(lang)->conjugationTenses().contains(t)) {
0397                     KMessageBox::information(this,
0398                                              i18n("The selected user defined tense could not be deleted\nbecause it is in use."),
0399                                              i18n("Deleting Tense Description"));
0400                     return;
0401                 }
0402             }
0403         }
0404 
0405         delete tenseList->takeItem(act);
0406         tenseIndex.erase(tenseIndex.begin() + act);
0407 
0408         if ((int)tenseList->count() <= act)
0409             act = tenseList->count() - 1;
0410         else
0411             updateListBox(act); // update items after current
0412 
0413         if (act >= 0)
0414             tenseList->setCurrentRow(act);
0415     }
0416     modifyButton->setEnabled(tenseList->count() > 0);
0417     deleteButton->setEnabled(tenseList->count() > 0);
0418 }