Viewing file: pygtk-demo.py (10.85 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/env python ''' $Id: pygtk-demo.py,v 1.8 2004/10/01 23:35:38 finlay Exp $
pygtk-demo.py 2004-07-18: Some enhancements for building the demolist like in gtk-demos of the gtk+ distribution. 2004-07-22: Simple syntaxhighlighting implemented, based on the tokenizer-module. '''
import string import re try: import pygtk pygtk.require('2.0') except ImportError: pass import gobject import gtk import pango
# use for simple syntax highlighting ;-) import tokenize import keyword
import demos D_TEMPL = '%sDemo'
# Some programmatic definition for the testgtk_demos list. This avoids extra # maintenance if the demo list grows up. The current definition requires # a class or function with a swapped case name+'Demo' like in the doc string. # Swapped case is build from the __doc__-string programatically. child_demos = {} testgtk_demos = [] for descr, mod in demos.demo_list: # Find some categorized demos try: main, child = descr.split('/') except ValueError: # No, only one application demo_class = D_TEMPL % re.sub('(\S+) *', lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()), descr) testgtk_demos.append((descr, mod, demo_class)) else: # Ok. Some more testing demo_class = D_TEMPL % re.sub('(\S+) *', lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()), child) try: # Applicationgroup already defined? child_demos[main.upper()].append((child, mod, demo_class)) except KeyError: # No. Start a new category child_demos.setdefault(main.upper(), []).append((child, mod, demo_class)) testgtk_demos.append((main, None, None, child_demos[main.upper()]))
( TITLE_COLUMN, MODULE_COLUMN, FUNC_COLUMN, ITALIC_COLUMN ) = range(4)
CHILDREN_COLUMN = 3
class InputStream(object): ''' Simple Wrapper for File-like objects. [c]StringIO doesn't provide a readline function for use with generate_tokens. Using a iterator-like interface doesn't succeed, because the readline function isn't used in such a context. (see <python-lib>/tokenize.py) ''' def __init__(self, data): self.__data = [ '%s\n' % x for x in data.splitlines() ] self.__lcount = 0 def readline(self): try: line = self.__data[self.__lcount] self.__lcount += 1 except IndexError: line = '' self.__lcount = 0 return line
class PyGtkDemo(gtk.Window): info_buffer = None source_buffer = None module_cache = {}
def __init__(self): gtk.Window.__init__(self) self.set_title("PyGTK+ Code Demos") self.connect('destroy', lambda w: gtk.main_quit()) self.set_default_size(800, 400)
hbox = gtk.HBox(False, 3) self.add(hbox)
treeview = self.__create_treeview() hbox.pack_start(treeview, False, False)
self.notebook = gtk.Notebook() hbox.pack_start(self.notebook, expand=True)
scrolled_window, self.info_buffer = self.__create_text(False) self._new_notebook_page(scrolled_window, '_Info') tag = self.info_buffer.create_tag('title') tag.set_property('font', 'Sans 18')
scrolled_window, self.source_buffer = self.__create_text(True) self._new_notebook_page(scrolled_window, '_Source') tag = self.source_buffer.create_tag('source') tag.set_property('font', 'monospace') tag.set_property('pixels_above_lines', 0) tag.set_property('pixels_below_lines', 0) tag = self.source_buffer.create_tag('keyword', foreground='#00007F', weight=pango.WEIGHT_BOLD) tag = self.source_buffer.create_tag('string', foreground='#7F007F') tag = self.source_buffer.create_tag('comment', foreground='#007F00', style=pango.STYLE_ITALIC)
self.show_all()
def run(self): gtk.main()
def _new_notebook_page(self, widget, label): l = gtk.Label('') l.set_text_with_mnemonic(label) self.notebook.append_page(widget, l)
def __create_treeview(self): model = gtk.TreeStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN )
treeview = gtk.TreeView(model) selection = treeview.get_selection() selection.set_mode(gtk.SELECTION_BROWSE) treeview.set_size_request(200, -1)
for module in testgtk_demos: iter = model.append(None) model.set(iter, TITLE_COLUMN, module[TITLE_COLUMN], MODULE_COLUMN, module[MODULE_COLUMN], FUNC_COLUMN, module[FUNC_COLUMN], ITALIC_COLUMN, False )
try: children = module[CHILDREN_COLUMN] for child_module in children: child_iter = model.append(iter) model.set(child_iter, TITLE_COLUMN, child_module[TITLE_COLUMN], MODULE_COLUMN, child_module[MODULE_COLUMN], FUNC_COLUMN, child_module[FUNC_COLUMN], ITALIC_COLUMN, False ) except IndexError: pass
cell = gtk.CellRendererText() cell.set_property('style', pango.STYLE_ITALIC)
column = gtk.TreeViewColumn("Widget (double click for demo)", cell, text=TITLE_COLUMN, style_set=ITALIC_COLUMN)
treeview.append_column(column)
selection.connect('changed', self.selection_changed_cb) treeview.connect('row-activated', self.row_activated_cb)
treeview.expand_all()
return treeview
def __create_text(self, is_source=False): scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.set_shadow_type(gtk.SHADOW_IN)
text_view = gtk.TextView() scrolled_window.add(text_view)
buffer = gtk.TextBuffer(None) text_view.set_buffer(buffer) text_view.set_editable(False) text_view.set_cursor_visible(False)
text_view.set_wrap_mode(not is_source)
return scrolled_window, buffer
def row_activated_cb(self, treeview, path, column): model = treeview.get_model() iter = model.get_iter(path) module_name = model.get_value(iter, MODULE_COLUMN) func_name = model.get_value(iter, FUNC_COLUMN) italic_value = model.get_value(iter, ITALIC_COLUMN) try: self.module_cache[module_name].present() except KeyError: module = getattr(demos, module_name) model.set(iter, ITALIC_COLUMN, not italic_value) cmd = 'demos.%s.%s' % (module_name, func_name) #print cmd window = eval(cmd)(self) if window: window.connect('destroy', self.window_closed_cb, model, path) self.module_cache[module_name] = window
def selection_changed_cb(self, selection): model, iter = selection.get_selected() if not iter: return False
name = model.get_value(iter, MODULE_COLUMN) self.load_module(name)
def window_closed_cb (self, window, model, path): iter = model.get_iter(path) module_name = model.get_value(iter, MODULE_COLUMN) del self.module_cache[module_name] italic_value = model.get_value(iter, ITALIC_COLUMN) if italic_value: model.set(iter, ITALIC_COLUMN, not italic_value)
def read_module(self, module): filename = module.__file__ if filename[-4:] == '.pyc': filename = filename[:-1] fd = open(filename) return fd.read()
def insert_documentation(self, module): buffer = self.info_buffer iter = buffer.get_iter_at_offset(0)
lines = string.split(module.__doc__ or '', '\n') buffer.insert(iter, lines[0]) start = buffer.get_iter_at_offset(0) buffer.apply_tag_by_name('title', start, iter) buffer.insert(iter, '\n') for line in lines[1:]: buffer.insert(iter, line) buffer.insert(iter, '\n')
def clear_buffers(self): start, end = self.info_buffer.get_bounds() self.info_buffer.delete(start, end)
start, end = self.source_buffer.get_bounds() self.source_buffer.delete(start, end)
def insert_source(self, data): source_buffer = self.source_buffer iter = source_buffer.get_iter_at_offset(0)
last_erow, last_ecol = 0, 0 was_newline = False # multiline statement detection for x in tokenize.generate_tokens(InputStream(data).readline): # x has 5-tuples tok_type, tok_str = x[0], x[1] srow, scol = x[2] erow, ecol = x[3]
# The tokenizer 'eats' the whitespaces, so we have to insert this again # if needed. if srow == last_erow: # Same line, spaces between statements if scol != last_ecol: source_buffer.insert_with_tags_by_name(iter, ' '*(scol-last_ecol), 'source') else: # New line. # First: Detect multiline statements. There is no special in the tokenizer stream. if was_newline is False and last_erow != 0: source_buffer.insert_with_tags_by_name(iter, ' \\\n', 'source') # new line check if it starts with col 0 if scol != 0: source_buffer.insert_with_tags_by_name(iter, ' '*scol, 'source') last_erow = erow last_ecol = ecol
if tok_type == tokenize.COMMENT: was_newline = True # newline is in tok_str included. source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'comment') continue elif tok_type == tokenize.NAME: if tok_str in keyword.kwlist: source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'keyword') continue elif tok_type == tokenize.STRING: source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'string') continue
# No special format for use. Check for newline. was_newline = tok_type in (tokenize.NEWLINE, tokenize.NL) source_buffer.insert_with_tags_by_name(iter, tok_str, 'source')
def load_module(self, name): self.clear_buffers() if name is None: return module = getattr(demos, name) if module.__doc__: self.insert_documentation(module)
source = self.read_module(module) self.insert_source(source)
if __name__ == '__main__': PyGtkDemo().run()
|