File indexing completed on 2024-04-28 11:48:59
0001 /* This file is part of the KDE libraries 0002 0003 SPDX-FileCopyrightText: 2009 Jakub Stachowski <qbast@go2.pl> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include <QString> 0009 0010 #include "guesslanguage.h" 0011 #include "languagefilter_p.h" 0012 #include "loader_p.h" 0013 #include "settingsimpl_p.h" 0014 #include "speller.h" 0015 0016 namespace Sonnet 0017 { 0018 #define MIN_RELIABILITY 0.1 0019 #define MAX_ITEMS 5 0020 0021 class LanguageFilterPrivate 0022 { 0023 public: 0024 LanguageFilterPrivate(AbstractTokenizer *s) 0025 : source(s) 0026 { 0027 gl.setLimits(MAX_ITEMS, MIN_RELIABILITY); 0028 } 0029 0030 ~LanguageFilterPrivate() 0031 { 0032 delete source; 0033 } 0034 0035 QString mainLanguage() const; 0036 0037 AbstractTokenizer *source = nullptr; 0038 Token lastToken; 0039 0040 mutable QString lastLanguage; 0041 mutable QString cachedMainLanguage; 0042 QString prevLanguage; 0043 0044 GuessLanguage gl; 0045 Speller sp; 0046 }; 0047 0048 QString LanguageFilterPrivate::mainLanguage() const 0049 { 0050 if (cachedMainLanguage.isNull()) { 0051 cachedMainLanguage = gl.identify(source->buffer(), QStringList(Loader::openLoader()->settings()->defaultLanguage())); 0052 } 0053 return cachedMainLanguage; 0054 } 0055 0056 /* -----------------------------------------------------------------*/ 0057 0058 LanguageFilter::LanguageFilter(AbstractTokenizer *source) 0059 : d(new LanguageFilterPrivate(source)) 0060 { 0061 d->prevLanguage = Loader::openLoader()->settings()->defaultLanguage(); 0062 } 0063 0064 LanguageFilter::LanguageFilter(const LanguageFilter &other) 0065 : d(new LanguageFilterPrivate(other.d->source)) 0066 { 0067 d->lastToken = other.d->lastToken; 0068 d->lastLanguage = other.d->lastLanguage; 0069 d->cachedMainLanguage = other.d->cachedMainLanguage; 0070 d->prevLanguage = other.d->prevLanguage; 0071 } 0072 0073 LanguageFilter::~LanguageFilter() 0074 { 0075 delete d; 0076 } 0077 0078 bool LanguageFilter::hasNext() const 0079 { 0080 return d->source->hasNext(); 0081 } 0082 0083 void LanguageFilter::setBuffer(const QString &buffer) 0084 { 0085 d->cachedMainLanguage = QString(); 0086 d->source->setBuffer(buffer); 0087 } 0088 0089 Token LanguageFilter::next() 0090 { 0091 d->lastToken = d->source->next(); 0092 d->prevLanguage = d->lastLanguage; 0093 d->lastLanguage = QString(); 0094 return d->lastToken; 0095 } 0096 0097 QString LanguageFilter::language() const 0098 { 0099 if (d->lastLanguage.isNull()) { 0100 d->lastLanguage = d->gl.identify(d->lastToken.toString(), QStringList() << d->prevLanguage << Loader::openLoader()->settings()->defaultLanguage()); 0101 } 0102 const QStringList available = d->sp.availableLanguages(); 0103 0104 // FIXME: do something a little more smart here 0105 if (!available.contains(d->lastLanguage)) { 0106 for (const QString &lang : available) { 0107 if (lang.startsWith(d->lastLanguage)) { 0108 d->lastLanguage = lang; 0109 break; 0110 } 0111 } 0112 } 0113 0114 return d->lastLanguage; 0115 } 0116 0117 bool LanguageFilter::isSpellcheckable() const 0118 { 0119 const QString &lastlang = language(); 0120 if (lastlang.isEmpty()) { 0121 return false; 0122 } 0123 0124 if (d->sp.availableLanguages().contains(lastlang)) { 0125 return true; 0126 } 0127 0128 return false; 0129 } 0130 0131 QString LanguageFilter::buffer() const 0132 { 0133 return d->source->buffer(); 0134 } 0135 0136 void LanguageFilter::replace(int position, int len, const QString &newWord) 0137 { 0138 d->source->replace(position, len, newWord); 0139 // FIXME: fix lastToken 0140 // uncache language for current token - it may have changed 0141 d->lastLanguage = QString(); 0142 } 0143 }