KTextAddons

autocorrectionwidget.cpp
1/*
2 SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "autocorrectionwidget.h"
8#include "autocorrectionutils.h"
9
10#include "ui_autocorrectionwidget.h"
11#include <TextAutoCorrectionCore/ImportAbstractAutocorrection>
12#include <TextAutoCorrectionCore/ImportKMailAutocorrection>
13#include <TextAutoCorrectionCore/ImportLibreOfficeAutocorrection>
14
15#include <KLineEditEventHandler>
16#include <TextAddonsWidgets/SelectSpecialCharDialog>
17
18#include <KLocalizedString>
19#include <KMessageBox>
20
21#include <QFileDialog>
22#include <QMenu>
23#include <QPointer>
24#include <QTreeWidgetItem>
25
26using namespace TextAutoCorrectionWidgets;
27using namespace TextAutoCorrectionCore;
28
29Q_DECLARE_METATYPE(AutoCorrectionWidget::ImportFileType)
30class TextAutoCorrectionWidgets::AutoCorrectionWidgetPrivate
31{
32public:
33 AutoCorrectionWidgetPrivate()
34 : ui(new Ui::AutoCorrectionWidget)
35 {
36 }
37
38 ~AutoCorrectionWidgetPrivate() = default;
39
40 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes m_singleQuotes;
41 TextAutoCorrectionCore::AutoCorrectionUtils::TypographicQuotes m_doubleQuotes;
42 QSet<QString> m_upperCaseExceptions;
43 QSet<QString> m_twoUpperLetterExceptions;
44 QHash<QString, QString> m_autocorrectEntries;
45 std::unique_ptr<Ui::AutoCorrectionWidget> const ui;
46 TextAutoCorrectionCore::AutoCorrection *mAutoCorrection = nullptr;
47 bool mWasChanged = false;
48 bool mHasHtmlSupport = true;
49};
50
51AutoCorrectionWidget::AutoCorrectionWidget(QWidget *parent)
52 : QWidget(parent)
53 , d(new TextAutoCorrectionWidgets::AutoCorrectionWidgetPrivate)
54{
55 d->ui->setupUi(this);
56
57 d->ui->treeWidget->setSortingEnabled(true);
58 d->ui->treeWidget->sortByColumn(0, Qt::AscendingOrder);
59
60 d->ui->add1->setEnabled(false);
61 d->ui->add2->setEnabled(false);
62
65 KLineEditEventHandler::catchReturnKey(d->ui->abbreviation);
66 KLineEditEventHandler::catchReturnKey(d->ui->twoUpperLetter);
67
68 connect(d->ui->autoChangeFormat, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
69 connect(d->ui->autoFormatUrl, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
70 connect(d->ui->upperCase, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
71 connect(d->ui->upperUpper, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
72 connect(d->ui->ignoreDoubleSpace, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
73 connect(d->ui->autoReplaceNumber, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
74 connect(d->ui->capitalizeDaysName, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
75 connect(d->ui->advancedAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
76 connect(d->ui->enabledAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
77 connect(d->ui->typographicSingleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableSingleQuotes);
78 connect(d->ui->typographicDoubleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableDoubleQuotes);
79 connect(d->ui->autoSuperScript, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
80 connect(d->ui->singleQuote1, &QPushButton::clicked, this, &AutoCorrectionWidget::selectSingleQuoteCharOpen);
81 connect(d->ui->singleQuote2, &QPushButton::clicked, this, &AutoCorrectionWidget::selectSingleQuoteCharClose);
82 connect(d->ui->singleDefault, &QPushButton::clicked, this, &AutoCorrectionWidget::setDefaultSingleQuotes);
83 connect(d->ui->doubleQuote1, &QPushButton::clicked, this, &AutoCorrectionWidget::selectDoubleQuoteCharOpen);
84 connect(d->ui->doubleQuote2, &QPushButton::clicked, this, &AutoCorrectionWidget::selectDoubleQuoteCharClose);
85 connect(d->ui->doubleDefault, &QPushButton::clicked, this, &AutoCorrectionWidget::setDefaultDoubleQuotes);
86 connect(d->ui->advancedAutocorrection, &QCheckBox::clicked, this, &AutoCorrectionWidget::enableAdvAutocorrection);
87 connect(d->ui->addButton, &QPushButton::clicked, this, &AutoCorrectionWidget::addAutocorrectEntry);
88 connect(d->ui->removeButton, &QPushButton::clicked, this, &AutoCorrectionWidget::removeAutocorrectEntry);
89 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::itemClicked, this, &AutoCorrectionWidget::setFindReplaceText);
90 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::deleteSelectedItems, this, &AutoCorrectionWidget::removeAutocorrectEntry);
91 connect(d->ui->treeWidget, &TextAutoCorrectionWidgets::AutoCorrectionTreeWidget::itemSelectionChanged, this, &AutoCorrectionWidget::updateAddRemoveButton);
92 connect(d->ui->find, &QLineEdit::textChanged, this, &AutoCorrectionWidget::enableAddRemoveButton);
93 connect(d->ui->replace, &QLineEdit::textChanged, this, &AutoCorrectionWidget::enableAddRemoveButton);
94 connect(d->ui->abbreviation, &QLineEdit::textChanged, this, &AutoCorrectionWidget::abbreviationChanged);
95 connect(d->ui->twoUpperLetter, &QLineEdit::textChanged, this, &AutoCorrectionWidget::twoUpperLetterChanged);
96 connect(d->ui->add1, &QPushButton::clicked, this, &AutoCorrectionWidget::addAbbreviationEntry);
97 connect(d->ui->remove1, &QPushButton::clicked, this, &AutoCorrectionWidget::removeAbbreviationEntry);
98 connect(d->ui->add2, &QPushButton::clicked, this, &AutoCorrectionWidget::addTwoUpperLetterEntry);
99 connect(d->ui->remove2, &QPushButton::clicked, this, &AutoCorrectionWidget::removeTwoUpperLetterEntry);
100 connect(d->ui->typographicDoubleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
101 connect(d->ui->typographicSingleQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
102 connect(d->ui->abbreviationList,
104 this,
105 &AutoCorrectionWidget::slotEnableDisableAbreviationList);
106 connect(d->ui->abbreviationList,
107 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::deleteSelectedItems,
108 this,
109 &AutoCorrectionWidget::removeAbbreviationEntry);
110 connect(d->ui->twoUpperLetterList,
112 this,
113 &AutoCorrectionWidget::slotEnableDisableTwoUpperEntry);
114 connect(d->ui->twoUpperLetterList,
115 &TextAutoCorrectionWidgets::AutoCorrectionListWidget::deleteSelectedItems,
116 this,
117 &AutoCorrectionWidget::removeTwoUpperLetterEntry);
118 connect(d->ui->autocorrectionLanguage,
120 this,
121 &AutoCorrectionWidget::changeLanguage);
122 connect(d->ui->addNonBreakingSpaceInFrench, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
123 connect(d->ui->twoUpperLetter, &QLineEdit::returnPressed, this, &AutoCorrectionWidget::addTwoUpperLetterEntry);
124 connect(d->ui->abbreviation, &QLineEdit::returnPressed, this, &AutoCorrectionWidget::addAbbreviationEntry);
125 connect(d->ui->replaceDoubleQuotesByFrenchQuotes, &QCheckBox::clicked, this, &AutoCorrectionWidget::emitChanged);
126
127 connect(d->ui->customWritablePath, &QLineEdit::textChanged, this, &AutoCorrectionWidget::emitChanged);
128 connect(d->ui->customSystemPath, &QLineEdit::textChanged, this, &AutoCorrectionWidget::emitChanged);
129
130 KLineEditEventHandler::catchReturnKey(d->ui->customWritablePath);
131 KLineEditEventHandler::catchReturnKey(d->ui->customSystemPath);
132
133 connect(d->ui->customWritablePathToolButton, &QToolButton::clicked, this, [this]() {
134 const QString path = QFileDialog::getExistingDirectory(this, i18n("Select Custom Writable Path"));
135 d->ui->customWritablePath->setText(path);
136 });
137
138 connect(d->ui->customSystemPathToolButton, &QToolButton::clicked, this, [this]() {
139 const QString path = QFileDialog::getExistingDirectory(this, i18n("Select Custom System Path"));
140 d->ui->customSystemPath->setText(path);
141 });
142
143 slotEnableDisableAbreviationList();
144 slotEnableDisableTwoUpperEntry();
145
146 auto menu = new QMenu(this);
147 d->ui->importAutoCorrection->setMenu(menu);
148
149 auto act = new QAction(i18nc("@action", "LibreOffice Autocorrection"), this);
150 act->setData(QVariant::fromValue(AutoCorrectionWidget::LibreOffice));
151 menu->addAction(act);
152
153 act = new QAction(i18nc("@action", "KMail/Calligra Autocorrection"), this);
154 act->setData(QVariant::fromValue(AutoCorrectionWidget::KMail));
155 menu->addAction(act);
156
157 connect(menu, &QMenu::triggered, this, &AutoCorrectionWidget::slotImportAutoCorrection);
158
159 connect(d->ui->exportAutoCorrection, &QPushButton::clicked, this, &AutoCorrectionWidget::slotExportAutoCorrection);
160 connect(d->ui->tabWidget, &QTabWidget::tabBarClicked, this, &AutoCorrectionWidget::slotChangeComboboxState);
161 slotChangeComboboxState(d->ui->tabWidget->currentIndex());
162
163 d->ui->systemPath->setText(TextAutoCorrectionCore::AutoCorrectionUtils::libreOfficeSystemPath());
164 d->ui->writablePath->setText(TextAutoCorrectionCore::AutoCorrectionUtils::libreOfficeWritableLocalAutoCorrectionPath());
165}
166
167AutoCorrectionWidget::~AutoCorrectionWidget() = default;
168
169void AutoCorrectionWidget::slotChangeComboboxState(int index)
170{
171 d->ui->autocorrectionLanguage->setEnabled(index < 2);
172}
173
174void AutoCorrectionWidget::setAutoCorrection(TextAutoCorrectionCore::AutoCorrection *autoCorrect)
175{
176 d->mAutoCorrection = autoCorrect;
177 setLanguage(d->ui->autocorrectionLanguage->language());
178}
179
180void AutoCorrectionWidget::setHasHtmlSupport(bool b)
181{
182 if (d->mHasHtmlSupport != b) {
183 d->mHasHtmlSupport = b;
184 updateHtmlSupport();
185 }
186}
187
188void AutoCorrectionWidget::updateHtmlSupport()
189{
190 d->ui->autoFormatUrl->setVisible(d->mHasHtmlSupport);
191 d->ui->autoSuperScript->setVisible(d->mHasHtmlSupport);
192 d->ui->autoChangeFormat->setVisible(d->mHasHtmlSupport);
193}
194
195void AutoCorrectionWidget::loadConfig()
196{
197 if (!d->mAutoCorrection) {
198 return;
199 }
200 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
201 d->ui->autoChangeFormat->setChecked(settings->isAutoBoldUnderline());
202 d->ui->autoFormatUrl->setChecked(settings->isAutoFormatUrl());
203 d->ui->enabledAutocorrection->setChecked(settings->isEnabledAutoCorrection());
204 d->ui->upperCase->setChecked(settings->isUppercaseFirstCharOfSentence());
205 d->ui->upperUpper->setChecked(settings->isFixTwoUppercaseChars());
206 d->ui->ignoreDoubleSpace->setChecked(settings->isSingleSpaces());
207 d->ui->autoReplaceNumber->setChecked(settings->isAutoFractions());
208 d->ui->capitalizeDaysName->setChecked(settings->isCapitalizeWeekDays());
209 d->ui->advancedAutocorrection->setChecked(settings->isAdvancedAutocorrect());
210 d->ui->autoSuperScript->setChecked(settings->isSuperScript());
211 d->ui->typographicDoubleQuotes->setChecked(settings->isReplaceDoubleQuotes());
212 d->ui->typographicSingleQuotes->setChecked(settings->isReplaceSingleQuotes());
213 d->ui->addNonBreakingSpaceInFrench->setChecked(settings->isAddNonBreakingSpace());
214 d->ui->replaceDoubleQuotesByFrenchQuotes->setChecked(settings->isReplaceDoubleQuotesByFrenchQuotes());
215
216 d->ui->customWritablePath->setText(settings->customWritablePath());
217 d->ui->customSystemPath->setText(settings->customSystemPath());
218
219 loadAutoCorrectionAndException();
220 d->mWasChanged = false;
221}
222
223void AutoCorrectionWidget::loadAutoCorrectionAndException()
224{
225 /* tab 2 - Custom Quotes */
226 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
227 d->m_singleQuotes = settings->typographicSingleQuotes();
228 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin);
229 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end);
230 d->m_doubleQuotes = settings->typographicDoubleQuotes();
231 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin);
232 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end);
233 enableSingleQuotes(d->ui->typographicSingleQuotes->isChecked());
234 enableDoubleQuotes(d->ui->typographicDoubleQuotes->isChecked());
235
236 /* tab 3 - Advanced Autocorrection */
237 d->m_autocorrectEntries = settings->autocorrectEntries();
238 addAutoCorrectEntries();
239
240 enableAdvAutocorrection(d->ui->advancedAutocorrection->isChecked());
241 /* tab 4 - Exceptions */
242 d->m_upperCaseExceptions = settings->upperCaseExceptions();
243 d->m_twoUpperLetterExceptions = settings->twoUpperLetterExceptions();
244
245 d->ui->twoUpperLetterList->clear();
246 d->ui->twoUpperLetterList->addItems(d->m_twoUpperLetterExceptions.values());
247
248 d->ui->abbreviationList->clear();
249 d->ui->abbreviationList->addItems(d->m_upperCaseExceptions.values());
250}
251
252void AutoCorrectionWidget::addAutoCorrectEntries()
253{
254 d->ui->treeWidget->clear();
255 QHash<QString, QString>::const_iterator i = d->m_autocorrectEntries.constBegin();
256 QTreeWidgetItem *item = nullptr;
257 while (i != d->m_autocorrectEntries.constEnd()) {
258 item = new QTreeWidgetItem(d->ui->treeWidget, item);
259 item->setText(0, i.key());
260 item->setText(1, i.value());
261 ++i;
262 }
263 d->ui->treeWidget->setSortingEnabled(true);
264 d->ui->treeWidget->sortByColumn(0, Qt::AscendingOrder);
265}
266
267void AutoCorrectionWidget::writeConfig()
268{
269 if (!d->mAutoCorrection) {
270 return;
271 }
272 AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
273 settings->setAutoBoldUnderline(d->ui->autoChangeFormat->isChecked());
274 settings->setAutoFormatUrl(d->ui->autoFormatUrl->isChecked());
275 settings->setEnabledAutoCorrection(d->ui->enabledAutocorrection->isChecked());
276 settings->setUppercaseFirstCharOfSentence(d->ui->upperCase->isChecked());
277 settings->setFixTwoUppercaseChars(d->ui->upperUpper->isChecked());
278 settings->setSingleSpaces(d->ui->ignoreDoubleSpace->isChecked());
279 settings->setCapitalizeWeekDays(d->ui->capitalizeDaysName->isChecked());
280 settings->setAdvancedAutocorrect(d->ui->advancedAutocorrection->isChecked());
281 settings->setSuperScript(d->ui->autoSuperScript->isChecked());
282
283 settings->setAutoFractions(d->ui->autoReplaceNumber->isChecked());
284
285 settings->setAutocorrectEntries(d->m_autocorrectEntries);
286 settings->setUpperCaseExceptions(d->m_upperCaseExceptions);
287 settings->setTwoUpperLetterExceptions(d->m_twoUpperLetterExceptions);
288
289 settings->setReplaceDoubleQuotes(d->ui->typographicDoubleQuotes->isChecked());
290 settings->setReplaceSingleQuotes(d->ui->typographicSingleQuotes->isChecked());
291 settings->setTypographicSingleQuotes(d->m_singleQuotes);
292 settings->setTypographicDoubleQuotes(d->m_doubleQuotes);
293 settings->setAddNonBreakingSpace(d->ui->addNonBreakingSpaceInFrench->isChecked());
294 settings->setReplaceDoubleQuotesByFrenchQuotes(d->ui->replaceDoubleQuotesByFrenchQuotes->isChecked());
295
296 settings->setCustomWritablePath(d->ui->customWritablePath->text());
297 settings->setCustomSystemPath(d->ui->customSystemPath->text());
298
299 d->mAutoCorrection->setAutoCorrectionSettings(settings);
300 d->mAutoCorrection->writeConfig();
301 d->mWasChanged = false;
302}
303
304void AutoCorrectionWidget::resetToDefault()
305{
306 d->ui->autoChangeFormat->setChecked(false);
307 d->ui->autoFormatUrl->setChecked(false);
308 d->ui->upperCase->setChecked(false);
309 d->ui->upperUpper->setChecked(false);
310 d->ui->ignoreDoubleSpace->setChecked(false);
311 d->ui->capitalizeDaysName->setChecked(false);
312 d->ui->advancedAutocorrection->setChecked(false);
313 d->ui->typographicDoubleQuotes->setChecked(false);
314 d->ui->typographicSingleQuotes->setChecked(false);
315 d->ui->autoSuperScript->setChecked(false);
316 d->ui->autoReplaceNumber->setChecked(false);
317 d->ui->typographicDoubleQuotes->setChecked(false);
318 d->ui->typographicSingleQuotes->setChecked(false);
319 d->ui->addNonBreakingSpaceInFrench->setChecked(false);
320
321 loadGlobalAutoCorrectionAndException();
322}
323
324void AutoCorrectionWidget::enableSingleQuotes(bool state)
325{
326 d->ui->singleQuote1->setEnabled(state);
327 d->ui->singleQuote2->setEnabled(state);
328 d->ui->singleDefault->setEnabled(state);
329}
330
331void AutoCorrectionWidget::enableDoubleQuotes(bool state)
332{
333 d->ui->doubleQuote1->setEnabled(state);
334 d->ui->doubleQuote2->setEnabled(state);
335 d->ui->doubleDefault->setEnabled(state);
336}
337
338void AutoCorrectionWidget::selectSingleQuoteCharOpen()
339{
341 dlg->setCurrentChar(d->m_singleQuotes.begin);
342 dlg->showSelectButton(false);
343 dlg->autoInsertChar();
344 if (dlg->exec()) {
345 d->m_singleQuotes.begin = dlg->currentChar();
346 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin);
347 emitChanged();
348 }
349 delete dlg;
350}
351
352void AutoCorrectionWidget::selectSingleQuoteCharClose()
353{
355 dlg->showSelectButton(false);
356 dlg->setCurrentChar(d->m_singleQuotes.end);
357 dlg->autoInsertChar();
358 if (dlg->exec()) {
359 d->m_singleQuotes.end = dlg->currentChar();
360 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end);
361 emitChanged();
362 }
363 delete dlg;
364}
365
366void AutoCorrectionWidget::setDefaultSingleQuotes()
367{
368 d->m_singleQuotes = TextAutoCorrectionCore::AutoCorrectionUtils::typographicDefaultSingleQuotes();
369 d->ui->simpleQuoteBeginReplace->setText(d->m_singleQuotes.begin);
370 d->ui->simpleQuoteEndReplace->setText(d->m_singleQuotes.end);
371 emitChanged();
372}
373
374void AutoCorrectionWidget::selectDoubleQuoteCharOpen()
375{
377 dlg->showSelectButton(false);
378 dlg->setCurrentChar(d->m_doubleQuotes.begin);
379 dlg->autoInsertChar();
380 if (dlg->exec()) {
381 d->m_doubleQuotes.begin = dlg->currentChar();
382 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin);
383 emitChanged();
384 }
385 delete dlg;
386}
387
388void AutoCorrectionWidget::selectDoubleQuoteCharClose()
389{
391 dlg->showSelectButton(false);
392 dlg->setCurrentChar(d->m_doubleQuotes.end);
393 dlg->autoInsertChar();
394 if (dlg->exec()) {
395 d->m_doubleQuotes.end = dlg->currentChar();
396 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end);
397 emitChanged();
398 }
399 delete dlg;
400}
401
402void AutoCorrectionWidget::setDefaultDoubleQuotes()
403{
404 d->m_doubleQuotes = AutoCorrectionUtils::typographicDefaultDoubleQuotes();
405 d->ui->doubleQuoteBeginReplace->setText(d->m_doubleQuotes.begin);
406 d->ui->doubleQuoteEndReplace->setText(d->m_doubleQuotes.end);
407 emitChanged();
408}
409
410void AutoCorrectionWidget::enableAdvAutocorrection(bool state)
411{
412 d->ui->findLabel->setEnabled(state);
413 d->ui->find->setEnabled(state);
414 d->ui->replaceLabel->setEnabled(state);
415 d->ui->replace->setEnabled(state);
416
417 const QString find = d->ui->find->text();
418 const QString replace = d->ui->replace->text();
419
420 d->ui->addButton->setEnabled(state && !find.isEmpty() && !replace.isEmpty());
421 d->ui->removeButton->setEnabled(state && d->ui->treeWidget->currentItem());
422 d->ui->treeWidget->setEnabled(state);
423}
424
425void AutoCorrectionWidget::addAutocorrectEntry()
426{
427 QTreeWidgetItem *item = d->ui->treeWidget->currentItem();
428 const QString find = d->ui->find->text();
429 const QString replace = d->ui->replace->text();
430 if (find == replace) {
431 KMessageBox::error(this, i18n("\"Replace\" string is the same as \"Find\" string."), i18nc("@title:window", "Add Autocorrection Entry"));
432 return;
433 }
434
435 bool modify = false;
436
437 // Modify actually, not add, so we want to remove item from hash
438 if (item && (find == item->text(0))) {
439 d->m_autocorrectEntries.remove(find);
440 modify = true;
441 }
442
443 d->m_autocorrectEntries.insert(find, replace);
444 d->ui->treeWidget->setSortingEnabled(false);
445 if (modify) {
446 item->setText(0, find);
447 item->setText(1, replace);
448 } else {
449 item = new QTreeWidgetItem(d->ui->treeWidget, item);
450 item->setText(0, find);
451 item->setText(1, replace);
452 }
453
454 d->ui->treeWidget->setSortingEnabled(true);
455 d->ui->treeWidget->setCurrentItem(item);
456 emitChanged();
457}
458
459void AutoCorrectionWidget::removeAutocorrectEntry()
460{
461 const QList<QTreeWidgetItem *> listItems = d->ui->treeWidget->selectedItems();
462 if (listItems.isEmpty()) {
463 return;
464 }
465 for (QTreeWidgetItem *item : listItems) {
466 QTreeWidgetItem *below = d->ui->treeWidget->itemBelow(item);
467
468 QString findStr;
469 if (below) {
470 // qCDebug(TEXTAUTOCORRECTION_AUTOCORRECT_LOG) << "below";
471 findStr = item->text(0);
472 delete item;
473 item = nullptr;
474 } else if (d->ui->treeWidget->topLevelItemCount() > 0) {
475 findStr = item->text(0);
476 delete item;
477 item = nullptr;
478 }
479 if (!findStr.isEmpty()) {
480 d->m_autocorrectEntries.remove(findStr);
481 }
482 }
483 d->ui->treeWidget->setSortingEnabled(false);
484
485 emitChanged();
486}
487
488void AutoCorrectionWidget::updateAddRemoveButton()
489{
490 QList<QTreeWidgetItem *> listItems = d->ui->treeWidget->selectedItems();
491 d->ui->removeButton->setEnabled(!listItems.isEmpty());
492}
493
494void AutoCorrectionWidget::enableAddRemoveButton()
495{
496 const QString find = d->ui->find->text();
497 const QString replace = d->ui->replace->text();
498
499 QTreeWidgetItem *item = nullptr;
500 if (d->m_autocorrectEntries.contains(find)) {
501 item = d->ui->treeWidget->findItems(find, Qt::MatchCaseSensitive).at(0);
502 }
503
504 bool enable = false;
505 if (find.isEmpty() || replace.isEmpty()) { // disable if no text in find/replace
506 enable = !(find.isEmpty() || replace.isEmpty());
507 } else if (item && find == item->text(0)) {
508 // We disable add / remove button if no text for the replacement
509 enable = !item->text(1).isEmpty();
510 d->ui->addButton->setText(i18n("&Modify"));
511 } else if (!item || !item->text(1).isEmpty()) {
512 enable = true;
513 d->ui->addButton->setText(i18n("&Add"));
514 }
515
516 if (item && replace == item->text(1)) {
517 d->ui->addButton->setEnabled(false);
518 } else {
519 d->ui->addButton->setEnabled(enable);
520 }
521 d->ui->removeButton->setEnabled(enable);
522}
523
524void AutoCorrectionWidget::setFindReplaceText(QTreeWidgetItem *item, int column)
525{
526 Q_UNUSED(column)
527 d->ui->find->setText(item->text(0));
528 d->ui->replace->setText(item->text(1));
529}
530
531void AutoCorrectionWidget::abbreviationChanged(const QString &text)
532{
533 d->ui->add1->setEnabled(!text.isEmpty());
534}
535
536void AutoCorrectionWidget::twoUpperLetterChanged(const QString &text)
537{
538 d->ui->add2->setEnabled(!text.isEmpty());
539}
540
541void AutoCorrectionWidget::addAbbreviationEntry()
542{
543 const QString text = d->ui->abbreviation->text();
544 if (text.isEmpty()) {
545 return;
546 }
547 if (!d->m_upperCaseExceptions.contains(text)) {
548 d->m_upperCaseExceptions.insert(text);
549 d->ui->abbreviationList->addItem(text);
550 }
551 d->ui->abbreviation->clear();
552 slotEnableDisableAbreviationList();
553 emitChanged();
554}
555
556void AutoCorrectionWidget::removeAbbreviationEntry()
557{
558 const QList<QListWidgetItem *> listItem = d->ui->abbreviationList->selectedItems();
559 if (listItem.isEmpty()) {
560 return;
561 }
562 for (QListWidgetItem *item : listItem) {
563 d->m_upperCaseExceptions.remove(item->text());
564 delete item;
565 }
566 slotEnableDisableAbreviationList();
567 emitChanged();
568}
569
570void AutoCorrectionWidget::addTwoUpperLetterEntry()
571{
572 const QString text = d->ui->twoUpperLetter->text();
573 if (text.isEmpty()) {
574 return;
575 }
576 if (!d->m_twoUpperLetterExceptions.contains(text)) {
577 d->m_twoUpperLetterExceptions.insert(text);
578 d->ui->twoUpperLetterList->addItem(text);
579 emitChanged();
580 }
581 slotEnableDisableTwoUpperEntry();
582 d->ui->twoUpperLetter->clear();
583}
584
585void AutoCorrectionWidget::removeTwoUpperLetterEntry()
586{
587 const QList<QListWidgetItem *> listItem = d->ui->twoUpperLetterList->selectedItems();
588 if (listItem.isEmpty()) {
589 return;
590 }
591 for (QListWidgetItem *item : listItem) {
592 d->m_twoUpperLetterExceptions.remove(item->text());
593 delete item;
594 }
595 slotEnableDisableTwoUpperEntry();
596 emitChanged();
597}
598
599void AutoCorrectionWidget::slotEnableDisableAbreviationList()
600{
601 const bool enable = (!d->ui->abbreviationList->selectedItems().isEmpty());
602 d->ui->add1->setEnabled(!d->ui->abbreviation->text().isEmpty());
603 d->ui->remove1->setEnabled(enable);
604}
605
606void AutoCorrectionWidget::slotEnableDisableTwoUpperEntry()
607{
608 const bool enable = (!d->ui->twoUpperLetterList->selectedItems().isEmpty());
609 d->ui->add2->setEnabled(!d->ui->twoUpperLetter->text().isEmpty());
610 d->ui->remove2->setEnabled(enable);
611}
612
613void AutoCorrectionWidget::slotImportAutoCorrection(QAction *act)
614{
615 if (act) {
616 const auto type = act->data().value<AutoCorrectionWidget::ImportFileType>();
617 QString title;
619 switch (type) {
620 case AutoCorrectionWidget::LibreOffice:
621 title = i18n("Import LibreOffice Autocorrection");
622 filter = i18n("LibreOffice Autocorrection File (*.dat)");
623 break;
624 case AutoCorrectionWidget::KMail:
625 title = i18n("Import KMail Autocorrection");
626 filter = i18n("KMail Autocorrection File (*.xml)");
627 break;
628 }
629 const QString fileName = QFileDialog::getOpenFileName(this, title, QString(), filter);
630 if (!fileName.isEmpty()) {
631 TextAutoCorrectionCore::ImportAbstractAutocorrection *importAutoCorrection = nullptr;
632 switch (type) {
633 case AutoCorrectionWidget::LibreOffice:
634 importAutoCorrection = new TextAutoCorrectionCore::ImportLibreOfficeAutocorrection;
635 break;
636 case AutoCorrectionWidget::KMail:
637 importAutoCorrection = new TextAutoCorrectionCore::ImportKMailAutocorrection;
638 break;
639 default:
640 return;
641 }
642 QString messageError;
643 if (importAutoCorrection->import(fileName, messageError, ImportAbstractAutocorrection::All)) {
644 d->m_autocorrectEntries = importAutoCorrection->autocorrectEntries();
645 addAutoCorrectEntries();
646
647 enableAdvAutocorrection(d->ui->advancedAutocorrection->isChecked());
648
649 d->m_upperCaseExceptions = importAutoCorrection->upperCaseExceptions();
650 d->m_twoUpperLetterExceptions = importAutoCorrection->twoUpperLetterExceptions();
651
652 d->ui->twoUpperLetterList->clear();
653 d->ui->twoUpperLetterList->addItems(d->m_twoUpperLetterExceptions.values());
654
655 d->ui->abbreviationList->clear();
656 d->ui->abbreviationList->addItems(d->m_upperCaseExceptions.values());
657 } else {
658 KMessageBox::error(this, messageError, i18nc("@title:window", "Import Autocorrection File"));
659 }
660 delete importAutoCorrection;
661 }
662 }
663}
664
665void AutoCorrectionWidget::setLanguage(const QString &lang)
666{
667 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
668 settings->setLanguage(lang);
669 d->mAutoCorrection->setAutoCorrectionSettings(settings);
670 loadAutoCorrectionAndException();
671 d->mWasChanged = false;
672}
673
674void AutoCorrectionWidget::changeLanguage()
675{
676 const QString lang = d->ui->autocorrectionLanguage->language();
677 if (lang.isEmpty()) {
678 return;
679 }
680 if (d->mWasChanged) {
681 const int rc = KMessageBox::warningTwoActions(this,
682 i18n("Language was changed, do you want to save config for previous language?"),
683 i18nc("@title:window", "Save config"),
686 if (rc == KMessageBox::ButtonCode::PrimaryAction) {
687 writeConfig();
688 }
689 }
690
691 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
692 settings->setLanguage(lang);
693 d->mAutoCorrection->setAutoCorrectionSettings(settings);
694 loadAutoCorrectionAndException();
695 d->mWasChanged = false;
696}
697
698void AutoCorrectionWidget::emitChanged()
699{
700 d->mWasChanged = true;
701 Q_EMIT changed();
702}
703
704void AutoCorrectionWidget::loadGlobalAutoCorrectionAndException()
705{
706 const QString lang = d->ui->autocorrectionLanguage->language();
707 TextAutoCorrectionCore::AutoCorrectionSettings *settings = d->mAutoCorrection->autoCorrectionSettings();
708 settings->setLanguage(lang, true);
709 d->mAutoCorrection->setAutoCorrectionSettings(settings);
710 loadAutoCorrectionAndException();
711 d->mWasChanged = true;
712 Q_EMIT changed();
713}
714
715void AutoCorrectionWidget::slotExportAutoCorrection()
716{
717 if (d->mWasChanged) {
718 KMessageBox::error(this, i18n("Please save changes before exporting settings."), i18nc("@title:window", "Export Autocorrection File"));
719 return;
720 }
721 const QString saveUrl = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Export Autocorrection File"), QDir::homePath());
722 if (saveUrl.isEmpty()) {
723 return;
724 }
725 d->mAutoCorrection->writeAutoCorrectionXmlFile(saveUrl);
726}
727
728#include "moc_autocorrectionwidget.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
void catchReturnKey(QObject *lineEdit)
ButtonCode warningTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KGuiItem save()
KGuiItem discard()
const QList< QKeySequence > & replace()
void clicked(bool checked)
QVariant data() const const
void currentIndexChanged(int index)
QString homePath()
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
void returnPressed()
void textChanged(const QString &text)
bool isEmpty() const const
void itemSelectionChanged()
void triggered(QAction *action)
Q_EMITQ_EMIT
bool isEmpty() const const
MatchCaseSensitive
AscendingOrder
void tabBarClicked(int index)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void itemClicked(QTreeWidgetItem *item, int column)
void itemSelectionChanged()
void setText(int column, const QString &text)
QString text(int column) const const
QVariant fromValue(T &&value)
T value() const const
QWidget * find(WId id)
void setupUi(QWidget *widget)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:49 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.