"Fossies" - the Fresh Open Source Software Archive 
Member "texstudio-3.1.1/src/spellerdialog.cpp" (21 Feb 2021, 10671 Bytes) of package /linux/misc/texstudio-3.1.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "spellerdialog.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
3.1.0_vs_3.1.1.
1 /***************************************************************************
2 * copyright : (C) 2007 by Pascal Brachet *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 ***************************************************************************/
10
11 #include "spellerdialog.h"
12
13 #include "smallUsefulFunctions.h"
14 #include "utilsUI.h"
15
16 #include "qdocumentline.h"
17
18 #include <QItemEditorCreatorBase>
19 #include <QStyledItemDelegate>
20
21 const QRegExpValidator wordValidator(QRegExp("[^<].*"), nullptr);
22
23 SpellerDialog::SpellerDialog(QWidget *parent, SpellerUtility *utility)
24 : QDialog(parent), m_statusBar(nullptr), m_speller(utility), editor(nullptr), editorView(nullptr)
25 {
26 ui.setupUi(this);
27 setModal(true);
28 UtilsUi::resizeInFontHeight(this, 31, 26);
29
30 m_statusBar = new QStatusBar();
31 delete ui.dummyStatusBar;
32 layout()->addWidget(m_statusBar);
33 // workaround for wrong status bar text color (black) in modern style
34 // TODO: change the style and remove this extra label
35 QLabel *messageArea = new QLabel(m_statusBar);
36 connect(m_statusBar, SIGNAL(messageChanged(QString)), messageArea, SLOT(setText(QString)));
37 m_statusBar->addPermanentWidget(messageArea, 1);
38
39 connect(ui.pushButtonIgnoreList, SIGNAL(clicked()), this, SLOT(toggleIgnoreList()));
40 connect(ui.pushButtonAdd, SIGNAL(clicked()), this, SLOT(addIgnoredWord()));
41 connect(ui.pushButtonRemove, SIGNAL(clicked()), this, SLOT(removeIgnoredWord()));
42 connect(ui.pushButtonIgnore, SIGNAL(clicked()), this, SLOT(slotIgnore()));
43 connect(ui.pushButtonAlwaysIgnore, SIGNAL(clicked()), this, SLOT(slotAlwaysIgnore()));
44 connect(ui.pushButtonReplace, SIGNAL(clicked()), this, SLOT(slotReplace()));
45 connect(ui.listSuggestions, SIGNAL(itemSelectionChanged()), this, SLOT(updateItem()));
46
47 ui.listSuggestions->setEnabled(false);
48 ui.lineEditNew->setEnabled(false);
49 ui.pushButtonIgnore->setEnabled(false);
50 ui.pushButtonAlwaysIgnore->setEnabled(false);
51 ui.pushButtonReplace->setEnabled(false);
52 ui.lineEditOriginal->setEnabled(false);
53
54 ui.ignoreListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
55 IgnoreListViewDelegate *itemDelegate = new IgnoreListViewDelegate(ui.ignoreListView);
56 ui.ignoreListView->setItemDelegate(itemDelegate);
57 connect(itemDelegate, SIGNAL(closeEditor(QWidget *)), this, SLOT(finishEditIgnoreList()));
58
59 toggleIgnoreList(true); // start with hidden ignore list
60 }
61
62 SpellerDialog::~SpellerDialog()
63 {
64 ui.lineEditOriginal->clear();
65 ui.listSuggestions->clear();
66 ui.lineEditNew->clear();
67
68 }
69
70 void SpellerDialog::setEditorView(LatexEditorView *edView)
71 {
72 editor = edView ? edView->editor : nullptr;
73 editorView = edView;
74 if(edView)
75 mReplacementList=edView->getReplacementList();
76 }
77
78 void SpellerDialog::startSpelling()
79 {
80 if (!editor) return;
81 ignoreListChanged = false;
82 if (editor->cursor().hasSelection()) {
83
84 m_statusBar->showMessage(tr("Check spelling selection..."));
85 startLine = editor->cursor().selectionStart().lineNumber();
86 startIndex = editor->cursor().selectionStart().columnNumber();
87 endLine = editor->cursor().selectionEnd().lineNumber();
88 endIndex = editor->cursor().selectionEnd().columnNumber();
89 } else {
90 m_statusBar->showMessage(tr("Check spelling from cursor..."));
91 editor->getCursorPosition(startLine, startIndex);
92 endLine = editor->document()->lines() - 1;
93 endIndex = editor->text(endLine).length();
94 }
95 curLine = startLine;
96 // determine tokenIndex from cursor index
97 QDocumentLineHandle *dlh=editor->document()->line(curLine).handle();
98 tl=dlh->getCookieLocked(QDocumentLine::LEXER_COOKIE).value<TokenList >();
99 for(tokenListIndex=0;tokenListIndex<tl.length();++tokenListIndex){
100 Token tk=tl.at(tokenListIndex);
101 if(tk.start+tk.length>startIndex)
102 break;
103 }
104 --tokenListIndex; // index is increased as first step in SpellingNextWord()
105 show();
106 SpellingNextWord();
107 }
108
109 void SpellerDialog::closeEvent(QCloseEvent *ce)
110 {
111 if (editorView && ignoreListChanged) {
112 ignoreListChanged = false;
113 editorView->reCheckSyntax(0);
114 }
115 if (editor) editor->setCursorPosition(startLine, startIndex);
116 ce->accept();
117 }
118
119 void SpellerDialog::accept()
120 {
121 if (editorView && ignoreListChanged) {
122 ignoreListChanged = false;
123 editorView->reCheckSyntax(0);
124 }
125 if (editor) editor->setCursorPosition(startLine, startIndex);
126 QDialog::accept();
127 }
128
129 void SpellerDialog::updateItem()
130 {
131 int current = -1;
132 QList<QListWidgetItem *> items;
133 items = ui.listSuggestions->selectedItems();
134 if (items.count() > 0) {
135 ui.listSuggestions->setCurrentItem(items[0]);
136 current = ui.listSuggestions->row(items[0]);
137 }
138 if (current >= 0) {
139 ui.lineEditNew->setText(ui.listSuggestions->currentItem()->text());
140 }
141 }
142
143 void SpellerDialog::slotIgnore()
144 {
145 SpellingNextWord();
146 }
147
148 void SpellerDialog::slotAlwaysIgnore()
149 {
150 //todo: real time update of now allowed words
151 m_speller->addToIgnoreList(ui.lineEditOriginal->text());
152 ignoreListChanged = true;
153 SpellingNextWord();
154 }
155
156 void SpellerDialog::slotReplace()
157 {
158 if (!editor) return;
159 if (editor->cursor().hasSelection()) {
160 QString selectedword = editor->cursor().selectedText();
161 editor->insertText(ui.lineEditNew->text());
162 }
163 SpellingNextWord();
164 }
165
166 void SpellerDialog::SpellingNextWord()
167 {
168 if (!editor || !m_speller) return;
169 for (; curLine <= endLine; curLine++) {
170 QDocumentLineHandle *dlh=editor->document()->line(curLine).handle();
171 tl=dlh->getCookieLocked(QDocumentLine::LEXER_COOKIE).value<TokenList >();
172 while(tokenListIndex<tl.length()-1){
173 ++tokenListIndex;
174 Token tk=tl.at(tokenListIndex);
175 if (tk.type!=Token::word)
176 continue;
177 if(tk.subtype != Token::text && tk.subtype != Token::title && tk.subtype != Token::shorttitle && tk.subtype != Token::todo && tk.subtype != Token::none)
178 continue;
179 QString word=tk.getText();
180 word = latexToPlainWordwithReplacementList(word, mReplacementList);
181 if (tk.ignoreSpelling || m_speller->check(word)) continue;
182 QStringList suggWords = m_speller->suggest(word);
183
184 QDocumentCursor wordSelection(editor->document(), curLine, tk.start);
185 wordSelection.movePosition(tk.length, QDocumentCursor::NextCharacter, QDocumentCursor::KeepAnchor);
186 editor->setCursor(wordSelection);
187
188 ui.listSuggestions->setEnabled(true);
189 ui.lineEditNew->setEnabled(true);
190 ui.pushButtonIgnore->setEnabled(true);
191 ui.pushButtonAlwaysIgnore->setEnabled(true);
192 ui.pushButtonReplace->setEnabled(true);
193 ui.lineEditOriginal->setEnabled(true);
194 ui.lineEditOriginal->setText(word);
195 ui.listSuggestions->clear();
196 ui.lineEditNew->clear();
197 m_statusBar->clearMessage();
198 if (!suggWords.isEmpty()) {
199 ui.listSuggestions->addItems(suggWords);
200 ui.lineEditNew->setText(suggWords.at(0));
201 }
202 return;
203 }
204 tokenListIndex = -1;
205 }
206
207 //no word found
208 ui.listSuggestions->setEnabled(false);
209 ui.lineEditNew->setEnabled(false);
210 ui.pushButtonIgnore->setEnabled(false);
211 ui.pushButtonAlwaysIgnore->setEnabled(false);
212 ui.pushButtonReplace->setEnabled(false);
213 ui.lineEditOriginal->setEnabled(false);
214 ui.lineEditOriginal->clear();
215 ui.listSuggestions->clear();
216 ui.lineEditNew->clear();
217 m_statusBar->showMessage("<b>" + tr("No more misspelled words") + "</b>");
218 }
219
220 void SpellerDialog::toggleIgnoreList(bool forceHide)
221 {
222 QList<QWidget *> hideableWidgets = QList<QWidget *>() << ui.ignoreListView << ui.labelIgnoredWords << ui.pushButtonAdd << ui.pushButtonRemove << ui.labelAsHideableSpacer;
223
224 if (ui.ignoreListView->isVisible() || forceHide) {
225 foreach (QWidget * w, hideableWidgets) w->hide();
226 ui.pushButtonIgnoreList->setText(tr("Show User Words"));
227 ui.pushButtonIgnoreList->setIcon(getRealIcon("down-arrow-circle-silver"));
228 resize(width(), height() - (ui.ignoreListView->height() + ui.gridLayout->verticalSpacing()));
229 } else {
230 resize(width(), height() + (ui.listSuggestions->height() + ui.gridLayout->verticalSpacing()));
231 ui.pushButtonIgnoreList->setText(tr("Hide User Words"));
232 ui.pushButtonIgnoreList->setIcon(getRealIcon("up-arrow-circle-silver"));
233 if (m_speller && !ui.ignoreListView->model())
234 ui.ignoreListView->setModel(m_speller->ignoreListModel());
235 foreach (QWidget * w, hideableWidgets) w->show();
236 }
237 }
238
239 void SpellerDialog::addIgnoredWord()
240 {
241 if (!m_speller) return;
242 finishEditIgnoreList(); // needed for possible cleanup if an editor is open, harmless otherwise
243
244 QStringListModel *m = m_speller->ignoreListModel();
245 m->insertRow(0);
246 m->setData(m->index(0), QVariant(tr("<new>", "Placeholder for new added word in ignore list")));
247
248 ui.ignoreListView->selectionModel()->setCurrentIndex(m->index(0), QItemSelectionModel::Select);
249 ui.ignoreListView->edit(m->index(0));
250 }
251
252 void SpellerDialog::removeIgnoredWord()
253 {
254 if (!m_speller) return;
255 if (!ui.ignoreListView->model()) return;
256 QString selectedWord = ui.ignoreListView->model()->data(ui.ignoreListView->currentIndex(), Qt::DisplayRole).toString();
257 m_speller->removeFromIgnoreList(selectedWord);
258 }
259
260 void SpellerDialog::finishEditIgnoreList()
261 {
262 QString word = ui.ignoreListView->model()->data(ui.ignoreListView->currentIndex(), Qt::DisplayRole).toString();
263 int dummy;
264 if (wordValidator.validate(word, dummy) == QValidator::Acceptable) {
265 m_speller->addToIgnoreList(word);
266 } else {
267 ui.ignoreListView->model()->removeRow(ui.ignoreListView->currentIndex().row());
268 }
269 }
270
271 ValidatedLineEdit::ValidatedLineEdit(QWidget *parent) : QLineEdit(parent)
272 {
273 setValidator(&wordValidator);
274 }
275
276 IgnoreListViewDelegate::IgnoreListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
277 {
278 QItemEditorCreatorBase *creator = new QStandardItemEditorCreator<ValidatedLineEdit>();
279 QItemEditorFactory *factory = new QItemEditorFactory();
280 factory->registerEditor(QVariant::String, creator);
281 setItemEditorFactory(factory);
282 }
283
284 void IgnoreListViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
285 {
286 QByteArray n = editor->metaObject()->userProperty().name();
287 if (!n.isEmpty()) {
288 QString word = editor->property(n).toString();
289 int pos;
290 if (wordValidator.validate(word, pos) == QValidator::Acceptable) {
291 model->setData(index, editor->property(n), Qt::EditRole);
292 }
293 }
294 }