Posts Tagged ‘pyqt’
* QPlainTextEdit With In Line Spell Check
Posted on August 22nd, 2009 by John. Filed under programming.
***Update: Simplified Highlighter.highlightBlock function
One thing Qt lacks is an integrated spell check in the text entry components. For a project I’m working on this is necessary. Using python-enchant and the QSyntaxHighlighter I was able to implement this functionality. Here is how to add an in line spell check support to a QPlainTextEdit.
#!/usr/bin/env python # -*- coding: utf-8 -*- __license__ = 'MIT' __copyright__ = '2009, John Schember ' __docformat__ = 'restructuredtext en' import re import sys import enchant from PyQt4.Qt import QAction from PyQt4.Qt import QApplication from PyQt4.Qt import QEvent from PyQt4.Qt import QMenu from PyQt4.Qt import QMouseEvent from PyQt4.Qt import QPlainTextEdit from PyQt4.Qt import QSyntaxHighlighter from PyQt4.Qt import QTextCharFormat from PyQt4.Qt import QTextCursor from PyQt4.Qt import Qt from PyQt4.QtCore import pyqtSignal class SpellTextEdit(QPlainTextEdit): def __init__(self, *args): 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() == Qt.RightButton: # Rewrite the mouse event to a left button event so the cursor is # moved to the location of the pointer. event = QMouseEvent(QEvent.MouseButtonPress, event.pos(), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) QPlainTextEdit.mousePressEvent(self, event) def contextMenuEvent(self, event): popup_menu = self.createStandardContextMenu() # Select the word under the cursor. cursor = self.textCursor() cursor.select(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 = QMenu('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(QSyntaxHighlighter): WORDS = u'(?iu)[\w\']+' def __init__(self, *args): 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 = QTextCharFormat() format.setUnderlineColor(Qt.red) format.setUnderlineStyle(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(QAction): ''' A special QAction that returns the text in a signal. ''' correct = pyqtSignal(unicode) def __init__(self, *args): QAction.__init__(self, *args) self.triggered.connect(lambda x: self.correct.emit( unicode(self.text()))) def main(args=sys.argv): app = QApplication(args) spellEdit = SpellTextEdit() spellEdit.show() return app.exec_() if __name__ == '__main__': sys.exit(main()) |
The SpellTextEdit’s purpose is straightforward. It will mark misspelled words. Right clicking on a word in the SpellTextEdit will cause the word to become selected and display a context menu. If the word is misspelled and there are spelling suggestions the context menu will include a sub menu of those suggestions. Selecting a suggestion will replace the misspelled text with the selection.
The Highlighter class takes text, breaks it into words, checks if they are spelled correctly and if not underlines the misspelled ones with a red squiggle. I’m using a regular expression to split the words instead of using str.split because str.split will only split on whitespace and include punctuation (e.g. “.!*) as part of the words.
SpellAction is a simple class that allows for the action’s text to be sent with the signal. This is necessary for dynamically creating the list of possible correction words in the right click menu. The SpellAction is connected to a function that replaces the selected text with the signal text.
* Calibre Week in Review
Posted on May 31st, 2009 by John. Filed under calibre.
Not much happened this week. A few bug fixes and a new output format, RTF. It produces acceptable results. It also embeds images into the file. The output could use some tweaking, but this will come with time. The only caveat is the output is ascii only. This is to keep compatibility with Cailbre’s RTF intput which can only accept ascii rtf files.
Pluginize has been merged back into trunk. Once a bit of testing is done by Kovid, he will be rolling out a beta for the 0.6 release. For those of you, like me, who use Ubuntu and build Calibre from source, there is a little change you will need to make in order to have it build. Open the file /usr/lib/python2.6/dist-packages/PyQt4/uic/Compiler/qtproxies.py and modify _qwidgets on line 238 to include “QWizardPage”.
Tags
Archives
- April 2013 (1)
- March 2013 (1)
- February 2013 (1)
- December 2012 (2)
- October 2012 (1)
- August 2012 (1)
- July 2012 (1)
- June 2012 (2)
- April 2012 (1)
- March 2012 (1)
- February 2012 (3)
- January 2012 (3)
- December 2011 (2)
- November 2011 (1)
- October 2011 (3)
- September 2011 (9)
- August 2011 (15)
- July 2011 (5)
- June 2011 (3)
- May 2011 (4)
- April 2011 (2)
- March 2011 (2)
- February 2011 (4)
- January 2011 (4)
- December 2010 (2)
- November 2010 (1)
- October 2010 (1)
- August 2010 (3)
- July 2010 (4)
- June 2010 (1)
- May 2010 (2)
- March 2010 (1)
- January 2010 (8)
- December 2009 (5)
- November 2009 (6)
- October 2009 (4)
- September 2009 (2)
- August 2009 (6)
- July 2009 (6)
- June 2009 (4)
- May 2009 (6)
- April 2009 (4)
- March 2009 (2)
- February 2009 (4)
- January 2009 (4)
- December 2008 (7)
- November 2008 (2)