diff options
| author | craig <craig@11d20701-8431-0410-a711-e3c959e3b870> | 2012-04-12 21:33:03 +0000 |
|---|---|---|
| committer | craig <craig@11d20701-8431-0410-a711-e3c959e3b870> | 2012-04-12 21:33:03 +0000 |
| commit | f3403971efbfd72c8a59eb1957292cf534f1233b (patch) | |
| tree | e7f9c07edc09836a262befb69e7af168bc0b8563 /scribus/plugins | |
| parent | edaa5356a69507d02769dc9a69f32021e6e07ac3 (diff) | |
| download | scribus-f3403971efbfd72c8a59eb1957292cf534f1233b.tar.gz scribus-f3403971efbfd72c8a59eb1957292cf534f1233b.tar.xz scribus-f3403971efbfd72c8a59eb1957292cf534f1233b.zip | |
Add hunspell based spell checker - not enabled, backup only for now, not enabled in the build
git-svn-id: svn://scribus.net/branches/Version14x/Scribus@17437 11d20701-8431-0410-a711-e3c959e3b870
Diffstat (limited to 'scribus/plugins')
10 files changed, 894 insertions, 0 deletions
diff --git a/scribus/plugins/tools/CMakeLists.txt b/scribus/plugins/tools/CMakeLists.txt index 16805ec..979354e 100644 --- a/scribus/plugins/tools/CMakeLists.txt +++ b/scribus/plugins/tools/CMakeLists.txt @@ -9,4 +9,7 @@ ADD_SUBDIRECTORY(subdivide) if (HAVE_ASPELL) ADD_SUBDIRECTORY(spellcheck) endif (HAVE_ASPELL) +if (HAVE_HUNSPELL) + ADD_SUBDIRECTORY(hunspellcheck) +endif (HAVE_HUNSPELL) ADD_SUBDIRECTORY(transform) diff --git a/scribus/plugins/tools/hunspellcheck/CMakeLists.txt b/scribus/plugins/tools/hunspellcheck/CMakeLists.txt new file mode 100644 index 0000000..4d1129c --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/CMakeLists.txt @@ -0,0 +1,46 @@ + + INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/scribus + ${HUNSPELL_INCLUDE_DIR} + ) + + SET(HUNSPELL_PLUGIN_UI_SRC + hunspelldialogbase.ui + ) + + SET(HUNSPELL_PLUGIN_MOC_CLASSES + hunspelldialog.h + hunspellplugin.h + hunspellpluginimpl.h + ) + + SET(HUNSPELL_PLUGIN_SOURCES + hunspelldialog.cpp + hunspellplugin.cpp + hunspellpluginimpl.cpp + ) + + SET(SCRIBUS_HUNSPELL_PLUGIN "hunspellplugin") + + QT4_WRAP_UI(HUNSPELL_PLUGIN_UI_SOURCES ${HUNSPELL_PLUGIN_UI_SRC} ) + QT4_WRAP_CPP(HUNSPELL_PLUGIN_MOC_SOURCES ${HUNSPELL_PLUGIN_MOC_CLASSES}) + + ADD_LIBRARY(${SCRIBUS_HUNSPELL_PLUGIN} MODULE + ${HUNSPELL_PLUGIN_SOURCES} + ${HUNSPELL_PLUGIN_MOC_SOURCES} + ${HUNSPELL_PLUGIN_UI_SOURCES} + ) + + TARGET_LINK_LIBRARIES(${SCRIBUS_HUNSPELL_PLUGIN} ${HUNSPELL_LIBRARIES} ${PLUGIN_LIBRARIES}) + + INSTALL(TARGETS ${SCRIBUS_HUNSPELL_PLUGIN} + LIBRARY + DESTINATION ${PLUGINDIR} + PERMISSIONS ${PLUGIN_PERMISSIONS} + ) + + ADD_DEPENDENCIES(${SCRIBUS_HUNSPELL_PLUGIN} ${EXE_NAME}) + +# SET_TARGET_PROPERTIES(${SCRIBUS_ASPELL_PLUGIN} PROPERTIES VERSION "0.0.1") + diff --git a/scribus/plugins/tools/hunspellcheck/hunspelldialog.cpp b/scribus/plugins/tools/hunspellcheck/hunspelldialog.cpp new file mode 100644 index 0000000..4d589e3 --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspelldialog.cpp @@ -0,0 +1,143 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ + +#include <QComboBox> +#include <QListWidget> +#include <QTextEdit> +#include "hunspelldialog.h" + + +HunspellDialog::HunspellDialog(QWidget *parent, ScribusDoc *doc, PageItem *frameToCheck) +{ + setupUi( this ); + setModal( true ); + + connect (ignoreOncePushButton, SIGNAL(clicked()), this, SLOT(goToNextWord())); + connect (ignoreAllPushButton, SIGNAL(clicked()), this, SLOT(ignoreAllWords())); + connect (changePushButton, SIGNAL(clicked()), this, SLOT(changeWord())); + connect (changeAllPushButton, SIGNAL(clicked()), this, SLOT(changeAllWords())); + + m_doc=doc; + m_docChanged=false; + fTC=frameToCheck; + changeOffset=0; +} + +void HunspellDialog::set(QStringList *dictEntries, Hunspell **hspellers, QList<WordsFound> *wfList) +{ + m_dictEntries=dictEntries; + m_hspellers=hspellers; + m_wfList=wfList; + + languagesComboBox->addItems(*dictEntries); + + wfListIndex=0; + goToNextWord(0); +} + +void HunspellDialog::goToNextWord(int i) +{ + if (i>=0) + wfListIndex=i; + else + ++wfListIndex; + if (wfListIndex>=m_wfList->count()) + { + statusLabel->setText(tr("Spelling check complete")); + suggestionsListWidget->clear(); + sentenceTextEdit->clear(); + changePushButton->setEnabled(false); + changeAllPushButton->setEnabled(false); + return; + } + else + statusLabel->setText(""); + currWF=m_wfList->at(wfListIndex); + suggestionsListWidget->clear(); + suggestionsListWidget->addItems(currWF.replacements); + suggestionsListWidget->setCurrentRow(0); + StoryText *iText=&fTC->itemText; + int sentencePos=qMax(0,iText->prevSentence(currWF.start)); + sentencePos=qMax(sentencePos, iText->nextWord(sentencePos)); + int nextSentencePos=qMin(iText->length(), iText->nextSentence(currWF.end)); + QString sentence=iText->text(sentencePos, nextSentencePos-sentencePos); + sentence.insert(currWF.end-sentencePos+changeOffset,"</b></font>"); + sentence.insert(currWF.start-sentencePos+changeOffset,"<font color=red><b>"); + sentenceTextEdit->setText(sentence); + +} + +void HunspellDialog::ignoreAllWords() +{ + QString wordToIgnore=m_wfList->at(wfListIndex).w; + //Do we start from 0 or from the instance of the word where we are... 0 for now + for(int i=0;i<m_wfList->count();++i) + if(m_wfList->at(i).w==wordToIgnore) + m_wfList->value(i).ignore=true; + goToNextWord(); +} + +void HunspellDialog::changeWord() +{ + //If we have ignored a word, skip to the next. + if(m_wfList->at(wfListIndex).ignore && !m_wfList->at(wfListIndex).changed) + goToNextWord(); + replaceWord(wfListIndex); + m_docChanged=true; + goToNextWord(); +} + +void HunspellDialog::changeAllWords() +{ + if(m_wfList->at(wfListIndex).ignore && !m_wfList->at(wfListIndex).changed) + return; + QString wordToChange=m_wfList->at(wfListIndex).w; + //Do we start from 0 or from the instance of the word where we are... 0 for now + for(int i=0;i<m_wfList->count();++i) + if(m_wfList->at(i).w==wordToChange) + { + m_wfList->value(i).changed=true; + } + m_docChanged=true; + goToNextWord(); +} + +void HunspellDialog::replaceWord(int i) +{ + StoryText *iText=&fTC->itemText; + currWF=m_wfList->at(i); + m_wfList->value(i).changed=true; + QString newText(suggestionsListWidget->currentItem()->text()); + if (newText.length()==currWF.w.length()) + { + for (int i = 0; i < currWF.w.length(); ++i) + iText->replaceChar(currWF.start+i+changeOffset, newText[i]); + } + else + { + if (newText.length()>currWF.w.length()) + { + for (int i = 0; i < currWF.w.length(); ++i) + iText->replaceChar(currWF.start+i+changeOffset, newText[i]); + for (int i = currWF.w.length(); i < newText.length(); ++i) + iText->insertChars(currWF.start+i+changeOffset, newText.mid(i,1), true); + int lengthDiff=newText.length()-currWF.w.length(); + changeOffset+=lengthDiff; + qDebug()<<"Change Offset is:"<<changeOffset; + } + else + { + for (int i = 0; i < newText.length(); ++i) + iText->replaceChar(currWF.start+i+changeOffset, newText[i]); + int lengthDiff=currWF.w.length() - newText.length(); + iText->removeChars(currWF.start+changeOffset+newText.length(), lengthDiff); + changeOffset-=lengthDiff; + qDebug()<<"Change Offset is:"<<changeOffset; + } + } + m_docChanged=true; +} diff --git a/scribus/plugins/tools/hunspellcheck/hunspelldialog.h b/scribus/plugins/tools/hunspellcheck/hunspelldialog.h new file mode 100644 index 0000000..b3e5a0f --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspelldialog.h @@ -0,0 +1,47 @@ +#ifndef HUNSPELLDIALOG_H +#define HUNSPELLDIALOG_H + +#include <QDialog> +#include <QList> +#include <QStringList> +#include <QWidget> + +#include <hunspell/hunspell.hxx> + +#include "pluginapi.h" +#include "hunspellpluginstructs.h" +#include "scribusdoc.h" +#include "pageitem.h" + +#include "ui_hunspelldialogbase.h" + +class PLUGIN_API HunspellDialog : public QDialog, private Ui::HunspellDialogBase +{ + Q_OBJECT + + public: + HunspellDialog(QWidget* parent, ScribusDoc *doc, PageItem* frameToCheck); + ~HunspellDialog() {}; + void set(QStringList* dictEntries, Hunspell **hspellers, QList<WordsFound>* wfList); + bool docChanged() {return m_docChanged;} + + public slots: + void goToNextWord(int i=-1); + void ignoreAllWords(); + void changeWord(); + void changeAllWords(); + void replaceWord(int i); + + private: + ScribusDoc* m_doc; + PageItem* fTC; + QStringList* m_dictEntries; + Hunspell **m_hspellers; + QList<WordsFound>* m_wfList; + WordsFound currWF; + int wfListIndex; + bool m_docChanged; + int changeOffset; +}; + +#endif // HUNSPELLDIALOG_H diff --git a/scribus/plugins/tools/hunspellcheck/hunspelldialogbase.ui b/scribus/plugins/tools/hunspellcheck/hunspelldialogbase.ui new file mode 100644 index 0000000..96f1631 --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspelldialogbase.ui @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HunspellDialogBase</class> + <widget class="QDialog" name="HunspellDialogBase"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>687</width> + <height>406</height> + </rect> + </property> + <property name="windowTitle"> + <string>Check Spelling</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Text Language:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="languagesComboBox"/> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Not in dictionary</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QTextEdit" name="sentenceTextEdit"/> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="ignoreOncePushButton"> + <property name="text"> + <string>Ignore Once</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="ignoreAllPushButton"> + <property name="text"> + <string>Ignore All</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Suggestions</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QListWidget" name="suggestionsListWidget"/> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="changePushButton"> + <property name="text"> + <string>Change</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="changeAllPushButton"> + <property name="text"> + <string>Change All</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLabel" name="statusLabel"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>HunspellDialogBase</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>HunspellDialogBase</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/scribus/plugins/tools/hunspellcheck/hunspellplugin.cpp b/scribus/plugins/tools/hunspellcheck/hunspellplugin.cpp new file mode 100644 index 0000000..5b089a7 --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspellplugin.cpp @@ -0,0 +1,95 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#include "hunspellplugin.h" +#include "hunspellpluginimpl.h" +#include "scribuscore.h" + +// See scplugin.h and pluginmanager.{cpp,h} for detail on what these methods +// do. That documentatation is not duplicated here. +// Please don't implement the functionality of your plugin here; do that +// in mypluginimpl.h and mypluginimpl.cpp . + +HunspellPlugin::HunspellPlugin() : ScActionPlugin() +{ + // Set action info in languageChange, so we only have to do + // it in one place. + languageChange(); +} + +HunspellPlugin::~HunspellPlugin() {}; + +void HunspellPlugin::languageChange() +{ + // Note that we leave the unused members unset. They'll be initialised + // with their default ctors during construction. + // Action name + m_actionInfo.name = "HunspellPlugin"; + // Action text for menu, including &accel + m_actionInfo.text = tr("Hunspell &Plugin"); + // Menu + m_actionInfo.menu = "Item"; + // If needed, what item to add the menu item after + //m_actionInfo.menuAfterName = "ColorWheel" + // If needed, the keyboard shortcut for the plugin + m_actionInfo.keySequence = "SHIFT+F7"; + // Should the menu item be enabled when the app starts + // (even without a document open) ? + m_actionInfo.enabledOnStartup = false; + m_actionInfo.notSuitableFor.append(PageItem::Line); + m_actionInfo.notSuitableFor.append(PageItem::Polygon); + m_actionInfo.notSuitableFor.append(PageItem::ImageFrame); + m_actionInfo.notSuitableFor.append(PageItem::PathText); + m_actionInfo.notSuitableFor.append(PageItem::LatexFrame); + m_actionInfo.needsNumObjects = 1; +} + +const QString HunspellPlugin::fullTrName() const +{ + return QObject::tr("Hunspell Plugin"); +} + +const ScActionPlugin::AboutData* HunspellPlugin::getAboutData() const +{ + AboutData* about = new AboutData; + Q_CHECK_PTR(about); + return about; +} + +void HunspellPlugin::deleteAboutData(const AboutData* about) const +{ + Q_ASSERT(about); + delete about; +} + +bool HunspellPlugin::run(ScribusDoc* doc, QString target) +{ + HunspellPluginImpl *hunspellPluginImpl = new HunspellPluginImpl(); + Q_CHECK_PTR(hunspellPluginImpl); + bool result = hunspellPluginImpl->run(target, doc); + delete hunspellPluginImpl; + return result; +} + +// Low level plugin API +int hunspellplugin_getPluginAPIVersion() +{ + return PLUGIN_API_VERSION; +} + +ScPlugin* hunspellplugin_getPlugin() +{ + HunspellPlugin* plug = new HunspellPlugin(); + Q_CHECK_PTR(plug); + return plug; +} + +void hunspellplugin_freePlugin(ScPlugin* plugin) +{ + HunspellPlugin* plug = dynamic_cast<HunspellPlugin*>(plugin); + Q_ASSERT(plug); + delete plug; +} diff --git a/scribus/plugins/tools/hunspellcheck/hunspellplugin.h b/scribus/plugins/tools/hunspellcheck/hunspellplugin.h new file mode 100644 index 0000000..0b89101 --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspellplugin.h @@ -0,0 +1,40 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#ifndef HUNSPELLPLUGIN_H +#define HUNSPELLPLUGIN_H + +#include "pluginapi.h" +#include "scplugin.h" + +/*! \brief See scplugin.h and pluginmanager.{cpp,h} for detail on what these methods do. +That documentatation is not duplicated here. +Please don't implement the functionality of your plugin here; do that +in mypluginimpl.h and mypluginimpl.cpp. */ +class PLUGIN_API HunspellPlugin : public ScActionPlugin +{ + Q_OBJECT + + public: + //! \brief Standard plugin implementation + HunspellPlugin(); + virtual ~HunspellPlugin(); + //! \brief main method to run the plug + virtual bool run(ScribusDoc* doc, QString target = QString::null); + virtual const QString fullTrName() const; + virtual const AboutData* getAboutData() const; + virtual void deleteAboutData(const AboutData* about) const; + virtual void languageChange(); + virtual void addToMainWindowMenu(ScribusMainWindow *) {}; + + // Special features (none) +}; + +extern "C" PLUGIN_API int hunspellplugin_getPluginAPIVersion(); +extern "C" PLUGIN_API ScPlugin* hunspellplugin_getPlugin(); +extern "C" PLUGIN_API void hunspellplugin_freePlugin(ScPlugin* plugin); + +#endif diff --git a/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.cpp b/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.cpp new file mode 100644 index 0000000..7d3c7da --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.cpp @@ -0,0 +1,251 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#include "hunspellpluginimpl.h" +#include "hunspelldialog.h" +#include "pageitem.h" +#include "pageitem_textframe.h" +#include "selection.h" +#include "scribusdoc.h" +#include "scribus.h" +#include "text/specialchars.h" +#include "util.h" + +#include <QDebug> +#include <QDir> +#include <QFile> +#include <QMessageBox> + +#ifdef Q_OS_WIN32 +#include <windows.h> +#include <shlobj.h> +#endif + + +// Initialize members here, if any +HunspellPluginImpl::HunspellPluginImpl() : QObject(0) +{ + hspellers=NULL; + numDicts=0; +} + +HunspellPluginImpl::~HunspellPluginImpl() +{ + if (hspellers) + { + for (int i = 0; i < numDicts; ++i) + { + delete hspellers[i]; + hspellers[i] = NULL; + } + delete[] hspellers; + } + hspellers = NULL; + numDicts = 0; +} + +bool HunspellPluginImpl::run(const QString & target, ScribusDoc* doc) +{ + m_doc=doc; + bool initOk=initHunspell(); + qDebug()<<"Hunspell Init Ok:"<<initOk; + if (!initOk) + return false; + bool spellCheckOk=checkWithHunspell(); + if (!spellCheckOk) + return false; + return true; +} + +bool HunspellPluginImpl::findDictionaries() +{ + //dictionaryPaths + QString macPortsPath("/opt/local/share/hunspell/"); + QString finkPath("/sw/share/hunspell/"); + QString osxLibreOfficePath("/Applications/LibreOffice.app/Contents/share/extensions"); + QString osxUserLibreOfficePath(QDir::homePath()+"/Applications/LibreOffice.app/Contents/share/extensions"); + QString linuxLocalPath("/usr/local/share/hunspell/"); + QString linuxPath("/usr/share/hunspell/"); + QString windowsLOPath("LibreOffice 3.5/share/extensions"); + QDir d; + +#ifdef Q_OS_MAC + d.setPath(macPortsPath); + if (d.exists()) + { + dictPath=macPortsPath; + return true; + } + d.setPath(finkPath); + if (d.exists()) + { + dictPath=finkPath; + return true; + } + d.setPath(osxLibreOfficePath); + if (d.exists()) + { + dictPath=osxLibreOfficePath; + return true; + } + d.setPath(osxUserLibreOfficePath); + if (d.exists()) + { + dictPath=osxUserLibreOfficePath; + return true; + } + return false; +#elif defined(Q_WS_X11) + d.setPath(linuxPath); + if (d.exists()) + { + dictPath=linuxPath; + return true; + } + d.setPath(linuxLocalPath); + if (d.exists()) + { + dictPath=linuxLocalPath; + return true; + } +#elif defined(Q_OS_WIN32) + QString progFiles = getSpecialDir(CSIDL_PROGRAM_FILES); + d.setPath(progFiles+windowsLOPath); + if (d.exists()) + { + dictPath=progFiles+windowsLOPath; + return true; + } +#endif + return false; +} + +bool HunspellPluginImpl::initHunspell() +{ + int errorCount=0; + bool dictPathFound=findDictionaries(); + if (!dictPathFound) + qDebug()<<"No preinstalled dictonary paths found"; + else + qDebug()<<"Preinstalled dictionary path selected"<<dictPath; + //TODO: Find this somehow +// QString startPath; +// startPath="/Applications/LibreOffice.app/Contents/share/extensions/dict-en/"; +// dictPath=startPath; + + // Find the dic and aff files in the location + QDir dictLocation(dictPath); + QStringList dictFilters, affFilters; + dictFilters << "*.dic"; + affFilters << "*.aff"; + QStringList dictList(dictLocation.entryList(dictFilters, QDir::Files, QDir::Name)); + dictList.replaceInStrings(".dic",""); + QStringList affList; + + //Ensure we have aff+dic file pairs, remove any hyphenation dictionaries from the list + QString dictName; + QStringListIterator dictListIterator(dictList); + while (dictListIterator.hasNext()) + { + dictName=dictListIterator.next(); + if (!QFile::exists(dictPath+dictName+".aff")) + dictList.removeAll(dictName); + } + numDicts=dictList.count(); + qDebug()<<"Number of dictionaries/AFFs found:"<<numDicts<<numAFFs; + if (numDicts==0) + ++errorCount; + qDebug()<<dictList; + + //Initialise one hunspeller for each dictionary found + //Maybe we only need the text language related one later on + dictEntries=dictList; + affEntries=affList; + hspellers = new Hunspell* [numDicts]; + for (int i=0; i<numDicts; ++i) + hspellers[i] = new Hunspell((dictPath+dictList.at(i)+".aff").toLocal8Bit().constData(), + (dictPath+dictList.at(i)+".dic").toLocal8Bit().constData()); + + return errorCount==0; +} + +bool HunspellPluginImpl::checkWithHunspell() +{ + PageItem *frameToCheck; + + for( int i = 0; i < m_doc->m_Selection->count(); ++i ) + { + frameToCheck = m_doc->m_Selection->itemAt(i); + parseTextFrame(frameToCheck); + openGUIForTextFrame(frameToCheck); + m_doc->view()->DrawNew(); + } + return true; +} + +bool HunspellPluginImpl::parseTextFrame(PageItem *frameToCheck) +{ + static QString wordBoundaries(" .,:;\"'!?\n"); + + StoryText *iText=&frameToCheck->itemText; + int len=iText->length(); + QString text=iText->text(0,len); +// qDebug()<<text; + int wordCount=0,wordNo=0,errorCount=0; + int currPos=0; + while (currPos<len) + { + int wordPos=iText->nextWord(currPos); + currPos=wordPos; + int eoWord=wordPos; + while(eoWord < len) + { + if (iText->text(eoWord).isLetterOrNumber()) + ++eoWord; + else + break; + } + QString word=iText->text(wordPos,eoWord-wordPos); + ++wordCount; + ++wordNo; + QStringList replacements; + if (hspellers[0]->spell(word.toLocal8Bit().constData())==0) + { +// qDebug()<<word; + ++errorCount; + char **sugglist = NULL; + int suggCount=hspellers[0]->suggest(&sugglist, word.toLocal8Bit().constData()); + for (int j=0; j < suggCount; ++j) + { +// qDebug()<<"Suggestion "<<j<<":"<<sugglist[j]; + replacements<<sugglist[j]; + } + hspellers[0]->free_list(&sugglist, suggCount); + + struct WordsFound wf; + wf.start=currPos; + wf.end=eoWord; + wf.w=word; + wf.replacements=replacements; + wf.changed=false; + wf.ignore=false; + wordsToCorrect.append(wf); + } + } +// qDebug()<<"Errors found:"<<errorCount; + return true; +} + +bool HunspellPluginImpl::openGUIForTextFrame(PageItem *frameToCheck) +{ + HunspellDialog hsDialog(m_doc->scMW(), m_doc, frameToCheck); + hsDialog.set(&dictEntries, hspellers, &wordsToCorrect); + hsDialog.exec(); + if (hsDialog.docChanged()) + m_doc->changed(); + return true; +} + diff --git a/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.h b/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.h new file mode 100644 index 0000000..d664682 --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspellpluginimpl.h @@ -0,0 +1,48 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#ifndef HUNSPELLPLUGINIMPL_H +#define HUNSPELLPLUGINIMPL_H + +#include <hunspell/hunspell.hxx> +#include "hunspellpluginstructs.h" + +#include <QObject> +#include <QString> +#include <QStringList> + +class QString; +class ScribusDoc; +class PageItem; + + + +class HunspellPluginImpl : public QObject +{ + Q_OBJECT + public: + HunspellPluginImpl(); + ~HunspellPluginImpl(); + bool run(const QString & target, ScribusDoc* doc=0); + bool findDictionaries(); + bool initHunspell(); + bool checkWithHunspell(); + bool parseTextFrame(PageItem *frameToCheck); + bool openGUIForTextFrame(PageItem *frameToCheck); + QList<WordsFound> wordsToCorrect; + + protected: + QStringList dictionaryPaths; + QString dictPath, affPath; + int numDicts, numAFFs; + Hunspell **hspellers; + QStringList dictEntries; + QStringList affEntries; + ScribusDoc* m_doc; +}; + +#endif + diff --git a/scribus/plugins/tools/hunspellcheck/hunspellpluginstructs.h b/scribus/plugins/tools/hunspellcheck/hunspellpluginstructs.h new file mode 100644 index 0000000..0515cbb --- /dev/null +++ b/scribus/plugins/tools/hunspellcheck/hunspellpluginstructs.h @@ -0,0 +1,16 @@ +#ifndef HUNSPELLPLUGINSTRUCTS_H +#define HUNSPELLPLUGINSTRUCTS_H + +#include <QString> +#include <QStringList> + +struct WordsFound { + int start; + int end; + QString w; + QStringList replacements; + bool changed; + bool ignore; +}; + +#endif // HUNSPELLPLUGINSTRUCTS_H |
