File indexing completed on 2026-07-19 08:32:55
0001 /* 0002 SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "autocorrectionwidget.h" 0008 #include "autocorrectionutils.h" 0009 0010 #include "ui_autocorrectionwidget.h" 0011 #include <TextAutoCorrectionCore/ImportAbstractAutocorrection> 0012 #include <TextAutoCorrectionCore/ImportKMailAutocorrection> 0013 #include <TextAutoCorrectionCore/ImportLibreOfficeAutocorrection> 0014 0015 #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) 0016 #include <TextAddonsWidgets/LineEditCatchReturnKey> 0017 #else 0018 #include <KLineEditEventHandler> 0019 #endif 0020 #include <TextAddonsWidgets/SelectSpecialCharDialog> 0021 0022 #include <KLocalizedString> 0023 #include <KMessageBox> 0024 0025 #include <QFileDialog> 0026 #include <QMenu> 0027 #include <QPointer> 0028 #include <QTreeWidgetItem> 0029 0030 using namespace TextAutoCorrectionWidgets; 0031 using namespace TextAutoCorrectionCore; 0032 0033 Q_DECLARE_METATYPE(AutoCorrectionWidget::ImportFileType) 0034 class TextAutoCorrectionWidgets::AutoCorrectionWidgetPrivate 0035 { 0036 public: 0037 AutoCorrectionWidgetPrivate() 0038 : ui(new Ui::AutoCorrectionWidget) 0039 { 0040 } 0041 0042 ~AutoCorrectionWidgetPrivate() = default; 0043 0044 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes m_singleQuotes; 0045 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes m_doubleQuotes; 0046 QSet<QString> m_upperCaseExceptions; 0047 QSet<QString> m_twoUpperLetterExceptions; 0048 QHash<QString, QString> m_autocorrectEntries; 0049 std::unique_ptr<Ui::AutoCorrectionWidget> const ui; 0050 TextAutoCorrectionCore::AutoCorrection *mAutoCorrection = nullptr; 0051 bool mWasChanged = false; 0052 bool mHasHtmlSupport = true; 0053 }; 0054 0055 AutoCorrectionWidget::AutoCorrectionWidget(QWidget *parent) 0056 : QWidget(parent) 0057 , d(new TextAutoCorrectionWidgets::AutoCorrectionWidgetPrivate) 0058 { 0059 d->ui->setupUi(this); 0060 0061 d->ui->treeWidget->setSortingEnabled(true); 0062 d->ui->treeWidget->sortByColumn(0, Qt::AscendingOrder); 0063 0064 d->ui->add1->setEnabled(false); 0065 d->ui->add2->setEnabled(false); 0066 0067 #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) 0068 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->find, this); 0069 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->replace, this); 0070 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->abbreviation, this); 0071 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->twoUpperLetter, this); 0072 #else 0073 KLineEditEventHandler::catchReturnKey(d->ui->find); 0074 KLineEditEventHandler::catchReturnKey(d->ui->replace); 0075 KLineEditEventHandler::catchReturnKey(d->ui->abbreviation); 0076 KLineEditEventHandler::catchReturnKey(d->ui->twoUpperLetter); 0077 0078 #endif 0079 connect(d->ui->autoChangeFormat, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0080 connect(d->ui->autoFormatUrl, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0081 connect(d->ui->upperCase, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0082 connect(d->ui->upperUpper, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0083 connect(d->ui->ignoreDoubleSpace, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0084 connect(d->ui->autoReplaceNumber, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0085 connect(d->ui->capitalizeDaysName, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0086 connect(d->ui->advancedAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0087 connect(d->ui->enabledAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0088 connect(d->ui->typographicSingleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableSingleQuotes); 0089 connect(d->ui->typographicDoubleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableDoubleQuotes); 0090 connect(d->ui->autoSuperScript, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0091 connect(d->ui->singleQuote1, &QPushButton::clicked, this, &AutoCorrectionWidget::selectSingleQuoteCharOpen); 0092 connect(d->ui->singleQuote2, &QPushButton::clicked, this, &AutoCorrectionWidget::selectSingleQuoteCharClose); 0093 connect(d->ui->singleDefault, &QPushButton::clicked, this, &AutoCorrectionWidget::setDefaultSingleQuotes); 0094 connect(d->ui->doubleQuote1, &QPushButton::clicked, this, &AutoCorrectionWidget::selectDoubleQuoteCharOpen); 0095 connect(d->ui->doubleQuote2, &QPushButton::clicked, this, &AutoCorrectionWidget::selectDoubleQuoteCharClose); 0096 connect(d->ui->doubleDefault, &QPushButton::clicked, this, &AutoCorrectionWidget::setDefaultDoubleQuotes); 0097 connect(d->ui->advancedAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableAdvAutocorrection); 0098 connect(d->ui->addButton, &QPushButton::clicked, this, &AutoCorrectionWidget::addAutocorrectEntry); 0099 connect(d->ui->removeButton, &QPushButton::clicked, this, &AutoCorrectionWidget::removeAutocorrectEntry); 0100 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::itemClicked, this, &AutoCorrectionWidget::setFindReplaceText); 0101 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::deleteSelectedItems, this, &AutoCorrectionWidget::removeAutocorrectEntry); 0102 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::itemSelectionChanged, this, &AutoCorrectionWidget::updateAddRemoveButton); 0103 connect(d->ui->find, &QLineEdit::textChanged, this, &AutoCorrectionWidget::enableAddRemoveButton); 0104 connect(d->ui->replace, &QLineEdit::textChanged, this, &AutoCorrectionWidget::enableAddRemoveButton); 0105 connect(d->ui->abbreviation, &QLineEdit::textChanged, this, &AutoCorrectionWidget::abbreviationChanged); 0106 connect(d->ui->twoUpperLetter, &QLineEdit::textChanged, this, &AutoCorrectionWidget::twoUpperLetterChanged); 0107 connect(d->ui->add1, &QPushButton::clicked, this, &AutoCorrectionWidget::addAbbreviationEntry); 0108 connect(d->ui->remove1, &QPushButton::clicked, this, &AutoCorrectionWidget::removeAbbreviationEntry); 0109 connect(d->ui->add2, &QPushButton::clicked, this, &AutoCorrectionWidget::addTwoUpperLetterEntry); 0110 connect(d->ui->remove2, &QPushButton::clicked, this, &AutoCorrectionWidget::removeTwoUpperLetterEntry); 0111 connect(d->ui->typographicDoubleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0112 connect(d->ui->typographicSingleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0113 connect(d->ui->abbreviationList, 0114 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::itemSelectionChanged, 0115 this, 0116 &AutoCorrectionWidget::slotEnableDisableAbreviationList); 0117 connect(d->ui->abbreviationList, 0118 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::deleteSelectedItems, 0119 this, 0120 &AutoCorrectionWidget::removeAbbreviationEntry); 0121 connect(d->ui->twoUpperLetterList, 0122 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::itemSelectionChanged, 0123 this, 0124 &AutoCorrectionWidget::slotEnableDisableTwoUpperEntry); 0125 connect(d->ui->twoUpperLetterList, 0126 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::deleteSelectedItems, 0127 this, 0128 &AutoCorrectionWidget::removeTwoUpperLetterEntry); 0129 connect(d->ui->autocorrectionLanguage, &TextAutoCorrectionWidgets::AutoCorrectionLanguage::activated, this, &AutoCorrectionWidget::changeLanguage); 0130 connect(d->ui->addNonBreakingSpaceInFrench, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0131 connect(d->ui->twoUpperLetter, &QLineEdit::returnPressed, this, &AutoCorrectionWidget::addTwoUpperLetterEntry); 0132 connect(d->ui->abbreviation, &QLineEdit::returnPressed, this, &AutoCorrectionWidget::addAbbreviationEntry); 0133 connect(d->ui->replaceDoubleQuotesByFrenchQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged); 0134 0135 connect(d->ui->customWritablePath, &QLineEdit::textChanged, this, &AutoCorrectionWidget::emitChanged); 0136 connect(d->ui->customSystemPath, &QLineEdit::textChanged, this, &AutoCorrectionWidget::emitChanged); 0137 0138 #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) 0139 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->customWritablePath, parent); 0140 TextAddonsWidgets::LineEditCatchReturnKey(d->ui->customSystemPath, parent); 0141 #else 0142 KLineEditEventHandler::catchReturnKey(d->ui->customWritablePath); 0143 KLineEditEventHandler::catchReturnKey(d->ui->customSystemPath); 0144 #endif 0145 0146 connect(d->ui->customWritablePathToolButton, &QToolButton::clicked, this, [this]() { 0147 const QString path = QFileDialog::getExistingDirectory(this, i18n("Select Custom Writable Path")); 0148 d->ui->customWritablePath->setText(path); 0149 }); 0150 0151 connect(d->ui->customSystemPathToolButton, &QToolButton::clicked, this, [this]() { 0152 const QString path = QFileDialog::getExistingDirectory(this, i18n("Select Custom System Path")); 0153 d->ui->customSystemPath->setText(path); 0154 }); 0155 0156 slotEnableDisableAbreviationList(); 0157 slotEnableDisableTwoUpperEntry(); 0158 0159 auto menu = new QMenu(this); 0160 d->ui->importAutoCorrection->setMenu(menu); 0161 0162 auto act = new QAction(i18n("LibreOffice Autocorrection"), this); 0163 act->setData(QVariant::fromValue(AutoCorrectionWidget::LibreOffice)); 0164 menu->addAction(act); 0165 0166 act = new QAction(i18n("KMail/Calligra Autocorrection"), this); 0167 act->setData(QVariant::fromValue(AutoCorrectionWidget::KMail)); 0168 menu->addAction(act); 0169 0170 connect(menu, &QMenu::triggered, this, &AutoCorrectionWidget::slotImportAutoCorrection); 0171 0172 connect(d->ui->exportAutoCorrection, &QPushButton::clicked, this, &AutoCorrectionWidget::slotExportAutoCorrection); 0173 connect(d->ui->tabWidget, &QTabWidget::tabBarClicked, this, &AutoCorrectionWidget::slotChangeComboboxState); 0174 slotChangeComboboxState(d->ui->tabWidget->currentIndex()); 0175 0176 d->ui->systemPath->setText(TextAutoCorrectionCore::AutoCorrectionUtils::libreOfficeSystemPath()); 0177 d->ui->writablePath->setText(TextAutoCorrectionCore::AutoCorrectionUtils::libreOfficeWritableLocalAutoCorrectionPath()); 0178 } 0179 0180 AutoCorrectionWidget::~AutoCorrectionWidget() = default; 0181 0182 void AutoCorrectionWidget::slotChangeComboboxState(int index) 0183 { 0184 d->ui->autocorrectionLanguage->setEnabled(index < 2); 0185 } 0186 0187 void AutoCorrectionWidget::setAutoCorrection(TextAutoCorrectionCore::AutoCorrection *autoCorrect) 0188 { 0189 d->mAutoCorrection = autoCorrect; 0190 setLanguage(d->ui->autocorrectionLanguage->language()); 0191 } 0192 0193 void AutoCorrectionWidget::setHasHtmlSupport(bool b) 0194 { 0195 if (d->mHasHtmlSupport != b) { 0196 d->mHasHtmlSupport = b; 0197 updateHtmlSupport(); 0198 } 0199 } 0200 0201 void AutoCorrectionWidget::updateHtmlSupport() 0202 { 0203 d->ui->autoFormatUrl->setVisible(d->mHasHtmlSupport); 0204 d->ui->autoSuperScript->setVisible(d->mHasHtmlSupport); 0205 d->ui->autoChangeFormat->setVisible(d->mHasHtmlSupport); 0206 } 0207 0208 void AutoCorrectionWidget::loadConfig() 0209 { 0210 if (!d->mAutoCorrection) { 0211 return; 0212 } 0213 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0214 d->ui->autoChangeFormat->setChecked(settings->isAutoBoldUnderline()); 0215 d->ui->autoFormatUrl->setChecked(settings->isAutoFormatUrl()); 0216 d->ui->enabledAutocorrection->setChecked(settings->isEnabledAutoCorrection()); 0217 d->ui->upperCase->setChecked(settings->isUppercaseFirstCharOfSentence()); 0218 d->ui->upperUpper->setChecked(settings->isFixTwoUppercaseChars()); 0219 d->ui->ignoreDoubleSpace->setChecked(settings->isSingleSpaces()); 0220 d->ui->autoReplaceNumber->setChecked(settings->isAutoFractions()); 0221 d->ui->capitalizeDaysName->setChecked(settings->isCapitalizeWeekDays()); 0222 d->ui->advancedAutocorrection->setChecked(settings->isAdvancedAutocorrect()); 0223 d->ui->autoSuperScript->setChecked(settings->isSuperScript()); 0224 d->ui->typographicDoubleQuotes->setChecked(settings->isReplaceDoubleQuotes()); 0225 d->ui->typographicSingleQuotes->setChecked(settings->isReplaceSingleQuotes()); 0226 d->ui->addNonBreakingSpaceInFrench->setChecked(settings->isAddNonBreakingSpace()); 0227 d->ui->replaceDoubleQuotesByFrenchQuotes->setChecked(settings->isReplaceDoubleQuotesByFrenchQuotes()); 0228 0229 d->ui->customWritablePath->setText(settings->customWritablePath()); 0230 d->ui->customSystemPath->setText(settings->customSystemPath()); 0231 0232 loadAutoCorrectionAndException(); 0233 d->mWasChanged = false; 0234 } 0235 0236 void AutoCorrectionWidget::loadAutoCorrectionAndException() 0237 { 0238 /* tab 2 - Custom Quotes */ 0239 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0240 d->m_singleQuotes = settings->typographicSingleQuotes(); 0241 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin); 0242 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end); 0243 d->m_doubleQuotes = settings->typographicDoubleQuotes(); 0244 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin); 0245 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end); 0246 enableSingleQuotes(d->ui->typographicSingleQuotes->isChecked()); 0247 enableDoubleQuotes(d->ui->typographicDoubleQuotes->isChecked()); 0248 0249 /* tab 3 - Advanced Autocorrection */ 0250 d->m_autocorrectEntries = settings->autocorrectEntries(); 0251 addAutoCorrectEntries(); 0252 0253 enableAdvAutocorrection(d->ui->advancedAutocorrection->isChecked()); 0254 /* tab 4 - Exceptions */ 0255 d->m_upperCaseExceptions = settings->upperCaseExceptions(); 0256 d->m_twoUpperLetterExceptions = settings->twoUpperLetterExceptions(); 0257 0258 d->ui->twoUpperLetterList->clear(); 0259 d->ui->twoUpperLetterList->addItems(d->m_twoUpperLetterExceptions.values()); 0260 0261 d->ui->abbreviationList->clear(); 0262 d->ui->abbreviationList->addItems(d->m_upperCaseExceptions.values()); 0263 } 0264 0265 void AutoCorrectionWidget::addAutoCorrectEntries() 0266 { 0267 d->ui->treeWidget->clear(); 0268 QHash<QString, QString>::const_iterator i = d->m_autocorrectEntries.constBegin(); 0269 QTreeWidgetItem *item = nullptr; 0270 while (i != d->m_autocorrectEntries.constEnd()) { 0271 item = new QTreeWidgetItem(d->ui->treeWidget, item); 0272 item->setText(0, i.key()); 0273 item->setText(1, i.value()); 0274 ++i; 0275 } 0276 d->ui->treeWidget->setSortingEnabled(true); 0277 d->ui->treeWidget->sortByColumn(0, Qt::AscendingOrder); 0278 } 0279 0280 void AutoCorrectionWidget::writeConfig() 0281 { 0282 if (!d->mAutoCorrection) { 0283 return; 0284 } 0285 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0286 settings->setAutoBoldUnderline(d->ui->autoChangeFormat->isChecked()); 0287 settings->setAutoFormatUrl(d->ui->autoFormatUrl->isChecked()); 0288 settings->setEnabledAutoCorrection(d->ui->enabledAutocorrection->isChecked()); 0289 settings->setUppercaseFirstCharOfSentence(d->ui->upperCase->isChecked()); 0290 settings->setFixTwoUppercaseChars(d->ui->upperUpper->isChecked()); 0291 settings->setSingleSpaces(d->ui->ignoreDoubleSpace->isChecked()); 0292 settings->setCapitalizeWeekDays(d->ui->capitalizeDaysName->isChecked()); 0293 settings->setAdvancedAutocorrect(d->ui->advancedAutocorrection->isChecked()); 0294 settings->setSuperScript(d->ui->autoSuperScript->isChecked()); 0295 0296 settings->setAutoFractions(d->ui->autoReplaceNumber->isChecked()); 0297 0298 settings->setAutocorrectEntries(d->m_autocorrectEntries); 0299 settings->setUpperCaseExceptions(d->m_upperCaseExceptions); 0300 settings->setTwoUpperLetterExceptions(d->m_twoUpperLetterExceptions); 0301 0302 settings->setReplaceDoubleQuotes(d->ui->typographicDoubleQuotes->isChecked()); 0303 settings->setReplaceSingleQuotes(d->ui->typographicSingleQuotes->isChecked()); 0304 settings->setTypographicSingleQuotes(d->m_singleQuotes); 0305 settings->setTypographicDoubleQuotes(d->m_doubleQuotes); 0306 settings->setAddNonBreakingSpace(d->ui->addNonBreakingSpaceInFrench->isChecked()); 0307 settings->setReplaceDoubleQuotesByFrenchQuotes(d->ui->replaceDoubleQuotesByFrenchQuotes->isChecked()); 0308 0309 settings->setCustomWritablePath(d->ui->customWritablePath->text()); 0310 settings->setCustomSystemPath(d->ui->customSystemPath->text()); 0311 0312 d->mAutoCorrection->setAutoCorrectionSettings(settings); 0313 d->mAutoCorrection->writeConfig(); 0314 d->mWasChanged = false; 0315 } 0316 0317 void AutoCorrectionWidget::resetToDefault() 0318 { 0319 d->ui->autoChangeFormat->setChecked(false); 0320 d->ui->autoFormatUrl->setChecked(false); 0321 d->ui->upperCase->setChecked(false); 0322 d->ui->upperUpper->setChecked(false); 0323 d->ui->ignoreDoubleSpace->setChecked(false); 0324 d->ui->capitalizeDaysName->setChecked(false); 0325 d->ui->advancedAutocorrection->setChecked(false); 0326 d->ui->typographicDoubleQuotes->setChecked(false); 0327 d->ui->typographicSingleQuotes->setChecked(false); 0328 d->ui->autoSuperScript->setChecked(false); 0329 d->ui->autoReplaceNumber->setChecked(false); 0330 d->ui->typographicDoubleQuotes->setChecked(false); 0331 d->ui->typographicSingleQuotes->setChecked(false); 0332 d->ui->addNonBreakingSpaceInFrench->setChecked(false); 0333 0334 loadGlobalAutoCorrectionAndException(); 0335 } 0336 0337 void AutoCorrectionWidget::enableSingleQuotes(bool state) 0338 { 0339 d->ui->singleQuote1->setEnabled(state); 0340 d->ui->singleQuote2->setEnabled(state); 0341 d->ui->singleDefault->setEnabled(state); 0342 } 0343 0344 void AutoCorrectionWidget::enableDoubleQuotes(bool state) 0345 { 0346 d->ui->doubleQuote1->setEnabled(state); 0347 d->ui->doubleQuote2->setEnabled(state); 0348 d->ui->doubleDefault->setEnabled(state); 0349 } 0350 0351 void AutoCorrectionWidget::selectSingleQuoteCharOpen() 0352 { 0353 QPointer<TextAddonsWidgets::SelectSpecialCharDialog> dlg = new TextAddonsWidgets::SelectSpecialCharDialog(this); 0354 dlg->setCurrentChar(d->m_singleQuotes.begin); 0355 dlg->showSelectButton(false); 0356 dlg->autoInsertChar(); 0357 if (dlg->exec()) { 0358 d->m_singleQuotes.begin = dlg->currentChar(); 0359 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin); 0360 emitChanged(); 0361 } 0362 delete dlg; 0363 } 0364 0365 void AutoCorrectionWidget::selectSingleQuoteCharClose() 0366 { 0367 QPointer<TextAddonsWidgets::SelectSpecialCharDialog> dlg = new TextAddonsWidgets::SelectSpecialCharDialog(this); 0368 dlg->showSelectButton(false); 0369 dlg->setCurrentChar(d->m_singleQuotes.end); 0370 dlg->autoInsertChar(); 0371 if (dlg->exec()) { 0372 d->m_singleQuotes.end = dlg->currentChar(); 0373 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end); 0374 emitChanged(); 0375 } 0376 delete dlg; 0377 } 0378 0379 void AutoCorrectionWidget::setDefaultSingleQuotes() 0380 { 0381 d->m_singleQuotes = TextAutoCorrectionCore::AutoCorrectionUtils::typographicDefaultSingleQuotes(); 0382 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin); 0383 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end); 0384 emitChanged(); 0385 } 0386 0387 void AutoCorrectionWidget::selectDoubleQuoteCharOpen() 0388 { 0389 QPointer<TextAddonsWidgets::SelectSpecialCharDialog> dlg = new TextAddonsWidgets::SelectSpecialCharDialog(this); 0390 dlg->showSelectButton(false); 0391 dlg->setCurrentChar(d->m_doubleQuotes.begin); 0392 dlg->autoInsertChar(); 0393 if (dlg->exec()) { 0394 d->m_doubleQuotes.begin = dlg->currentChar(); 0395 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin); 0396 emitChanged(); 0397 } 0398 delete dlg; 0399 } 0400 0401 void AutoCorrectionWidget::selectDoubleQuoteCharClose() 0402 { 0403 QPointer<TextAddonsWidgets::SelectSpecialCharDialog> dlg = new TextAddonsWidgets::SelectSpecialCharDialog(this); 0404 dlg->showSelectButton(false); 0405 dlg->setCurrentChar(d->m_doubleQuotes.end); 0406 dlg->autoInsertChar(); 0407 if (dlg->exec()) { 0408 d->m_doubleQuotes.end = dlg->currentChar(); 0409 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end); 0410 emitChanged(); 0411 } 0412 delete dlg; 0413 } 0414 0415 void AutoCorrectionWidget::setDefaultDoubleQuotes() 0416 { 0417 d->m_doubleQuotes = AutoCorrectionUtils::typographicDefaultDoubleQuotes(); 0418 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin); 0419 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end); 0420 emitChanged(); 0421 } 0422 0423 void AutoCorrectionWidget::enableAdvAutocorrection(bool state) 0424 { 0425 d->ui->findLabel->setEnabled(state); 0426 d->ui->find->setEnabled(state); 0427 d->ui->replaceLabel->setEnabled(state); 0428 d->ui->replace->setEnabled(state); 0429 0430 const QString find = d->ui->find->text(); 0431 const QString replace = d->ui->replace->text(); 0432 0433 d->ui->addButton->setEnabled(state && !find.isEmpty() && !replace.isEmpty()); 0434 d->ui->removeButton->setEnabled(state && d->ui->treeWidget->currentItem()); 0435 d->ui->treeWidget->setEnabled(state); 0436 } 0437 0438 void AutoCorrectionWidget::addAutocorrectEntry() 0439 { 0440 QTreeWidgetItem *item = d->ui->treeWidget->currentItem(); 0441 const QString find = d->ui->find->text(); 0442 const QString replace = d->ui->replace->text(); 0443 if (find == replace) { 0444 KMessageBox::error(this, i18n("\"Replace\" string is the same as \"Find\" string."), i18n("Add Autocorrection Entry")); 0445 return; 0446 } 0447 0448 bool modify = false; 0449 0450 // Modify actually, not add, so we want to remove item from hash 0451 if (item && (find == item->text(0))) { 0452 d->m_autocorrectEntries.remove(find); 0453 modify = true; 0454 } 0455 0456 d->m_autocorrectEntries.insert(find, replace); 0457 d->ui->treeWidget->setSortingEnabled(false); 0458 if (modify) { 0459 item->setText(0, find); 0460 item->setText(1, replace); 0461 } else { 0462 item = new QTreeWidgetItem(d->ui->treeWidget, item); 0463 item->setText(0, find); 0464 item->setText(1, replace); 0465 } 0466 0467 d->ui->treeWidget->setSortingEnabled(true); 0468 d->ui->treeWidget->setCurrentItem(item); 0469 emitChanged(); 0470 } 0471 0472 void AutoCorrectionWidget::removeAutocorrectEntry() 0473 { 0474 const QList<QTreeWidgetItem *> listItems = d->ui->treeWidget->selectedItems(); 0475 if (listItems.isEmpty()) { 0476 return; 0477 } 0478 for (QTreeWidgetItem *item : listItems) { 0479 QTreeWidgetItem *below = d->ui->treeWidget->itemBelow(item); 0480 0481 QString findStr; 0482 if (below) { 0483 // qCDebug(TEXTAUTOCORRECTION_AUTOCORRECT_LOG) << "below"; 0484 findStr = item->text(0); 0485 delete item; 0486 item = nullptr; 0487 } else if (d->ui->treeWidget->topLevelItemCount() > 0) { 0488 findStr = item->text(0); 0489 delete item; 0490 item = nullptr; 0491 } 0492 if (!findStr.isEmpty()) { 0493 d->m_autocorrectEntries.remove(findStr); 0494 } 0495 } 0496 d->ui->treeWidget->setSortingEnabled(false); 0497 0498 emitChanged(); 0499 } 0500 0501 void AutoCorrectionWidget::updateAddRemoveButton() 0502 { 0503 QList<QTreeWidgetItem *> listItems = d->ui->treeWidget->selectedItems(); 0504 d->ui->removeButton->setEnabled(!listItems.isEmpty()); 0505 } 0506 0507 void AutoCorrectionWidget::enableAddRemoveButton() 0508 { 0509 const QString find = d->ui->find->text(); 0510 const QString replace = d->ui->replace->text(); 0511 0512 QTreeWidgetItem *item = nullptr; 0513 if (d->m_autocorrectEntries.contains(find)) { 0514 item = d->ui->treeWidget->findItems(find, Qt::MatchCaseSensitive).at(0); 0515 } 0516 0517 bool enable = false; 0518 if (find.isEmpty() || replace.isEmpty()) { // disable if no text in find/replace 0519 enable = !(find.isEmpty() || replace.isEmpty()); 0520 } else if (item && find == item->text(0)) { 0521 // We disable add / remove button if no text for the replacement 0522 enable = !item->text(1).isEmpty(); 0523 d->ui->addButton->setText(i18n("&Modify")); 0524 } else if (!item || !item->text(1).isEmpty()) { 0525 enable = true; 0526 d->ui->addButton->setText(i18n("&Add")); 0527 } 0528 0529 if (item && replace == item->text(1)) { 0530 d->ui->addButton->setEnabled(false); 0531 } else { 0532 d->ui->addButton->setEnabled(enable); 0533 } 0534 d->ui->removeButton->setEnabled(enable); 0535 } 0536 0537 void AutoCorrectionWidget::setFindReplaceText(QTreeWidgetItem *item, int column) 0538 { 0539 Q_UNUSED(column) 0540 d->ui->find->setText(item->text(0)); 0541 d->ui->replace->setText(item->text(1)); 0542 } 0543 0544 void AutoCorrectionWidget::abbreviationChanged(const QString &text) 0545 { 0546 d->ui->add1->setEnabled(!text.isEmpty()); 0547 } 0548 0549 void AutoCorrectionWidget::twoUpperLetterChanged(const QString &text) 0550 { 0551 d->ui->add2->setEnabled(!text.isEmpty()); 0552 } 0553 0554 void AutoCorrectionWidget::addAbbreviationEntry() 0555 { 0556 const QString text = d->ui->abbreviation->text(); 0557 if (text.isEmpty()) { 0558 return; 0559 } 0560 if (!d->m_upperCaseExceptions.contains(text)) { 0561 d->m_upperCaseExceptions.insert(text); 0562 d->ui->abbreviationList->addItem(text); 0563 } 0564 d->ui->abbreviation->clear(); 0565 slotEnableDisableAbreviationList(); 0566 emitChanged(); 0567 } 0568 0569 void AutoCorrectionWidget::removeAbbreviationEntry() 0570 { 0571 const QList<QListWidgetItem *> listItem = d->ui->abbreviationList->selectedItems(); 0572 if (listItem.isEmpty()) { 0573 return; 0574 } 0575 for (QListWidgetItem *item : listItem) { 0576 d->m_upperCaseExceptions.remove(item->text()); 0577 delete item; 0578 } 0579 slotEnableDisableAbreviationList(); 0580 emitChanged(); 0581 } 0582 0583 void AutoCorrectionWidget::addTwoUpperLetterEntry() 0584 { 0585 const QString text = d->ui->twoUpperLetter->text(); 0586 if (text.isEmpty()) { 0587 return; 0588 } 0589 if (!d->m_twoUpperLetterExceptions.contains(text)) { 0590 d->m_twoUpperLetterExceptions.insert(text); 0591 d->ui->twoUpperLetterList->addItem(text); 0592 emitChanged(); 0593 } 0594 slotEnableDisableTwoUpperEntry(); 0595 d->ui->twoUpperLetter->clear(); 0596 } 0597 0598 void AutoCorrectionWidget::removeTwoUpperLetterEntry() 0599 { 0600 const QList<QListWidgetItem *> listItem = d->ui->twoUpperLetterList->selectedItems(); 0601 if (listItem.isEmpty()) { 0602 return; 0603 } 0604 for (QListWidgetItem *item : listItem) { 0605 d->m_twoUpperLetterExceptions.remove(item->text()); 0606 delete item; 0607 } 0608 slotEnableDisableTwoUpperEntry(); 0609 emitChanged(); 0610 } 0611 0612 void AutoCorrectionWidget::slotEnableDisableAbreviationList() 0613 { 0614 const bool enable = (!d->ui->abbreviationList->selectedItems().isEmpty()); 0615 d->ui->add1->setEnabled(!d->ui->abbreviation->text().isEmpty()); 0616 d->ui->remove1->setEnabled(enable); 0617 } 0618 0619 void AutoCorrectionWidget::slotEnableDisableTwoUpperEntry() 0620 { 0621 const bool enable = (!d->ui->twoUpperLetterList->selectedItems().isEmpty()); 0622 d->ui->add2->setEnabled(!d->ui->twoUpperLetter->text().isEmpty()); 0623 d->ui->remove2->setEnabled(enable); 0624 } 0625 0626 void AutoCorrectionWidget::slotImportAutoCorrection(QAction *act) 0627 { 0628 if (act) { 0629 const auto type = act->data().value<AutoCorrectionWidget::ImportFileType>(); 0630 QString title; 0631 QString filter; 0632 switch (type) { 0633 case AutoCorrectionWidget::LibreOffice: 0634 title = i18n("Import LibreOffice Autocorrection"); 0635 filter = i18n("LibreOffice Autocorrection File (*.dat)"); 0636 break; 0637 case AutoCorrectionWidget::KMail: 0638 title = i18n("Import KMail Autocorrection"); 0639 filter = i18n("KMail Autocorrection File (*.xml)"); 0640 break; 0641 } 0642 const QString fileName = QFileDialog::getOpenFileName(this, title, QString(), filter); 0643 if (!fileName.isEmpty()) { 0644 TextAutoCorrectionCore::ImportAbstractAutocorrection *importAutoCorrection = nullptr; 0645 switch (type) { 0646 case AutoCorrectionWidget::LibreOffice: 0647 importAutoCorrection = new TextAutoCorrectionCore::ImportLibreOfficeAutocorrection; 0648 break; 0649 case AutoCorrectionWidget::KMail: 0650 importAutoCorrection = new TextAutoCorrectionCore::ImportKMailAutocorrection; 0651 break; 0652 default: 0653 return; 0654 } 0655 QString messageError; 0656 if (importAutoCorrection->import(fileName, messageError, ImportAbstractAutocorrection::All)) { 0657 d->m_autocorrectEntries = importAutoCorrection->autocorrectEntries(); 0658 addAutoCorrectEntries(); 0659 0660 enableAdvAutocorrection(d->ui->advancedAutocorrection->isChecked()); 0661 0662 d->m_upperCaseExceptions = importAutoCorrection->upperCaseExceptions(); 0663 d->m_twoUpperLetterExceptions = importAutoCorrection->twoUpperLetterExceptions(); 0664 0665 d->ui->twoUpperLetterList->clear(); 0666 d->ui->twoUpperLetterList->addItems(d->m_twoUpperLetterExceptions.values()); 0667 0668 d->ui->abbreviationList->clear(); 0669 d->ui->abbreviationList->addItems(d->m_upperCaseExceptions.values()); 0670 } else { 0671 KMessageBox::error(this, messageError, i18n("Import Autocorrection File")); 0672 } 0673 delete importAutoCorrection; 0674 } 0675 } 0676 } 0677 0678 void AutoCorrectionWidget::setLanguage(const QString &lang) 0679 { 0680 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0681 settings->setLanguage(lang); 0682 d->mAutoCorrection->setAutoCorrectionSettings(settings); 0683 loadAutoCorrectionAndException(); 0684 d->mWasChanged = false; 0685 } 0686 0687 void AutoCorrectionWidget::changeLanguage(int index) 0688 { 0689 if (index == -1) { 0690 return; 0691 } 0692 if (d->mWasChanged) { 0693 const int rc = KMessageBox::warningTwoActions(this, 0694 i18n("Language was changed, do you want to save config for previous language?"), 0695 i18n("Save config"), 0696 KStandardGuiItem::save(), 0697 KStandardGuiItem::discard()); 0698 if (rc == KMessageBox::ButtonCode::PrimaryAction) { 0699 writeConfig(); 0700 } 0701 } 0702 const QString lang = d->ui->autocorrectionLanguage->itemData(index).toString(); 0703 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0704 settings->setLanguage(lang); 0705 d->mAutoCorrection->setAutoCorrectionSettings(settings); 0706 loadAutoCorrectionAndException(); 0707 d->mWasChanged = false; 0708 } 0709 0710 void AutoCorrectionWidget::emitChanged() 0711 { 0712 d->mWasChanged = true; 0713 Q_EMIT changed(); 0714 } 0715 0716 void AutoCorrectionWidget::loadGlobalAutoCorrectionAndException() 0717 { 0718 const QString lang = d->ui->autocorrectionLanguage->itemData(d->ui->autocorrectionLanguage->currentIndex()).toString(); 0719 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings(); 0720 settings->setLanguage(lang, true); 0721 d->mAutoCorrection->setAutoCorrectionSettings(settings); 0722 loadAutoCorrectionAndException(); 0723 d->mWasChanged = true; 0724 Q_EMIT changed(); 0725 } 0726 0727 void AutoCorrectionWidget::slotExportAutoCorrection() 0728 { 0729 if (d->mWasChanged) { 0730 KMessageBox::error(this, i18n("Please save changes before exporting settings."), i18n("Export Autocorrection File")); 0731 return; 0732 } 0733 const QString saveUrl = QFileDialog::getSaveFileName(this, i18n("Export Autocorrection File"), QDir::homePath()); 0734 if (saveUrl.isEmpty()) { 0735 return; 0736 } 0737 d->mAutoCorrection->writeAutoCorrectionXmlFile(saveUrl); 0738 } 0739 0740 #include "moc_autocorrectionwidget.cpp"