File indexing completed on 2024-12-22 04:28:08

0001 /*
0002   SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "autocorrectionsettings.h"
0008 #include "export/exportlibreofficeautocorrection.h"
0009 #include "import/importlibreofficeautocorrection.h"
0010 
0011 #include "settings/textautocorrectionsettings.h"
0012 #include "textautocorrection_debug.h"
0013 
0014 #include <QRegularExpression>
0015 #include <QStandardPaths>
0016 
0017 using namespace TextAutoCorrectionCore;
0018 namespace TextAutoCorrectionCore
0019 {
0020 class AutoCorrectionSettingsPrivate
0021 {
0022 public:
0023     AutoCorrectionUtils::TypographicQuotes mTypographicSingleQuotes;
0024     AutoCorrectionUtils::TypographicQuotes mTypographicDoubleQuotes;
0025     AutoCorrectionUtils::TypographicQuotes mDoubleFrenchQuotes;
0026 
0027     QHash<QString, QString> mAutocorrectEntries;
0028     QHash<QString, QString> mSuperScriptEntries;
0029 
0030     QSet<QString> mUpperCaseExceptions;
0031     QSet<QString> mTwoUpperLetterExceptions;
0032 
0033     QString mCustomWritablePath;
0034     QString mCustomSystemPath;
0035 
0036     QString mAutoCorrectLang;
0037 
0038     QChar mNonBreakingSpace;
0039 
0040     int mMaxFindStringLength = 0;
0041     int mMinFindStringLength = 0;
0042 
0043     bool mSingleSpaces = true; // suppress double spaces.
0044     bool mUppercaseFirstCharOfSentence = false; // convert first letter of a sentence automatically to uppercase
0045     bool mFixTwoUppercaseChars = false; // convert two uppercase characters to one upper and one lowercase.
0046     bool mAutoFractions = true; // replace 1/2 with ½
0047     bool mCapitalizeWeekDays = false;
0048     bool mAdvancedAutocorrect = false; // autocorrection from a list of entries
0049 
0050     bool mReplaceDoubleQuotes = false; // replace double quotes with typographical quotes
0051     bool mReplaceSingleQuotes = false; // replace single quotes with typographical quotes
0052 
0053     bool mAutoFormatUrl = false;
0054     bool mAutoBoldUnderline = false;
0055     bool mEnabled = false;
0056     bool mSuperScriptAppendix = false;
0057 
0058     bool mAddNonBreakingSpace = false;
0059     bool mReplaceDoubleQuotesByFrenchQuotes = false;
0060 };
0061 }
0062 
0063 AutoCorrectionSettings::AutoCorrectionSettings()
0064     : d(new TextAutoCorrectionCore::AutoCorrectionSettingsPrivate)
0065 {
0066     // default double quote open 0x201c
0067     // default double quote close 0x201d
0068     // default single quote open 0x2018
0069     // default single quote close 0x2019
0070     d->mTypographicSingleQuotes = AutoCorrectionUtils::typographicDefaultSingleQuotes();
0071     d->mTypographicDoubleQuotes = AutoCorrectionUtils::typographicDefaultDoubleQuotes();
0072     d->mDoubleFrenchQuotes = AutoCorrectionUtils::typographicDefaultFrenchQuotes();
0073     d->mNonBreakingSpace = QChar(QChar::Nbsp);
0074     readConfig();
0075 }
0076 
0077 AutoCorrectionSettings::~AutoCorrectionSettings() = default;
0078 
0079 void AutoCorrectionSettings::setCapitalizeWeekDays(bool b)
0080 {
0081     d->mCapitalizeWeekDays = b;
0082 }
0083 
0084 void AutoCorrectionSettings::setReplaceDoubleQuotes(bool b)
0085 {
0086     d->mReplaceDoubleQuotes = b;
0087 }
0088 
0089 void AutoCorrectionSettings::setReplaceSingleQuotes(bool b)
0090 {
0091     d->mReplaceSingleQuotes = b;
0092 }
0093 
0094 void AutoCorrectionSettings::setAdvancedAutocorrect(bool b)
0095 {
0096     d->mAdvancedAutocorrect = b;
0097 }
0098 
0099 void AutoCorrectionSettings::setAutoFormatUrl(bool b)
0100 {
0101     d->mAutoFormatUrl = b;
0102 }
0103 
0104 void AutoCorrectionSettings::setAutoBoldUnderline(bool b)
0105 {
0106     d->mAutoBoldUnderline = b;
0107 }
0108 
0109 void AutoCorrectionSettings::setSuperScript(bool b)
0110 {
0111     d->mSuperScriptAppendix = b;
0112 }
0113 
0114 void AutoCorrectionSettings::setAddNonBreakingSpace(bool b)
0115 {
0116     d->mAddNonBreakingSpace = b;
0117 }
0118 
0119 bool AutoCorrectionSettings::isEnabledAutoCorrection() const
0120 {
0121     return d->mEnabled;
0122 }
0123 
0124 bool AutoCorrectionSettings::isUppercaseFirstCharOfSentence() const
0125 {
0126     return d->mUppercaseFirstCharOfSentence;
0127 }
0128 
0129 bool AutoCorrectionSettings::isFixTwoUppercaseChars() const
0130 {
0131     return d->mFixTwoUppercaseChars;
0132 }
0133 
0134 bool AutoCorrectionSettings::isSingleSpaces() const
0135 {
0136     return d->mSingleSpaces;
0137 }
0138 
0139 bool AutoCorrectionSettings::isAutoFractions() const
0140 {
0141     return d->mAutoFractions;
0142 }
0143 
0144 bool AutoCorrectionSettings::isCapitalizeWeekDays() const
0145 {
0146     return d->mCapitalizeWeekDays;
0147 }
0148 
0149 bool AutoCorrectionSettings::isReplaceDoubleQuotes() const
0150 {
0151     return d->mReplaceDoubleQuotes;
0152 }
0153 
0154 bool AutoCorrectionSettings::isReplaceSingleQuotes() const
0155 {
0156     return d->mReplaceSingleQuotes;
0157 }
0158 
0159 bool AutoCorrectionSettings::isAdvancedAutocorrect() const
0160 {
0161     return d->mAdvancedAutocorrect;
0162 }
0163 
0164 bool AutoCorrectionSettings::isAutoFormatUrl() const
0165 {
0166     return d->mAutoFormatUrl;
0167 }
0168 
0169 bool AutoCorrectionSettings::isAutoBoldUnderline() const
0170 {
0171     return d->mAutoBoldUnderline;
0172 }
0173 
0174 bool AutoCorrectionSettings::isSuperScript() const
0175 {
0176     return d->mSuperScriptAppendix;
0177 }
0178 
0179 bool AutoCorrectionSettings::isAddNonBreakingSpace() const
0180 {
0181     return d->mAddNonBreakingSpace;
0182 }
0183 
0184 bool AutoCorrectionSettings::isReplaceDoubleQuotesByFrenchQuotes() const
0185 {
0186     return d->mReplaceDoubleQuotesByFrenchQuotes;
0187 }
0188 
0189 void AutoCorrectionSettings::setEnabledAutoCorrection(bool b)
0190 {
0191     d->mEnabled = b;
0192 }
0193 
0194 void AutoCorrectionSettings::setReplaceDoubleQuotesByFrenchQuotes(bool b)
0195 {
0196     d->mReplaceDoubleQuotesByFrenchQuotes = b;
0197 }
0198 
0199 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes AutoCorrectionSettings::typographicSingleQuotes() const
0200 {
0201     return d->mTypographicSingleQuotes;
0202 }
0203 
0204 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes AutoCorrectionSettings::typographicDoubleQuotes() const
0205 {
0206     return d->mTypographicDoubleQuotes;
0207 }
0208 
0209 void AutoCorrectionSettings::setTypographicSingleQuotes(TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes singleQuote)
0210 {
0211     d->mTypographicSingleQuotes = singleQuote;
0212 }
0213 
0214 void AutoCorrectionSettings::setTypographicDoubleQuotes(AutoCorrectionUtils::TypographicQuotes doubleQuote)
0215 {
0216     d->mTypographicDoubleQuotes = doubleQuote;
0217 }
0218 
0219 void AutoCorrectionSettings::readConfig()
0220 {
0221     d->mAutoBoldUnderline = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->autoBoldUnderline();
0222     d->mAutoFormatUrl = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->autoFormatUrl();
0223     d->mUppercaseFirstCharOfSentence = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->uppercaseFirstCharOfSentence();
0224     d->mFixTwoUppercaseChars = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->fixTwoUppercaseChars();
0225     d->mSingleSpaces = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->singleSpaces();
0226     d->mAutoFractions = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->autoFractions();
0227     d->mCapitalizeWeekDays = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->capitalizeWeekDays();
0228     d->mAdvancedAutocorrect = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->advancedAutocorrect();
0229     d->mReplaceDoubleQuotes = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->replaceDoubleQuotes();
0230     d->mReplaceSingleQuotes = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->replaceSingleQuotes();
0231     d->mEnabled = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->enabled();
0232     d->mSuperScriptAppendix = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->superScript();
0233     d->mAddNonBreakingSpace = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->addNonBreakingSpaceInFrench();
0234     d->mReplaceDoubleQuotesByFrenchQuotes = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->replaceDoubleQuotesByFrenchQuotes();
0235     d->mCustomSystemPath = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->customSystemPath();
0236     d->mCustomWritablePath = TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->customWritablePath();
0237 
0238     d->mTypographicSingleQuotes =
0239         AutoCorrectionUtils::TypographicQuotes::fromString(TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->typographicSingleQuotes());
0240     if (d->mTypographicSingleQuotes.isEmpty()) {
0241         d->mTypographicSingleQuotes = AutoCorrectionUtils::typographicDefaultSingleQuotes();
0242     }
0243     d->mTypographicDoubleQuotes =
0244         AutoCorrectionUtils::TypographicQuotes::fromString(TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->typographicDoubleQuotes());
0245     if (d->mTypographicDoubleQuotes.isEmpty()) {
0246         d->mTypographicDoubleQuotes = AutoCorrectionUtils::typographicDefaultDoubleQuotes();
0247     }
0248     readAutoCorrectionFile();
0249 }
0250 
0251 void AutoCorrectionSettings::writeConfig()
0252 {
0253     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setAutoBoldUnderline(d->mAutoBoldUnderline);
0254     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setAutoFormatUrl(d->mAutoFormatUrl);
0255     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setUppercaseFirstCharOfSentence(d->mUppercaseFirstCharOfSentence);
0256     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setFixTwoUppercaseChars(d->mFixTwoUppercaseChars);
0257     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setSingleSpaces(d->mSingleSpaces);
0258     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setAutoFractions(d->mAutoFractions);
0259     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setCapitalizeWeekDays(d->mCapitalizeWeekDays);
0260     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setAdvancedAutocorrect(d->mAdvancedAutocorrect);
0261     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setReplaceDoubleQuotes(d->mReplaceDoubleQuotes);
0262     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setReplaceSingleQuotes(d->mReplaceSingleQuotes);
0263     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setEnabled(d->mEnabled);
0264     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setSuperScript(d->mSuperScriptAppendix);
0265     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setAddNonBreakingSpaceInFrench(d->mAddNonBreakingSpace);
0266     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setTypographicSingleQuotes(d->mTypographicSingleQuotes.toString());
0267     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setTypographicDoubleQuotes(d->mTypographicDoubleQuotes.toString());
0268     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setReplaceDoubleQuotesByFrenchQuotes(d->mReplaceDoubleQuotesByFrenchQuotes);
0269     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setCustomWritablePath(d->mCustomWritablePath);
0270     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setCustomSystemPath(d->mCustomSystemPath);
0271     TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->requestSync();
0272     writeAutoCorrectionFile();
0273 }
0274 
0275 void AutoCorrectionSettings::setAutoFractions(bool newAutoFractions)
0276 {
0277     d->mAutoFractions = newAutoFractions;
0278 }
0279 
0280 void AutoCorrectionSettings::setSingleSpaces(bool newSingleSpaces)
0281 {
0282     d->mSingleSpaces = newSingleSpaces;
0283 }
0284 
0285 void AutoCorrectionSettings::setFixTwoUppercaseChars(bool newFixTwoUppercaseChars)
0286 {
0287     d->mFixTwoUppercaseChars = newFixTwoUppercaseChars;
0288 }
0289 
0290 void AutoCorrectionSettings::setUppercaseFirstCharOfSentence(bool newUppercaseFirstCharOfSentence)
0291 {
0292     d->mUppercaseFirstCharOfSentence = newUppercaseFirstCharOfSentence;
0293 }
0294 
0295 void AutoCorrectionSettings::setUpperCaseExceptions(const QSet<QString> &exceptions)
0296 {
0297     d->mUpperCaseExceptions = exceptions;
0298 }
0299 
0300 void AutoCorrectionSettings::setTwoUpperLetterExceptions(const QSet<QString> &exceptions)
0301 {
0302     d->mTwoUpperLetterExceptions = exceptions;
0303 }
0304 
0305 QSet<QString> AutoCorrectionSettings::upperCaseExceptions() const
0306 {
0307     return d->mUpperCaseExceptions;
0308 }
0309 
0310 QSet<QString> AutoCorrectionSettings::twoUpperLetterExceptions() const
0311 {
0312     return d->mTwoUpperLetterExceptions;
0313 }
0314 
0315 QString AutoCorrectionSettings::language() const
0316 {
0317     return d->mAutoCorrectLang;
0318 }
0319 
0320 void AutoCorrectionSettings::setLanguage(const QString &lang, bool forceGlobal)
0321 {
0322     if (d->mAutoCorrectLang != lang || forceGlobal) {
0323         d->mAutoCorrectLang = lang;
0324         // Re-read xml file
0325         readAutoCorrectionFile(forceGlobal);
0326     }
0327 }
0328 
0329 bool AutoCorrectionSettings::isFrenchLanguage() const
0330 {
0331     return d->mAutoCorrectLang == QLatin1String("FR_fr") || d->mAutoCorrectLang == QLatin1String("fr");
0332 }
0333 
0334 bool AutoCorrectionSettings::addAutoCorrect(const QString &currentWord, const QString &replaceWord)
0335 {
0336     if (!d->mAutocorrectEntries.contains(currentWord)) {
0337         d->mAutocorrectEntries.insert(currentWord, replaceWord);
0338         writeAutoCorrectionFile();
0339         return true;
0340     } else {
0341         return false;
0342     }
0343 }
0344 
0345 QChar AutoCorrectionSettings::nonBreakingSpace() const
0346 {
0347     return d->mNonBreakingSpace;
0348 }
0349 
0350 void AutoCorrectionSettings::setNonBreakingSpace(const QChar &newNonBreakingSpace)
0351 {
0352     d->mNonBreakingSpace = newNonBreakingSpace;
0353 }
0354 
0355 QHash<QString, QString> AutoCorrectionSettings::superScriptEntries() const
0356 {
0357     return d->mSuperScriptEntries;
0358 }
0359 
0360 void AutoCorrectionSettings::setSuperScriptEntries(const QHash<QString, QString> &newSuperScriptEntries)
0361 {
0362     d->mSuperScriptEntries = newSuperScriptEntries;
0363 }
0364 
0365 void AutoCorrectionSettings::setAutocorrectEntries(const QHash<QString, QString> &entries)
0366 {
0367     d->mMaxFindStringLength = 0;
0368     d->mMinFindStringLength = 0;
0369     QHashIterator<QString, QString> i(entries);
0370     while (i.hasNext()) {
0371         i.next();
0372         const int findStringLenght(i.key().length());
0373         d->mMaxFindStringLength = qMax(d->mMaxFindStringLength, findStringLenght);
0374         d->mMinFindStringLength = qMin(d->mMinFindStringLength, findStringLenght);
0375     }
0376     d->mAutocorrectEntries = entries;
0377 }
0378 
0379 QHash<QString, QString> AutoCorrectionSettings::autocorrectEntries() const
0380 {
0381     return d->mAutocorrectEntries;
0382 }
0383 
0384 void AutoCorrectionSettings::writeAutoCorrectionFile(const QString &filename)
0385 {
0386     ExportLibreOfficeAutocorrection correct;
0387     correct.setAutocorrectEntries(d->mAutocorrectEntries);
0388     correct.setUpperCaseExceptions(d->mUpperCaseExceptions);
0389     correct.setTwoUpperLetterExceptions(d->mTwoUpperLetterExceptions);
0390     QString message;
0391     if (!correct.exportData(d->mAutoCorrectLang, filename, message, d->mCustomWritablePath)) {
0392         qCDebug(TEXTAUTOCORRECTION_LOG) << "We can't save in file :" << filename;
0393     }
0394 }
0395 
0396 int AutoCorrectionSettings::maxFindStringLength() const
0397 {
0398     return d->mMaxFindStringLength;
0399 }
0400 
0401 int AutoCorrectionSettings::minFindStringLength() const
0402 {
0403     return d->mMinFindStringLength;
0404 }
0405 
0406 void AutoCorrectionSettings::loadLocalFileName(const QString &localFileName, const QString &fname)
0407 {
0408     ImportLibreOfficeAutocorrection import;
0409     QString messageError;
0410     if (import.import(localFileName, messageError, ImportAbstractAutocorrection::All)) {
0411         d->mUpperCaseExceptions = import.upperCaseExceptions();
0412         d->mTwoUpperLetterExceptions = import.twoUpperLetterExceptions();
0413         d->mAutocorrectEntries = import.autocorrectEntries();
0414         // Don't import it in local
0415         // mSuperScriptEntries = import.superScriptEntries();
0416     }
0417     if (!fname.isEmpty() && import.import(fname, messageError, ImportAbstractAutocorrection::SuperScript)) {
0418         d->mSuperScriptEntries = import.superScriptEntries();
0419     }
0420     d->mMaxFindStringLength = import.maxFindStringLenght();
0421     d->mMinFindStringLength = import.minFindStringLenght();
0422 }
0423 
0424 void AutoCorrectionSettings::loadGlobalFileName(const QString &fname)
0425 {
0426     if (fname.isEmpty()) {
0427         const QString fileName = containsAutoCorrectionFile(d->mAutoCorrectLang);
0428         if (!fileName.isEmpty()) {
0429             QString errorMessage;
0430             ImportLibreOfficeAutocorrection import;
0431             if (import.import(fileName, errorMessage)) {
0432                 d->mUpperCaseExceptions = import.upperCaseExceptions();
0433                 d->mTwoUpperLetterExceptions = import.twoUpperLetterExceptions();
0434                 d->mAutocorrectEntries = import.autocorrectEntries();
0435                 d->mSuperScriptEntries = import.superScriptEntries();
0436                 d->mMaxFindStringLength = import.maxFindStringLenght();
0437                 d->mMinFindStringLength = import.minFindStringLenght();
0438             }
0439         }
0440     } else {
0441         qDebug() << " import libreoffice file " << fname;
0442         ImportLibreOfficeAutocorrection import;
0443         QString messageError;
0444         if (import.import(fname, messageError, ImportAbstractAutocorrection::All)) {
0445             d->mUpperCaseExceptions = import.upperCaseExceptions();
0446             d->mTwoUpperLetterExceptions = import.twoUpperLetterExceptions();
0447             d->mAutocorrectEntries = import.autocorrectEntries();
0448             d->mSuperScriptEntries = import.superScriptEntries();
0449             d->mMaxFindStringLength = import.maxFindStringLenght();
0450             d->mMinFindStringLength = import.minFindStringLenght();
0451         }
0452     }
0453 }
0454 
0455 void AutoCorrectionSettings::migrateKMailXmlFile()
0456 {
0457 #if 0
0458     // TODO
0459     QString kdelang = QStringLiteral("en_US");
0460     const QStringList lst = QLocale::system().uiLanguages();
0461     if (!lst.isEmpty()) {
0462         kdelang = lst.at(0);
0463         if (kdelang == QLatin1Char('C')) {
0464             kdelang = QStringLiteral("en_US");
0465         }
0466     }
0467     static QRegularExpression reg(QStringLiteral("@.*"));
0468     kdelang.remove(reg);
0469 
0470     QString localFileName;
0471     static QRegularExpression regpath(QRegularExpression(QStringLiteral("_.*")));
0472     // Look at local file:
0473     if (!forceGlobal) {
0474         if (!mAutoCorrectLang.isEmpty()) {
0475             localFileName =
0476                 QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/custom-") + mAutoCorrectLang + QLatin1String(".xml"));
0477         } else {
0478             if (!kdelang.isEmpty()) {
0479                 localFileName =
0480                     QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/custom-") + kdelang + QLatin1String(".xml"));
0481             }
0482             if (localFileName.isEmpty() && kdelang.contains(QLatin1Char('_'))) {
0483                 kdelang.remove(regpath);
0484                 localFileName =
0485                     QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/custom-") + kdelang + QLatin1String(".xml"));
0486             }
0487         }
0488     }
0489     QString fname;
0490     // Load Global directly
0491     if (!mAutoCorrectLang.isEmpty()) {
0492         if (mAutoCorrectLang == QLatin1String("en_US")) {
0493             fname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("autocorrect/autocorrect.xml"));
0494         } else {
0495             fname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/") + mAutoCorrectLang + QLatin1String(".xml"));
0496         }
0497     } else {
0498         if (fname.isEmpty() && !kdelang.isEmpty()) {
0499             fname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/") + kdelang + QLatin1String(".xml"));
0500         }
0501         if (fname.isEmpty() && kdelang.contains(QLatin1Char('_'))) {
0502             kdelang.remove(regpath);
0503             fname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("autocorrect/") + kdelang + QLatin1String(".xml"));
0504         }
0505     }
0506     if (fname.isEmpty()) {
0507         fname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("autocorrect/autocorrect.xml"));
0508     }
0509 
0510     if (mAutoCorrectLang.isEmpty()) {
0511         mAutoCorrectLang = kdelang;
0512     }
0513 #endif
0514 }
0515 
0516 void AutoCorrectionSettings::readAutoCorrectionFile(bool forceGlobal)
0517 {
0518     d->mUpperCaseExceptions.clear();
0519     d->mAutocorrectEntries.clear();
0520     d->mTwoUpperLetterExceptions.clear();
0521     d->mSuperScriptEntries.clear();
0522 
0523     QString kdelang = QStringLiteral("en-US");
0524     const QStringList lst = QLocale::system().uiLanguages();
0525     if (!lst.isEmpty()) {
0526         kdelang = lst.at(0);
0527         if (kdelang == QLatin1Char('C')) {
0528             kdelang = QStringLiteral("en-US");
0529         }
0530     }
0531     static QRegularExpression reg(QStringLiteral("@.*"));
0532     kdelang.remove(reg);
0533 
0534     QString localFileName;
0535     static QRegularExpression regpath(QRegularExpression(QStringLiteral("_.*")));
0536     // Look at local file:
0537     if (!forceGlobal) {
0538         if (d->mAutoCorrectLang.isEmpty()) {
0539             if (!kdelang.isEmpty()) {
0540                 localFileName = containsAutoCorrectionFile(kdelang);
0541             }
0542             if (localFileName.isEmpty() && kdelang.contains(QLatin1Char('_'))) {
0543                 kdelang.remove(regpath);
0544                 localFileName = containsAutoCorrectionFile(kdelang);
0545             }
0546         }
0547     }
0548     QString fname;
0549     // Load Global directly
0550     if (!d->mAutoCorrectLang.isEmpty()) {
0551         localFileName = containsAutoCorrectionFile(d->mAutoCorrectLang);
0552     } else {
0553         if (fname.isEmpty() && !kdelang.isEmpty()) {
0554             fname = containsAutoCorrectionFile(kdelang);
0555         }
0556         if (fname.isEmpty() && kdelang.contains(QLatin1Char('_'))) {
0557             kdelang.remove(regpath);
0558             fname = containsAutoCorrectionFile(kdelang);
0559         }
0560     }
0561 
0562     if (d->mAutoCorrectLang.isEmpty()) {
0563         d->mAutoCorrectLang = kdelang;
0564     }
0565     // qDebug() << " fname :" << fname;
0566     // qDebug() << " localFileName:" << localFileName;
0567 
0568     if (localFileName.isEmpty()) {
0569         loadGlobalFileName(fname);
0570     } else {
0571         loadLocalFileName(localFileName, fname);
0572     }
0573 }
0574 
0575 QString AutoCorrectionSettings::containsAutoCorrectionFile(const QString &fileName)
0576 {
0577     return AutoCorrectionUtils::containsAutoCorrectionFile(fileName, d->mCustomSystemPath, d->mCustomWritablePath);
0578 }
0579 
0580 AutoCorrectionUtils::TypographicQuotes AutoCorrectionSettings::doubleFrenchQuotes() const
0581 {
0582     return d->mDoubleFrenchQuotes;
0583 }
0584 
0585 void AutoCorrectionSettings::setDoubleFrenchQuotes(const AutoCorrectionUtils::TypographicQuotes &newDoubleFrenchQuotes)
0586 {
0587     d->mDoubleFrenchQuotes = newDoubleFrenchQuotes;
0588 }
0589 
0590 QString AutoCorrectionSettings::customWritablePath() const
0591 {
0592     return d->mCustomWritablePath;
0593 }
0594 
0595 void AutoCorrectionSettings::setCustomWritablePath(const QString &path)
0596 {
0597     d->mCustomWritablePath = path;
0598 }
0599 
0600 QString AutoCorrectionSettings::customSystemPath() const
0601 {
0602     return d->mCustomSystemPath;
0603 }
0604 
0605 void AutoCorrectionSettings::setCustomSystemPath(const QString &path)
0606 {
0607     d->mCustomSystemPath = path;
0608 }
0609 
0610 QDebug operator<<(QDebug d, const TextAutoCorrectionCore::AutoCorrectionSettings &t)
0611 {
0612     d << "mAddNonBreakingSpace " << t.nonBreakingSpace();
0613     d << "mSuperScriptAppendix " << t.isSuperScript();
0614     d << "mEnabled " << t.isEnabledAutoCorrection();
0615     d << "mAutoBoldUnderline " << t.isAutoBoldUnderline();
0616     d << "mAutoFormatUrl " << t.isAutoFormatUrl();
0617     d << "mReplaceSingleQuotes " << t.isReplaceSingleQuotes();
0618     d << "mReplaceDoubleQuotes " << t.isReplaceDoubleQuotes();
0619     d << "mAdvancedAutocorrect " << t.isAdvancedAutocorrect();
0620     d << "mCapitalizeWeekDays " << t.isCapitalizeWeekDays();
0621     d << "mAutoFractions " << t.isAutoFractions();
0622     d << "mFixTwoUppercaseChars " << t.isFixTwoUppercaseChars();
0623     d << "mUppercaseFirstCharOfSentence " << t.isUppercaseFirstCharOfSentence();
0624     d << "mSingleSpaces " << t.isSingleSpaces();
0625     d << "mMaxFindStringLength " << t.maxFindStringLength();
0626     d << "mMinFindStringLength " << t.minFindStringLength();
0627     d << "mNonBreakingSpace " << t.nonBreakingSpace();
0628     d << "mAutoCorrectLang " << t.language();
0629     d << "mTwoUpperLetterExceptions " << t.twoUpperLetterExceptions();
0630     d << "mUpperCaseExceptions " << t.upperCaseExceptions();
0631     d << "mSuperScriptEntries " << t.superScriptEntries();
0632     d << "mAutocorrectEntries " << t.autocorrectEntries();
0633     d << "mTypographicDoubleQuotes " << t.typographicDoubleQuotes();
0634     d << "mTypographicSingleQuotes " << t.typographicSingleQuotes();
0635     d << "mReplaceDoubleQuotesByFrenchQuotes " << t.isReplaceDoubleQuotesByFrenchQuotes();
0636     return d;
0637 }