From eb3a1f25b110039392c37287cdc052d2067bf690 Mon Sep 17 00:00:00 2001 From: chick Date: Wed, 16 Apr 2014 10:08:28 -0700 Subject: [PATCH] dabbled with buttons --- ast_viewer/ast_tool_box.py | 103 ------ ast_viewer/astviewer.py | 420 ----------------------- ast_viewer/fiddle.py | 38 -- ast_viewer/views/ast_transform_viewer.py | 125 ------- ast_viewer/views/ast_tree_tabs.py | 75 ---- ast_viewer/views/ast_tree_widget.py | 187 ---------- ast_viewer/views/code_views/code_pane.py | 3 + images/one_windows.png | Bin 0 -> 932 bytes images/three_windows.png | Bin 0 -> 1197 bytes images/two_windows.png | Bin 0 -> 1209 bytes 10 files changed, 3 insertions(+), 948 deletions(-) delete mode 100644 ast_viewer/astviewer.py delete mode 100644 ast_viewer/fiddle.py delete mode 100644 ast_viewer/views/ast_transform_viewer.py delete mode 100644 ast_viewer/views/ast_tree_tabs.py delete mode 100644 ast_viewer/views/ast_tree_widget.py create mode 100644 images/one_windows.png create mode 100644 images/three_windows.png create mode 100644 images/two_windows.png diff --git a/ast_viewer/ast_tool_box.py b/ast_viewer/ast_tool_box.py index 7aff485..226380a 100644 --- a/ast_viewer/ast_tool_box.py +++ b/ast_viewer/ast_tool_box.py @@ -12,9 +12,6 @@ from PySide import QtCore, QtGui import ast_viewer -from ast_viewer.views.ast_tree_widget import AstTreeWidget -from ast_viewer.views.ast_tree_tabs import AstTreePane -from ast_viewer.views.ast_transform_viewer import AstTransformViewer from ast_viewer.controllers.tree_transform_controller import TreeTransformController @@ -270,106 +267,6 @@ def _load_file(self, file_name): logger.warn(msg) QtGui.QMessageBox.warning(self, 'error', msg) - def add_tree_tab(self, ast_tree=None, transformer=None, name=None): - """ - Adds a new ast tab after running the specified transformer - on the current tab's ast - """ - if not ast_tree: - ast_tree = self.ast_tree_tabs.current_ast() - - if transformer: - new_ast_tree = copy.deepcopy(ast_tree) - # print("got transformer %s" % transformer) - try: - transformer.visit(new_ast_tree) - except Exception as e: - print("Exception calling transformer %s" % e.message) - - new_tree_tab = AstTreeWidget(self, main_window=self) - new_tree_tab.make_tree_from(new_ast_tree) - - if not name: - name = "Tree %d" % (self.ast_tree_tabs.count() + 1) - - self.ast_tree_tabs.addTab(new_tree_tab, name) - self.ast_tree_tabs.setCurrentWidget(new_tree_tab) - - @QtCore.Slot(QtGui.QTreeWidgetItem, QtGui.QTreeWidgetItem) - def highlight_node(self, current_item, _previous_item): - """ Highlights the node if it has line:col information. - """ - highlight_str = current_item.text(AstTreeWidget.COL_HIGHLIGHT) - from_line_str, from_col_str, to_line_str, to_col_str = highlight_str.split(":") - - try: - from_line_col = (int(from_line_str), int(from_col_str)) - except ValueError: - from_line_col = None - - try: - to_line_col = (int(to_line_str), int(to_col_str)) - except ValueError: - to_line_col = None - - logger.debug("Highlighting ({!r}) : ({!r})".format(from_line_col, to_line_col)) - self.select_text(from_line_col, to_line_col) - - def select_text(self, from_line_col, to_line_col): - """ Selects a text in the range from_line:col ... to_line:col - from_line_col and to_line_col should be a (line, column) tuple - If from_line_col is None, the selection starts at the beginning of the document - If to_line_col is None, the selection goes to the end of the document - """ - text_cursor = self.editor.textCursor() - - if from_line_col is None: - text_cursor.movePosition(QtGui.QTextCursor.Start, QtGui.QTextCursor.MoveAnchor) - else: - from_line, from_col = from_line_col - # findBlockByLineNumber seems to be 0-based. - from_text_block = self.editor.document().findBlockByLineNumber(from_line - 1) - from_pos = from_text_block.position() + from_col - text_cursor.setPosition(from_pos, QtGui.QTextCursor.MoveAnchor) - - if to_line_col is None: - text_cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor) - else: - to_line, to_col = to_line_col - to_text_block = self.editor.document().findBlockByLineNumber(to_line - 1) - to_pos = to_text_block.position() + to_col - text_cursor.setPosition(to_pos, QtGui.QTextCursor.KeepAnchor) - - self.editor.setTextCursor(text_cursor) - - def search_box_changed(self): - # print("search_box is now '%s'" % self.search_box.text()) - - if not self.search_box.text(): - return - - current_tree = self.ast_tree_tabs.currentWidget() - # print("current tree %s" % current_tree) - # - # for widget_index in range(self.ast_tree_tabs.count()): - # widget = self.ast_tree_tabs.widget(widget_index) - # print("widget %s ast_tree %s" % (widget, widget.ast_root)) - - items = current_tree.findItems( - self.search_box.text(), - QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive, - column=AstTreeWidget.COL_NODE - ) - # print("Found %d items" % len(items)) - if len(items) > 0: - print(items[0]) - current_tree.setCurrentItem(items[0]) - current_tree.expandItem(items[0]) - - def my_test(self): - """ Function for testing """ - pass - def about(self): """ Shows the about message window. """ QtGui.QMessageBox.about(self, "About %s" % PROGRAM_NAME, ABOUT_MESSAGE) diff --git a/ast_viewer/astviewer.py b/ast_viewer/astviewer.py deleted file mode 100644 index 379bbee..0000000 --- a/ast_viewer/astviewer.py +++ /dev/null @@ -1,420 +0,0 @@ -""" - Program that shows the program on the right and its abstract syntax tree (ast) on the left. -""" -from __future__ import print_function - -import sys -import logging -import ast -import traceback -import copy - -from PySide import QtCore, QtGui - -import ast_viewer -from ast_viewer.views.ast_tree_widget import AstTreeWidget -from ast_viewer.views.ast_tree_tabs import AstTreePane -from ast_viewer.views.ast_transform_viewer import AstTransformViewer - -from ast_viewer.controllers.tree_transform_controller import TreeTransformController - - -logger = logging.getLogger(__name__) - -DEBUGGING = False - -PROGRAM_NAME = 'AST Toolkit' -PROGRAM_VERSION = '1.0.0' -ABOUT_MESSAGE = u""" -%(prog)s version %(version)s -""" % {"prog": PROGRAM_NAME, "version": ast_viewer.__version__} - - -def logging_basic_config(level): - """ Setup basic config logging. Useful for debugging to quickly setup a useful logger""" - fmt = '%(filename)20s:%(lineno)-4d : %(levelname)-7s: %(message)s' - logging.basicConfig(level=level, format=fmt) - - -def check_class(obj, target_class, allow_none=False): - """ Checks that the obj is a (sub)type of target_class. - Raises a TypeError if this is not the case. - """ - if not isinstance(obj, target_class): - if not (allow_none and obj is None): - raise TypeError("obj must be a of type {}, got: {}" - .format(target_class, type(obj))) - - -def get_qapplication_instance(): - """ Returns the QApplication instance. Creates one if it doesn't exist. - """ - app = QtGui.QApplication.instance() - if app is None: - app = QtGui.QApplication(sys.argv) - app.setStyle(QtGui.QMacStyle) - QtGui.QApplication.setStyle(QtGui.QMacStyle()) - check_class(app, QtGui.QApplication) - return app - - -def view(*args, **kwargs): - """ Opens an AstViewer window""" - app = get_qapplication_instance() - - window = AstViewer(*args, **kwargs) - window.show() - window.activateWindow() - if sys.platform == "darwin": - window.raise_() - - logger.info("Starting the AST viewer...") - exit_code = app.exec_() - logger.info("AST viewer done...") - return exit_code - - -def class_name(obj): - """ Returns the class name of an object""" - return obj.__class__.__name__ - - -# The main window inherits from a Qt class, therefore it has many -# ancestors public methods and attributes. -# pylint: disable=R0901, R0902, R0904, W0201, R0913 - -class AstViewer(QtGui.QMainWindow): - """ - The main application. - """ - - def __init__(self, file_name=None, mode='exec', - width=None, height=None): - """ Constructor - - AST browser windows that displays the Abstract Syntax Tree - of source code. - - The source can be given as text in the source parameter, or - can be read from a file. The file_name parameter overrides - the source parameter. - - The mode argument specifies what kind of code must be compiled; - it can be 'exec' if source consists of a sequence of statements, - 'eval' if it consists of a single expression, or 'single' if it - consists of a single interactive statement (in the latter case, - expression statements that evaluate to something other than None - will be printed). - (see http://docs.python.org/2/library/functions.html#compile) - - If width and height are both set, the window is resized. - """ - super(AstViewer, self).__init__() - - valid_modes = ['exec', 'eval', 'single'] - if mode not in valid_modes: - raise ValueError("Mode must be one of: {}".format(valid_modes)) - self._mode = mode - - # Controllers - self.tree_transform_controller = TreeTransformController() - self.tree_transform_controller.ast_tree_manager.new_item_from_file(file_name) - - # Views - # self.ast_tree_tabs = AstTreeTabs(self, self.tree_transform_controller) - self.ast_tree_pane = AstTreePane(self, self.tree_transform_controller) - self.ast_tree_tabs = self.ast_tree_pane.ast_tree_tabs - self.ast_transform_viewer = AstTransformViewer(self, self.tree_transform_controller) - - self._setup_actions() - self._setup_menu() - self._setup_views() - self.setWindowTitle('{}'.format(PROGRAM_NAME)) - - if width and height: - self.resize(width, height) - - def _setup_actions(self): - """ Creates the MainWindow actions. - """ - self.col_field_action = QtGui.QAction( - "Show Field Column", self, checkable=True, checked=True, - statusTip="Shows or hides the Field column") - self.col_field_action.setShortcut("Ctrl+1") - assert self.col_field_action.toggled.connect(self.show_field_column) - - self.col_class_action = QtGui.QAction( - "Show Class Column", self, checkable=True, checked=True, - statusTip="Shows or hides the Class column") - self.col_class_action.setShortcut("Ctrl+2") - assert self.col_class_action.toggled.connect(self.show_class_column) - - self.col_value_action = QtGui.QAction( - "Show Value Column", self, checkable=True, checked=True, - statusTip="Shows or hides the Value column") - self.col_value_action.setShortcut("Ctrl+3") - assert self.col_value_action.toggled.connect(self.show_value_column) - - self.col_pos_action = QtGui.QAction( - "Show Line:Col Column", self, checkable=True, checked=True, - statusTip="Shows or hides the 'Line : Col' column") - self.col_pos_action.setShortcut("Ctrl+4") - assert self.col_pos_action.toggled.connect(self.show_pos_column) - - def _setup_menu(self): - """ Sets up the main menu. - """ - file_menu = self.menuBar().addMenu("&File") - file_menu.addAction("&Open...", self.open_file, "Ctrl+O") - #file_menu.addAction("C&lose", self.close_window, "Ctrl+W") - file_menu.addAction("E&xit", AstViewer.quit_application, "Ctrl+Q") - - if DEBUGGING is True: - file_menu.addSeparator() - file_menu.addAction("&Test", self.my_test, "Ctrl+T") - - view_menu = self.menuBar().addMenu("&View") - - self.auto_expand_ast = QtGui.QAction("Expand AST trees on create", self, checkable=True, checked=True) - assert self.auto_expand_ast.toggled.connect(self.set_auto_expand) - - view_menu.addAction(self.col_field_action) - view_menu.addAction(self.col_class_action) - view_menu.addAction(self.col_value_action) - view_menu.addAction(self.col_pos_action) - - self.menuBar().addSeparator() - help_menu = self.menuBar().addMenu("&Help") - help_menu.addAction('&About', self.about) - - def _setup_views(self): - """ Creates the UI widgets. - """ - central_splitter = QtGui.QSplitter(self, orientation=QtCore.Qt.Horizontal) - self.setCentralWidget(central_splitter) - central_layout = QtGui.QHBoxLayout() - central_splitter.setLayout(central_layout) - - # Create base tree widget - central_layout.addWidget(self.ast_tree_pane) - - # central_layout.addWidget(self.editor) - - central_layout.addWidget(self.ast_transform_viewer) - - # Splitter parameters - central_splitter.setCollapsible(0, True) - central_splitter.setCollapsible(1, True) - central_splitter.setSizes([700, 300]) - central_splitter.setStretchFactor(0, 0.5) - central_splitter.setStretchFactor(1, 0.5) - - # Connect signals - # assert self.ast_tree.currentItemChanged.connect(self.highlight_node) - - def set_auto_expand(self): - self.tree_transform_controller.ast_tree_manager.set_auto_expand(self.auto_expand_ast.isChecked()) - - def new_file(self): - """ Clears the widgets """ - self.ast_tree.make_tree_from() - - - def open_file(self, file_name=None): - """ Opens a new file. Show the open file dialog if file_name is None. - """ - if not file_name: - file_name = self._get_file_name_from_dialog() - - self._update_widgets(file_name) - - - def _get_file_name_from_dialog(self): - """ Opens a file dialog and returns the file name selected by the user - """ - file_name, _ = QtGui.QFileDialog.getOpenFileName(self, "Open File", - '', "Python Files (*.py);;All Files (*)") - return file_name - - - def _update_widgets(self, file_name): - """ Reads source from a file and updates the tree and editor widgets.. - """ - if file_name: - self._load_file(file_name) - - self.setWindowTitle('{} - {}'.format(PROGRAM_NAME, self._file_name)) - # self.editor.setPlainText(self._source_code) - - try: - self._fill_ast_tree_widget() - except StandardError, ex: - if DEBUGGING: - raise - else: - stack_trace = traceback.format_exc() - msg = "Unable to parse file: {}\n\n{}\n\n{}" \ - .format(self._file_name, ex, stack_trace) - logger.exception(ex) - QtGui.QMessageBox.warning(self, 'error', msg) - - def _load_file(self, file_name): - """ - Opens a file and sets self._file_name and self._source code if successful - """ - logger.debug("Opening {!r}".format(file_name)) - - in_file = QtCore.QFile(file_name) - if in_file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): - text = in_file.readAll() - try: - source_code = str(text, encoding='ascii') # Python 3 - except TypeError: - source_code = str(text) # Python 2 - - self._file_name = file_name - self._source_code = source_code - - else: - msg = "Unable to open file: {}".format(file_name) - logger.warn(msg) - QtGui.QMessageBox.warning(self, 'error', msg) - - def add_tree_tab(self, ast_tree=None, transformer=None, name=None): - """ - Adds a new ast tab after running the specified transformer - on the current tab's ast - """ - if not ast_tree: - ast_tree = self.ast_tree_tabs.current_ast() - - if transformer: - new_ast_tree = copy.deepcopy(ast_tree) - # print("got transformer %s" % transformer) - try: - transformer.visit(new_ast_tree) - except Exception as e: - print("Exception calling transformer %s" % e.message) - - new_tree_tab = AstTreeWidget(self, main_window=self) - new_tree_tab.make_tree_from(new_ast_tree) - - if not name: - name = "Tree %d" % (self.ast_tree_tabs.count() + 1) - - self.ast_tree_tabs.addTab(new_tree_tab, name) - self.ast_tree_tabs.setCurrentWidget(new_tree_tab) - - @QtCore.Slot(QtGui.QTreeWidgetItem, QtGui.QTreeWidgetItem) - def highlight_node(self, current_item, _previous_item): - """ Highlights the node if it has line:col information. - """ - highlight_str = current_item.text(AstTreeWidget.COL_HIGHLIGHT) - from_line_str, from_col_str, to_line_str, to_col_str = highlight_str.split(":") - - try: - from_line_col = (int(from_line_str), int(from_col_str)) - except ValueError: - from_line_col = None - - try: - to_line_col = (int(to_line_str), int(to_col_str)) - except ValueError: - to_line_col = None - - logger.debug("Highlighting ({!r}) : ({!r})".format(from_line_col, to_line_col)) - self.select_text(from_line_col, to_line_col) - - def select_text(self, from_line_col, to_line_col): - """ Selects a text in the range from_line:col ... to_line:col - from_line_col and to_line_col should be a (line, column) tuple - If from_line_col is None, the selection starts at the beginning of the document - If to_line_col is None, the selection goes to the end of the document - """ - text_cursor = self.editor.textCursor() - - if from_line_col is None: - text_cursor.movePosition(QtGui.QTextCursor.Start, QtGui.QTextCursor.MoveAnchor) - else: - from_line, from_col = from_line_col - # findBlockByLineNumber seems to be 0-based. - from_text_block = self.editor.document().findBlockByLineNumber(from_line - 1) - from_pos = from_text_block.position() + from_col - text_cursor.setPosition(from_pos, QtGui.QTextCursor.MoveAnchor) - - if to_line_col is None: - text_cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor) - else: - to_line, to_col = to_line_col - to_text_block = self.editor.document().findBlockByLineNumber(to_line - 1) - to_pos = to_text_block.position() + to_col - text_cursor.setPosition(to_pos, QtGui.QTextCursor.KeepAnchor) - - self.editor.setTextCursor(text_cursor) - - def search_box_changed(self): - # print("search_box is now '%s'" % self.search_box.text()) - - if not self.search_box.text(): - return - - current_tree = self.ast_tree_tabs.currentWidget() - # print("current tree %s" % current_tree) - # - # for widget_index in range(self.ast_tree_tabs.count()): - # widget = self.ast_tree_tabs.widget(widget_index) - # print("widget %s ast_tree %s" % (widget, widget.ast_root)) - - items = current_tree.findItems( - self.search_box.text(), - QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive, - column=AstTreeWidget.COL_NODE - ) - # print("Found %d items" % len(items)) - if len(items) > 0: - print(items[0]) - current_tree.setCurrentItem(items[0]) - current_tree.expandItem(items[0]) - - @QtCore.Slot(int) - def show_field_column(self, checked): - """ Shows or hides the field column""" - self.ast_tree.setColumnHidden(AstTreeWidget.COL_FIELD, not checked) - - @QtCore.Slot(int) - def show_class_column(self, checked): - """ Shows or hides the class column""" - self.ast_tree.setColumnHidden(AstTreeWidget.COL_CLASS, not checked) - - @QtCore.Slot(int) - def show_value_column(self, checked): - """ Shows or hides the value column""" - self.ast_tree.setColumnHidden(AstTreeWidget.COL_VALUE, not checked) - - @QtCore.Slot(int) - def show_pos_column(self, checked): - """ Shows or hides the line:col column""" - self.ast_tree.setColumnHidden(AstTreeWidget.COL_POS, not checked) - - def my_test(self): - """ Function for testing """ - pass - - def about(self): - """ Shows the about message window. """ - QtGui.QMessageBox.about(self, "About %s" % PROGRAM_NAME, ABOUT_MESSAGE) - - def close_window(self): - """ Closes the window """ - self.close() - - @staticmethod - def quit_application(): - """ Closes all windows """ - app = QtGui.QApplication.instance() - app.closeAllWindows() - -# pylint: enable=R0901, R0902, R0904, W0201 - -if __name__ == '__main__': - sys.exit(view(source_code="print a + 5 + 6 / 3.7", mode='eval', width=800, height=600)) diff --git a/ast_viewer/fiddle.py b/ast_viewer/fiddle.py deleted file mode 100644 index cdb792f..0000000 --- a/ast_viewer/fiddle.py +++ /dev/null @@ -1,38 +0,0 @@ -__author__ = 'Chick Markley' - -import sys - -from PySide import QtGui - - -app = QtGui.QApplication(sys.argv) - -wid = QtGui.QWidget() -wid.resize(250, 150) -wid.setWindowTitle('Simple') - -# NOTICE: the difference -QtGui.QIcon.setThemeSearchPaths(["/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources"]) -print "search paths", QtGui.QIcon.themeSearchPaths() -print "themeName:", QtGui.QIcon.themeName() -print "hasThemeIcon:", QtGui.QIcon.hasThemeIcon("edit-undo") - -# qutils.config_theme_path() - -print "themeName:", QtGui.QIcon.themeName() -print "hasThemeIcon:", QtGui.QIcon.hasThemeIcon("edit-undo") -print - -my_online = QtGui.QIcon("/path/to/my_online.png") - -icon = QtGui.QIcon.fromTheme("user-online", my_online) -print "icon not found:", icon.isNull() -print "availableSizes:", icon.availableSizes() - - -wid.setWindowIcon( - QtGui.QIcon.fromTheme("system-open") -) -wid.show() - -sys.exit(app.exec_()) \ No newline at end of file diff --git a/ast_viewer/views/ast_transform_viewer.py b/ast_viewer/views/ast_transform_viewer.py deleted file mode 100644 index aef42f7..0000000 --- a/ast_viewer/views/ast_transform_viewer.py +++ /dev/null @@ -1,125 +0,0 @@ -from __future__ import print_function - -__author__ = 'Chick Markley' - -from PySide import QtGui, QtCore -import ast -import inspect -from ctree.codegen import CodeGenVisitor -from ast_viewer.views.editor_widget import EditorPane - - -class AstTransformViewer(QtGui.QGroupBox): - def __init__(self, parent, tree_transform_controller): - super(AstTransformViewer, self).__init__("Available Transforms") - - self.controller = tree_transform_controller - self.parent_viewer = parent - - self.last_used_directory = "." - - layout = QtGui.QVBoxLayout() - - button_box = QtGui.QGroupBox() - button_layout = QtGui.QHBoxLayout() - go_button = QtGui.QPushButton("Apply") - go_button.clicked.connect(self.go) - - open_button = QtGui.QPushButton("Load File") - open_button.clicked.connect(self.load) - - package_button = QtGui.QPushButton("Load Package") - package_button.clicked.connect(self.load_package) - - button_layout.addWidget(package_button) - button_layout.addWidget(open_button) - button_layout.addWidget(go_button) - - button_box.setLayout(button_layout) - - layout.addWidget(button_box) - - self.transform_list = QtGui.QListWidget() - self.transformers = self.controller.ast_transformer_manager - self.transformers.get_ast_transformers('ctree.transformations') - - self.reload_list() - self.transform_list.itemClicked.connect(self.show) - self.transform_list.doubleClicked.connect(self.go) - - layout.addWidget(self.transform_list) - - self.editor = EditorPane() - layout.addWidget(self.editor) - - self.setLayout(layout) - - def go(self): - current_item = self.transform_list.currentItem() - print("apply invoked with %s" % current_item.text()) - - transformer = current_item.ast_transformer_item.node_transformer() - print("go got transformer %s" % transformer) - if isinstance(transformer, ast.NodeTransformer): - print("let's add a tree") - self.parent_viewer.add_tree_tab(name=current_item.text(), transformer=transformer) - elif isinstance(transformer, CodeGenVisitor): - print(transformer.visit(self)) - - @QtCore.Slot(QtGui.QListWidgetItem) - def show(self, item): - print("show item %s" % item) - transformer = item.ast_transformer_item.node_transformer - self.editor.setPlainText(inspect.getsource(transformer)) - - def reload_list(self): - print("self.transformers %s" % self.transformers) - self.transform_list.clear() - for transformer in self.transformers.transformer_items: - print("adding transformer %s" % transformer.name) - self.transform_list.addItem( - AstTransformWidgetItem(transformer) - ) - - def load(self): - file_name, _ = QtGui.QFileDialog.getOpenFileName( - self.parent_viewer, - caption="Select a file containing Node Transformers", - # dir=os.getcwd(), - # filter="Python Files (*.py);;All Files (*);;" - ) - print("got file_name %s" % file_name) - self.controller.load_transforms(file_name) - self.reload_list() - - def load_package(self): - package_name, ok = QtGui.QInputDialog.getText( - self, - "Load additional tranformers", - "package name or path to file", - QtGui.QLineEdit.Normal, - "ast_viewer.transformers.identity_transform" - ) - if ok and package_name != '': - print("Got package name %s" % package_name) - self.controller.load_transforms(package_name) - self.reload_list() - - def contextMenuEvent(self, event): - menu = QtGui.QMenu(self) - menu.addAction( - QtGui.QAction("Show source", self) - ) - menu.addAction( - QtGui.QAction("Apply to current tree", self) - ) - menu.addAction( - QtGui.QAction("Apply to current node of current tree", self) - ) - menu.exec_(event.globalPos()) - - -class AstTransformWidgetItem(QtGui.QListWidgetItem): - def __init__(self, ast_transformer_item): - super(AstTransformWidgetItem, self).__init__(ast_transformer_item.name()) - self.ast_transformer_item = ast_transformer_item diff --git a/ast_viewer/views/ast_tree_tabs.py b/ast_viewer/views/ast_tree_tabs.py deleted file mode 100644 index 3736873..0000000 --- a/ast_viewer/views/ast_tree_tabs.py +++ /dev/null @@ -1,75 +0,0 @@ -__author__ = 'Chick Markley' - -from PySide import QtGui, QtCore -from ast_viewer.views.ast_tree_widget import AstTreeWidget -from ast_viewer.views.search_widget import SearchLineEdit - -class AstTreePane(QtGui.QGroupBox): - def __init__(self, main_window, controller): - super(AstTreePane, self).__init__("AST Trees") - self.main_window = main_window - self.controller = controller - - layout = QtGui.QVBoxLayout() - - self.search_box = SearchLineEdit(self, on_changed=self.search_box_changed) - layout.addWidget(self.search_box) - - self.ast_tree_tabs = AstTreeTabs(self, self.main_window, self.controller) - layout.addWidget(self.ast_tree_tabs) - - self.setLayout(layout) - - def search_box_changed(self): - if not self.search_box.text(): - return - - current_tree = self.ast_tree_tabs.currentWidget() - # print("current tree %s" % current_tree) - # - # for widget_index in range(self.ast_tree_tabs.count()): - # widget = self.ast_tree_tabs.widget(widget_index) - # print("widget %s ast_tree %s" % (widget, widget.ast_root)) - - items = current_tree.findItems( - self.search_box.text(), - QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive, - column=AstTreeWidget.COL_NODE - ) - # print("Found %d items" % len(items)) - if len(items) > 0: - # print(items[0]) - current_tree.setCurrentItem(items[0]) - current_tree.expandItem(items[0]) - - -class AstTreeTabs(QtGui.QTabWidget): - def __init__(self, parent, main_window, tree_transform_controller): - super(AstTreeTabs, self).__init__(parent) - self.parent = parent - self.main_window = main_window - self.tree_transform_controller = tree_transform_controller - - self.setTabsClosable(True) - self.setUsesScrollButtons(True) - self.setStyle(QtGui.QStyleFactory.create("Plastique")) - self.tabCloseRequested.connect(self.close_tab) - - for tree_item in self.tree_transform_controller.ast_tree_manager: - ast_tree_widget = AstTreeWidget(self, self.main_window) - ast_tree_widget.make_tree_from(tree_item.ast_tree) - self.addTab( - ast_tree_widget, - tree_item.name - ) - - @QtCore.Slot(int) - def close_tab(self, index): - print("Tab close requested index %s" % index) - self.tree_transform_controller.ast_tree_manager.delete(index) - self.removeTab(index) - - def current_ast(self): - if self.currentWidget(): - return self.currentWidget().ast_root - return None \ No newline at end of file diff --git a/ast_viewer/views/ast_tree_widget.py b/ast_viewer/views/ast_tree_widget.py deleted file mode 100644 index bf01743..0000000 --- a/ast_viewer/views/ast_tree_widget.py +++ /dev/null @@ -1,187 +0,0 @@ -__author__ = 'Chick Markley' - -import types -import ast - -from PySide import QtGui, QtCore - -DEBUGGING = False - - -class AstTreeItem(QtGui.QTreeWidgetItem): - """ - connects a gui tree item with the corresponding node in the actual ast tree - """ - def __init__(self, parent, source_node=None): - super(AstTreeItem, self).__init__(parent) - self.ast_node = source_node - - -class TransformerAction(QtGui.QAction): - def __init__(self, text, tree_widget, **kwargs): - super(TransformerAction, self).__init__(text, tree_widget, **kwargs) - self.tree_widget = tree_widget - self.text = text - self.triggered.connect(self.do_transform) - - def do_transform(self): - print("Triggered with string %s" % self.text) - self.tree_widget.transform_current_ast(self.text) - - -class AstTreeWidget(QtGui.QTreeWidget): - """ - displays an ast as a tree widget - """ - COL_NODE = 0 - COL_FIELD = 1 - COL_CLASS = 2 - COL_VALUE = 3 - COL_POS = 4 - COL_HIGHLIGHT = 5 - - def __init__(self, parent=None, main_window=None): - super(AstTreeWidget, self).__init__(parent) - - self.parent_viewer = parent - self.main_window = main_window - - self.ast_root = None - self.setColumnCount(2) - self.setHeaderLabels( - ["Node"] - ) - self.header().resizeSection(AstTreeWidget.COL_NODE, 800) - self.header().setStretchLastSection(True) - - self.ast_transformers = self.parent_viewer.tree_transform_controller.ast_transformer_manager - self.ast_transformers.get_ast_transformers('ctree.transformations') - - self.transform_signal = QtCore.Signal(int) - - self.show_with_dot_action = QtGui.QAction( - "&show tree using dot", - self, - statusTip="Create a *.png file using dot", - triggered=self.show_with_dot - ) - self.make_root_action = QtGui.QAction( - "&Make this node be root", - self, - statusTip="This node will be made the current root in this window", - triggered=self.make_root - ) - self.expand_descendants_action = QtGui.QAction( - "&Expand all children", - self, - statusTip="Expand all descendant nodes", - triggered=self.expand_descendants - ) - - def contextMenuEvent(self, event): - menu = QtGui.QMenu(self) - menu.addAction(self.show_with_dot_action) - menu.addAction(self.expand_descendants_action) - - sub_menu = QtGui.QMenu(self) - sub_menu.setTitle("Available transformers") - for transformer_name in self.ast_transformers.transformers_by_name: - sub_menu_action = TransformerAction(transformer_name, self) - sub_menu.addAction(sub_menu_action) - menu.addMenu(sub_menu) - menu.addAction(self.make_root_action) - menu.exec_(event.globalPos()) - - def transform_current_ast(self, name): - transformer = self.ast_transformers.get_instance_by_name(name) - self.main_window.add_tree_tab(transformer=transformer) - - def show_with_dot(self): - from ctree.visual.dot_manager import DotManager - print("calling open") - DotManager.dot_ast_to_browser(self.currentItem().ast_node, "ast_%s.png" % "tree") - - def make_root(self): - """make the current item the displayed root of the tree""" - self.make_tree_from(self.currentItem().ast_node) - - def expand_descendants(self, item=None): - """Expand all descendants of the current item""" - if item is None: - item = self.currentItem() - item.setExpanded(True) - # print("at_node %s children count %d" % (item, item.childCount())) - for child_index in range(item.childCount()): - self.expand_descendants(item.child(child_index)) - - def make_tree_from(self, syntax_tree, file_name="", display_depth=1): - """ - Populates the tree widget. - """ - self.clear() - - # State we keep during the recursion. - # Is needed to populate the selection column. - to_be_updated = list([]) - state = {'from': '? : ?', 'to': '1 : 0'} - - def add_node(ast_node, parent_item, field_label): - """ - Helper function that recursively adds nodes. - :param parent_item: The parent QTreeWidgetItem to which this node will be added - :param field_label: Labels how this node is known to the parent - """ - node_item = AstTreeItem(parent_item) - node_item.ast_node = ast_node - - if hasattr(ast_node, 'lineno'): - position_str = " ({:d}:{:d})".format(ast_node.lineno, ast_node.col_offset) - - # If we find a new position string we set the items found since the last time - # to 'old_line : old_col : new_line : new_col' and reset the list - # of to-be-updated nodes - if position_str != state['to']: - state['from'] = state['to'] - state['to'] = position_str - for node in to_be_updated: - node.setText(AstTreeWidget.COL_HIGHLIGHT, "{} : {}".format(state['from'], state['to'])) - to_be_updated[:] = [node_item] - else: - to_be_updated.append(node_item) - else: - to_be_updated.append(node_item) - position_str = "" - - # Recursively descend the AST - if isinstance(ast_node, ast.AST): - value_str = '' - node_str = "{} = {}".format(field_label, class_name(ast_node)) - for key, val in ast.iter_fields(ast_node): - if val: - add_node(val, node_item, key) - elif isinstance(ast_node, types.ListType) or isinstance(ast_node, types.TupleType): - value_str = '' - node_str = "{} = {}".format(field_label, class_name(ast_node)) - for idx, node in enumerate(ast_node): - add_node(node, node_item, "{}[{:d}]".format(field_label, idx)) - else: - value_str = repr(ast_node) - node_str = "{}: {}".format(field_label, value_str) - - if position_str: - node_str += position_str - - node_item.setText(AstTreeWidget.COL_NODE, node_str) - - # End of helper function - - #syntax_tree = ast.parse(self._source_code, filename=self._file_name, mode=self._mode) - #logger.debug(ast.dump(syntax_tree)) - add_node(syntax_tree, self, '"{}"'.format(file_name)) - self.expandToDepth(display_depth) - - self.ast_root = syntax_tree - -def class_name(obj): - """ Returns the class name of an object""" - return obj.__class__.__name__ diff --git a/ast_viewer/views/code_views/code_pane.py b/ast_viewer/views/code_views/code_pane.py index f9ff4b2..e8abbba 100644 --- a/ast_viewer/views/code_views/code_pane.py +++ b/ast_viewer/views/code_views/code_pane.py @@ -24,16 +24,19 @@ def __init__(self, code_presenter=None, panel_count=2): toolbar_layout.setContentsMargins(0, 0, 0, 0) toolbar_layout.addSpacing(0) + # one_button = QtGui.QPushButton(QtGui.QIcon(QtGui.QPixmap("images/one_windows.png")), "") one_button = QtGui.QPushButton("|1|") one_button.setStyleSheet("QToolButton { border: none; padding: 0px;}") one_button.clicked.connect(self.set_to_one_panel) toolbar_layout.addWidget(one_button) + # two_button = QtGui.QPushButton(QtGui.QIcon(QtGui.QPixmap("images/two_windows.png")), "") two_button = QtGui.QPushButton("|1|2|") two_button.setStyleSheet("QToolButton { border: none; padding: 0px;}") two_button.clicked.connect(self.set_to_two_panel) toolbar_layout.addWidget(two_button) + # self.three_button = QtGui.QPushButton(QtGui.QIcon(QtGui.QPixmap("images/three_windows.png")), "") self.three_button = QtGui.QPushButton("|1|2|3|") self.three_button.setStyleSheet("QToolButton { border: none; padding: 0px;}") self.three_button.clicked.connect(self.set_to_three_panel) diff --git a/images/one_windows.png b/images/one_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..b871f2162a9d3db27133093f70464d788f93fc29 GIT binary patch literal 932 zcmV;V16%xwP)%-6g~I8H#;*6 zibO+z0+tXqh%qrHHa1i?_7?sF5)*4GTmO(27A97HGf>eir_(mmpBA|ng_Y&;u?wR^ahQ?5K0V(FHoxr1M)T{PcH7+t@U$=j0&ACU zT$>%eIzJ5%0T6|fCbU`y^z6l(g_RF$ONA0JR1L@HXD6|JAXwYnQCR?n8MBk;F*h@g z)lcgSr=8D4fH7plu!7w^2M6wmK$H9dKnMat9ED)wuuuYshyrU6g%)w#)@T7BB7|W8 zV>s3MYy<#cCRob|tW~K124IZ=GnGI95v(B?M_}$4jy?qdh6#o{cPx~En{({0*MHa=pSP2G_fL`Nf4F;NkqqYn- z0cjew|B?Vnq(QMUc(NCOh|`+}BB=*;o0nq|QMnID>ORdlVDmm+M4)dPIu^eG0t`o{ zq!Q?sf!cPk^L`jE+5_a|@lHgY08Z{GNjEH50n(LP2BY~$F_6lmbC!T~>x@*symL1x zNdaAfIT4V`6v#HJ=8M5z3h0!6mVmbTETHQFqO2E^Up|x=ta z*$XG`R@y9Z{3WDO1=-5-FK2<26Gxv-KoYkssS`|kz}fDEY(A$EohJB$Li=HYiuVC& z3zPF`i-@3cCEDAA5WzW@s!hqHfYyF%r`c>qQ&Uq2!${{+m>JdtXfzrKf=aOj?6>xx zynOZi?$*|49v(iIN@tYl9!pOQ0>n8q8V#(xe}{U#UbqK5*x1-uZ#J8Y%sg_M#6%Df z(L@}_fwdOSxjqyQp;D=!UY|p)HVqFC4-XFy4-XHI-{U)zc2-!FVe@(b0000ug!&u-V5`4hvuL7-PFc-_0137Tb;SFwgeCX;L>crcZ@rm_ptHdb*Bu0(ChW-&gQ*q+rPGNR%(EH zEpDu>&SSsNXzw0~0-&`pjpj-NTRR6%nLsJ5&R;@vrGbaPKfZR_^CANT0qHo7aQMQ& zK;=$Q)-^#$lNfufoG}alOk+-wiYqk$5mBfEB(X-C4n!F=jza{2LaHOD3=xgFGLjhp zfKmjl6+*2=9-xB&N)f_PJ7XAtDsa^sfCxGu1csngo^Z;?CLvIS0l8&}PB^71Ho!+s zW!_(|13JR~^HkJEygpsSY_N+D+se75lK7f z@lr~ub6`%m7k$iCYk;#{I_P|uA{WO|_@6Przo9?}xX=c8IpB+JfHEO;ZU*4Ow@aqT zQ3(rZtHUsZ*~qE^GkC~4WeQy7t#HxC`KB!14jZ>j;jNds4rtrMGqb2pF&M*-JBE3J zn@R#lAuw`Fkvk7LW85+YE>KnH06saqVHOTVc;eR;lkbsHHh*f%*Dp#m#m%tLYs5_P z;BIn2Zs9!6q&a|vQ6pt|f^*{mLkBa=AjnFZIHTJzB)h8GmBDcp5JrwT2M8IS)XOwguyDBhRglwiY#x29LQSuq@0wr%86B%7T+G1f6;KD8)b%MpXlyySR?*hV3 z$f^$z*XF|eko5s}GeJp#K3ftL+Knvc0R&jDRYuCjw}?nw(}@U1INFjj{3nj89*Fdg zdIwpSC5wxTh~q?L0Ud?s3P(DEIbUN66u!UBuRe28hy4&qO&a!MnDRucY7h^_9M007H zhDnm3)oNn%?hmCGi=tS}0E8%t&}ucYyu1W2FE1}IFE1}IufNwHBbaWd3|iYQ00000 LNkvXXu0mjf{zDpX literal 0 HcmV?d00001 diff --git a/images/two_windows.png b/images/two_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..b353f6c0b79b672131642c2147cda4e2e66e05e8 GIT binary patch literal 1209 zcmV;q1V;ObP)Q_ zHLO&ye|U_;qZc0mg!Ok<&}qk4owuKHWp8x!#dMl}4d6#L143hNe){qD>W5b@0Ym`A zA>;_-@dUSb@1wWAij1id%7pQFLbrGCUwiQTlbfmrblUO8mF-PDp9r4pA3H5HV8-_5 zTiCh0f%khCbLNS&0XFyHqo>!(K3B?sARrUR5l&vFNWobU)YMc60zxZ^Q80zrE&Kt% z;xcipY5);YXaXd$L8~=&idZ5-9ES)3#*CRv-H(99t)g-U0AMB>pPr&vef}hgy%0>fTIEL zthBKf?Bl(Sf_bK5K*1gE0KaG&aJ46Lc`ZS^-NxD3#JON4Ndi6zv988kldjS#BIh;s4rz zrWKd~=h}c*Q#s!TR5@b*i2-8$ZGuY`9H`WTiU>qf_slIa+kVDWGQ;9FVgOJqRutp2 zFjX(^tBeDt>gGknt&WL6AjJ%uF%`aiP6Gt!CP70-AP-rm){O|W{TIwMRZ9YbY$#H1 zg^SInB5sY0|?nIlk~U$+p*81r*0N{-IB zjYL2mV5tbmwF-zVFmlA2HEd}H`KwNvFr6edi2Gr?K zDwo0R2srdYv>2&b8PrLFb$qN`1vHMpY^9=f1eUncOa$Z!3#nTbpoK1AezcsEpwt?& zDknkrFShjCqA1M*3tZ(((OGs?m<7lx)lzeU`@01eRj|=%P%T`oWvVd$wJK0VfH3KOy4VXSjl*>cbiE{~RJK%^OWd;JDzQaGaJ&*l!AbLLFjDxPOqRH$eIYVF z9UqTIqom*OBaRcdOJQc1AjEJuL>NZs_xp&W#Jvw(;;I^OIzIj3?!7x-9vnR5Zudf| zI3ugmvmX#iF&qx@;J07#_|Hc;ICzF`_kwd5Ea{v(7!1^Nz&Cq)drwEB(G6x^`KJ&Q zK}bZsR;v{nWAbpHU)V)agu!43hlfYly?Y1UZbxMnD7af&m*C~)<>lq&<>lq&^+x># XMs`L`6LNlk00000NkvXXu0mjf$`Kq^ literal 0 HcmV?d00001