diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 33ba25046..195f724f8 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -19,7 +19,7 @@ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # # more details. # # # -# You should have received a copy of the GNU General Public License along # +# You should have received a copy of the GNU General Pu__init__.pyblic License along # # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### @@ -27,6 +27,109 @@ The :mod:`ui` module provides the core user interface for OpenLP """ +# http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/ + +import re +import sys +import enchant + +from PyQt4 import QtCore, QtGui + +class SpellTextEdit(QtGui.QPlainTextEdit): + + def __init__(self, *args): + QtGui.QPlainTextEdit.__init__(self, *args) + + # Default dictionary based on the current locale. + self.dict = enchant.Dict() + self.highlighter = Highlighter(self.document()) + self.highlighter.setDict(self.dict) + + def mousePressEvent(self, event): + if event.button() == QtCore.Qt.RightButton: + # Rewrite the mouse event to a left button event so the cursor is + # moved to the location of the pointer. + event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, event.pos(), + QtCore.Qt.LeftButton, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier) + QtGui.QPlainTextEdit.mousePressEvent(self, event) + + def contextMenuEvent(self, event): + popup_menu = self.createStandardContextMenu() + + # Select the word under the cursor. + cursor = self.textCursor() + cursor.select(QtGui.QTextCursor.WordUnderCursor) + self.setTextCursor(cursor) + + # Check if the selected word is misspelled and offer spelling + # suggestions if it is. + if self.textCursor().hasSelection(): + text = unicode(self.textCursor().selectedText()) + if not self.dict.check(text): + spell_menu = QtGui.QMenu(u'Spelling Suggestions') + for word in self.dict.suggest(text): + action = SpellAction(word, spell_menu) + action.correct.connect(self.correctWord) + spell_menu.addAction(action) + # Only add the spelling suggests to the menu if there are + # suggestions. + if len(spell_menu.actions()) != 0: + popup_menu.insertSeparator(popup_menu.actions()[0]) + popup_menu.insertMenu(popup_menu.actions()[0], spell_menu) + + popup_menu.exec_(event.globalPos()) + + def correctWord(self, word): + ''' + Replaces the selected text with word. + ''' + cursor = self.textCursor() + cursor.beginEditBlock() + + cursor.removeSelectedText() + cursor.insertText(word) + + cursor.endEditBlock() + +class Highlighter(QtGui.QSyntaxHighlighter): + + WORDS = u'(?iu)[\w\']+' + + def __init__(self, *args): + QtGui.QSyntaxHighlighter.__init__(self, *args) + + self.dict = None + + def setDict(self, dict): + self.dict = dict + + def highlightBlock(self, text): + if not self.dict: + return + + text = unicode(text) + + format = QtGui.QTextCharFormat() + format.setUnderlineColor(QtCore.Qt.red) + format.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline) + + for word_object in re.finditer(self.WORDS, text): + if not self.dict.check(word_object.group()): + self.setFormat(word_object.start(), + word_object.end() - word_object.start(), format) + +class SpellAction(QtGui.QAction): + ''' + A special QAction that returns the text in a signal. + ''' + correct = QtCore.pyqtSignal(unicode) + + def __init__(self, *args): + QtGui.QAction.__init__(self, *args) + + self.triggered.connect(lambda x: self.correct.emit( + unicode(self.text()))) + class HideMode(object): """ This is basically an enumeration class which specifies the mode of a Bible. diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index 241f96237..ac58789fa 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate +from openlp.core.ui import SpellTextEdit class Ui_CustomEditDialog(object): def setupUi(self, customEditDialog): @@ -73,7 +74,7 @@ class Ui_CustomEditDialog(object): self.editLayout3.setSpacing(8) self.editLayout3.setMargin(0) self.editLayout3.setObjectName(u'editLayout3') - self.verseTextEdit = QtGui.QTextEdit(self.editWidget) + self.verseTextEdit = SpellTextEdit(self.editWidget) self.verseTextEdit.setObjectName(u'verseTextEdit') self.editLayout3.addWidget(self.verseTextEdit) self.buttonWidget = QtGui.QWidget(self.editWidget) diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py index 10c0d6849..e165b2b86 100644 --- a/openlp/plugins/songs/forms/editversedialog.py +++ b/openlp/plugins/songs/forms/editversedialog.py @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate +from openlp.core.ui import SpellTextEdit from openlp.plugins.songs.lib import VerseType class Ui_EditVerseDialog(object): @@ -38,7 +39,7 @@ class Ui_EditVerseDialog(object): self.EditVerseLayout.setSpacing(8) self.EditVerseLayout.setMargin(8) self.EditVerseLayout.setObjectName(u'EditVerseLayout') - self.VerseTextEdit = QtGui.QPlainTextEdit(EditVerseDialog) + self.VerseTextEdit = SpellTextEdit(EditVerseDialog) self.VerseTextEdit.setObjectName(u'VerseTextEdit') self.EditVerseLayout.addWidget(self.VerseTextEdit) self.VerseTypeLayout = QtGui.QHBoxLayout() diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index 3622593a0..46d9f954c 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -45,6 +45,9 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) + QtCore.QObject.connect(self.VerseTextEdit, + QtCore.SIGNAL('customContextMenuRequested(QPoint)'), + self.contextMenu) QtCore.QObject.connect( self.InsertButton, QtCore.SIGNAL(u'clicked()'), @@ -57,6 +60,10 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): ) self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---') + def contextMenu(self, point): + item = self.serviceManagerList.itemAt(point) + print item + def insertVerse(self, title, num=1): if self.VerseTextEdit.textCursor().columnNumber() != 0: self.VerseTextEdit.insertPlainText(u'\n')