diff python/ide.py @ 248:b10d46e5c8dd

ide refactor
author Windel Bouwman
date Fri, 26 Jul 2013 16:46:02 +0200
parents dd8bbb963458
children e41e4109addd
line wrap: on
line diff
--- a/python/ide.py	Fri Jul 26 10:44:26 2013 +0200
+++ b/python/ide.py	Fri Jul 26 16:46:02 2013 +0200
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
-import sys, os, base64
-assert sys.version_info.major == 3, "Needs to be run in python version 3.x"
+import sys
+import os
 
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
@@ -9,32 +9,33 @@
 # Compiler imports:
 import ppci
 from astviewer import AstViewer
-#from codeeditor import CodeEdit
 from codeedit import CodeEdit
 stutil = __import__('st-util')
 import c3
 
+
 class BuildOutput(QTextEdit):
-   """ Build output component """
-   def __init__(self, parent=None):
+    """ Build output component """
+    def __init__(self, parent=None):
       super(BuildOutput, self).__init__(parent)
       self.setCurrentFont(QFont('Courier'))
       self.setReadOnly(True)
       self.append('Build output will appear here!')
 
+
 class BuildErrors(QTreeView):
-   sigErrorSelected = pyqtSignal(object)
-   def __init__(self, parent=None):
-      super(BuildErrors, self).__init__(parent)
-      model = QStandardItemModel()
-      self.setModel(model)
-      self.clicked.connect(self.itemSelected)
-      self.errorIcon = QIcon('icons/error.png')
-      self.model = QStandardItemModel()
-      self.model.setHorizontalHeaderLabels(['Message', 'Row', 'Column'])
-      self.setModel(self.model)
+    sigErrorSelected = pyqtSignal(object)
+    def __init__(self, parent=None):
+        super(BuildErrors, self).__init__(parent)
+        model = QStandardItemModel()
+        self.setModel(model)
+        self.clicked.connect(self.itemSelected)
+        self.errorIcon = QIcon('icons/error.png')
+        self.model = QStandardItemModel()
+        self.model.setHorizontalHeaderLabels(['Message', 'Row', 'Column'])
+        self.setModel(self.model)
 
-   def setErrorList(self, errorlist):
+    def setErrorList(self, errorlist):
       c = self.model.rowCount()
       self.model.removeRows(0, c)
       for e in errorlist:
@@ -45,7 +46,8 @@
          icol = QStandardItem(str(e.loc.col))
          icol.setData(e)
          self.model.appendRow([item, irow, icol])
-   def itemSelected(self, index):
+
+    def itemSelected(self, index):
       if not index.isValid():
          return
       item = self.model.itemFromIndex(index)
@@ -54,219 +56,200 @@
 
 
 class AboutDialog(QDialog):
-   def __init__(self, parent=None):
-      super(AboutDialog, self).__init__(parent)
-      self.setWindowTitle('About')
-      l = QVBoxLayout(self)
-      txt = QTextEdit(self)
-      txt.setReadOnly(True)
-      aboutText = """<h1>lcfOS IDE</h1>
-      <p>An all-in-one IDE for OS development.</p>
-      <p>https://www.assembla.com/spaces/lcfOS/wiki</p>
-      <p>Author: Windel Bouwman</p>
-      """
-      txt.append(aboutText)
-      l.addWidget(txt)
-      but = QPushButton('OK')
-      but.setDefault(True)
-      but.clicked.connect(self.close)
-      l.addWidget(but)
+    def __init__(self, parent=None):
+        super(AboutDialog, self).__init__(parent)
+        self.setWindowTitle('About')
+        l = QVBoxLayout(self)
+        txt = QTextEdit(self)
+        txt.setReadOnly(True)
+        aboutText = """<h1>lcfOS IDE</h1>
+        <p>An all-in-one IDE for OS development.</p>
+        <p>https://www.assembla.com/spaces/lcfOS/wiki</p>
+        <p>Author: Windel Bouwman</p>
+        """
+        txt.append(aboutText)
+        l.addWidget(txt)
+        but = QPushButton('OK')
+        but.setDefault(True)
+        but.clicked.connect(self.close)
+        l.addWidget(but)
+
 
 class Ide(QMainWindow):
-  def __init__(self, parent=None):
-    super(Ide, self).__init__(parent)
-    self.setWindowTitle('LCFOS IDE')
-    icon = QIcon('icons/logo.png')
-    self.setWindowIcon(icon)
+    def __init__(self, parent=None):
+        super(Ide, self).__init__(parent)
+        self.setWindowTitle('LCFOS IDE')
+        icon = QIcon('icons/logo.png')
+        self.setWindowIcon(icon)
 
-    # Create menus:
-    mb = self.menuBar()
-    self.fileMenu = mb.addMenu('File')
-    self.viewMenu = mb.addMenu('View')
-    self.helpMenu = mb.addMenu('Help')
-
-    # Create mdi area:
-    self.mdiArea = QMdiArea()
-    self.setCentralWidget(self.mdiArea)
+        # Create menus:
+        mb = self.menuBar()
+        self.fileMenu = mb.addMenu('File')
+        self.viewMenu = mb.addMenu('View')
+        self.helpMenu = mb.addMenu('Help')
 
-    # Create components:
-    def addComponent(name, widget):
-       dw = QDockWidget(name)
-       dw.setWidget(widget)
-       dw.setObjectName(name)
-       self.addDockWidget(Qt.RightDockWidgetArea, dw)
-       self.viewMenu.addAction(dw.toggleViewAction())
-       return widget
+        # Create mdi area:
+        self.mdiArea = QMdiArea()
+        self.mdiArea.setViewMode(QMdiArea.TabbedView)
+        self.setCentralWidget(self.mdiArea)
 
-    self.buildOutput = addComponent('Build output', BuildOutput())
-    self.astViewer = addComponent('AST viewer', AstViewer())
-    self.astViewer.sigNodeSelected.connect(self.nodeSelected)
-    self.builderrors = addComponent('Build errors', BuildErrors())
-    self.builderrors.sigErrorSelected.connect(self.errorSelected)
-    self.devxplr = addComponent('Device explorer', stutil.DeviceExplorer())
-    self.regview = addComponent('Registers', stutil.RegisterView())
-    self.memview = addComponent('Memory', stutil.MemoryView())
-    self.ctrlToolbar = stutil.DebugToolbar()
-    self.addToolBar(self.ctrlToolbar)
-    self.ctrlToolbar.setObjectName('debugToolbar')
-    self.devxplr.deviceSelected.connect(self.regview.mdl.setDevice)
-    self.ctrlToolbar.statusChange.connect(self.memview.refresh)
-    self.devxplr.deviceSelected.connect(self.memview.setDevice)
-    self.devxplr.deviceSelected.connect(self.ctrlToolbar.setDevice)
-    self.ctrlToolbar.statusChange.connect(self.regview.refresh)
-    self.ctrlToolbar.codePosition.connect(self.pointCode)
+        # Create components:
+        def addComponent(name, widget):
+           dw = QDockWidget(name)
+           dw.setWidget(widget)
+           dw.setObjectName(name)
+           self.addDockWidget(Qt.RightDockWidgetArea, dw)
+           self.viewMenu.addAction(dw.toggleViewAction())
+           return widget
 
-    # About dialog:
-    self.aboutDialog = AboutDialog()
-    self.aboutDialog.setWindowIcon(icon)
-    # Create actions:
-    def addMenuEntry(name, menu, callback, shortcut=None):
-      a = QAction(name, self)
-      menu.addAction(a)
-      a.triggered.connect(callback)
-      if shortcut:
-         a.setShortcut(shortcut)
-
-    addMenuEntry("New", self.fileMenu, self.newFile, shortcut=QKeySequence(QKeySequence.New))
-    addMenuEntry("Open", self.fileMenu, self.openFile, shortcut=QKeySequence(QKeySequence.Open))
-    addMenuEntry("Save", self.fileMenu, self.saveFile, shortcut=QKeySequence(QKeySequence.Save))
-    addMenuEntry("Build", self.fileMenu, self.buildFile, shortcut=QKeySequence("F7"))
-
-    self.helpAction  = QAction('Help', self)
-    self.helpAction.setShortcut(QKeySequence('F1'))
-    self.helpMenu.addAction(self.helpAction)
-    addMenuEntry('About', self.helpMenu, self.aboutDialog.open)
-
-    addMenuEntry('Cascade windows', self.viewMenu, self.mdiArea.cascadeSubWindows)
-    addMenuEntry('Tile windows', self.viewMenu, self.mdiArea.tileSubWindows)
+        self.buildOutput = addComponent('Build output', BuildOutput())
+        self.astViewer = addComponent('AST viewer', AstViewer())
+        self.astViewer.sigNodeSelected.connect(self.nodeSelected)
+        self.builderrors = addComponent('Build errors', BuildErrors())
+        self.builderrors.sigErrorSelected.connect(self.errorSelected)
+        self.devxplr = addComponent('Device explorer', stutil.DeviceExplorer())
+        self.regview = addComponent('Registers', stutil.RegisterView())
+        self.memview = addComponent('Memory', stutil.MemoryView())
+        self.ctrlToolbar = stutil.DebugToolbar()
+        self.addToolBar(self.ctrlToolbar)
+        self.ctrlToolbar.setObjectName('debugToolbar')
+        self.devxplr.deviceSelected.connect(self.regview.mdl.setDevice)
+        self.ctrlToolbar.statusChange.connect(self.memview.refresh)
+        self.devxplr.deviceSelected.connect(self.memview.setDevice)
+        self.devxplr.deviceSelected.connect(self.ctrlToolbar.setDevice)
+        self.ctrlToolbar.statusChange.connect(self.regview.refresh)
+        self.ctrlToolbar.codePosition.connect(self.pointCode)
 
-    sb = self.statusBar()
+        # About dialog:
+        self.aboutDialog = AboutDialog()
+        self.aboutDialog.setWindowIcon(icon)
+        # Create actions:
+        def addMenuEntry(name, menu, callback, shortcut=None):
+          a = QAction(name, self)
+          menu.addAction(a)
+          a.triggered.connect(callback)
+          if shortcut:
+             a.setShortcut(shortcut)
 
-    # Load settings:
-    self.settings = QSettings('windelsoft', 'lcfoside')
-    self.loadSettings()
-
-    ce = self.newFile()
-    self.diag = ppci.DiagnosticsManager()
-    self.c3front = c3.Builder(self.diag)
+        addMenuEntry("New", self.fileMenu, self.newFile, shortcut=QKeySequence(QKeySequence.New))
+        addMenuEntry("Open", self.fileMenu, self.openFile, shortcut=QKeySequence(QKeySequence.Open))
+        addMenuEntry("Save", self.fileMenu, self.saveFile, shortcut=QKeySequence(QKeySequence.Save))
+        addMenuEntry("Build", self.fileMenu, self.buildFile, shortcut=QKeySequence("F7"))
 
-  # File handling:
-  def newFile(self):
-     ce = CodeEdit()
-     ce.textChanged.connect(self.buildFile)
-     w = self.mdiArea.addSubWindow(ce)
-     ce.show()
-     w.resize(500, 700)
-     return ce
+        self.helpAction  = QAction('Help', self)
+        self.helpAction.setShortcut(QKeySequence('F1'))
+        self.helpMenu.addAction(self.helpAction)
+        addMenuEntry('About', self.helpMenu, self.aboutDialog.open)
+
+        addMenuEntry('Cascade windows', self.viewMenu, self.mdiArea.cascadeSubWindows)
+        addMenuEntry('Tile windows', self.viewMenu, self.mdiArea.tileSubWindows)
+        sb = self.statusBar()
 
-  def openFile(self):
-     filename = QFileDialog.getOpenFileName(self, "Open C3 file...", "*.c3", "C3 source files (*.ks)")
-     if filename:
-        self.loadFile(filename)
+        # Load settings:
+        self.settings = QSettings('windelsoft', 'lcfoside')
+        self.loadSettings()
+        self.diag = ppci.DiagnosticsManager()
+        self.c3front = c3.Builder(self.diag)
+
+    # File handling:
+    def newFile(self):
+        self.newCodeEdit()
 
-  def saveFile(self):
-     ac = self.activeMdiChild()
-     if ac:
-         ac.save()
-  
-  def loadFile(self, filename):
-     # Find existing mdi widget:
-     wid = self.findMdiChild(filename)
-     if wid:
-        self.mdiArea.setActiveSubWindow(wid.parent())
-        return wid
+    def openFile(self):
+        filename = QFileDialog.getOpenFileName(self, "Open C3 file...", "*.c3",
+            "C3 source files (*.c3)")
+        if filename:
+            self.loadFile(filename)
 
-     # Create a new one:
-     ce = CodeEdit()
+    def saveFile(self):
+        ac = self.activeMdiChild()
+        if ac:
+            ac.save()
 
-     #source = self.project.loadProjectFile(filename)
-     try:
-        with open(filename) as f:
-          source = f.read()
-          ce.setSource(source)
-     except Exception as e:
-        print('exception opening file', e)
-     self.mdiArea.addSubWindow(ce)
-     ce.setFileName(filename)
-     ce.show()
-     return ce
+    def loadFile(self, filename):
+        ce = self.newCodeEdit()
+        try:
+            with open(filename) as f:
+                ce.Source = f.read()
+                ce.FileName = filename
+        except Exception as e:
+            print('exception opening file', e)
 
-  # MDI:
-  def activeMdiChild(self):
-     aw = self.mdiArea.activeSubWindow()
-     if aw:
-        return aw.widget()
-     else:
-        return None
+    # MDI:
+    def newCodeEdit(self):
+        ce = CodeEdit()
+        ce.textChanged.connect(self.buildFile)
+        w = self.mdiArea.addSubWindow(ce)
+        ce.show()
+        return ce
+
+    def activeMdiChild(self):
+        aw = self.mdiArea.activeSubWindow()
+        if aw:
+            return aw.widget()
+
+    def findMdiChild(self, filename):
+        for wid in self.allChildren():
+            if wid.filename == filename:
+                return wid
 
-  def findMdiChild(self, filename):
-     for window in self.mdiArea.subWindowList():
-        wid = window.widget()
-        if wid.filename == filename:
-           return wid
-     return None
-  
-  def allChildren(self):
-     c = []
-     for window in self.mdiArea.subWindowList():
-        wid = window.widget()
-        c.append(wid)
-     return c
+    def allChildren(self):
+        return [w.widget() for w in self.mdiArea.subWindowList()]
+
+    # Settings:
+    def loadSettings(self):
+        if self.settings.contains('mainwindowstate'):
+            self.restoreState(self.settings.value('mainwindowstate'))
+        if self.settings.contains('mainwindowgeometry'):
+            self.restoreGeometry(self.settings.value('mainwindowgeometry'))
+        if self.settings.contains('lastfiles'):
+            lfs = self.settings.value('lastfiles')
+            for lf in lfs:
+                self.loadFile(lf)
 
-  # Settings:
-  def loadSettings(self):
-     if self.settings.contains('mainwindowstate'):
-        self.restoreState(self.settings.value('mainwindowstate'))
-     if self.settings.contains('mainwindowgeometry'):
-        self.restoreGeometry(self.settings.value('mainwindowgeometry'))
-     if self.settings.contains('lastfile'):
-        self.loadFile(self.settings.value('lastfile'))
-  
-  def closeEvent(self, ev):
-     self.settings.setValue('mainwindowstate', self.saveState())
-     self.settings.setValue('mainwindowgeometry', self.saveGeometry())
-     #   # TODO: ask for save of opened files
-     ac = self.activeMdiChild()
-     if ac:
-        if hasattr(ac, 'filename') and ac.filename:
-           self.settings.setValue('lastfile', ac.filename)
+    def closeEvent(self, ev):
+        self.settings.setValue('mainwindowstate', self.saveState())
+        self.settings.setValue('mainwindowgeometry', self.saveGeometry())
+        ac = self.activeMdiChild()
+        lfs = [ce.FileName for ce in self.allChildren() if ce.FileName]
+        self.settings.setValue('lastfiles', lfs)
+        ev.accept()
+
+    # Error handling:
+    def nodeSelected(self, node):
+        self.showLoc(node.loc)
+
+    def errorSelected(self, err):
+        self.showLoc(err.loc)
+
+    def showLoc(self, loc):
+        ce = self.activeMdiChild()
+        if not ce:
+            return
+        if loc:
+            ce.setRowCol(loc.row, loc.col)
+            ce.setFocus()
         else:
-           self.settings.remove('lastfile')
-     else:
-        self.settings.remove('lastfile')
-     ev.accept()
+            ce.clearErrors()
 
-  # Error handling:
-  def nodeSelected(self, node):
-      ce = self.activeMdiChild()
-      if not ce:
-         return
-      if node.loc:
-         row, col = node.loc.row, node.loc.col
-         ce.setRowCol(row, col)
-         ce.setFocus()
-      else:
-         ce.clearErrors()
-
-  def errorSelected(self, err):
-     ce = self.activeMdiChild()
-     if not ce:
-        return
-     ce.setRowCol(err.loc.row, err.loc.col)
-     ce.setFocus()
-
-  def pointCode(self, p):
+    def pointCode(self, p):
         print('PC', p)
 
+    # Build recepy:
+    def buildFile(self):
+        ce = self.activeMdiChild()
+        if not ce:
+            return
+        self.buildOutput.clear()
+        self.diag.clear()
+        self.buildOutput.append('Starting build')
+        ir = self.c3front.build(ce.Source)
 
-  # Build recepy:
-  def buildFile(self):
-     ce = self.activeMdiChild()
-     if ce:
-        source = ce.Source
-        self.buildOutput.clear()
-        self.buildOutput.append('Starting build')
-        ir = self.c3front.build(source)
+        # Set errors:
+        for err in self.diag.diags:
+            self.buildOutput.append(str(err))
+        self.builderrors.setErrorList(self.diag.diags)
+        ce.setErrors(self.diag.diags)
         ast = self.c3front.pkg
         self.astViewer.setAst(ast)
         self.buildOutput.append("Done!")