#!/usr/bin/env python
# BloGTK Version 1.0
# Spell Check Routines - spellcheck.py
# (C)2004 Jay Reding
# Code released under the terms of the BSD License. (See file LICENSE)
import gtk
import commands
import os
import re
import cPickle
foo = 0
class SpellCheck:
def displaySpellWindow(self, mainGlade):
self.iterator = 0
# 0.8 - Here's where we display the spell checker window.
self.mainGlade = mainGlade
# 0.8 - Pull our widgets from the Glade file
self.spellWindow = self.mainGlade.get_widget("spellingWindow")
self.cancelButton = self.mainGlade.get_widget("cancelButton")
self.mistakeEntry = self.mainGlade.get_widget("mistakeEntry")
self.replacementsCombo = self.mainGlade.get_widget("replacementsCombo")
self.changeEntry = self.mainGlade.get_widget('changeEntry')
self.ignoreButton = self.mainGlade.get_widget('ignoreButton')
self.spellWindow.connect_object("delete_event", self.windowHider, self.spellWindow)
self.cancelButton.connect_object("clicked", self.windowHider, self.spellWindow, foo)
self.replacementsCombo.entry.connect_object("changed", self.fillReplacement, foo)
self.mainGlade.signal_autoconnect({'on_ignoreButton_clicked': self.advanceIter})
self.mainGlade.signal_autoconnect({'on_changeButton_clicked': self.replaceWord})
self.mainGlade.signal_autoconnect({'on_addDictButton_clicked': self.addtoCustomDict})
# 0.8 - Here's were we check for the existence of our custom dictionary. If it doesn't
# exist, we create it. If it does, we unpickle the data.
if os.path.isfile(os.path.expanduser('~') + "/.BloGTK/custom.dict") == 0:
print "Creating a new custom dictionary"
self.customDict = open(os.path.expanduser('~') + "/.BloGTK/custom.dict", "w")
self.jargon = ["blog", "Blogger", "trackback", "pingback"]
cPickle.dump(self.jargon, self.customDict)
self.customDict.close()
else:
self.customDict = open(os.path.expanduser('~') + "/.BloGTK/custom.dict", "rw")
self.jargon = cPickle.load(self.customDict)
self.customDict.close()
self.spellWindow.show()
self.writeFile()
def writeFile(self):
# 0.8 - This is where we write out the body of our post to a temporary file.
# 0.96 - We need to spellcheck whatever window is currently selected, in
# case the user has utilized the Extended or Excerpt fields. Until I can
# figure a way of checking them all simultaneously, we'll have the option
# of checking whatever field is currently selected.
self.bodyView = self.mainGlade.get_widget('bodyView')
self.extendedView = self.mainGlade.get_widget('extendedView')
self.excerptView = self.mainGlade.get_widget('excerptView')
if self.bodyView.is_focus() == 1:
self.selectedWindow = self.bodyView
elif self.extendedView.is_focus() == 1:
self.selectedWindow = self.extendedView
elif self.excerptView.is_focus() == 1:
self.selectedWindow = self.excerptView
# 1.1 - If none of the right fields are selected, we'll assume they want the
# main entry field.
else:
self.bodyView.set_focus();
self.selectedWindow = self.bodyView
self.buffer = self.selectedWindow.get_buffer()
self.startiter = self.buffer.get_start_iter()
self.enditer = self.buffer.get_end_iter()
self.body = self.buffer.get_text(self.startiter, self.enditer, include_hidden_chars=1)
self.file = open(os.path.expanduser('~') + "/.BloGTK/temp", "w")
self.file.write(self.body)
self.file.close()
# 0.8 - We need to set our iter for parsing the entry at the beginning of the TextBuffer.
self.entryIter = self.startiter
self.spellcheck()
def spellcheck(self):
# 0.8 - Here's where we make our call to aspell to process our temporary file
# Patch: the -H option shall filter the html-code. Somehow the encoding should
# be set. As a fedora user I needed utf-8 here.
self.spelling = commands.getoutput('aspell -H --encoding=utf-8 -a < ' + os.path.expanduser('~') + "/.BloGTK/temp")
self.wordlist = []
self.corrections = []
# 0.8 - This code uses regular expressions to strip out the HTML from our results.
# It has been shamelessly cribbed from http://www.intertwingly.net/code/mombo/spellcheck.py.
self.spelling = re.compile('^& (\w+) \d+ \d+: (.*)',re.M).findall(self.spelling)
# 0.8 - Now we create two lists - one list has our spelling mistakes, the other has our list
# of suggested replacements.
for found,suggest in self.spelling:
if found in self.jargon: continue
self.wordlist.append(found)
self.corrections.append(suggest.split(", "))
if self.wordlist == []:
self.windowHider(self.spellWindow, foo)
errDialog = gtk.Dialog(title="Spell Check", parent=self.spellWindow, flags=0)
button2 = gtk.Button(stock=gtk.STOCK_OK)
button2.connect_object("clicked", gtk.Widget.destroy, errDialog)
errDialog.action_area.pack_start(button2, gtk.TRUE, gtk.TRUE, 0)
button2.show()
errLabel = gtk.Label("No misspelled words found.")
errDialog.vbox.pack_start(errLabel, gtk.TRUE, gtk.TRUE, 2)
errLabel.show()
errDialog.show()
else:
self.populateSpellWindow()
def populateSpellWindow(self):
# 0.8 - Oddly enough, self.iterator is getting assigned multiple values rather than being
# cleared. If you spell check more than once errors start popping up. This is a temporary
# fix until that weirdness gets fixed.
try:
self.mistakeEntry.set_text(self.wordlist[self.iterator])
self.suggestions = self.corrections[self.iterator]
self.replacementsCombo.set_popdown_strings(self.suggestions)
# Patch: We use a function here. I couldn't follow your above and below described problem.
# For me it works without your counter. The problem I've found was that you easily
# could loose your mark in the blog window if you click in the spell check window.
# This works against your replacement mechanism. That's why. Let us just repeat the
# .setMark when we finally want to replace the word. See replaceWord.
self.setMark(self.wordlist[self.iterator])
except:
pass
def replaceWord(self, widget):
# 0.8 - For some bizarre reason, PyGTK keeps doubling or even tripling the number of
# times text is inserted. This is a major problem, so here's an ugly but workable hack
# that fixes it: we create an iterator, then advance it when text is inserted, making
# sure that the function only gets called when the iterator is at 1. At least this way
# everything seems to work.
# Patch: Now we go for sure and mark the word again. The user cannot interfere anymore.
self.setMark(self.wordlist[self.iterator])
self.buffer.delete_selection(0,0)
self.buffer.insert_at_cursor(self.changeEntry.get_text())
self.entryIter = self.buffer.get_iter_at_mark(self.insMark)
self.advanceIter(foo)
def fillReplacement(self, widget):
self.replacementSuggestion = self.replacementsCombo.entry.get_text()
self.changeEntry.set_text(self.replacementSuggestion)
def advanceIter(self, widget):
self.iterator = self.iterator + 1
self.entryIter = self.buffer.get_iter_at_mark(self.selMark)
if self.iterator == len(self.wordlist):
self.windowHider(self.spellWindow, foo)
errDialog = gtk.Dialog(title="Spell Check", parent=None, flags=0)
button2 = gtk.Button(stock=gtk.STOCK_OK)
button2.connect_object("clicked", gtk.Widget.destroy, errDialog)
errDialog.action_area.pack_start(button2, gtk.TRUE, gtk.TRUE, 0)
button2.show()
errLabel = gtk.Label("Spell Check Complete.")
errDialog.vbox.pack_start(errLabel, gtk.TRUE, gtk.TRUE, 2)
errLabel.show()
errDialog.show()
else:
self.populateSpellWindow()
def addtoCustomDict(self, widget):
self.word = self.mistakeEntry.get_text()
self.jargon.append(self.mistakeEntry.get_text())
cPickle.dump(self.jargon, open(os.path.expanduser('~') + "/.BloGTK/custom.dict", "w"))
self.customDict.close()
self.advanceIter(widget)
def windowHider(self, widget, foo):
# I'm outta here!
widget.hide()
return gtk.FALSE
def setMark(self, wordToMark):
# Patch: This function is basically the old code just implemented as a function
self.selMark = self.buffer.get_selection_bound()
self.insMark = self.buffer.get_insert()
self.match_start, self.match_end = self.entryIter.forward_search(self.wordlist[self.iterator], gtk.TEXT_SEARCH_TEXT_ONLY)
self.buffer.move_mark(self.selMark, self.match_end)
self.buffer.move_mark(self.insMark, self.match_start)
self.bodyView.scroll_mark_onscreen(self.insMark)
def setDict(self):
# Patch: A way to check for installed dicts which then could be set in the preference settings.
# Good for all the non-native blog writers ;-)
self.installedDicts = re.compile('([\w-]+)').findall(commands.getoutput('aspell dump dicts'))
# Patch: One would then have to change the aspell command to something like that:
# aspell -H --encoding=utf-8 -a < ' + self.DictLocation + ' --master=' + self.blog_lang)
|