|
Hi,
this is a (tentative) patch to let Gnome-Blog
( www.gnome.org/seth/gnome-blog/index.html www.gnome.org/seth/gnome-blog/index.html ) check your spelling.
One can choose the language in the preference section. It uses aspell
and is partly "stolen" from BloGtk ( blogtk.sf.net blogtk.sf.net ).
A screenshot can be find under:
www.ronny-klein.de/linux/archives/gnome-blog-can-spell-checking.html www.ronny-klein.de/linux/archives/gnome-blog-can-spell-checking.html .
And the patch is also available from:
www.ronny-klein.de/linux/archives/gnome-blog-diff-2004-02-15-19-04-37 www.ronny-klein.de/linux/archives/gnome-blog-diff-2004-02-15-19-04-37
Im utterly new to programming, so dont blame me for anything. However,
as a non-native English speaker Id just needed this feature, and it
seems that Seth is waiting until spell checking is integrated into PyGtk
which is, of course, the preferred way to do so.
Ive submitted the patch to Seth, but, Ive gotten no answer yet. So,
Ive decided to post this here because I think this is an eagerly
expected feature. Any suggestion is welcome :o)
How to apply:
1. Download Gnome-Blog 0.7 from the site mentioned above.
2. mv ~/YourDownloadDirectory/gnome-blog-diff-2004-02-15-19-04-37
/PythonLibDirectory/site-packages/gnome-blog/
3. cd /PythonLibDirectory/site-packages/gnome-blog
4. patch < gnome-blog-diff-2004-02-15-19-04-37
5. rm gnome-blog-diff-2004-02-15-19-04-37
Start Gnome-Blog new. Happy Blogging!
Index: blog.py
===================================================================
RCS file: /home/rklein/Home/Downloads/Quellen/cvsroot/gnome-blog/blog.py,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 blog.py
--- blog.py 15 Feb 2004 13:22:43 -0000 1.1.1.1
+++ blog.py 15 Feb 2004 18:04:17 -0000
@@ -2,7 +2,7 @@
def getBlogList (gconf_prefix):
client = gconf.client_get_default()
- (username, password, protocol, url) = _getSettings(client, gconf_prefix)
+ (username, password, protocol, url, lang) = _getSettings(client, gconf_prefix)
blog_backend = _getBlogBackend(protocol)
return blog_backend.getBlogList(username, password, url, client, gconf_prefix)
@@ -10,7 +10,7 @@
def postEntry (title, entry, gconf_prefix):
client = gconf.client_get_default()
- (username, password, protocol, url) = _getSettings(client, gconf_prefix)
+ (username, password, protocol, url, lang) = _getSettings(client, gconf_prefix)
blog_backend = _getBlogBackend(protocol)
return blog_backend.postEntry(username, password,
@@ -24,8 +24,9 @@
password = client.get_string(gconf_prefix + "/blog_password")
protocol = client.get_string(gconf_prefix + "/blog_protocol")
url = client.get_string(gconf_prefix + "/xmlrpc_url")
+ lang = client.get_string(gconf_prefix + "/blog_lang")
- return (username, password, protocol, url)
+ return (username, password, protocol, url, lang)
def _getBlogBackend(protocol):
modulename = "gnomeblog.%s" % (protocol)
Index: blog_poster.py
===================================================================
RCS file: /home/rklein/Home/Downloads/Quellen/cvsroot/gnome-blog/blog_poster.py,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 blog_poster.py
--- blog_poster.py 15 Feb 2004 13:22:43 -0000 1.1.1.1
+++ blog_poster.py 15 Feb 2004 17:02:49 -0000
@@ -8,6 +8,7 @@
from gnomeblog import hig_alert
from gnomeblog import rich_entry
from gnomeblog import blog
+from gnomeblog import spellcheck
gconf_prefix = None
@@ -45,7 +46,8 @@
buttonBox.pack_end(self.postButtonAlignment)
boldToggle = self.blogEntry.createStyleToggle([("weight", pango.WEIGHT_BOLD)], gtk.STOCK_BOLD, "strong")
- italicToggle = self.blogEntry.createStyleToggle([("style", pango.STYLE_ITALIC)], gtk.STOCK_ITALIC, "em")
+ italicToggle = self.blogEntry.createStyleToggle([("style", pango.STYLE_ITALIC)], gtk.STOCK_ITALIC, "em")
+ spellButton = spellcheck.InsertSpellCheckButton(self.blogEntry, gtk.STOCK_SPELL_CHECK, prefs_key)
linkButton = rich_entry.InsertHyperlinkButton(self.blogEntry)
#link_tag = self.blogBuffer.create_tag("a")
@@ -54,7 +56,8 @@
#linkButton = InsertButton
buttonBox.pack_start(boldToggle, expand=gtk.FALSE)
- buttonBox.pack_start(italicToggle, expand=gtk.FALSE)
+ buttonBox.pack_start(italicToggle, expand=gtk.FALSE)
+ buttonBox.pack_start(spellButton, expand=gtk.FALSE)
buttonBox.pack_start(linkButton, expand=gtk.FALSE)
if (extra_button != None):
buttonBox.pack_start(extra_button, expand=gtk.FALSE)
Index: blogger_prefs.py
===================================================================
RCS file: /home/rklein/Home/Downloads/Quellen/cvsroot/gnome-blog/blogger_prefs.py,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 blogger_prefs.py
--- blogger_prefs.py 15 Feb 2004 13:22:43 -0000 1.1.1.1
+++ blogger_prefs.py 15 Feb 2004 17:04:05 -0000
@@ -1,5 +1,7 @@
import gtk
import gconf
+import commands
+import re
import gettext
_ = gettext.gettext
@@ -51,32 +53,42 @@
("MetaWeblog", "MetaWeblog")])
self.blogProtocolLabel = LeftLabel("Blog Protocol:")
+ self.langMenu = gconf_widgets.OptionMenu(gconf_prefix + "/blog_lang")
+ self.langDict = re.compile(([w-]+)).findall(commands.getoutput(aspell dump dicts))
+ self.langUser=[]
+ for self.langDictItem in self.langDict:
+ self.langUser.append((self.langDictItem, self.langDictItem))
+ self.langMenu.setStringValuePairs(self.langUser)
+ self.langMenuLabel = LeftLabel(_("Language:"))
+
self.urlEntry = gconf_widgets.Entry(gconf_prefix + "/xmlrpc_url")
self.urlEntry.set_width_chars(45)
self.urlLabel = LeftLabel(_("Blog Base URL:"))
- self.blogLabel = LeftLabel(_("Blog Name:"))
+ self.blogLabel = LeftLabel(_("Blog Name:"))
self.blogMenu = gconf_widgets.OptionMenu(gconf_prefix + "/blog_id")
self.lookupButton = gtk.Button(_("Lookup Blogs"))
self.lookupButton.connect("clicked", self._onLookupBlogsButton)
- table = gtk.Table(rows=4, columns=3)
+ table = gtk.Table(rows=5, columns=3)
table.set_row_spacings(12)
table.set_col_spacings(6)
table.attach(self.blogProtocolLabel, 0, 1, 0, 1, xoptions=gtk.FILL)
table.attach(self.urlLabel, 0, 1, 1, 2, xoptions=gtk.FILL)
- table.attach(LeftLabel("Username:"), 0, 1, 2, 3, xoptions=gtk.FILL)
- table.attach(LeftLabel("Password:"), 0, 1, 3, 4, xoptions=gtk.FILL)
- table.attach(self.blogLabel, 0, 1, 4, 5, xoptions=gtk.FILL)
+ table.attach(self.langMenuLabel, 0 , 1, 2, 3, xoptions=gtk.FILL)
+ table.attach(LeftLabel("Username:"), 0, 1, 3, 4, xoptions=gtk.FILL)
+ table.attach(LeftLabel("Password:"), 0, 1, 4, 5, xoptions=gtk.FILL)
+ table.attach(self.blogLabel, 0, 1, 5, 6, xoptions=gtk.FILL)
table.attach(self.blogProtocolMenu, 1, 3, 0, 1)
table.attach(self.urlEntry, 1, 3, 1, 2)
- table.attach(gconf_widgets.Entry(gconf_prefix + "/blog_username"), 1, 3, 2, 3)
- table.attach(gconf_widgets.Entry(gconf_prefix + "/blog_password", gtk.TRUE), 1, 3, 3, 4)
- table.attach(self.blogMenu, 1, 2, 4, 5)
- table.attach(self.lookupButton, 2, 3, 4, 5, xoptions=gtk.FILL)
+ table.attach(self.langMenu, 1, 3, 2, 3)
+ table.attach(gconf_widgets.Entry(gconf_prefix + "/blog_username"), 1, 3, 3, 4)
+ table.attach(gconf_widgets.Entry(gconf_prefix + "/blog_password", gtk.TRUE), 1, 3, 4, 5)
+ table.attach(self.blogMenu, 1, 2, 5, 6)
+ table.attach(self.lookupButton, 2, 3, 5, 6, xoptions=gtk.FILL)
vbox = gtk.VBox()
vbox.pack_start(blogTypeBox)
Index: spellcheck.py
===================================================================
RCS file: spellcheck.py
diff -N spellcheck.py
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ spellcheck.py 15 Feb 2004 17:04:53 -0000
@@ -0,0 +1,263 @@
+import gtk
+import commands
+import os
+import re
+import cPickle
+import gconf
+
+from gnomeblog import blog
+
+foo = 0
+
+class InsertSpellCheckButton(gtk.Button):
+ def __init__(self, rich_entry, stock_icon_id, prefs_key):
+ gtk.Button.__init__(self)
+ self.rich_entry = rich_entry
+ self.prefs_key = prefs_key
+ self.buffer = self.rich_entry.get_buffer()
+ self.connect("clicked", self._onClicked)
+ image = gtk.Image()
+ image.set_from_stock(stock_icon_id, gtk.ICON_SIZE_SMALL_TOOLBAR)
+ self.add(image)
+ image.show()
+
+ def _onClicked(self, button):
+ self.SpellCheck = SpellCheck(self.rich_entry, self.prefs_key)
+ self.SpellCheck.displaySpellWindow()
+
+class SpellCheck:
+ def __init__(self, buffer, prefs_key):
+ self.gconf_prefix = prefs_key
+ self.buffer = buffer
+
+ def displaySpellWindow(self):
+
+ self.spellWindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.spellWindow.set_title("Check Spelling")
+ self.spellWindow.set_border_width(6)
+ self.spellWindow.set_size_request(400, 250)
+ self.spellWindow.set_modal(gtk.TRUE)
+
+ self.hbox = gtk.HBox()
+ self.hbox.set_spacing(12)
+
+ self.vboxLeft = gtk.VBox()
+ self.vboxLeft.set_spacing(6)
+ self.vboxRight = gtk.VBox()
+ self.vboxRight.set_spacing(6)
+
+ self.mistakeLabel = gtk.Label("Not in Dictionary:")
+ self.mistakeLabel.set_alignment(0.0, 0.5)
+
+ self.changeLabel = gtk.Label("Change To:")
+ self.changeLabel.set_alignment(0.0, 0.5)
+
+ self.replacementsLabel = gtk.Label("Suggested Replacements:")
+ self.replacementsLabel.set_alignment(0.0, 0.5)
+
+ self.mistakeEntry = gtk.Entry()
+ self.mistakeEntry.set_editable(gtk.FALSE)
+
+ self.changeEntry = gtk.Entry()
+ self.replacementsCombo = gtk.Combo()
+
+ self.vboxLeft.pack_start(self.mistakeLabel, expand=gtk.FALSE)
+ self.vboxLeft.pack_start(self.mistakeEntry, expand=gtk.FALSE)
+ self.vboxLeft.pack_start(self.changeLabel, expand=gtk.FALSE)
+ self.vboxLeft.pack_start(self.changeEntry, expand=gtk.FALSE)
+ self.vboxLeft.pack_start(self.replacementsLabel, expand=gtk.FALSE)
+ self.vboxLeft.pack_start(self.replacementsCombo, expand=gtk.FALSE)
+
+ self.separator = gtk.VSeparator()
+
+ self.changeButton = gtk.Button("C_hange Word")
+ self.ignoreButton = gtk.Button("_Ignore Word")
+ self.addDictButton = gtk.Button("_Add To Dictionary")
+ self.cancelButton = gtk.Button("_Cancel", gtk.STOCK_CANCEL)
+ self.cancelButton.grab_focus()
+
+ self.vboxRight.pack_start(self.changeButton, expand=gtk.FALSE)
+ self.vboxRight.pack_start(self.ignoreButton, expand=gtk.FALSE)
+ self.vboxRight.pack_start(self.addDictButton, expand=gtk.FALSE)
+ self.vboxRight.pack_end(self.cancelButton, expand=gtk.FALSE)
+
+ self.hbox.pack_start(self.vboxLeft)
+ self.hbox.pack_start(self.separator)
+ self.hbox.pack_start(self.vboxRight)
+
+ self.spellWindow.add(self.hbox)
+ self.spellWindow.show_all()
+
+ 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.ignoreButton.connect("clicked", self.advanceIter)
+ self.changeButton.connect("clicked", self.replaceWord)
+ self.addDictButton.connect("clicked", self.addtoCustomDict)
+
+ # Heres were we check for the existence of our custom dictionary. If it doesnt
+ # exist, we create it. If it does, we unpickle the data.
+
+ self.customDictDir = os.path.expanduser(~) + "/.gnome-blog"
+ if os.path.exists(self.customDictDir) == 0:
+ os.mkdir(self.customDictDir)
+
+ self.customDictLocation = self.customDictDir + "/custom.dict"
+
+ if os.path.isfile(self.customDictLocation) == 0:
+ print "Creating a new custom dictionary"
+ self.customDict = open(self.customDictLocation, "w")
+ self.jargon = ["blog", "Blogger", "trackback", "pingback"]
+ cPickle.dump(self.jargon, self.customDict)
+ self.customDict.close()
+ else:
+ self.customDict = open(self.customDictLocation, "rw")
+ self.jargon = cPickle.load(self.customDict)
+ self.customDict.close()
+
+ self.spellWindow.show()
+
+ self.writeFile()
+
+ def writeFile(self):
+ self.bodyView = self.buffer
+ self.buffer = self.bodyView.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.fileLocation = "/tmp/" + str(os.getuid()) + ".gnomeblog.tmp"
+ self.file = open(self.fileLocation, "w")
+ self.file.write(self.body)
+ self.file.close()
+
+ # 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):
+
+ # Heres where we make our call to aspell to process our temporary file
+ client = gconf.client_get_default()
+ self.blog_lang = blog._getSettings(client, self.gconf_prefix)[4]
+ self.spelling = commands.getoutput(aspell -H --encoding=utf-8 -a < + self.fileLocation + --master= + self.blog_lang)
+ self.wordlist = []
+ self.corrections = []
+
+ # This code uses regular expressions to strip out the HTML from our results.
+ # It has been shamelessly cribbed from www.intertwingly.net/code/mombo/spellcheck.py www.intertwingly.net/code/mombo/spellcheck.py .
+ self.spelling = re.compile(^& (w+) d+ d+: (.*),re.M).findall(self.spelling)
+
+ # 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)
+ errDialog.set_border_width(6)
+ errDialog.set_modal(gtk.TRUE)
+ 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.iterator = 0
+ self.populateSpellWindow()
+
+ def populateSpellWindow(self):
+
+ try:
+ self.mistakeEntry.set_text(self.wordlist[self.iterator])
+
+ self.suggestions = self.corrections[self.iterator]
+
+ self.replacementsCombo.set_popdown_strings(self.suggestions)
+
+ self.setMark(self.wordlist[self.iterator])
+
+ except:
+ pass
+
+ def replaceWord(self, widget):
+
+ 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)
+ errDialog.set_border_width(6)
+ errDialog.set_modal(gtk.TRUE)
+ 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(self.customDictLocation, "w"))
+ self.customDict.close()
+
+ self.advanceIter(widget)
+
+ def windowHider(self, widget, foo):
+ # Strike me down, and Ill become invisible like Obi-Wan did...
+ widget.hide()
+ return gtk.FALSE
+
+ def setMark(self, wordToMark):
+ 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)
|