Subversion Repositories Scribus

Rev

Rev 12479 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
11087 fschmid 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
#include "aspellpluginimpl.h"
8
#include "pageitem_textframe.h"
11088 fschmid 9
#include "util.h"
11087 fschmid 10
#include <QMessageBox>
12164 fschmid 11
 
11087 fschmid 12
const char* AspellPluginImpl::kDEF_CONTEXT = "AspellPlugin";
13
const QString AspellPluginImpl::kDEF_ASPELL_ENTRY =
14
        QString( "en" ) + Speller::Aspell::Suggest::kDICT_DELIM +
15
        QString( "en" ) + Speller::Aspell::Suggest::kDICT_DELIM +
16
        QString( "*" ) + Speller::Aspell::Suggest::kDICT_DELIM +
17
        QString( "60" );  // I.e., en/en/*/60 corresponding to default English dictionary
18
 
19
// Initialize members here, if any
20
AspellPluginImpl::AspellPluginImpl(ScribusDoc* doc, QWidget* parent) :
21
        QDialog( parent ), fdoc( doc ), fpos(0), fidx(0)
22
{
23
        // Constructor.
24
        setupUi( this );
25
        setModal( true );
26
 
27
        rememberedWords.clear();
28
        // Get stored language, jargon, encoding settings
29
        fprefs = PrefsManager::instance()->prefsFile->getPluginContext( kDEF_CONTEXT );
30
        getPreferences();
31
        QString text = tr( "Loaded " ) + (fentry == kDEF_ASPELL_ENTRY ? tr( "default " ) : "") + fentry + tr( " aspell dictionary." );
32
        doc->scMW()->setStatusBarInfoText( text );
33
        try
34
        {
35
                // Deactivate GUI elements in spell-checking tab until an
36
                // aspell dictionary is chosen.
12536 cbradney 37
                activateSpellGUI(false);
11087 fschmid 38
 
39
                // Create speller, and get list of available aspell
40
                // dictionaries.
41
                fsuggest = new Speller::Aspell::Suggest( flang.toUtf8().data(), fjargon.toUtf8().data(), fencoding.toUtf8().data() );
42
                Q_CHECK_PTR( fsuggest );
43
 
44
                // Get list of available aspell dictionaries
45
                std::vector<std::string> entries;
46
                fsuggest->listDicts( entries );
47
                for( std::vector<std::string>::const_iterator i = entries.begin(); i != entries.end(); ++i )
48
                {
49
                        // FIXME: Handle encodings other than UTF-8.
11088 fschmid 50
                        flistDicts->addItem(i->c_str());
11087 fschmid 51
                }
11088 fschmid 52
                setCurrentComboItem(flistDicts, fentry);
11087 fschmid 53
        }
54
        catch( const std::invalid_argument& err )
55
        {
56
                QString warn = tr( "aspellplugin (AspellPluginImpl::"
57
                                   "AspellPluginImpl): Error in aspell "
58
                                   "speller configuration." );
59
                qWarning( "%s", warn.toUtf8().data() );
60
        }
61
        catch( const std::runtime_error& err )
62
        {
63
                QString warn = tr( "aspellplugin (AspellPluginImpl::"
64
                                   "AspellPluginImpl): Error in creating "
65
                                   "aspell speller." );
66
                qWarning( "%s", warn.toUtf8().data() );
67
        }
12536 cbradney 68
        activateSpellGUI(true);
11087 fschmid 69
        parseSelection();
70
}
71
//__________________________________________________________________________
72
AspellPluginImpl::~AspellPluginImpl()
73
{
74
        // Destructor
75
        try
76
        {
77
                fsuggest->saveLists();
78
        }
79
        catch( const std::runtime_error& err )
80
        {
81
                qWarning( "aspellplugin (AspellPluginImpl::~AspellPlugin"
82
                          "Impl): Error in saving aspell word lists." );
83
        }
84
 
85
        delete fsuggest;
86
}
87
//__________________________________________________________________________
12536 cbradney 88
void AspellPluginImpl::activateSpellGUI(bool active)
11087 fschmid 89
{
90
        // Activates spell-checking GUI elements in spell-checking
91
        // tab, i.e., everything except combo box at top
12536 cbradney 92
        fcurrWord->setEnabled( active );
93
        flistReplacements->setEnabled( active );
94
        fchangeBtn->setEnabled( active );
95
        fchangeAllBtn->setEnabled( active );
96
        fskipAllBtn->setEnabled( active );
97
        fskipBtn->setEnabled( active );
98
        faddWordBtn->setEnabled( active );
99
        ftextLabel1->setEnabled( active );
100
        ftextLabel2->setEnabled( active );
101
        ftextLabel4->setEnabled( active );
102
        fmisSpelling->setEnabled( active );
103
        flistDicts->setEnabled( active );
11087 fschmid 104
}
105
//__________________________________________________________________________
106
void AspellPluginImpl::nextWord()
107
{
108
        QString wordBoundaries = QString(" .,:;\"'!?\n");
109
        uint len = fFrame->itemText.length();
110
        while (fpos < len && wordBoundaries.indexOf(fFrame->itemText.text(fpos)) >= 0)
111
        {
112
                ++fpos;
113
        }
114
        int pa = fpos;
115
        int pe = 0;
116
        while (fpos < len && wordBoundaries.indexOf(fFrame->itemText.text(fpos)) < 0)
117
        {
118
                ++fpos;
119
        }
120
        pe = fpos;
12164 fschmid 121
        if (pa == pe)
122
        {
123
                spellCheckDone();       // No more new Text, bail out from Spellchecking
124
                return;
125
        }
11087 fschmid 126
        fcontent = fFrame->itemText.text(pa, pe - pa);
127
        fpos = pa;
128
}
129
//__________________________________________________________________________
130
void AspellPluginImpl::checkText()
131
{
132
        // Called from parseXXX(), after filling in the currently
133
        // relevant text into 'fcontent'. Handles spell-checking of
134
        // the text.
135
        while (fpos < static_cast<uint>(fFrame->itemText.length()))
136
        {
137
                std::vector<std::string> replacement;
138
                bool status = fsuggest->checkWord(fcontent.toUtf8().data(), replacement);
139
                if (!status)
140
                {
141
                        fmisSpelling->setText( fcontent );
142
                        fcurrWord->setText( "" );
143
                        flistReplacements->clear();
144
                        unsigned int idx = 0;
145
                        for( std::vector<std::string>::const_iterator i = replacement.begin(); i != replacement.end(); ++i )
146
                        {
147
                        // FIXME: Handle encodings other than UTF-8.
148
                                QString dict = QString::fromUtf8(i->c_str());
149
                                flistReplacements->insertItem( idx, dict );
150
                                idx++;
151
                        }
152
                        if( flistReplacements->count() > 0 )
153
                        {
154
                                // FIXME: Is this the correct substitute for
155
                                // setSelected()?
156
                                flistReplacements->setCurrentRow( 0 );
157
                                fcurrWord->setText( flistReplacements->currentItem()->text() );
158
                        }
159
                        if (rememberedWords.contains(fcontent))
160
                        {
161
                                QString repl = rememberedWords.value(fcontent);
162
                                int cs, cx;
163
                                if (fcontent.length() == repl.length())
164
                                {
165
                                        for (cs = 0; cs < fcontent.length(); ++cs)
166
                                                fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
167
                                }
168
                                else
169
                                {
170
                                        if (fcontent.length() < repl.length())
171
                                        {
172
                                                for (cs = 0; cs < fcontent.length(); ++cs)
173
                                                        fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
174
                                                for (cx = cs; cx < repl.length(); ++cx)
175
                                                        fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
176
                                        }
177
                                        else
178
                                        {
179
                                                for (cs = 0; cs < repl.length(); ++cs)
180
                                                        fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
181
                                                fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
182
                                        }
183
                                }
184
                        }
185
                        else
186
                                break;
187
                }
188
                fpos += fcontent.length();
189
                nextWord();
190
        }
191
}
192
//__________________________________________________________________________
193
void AspellPluginImpl::spellCheckDone()
194
{
195
        // Called once all words in the current text, i.e., in 'fcontent'
196
        // have been spell-checked. Pops up an information dialog.
12479 cbradney 197
        QString completeMsg(tr("Spelling check complete"));
198
        QMessageBox::information(fdoc->scMW(), tr("Spell Checker"), completeMsg);
11087 fschmid 199
        if( fFrame && fFrame->asTextFrame() )
200
                fFrame->asTextFrame()->invalidateLayout();
201
        if( fnchanges.fntot > 0 )
202
        {
203
                fdoc->changed();
204
        }
205
        // Redraw document
206
        fdoc->view()->DrawNew();
11299 fschmid 207
        QApplication::changeOverrideCursor(Qt::ArrowCursor);
208
//      QApplication::restoreOverrideCursor();
12479 cbradney 209
        fdoc->scMW()->setStatusBarInfoText(completeMsg);
11087 fschmid 210
        fdoc->scMW()->mainWindowProgressBar->reset();
211
        close();
212
}
213
//__________________________________________________________________________
214
void AspellPluginImpl::on_fcloseBtn_clicked()
215
{
216
        // Called when the "Close" button is clicked. Makes any pending
217
        // replacements and closes the spell-checking window.
218
        spellCheckDone();  // Also closes spell-checking window.
219
}
220
//__________________________________________________________________________
221
void AspellPluginImpl::on_fchangeBtn_clicked()
222
{
223
        // Called when the "Change" button is clicked. Replaces the word
224
        // being spell-checked with the current word in text edit box.
225
        // FIXME: Handle encodings other than UTF-8.
11088 fschmid 226
        QString repl = fcurrWord->text();
11087 fschmid 227
        int cs, cx;
228
        if (fcontent.length() == repl.length())
229
        {
230
                for (cs = 0; cs < fcontent.length(); ++cs)
231
                        fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
232
        }
233
        else
234
        {
235
                if (fcontent.length() < repl.length())
236
                {
237
                        for (cs = 0; cs < fcontent.length(); ++cs)
238
                                fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
239
                        for (cx = cs; cx < repl.length(); ++cx)
240
                                fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
241
                }
242
                else
243
                {
244
                        for (cs = 0; cs < repl.length(); ++cs)
245
                                fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
246
                        fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
247
                }
248
        }
249
        fpos += fcontent.length();
250
        nextWord();
251
        checkText();
252
}
253
//__________________________________________________________________________
254
void AspellPluginImpl::on_fchangeAllBtn_clicked()
255
{
256
        // Called when the "Change All" button is clicked. Replaces all
257
        // instances of the word being spell-checked with the current word in
258
        // text edit box.
11088 fschmid 259
        QString repl = fcurrWord->text();
11087 fschmid 260
        int cs, cx;
261
        if (fcontent.length() == repl.length())
262
        {
263
                for (cs = 0; cs < fcontent.length(); ++cs)
264
                        fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
265
        }
266
        else
267
        {
268
                if (fcontent.length() < repl.length())
269
                {
270
                        for (cs = 0; cs < fcontent.length(); ++cs)
271
                                fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
272
                        for (cx = cs; cx < repl.length(); ++cx)
273
                                fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
274
                }
275
                else
276
                {
277
                        for (cs = 0; cs < repl.length(); ++cs)
278
                                fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
279
                        fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
280
                }
281
        }
282
        if (!rememberedWords.contains(fcontent))
283
                rememberedWords.insert(fcontent, repl);
284
        fpos += fcontent.length();
285
        nextWord();  // Go to next word
286
        checkText();
287
}
288
//__________________________________________________________________________
289
void AspellPluginImpl::on_fskipBtn_clicked()
290
{
291
        // Called when the "Skip" button is clicked. Skips the word currently
292
        // being spell-checked.
293
        fpos += fcontent.length();
294
        nextWord();  // Go to next word
295
        checkText();
296
}
297
//__________________________________________________________________________
298
void AspellPluginImpl::on_fskipAllBtn_clicked()
299
{
300
        // Called when the "Skip All" button is clicked. Puts the word
301
        // currently being spell-checked into the list of words to be ignored
302
        // for this session.
303
        try
304
        {
305
#if 0
306
                std::cerr << "on_fskipAllBtn_clicked: Ignoring \"" <<
307
                  fwordlist[fidx] << "\"\n";
308
#endif
309
                fsuggest->ignoreWord( fcontent.toUtf8().data() );
310
        }
311
        catch( const std::runtime_error& err )
312
        {
313
 
314
                QString warn =
315
                  tr( "AspellPluginImpl::on_fskipAllBtn_clicked(): Unable "
316
                      "to skip all instances of \"" ) + fcontent +
317
                  tr(" by adding it to the session list.");
318
                qWarning( "%s", warn.toUtf8().data() );
319
        }
320
        fpos += fcontent.length();
321
        nextWord();  // Go to next word
322
        checkText();
323
}
324
//__________________________________________________________________________
325
void AspellPluginImpl::on_faddWordBtn_clicked()
326
{
327
        // Called when the "Add word" button is clicked. Adds word to personal
328
        // word list.
329
        try
330
        {
331
                // FIXME: Handle encodings other than UTF-8.
332
                // FIXME: Is this the right replacement for fcurrWord->text()?
11088 fschmid 333
                fsuggest->addPersonalList( fcurrWord->text().toUtf8().data() );
11087 fschmid 334
        }
335
        catch( const std::runtime_error& err )
336
        {
337
                QString warn =
338
                        tr( "AspellPluginImpl::on_faddWordBtn_clicked(): "
339
                            "Unable to add word to personal list." );
340
                qWarning( "%s", warn.toUtf8().data() );
341
        }
342
}
343
//__________________________________________________________________________
344
void AspellPluginImpl::on_flistReplacements_itemActivated()
345
{
346
        // Called when an item in the list of replacements is
347
        // selected. Replaces current word in text edit box with the text
348
        // of the selected item. 
349
        fcurrWord->setText( flistReplacements->currentItem()->text() );
350
}
351
//__________________________________________________________________________
11088 fschmid 352
void AspellPluginImpl::on_flistDicts_activated()
11087 fschmid 353
{
354
        // Called when an item in the list of available aspell dictionaries is
355
        // selected, i.e., by double-clicking, or pressing enter. Resets
356
        // aspell configuration to use the selected dictionary.
11088 fschmid 357
        QString entry = flistDicts->currentText();
11087 fschmid 358
        QStringList fields = entry.split( Speller::Aspell::Suggest::kDICT_DELIM );
359
        // Ensure that we have at least the right no.of fields.
360
        if( fields.size() == 4 )
361
        {
362
                QString value =
363
                        fields[0] + Speller::Aspell::Suggest::kDICT_DELIM +
364
                        fields[1] + Speller::Aspell::Suggest::kDICT_DELIM +
365
                        fields[2] + Speller::Aspell::Suggest::kDICT_DELIM +
366
                        fields[3];
11088 fschmid 367
                fsuggest->resetConfig( fields[1].toAscii().data(), fields[2].toAscii().data() );
11087 fschmid 368
                // FIXME: Handle encodings other than UTF-8.
369
                setPreferences( fields[1], fields[2], Speller::Aspell::Suggest::kDEF_ENCODING, value );
370
        }
371
}
372
//__________________________________________________________________________
373
void AspellPluginImpl::getPreferences()
374
{
375
        // Retrieves user preferences from saved settings. Defaults are
376
        // supplied 
377
        flang = fprefs->get( "lang", Speller::Aspell::Suggest::kDEF_LANG );
11088 fschmid 378
        fjargon = fprefs->get( "jargon", Speller::Aspell::Suggest::kDEF_JARGON );
11087 fschmid 379
        // FIXME: Handle encodings other than UTF-8.
11088 fschmid 380
        fencoding = fprefs->get( "encoding", Speller::Aspell::Suggest::kDEF_ENCODING );
11087 fschmid 381
        fentry = fprefs->get( "entry", kDEF_ASPELL_ENTRY );
382
}
383
//__________________________________________________________________________
384
void AspellPluginImpl::setPreferences(const QString& lang,
385
                                      const QString& jargon,
386
                                      const QString& encoding,
387
                                      const QString& entry)
388
{
389
        // Saves user preferences using Scribus preferences manager.
390
        fprefs->set( "lang", lang );
11088 fschmid 391
        QString val = jargon == Speller::Aspell::Suggest::kEMPTY ? "" : jargon;
11087 fschmid 392
        fprefs->set( "jargon", val );
393
        fprefs->set( "encoding", encoding );
394
        fprefs->set( "entry", entry );
395
}
396
//__________________________________________________________________________
397
void AspellPluginImpl::languageChange()
398
{
399
        qWarning( "AspellPluginImpl::languageChange(): Not implemented yet" );
400
}
401
//__________________________________________________________________________
402
void AspellPluginImpl::parseItem()
403
{
404
        // Parse text in a frame, and spell-check it.
405
        // Process only text frames
406
        if( fFrame && fFrame->asTextFrame() )
407
        {
408
                nextWord();
409
                checkText();
410
        }
411
}
412
//__________________________________________________________________________
413
void AspellPluginImpl::parseSelection()
414
{
415
        fcontent.truncate( 0 );  // Start with empty string
416
        uint ndocs = fdoc->m_Selection->count();
417
        for( uint i = 0; i < ndocs; ++i )
418
        {
419
                fFrame = fdoc->m_Selection->itemAt( i );
420
                parseItem();
421
        }
422
}
423
//__________________________________________________________________________
424
//@@@@@@@@@@@@@@@@@@@@@@@@@ END OF FILE @@@@@@@@@@@@@@@@@@@@@@@@@