diff --git a/src/ui/dialog.cpp b/src/ui/dialog.cpp index 8cd6398..e531cbd 100644 --- a/src/ui/dialog.cpp +++ b/src/ui/dialog.cpp @@ -1,436 +1,437 @@ /** * dialog.cpp * * Copyright (C) 2003 Zack Rusin * Copyright (C) 2009-2010 Michel Ludwig * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "dialog.h" #include "ui_sonnetui.h" #include "backgroundchecker.h" #include "speller.h" #include "settings_p.h" #include #include #include #include #include #include #include #include #include namespace Sonnet { //to initially disable sorting in the suggestions listview #define NONSORTINGCOLUMN 2 class ReadOnlyStringListModel : public QStringListModel { public: ReadOnlyStringListModel(QObject *parent) : QStringListModel(parent) { } Qt::ItemFlags flags(const QModelIndex &index) const override { Q_UNUSED(index); return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } }; class DialogPrivate { public: Ui_SonnetUi ui; ReadOnlyStringListModel *suggestionsModel = nullptr; QWidget *wdg = nullptr; QDialogButtonBox *buttonBox = nullptr; QProgressDialog *progressDialog = nullptr; QString originalBuffer; BackgroundChecker *checker = nullptr; QString currentWord; int currentPosition; QMap replaceAllMap; bool restart;//used when text is distributed across several qtextedits, eg in KAider QMap dictsMap; int progressDialogTimeout; bool showCompletionMessageBox; bool spellCheckContinuedAfterReplacement; bool canceled; void deleteProgressDialog(bool directly) { if (progressDialog) { progressDialog->hide(); if (directly) { delete progressDialog; } else { progressDialog->deleteLater(); } progressDialog = nullptr; } } }; Dialog::Dialog(BackgroundChecker *checker, QWidget *parent) : QDialog(parent) , d(new DialogPrivate) { setModal(true); setWindowTitle(tr("Check Spelling", "@title:window")); d->checker = checker; d->canceled = false; d->showCompletionMessageBox = false; d->spellCheckContinuedAfterReplacement = true; d->progressDialogTimeout = -1; d->progressDialog = nullptr; initGui(); initConnections(); } Dialog::~Dialog() { delete d; } void Dialog::initConnections() { connect(d->ui.m_addBtn, &QAbstractButton::clicked, this, &Dialog::slotAddWord); connect(d->ui.m_replaceBtn, &QAbstractButton::clicked, this, &Dialog::slotReplaceWord); connect(d->ui.m_replaceAllBtn, &QAbstractButton::clicked, this, &Dialog::slotReplaceAll); connect(d->ui.m_skipBtn, &QAbstractButton::clicked, this, &Dialog::slotSkip); connect(d->ui.m_skipAllBtn, &QAbstractButton::clicked, this, &Dialog::slotSkipAll); connect(d->ui.m_suggestBtn, &QAbstractButton::clicked, this, &Dialog::slotSuggest); connect(d->ui.m_language, SIGNAL(activated(QString)), SLOT(slotChangeLanguage(QString))); connect(d->ui.m_suggestions, SIGNAL(clicked(QModelIndex)), SLOT(slotSelectionChanged(QModelIndex))); connect(d->checker, SIGNAL(misspelling(QString,int)), SLOT(slotMisspelling(QString,int))); connect(d->checker, SIGNAL(done()), SLOT(slotDone())); connect(d->ui.m_suggestions, SIGNAL(doubleClicked(QModelIndex)), SLOT(slotReplaceWord())); connect(d->buttonBox, &QDialogButtonBox::accepted, this, &Dialog::slotFinished); connect(d->buttonBox, &QDialogButtonBox::rejected, this, &Dialog::slotCancel); connect(d->ui.m_replacement, SIGNAL(returnPressed()), this, SLOT(slotReplaceWord())); connect(d->ui.m_autoCorrect, SIGNAL(clicked()), SLOT(slotAutocorrect())); // button use by kword/kpresenter // hide by default d->ui.m_autoCorrect->hide(); } void Dialog::initGui() { QVBoxLayout *layout = new QVBoxLayout(this); d->wdg = new QWidget(this); d->ui.setupUi(d->wdg); layout->addWidget(d->wdg); setGuiEnabled(false); d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); layout->addWidget(d->wdg); layout->addWidget(d->buttonBox); //d->ui.m_suggestions->setSorting( NONSORTINGCOLUMN ); fillDictionaryComboBox(); d->restart = false; d->suggestionsModel = new ReadOnlyStringListModel(this); d->ui.m_suggestions->setModel(d->suggestionsModel); } void Dialog::activeAutoCorrect(bool _active) { if (_active) { d->ui.m_autoCorrect->show(); } else { d->ui.m_autoCorrect->hide(); } } void Dialog::showProgressDialog(int timeout) { d->progressDialogTimeout = timeout; } void Dialog::showSpellCheckCompletionMessage(bool b) { d->showCompletionMessageBox = b; } void Dialog::setSpellCheckContinuedAfterReplacement(bool b) { d->spellCheckContinuedAfterReplacement = b; } void Dialog::slotAutocorrect() { setGuiEnabled(false); setProgressDialogVisible(true); emit autoCorrect(d->currentWord, d->ui.m_replacement->text()); slotReplaceWord(); } void Dialog::setGuiEnabled(bool b) { d->wdg->setEnabled(b); } void Dialog::setProgressDialogVisible(bool b) { if (!b) { d->deleteProgressDialog(true); } else if (d->progressDialogTimeout >= 0) { if (d->progressDialog) { return; } d->progressDialog = new QProgressDialog(this); d->progressDialog->setLabelText(tr("Spell checking in progress...", "progress label")); d->progressDialog->setWindowTitle(tr("Check Spelling", "@title:window")); d->progressDialog->setModal(true); d->progressDialog->setAutoClose(false); d->progressDialog->setAutoReset(false); // create an 'indefinite' progress box as we currently cannot get progress feedback from // the speller d->progressDialog->reset(); d->progressDialog->setRange(0, 0); d->progressDialog->setValue(0); connect(d->progressDialog, &QProgressDialog::canceled, this, &Dialog::slotCancel); d->progressDialog->setMinimumDuration(d->progressDialogTimeout); } } void Dialog::slotFinished() { setProgressDialogVisible(false); emit stop(); //FIXME: should we emit done here? emit done(d->checker->text()); emit spellCheckStatus(tr("Spell check stopped.")); accept(); } void Dialog::slotCancel() { d->canceled = true; d->deleteProgressDialog(false); // this method can be called in response to // pressing 'Cancel' on the dialog emit cancel(); emit spellCheckStatus(tr("Spell check canceled.")); reject(); } QString Dialog::originalBuffer() const { return d->originalBuffer; } QString Dialog::buffer() const { return d->checker->text(); } void Dialog::setBuffer(const QString &buf) { d->originalBuffer = buf; //it is possible to change buffer inside slot connected to done() signal d->restart = true; } void Dialog::fillDictionaryComboBox() { + // Since m_language is changed to DictionaryComboBox most code here is gone, + // So fillDictionaryComboBox() could be removed and code moved to initGui() + // because the call in show() looks obsolete Speller speller = d->checker->speller(); d->dictsMap = speller.availableDictionaries(); - QStringList langs = d->dictsMap.keys(); - d->ui.m_language->clear(); - d->ui.m_language->addItems(langs); + updateDictionaryComboBox(); } void Dialog::updateDictionaryComboBox() { const Speller &speller = d->checker->speller(); - d->ui.m_language->setCurrentIndex(d->dictsMap.values().indexOf(speller.language())); + d->ui.m_language->setCurrentByDictionary(speller.language()); } void Dialog::updateDialog(const QString &word) { d->ui.m_unknownWord->setText(word); d->ui.m_contextLabel->setText(d->checker->currentContext()); const QStringList suggs = d->checker->suggest(word); if (suggs.isEmpty()) { d->ui.m_replacement->clear(); } else { d->ui.m_replacement->setText(suggs.first()); } fillSuggestions(suggs); } void Dialog::show() { d->canceled = false; fillDictionaryComboBox(); if (d->originalBuffer.isEmpty()) { d->checker->start(); } else { d->checker->setText(d->originalBuffer); } setProgressDialogVisible(true); } void Dialog::slotAddWord() { setGuiEnabled(false); setProgressDialogVisible(true); d->checker->addWordToPersonal(d->currentWord); d->checker->continueChecking(); } void Dialog::slotReplaceWord() { setGuiEnabled(false); setProgressDialogVisible(true); QString replacementText = d->ui.m_replacement->text(); emit replace(d->currentWord, d->currentPosition, replacementText); if (d->spellCheckContinuedAfterReplacement) { d->checker->replace(d->currentPosition, d->currentWord, replacementText); d->checker->continueChecking(); } else { d->checker->stop(); } } void Dialog::slotReplaceAll() { setGuiEnabled(false); setProgressDialogVisible(true); d->replaceAllMap.insert(d->currentWord, d->ui.m_replacement->text()); slotReplaceWord(); } void Dialog::slotSkip() { setGuiEnabled(false); setProgressDialogVisible(true); d->checker->continueChecking(); } void Dialog::slotSkipAll() { setGuiEnabled(false); setProgressDialogVisible(true); //### do we want that or should we have a d->ignoreAll list? Speller speller = d->checker->speller(); speller.addToPersonal(d->currentWord); d->checker->setSpeller(speller); d->checker->continueChecking(); } void Dialog::slotSuggest() { QStringList suggs = d->checker->suggest(d->ui.m_replacement->text()); fillSuggestions(suggs); } void Dialog::slotChangeLanguage(const QString &lang) { Speller speller = d->checker->speller(); QString languageCode = d->dictsMap[lang]; if (!languageCode.isEmpty()) { d->checker->changeLanguage(languageCode); slotSuggest(); emit languageChanged(languageCode); } } void Dialog::slotSelectionChanged(const QModelIndex &item) { d->ui.m_replacement->setText(item.data().toString()); } void Dialog::fillSuggestions(const QStringList &suggs) { d->suggestionsModel->setStringList(suggs); } void Dialog::slotMisspelling(const QString &word, int start) { setGuiEnabled(true); setProgressDialogVisible(false); emit misspelling(word, start); //NOTE this is HACK I had to introduce because BackgroundChecker lacks 'virtual' marks on methods //this dramatically reduces spellchecking time in Lokalize //as this doesn't fetch suggestions for words that are present in msgid if (!updatesEnabled()) { return; } d->currentWord = word; d->currentPosition = start; if (d->replaceAllMap.contains(word)) { d->ui.m_replacement->setText(d->replaceAllMap[ word ]); slotReplaceWord(); } else { updateDialog(word); } QDialog::show(); } void Dialog::slotDone() { d->restart = false; emit done(d->checker->text()); if (d->restart) { updateDictionaryComboBox(); d->checker->setText(d->originalBuffer); d->restart = false; } else { setProgressDialogVisible(false); emit spellCheckStatus(tr("Spell check complete.")); accept(); if (!d->canceled && d->showCompletionMessageBox) { QMessageBox::information(this, tr("Spell check complete."), tr("Check Spelling", "@title:window")); } } } } diff --git a/src/ui/sonnetui.ui b/src/ui/sonnetui.ui index 06ebed0..1d12f2c 100644 --- a/src/ui/sonnetui.ui +++ b/src/ui/sonnetui.ui @@ -1,306 +1,313 @@ SonnetUi 0 0 481 311 0 0 430 300 0 0 0 0 <qt><p>This word was considered to be an "unknown word" because it does not match any entry in the dictionary currently in use. It may also be a word in a foreign language.</p> <p>If the word is not misspelled, you may add it to the dictionary by clicking <b>Add to Dictionary</b>. If you do not want to add the unknown word to the dictionary, but you want to leave it unchanged, click <b>Ignore</b> or <b>Ignore All</b>.</p> <p>However, if the word is misspelled, you can try to find the correct replacement in the list below. If you cannot find a replacement there, you may type it in the text box below, and click <b>Replace</b> or <b>Replace All</b>.</p> </qt> Unknown word: Unknown word <qt><p>This word was considered to be an "unknown word" because it does not match any entry in the dictionary currently in use. It may also be a word in a foreign language.</p> <p>If the word is not misspelled, you may add it to the dictionary by clicking <b>Add to Dictionary</b>. If you do not want to add the unknown word to the dictionary, but you want to leave it unchanged, click <b>Ignore</b> or <b>Ignore All</b>.</p> <p>However, if the word is misspelled, you can try to find the correct replacement in the list below. If you cannot find a replacement there, you may type it in the text box below, and click <b>Replace</b> or <b>Replace All</b>.</p> </qt> <b>misspelled</b> <qt> <p>Select the language of the document you are proofing here.</p> </qt> &Language: m_language Text excerpt showing the unknown word in its context. <qt> <p>Here you can see a text excerpt showing the unknown word in its context. If this information is not sufficient to choose the best replacement for the unknown word, you can click on the document you are proofing, read a larger part of the text and then return here to continue proofing.</p> </qt> QFrame::Box ... the <b>misspelled</b> word shown in context ... Qt::AlignCenter <qt> <p>The unknown word was detected and considered unknown because it is not included in the dictionary.<br> Click here if you consider the unknown word not to be misspelled, and you want to avoid wrongly detecting it again in the future. If you want to let it remain as is, but not add it to the dictionary, then click <b>Ignore</b> or <b>Ignore All</b> instead.</p> </qt> << Add to Dictionary Qt::Horizontal QSizePolicy::Expanding 74 20 Suggestion List <qt> <p>If the unknown word is misspelled, you should check if the correction for it is available and if it is, click on it. If none of the words in this list is a good replacement you may type the correct word in the edit box above.</p> <p>To correct this word click <b>Replace</b> if you want to correct only this occurrence or <b>Replace All</b> if you want to correct all occurrences.</p> </qt> QListView::Adjust <qt> <p>If the unknown word is misspelled, you should type the correction for your misspelled word here or select it from the list below.</p> <p>You can then click <b>Replace</b> if you want to correct only this occurrence of the word or <b>Replace All</b> if you want to correct all occurrences.</p> </qt> Replace &with: m_replacement <qt> <p>If the unknown word is misspelled, you should type the correction for your misspelled word here or select it from the list below.</p> <p>You can then click <b>Replace</b> if you want to correct only this occurrence of the word or <b>Replace All</b> if you want to correct all occurrences.</p> </qt> - + Language Selection <qt> <p>Select the language of the document you are proofing here.</p> </qt> 6 0 0 0 0 S&uggest <qt> <p>Click here to replace this occurrence of the unknown text with the text in the edit box above (to the left).</p> </qt> &Replace <qt> <p>Click here to replace all occurrences of the unknown text with the text in the edit box above (to the left).</p> </qt> R&eplace All <qt> <p>Click here to let this occurrence of the unknown word remain as is.</p> <p>This action is useful when the word is a name, an acronym, a foreign word or any other unknown word that you want to use but not add to the dictionary.</p> </qt> &Ignore <qt> <p>Click here to let all occurrences of the unknown word remain as they are.</p> <p>This action is useful when the word is a name, an acronym, a foreign word or any other unknown word that you want to use but not add to the dictionary.</p> </qt> I&gnore All <qt> <p>Click here to let all occurrences of the unknown word remain as they are.</p> <p>This action is useful when the word is a name, an acronym, a foreign word or any other unknown word that you want to use but not add to the dictionary.</p> </qt> Autocorrect Qt::Vertical QSizePolicy::Expanding 20 20 + + + Sonnet::DictionaryComboBox + QComboBox +
sonnet/dictionarycombobox.h
+
+
m_addBtn m_replacement m_suggestBtn m_replaceBtn m_replaceAllBtn m_skipBtn m_skipAllBtn m_suggestions m_language