00001
00002
00003
00004
00005
00006
00007 #include "aspellpluginimpl.h"
00008 #include "pageitem_textframe.h"
00009 #include "util.h"
00010 #include <QMessageBox>
00011 const char* AspellPluginImpl::kDEF_CONTEXT = "AspellPlugin";
00012 const QString AspellPluginImpl::kDEF_ASPELL_ENTRY =
00013 QString( "en" ) + Speller::Aspell::Suggest::kDICT_DELIM +
00014 QString( "en" ) + Speller::Aspell::Suggest::kDICT_DELIM +
00015 QString( "*" ) + Speller::Aspell::Suggest::kDICT_DELIM +
00016 QString( "60" );
00017
00018
00019 AspellPluginImpl::AspellPluginImpl(ScribusDoc* doc, QWidget* parent) :
00020 QDialog( parent ), fdoc( doc ), fpos(0), fidx(0)
00021 {
00022
00023 setupUi( this );
00024 setModal( true );
00025
00026 rememberedWords.clear();
00027
00028 fprefs = PrefsManager::instance()->prefsFile->getPluginContext( kDEF_CONTEXT );
00029 getPreferences();
00030 QString text = tr( "Loaded " ) + (fentry == kDEF_ASPELL_ENTRY ? tr( "default " ) : "") + fentry + tr( " aspell dictionary." );
00031 doc->scMW()->setStatusBarInfoText( text );
00032 try
00033 {
00034
00035
00036 deactivateSpellGUI();
00037
00038
00039
00040 fsuggest = new Speller::Aspell::Suggest( flang.toUtf8().data(), fjargon.toUtf8().data(), fencoding.toUtf8().data() );
00041 Q_CHECK_PTR( fsuggest );
00042
00043
00044 std::vector<std::string> entries;
00045 fsuggest->listDicts( entries );
00046 for( std::vector<std::string>::const_iterator i = entries.begin(); i != entries.end(); ++i )
00047 {
00048
00049 flistDicts->addItem(i->c_str());
00050 }
00051 setCurrentComboItem(flistDicts, fentry);
00052 }
00053 catch( const std::invalid_argument& err )
00054 {
00055 QString warn = tr( "aspellplugin (AspellPluginImpl::"
00056 "AspellPluginImpl): Error in aspell "
00057 "speller configuration." );
00058 qWarning( "%s", warn.toUtf8().data() );
00059 }
00060 catch( const std::runtime_error& err )
00061 {
00062 QString warn = tr( "aspellplugin (AspellPluginImpl::"
00063 "AspellPluginImpl): Error in creating "
00064 "aspell speller." );
00065 qWarning( "%s", warn.toUtf8().data() );
00066 }
00067 activateSpellGUI();
00068 parseSelection();
00069 }
00070
00071 AspellPluginImpl::~AspellPluginImpl()
00072 {
00073
00074 try
00075 {
00076 fsuggest->saveLists();
00077 }
00078 catch( const std::runtime_error& err )
00079 {
00080 qWarning( "aspellplugin (AspellPluginImpl::~AspellPlugin"
00081 "Impl): Error in saving aspell word lists." );
00082 }
00083
00084 delete fsuggest;
00085 }
00086
00087 void AspellPluginImpl::activateSpellGUI()
00088 {
00089
00090
00091 fcurrWord->setEnabled( true );
00092 flistReplacements->setEnabled( true );
00093 fchangeBtn->setEnabled( true );
00094 fchangeAllBtn->setEnabled( true );
00095 fskipAllBtn->setEnabled( true );
00096 fskipBtn->setEnabled( true );
00097 faddWordBtn->setEnabled( true );
00098 ftextLabel1->setEnabled( true );
00099 ftextLabel2->setEnabled( true );
00100 ftextLabel3->setEnabled( true );
00101 ftextLabel4->setEnabled( true );
00102 fmisSpelling->setEnabled( true );
00103 flistDicts->setEnabled( true );
00104 }
00105
00106 void AspellPluginImpl::deactivateSpellGUI()
00107 {
00108
00109
00110 fcurrWord->setEnabled( false );
00111 flistReplacements->setEnabled( false );
00112 fchangeBtn->setEnabled( false );
00113 fchangeAllBtn->setEnabled( false );
00114 fskipAllBtn->setEnabled( false );
00115 fskipBtn->setEnabled( false );
00116 faddWordBtn->setEnabled( false );
00117 ftextLabel1->setEnabled( false );
00118 ftextLabel2->setEnabled( false );
00119 ftextLabel3->setEnabled( false );
00120 ftextLabel4->setEnabled( false );
00121 fmisSpelling->setEnabled( false );
00122 flistDicts->setEnabled( false );
00123 }
00124
00125 void AspellPluginImpl::nextWord()
00126 {
00127 QString wordBoundaries = QString(" .,:;\"'!?\n");
00128 uint len = fFrame->itemText.length();
00129 while (fpos < len && wordBoundaries.indexOf(fFrame->itemText.text(fpos)) >= 0)
00130 {
00131 ++fpos;
00132 }
00133 int pa = fpos;
00134 int pe = 0;
00135 while (fpos < len && wordBoundaries.indexOf(fFrame->itemText.text(fpos)) < 0)
00136 {
00137 ++fpos;
00138 }
00139 pe = fpos;
00140 fcontent = fFrame->itemText.text(pa, pe - pa);
00141 fpos = pa;
00142 }
00143
00144 void AspellPluginImpl::checkText()
00145 {
00146
00147
00148
00149 while (fpos < static_cast<uint>(fFrame->itemText.length()))
00150 {
00151 std::vector<std::string> replacement;
00152 bool status = fsuggest->checkWord(fcontent.toUtf8().data(), replacement);
00153 if (!status)
00154 {
00155 fmisSpelling->setText( fcontent );
00156 fcurrWord->setText( "" );
00157 flistReplacements->clear();
00158 unsigned int idx = 0;
00159 for( std::vector<std::string>::const_iterator i = replacement.begin(); i != replacement.end(); ++i )
00160 {
00161
00162 QString dict = QString::fromUtf8(i->c_str());
00163 flistReplacements->insertItem( idx, dict );
00164 idx++;
00165 }
00166 if( flistReplacements->count() > 0 )
00167 {
00168
00169
00170 flistReplacements->setCurrentRow( 0 );
00171 fcurrWord->setText( flistReplacements->currentItem()->text() );
00172 }
00173 if (rememberedWords.contains(fcontent))
00174 {
00175 QString repl = rememberedWords.value(fcontent);
00176 int cs, cx;
00177 if (fcontent.length() == repl.length())
00178 {
00179 for (cs = 0; cs < fcontent.length(); ++cs)
00180 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00181 }
00182 else
00183 {
00184 if (fcontent.length() < repl.length())
00185 {
00186 for (cs = 0; cs < fcontent.length(); ++cs)
00187 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00188 for (cx = cs; cx < repl.length(); ++cx)
00189 fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
00190 }
00191 else
00192 {
00193 for (cs = 0; cs < repl.length(); ++cs)
00194 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00195 fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
00196 }
00197 }
00198 }
00199 else
00200 break;
00201 }
00202 fpos += fcontent.length();
00203 nextWord();
00204 }
00205 }
00206
00207 void AspellPluginImpl::spellCheckDone()
00208 {
00209
00210
00211 QMessageBox::information(fdoc->scMW(), tr("Spell-Checker"), tr("Spell-checking completed."));
00212 if( fFrame && fFrame->asTextFrame() )
00213 fFrame->asTextFrame()->invalidateLayout();
00214 if( fnchanges.fntot > 0 )
00215 {
00216 fdoc->changed();
00217 }
00218
00219 fdoc->view()->DrawNew();
00220 QApplication::changeOverrideCursor(Qt::ArrowCursor);
00221
00222 fdoc->scMW()->setStatusBarInfoText(tr("Spell-checking done." ));
00223 fdoc->scMW()->mainWindowProgressBar->reset();
00224 close();
00225 }
00226
00227 void AspellPluginImpl::on_fcloseBtn_clicked()
00228 {
00229
00230
00231 spellCheckDone();
00232 }
00233
00234 void AspellPluginImpl::on_fchangeBtn_clicked()
00235 {
00236
00237
00238
00239 QString repl = fcurrWord->text();
00240 int cs, cx;
00241 if (fcontent.length() == repl.length())
00242 {
00243 for (cs = 0; cs < fcontent.length(); ++cs)
00244 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00245 }
00246 else
00247 {
00248 if (fcontent.length() < repl.length())
00249 {
00250 for (cs = 0; cs < fcontent.length(); ++cs)
00251 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00252 for (cx = cs; cx < repl.length(); ++cx)
00253 fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
00254 }
00255 else
00256 {
00257 for (cs = 0; cs < repl.length(); ++cs)
00258 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00259 fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
00260 }
00261 }
00262 fpos += fcontent.length();
00263 nextWord();
00264 checkText();
00265 }
00266
00267 void AspellPluginImpl::on_fchangeAllBtn_clicked()
00268 {
00269
00270
00271
00272 QString repl = fcurrWord->text();
00273 int cs, cx;
00274 if (fcontent.length() == repl.length())
00275 {
00276 for (cs = 0; cs < fcontent.length(); ++cs)
00277 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00278 }
00279 else
00280 {
00281 if (fcontent.length() < repl.length())
00282 {
00283 for (cs = 0; cs < fcontent.length(); ++cs)
00284 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00285 for (cx = cs; cx < repl.length(); ++cx)
00286 fFrame->itemText.insertChars(fpos+cx, repl.mid(cx,1), true);
00287 }
00288 else
00289 {
00290 for (cs = 0; cs < repl.length(); ++cs)
00291 fFrame->itemText.replaceChar(fpos+cs, repl[cs]);
00292 fFrame->itemText.removeChars(fpos+cs, fcontent.length() - cs);
00293 }
00294 }
00295 if (!rememberedWords.contains(fcontent))
00296 rememberedWords.insert(fcontent, repl);
00297 fpos += fcontent.length();
00298 nextWord();
00299 checkText();
00300 }
00301
00302 void AspellPluginImpl::on_fskipBtn_clicked()
00303 {
00304
00305
00306 fpos += fcontent.length();
00307 nextWord();
00308 checkText();
00309 }
00310
00311 void AspellPluginImpl::on_fskipAllBtn_clicked()
00312 {
00313
00314
00315
00316 try
00317 {
00318 #if 0
00319 std::cerr << "on_fskipAllBtn_clicked: Ignoring \"" <<
00320 fwordlist[fidx] << "\"\n";
00321 #endif
00322 fsuggest->ignoreWord( fcontent.toUtf8().data() );
00323 }
00324 catch( const std::runtime_error& err )
00325 {
00326
00327 QString warn =
00328 tr( "AspellPluginImpl::on_fskipAllBtn_clicked(): Unable "
00329 "to skip all instances of \"" ) + fcontent +
00330 tr(" by adding it to the session list.");
00331 qWarning( "%s", warn.toUtf8().data() );
00332 }
00333 fpos += fcontent.length();
00334 nextWord();
00335 checkText();
00336 }
00337
00338 void AspellPluginImpl::on_faddWordBtn_clicked()
00339 {
00340
00341
00342 try
00343 {
00344
00345
00346 fsuggest->addPersonalList( fcurrWord->text().toUtf8().data() );
00347 }
00348 catch( const std::runtime_error& err )
00349 {
00350 QString warn =
00351 tr( "AspellPluginImpl::on_faddWordBtn_clicked(): "
00352 "Unable to add word to personal list." );
00353 qWarning( "%s", warn.toUtf8().data() );
00354 }
00355 }
00356
00357 void AspellPluginImpl::on_flistReplacements_itemActivated()
00358 {
00359
00360
00361
00362 fcurrWord->setText( flistReplacements->currentItem()->text() );
00363 }
00364
00365 void AspellPluginImpl::on_flistDicts_activated()
00366 {
00367
00368
00369
00370 QString entry = flistDicts->currentText();
00371 QStringList fields = entry.split( Speller::Aspell::Suggest::kDICT_DELIM );
00372
00373 if( fields.size() == 4 )
00374 {
00375 QString value =
00376 fields[0] + Speller::Aspell::Suggest::kDICT_DELIM +
00377 fields[1] + Speller::Aspell::Suggest::kDICT_DELIM +
00378 fields[2] + Speller::Aspell::Suggest::kDICT_DELIM +
00379 fields[3];
00380 fsuggest->resetConfig( fields[1].toAscii().data(), fields[2].toAscii().data() );
00381
00382 setPreferences( fields[1], fields[2], Speller::Aspell::Suggest::kDEF_ENCODING, value );
00383 }
00384 }
00385
00386 void AspellPluginImpl::getPreferences()
00387 {
00388
00389
00390 flang = fprefs->get( "lang", Speller::Aspell::Suggest::kDEF_LANG );
00391 fjargon = fprefs->get( "jargon", Speller::Aspell::Suggest::kDEF_JARGON );
00392
00393 fencoding = fprefs->get( "encoding", Speller::Aspell::Suggest::kDEF_ENCODING );
00394 fentry = fprefs->get( "entry", kDEF_ASPELL_ENTRY );
00395 }
00396
00397 void AspellPluginImpl::setPreferences(const QString& lang,
00398 const QString& jargon,
00399 const QString& encoding,
00400 const QString& entry)
00401 {
00402
00403 fprefs->set( "lang", lang );
00404 QString val = jargon == Speller::Aspell::Suggest::kEMPTY ? "" : jargon;
00405 fprefs->set( "jargon", val );
00406 fprefs->set( "encoding", encoding );
00407 fprefs->set( "entry", entry );
00408 }
00409
00410 void AspellPluginImpl::languageChange()
00411 {
00412 qWarning( "AspellPluginImpl::languageChange(): Not implemented yet" );
00413 }
00414
00415 void AspellPluginImpl::parseItem()
00416 {
00417
00418
00419 if( fFrame && fFrame->asTextFrame() )
00420 {
00421 nextWord();
00422 checkText();
00423 }
00424 }
00425
00426 void AspellPluginImpl::parseSelection()
00427 {
00428 fcontent.truncate( 0 );
00429 uint ndocs = fdoc->m_Selection->count();
00430 for( uint i = 0; i < ndocs; ++i )
00431 {
00432 fFrame = fdoc->m_Selection->itemAt( i );
00433 parseItem();
00434 }
00435 }
00436
00437