Mercurial > lcfOS
view python/apps/ide.py @ 64:4a27c28c7d0f
File movage
author | windel |
---|---|
date | Sun, 07 Oct 2012 17:13:47 +0200 |
parents | python/apps/runide.py@32078200cdd6 |
children | 361f7d13adea |
line wrap: on
line source
import sys from PyQt4.QtCore import * from PyQt4.QtGui import * # ide components: from .codeeditor import CodeEdit from .astviewer import AstViewer import base64 import os.path # Compiler imports: from project import Project from compiler.compiler import Compiler lcfospng = base64.decodestring(b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A\n/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEhMKBk7B678AAAA/SURBVFjD\n7dbBCQAgDATBi9h/y7EFA4Kf2QLCwH1S6XQu6sqoujublc8BAAAAAAAAAAB8B+zXT6YJAAAAAKYd\nWSgFQNUyijIAAAAASUVORK5CYII=\n') class BuildOutput(QTextEdit): """ 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(QListView): sigErrorSelected = pyqtSignal(object) def __init__(self, parent=None): super(BuildErrors, self).__init__(parent) model = QStandardItemModel() self.setModel(model) self.clicked.connect(self.itemSelected) def setErrorList(self, errorlist): model = QStandardItemModel() for e in errorlist: row, col, msg = e item = QStandardItem(str(msg)) item.setData(e) model.appendRow(item) self.setModel(model) def itemSelected(self, index): if not index.isValid(): return model = self.model() item = model.itemFromIndex(index) err = item.data() self.sigErrorSelected.emit(err) class ProjectView(QWidget): sigLoadFile = pyqtSignal(str) def __init__(self, parent=None): super(ProjectView, self).__init__(parent) self.treeview = QTreeView(self) self.treeview.setContextMenuPolicy(Qt.CustomContextMenu) l = QVBoxLayout(self) l.addWidget(self.treeview) pm = QPixmap() pm.loadFromData(lcfospng) self.projectIcon = QIcon(pm) # Connect signals: self.treeview.activated.connect(self.activate) self.treeview.customContextMenuRequested.connect(self.contextMenu) def setProject(self, project): self.project = project model = QStandardItemModel() root = model.invisibleRootItem() pitem = QStandardItem(self.projectIcon, project.name) pitem.setEditable(False) pitem.setData(project) root.appendRow(pitem) for f in self.project.files: fitem = QStandardItem(f) pitem.appendRow(fitem) fitem.setEditable(False) fitem.setData(f) self.treeview.setModel(model) self.treeview.expandAll() def contextMenu(self, pos): idx = self.treeview.indexAt(pos) if not idx.isValid(): return item = self.treeview.model().itemFromIndex(idx) def activate(self, index): if not index.isValid(): return model = self.treeview.model() item = model.itemFromIndex(index) fn = item.data() if type(fn) is str: self.sigLoadFile.emit(fn) 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) class ProjectOptions(QDialog): pass # TODO: project options in here class Ide(QMainWindow): def __init__(self, parent=None): super(Ide, self).__init__(parent) self.setWindowTitle('LCFOS IDE') icon = QPixmap() icon.loadFromData(lcfospng) self.setWindowIcon(QIcon(icon)) # Create menus: self.fileMenu = self.menuBar().addMenu('File') self.viewMenu = self.menuBar().addMenu('View') self.projectMenu = self.menuBar().addMenu('Project') self.helpMenu = self.menuBar().addMenu('Help') # Create mdi area: self.mdiArea = QMdiArea() self.setCentralWidget(self.mdiArea) # Create components: self.buildOutput = BuildOutput() self.addComponent('Build output', self.buildOutput) self.astViewer = AstViewer() self.addComponent('AST viewer', self.astViewer) self.astViewer.sigNodeSelected.connect(self.nodeSelected) self.builderrors = BuildErrors() self.addComponent('Build errors', self.builderrors) self.builderrors.sigErrorSelected.connect(self.errorSelected) self.projectview = ProjectView() self.addComponent('Project', self.projectview) self.projectview.sigLoadFile.connect(self.loadFile) # About dialog: self.aboutDialog = AboutDialog() self.aboutDialog.setWindowIcon(QIcon(icon)) # Create actions: self.buildAction = QAction('Build!', self) self.buildAction.setShortcut(QKeySequence('F7')) self.projectMenu.addAction(self.buildAction) self.buildAction.triggered.connect(self.buildFile) self.openProjectAction = QAction("Open project", self) self.openProjectAction.triggered.connect(self.openProject) self.projectMenu.addAction(self.openProjectAction) self.helpAction = QAction('Help', self) self.helpAction.setShortcut(QKeySequence('F1')) self.helpMenu.addAction(self.helpAction) self.aboutAction = QAction('About', self) self.helpMenu.addAction(self.aboutAction) self.aboutAction.triggered.connect(self.aboutDialog.open) self.newFileAction = QAction("New File", self) self.fileMenu.addAction(self.newFileAction) self.newFileAction.triggered.connect(self.newFile) self.saveFileAction = QAction("Save File", self) self.fileMenu.addAction(self.saveFileAction) self.saveFileAction.triggered.connect(self.saveFile) self.closeFileAction = QAction("Close File", self) self.fileMenu.addAction(self.closeFileAction) self.closeFileAction.triggered.connect(self.closeFile) cascadeAction = QAction("Cascade windows", self) cascadeAction.triggered.connect(self.mdiArea.cascadeSubWindows) self.viewMenu.addAction(cascadeAction) tileAction = QAction('Tile windows', self) tileAction.triggered.connect(self.mdiArea.tileSubWindows) self.viewMenu.addAction(tileAction) # Load settings: self.settings = QSettings('windelsoft', 'lcfoside') self.loadSettings() def addComponent(self, name, widget): dw = QDockWidget(name) dw.setWidget(widget) dw.setObjectName(name) self.addDockWidget(Qt.RightDockWidgetArea, dw) self.viewMenu.addAction(dw.toggleViewAction()) # File handling: def newFile(self): ce = CodeEdit() w = self.mdiArea.addSubWindow(ce) ce.show() def saveFile(self): ac = self.activeMdiChild() if ac: ac.saveFile() def saveAll(self): pass def openFile(self): # TODO pass def closeFile(self): ac = self.activeMdiChild() if ac: self.mdiArea.removeSubWindow(ac) def loadFile(self, filename): # Find existing mdi widget: wid = self.findMdiChild(filename) if wid: self.mdiArea.setActiveSubWindow(wid.parent()) return wid # Create a new one: ce = CodeEdit() source = self.project.loadProjectFile(filename) ce.setSource(source) self.mdiArea.addSubWindow(ce) ce.show() return ce # MDI: def activeMdiChild(self): aw = self.mdiArea.activeSubWindow() if aw: return aw.widget() else: return None 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 # 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('openedproject'): projectfile = self.settings.value('openedproject') self.loadProject(projectfile) def closeEvent(self, ev): self.settings.setValue('mainwindowstate', self.saveState()) self.settings.setValue('mainwindowgeometry', self.saveGeometry()) if self.project: self.settings.setValue('openedproject', self.project.filename) # TODO: ask for save of opened files ev.accept() # Error handling: def nodeSelected(self, node): ce = self.activeMdiChild() if not ce: return if node.location: row, col = node.location ce.highlightErrorLocation( row, col ) else: ce.clearErrors() def errorSelected(self, err): row, col, msg = err ce = self.activeMdiChild() if not ce: return ce.highlightErrorLocation(row, col) # Project loading: def loadProject(self, filename): self.project = Project(filename) self.projectview.setProject(self.project) def openProject(self): filename = QFileDialog.getOpenFileName(self, \ "Choose project file", "", "lcfos Project files (*.lcp)") if filename: self.loadProject(filename) # Build recepy: def buildFile(self): """ Build project """ self.saveAll() self.buildOutput.clear() self.buildOutput.append(str(self.compiler)) mods = self.compiler.compileProject(self.project) self.builderrors.setErrorList(self.compiler.errorlist) self.astViewer.setAst(mods[0]) for err in self.compiler.errorlist: self.buildOutput.append(str(err)) self.buildOutput.append("Done!") if __name__ == '__main__': app = QApplication(sys.argv) ide = Ide() ide.compiler = Compiler() ide.show() app.exec_()