Source

codeaide / codeaide / ide / simple / python.py

Full commit
# -*- coding: utf-8 -*-
import os

from PyQt4.QtCore import Qt, SIGNAL, QUrl, QDir
from PyQt4.QtGui import QColor, QTreeWidget, QTreeWidgetItem, QTreeView, QFileSystemModel, QDirModel, QFrame

from codeaide.interface import implements
from codeaide.ide.base import (
  i18n, load_icon, DockBase, DocumentCommandBase)
from codeaide.ide import api
from codeaide.ide.simple.base import view, doc
from codeaide.ide.simple.utils import call_on_idle



class RunCommand(DocumentCommandBase):
    implements(api.Command)

    title = i18n("&Run in console")
    menu = i18n("&Run")
    shortcut = i18n("F5")
    icon = "run-build"
    toolbar = i18n("Run")


    def execute(self):
        lines = unicode(doc().toPlainText()).splitlines()
        for i, l in enumerate(lines):
            if not l.strip().startswith("#"):
                break
            if "-*-coding:" in "".join(l.split()):
                lines[i] = "# disabled coding"
        src = "\n".join(lines)
        ns = {
             "__file__": (doc().filename or "unnamed.py"),
             "__name__":"__main__"
             }
        # Output goes to console which redirects sys.stdout
        print "Starting script..."
        try:
            exec src in ns
        except Exception, e:
            print "Script failed:", e
            if isinstance(e, SyntaxError):
                self.doc.set_row_start(e.lineno-1)
                return
            import sys, traceback
            traceback.print_exc()
            try:
                etype, value, tb = sys.exc_info()
                tb = tb.tb_next
                self.doc.set_row_start(tb.tb_lineno-1)
            except Exception, e:
                pass
            return
        print "Script done."




class ConsoleDock(DockBase):
    implements(api.Dock)

    title = i18n("Python Console")
    toggle_shortcut = "Alt+2"
    icon = "terminal"
    statusbar = True
    #toggle_menu = i18n("&View")
    #toolbar = i18n("Views")
    area = Qt.BottomDockWidgetArea
    switch_shortcut = "Ctrl+2"


    def create_widget(self, parent):
        from codeaide.editors import PythonConsole
        console = PythonConsole(parent)
        console.new_buffer()
        return console



class OutlineItem(QTreeWidgetItem):


    def __init__(self, parent, node):
        QTreeWidgetItem.__init__(self, parent)
        kind = node.get_kind()
        if kind == "function":
            self.setIcon(0, load_icon("code-function"))
        elif kind == "class":
            self.setIcon(0, load_icon("code-class"))
        else:
            print "unknown kind", kind
        name = node.name
        self.key = "%s.%s" % (parent.key, name)
        self.setText(0, name)
        self.node = node
        self.items = []
        root = self.treeWidget()
        eflag = root.is_expanded.get(self.key, True)
        self.setExpanded(eflag)
        for child in node.get_children():
            i = self.__class__(self, child)
            self.items.append(i)
            self.addChild(i)



class OutlineDock(DockBase):
    implements(api.Dock)

    #toggle_menu = i18n("&View")
    #toolbar = i18n("Views")
    title = i18n("Python outline")
    toggle_shortcut = "Alt+3"
    switch_shortcut = "Ctrl+3"
    icon = "view-list-tree"
    area = Qt.LeftDockWidgetArea
    statusbar = True


    def create_widget(self, parent):
        self.tree = None
        self.items = []
        self.connect(parent.window(), SIGNAL("active_document_changed(PyQt_PyObject)"), self.on_active_document_changed)
        self.tree = QTreeWidget(parent)
        self.tree.setFrameStyle(QFrame.NoFrame)
        self.tree.key = ""
        self.tree.is_expanded = {}
        self.tree.setHeaderLabels(["Name"])
        self.tree.setHeaderHidden(True)
        self.tree.connect(self.tree, SIGNAL("itemActivated(QTreeWidgetItem*,int)"), self.on_activated)
        self.tree.connect(self.tree, SIGNAL("itemExpanded(QTreeWidgetItem*)"), self.on_expanded)
        self.tree.connect(self.tree, SIGNAL("itemCollapsed(QTreeWidgetItem*)"), self.on_collapsed)
        #self.tree.setRootIsDecorated(False)
        editor = view().currentWidget()
        if editor:
            self.on_active_document_changed(editor)
        return self.tree


    def on_active_document_changed(self, editor):
        self.editor = editor
        if self.tree:
            #self.tree.is_expanded.clear()
            self.tree.key = str(id(editor))
            del self.items[:]
            self.tree.clear()
            if editor:
                editor.connect(editor, SIGNAL("structure_changed"), self.update)
            nodes = getattr(editor, "structure", None)
            self.update(nodes)


    def on_expanded(self, item):
        self.tree.is_expanded[item.key] = True


    def on_collapsed(self, item):
        self.tree.is_expanded[item.key] = False


    def update(self, nodes):
        del self.items[:]
        self.tree.clear()
        if not nodes:
            return
        for n in nodes:
            i = OutlineItem(self.tree, n)
            self.items.append(i)
        #self.tree.setColumnWidth(0, 48)
        self.tree.resizeColumnToContents(0)


    def on_activated(self, item, item_col):
        row = item.node.get_line_number() - 1
        self.editor.set_row_start(row)
        self.editor.centerCursor()
        self.editor.setFocus()






class FileBrowser(QTreeView):

    def __init__(self, parent):
        QTreeView.__init__(self, parent)
        #self.fs_model = QDirModel(self)
        #self.fs_model.setLazyChildCount(True)
        #self.fs_model.setNameFilters(["*.py"])
        self.fs_model = QFileSystemModel()
        #self.fs_model.setNameFilters(["*.py"])
        self.fs_model.setFilter(QDir.AllEntries)
        self.setFrameStyle(QFrame.NoFrame)
        self.fs_model = QFileSystemModel()
        self.fs_model.setNameFilters(["*.py"])
        
        #self.fs_model.setRootPath(QDir.currentPath())
        self.fs_model.setRootPath(os.path.abspath(api.Project.instance.root_path))
        self.fs_model.setNameFilterDisables(True)

        self.setModel(self.fs_model)
        #self.setCurrentIndex(self.fs_model.index(QDir.currentPath()))
        #self.setCurrentIndex(self.fs_model.index(QDir.currentPath()))
        self.setRootIndex(self.fs_model.index(QDir.currentPath()))
        self.setColumnHidden(1, True)
        self.setColumnHidden(2, True)
        self.setColumnHidden(3, True)
        self.setHeaderHidden(True)
        self.connect(self, SIGNAL("activated(const QModelIndex&)"), self.on_activated)


    def on_activated(self, idx):
        fn = unicode(self.fs_model.filePath(idx))
        if not os.path.isdir(fn):
            print "*", fn
            view().open_filename(fn)



class FileDock(DockBase):


    implements(api.Dock)

    title = i18n("Filesystem")
    toggle_shortcut = "Alt+4"
    switch_shortcut = "Ctrl+4"
    icon = "system-file-manager"
    statusbar = True
    #toggle_menu = i18n("&View")
    #toolbar = i18n("Views")
    area = Qt.LeftDockWidgetArea


    def create_widget(self, parent):
        browser = FileBrowser(parent)
        return browser