# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: proycon@anaproy.nl-20120425200611-ncmtwh12n9c34x03
# target_branch: bzr+ssh://bazaar.launchpad.net/%2Bbranch/scribes/
# testament_sha1: a967c7ecb0a07abe8eb22325ec222c13cf51a7f0
# timestamp: 2012-04-25 22:22:37 +0200
# base_revision_id: mystilleef@gmail.com-20111118163400-\
# g4ldqge3dg50i90o
#
# Begin patch
=== added directory 'LanguagePlugins/CPPSymbolBrowser'
=== added file 'LanguagePlugins/CPPSymbolBrowser/Manager.py'
--- LanguagePlugins/CPPSymbolBrowser/Manager.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/Manager.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,63 @@
+from gobject import GObject, SIGNAL_RUN_LAST, TYPE_NONE
+from gobject import TYPE_PYOBJECT
+
+class Manager(GObject):
+
+ __gsignals__ = {
+ "destroy": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
+ "update": (SIGNAL_RUN_LAST, TYPE_NONE, (TYPE_PYOBJECT,)),
+ "show-window": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
+ "hide-window": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
+ }
+
+ def __init__(self, editor):
+ GObject.__init__(self)
+ self.__init_attributes(editor)
+ from Updater import Updater
+ Updater(editor, self)
+ from TreeView import TreeView
+ TreeView(editor, self)
+ from Window import Window
+ Window(editor, self)
+
+ def __init_attributes(self, editor):
+ self.__editor = editor
+ from os.path import join, split
+ current_folder = split(globals()["__file__"])[0]
+ glade_file = join(current_folder, "SymbolBrowser.glade")
+ from gtk.gdk import pixbuf_new_from_file
+ class_pixbuf = join(current_folder, "class.png")
+ self.__class_pixbuf = pixbuf_new_from_file(class_pixbuf)
+ function_pixbuf = join(current_folder, "function.png")
+ self.__function_pixbuf = pixbuf_new_from_file(function_pixbuf)
+ method_pixbuf = join(current_folder, "method.png")
+ self.__method_pixbuf = pixbuf_new_from_file(method_pixbuf)
+ from gtk.glade import XML
+ self.__glade = XML(glade_file, "Window", "scribes")
+ return
+
+ def __get_glade(self):
+ return self.__glade
+
+ def __get_class_pixbuf(self):
+ return self.__class_pixbuf
+
+ def __get_function_pixbuf(self):
+ return self.__function_pixbuf
+
+ def __get_method_pixbuf(self):
+ return self.__method_pixbuf
+
+ glade = property(__get_glade)
+ class_pixbuf = property(__get_class_pixbuf)
+ function_pixbuf = property(__get_function_pixbuf)
+ method_pixbuf = property(__get_method_pixbuf)
+
+ def show_browser(self):
+ self.emit("show-window")
+ return
+
+ def destroy(self):
+ self.emit("destroy")
+ del self
+ return
=== added file 'LanguagePlugins/CPPSymbolBrowser/SymbolBrowser.glade'
--- LanguagePlugins/CPPSymbolBrowser/SymbolBrowser.glade 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/SymbolBrowser.glade 2012-04-25 20:06:11 +0000
@@ -0,0 +1,44 @@
+
+
+
+
+
+ 10
+ Classes and Functions
+ ScribesSymbolBrowser
+ center-on-parent
+ 350
+ 400
+ True
+ scribes
+ dialog
+ True
+ True
+ True
+ static
+ ScribesSymbolBrowser
+
+
+ True
+ True
+ never
+ automatic
+ in
+
+
+ True
+ False
+ True
+ True
+ True
+ False
+ True
+ 1
+ True
+ 2
+
+
+
+
+
+
=== added file 'LanguagePlugins/CPPSymbolBrowser/TreeView.py'
--- LanguagePlugins/CPPSymbolBrowser/TreeView.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/TreeView.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,175 @@
+class TreeView(object):
+
+ def __init__(self, editor, manager):
+ self.__init_attributes(editor, manager)
+ self.__set_properties()
+ self.__sigid1 = self.__manager.connect("destroy", self.__destroy_cb)
+ self.__sigid2 = self.__manager.connect("update", self.__update_cb)
+ self.__sigid3 = self.__treeview.connect("row-activated", self.__row_activated_cb)
+ from gobject import idle_add
+ idle_add(self.__precompile_method, priority=9999)
+
+ def __init_attributes(self, editor, manager):
+ self.__manager = manager
+ self.__symbols = None
+ self.__parent = None
+ self.__editor = editor
+ self.__treeview = manager.glade.get_widget("TreeView")
+ self.__model = self.__create_model()
+ self.__column = self.__create_column()
+ self.__depth_level_iter = None
+ return
+
+ def __set_properties(self):
+ self.__treeview.append_column(self.__column)
+ self.__treeview.map()
+ return
+
+ def __create_model(self):
+ from gtk import TreeStore
+ from gtk.gdk import Pixbuf
+ model = TreeStore(int, str, str, int, Pixbuf)
+ return model
+
+ def __create_column(self):
+ from gtk import TreeViewColumn, CellRendererText, CellRendererPixbuf
+ from gtk import TREE_VIEW_COLUMN_FIXED
+ column = TreeViewColumn()
+ pixbuf_renderer = CellRendererPixbuf()
+ text_renderer = CellRendererText()
+ column.pack_start(pixbuf_renderer, False)
+ column.pack_start(text_renderer, False)
+ column.set_sizing(TREE_VIEW_COLUMN_FIXED)
+ column.set_resizable(False)
+ column.set_attributes(text_renderer, text=1)
+ column.set_attributes(pixbuf_renderer, pixbuf=4)
+ return column
+
+ def __populate_model(self, symbols):
+ self.__treeview.set_property("sensitive", False)
+ if self.__symbols != symbols:
+ self.__treeview.window.freeze_updates()
+ from copy import copy
+ self.__symbols = copy(symbols)
+ self.__treeview.set_model(None)
+ self.__model.clear()
+ indentation = self.__get_indentation_levels(symbols)
+ append = self.__append_symbols
+ for item in symbols:
+ append(item, indentation)
+ self.__treeview.set_model(self.__model)
+ self.__treeview.window.thaw_updates()
+ self.__select_row()
+ self.__treeview.set_property("sensitive", True)
+ self.__treeview.grab_focus()
+ return False
+
+ def __select_row(self):
+ current_line = self.__editor.cursor.get_line() + 1
+ get_line = lambda x: x[0]
+ lines = [get_line(symbol) for symbol in self.__symbols]
+ lines.reverse()
+ found_line = False
+ for line in lines:
+ if not (current_line == line or current_line > line): continue
+ found_line = True
+ current_line = line
+ break
+ if found_line:
+ self.__select_line_in_treeview(current_line)
+ else:
+ self.__editor.select_row(self.__treeview)
+ return
+
+ def __select_line_in_treeview(self, line):
+ iterator = self.__model.get_iter_root()
+ while True:
+ if self.__model.get_value(iterator, 0) == line: break
+ if self.__model.iter_has_child(iterator):
+ parent_iterator = iterator
+ found_line = False
+ for index in xrange(self.__model.iter_n_children(iterator)):
+ iterator = self.__model.iter_nth_child(parent_iterator, index)
+ if not (self.__model.get_value(iterator, 0) == line): continue
+ found_line = True
+ break
+ if found_line: break
+ iterator = parent_iterator
+ iterator = self.__model.iter_next(iterator)
+ if iterator is None: break
+# try:
+ path = self.__model.get_path(iterator)
+ self.__treeview.expand_to_path(path)
+ self.__treeview.get_selection().select_iter(iterator)
+ self.__treeview.set_cursor(path)
+ self.__treeview.scroll_to_cell(path, use_align=True, row_align=0.5)
+# except TypeError:
+# pass
+ return
+
+ def __get_indentation_levels(self, symbols):
+ get_indentation = lambda x: x[-2]
+ indentations = [get_indentation(symbol) for symbol in symbols]
+ indentation_levels = list(set(indentations))
+ indentation_levels.sort()
+ return indentation_levels
+
+ def __append_symbols(self, item, indentation):
+ index = indentation.index(item[-2])
+ parent = self.__find_parent(index)
+ self.__depth_level_iter = self.__model.append(parent, item)
+ return
+
+ def __find_parent(self, index):
+ if not index: return None
+ depth = self.__model.iter_depth(self.__depth_level_iter)
+ if index == depth:
+ parent = self.__model.iter_parent(self.__depth_level_iter)
+ elif index < depth:
+ self.__depth_level_iter = self.__model.iter_parent(self.__depth_level_iter)
+ parent = self.__find_parent(index)
+ elif index > depth:
+ parent = self.__depth_level_iter
+ return parent
+
+ def __select_symbol(self, line, name):
+ begin = self.__editor.textbuffer.get_iter_at_line(line - 1)
+ end = self.__editor.forward_to_line_end(begin.copy())
+ from gtk import TEXT_SEARCH_TEXT_ONLY
+ x, y = begin.forward_search(name, TEXT_SEARCH_TEXT_ONLY, end)
+ self.__editor.textbuffer.select_range(x, y)
+ self.__editor.move_view_to_cursor(True)
+ return False
+
+ def __forward_to_line_end(self, iterator):
+ if iterator.ends_line(): return iterator
+ iterator.forward_to_line_end()
+ return iterator
+
+ def __destroy_cb(self, manager):
+ self.__editor.disconnect_signal(self.__sigid1, self.__manager)
+ self.__editor.disconnect_signal(self.__sigid2, self.__manager)
+ self.__editor.disconnect_signal(self.__sigid3, self.__treeview)
+ self.__treeview.destroy()
+ del self
+ return
+
+ def __row_activated_cb(self, treeview, path, column):
+ iterator = self.__model.get_iter(path)
+ self.__manager.emit("hide-window")
+ self.__treeview.set_property("sensitive", False)
+ line = self.__model.get_value(iterator, 0)
+ name = self.__model.get_value(iterator, 1)
+ self.__select_symbol(line, name)
+ return True
+
+ def __update_cb(self, manager, symbols):
+ from gobject import idle_add
+ idle_add(self.__populate_model, symbols, priority=9999)
+ return False
+
+ def __precompile_method(self):
+ methods = [self.__select_symbol, self.__row_activated_cb,
+ self.__populate_model]
+ self.__editor.optimize(methods)
+ return False
=== added file 'LanguagePlugins/CPPSymbolBrowser/Trigger.py'
--- LanguagePlugins/CPPSymbolBrowser/Trigger.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/Trigger.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,39 @@
+from SCRIBES.SignalConnectionManager import SignalManager
+from SCRIBES.TriggerManager import TriggerManager
+from gettext import gettext as _
+
+class Trigger(SignalManager, TriggerManager):
+
+ def __init__(self, editor):
+ SignalManager.__init__(self)
+ TriggerManager.__init__(self, editor)
+ self.__init_attributes(editor)
+ self.connect(self.__trigger, "activate", self.__activate_cb)
+
+ def __init_attributes(self, editor):
+ self.__editor = editor
+ self.__manager = None
+ name, shortcut, description, category = (
+ "show-python-symbol-brower",
+ "F5",
+ _("Show classes, methods and functions"),
+ _("Python")
+ )
+ self.__trigger = self.create_trigger(name, shortcut, description, category)
+ return
+
+ def __activate_cb(self, *args):
+ try:
+ self.__manager.show_browser()
+ except AttributeError:
+ from Manager import Manager
+ self.__manager = Manager(self.__editor)
+ self.__manager.show_browser()
+ return
+
+ def destroy(self):
+ self.disconnect()
+ self.remove_triggers()
+ if self.__manager: self.__manager.destroy()
+ del self
+ return
=== added file 'LanguagePlugins/CPPSymbolBrowser/Updater.py'
--- LanguagePlugins/CPPSymbolBrowser/Updater.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/Updater.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,101 @@
+class Updater(object):
+
+ def __init__(self, editor, manager):
+ self.__init_attributes(editor, manager)
+ self.__sigid1 = manager.connect("show-window", self.__show_window_cb)
+ from gobject import idle_add
+ idle_add(self.__precompile_methods, priority=9999)
+
+ def __init_attributes(self, editor, manager):
+ self.__editor = editor
+ self.__manager = manager
+ from collections import deque
+ # symbols has the format [(line_number, name, type), ...]
+ self.__symbols = deque([])
+ self.__depth = 0
+ self.__inside_class = False
+ self.__class_depth = 0
+ self.__function_depth = 0
+ return
+
+ def __get_symbols(self):
+ try:
+ self.__symbols.clear()
+ f = open('/tmp/scribes.cppsymbolbrowser','w')
+ f.write(self.__editor.text)
+ f.close()
+ from os import system
+ system('ctags -f /tmp/tags --language-force=C++ --fields=afmikKlnsStz /tmp/scribes.cppsymbolbrowser')
+ self.__extract_symbols('/tmp/tags')
+ self.__manager.emit("update", self.__symbols)
+ except SyntaxError:
+ pass
+ return False
+
+ def __extract_symbols(self, filename):
+ classes = {} #sort by class (None key for no class)
+
+ f = open(filename)
+ for line in f:
+ line = line.strip()
+ if not line or line[0] == '!':
+ continue
+ #print "DEBUG: PARSING LINE: ", line
+ fields = line.split('\t')
+ #if not len(fields) >= 3:
+ # print "CPPSymbolBrowser unparsable ctags line: ", line
+ name = fields[0]
+ filename = fields[1]
+ attribs = {}
+ for x in fields[3:]:
+ x = x.split(':',1)
+ if len(x) == 2:
+ attribs[x[0]] = x[1]
+ if 'class' in attribs:
+ cls = attribs['class']
+ else:
+ cls = None
+ if 'line' in attribs:
+ lineno = int(attribs['line'])
+ else:
+ continue
+
+ if not cls in classes:
+ classes[cls] = []
+
+ #print "DEBUG: Found: ", repr((name, filename, lineno, attribs))
+ classes[cls].append( (name, filename, lineno, attribs) )
+ f.close()
+
+ for cls in sorted(classes.keys()):
+ if cls != None:
+ lineno = 0
+ for name,filename,line,attribs in classes[cls]:
+ if name == cls:
+ lineno = line
+ break
+ if lineno:
+ self.__symbols.append( (lineno, name, 'Class', 0, self.__manager.class_pixbuf) )
+ depth = 1
+ else:
+ depth = 0
+ else:
+ depth = 0
+
+ for name,filename,line,attribs in sorted(classes[cls]):
+ if depth == 0:
+ self.__symbols.append( (line, name, 'Function', depth, self.__manager.function_pixbuf) )
+ else:
+ self.__symbols.append( (line, name, 'Method', depth, self.__manager.method_pixbuf) )
+ return
+
+
+ def __precompile_methods(self):
+ methods = (self.__extract_symbols, self.__get_symbols,)
+ self.__editor.optimize(methods)
+ return False
+
+ def __show_window_cb(self, *args):
+ from gobject import idle_add
+ idle_add(self.__get_symbols, priority=9999)
+ return
=== added file 'LanguagePlugins/CPPSymbolBrowser/Window.py'
--- LanguagePlugins/CPPSymbolBrowser/Window.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/CPPSymbolBrowser/Window.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,68 @@
+class Window(object):
+
+ def __init__(self, editor, manager):
+ self.__init_attributes(editor, manager)
+ self.__set_properties()
+ self.__sigid1 = manager.connect("destroy", self.__destroy_cb)
+ self.__sigid2 = manager.connect("show-window", self.__show_window_cb)
+ self.__sigid3 = manager.connect("hide-window", self.__hide_window_cb)
+ self.__sigid4 = self.__window.connect("delete-event", self.__delete_event_cb)
+ self.__sigid5 = self.__window.connect("key-press-event", self.__key_press_event_cb)
+ self.__window.set_property("sensitive", True)
+
+ def __init_attributes(self, editor, manager):
+ self.__manager = manager
+ self.__editor = editor
+ self.__window = manager.glade.get_widget("Window")
+ return
+
+ def __set_properties(self):
+ self.__window.set_transient_for(self.__editor.window)
+ return
+
+ def __show(self):
+ self.__editor.busy()
+ message = "C/C++ symbols"
+ self.__editor.set_message(message, "yes")
+ self.__window.show_all()
+ return False
+
+ def __hide(self):
+ self.__editor.busy(False)
+ message = "C/C++ symbols"
+ self.__editor.unset_message(message, "yes")
+ self.__window.hide()
+ return False
+
+ def __destroy(self):
+ self.__editor.disconnect_signal(self.__sigid1, self.__manager)
+ self.__editor.disconnect_signal(self.__sigid2, self.__manager)
+ self.__editor.disconnect_signal(self.__sigid3, self.__manager)
+ self.__editor.disconnect_signal(self.__sigid4, self.__window)
+ self.__editor.disconnect_signal(self.__sigid5, self.__window)
+ self.__window.destroy()
+ del self
+ self = None
+ return
+
+ def __destroy_cb(self, *args):
+ self.__destroy()
+ return
+
+ def __hide_window_cb(self, *args):
+ self.__hide()
+ return
+
+ def __show_window_cb(self, *args):
+ self.__show()
+ return
+
+ def __delete_event_cb(self, *args):
+ self.__hide()
+ return True
+
+ def __key_press_event_cb(self, window, event):
+ from gtk import keysyms
+ if event.keyval != keysyms.Escape: return False
+ self.__hide()
+ return True
=== added file 'LanguagePlugins/CPPSymbolBrowser/__init__.py'
=== added file 'LanguagePlugins/CPPSymbolBrowser/class.png'
Binary files LanguagePlugins/CPPSymbolBrowser/class.png 1970-01-01 00:00:00 +0000 and LanguagePlugins/CPPSymbolBrowser/class.png 2012-04-25 20:06:11 +0000 differ
=== added file 'LanguagePlugins/CPPSymbolBrowser/function.png'
Binary files LanguagePlugins/CPPSymbolBrowser/function.png 1970-01-01 00:00:00 +0000 and LanguagePlugins/CPPSymbolBrowser/function.png 2012-04-25 20:06:11 +0000 differ
=== added file 'LanguagePlugins/CPPSymbolBrowser/method.png'
Binary files LanguagePlugins/CPPSymbolBrowser/method.png 1970-01-01 00:00:00 +0000 and LanguagePlugins/CPPSymbolBrowser/method.png 2012-04-25 20:06:11 +0000 differ
=== added file 'LanguagePlugins/PluginCPPSymbrolBrowser.py'
--- LanguagePlugins/PluginCPPSymbrolBrowser.py 1970-01-01 00:00:00 +0000
+++ LanguagePlugins/PluginCPPSymbrolBrowser.py 2012-04-25 20:06:11 +0000
@@ -0,0 +1,25 @@
+name = "Python Symbol Browser"
+authors = ["Lateef Alabi-Oki ", "Maarten van Gompel (rpoycon) " ]
+languages = ["cpp"]
+version = 0.1
+autoload = True
+class_name = "CPPSymbolBrowserPlugin"
+short_description = "Show symbols in C++ source code."
+long_description = """This plugin allows users to view all symbols in
+c++ source code and navigate to them easily. Press F5 to show the
+symbol browser."""
+
+class CPPSymbolBrowserPlugin(object):
+
+ def __init__(self, editor):
+ self.__editor = editor
+ self.__trigger = None
+
+ def load(self):
+ from CPPSymbolBrowser.Trigger import Trigger
+ self.__trigger = Trigger(self.__editor)
+ return
+
+ def unload(self):
+ self.__trigger.destroy()
+ return
=== modified file 'SCRIBES/Globals.py'
--- SCRIBES/Globals.py 2011-11-10 15:09:01 +0000
+++ SCRIBES/Globals.py 2012-04-25 20:06:11 +0000
@@ -33,8 +33,8 @@
root_plugin_folder = join(library_path, "scribes")
core_plugin_folder = core_generic_plugin_folder = join(root_plugin_folder, "GenericPlugins")
core_language_plugin_folder = join(root_plugin_folder, "LanguagePlugins")
-python_path = "/usr/lib/python2.7/site-packages"
-version = "0.4-dev-build1038"
+python_path = "/usr/lib/python2.7/dist-packages"
+version = "0.4-dev-build1052"
author = ["Author:", "\tLateef Alabi-Oki \n",
"Contributors:",
"\tIb Lundgren ",
=== modified file 'po/Makefile.in'
--- po/Makefile.in 2011-11-10 15:09:01 +0000
+++ po/Makefile.in 2012-04-25 20:06:11 +0000
@@ -19,9 +19,9 @@
GETTEXT_PACKAGE = scribes
PACKAGE = scribes
-VERSION = 0.4-dev-build1038
+VERSION = 0.4-dev-build1052
-SHELL = /bin/sh
+SHELL = /bin/bash
srcdir = .
top_srcdir = ..
@@ -36,7 +36,7 @@
DATADIRNAME = share
itlocaledir = $(prefix)/$(DATADIRNAME)/locale
subdir = po
-install_sh = ${SHELL} /home/lateef/Dropbox/scribes/install-sh
+install_sh = ${SHELL} /home/proycon/scribes/install-sh
# Automake >= 1.8 provides /bin/mkdir -p.
# Until it can be supposed, use the safe fallback:
mkdir_p = $(install_sh) -d
# Begin bundle
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