--- author: '' category: '' date: 2009/09/22 04:01 description: '' link: '' priority: '' slug: BB832 tags: programming, pyqt, python, qt, rst2pdf title: Yak Shavings for September 22, 2009 type: text updated: 2009/09/22 04:01 url_type: '' --- **yak shaving** (idiomatic) Any apparently useless activity which, by allowing you to overcome intermediate difficulties, allows you to solve a larger problem. This yak is starting to look better. For my second pile of yak shavings: turning QPlainTextEdit_ into a decent editing widget for programmers. As work advanced in my rst2pdf_ editor (BTW: need a name!), it became obvious that the piece of the UI the user will use most is just a couple of plain text editors. Qt comes with a widget for that, of course, called QPlainTextEdit_. However, it's a very, very bad widget for programmers. Here's the least I wanted: 1) Syntax highlighting for two languages: restructured text and javascript. This yak is already shaved_. 2) Line numbers 3) Current line highlight 4) Error highlight when it makes sense (like, in the stylesheet) One way to achieve this would be to dump QPlainTextEdit and use QSciScintilla_ which is the basis for the code editor in eric_ and (another version) in scite_. However, I experienced a bad bug in QSciScintilla, where I can't type accented characters! Without that, (decent) spanish is impossible, and the bug seems to be at least two years old, so... no go. So, did I get those features? I say yes! Here is the video (yes, I am getting addicted to making these, since qt-recordmydesktop makes them so easy ;-): .. raw:: html The basis for this is the `Code Editor example `_ that comes with Qt itself, plus a bit of my own handywork. First, I ported Code Editor from C++ to Python, which was very simple and took a few minutes. That takes care of points 2 and 3. Then, the syntax highlight was plugged in, which was point 1. Then, how about realtime javascript validation? Easy using simplejson! Just make sure to run this whenever you want validation (I do it on every keystroke). Replace self.ui.style.toPlainText with whatever your widget is called, of course: .. code-block:: python def validateStyle(self): style=unicode(self.ui.style.toPlainText()) #no point in validating an empty string if not style.strip(): return pos=None try: json.loads(style) except ValueError, e: s=str(e) print s if s == 'No JSON object could be decoded': pos=0 elif s.startswith('Expecting '): pos=int(s.split(' ')[-1][:-1]) else: print 'UNKNOWN ERROR' # This makes a red bar appear in the line # containing position pos self.ui.style.highlightError(pos) ``highlightError(pos)`` simply stores pos in the Code Editor, which will draw a red bar in that line, the same way it highlights the current line. And that's it. Here is the code for `codeeditor.py`_ .. _codeeditor.py: //ralsina.me/static/codeeditor.py .. _scite: http://www.scintilla.org/SciTE.html .. _eric: http://eric-ide.python-projects.org/ .. _QSciScintilla: http://www.riverbankcomputing.co.uk/static/Docs/QScintilla2/classQsciScintilla.html .. _shaved: //ralsina.me/weblog/2009/09/21.html#BB831 .. _qplaintextedit: http://doc.trolltech.com/4.5/qplaintextedit.html#details .. _rst2pdf: http://rst2pdf.googlecode.com