<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>John&#039;s Blog &#187; widget</title>
	<atom:link href="http://john.nachtimwald.com/tag/widget/feed/" rel="self" type="application/rss+xml" />
	<link>http://john.nachtimwald.com</link>
	<description>My little blog</description>
	<lastBuildDate>Sat, 31 Jul 2010 17:28:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>QPlainTextEdit With In Line Spell Check</title>
		<link>http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/</link>
		<comments>http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 21:06:33 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[pyqt]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[spell check]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://john.nachtimwald.com/?p=197</guid>
		<description><![CDATA[***Update: Simplified Highlighter.highlightBlock function One thing Qt lacks is an integrated spell check in the text entry components. For a project I&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>***Update: Simplified Highlighter.highlightBlock function</p>
<p>One thing Qt lacks is an integrated spell check in the text entry components. For a project I&#8217;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.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
__license__ = <span style="color: #483d8b;">'MIT'</span>
__copyright__ = <span style="color: #483d8b;">'2009, John Schember '</span>
__docformat__ = <span style="color: #483d8b;">'restructuredtext en'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> enchant
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QAction
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QApplication
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QEvent
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QMenu
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QMouseEvent
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QPlainTextEdit
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QSyntaxHighlighter
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QTextCharFormat
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> QTextCursor
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">Qt</span> <span style="color: #ff7700;font-weight:bold;">import</span> Qt
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4.<span style="color: black;">QtCore</span> <span style="color: #ff7700;font-weight:bold;">import</span> pyqtSignal
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SpellTextEdit<span style="color: black;">&#40;</span>QPlainTextEdit<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
        QPlainTextEdit.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Default dictionary based on the current locale.</span>
        <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span> = enchant.<span style="color: black;">Dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">highlighter</span> = Highlighter<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">document</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">highlighter</span>.<span style="color: black;">setDict</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> mousePressEvent<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">button</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == Qt.<span style="color: black;">RightButton</span>:
            <span style="color: #808080; font-style: italic;"># Rewrite the mouse event to a left button event so the cursor is</span>
            <span style="color: #808080; font-style: italic;"># moved to the location of the pointer.</span>
            event = QMouseEvent<span style="color: black;">&#40;</span>QEvent.<span style="color: black;">MouseButtonPress</span>, event.<span style="color: black;">pos</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                Qt.<span style="color: black;">LeftButton</span>, Qt.<span style="color: black;">LeftButton</span>, Qt.<span style="color: black;">NoModifier</span><span style="color: black;">&#41;</span>
        QPlainTextEdit.<span style="color: black;">mousePressEvent</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> contextMenuEvent<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        popup_menu = <span style="color: #008000;">self</span>.<span style="color: black;">createStandardContextMenu</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Select the word under the cursor.</span>
        cursor = <span style="color: #008000;">self</span>.<span style="color: black;">textCursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        cursor.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span>QTextCursor.<span style="color: black;">WordUnderCursor</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">setTextCursor</span><span style="color: black;">&#40;</span>cursor<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Check if the selected word is misspelled and offer spelling</span>
        <span style="color: #808080; font-style: italic;"># suggestions if it is.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">textCursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">hasSelection</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            text = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">textCursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">selectedText</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span>.<span style="color: black;">check</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>:
                spell_menu = QMenu<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Spelling Suggestions'</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">for</span> word <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span>.<span style="color: black;">suggest</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>:
                    action = SpellAction<span style="color: black;">&#40;</span>word, spell_menu<span style="color: black;">&#41;</span>
                    action.<span style="color: black;">correct</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">correctWord</span><span style="color: black;">&#41;</span>
                    spell_menu.<span style="color: black;">addAction</span><span style="color: black;">&#40;</span>action<span style="color: black;">&#41;</span>
                <span style="color: #808080; font-style: italic;"># Only add the spelling suggests to the menu if there are</span>
                <span style="color: #808080; font-style: italic;"># suggestions.</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>spell_menu.<span style="color: black;">actions</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
                    popup_menu.<span style="color: black;">insertSeparator</span><span style="color: black;">&#40;</span>popup_menu.<span style="color: black;">actions</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
                    popup_menu.<span style="color: black;">insertMenu</span><span style="color: black;">&#40;</span>popup_menu.<span style="color: black;">actions</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, spell_menu<span style="color: black;">&#41;</span>
&nbsp;
        popup_menu.<span style="color: black;">exec_</span><span style="color: black;">&#40;</span>event.<span style="color: black;">globalPos</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> correctWord<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, word<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
        Replaces the selected text with word.
        '</span><span style="color: #483d8b;">''</span>
        cursor = <span style="color: #008000;">self</span>.<span style="color: black;">textCursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">beginEditBlock</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        cursor.<span style="color: black;">removeSelectedText</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">insertText</span><span style="color: black;">&#40;</span>word<span style="color: black;">&#41;</span>
&nbsp;
        cursor.<span style="color: black;">endEditBlock</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Highlighter<span style="color: black;">&#40;</span>QSyntaxHighlighter<span style="color: black;">&#41;</span>:
&nbsp;
    WORDS = u<span style="color: #483d8b;">'(?iu)[<span style="color: #000099; font-weight: bold;">\w</span><span style="color: #000099; font-weight: bold;">\'</span>]+'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
        QSyntaxHighlighter.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> setDict<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">dict</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span> = <span style="color: #008000;">dict</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> highlightBlock<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, text<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
        text = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>
&nbsp;
        format = QTextCharFormat<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        format.<span style="color: black;">setUnderlineColor</span><span style="color: black;">&#40;</span>Qt.<span style="color: black;">red</span><span style="color: black;">&#41;</span>
        format.<span style="color: black;">setUnderlineStyle</span><span style="color: black;">&#40;</span>QTextCharFormat.<span style="color: black;">SpellCheckUnderline</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">for</span> word_object <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">finditer</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">WORDS</span>, text<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: #008000;">dict</span>.<span style="color: black;">check</span><span style="color: black;">&#40;</span>word_object.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">setFormat</span><span style="color: black;">&#40;</span>word_object.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                    word_object.<span style="color: black;">end</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - word_object.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, format<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SpellAction<span style="color: black;">&#40;</span>QAction<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
    A special QAction that returns the text in a signal.
    '</span><span style="color: #483d8b;">''</span>
&nbsp;
    correct = pyqtSignal<span style="color: black;">&#40;</span><span style="color: #008000;">unicode</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
        QAction.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">triggered</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: #008000;">self</span>.<span style="color: black;">correct</span>.<span style="color: black;">emit</span><span style="color: black;">&#40;</span>
            <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">text</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>args=<span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span>:
    app = QApplication<span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span>
&nbsp;
    spellEdit = SpellTextEdit<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    spellEdit.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> app.<span style="color: black;">exec_</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span>main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>The SpellTextEdit&#8217;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.</p>
<p>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&#8217;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. &#8220;.!*) as part of the words.</p>
<p>SpellAction is a simple class that allows for the action&#8217;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.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
