[gedit-list] restoutline plugin



  Hello:
  I just wrote a plugin to build an outline of a ReStructuredText (rst)
document, based upon pythonoutline by Dieter Verfaillie. I'm attaching
the relevant files, hope you get them. I'd love to have some feedback.
  Regards
[Gedit Plugin]
Loader=python
Module=rstoutline
IAge=2
Name=ReST outline
Description=ResT header outline
Authors=Pablo Angulo based upon pythonoutline by Dieter Verfaillie
Copyright=Copyright © 2011 Pablo Angulo
Website=http://www.uam.es/personal_pdi/ciencias/pangulo/
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# This file is part of the ReST Outline Plugin for Gedit
# based upon Python Outline Plugin for Gedit
# Copyright (C) 2007 Dieter Verfaillie <dieterv optionexplicit be>
# Copyright (C) 2011 Pablo Angulo <pangard cancamusa net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import gtk
import gedit

import gc
import time

class ReSTParser (object):
    '''DocString
    '''
    header_chars = ['=', '-', '`', ':', "'", '"', '~', '^', '_', '*', '+', '#', '<', '>']

    def __init__(self, treemodel):
        self.treemodel = treemodel
        
    def parse(self, text):
        last = None
        parents = []
        levels  = []
        for j,line in enumerate(text.splitlines()):
            first = line[0] if line else ''
            if last and first in self.header_chars and all(c==first for c in line):
                if first not in levels:
                    levels.append(first)
                i = levels.index(first)                
                while i>len(parents):
                    parents.append(self.treemodel.append(parents[-1] if parents else None, 
                                         ('?', 'empty node', str(j-1))))
                if i<len(parents):
                    parents = parents[:i]
                parents.append(self.treemodel.append(parents[-1] if parents else None, 
                                  (first, last, str(j-1))))
                

            last = line



class OutlineBox(gtk.VBox):
    def __init__(self):
        gtk.VBox.__init__(self)

        scrolledwindow = gtk.ScrolledWindow()
        scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrolledwindow.show()
        self.pack_start(scrolledwindow, True, True, 0)

        self.treeview = gtk.TreeView()
        self.treeview.set_rules_hint(True)
        self.treeview.set_headers_visible(False)
        self.treeview.set_enable_search(True)
        self.treeview.set_reorderable(False)
        self.treeselection = self.treeview.get_selection()
        self.treeselection.connect('changed', self.on_selection_changed)
        scrolledwindow.add(self.treeview)

        col = gtk.TreeViewColumn()
        col.set_title('name')
        col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        col.set_expand(True)
        render_text = gtk.CellRendererText()
#        render_text.set_property('cell-background', '#CCCCCC')
        render_text.set_property('xpad', 5)
        render_text.set_property('xalign', 0)
        render_text.set_property('yalign', 0.5)
        col.pack_start(render_text, expand=False)
        col.add_attribute(render_text, 'text', 0)
        render_text = gtk.CellRendererText()
        render_text.set_property('xalign', 0)
        render_text.set_property('yalign', 0.5)
        col.pack_start(render_text, expand=True)
        col.add_attribute(render_text, 'text', 1)
        self.treeview.append_column(col)
        self.treeview.set_search_column(1)

        self.label = gtk.Label()
        self.pack_end(self.label, False)

        self.expand_classes = False
        self.expand_functions = False

        self.show_all()


    def on_row_has_child_toggled(self, treemodel, path, iter):
#        elif self.expand_functions and treemodel.get_value(iter, 2) == 'Function':
        self.treeview.expand_row(path, False)

    def on_selection_changed(self, selection):
        model, iter = selection.get_selected()
        if iter:
            lineno = model.get_value(iter, 2)
            if not lineno: return
            lineno = int(lineno)
            name = model.get_value(iter, 1)
            linestartiter = self.buffer.get_iter_at_line(lineno)
            lineenditer = self.buffer.get_iter_at_line(lineno)
            lineenditer.forward_line()
            line = self.buffer.get_text(linestartiter, lineenditer)
            self.buffer.select_range(linestartiter, lineenditer)
            self.view.scroll_to_cursor()

    def create_treemodel(self):
        #Header char, header, lineno
        treemodel = gtk.TreeStore(str, str, str)
        handler = treemodel.connect('row-has-child-toggled', self.on_row_has_child_toggled)
        return treemodel, handler

    def parse(self, view, buffer):
        self.view = view
        self.buffer = buffer

        startTime = time.time()

        treemodel, handler = self.create_treemodel()
        self.treeview.set_model(treemodel)
        self.treeview.freeze_child_notify()

        bounds = self.buffer.get_bounds()
        text   = self.buffer.get_text(bounds[0], bounds[1]).replace('\r', '\n') + '\n'
        rstparser = ReSTParser(treemodel)
        rstparser.parse(text)
        gc.collect()

        treemodel.disconnect(handler)
        self.treeview.thaw_child_notify()

        stopTime = time.time()
        self.label.set_text('Outline created in ' + str(float(stopTime - startTime)) + ' s')


class PythonOutlinePluginInstance(object):
    def __init__(self, plugin, window):
        self._window = window
        self._plugin = plugin

        self._insert_panel()

    def deactivate(self):
        self._remove_panel

        self._window = None
        self._plugin = None

    def update_ui(self):
        document = self._window.get_active_document()
        if document:
            print document.get_uri(), document.is_untouched(), document.get_modified()
        if document and document.get_modified():
            uri = str(document.get_uri())
            if document.get_mime_type() == 'text/restructured' or uri.endswith('.rst'):
                self.outlinebox.parse(self._window.get_active_view(), document)
            else:
                treemodel, handler = self.outlinebox.create_treemodel()
                self.outlinebox.treeview.set_model(treemodel)

    def _insert_panel(self):
        self.panel = self._window.get_side_panel()
        self.outlinebox = OutlineBox()
        self.panel.add_item(self.outlinebox, "ReST Outline", gtk.STOCK_INDEX)

    def _remove_panel(self):
        self.panel.destroy()


class PythonOutlinePlugin(gedit.Plugin):
    def __init__(self):
        gedit.Plugin.__init__(self)
        self._instances = {}

    def activate(self, window):
        self._instances[window] = PythonOutlinePluginInstance(self, window)

    def deactivate(self, window):
        self._instances[window].deactivate()
        del self._instances[window]

    def update_ui(self, window):
        self._instances[window].update_ui()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]