# 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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