1 /***************************************************************************
2 * copyright : (C) 2007-2017 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 <QDebug>
14 #include <QTextCursor>
15 #include <QTextBlock>
16 #include <QMessageBox>
17 #include <QTimer>
18 #include <QCloseEvent>
19 #include <QTextCodec>
20 #include <QTextStream>
21 #include <QTextCharFormat>
22 #include <QFileInfo>
23 #include <QApplication>
24 #include "blockdata.h"
25
SpellerDialog(QWidget * parent,LatexEditor * ed,QString ignoredWords)26 SpellerDialog::SpellerDialog(QWidget *parent,LatexEditor *ed,QString ignoredWords)
27 :QDialog( parent)
28 {
29 editor=ed;
30
31 ui.setupUi(this);
32 setModal(true);
33
34 pChecker = editor->pChecker;
35 if (pChecker) spell_encoding=QString(pChecker->get_dic_encoding());
36
37 connect(ui.pushButtonIgnore, SIGNAL(clicked()), this, SLOT(slotIgnore()));
38 connect(ui.pushButtonAlwaysIgnore, SIGNAL(clicked()), this, SLOT(slotAlwaysIgnore()));
39 connect(ui.pushButtonReplace, SIGNAL(clicked()), this, SLOT(slotReplace()));
40 connect(ui.listWidget, SIGNAL(itemSelectionChanged()),this, SLOT(updateItem()));
41
42 if (!ignoredWords.isEmpty()) alwaysignoredwordList=ignoredWords.split(",");
43 else alwaysignoredwordList.clear();
44 ignoredwordList=alwaysignoredwordList;
45 QFile wordsfile(":/spell/spellignore.txt");
46 QString line;
47 if (wordsfile.open(QFile::ReadOnly))
48 {
49 while (!wordsfile.atEnd())
50 {
51 line = wordsfile.readLine();
52 if (!line.isEmpty()) hardignoredwordList.append(line.trimmed());
53 }
54 }
55 ui.listWidget->setEnabled(false);
56 ui.lineEditNew->setEnabled(false);
57 ui.pushButtonIgnore->setEnabled(false);
58 ui.pushButtonAlwaysIgnore->setEnabled(false);
59 ui.pushButtonReplace->setEnabled(false);
60 ui.lineEditOriginal->setEnabled(false);
61 ui.lineEditOriginal->clear();
62 ui.listWidget->clear();
63 ui.lineEditNew->clear();
64 show();
65 c = editor->textCursor();
66 spellingInit();
67 //QFileInfo fi(SpellDic);
68 //if (fi.exists() && fi.isReadable()) spellingInit();
69 //else ui.labelMessage->setText("<b>"+tr("Error : Can't open the dictionary")+"</b>");
70 }
71
~SpellerDialog()72 SpellerDialog::~SpellerDialog(){
73 //delete pChecker;
74 }
75
closeEvent(QCloseEvent * ce)76 void SpellerDialog::closeEvent( QCloseEvent* ce )
77 {
78 QTextCursor cursor=editor->textCursor();
79 cursor.setPosition(startpos,QTextCursor::MoveAnchor);
80 editor->setTextCursor(cursor);
81 ce->accept();
82 }
83
accept()84 void SpellerDialog::accept()
85 {
86 QTextCursor cursor=editor->textCursor();
87 cursor.setPosition(startpos,QTextCursor::MoveAnchor);
88 editor->setTextCursor(cursor);
89 QDialog::accept();
90 }
91
updateItem()92 void SpellerDialog::updateItem()
93 {
94 int current=-1;
95 QList<QListWidgetItem *> items;
96 items = ui.listWidget->selectedItems();
97 if (items.count() > 0)
98 {
99 ui.listWidget->setCurrentItem(items[0]);
100 current=ui.listWidget->row(items[0]);
101 }
102 if (current>=0)
103 {
104 ui.lineEditNew->setText(ui.listWidget->currentItem()->text());
105 }
106 }
107
108
spellingInit()109 void SpellerDialog::spellingInit()
110 {
111 deltacol=0;
112 go=true;
113 if (c.hasSelection())
114 {
115 ui.labelMessage->setText(tr("Check spelling selection..."));
116 startpos=c.selectionStart();
117 endpos=c.selectionEnd();
118 c.setPosition(endpos,QTextCursor::MoveAnchor);
119 c.setPosition(startpos,QTextCursor::MoveAnchor);
120 SpellingNextWord();
121 }
122 else
123 {
124 // c.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
125 ui.labelMessage->setText(tr("Check spelling from cursor..."));
126 startpos=c.position();
127 c.movePosition(QTextCursor::End,QTextCursor::MoveAnchor);
128 endpos=c.position();
129 c.setPosition(startpos,QTextCursor::MoveAnchor);
130 SpellingNextWord();
131 }
132 }
133
slotIgnore()134 void SpellerDialog::slotIgnore()
135 {
136 ignoredwordList.append(ui.lineEditOriginal->text());
137 ui.listWidget->setEnabled(false);
138 ui.lineEditNew->setEnabled(false);
139 ui.pushButtonIgnore->setEnabled(false);
140 ui.pushButtonAlwaysIgnore->setEnabled(false);
141 ui.pushButtonReplace->setEnabled(false);
142 ui.lineEditOriginal->setEnabled(false);
143 ui.lineEditOriginal->clear();
144 ui.listWidget->clear();
145 ui.lineEditNew->clear();
146 ui.labelMessage->setText("<b>"+tr("No more misspelled words")+"</b>");
147 SpellingNextWord();
148 }
149
slotAlwaysIgnore()150 void SpellerDialog::slotAlwaysIgnore()
151 {
152 alwaysignoredwordList.append(ui.lineEditOriginal->text());
153 ignoredwordList.append(ui.lineEditOriginal->text());
154 ui.listWidget->setEnabled(false);
155 ui.lineEditNew->setEnabled(false);
156 ui.pushButtonIgnore->setEnabled(false);
157 ui.pushButtonAlwaysIgnore->setEnabled(false);
158 ui.pushButtonReplace->setEnabled(false);
159 ui.lineEditOriginal->setEnabled(false);
160 ui.lineEditOriginal->clear();
161 ui.listWidget->clear();
162 ui.lineEditNew->clear();
163 ui.labelMessage->setText("<b>"+tr("No more misspelled words")+"</b>");
164 SpellingNextWord();
165 }
166
slotReplace()167 void SpellerDialog::slotReplace()
168 {
169 QString selectedword="";
170 QTextCursor cursor=editor->textCursor();
171 if (cursor.hasSelection()) selectedword=cursor.selectedText();
172 QString newword=ui.lineEditNew->text();
173 if (!newword.isEmpty())
174 {
175 deltacol=deltacol+newword.length()-selectedword.length();
176 editor->replace(newword,false,"");
177 }
178 ui.listWidget->setEnabled(false);
179 ui.lineEditNew->setEnabled(false);
180 ui.pushButtonIgnore->setEnabled(false);
181 ui.pushButtonAlwaysIgnore->setEnabled(false);
182 ui.pushButtonReplace->setEnabled(false);
183 ui.lineEditOriginal->setEnabled(false);
184 ui.lineEditOriginal->clear();
185 ui.listWidget->clear();
186 ui.lineEditNew->clear();
187 ui.labelMessage->setText("<b>"+tr("No more misspelled words")+"</b>");
188 SpellingNextWord();
189 }
190
SpellingNextWord()191 void SpellerDialog::SpellingNextWord()
192 {
193 /*QApplication::setOverrideCursor(Qt::WaitCursor);
194 BlockData* data;
195 QTextCodec *codec = QTextCodec::codecForName(spell_encoding.toLatin1());
196 QByteArray encodedString;
197 QTextBlock block;
198 QString text,word;
199 bool gonext=true;
200 QByteArray t;
201 int li,cols,cole,colstart,colend,check,ns;
202 char ** wlst;
203 QStringList suggWords;
204 while(gonext && c.position() < endpos+deltacol && go)
205 {
206 ui.listWidget->setEnabled(false);
207 ui.lineEditNew->setEnabled(false);
208 ui.pushButtonIgnore->setEnabled(false);
209 ui.pushButtonAlwaysIgnore->setEnabled(false);
210 ui.pushButtonReplace->setEnabled(false);
211 ui.lineEditOriginal->setEnabled(false);
212 ui.lineEditOriginal->clear();
213 ui.listWidget->clear();
214 ui.lineEditNew->clear();
215 ui.labelMessage->setText("<b>"+tr("No more misspelled words")+"</b>");
216
217 // c.movePosition(QTextCursor::NextCharacter,QTextCursor::MoveAnchor);
218 c.movePosition(QTextCursor::StartOfWord,QTextCursor::MoveAnchor);
219 data = (BlockData*)c.block().userData();
220 li=c.blockNumber();
221 block=c.block();
222 colstart=c.position()-block.position();
223 c.movePosition(QTextCursor::EndOfWord,QTextCursor::KeepAnchor);
224 block=c.block();
225 colend=c.position()-block.position()-1;
226 cols=colstart;
227 text=c.selectedText();
228 while ((cols<colend && cols<data->code.count() && data->code[cols]==1) || text.mid(cols-colstart,1)==" " || text.mid(cols-colstart,1)=="\t" )
229 {
230 cols++;
231 }
232 cole=colend;
233 while (cole>colstart && cole<data->code.count() && data->code[cole]==1)
234 {
235 cole--;
236 }
237 if (text.length()>1 && cole>cols)
238 {
239 word=text.mid(cols-colstart,cole-cols+1);
240 if (!ignoredwordList.contains(word) && !hardignoredwordList.contains(word))
241 {
242 encodedString = codec->fromUnicode(word);
243 if (pChecker) check = pChecker->spell(encodedString.data());
244 else check=true;
245 if (!check)
246 {
247 editor->selectword(li,cols,word);
248 ui.listWidget->setEnabled(true);
249 ui.lineEditNew->setEnabled(true);
250 ui.pushButtonIgnore->setEnabled(true);
251 ui.pushButtonAlwaysIgnore->setEnabled(true);
252 ui.pushButtonReplace->setEnabled(true);
253 ui.lineEditOriginal->setEnabled(true);
254 ui.lineEditOriginal->setText(word);
255 ui.listWidget->clear();
256 ui.lineEditNew->clear();
257 ui.labelMessage->setText("");
258 gonext=false;
259 ns = pChecker->suggest(&wlst,encodedString.data());
260 if (ns > 0)
261 {
262 suggWords.clear();
263 for (int i=0; i < ns; i++)
264 {
265 suggWords.append(codec->toUnicode(wlst[i]));
266 //free(wlst[i]);
267 }
268 //free(wlst);
269 pChecker->free_list(&wlst, ns);
270 if (!suggWords.isEmpty())
271 {
272 if (suggWords.contains(word)) gonext=true;
273 else
274 {
275 ui.listWidget->addItems(suggWords);
276 ui.lineEditNew->setText(suggWords.at(0));
277 }
278 }
279 }
280 }
281 }
282 }
283 go=c.movePosition(QTextCursor::NextWord,QTextCursor::MoveAnchor);
284 }
285 QApplication::restoreOverrideCursor();*/
286 QApplication::setOverrideCursor(Qt::WaitCursor);
287 QTextCodec *codec = QTextCodec::codecForName(spell_encoding.toLatin1());
288 QTextBlock block;
289 QString text;
290 int i;
291 int check;
292 int offset ;
293 int ns;
294 char ** wlst;
295 QChar ch;
296 QString buffer;
297 QByteArray encodedString;
298 QStringList suggWords;
299 BlockData* blockData;
300 block=c.block();
301 bool gonext=true;
302 while (gonext && c.position() < endpos+deltacol && block.isValid() )
303 {
304 ui.listWidget->setEnabled(false);
305 ui.lineEditNew->setEnabled(false);
306 ui.pushButtonIgnore->setEnabled(false);
307 ui.pushButtonAlwaysIgnore->setEnabled(false);
308 ui.pushButtonReplace->setEnabled(false);
309 ui.lineEditOriginal->setEnabled(false);
310 ui.lineEditOriginal->clear();
311 ui.listWidget->clear();
312 ui.lineEditNew->clear();
313 ui.labelMessage->setText("<b>"+tr("No more misspelled words")+"</b>");
314 i=0;
315 text=block.text();
316 blockData= (BlockData*)block.userData();
317 while (gonext && i < text.length())
318 {
319 buffer = QString::null;
320 ch = text.at( i );
321 offset=0;
322 while ((blockData->code[i]!=1) && (!isSpace(ch)))
323 {
324 buffer += ch;
325 i++;
326 if (i < text.length()) ch = text.at( i );
327 else break;
328 }
329 while (buffer.startsWith('\''))
330 {
331 buffer=buffer.right(buffer.size()-1);
332 }
333 while (buffer.endsWith('\''))
334 {
335 buffer.chop(1);
336 offset++;
337 }
338 if ( (i - buffer.length()-offset+block.position() <= endpos+deltacol) && (i-offset+block.position()>=c.position()) && (buffer.length() > 1) && (!ignoredwordList.contains(buffer)) && (!hardignoredwordList.contains(buffer)))
339 {
340 encodedString = codec->fromUnicode(buffer);
341 if (pChecker) check = pChecker->spell(encodedString.data());
342 else check=true;
343 if (!check)
344 {
345 editor->selectword(block.blockNumber(),i - buffer.length()-offset,buffer);
346 ui.listWidget->setEnabled(true);
347 ui.lineEditNew->setEnabled(true);
348 ui.pushButtonIgnore->setEnabled(true);
349 ui.pushButtonAlwaysIgnore->setEnabled(true);
350 ui.pushButtonReplace->setEnabled(true);
351 ui.lineEditOriginal->setEnabled(true);
352 ui.lineEditOriginal->setText(buffer);
353 ui.listWidget->clear();
354 ui.lineEditNew->clear();
355 ui.labelMessage->setText("");
356 gonext=false;
357 ns = pChecker->suggest(&wlst,encodedString.data());
358 if (ns > 0)
359 {
360 suggWords.clear();
361 for (int i=0; i < ns; i++)
362 {
363 suggWords.append(codec->toUnicode(wlst[i]));
364 //free(wlst[i]);
365 }
366 //free(wlst);
367 pChecker->free_list(&wlst, ns);
368 if (!suggWords.isEmpty())
369 {
370 if (suggWords.contains(buffer)) gonext=true;
371 else
372 {
373 ui.listWidget->addItems(suggWords);
374 ui.lineEditNew->setText(suggWords.at(0));
375 }
376 }
377 }
378 }
379 }
380 i++;
381 }
382 block = block.next();
383 }
384 QApplication::restoreOverrideCursor();
385
386 }
387
isSpace(QChar c) const388 bool SpellerDialog::isSpace(QChar c) const
389 {
390 return c == QLatin1Char(' ')
391 || c == QChar::Nbsp
392 || c == QChar::LineSeparator
393 || c == QLatin1Char('\t')
394 ;
395 }
396