changeset 95:4a37d6992bd3

movage
author windel
date Mon, 24 Dec 2012 13:24:59 +0100
parents 1be00bcfaabb
children a350055d6119
files python/apps/bouncing_cube.py python/apps/build.py python/apps/diagrameditor.py python/apps/diagramitems.py python/apps/icons.py python/apps/ide.py python/bouncing_cube.py python/build.py python/diagrameditor.py python/diagramitems.py python/icons.py python/ide.py python/libs/compiler/core/__init__.py python/libs/compiler/core/basicblock.py python/libs/compiler/core/bitreader.py python/libs/compiler/core/context.py python/libs/compiler/core/errors.py python/libs/compiler/core/function.py python/libs/compiler/core/instruction.py python/libs/compiler/core/llvmtype.py python/libs/compiler/core/module.py python/libs/compiler/core/value.py python/ppci/core/__init__.py python/ppci/core/basicblock.py python/ppci/core/bitreader.py python/ppci/core/context.py python/ppci/core/errors.py python/ppci/core/function.py python/ppci/core/instruction.py python/ppci/core/llvmtype.py python/ppci/core/module.py python/ppci/core/value.py
diffstat 32 files changed, 1628 insertions(+), 1628 deletions(-) [+]
line wrap: on
line diff
--- a/python/apps/bouncing_cube.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-from PyQt4.QtGui import *
-from PyQt4.QtCore import *
-from PyQt4.QtOpenGL import QGLWidget
-from OpenGL.GL import *
-from OpenGL.GLU import gluPerspective
-import sys
-from random import random
-from math import pi, cos, sin, fabs, sqrt
-from numpy import mat, array, ones, zeros, eye
-from numpy.linalg import norm
-import numpy as np
-import time
-import scipy.integrate
-#import pyopencl
-
-"""
-  Test script that lets a dice bounce.
-  Converted from 20-sim equations into python code.
-
-  20-sim website:
-    http://www.20sim.com
-
-"""
-def drawCube(w):
-      glBegin(GL_QUADS)			# Start Drawing The Cube
-      glColor3f(0.0,1.0,0.0)			# Set The Color To Blue
-      glVertex3f( w, w,-w)		# Top Right Of The Quad (Top)
-      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Top)
-      glVertex3f(-w, w, w)		# Bottom Left Of The Quad (Top)
-      glVertex3f( w, w, w)		# Bottom Right Of The Quad (Top)
-
-      glColor3f(1.0,0.5,0.0)			# Set The Color To Orange
-      glVertex3f( w,-w, w)		# Top Right Of The Quad (Bottom)
-      glVertex3f(-w,-w, w)		# Top Left Of The Quad (Bottom)
-      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Bottom)
-      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Bottom)
-
-      glColor3f(1.0,0.0,0.0)			# Set The Color To Red
-      glVertex3f( w, w, w)		# Top Right Of The Quad (Front)
-      glVertex3f(-w, w, w)		# Top Left Of The Quad (Front)
-      glVertex3f(-w,-w, w)		# Bottom Left Of The Quad (Front)
-      glVertex3f( w,-w, w)		# Bottom Right Of The Quad (Front)
-
-      glColor3f(1.0,1.0,0.0)			# Set The Color To Yellow
-      glVertex3f( w,-w,-w)		# Bottom Left Of The Quad (Back)
-      glVertex3f(-w,-w,-w)		# Bottom Right Of The Quad (Back)
-      glVertex3f(-w, w,-w)		# Top Right Of The Quad (Back)
-      glVertex3f( w, w,-w)		# Top Left Of The Quad (Back)
-
-      glColor3f(0.0,0.0,1.0)			# Set The Color To Blue
-      glVertex3f(-w, w, w)		# Top Right Of The Quad (Left)
-      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Left)
-      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Left)
-      glVertex3f(-w,-w, w)		# Bottom Right Of The Quad (Left)
-
-      glColor3f(1.0,0.0,1.0)			# Set The Color To Violet
-      glVertex3f( w, w,-w)		# Top Right Of The Quad (Right)
-      glVertex3f( w, w, w)		# Top Left Of The Quad (Right)
-      glVertex3f( w,-w, w)		# Bottom Left Of The Quad (Right)
-      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Right)
-      glEnd()				# Done Drawing The Quad
-
-def drawFloor(w, h):
-      glBegin(GL_QUADS)			# Start Drawing The Cube
-
-      glColor3f(1.0,0.5,0.0) # Set The Color To Orange
-      glVertex3f( w,-w,h)# Top Right Of The Quad (Bottom)
-      glVertex3f(-w,-w,h)# Top Left Of The Quad (Bottom)
-      glVertex3f(-w,w,h)# Bottom Left Of The Quad (Bottom)
-      glVertex3f( w,w,h)# Bottom Right Of The Quad (Bottom)
-      glEnd()				# Done Drawing The Quad
-
-def drawAxis():
-  glLineWidth(0.5)
-  glBegin(GL_LINES)
-  glColor3f(1.0, 0.0, 0.0)
-  glVertex3f(0,0,0)
-  glVertex3f(1,0,0)
-  glColor3f(0.0, 1.0, 0.0)
-  glVertex3f(0,0,0)
-  glVertex3f(0,1,0)
-  glColor3f(0.0, 0.0, 1.0)
-  glVertex3f(0,0,0)
-  glVertex3f(0,0,1)
-  glEnd()
-
-
-def cross(A, B):
-   a = A.A1
-   b = B.A1
-   return mat(np.cross(a, b)).T
-
-def skew(X):
-  Y = mat(zeros( (3, 3) ))
-  a,b,c = X.A1
-  Y[0,1] = -c
-  Y[0,2] = b
-  Y[1,0] = c
-  Y[1,2] = -a
-  Y[2,0] = -b
-  Y[2,1] = a
-  return Y
-
-def adjoint(T):
-  W = T[0:3, 0]
-  V = T[3:6, 0]
-  a = mat(zeros( (6,6) ) )
-  a[0:3, 0:3] = skew(W)
-  a[3:6, 0:3] = skew(V)
-  a[3:6, 3:6] = skew(W)
-  return a
-
-def Adjoint(H):
-  R = H[0:3, 0:3]
-  P = H[0:3, 3]
-  a = mat(zeros( (6,6) ) )
-  a[0:3, 0:3] = R
-  a[3:6, 3:6] = R
-  a[3:6, 0:3] = skew(P) * R
-  return a
-
-def quatToR(q):
-  x, y, z, w = q.A1
-  r = mat(eye(3))
-  r[0,0] = 1 - (2*y**2+2*z**2)
-  r[0,1] = 2*x*y+2*z*w
-  r[0,2] = 2*x*z - 2*y*w
-  r[1,0] = 2*x*y-2*z*w
-  r[1,1] = 1 - (2*x**2 + 2*z**2)
-  r[1,2] = 2*y*z + 2*x*w
-  r[2,0] = 2*x*z+2*y*w
-  r[2,1] = 2*y*z - 2*x*w
-  r[2,2] = 1 - (2*x**2+2*y**2)
-  return r
-
-def rotateAbout(axis, angle):
-   ax, ay, az = (axis/norm(axis)).A1
-   qx = ax*sin(angle/2.0)
-   qy = ay*sin(angle/2.0)
-   qz = az*sin(angle/2.0)
-   qw = cos(angle/2.0)
-   q = mat(array([qx,qy,qz,qw])).T
-   return q
-
-def normalizeQuaternion(quat):
-  x,y,z,w = quat.A1
-  magnitude = sqrt(x*x + y*y + z*z + w*w)
-  x = x / magnitude
-  y = y / magnitude
-  z = z / magnitude
-  w = w / magnitude
-  quat[0, 0] = x
-  quat[1, 0] = y
-  quat[2, 0] = z
-  quat[3, 0] = w
-  return quat
-
-def VTo4x4(V):
-    v1, v2, v3 = V.A1
-    return mat(array( \
-      [[0.0, -v3,  v2, -v1], \
-      [ v3,  0.0, -v1, -v2], \
-      [-v2, v1, 0.0, -v3], \
-      [v1, v2, v3, 0.0] ]))
-
-def homogeneous(R,p):
-    H = mat(eye(4))
-    H[0:3, 0:3] = R
-    H[0:3, 3] = p
-    return H
-
-def rateOfChange(states, thetime, parameters):
-    quat = states[0:4,  0] # Orientation (4)
-    pos  = states[4:7,  0] # Position (3)
-    P    = states[7:13, 0] # Momentum (6)
-    massI, gravity = parameters
-    # Rigid body parts:
-    # Forward Kinematic chain:
-    H = homogeneous(quatToR(quat), pos) # Forward kinematics
-
-    AdjX2 = mat(eye(6)) # The connectionpoint in the real world
-    adjAdjX2_1 = adjoint(AdjX2[0:6,0])
-    adjAdjX2_2 = adjoint(AdjX2[0:6,1])
-    adjAdjX2_3 = adjoint(AdjX2[0:6,2])
-    adjAdjX2_4 = adjoint(AdjX2[0:6,3])
-    adjAdjX2_5 = adjoint(AdjX2[0:6,4])
-    adjAdjX2_6 = adjoint(AdjX2[0:6,5])
-    AdjInv2 = Adjoint(H.I)
-    M2 = AdjInv2.T * (massI * AdjInv2) # Transfor mass to base frame
-    MassMatrix = M2
-
-    wrenchGrav2 = mat( zeros((1,6)) )
-    wrenchGrav2[0, 0:3] = -cross(gravity, pos).T
-    wrenchGrav2[0, 3:6] = gravity.T
-
-    Bk = mat( zeros( (6,6) ))
-    Bk[0:3, 0:3] = skew(P[0:3, 0])
-    Bk[3:6, 0:3] = skew(P[3:6, 0])
-    Bk[0:3, 3:6] = skew(P[3:6, 0])
-
-    # TODO: do this a cholesky:
-    v = np.linalg.solve(MassMatrix, P) # Matrix inverse like thingy !
-
-    T2_00 = v # Calculate the relative twist!
-    TM2 = T2_00.T * M2
-    twistExternal = T2_00 # Twist van het blokje
-    TMSum2 = TM2
-
-    PDotBodies = mat( zeros( (6,1)) )
-    PDotBodies[0,0] = TMSum2 * (adjAdjX2_1 * T2_00)
-    PDotBodies[1,0] = TMSum2 * (adjAdjX2_2 * T2_00)
-    PDotBodies[2,0] = TMSum2 * (adjAdjX2_3 * T2_00)
-    PDotBodies[3,0] = TMSum2 * (adjAdjX2_4 * T2_00)
-    PDotBodies[4,0] = TMSum2 * (adjAdjX2_5 * T2_00)
-    PDotBodies[5,0] = TMSum2 * (adjAdjX2_6 * T2_00)
-    
-    PDot = -PDotBodies - Bk * v
-    PDot += wrenchGrav2.T
-    
-    ##### Contact wrench part:
-    HB_W = H # Is H-matrix van het blokje
-    WrenchB = mat(zeros( (1,6) ))
-    for px in [-0.5, 0.5]:
-      for py in [-0.5, 0.5]:
-        for pz in [-0.5, 0.5]:
-          HB1_B = homogeneous(mat(eye(3)), mat([px,py,pz]).T)
-          HB1_W = HB_W * HB1_B
-          HW1_W = homogeneous(mat(eye(3)), HB1_W[0:3,3])
-          HW_W1 = HW1_W.I
-          HB_W1 = HW_W1 * HB_W
-    
-          AdjHB_W1 = Adjoint(HB_W1)
-          TB_W1_W1 = AdjHB_W1 * twistExternal
-          z = HB1_W[2, 3]
-          vx, vy, vz = TB_W1_W1[3:6, 0].A1
-          if z < 0:
-            # Contact forces:
-            Fx = -50.0*vx
-            Fy = -50.0*vy
-            Fz = -z*50000.0 
-          else:
-            Fx = 0.0
-            Fy = 0.0
-            Fz = 0.0
-          # TODO: reflect impulse
-          WrenchW1 = mat([0,0,0,0,0,Fz])
-          # Transform it back:
-          WrenchB += (AdjHB_W1.T * WrenchW1.T).T
-    ##### End of contact wrench
-
-    PDot += (WrenchB * AdjInv2).T
-
-    # Position and orientation rates:
-    QOmega = VTo4x4(v[0:3, 0])
-    quatDot = 0.5 * QOmega * quat
-    vel = v[3:6, 0]
-    posDot = skew(v[0:3]) * pos + vel
-    # The rate vector:
-    rates = mat(zeros( (13,1) ))
-    rates[0:4, 0] = quatDot
-    rates[4:7, 0] = posDot
-    rates[7:13, 0] = PDot
-    return rates
-
-def fWrapper(y, t, parameters):
-   y = mat(y).T
-   dy = rateOfChange(y, t, parameters)
-   return dy.T.A1
-  
-def SCIPY(endtime, dt, state, parameters):
-    times = np.arange(0.0, endtime, dt)
-    y0 = state.T.A1
-    res = scipy.integrate.odeint(fWrapper, y0, times, args=(parameters,))
-    states = []
-    res = res.T
-    r,c =  res.shape
-    for ci in range(0,c):
-      states.append(mat(res[:,ci]).T)
-    return states
-  
-def RK4(endtime, dt, state, parameters):
-    t = 0.0
-    states = []
-    while t < endtime:
-      newstate = mat (zeros( state.shape )) # Create a new object
-
-      #### Runge Kutta integration:
-      k1 = rateOfChange(state,             t, parameters)
-      k2 = rateOfChange(state + 0.5*dt*k1, t, parameters)
-      k3 = rateOfChange(state + 0.5*dt*k1, t, parameters)
-      k4 = rateOfChange(state + dt*k3,     t, parameters)
-      newstate = state + (dt/6.0)*(k1+2*k2+2*k3+k4)
-
-      # Normalize quat:
-      newstate[0:4, 0] = normalizeQuaternion(newstate[0:4, 0])
-      states.append(newstate)
-
-      state = newstate
-
-      t += dt
-      print state[6,0], t, ' ', (t/endtime)*100.0, '%'
-    return states
-  
-
-def simulate(endtime, dt):
-    PInitial = mat( zeros((6,1)) )
-    posInitial = mat(array([-1.2, -1.3, 2.8])).T
-    quatInitial = rotateAbout(mat(array([0.2, 1.0, 0.4])).T, 0.5)
-    # Parameters:
-    gravity = mat( array([0,0,-9.81]) ).T
-    massI = mat(eye(6)) * 1.01 # Mass matrix
-    parameters = (massI, gravity)
-
-    # The state vector!
-    state = mat(zeros( (13,1) ))
-    state[0:4, 0] = quatInitial
-    state[4:7, 0] = posInitial
-    state[7:13, 0] = PInitial
-
-    return SCIPY(endtime, dt, state, parameters)
-
-class W(QGLWidget):
-  time = 0.0
-  index = 0
-  def __init__(self, states, dt, parent=None):
-    super(W, self).__init__(parent)
-    self.firstRun = True
-    self.savePNGS = False
-    self.dt = dt
-    self.resize(500,500)
-    self.states = states
-    self.UP()
-    t = QTimer(self)
-    t.timeout.connect(self.UP)
-    t.start(self.dt*1000.0)
-
-  def UP(self):
-    self.time += self.dt
-    if self.states:
-      state = self.states[self.index]
-      self.Dicequat = state[0:4, 0]
-      self.Dicepos = state[4:7, 0]
-      self.index += 1
-      if self.index == len(self.states):
-        self.index = 0
-        self.firstRun = False
-    # Paint:
-    self.update()
-    if self.firstRun:
-       # Create png images for the movie:
-       if self.savePNGS:
-          pm = self.renderPixmap()
-          pm.save('image'+str(self.index)+'.png')
-
-  def initializeGL(self):
-      glClearColor(0.0, 0.5, 0.0, 1.0)
-      glEnable(GL_DEPTH_TEST)
-      glDepthFunc(GL_LESS)
-      glShadeModel(GL_SMOOTH)
-  def resizeGL(self,w,h):
-      glViewport(0, 0, w, h)
-      glMatrixMode(GL_PROJECTION)
-      glLoadIdentity()
-      gluPerspective(45.0, float(w)/float(h), 0.1, 100.0)
-      glMatrixMode(GL_MODELVIEW)
-  def paintGL(self):
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Clear buffers
-      glLoadIdentity() # Reset The View
-
-      glLoadIdentity()
-      glTranslatef(0.0,-2.0,-10.0) # Move Left And Into The Screen
-      glRotatef(-90.0, 1.0, 0.0, 0.0)
-      drawFloor(2.0, 0.0)
-      drawAxis()
-      self.renderText(1.0, 0.0, 0.0, 'X')
-      self.renderText(0.0, 1.0, 0.0, 'Y')
-      self.renderText(0.0, 0.0, 1.0, 'Z')
-
-      self.renderText(0.0,0.0,1.2,str(self.time))
-
-      x,y,z = self.Dicepos.A1
-      R = quatToR(self.Dicequat)
-
-      glTranslatef(x, y, z)
-      # Trick to rotate the openGL matrix:
-      r = R.A1
-      rotR = (r[0], r[3], r[6], 0.0,
-              r[1], r[4], r[7], 0.0,
-              r[2], r[5], r[8], 0.0,
-              0.0,  0.0,  0.0,  1.0)
-      glMultMatrixd(rotR)
-      
-      drawCube(0.6)
-
-et = 20.0
-dt = 0.04
-print 'starting integration... endtime =', et, ' stepsize =', dt
-t0 = time.time()
-states = simulate(et, dt)
-t1 = time.time()
-print 'That was heavy, it took me ', t1-t0, ' seconds!'
-app = QApplication(sys.argv)
-w = W(states, dt)
-w.show()
-sys.exit(app.exec_())
-
--- a/python/apps/build.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-import sys, os, argparse
-sys.path.insert(0, os.path.join('..','libs'))
-
-# Compiler imports:
-from compiler import Compiler
-from project import Project
-
-if __name__ == '__main__':
-   parser = argparse.ArgumentParser(description='Build tool to build projects')
-   parser.add_argument('project', type=str, help='the project to be build')
-   args = parser.parse_args()
-
-   try:
-      project = Project(args.project)
-   except IOError:
-      print('Failed to load {0}'.format(args.project))
-      sys.exit(3)
-   pc = Compiler()
-   pc.compileProject(project)
-
--- a/python/apps/diagrameditor.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-#!/usr/bin/python
-
-from PyQt4.QtGui import *
-from PyQt4.QtCore import *
-import sys, json, base64
-
-from diagramitems import Connection, ResizeSelectionHandle, Block, DiagramScene, CodeBlock
-from icons import newicon, saveicon, loadicon
-import diagramitems
-
-"""
- Author: Windel Bouwman
- Year: 2012
- Description: This script implements a diagram editor.
- run with python 3.x as:
-  $ python [thisfile.py]
-"""
-def indent(lines):
-   return ['   ' + line for line in lines]
-
-class ParameterDialog(QDialog):
-   def __init__(self, block, parent = None):
-      super(ParameterDialog, self).__init__(parent)
-      self.block = block
-      self.button = QPushButton('Ok', self)
-      self.nameEdit = QLineEdit(self.block.name)
-      self.codeEdit = QTextEdit(self)
-      self.codeEdit.setPlainText(self.block.code)
-      l = QFormLayout(self)
-      l.addRow('Name:', self.nameEdit)
-      l.addRow('Code:', self.codeEdit)
-      l.addWidget(self.button)
-      self.button.clicked.connect(self.OK)
-   def OK(self):
-      self.block.name = self.nameEdit.text()
-      self.block.code = self.codeEdit.toPlainText()
-      self.close()
-
-class EditorGraphicsView(QGraphicsView):
-   def __init__(self, parent=None):
-      QGraphicsView.__init__(self, parent)
-      self.setDragMode(QGraphicsView.RubberBandDrag)
-      self.delShort = QShortcut(QKeySequence.Delete, self)
-      self._model = None
-      self.treeView = QTreeView()
-      self.treeView.activated.connect(self.itemActivated)
-   def itemActivated(self, idx):
-      b = idx.internalPointer()
-      s = b.scene()
-      s.clearSelection()
-      b.setSelected(True)
-   def setDiagram(self, d):
-      self.setScene(d)
-      self.delShort.activated.connect(d.deleteItems)
-   def getModel(self): 
-      return self._model
-   def setModel(self, m):
-      self._model = m
-      if m:
-         self.treeView.setModel(m)
-         self.diagram = m.rootDiagram
-         self.model.modelReset.connect(self.treeView.expandAll)
-   model = property(getModel, setModel)
-   diagram = property(lambda s: s.scene(), setDiagram)
-   def save(self):
-      if self.model:
-         if not self.model.filename:
-            self.model.filename = QFileDialog.getSaveFileName(self)
-         if self.model.filename:
-            with open(self.model.filename, 'w') as f:
-               f.write(json.dumps(self.model.Dict, indent=2))
-   def load(self):
-      filename = QFileDialog.getOpenFileName(self)
-      if filename:
-         self.model = loadModel(filename)
-   def newModel(self):
-      self.model = ModelHierarchyModel()
-   def goUp(self):
-      if hasattr(self.diagram, 'containingBlock'):
-         self.diagram = self.diagram.containingBlock.scene()
-         self.zoomAll()
-   def showCode(self):
-      if self.model:
-         c = self.model.gencode()
-         c = '\n'.join(c)
-         d = QDialog()
-         l = QFormLayout(d)
-         codeview = QTextEdit()
-         codeview.setPlainText(c)
-         l.addRow('code', codeview)
-         runButton = QPushButton('Run')
-         outputview = QTextEdit()
-         l.addRow('Output', outputview)
-         l.addWidget(runButton)
-         def print2(txt):
-            txt2 = outputview.toPlainText()
-            outputview.setPlainText(txt2 + '\n' + txt)
-         def runIt():
-            outputview.clear()
-            globs = {'print': print2}
-            exec(codeview.toPlainText(), globs)
-         runButton.clicked.connect(runIt)
-         d.exec_()
-   def zoomAll(self):
-      """ zoom to fit all items """
-      rect = self.diagram.itemsBoundingRect()
-      self.fitInView(rect, Qt.KeepAspectRatio)
-   def wheelEvent(self, event):
-      pos = event.pos()
-      posbefore = self.mapToScene(pos)
-      degrees = event.delta() / 8.0
-      sx = (100.0 + degrees) / 100.0
-      self.scale(sx, sx)
-      event.accept()
-   def dragEnterEvent(self, event):
-      if event.mimeData().hasFormat('component/name'):
-         event.accept()
-   def dragMoveEvent(self, event):
-      if event.mimeData().hasFormat('component/name'): event.accept()
-   def dropEvent(self, event):
-      if event.mimeData().hasFormat('component/name'):
-         name = bytes(event.mimeData().data('component/name')).decode()
-         kind, name = name.split(':')
-         pos = self.mapToScene(event.pos())
-         s = self.scene()
-         print(kind, 'name:', name)
-         kind = getattr(diagramitems, kind)
-         print(kind)
-         b = kind(s.uniqify(name))
-         b.setPos(pos)
-         s.addItem(b)
-
-class LibraryModel(QStandardItemModel):
-   mimeTypes = lambda self: ['component/name']
-   def mimeData(self, idxs):
-      mimedata = QMimeData()
-      for idx in idxs:
-         if idx.isValid():
-            txt = self.data(idx, Qt.DisplayRole)
-            mimedata.setData('component/name', txt)
-      return mimedata
-
-class ModelHierarchyModel(QAbstractItemModel):
-   def __init__(self):
-      super(ModelHierarchyModel, self).__init__()
-      self.rootDiagram = DiagramScene()
-      self.rootDiagram.structureChanged.connect(self.handlechange)
-      self.filename = None
-   def handlechange(self):
-      self.modelReset.emit()
-   def setDict(self, d):
-      self.rootDiagram.Dict = d
-      self.modelReset.emit()
-   def getDict(self):
-      return self.rootDiagram.Dict
-   Dict = property(getDict, setDict)
-   def gencode(self):
-      c = ['def topLevel():']
-      c += indent(self.rootDiagram.gencode())
-      c.append('print("Running model")')
-      c.append('topLevel()')
-      c.append('print("Done")')
-      return c
-   def index(self, row, column, parent=None):
-      if parent.isValid():
-         parent = parent.internalPointer().subModel
-      else:
-         parent = self.rootDiagram
-      blocks = sorted(parent.blocks, key=lambda b:  b.name)
-      block = blocks[row]
-      # Store the index to retrieve it later in the parent function.
-      # TODO: solve this in a better way.
-      block.index = self.createIndex(row, column, block)
-      return block.index
-   def parent(self, index):
-      if index.isValid():
-         block = index.internalPointer()
-         if block.scene() == self.rootDiagram:
-            return QModelIndex()
-         else:
-            print(block)
-            outerBlock = block.scene().containingBlock
-            return outerBlock.index
-      print('parent: No valid index')
-   def data(self, index, role):
-      if index.isValid() and role == Qt.DisplayRole:
-         b = index.internalPointer()
-         if index.column() == 0:
-            return b.name
-         elif index.column() == 1:
-            return str(type(b))
-   def headerData(self, section, orientation, role):
-      if orientation == Qt.Horizontal and role == Qt.DisplayRole:
-         if section == 0:
-            return "Element"
-         elif section == 1:
-            return "Type"
-         else:
-            return "x"
-   def rowCount(self, parent):
-      if parent.column() > 0: 
-         return 0
-      if parent.isValid():
-         block = parent.internalPointer()
-         if hasattr(block, 'subModel'):
-            return len(block.subModel.blocks)
-         else:
-            return 0
-      else:
-         return len(self.rootDiagram.blocks)
-   def columnCount(self, parent):
-      return 2
-
-class LibraryWidget(QListView):
-   def __init__(self):
-      super(LibraryWidget, self).__init__(None)
-      self.libraryModel = LibraryModel(self)
-      self.libraryModel.setColumnCount(1)
-      # Create an icon with an icon:
-      pixmap = QPixmap(60, 60)
-      pixmap.fill()
-      painter = QPainter(pixmap)
-      painter.fillRect(10, 10, 40, 40, Qt.blue)
-      painter.setBrush(Qt.yellow)
-      painter.drawEllipse(20, 20, 20, 20)
-      painter.end()
-      # Fill library:
-      for name in ['CodeBlock:codeBlock', 'DiagramBlock:submod', 'Block:blk']:
-         self.libraryModel.appendRow(QStandardItem(QIcon(pixmap), name))
-      self.setModel(self.libraryModel)
-      self.setViewMode(self.IconMode)
-      self.setDragDropMode(self.DragOnly)
-
-def warning(txt):
-   QMessageBox.warning(None, "Warning", txt)
-
-def loadModel(filename):
-   try:
-      m = ModelHierarchyModel()
-      with open(filename, 'r') as f: data = f.read()
-      m.filename = filename
-      m.Dict = json.loads(data)
-      return m
-   except KeyError:
-      warning('Corrupt model: {0}'.format(filename))
-   except ValueError:
-      warning('Corrupt model: {0}'.format(filename))
-   except FileNotFoundError:
-      warning('File [{0}] not found'.format(filename))
-
-class Main(QMainWindow):
-   def __init__(self):
-      super(Main, self).__init__(None)
-      self.editor = EditorGraphicsView()
-      self.setCentralWidget(self.editor)
-      self.setWindowTitle("Diagram editor")
-      def buildIcon(b64):
-         icon = base64.decodestring(b64)
-         pm = QPixmap()
-         pm.loadFromData(icon)
-         return QIcon(pm)
-      toolbar = self.addToolBar('Tools')
-      toolbar.setObjectName('Tools')
-      def act(name, shortcut, callback, icon=None):
-         a = QAction(icon, name, self) if icon else QAction(name, self)
-         a.setShortcuts(shortcut)
-         a.triggered.connect(callback)
-         toolbar.addAction(a)
-      act('New', QKeySequence.New, self.editor.newModel, buildIcon(newicon))
-      act('Save', QKeySequence.Save, self.editor.save, buildIcon(saveicon))
-      act('Load', QKeySequence.Open, self.editor.load, buildIcon(loadicon))
-      act('Full screen', QKeySequence("F11"), self.toggleFullScreen)
-      act('Fit in view', QKeySequence("F8"), self.editor.zoomAll)
-      act('Go up', QKeySequence(Qt.Key_Up), self.editor.goUp)
-      act('Model code', QKeySequence("F7"), self.editor.showCode)
-      def addDock(name, widget):
-         dock = QDockWidget(name, self)
-         dock.setObjectName(name)
-         dock.setWidget(widget)
-         self.addDockWidget(Qt.LeftDockWidgetArea, dock)
-      addDock('Library', LibraryWidget())
-      addDock('Model tree', self.editor.treeView)
-      self.settings = QSettings('windelsoft', 'diagrameditor')
-      self.loadSettings()
-   def toggleFullScreen(self):
-      self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)
-      self.editor.zoomAll()
-   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('openedmodel'):
-         modelfile = self.settings.value('openedmodel')
-         self.editor.model = loadModel(modelfile)
-   def closeEvent(self, ev):
-      self.settings.setValue('mainwindowstate', self.saveState())
-      self.settings.setValue('mainwindowgeometry', self.saveGeometry())
-      if self.editor.model and self.editor.model.filename:
-         self.settings.setValue('openedmodel', self.editor.model.filename)
-         # TODO: ask for save of opened files
-      else:
-         self.settings.remove('openedmodel')
-      ev.accept()
-
-if __name__ == '__main__':
-   if sys.version_info.major != 3:
-      print('Please use python 3.x')
-      sys.exit(1)
-   app = QApplication(sys.argv)
-   main = Main()
-   main.show()
-   app.exec_()
-
--- a/python/apps/diagramitems.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,435 +0,0 @@
-"""
- Contains all blocks that can be used to build models.
-"""
-
-from PyQt4.QtGui import *
-from PyQt4.QtCore import *
-
-def uniqify(name, names):
-   newname, i = name, 1
-   while newname in names: newname, i = name + str(i), i + 1
-   return newname
-
-def enum(**enums):
-   return type('Enum', (), enums)
-
-Position = enum(TOP=0, TOP_RIGHT=1, RIGHT=2, BOTTOM_RIGHT=3, BOTTOM=4, BOTTOM_LEFT=5, LEFT=6, TOP_LEFT=7)
-
-def buildPath(pts):
-   path = QPainterPath(pts[0])
-   for pt in pts[1:]: path.lineTo(pt)
-   return path
-
-def equalSpace(n, l, offset=15):
-   if n == 1:
-      return [l / 2]
-   elif n > 1:
-      return [offset + (l - offset*2)/(n - 1)*i for i in range(n)]
-   return []
-
-class Connection(QGraphicsPathItem):
-   """ A connection between blocks """
-   def __init__(self, fromPort=None, toPort=None):
-      super(Connection, self).__init__()
-      self.pos2 = self.fromPort = self.toPort = None
-      self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape)
-      pen = QPen(Qt.blue, 2, cap=Qt.RoundCap)
-      self.setPen(pen)
-      self.arrowhead = QGraphicsPathItem(self)
-      self.arrowhead.setPath(buildPath([QPointF(0.0, 0.0), QPointF(-6.0, 10.0), QPointF(6.0, 10.0), QPointF(0.0, 0.0)]))
-      self.arrowhead.setPen(pen)
-      self.arrowhead.setBrush(QBrush(pen.color()))
-      self.vias = []
-      self.setFromPort(fromPort)
-      self.setToPort(toPort)
-   def getDict(self):
-      d = {}
-      d['fromBlock'] = self.fromPort.block.name
-      d['fromPort'] = self.fromPort.name
-      d['toBlock'] = self.toPort.block.name
-      d['toPort'] = self.toPort.name
-      return d
-   Dict = property(getDict)
-   def myDelete(self):
-      scene = self.scene()
-      if scene:
-         self.setFromPort(None)
-         self.setToPort(None)
-         scene.removeItem(self)
-   def setFromPort(self, fromPort):
-      if self.fromPort:
-         self.fromPort.posCallbacks.remove(self.setBeginPos)
-         self.fromPort.connection = None
-      self.fromPort = fromPort
-      if self.fromPort:
-         self.fromPort.connection = self
-         self.updateLineStukken()
-         self.fromPort.posCallbacks.append(self.setBeginPos)
-   def setToPort(self, toPort):
-      if self.toPort:
-         self.toPort.posCallbacks.remove(self.setEndPos)
-         self.toPort.connection = None
-      self.toPort = toPort
-      if self.toPort:
-         self.setEndPos(toPort.scenePos())
-         self.toPort.connection = self
-         self.toPort.posCallbacks.append(self.setEndPos)
-   def getPos1(self):
-      if self.fromPort:
-         return self.fromPort.scenePos()
-   def setBeginPos(self, pos1): self.updateLineStukken()
-   def setEndPos(self, endpos):
-      self.pos2 = endpos
-      self.updateLineStukken()
-   def itemChange(self, change, value):
-      if change == self.ItemSelectedHasChanged:
-         for via in self.vias:
-            via.setVisible(value)
-      return super(Connection, self).itemChange(change, value)
-   def shape(self): return self.myshape
-   def updateLineStukken(self):
-      """
-         This algorithm determines the optimal routing of all signals.
-         TODO: implement nice automatic line router
-      """
-      pos1 = self.getPos1()
-      pos2 = self.pos2
-      if pos1 is None or pos2 is None:
-         return
-      scene = self.scene()
-      vias = [pos1 + QPointF(20, 0)] + self.vias + [pos2 + QPointF(-20, 0)]
-      if scene:
-         litem = QGraphicsLineItem()
-         litem.setFlags(self.ItemIsSelectable)
-         scene.addItem(litem)
-         for p1, p2 in zip(vias[:-1], vias[1:]):
-            line = QLineF(p1, p2)
-            litem.setLine(line)
-            citems = scene.collidingItems(litem)
-            citems = [i for i in citems if type(i) is Block]
-         scene.removeItem(litem)
-      pts = [pos1] + vias + [pos2]
-      self.arrowhead.setPos(pos2)
-      self.arrowhead.setRotation(90)
-      p = buildPath(pts)
-      self.setPath(p)
-      """ Create a shape outline using the path stroker """
-      s = super(Connection, self).shape()
-      pps = QPainterPathStroker()
-      pps.setWidth(10)
-      self.myshape = pps.createStroke(s).simplified()
-
-class PortItem(QGraphicsPathItem):
-   """ Represents a port to a subsystem """
-   def __init__(self, name, block):
-      super(PortItem, self).__init__(block)
-      self.textItem = QGraphicsTextItem(self)
-      self.connection = None
-      self.block = block
-      self.setCursor(QCursor(Qt.CrossCursor))
-      self.setPen(QPen(Qt.blue, 2, cap=Qt.RoundCap))
-      self.name = name
-      self.posCallbacks = []
-      self.setFlag(self.ItemSendsScenePositionChanges, True)
-   def getName(self): return self.textItem.toPlainText()
-   def setName(self, name):
-      self.textItem.setPlainText(name)
-      rect = self.textItem.boundingRect()
-      lw, lh = rect.width(), rect.height()
-      lx = 3 if type(self) is InputPort else -3 - lw
-      self.textItem.setPos(lx, -lh / 2)
-   name = property(getName, setName)
-   def getDict(self): 
-      return {'name': self.name}
-   Dict = property(getDict)
-   def itemChange(self, change, value):
-      if change == self.ItemScenePositionHasChanged:
-         for cb in self.posCallbacks: cb(value)
-         return value
-      return super(PortItem, self).itemChange(change, value)
-
-class OutputPort(PortItem):
-   def __init__(self, name, block, d=10.0):
-      super(OutputPort, self).__init__(name, block)
-      self.setPath(buildPath([QPointF(0.0, -d), QPointF(d, 0), QPointF(0.0, d)]))
-   def mousePressEvent(self, event):
-      self.scene().startConnection(self)
-
-class InputPort(PortItem):
-   def __init__(self, name, block, d=10.0):
-      super(InputPort, self).__init__(name, block)
-      self.setPath(buildPath([QPointF(-d, -d), QPointF(0, 0), QPointF(-d, d)]))
-
-class Handle(QGraphicsEllipseItem):
-   """ A handle that can be moved by the mouse """
-   def __init__(self, dx=10.0, parent=None):
-      super(Handle, self).__init__(QRectF(-0.5*dx,-0.5*dx,dx,dx), parent)
-      self.setBrush(QBrush(Qt.white))
-      self.setFlags(self.ItemIsMovable)
-      self.setZValue(1)
-      self.setVisible(False)
-      self.setCursor(QCursor(Qt.SizeFDiagCursor))
-   def mouseMoveEvent(self, event):
-      """ Move function without moving the other selected elements """
-      p = self.mapToParent(event.pos())
-      self.setPos(p)
-
-class ResizeSelectionHandle(Handle):
-   def __init__(self, position, block):
-      super(ResizeSelectionHandle, self).__init__(dx=12, parent=block)
-      self.position = position
-      self.block = block
-      if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]:
-         self.setCursor(QCursor(Qt.SizeFDiagCursor))
-      elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]:
-         self.setCursor(QCursor(Qt.SizeBDiagCursor))
-      elif position in [Position.TOP, Position.BOTTOM]:
-         self.setCursor(QCursor(Qt.SizeVerCursor))
-      elif position in [Position.LEFT, Position.RIGHT]:
-         self.setCursor(QCursor(Qt.SizeHorCursor))
-   def mouseMoveEvent(self, event):
-      self.block.sizerMoveEvent(self, event.scenePos())
-
-class Block(QGraphicsRectItem):
-   """ Represents a block in the diagram. """
-   def __init__(self, name='Untitled', parent=None):
-      super(Block, self).__init__(parent)
-      self.selectionHandles = [ResizeSelectionHandle(i, self) for i in range(8)]
-      # Properties of the rectangle:
-      self.setPen(QPen(Qt.blue, 2))
-      self.setBrush(QBrush(Qt.lightGray))
-      self.setFlags(self.ItemIsSelectable | self.ItemIsMovable | self.ItemSendsScenePositionChanges)
-      self.setCursor(QCursor(Qt.PointingHandCursor))
-      self.setAcceptHoverEvents(True)
-      self.label = QGraphicsTextItem(name, self)
-      self.name = name
-      # Create corner for resize:
-      button = QPushButton('+in')
-      button.clicked.connect(self.newInputPort)
-      self.buttonItemAddInput = QGraphicsProxyWidget(self)
-      self.buttonItemAddInput.setWidget(button)
-      self.buttonItemAddInput.setVisible(False)
-      button = QPushButton('+out')
-      button.clicked.connect(self.newOutputPort)
-      self.buttonItemAddOutput = QGraphicsProxyWidget(self)
-      self.buttonItemAddOutput.setWidget(button)
-      self.buttonItemAddOutput.setVisible(False)
-      # Inputs and outputs of the block:
-      self.inputs = []
-      self.outputs = []
-      self.changeSize(2,2)
-   def editParameters(self):
-      pd = ParameterDialog(self, self.window())
-      pd.exec_()
-   def newInputPort(self):
-      names = [i.name for i in self.inputs + self.outputs]
-      self.addInput(InputPort(uniqify('in', names), self))
-   def newOutputPort(self):
-      names = [i.name for i in self.inputs + self.outputs]
-      self.addOutput(OutputPort(uniqify('out', names), self))
-   def setName(self, name): self.label.setPlainText(name)
-   def getName(self): return self.label.toPlainText()
-   name = property(getName, setName)
-   def getDict(self):
-      d = {'x': self.scenePos().x(), 'y': self.scenePos().y()}
-      rect = self.rect()
-      d.update({'width': rect.width(), 'height': rect.height()})
-      d['name'] = self.name
-      d['inputs'] = [inp.Dict for inp in self.inputs]
-      d['outputs'] = [outp.Dict for outp in self.outputs]
-      return d
-   def setDict(self, d):
-      self.name = d['name']
-      self.setPos(d['x'], d['y'])
-      self.changeSize(d['width'], d['height'])
-      for inp in d['inputs']:
-         self.addInput(InputPort(inp['name'], self))
-      for outp in d['outputs']:
-         self.addOutput(OutputPort(outp['name'], self))
-   Dict = property(getDict, setDict)
-   def addInput(self, i):
-      self.inputs.append(i)
-      self.updateSize()
-   def addOutput(self, o):
-      self.outputs.append(o)
-      self.updateSize()
-   def contextMenuEvent(self, event):
-      menu = QMenu()
-      pa = menu.addAction('Parameters')
-      pa.triggered.connect(self.editParameters)
-      menu.exec_(event.screenPos())
-   def itemChange(self, change, value):
-      if change == self.ItemSelectedHasChanged:
-         for child in [self.buttonItemAddInput, self.buttonItemAddOutput]:
-            child.setVisible(value)
-         if value:
-            self.repositionAndShowHandles()
-         else:
-            [h.setVisible(False) for h in self.selectionHandles]
-
-      return super(Block, self).itemChange(change, value)
-   def hoverEnterEvent(self, event):
-      if not self.isSelected():
-         self.repositionAndShowHandles()
-      super(Block, self).hoverEnterEvent(event)
-   def hoverLeaveEvent(self, event):
-      if not self.isSelected():
-         [h.setVisible(False) for h in self.selectionHandles]
-      super(Block, self).hoverLeaveEvent(event)
-   def myDelete(self):
-      for p in self.inputs + self.outputs:
-         if p.connection: p.connection.myDelete()
-      self.scene().removeItem(self)
-   def repositionAndShowHandles(self):
-         r = self.rect()
-         self.selectionHandles[Position.TOP_LEFT].setPos(r.topLeft())
-         self.selectionHandles[Position.TOP].setPos(r.center().x(), r.top())
-         self.selectionHandles[Position.TOP_RIGHT].setPos(r.topRight())
-         self.selectionHandles[Position.RIGHT].setPos(r.right(), r.center().y())
-         self.selectionHandles[Position.BOTTOM_RIGHT].setPos(r.bottomRight())
-         self.selectionHandles[Position.BOTTOM].setPos(r.center().x(), r.bottom())
-         self.selectionHandles[Position.BOTTOM_LEFT].setPos(r.bottomLeft())
-         self.selectionHandles[Position.LEFT].setPos(r.left(), r.center().y())
-         for h in self.selectionHandles:
-            h.setVisible(True)
-   def sizerMoveEvent(self, handle, pos):
-      r = self.rect().translated(self.pos())
-      if handle.position == Position.TOP_LEFT: r.setTopLeft(pos)
-      elif handle.position == Position.TOP: r.setTop(pos.y())
-      elif handle.position == Position.TOP_RIGHT: r.setTopRight(pos)
-      elif handle.position == Position.RIGHT: r.setRight(pos.x())
-      elif handle.position == Position.BOTTOM_RIGHT: r.setBottomRight(pos)
-      elif handle.position == Position.BOTTOM: r.setBottom(pos.y())
-      elif handle.position == Position.BOTTOM_LEFT: r.setBottomLeft(pos)
-      elif handle.position == Position.LEFT: r.setLeft(pos.x())
-      else:
-         print('invalid position')
-      self.setCenterAndSize(r.center(), r.size())
-      self.repositionAndShowHandles()
-   def updateSize(self):
-      rect = self.rect()
-      h, w = rect.height(), rect.width()
-      self.buttonItemAddInput.setPos(0, h + 4)
-      self.buttonItemAddOutput.setPos(w+10, h+4)
-      for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)):
-         inp.setPos(0.0, y)
-      for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)):
-         outp.setPos(w, y)
-   def setCenterAndSize(self, center, size):
-      self.changeSize(size.width(), size.height())
-      p = QPointF(size.width(), size.height())
-      self.setPos(center - p / 2)
-   def changeSize(self, w, h):
-      h = 20 if h < 20 else h
-      w = 40 if w < 40 else w
-      self.setRect(0.0, 0.0, w, h)
-      rect = self.label.boundingRect()
-      self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2)
-      self.updateSize()
-
-class CodeBlock(Block):
-   def __init__(self, name='Untitled', parent=None):
-      super(CodeBlock, self).__init__(name, parent)
-      self.code = ''
-   def setDict(self, d):
-      super(CodeBlock, self).setDict(d)
-      self.code = d['code']
-   def getDict(self):
-      d = super(CodeBlock, self).getDict()
-      d['code'] = self.code
-      return d
-   def gencode(self):
-      c = ['def {0}():'.format(self.name)]
-      if self.code:
-         c += indent(self.code.split('\n'))
-      else:
-         c += indent(['pass'])
-      return c
-
-class DiagramBlock(Block):
-   def __init__(self, name='Untitled', parent=None):
-      super(DiagramBlock, self).__init__(name, parent)
-      self.subModel = DiagramScene()
-      self.subModel.containingBlock = self
-   def setDict(self, d):
-      self.subModel.Dict = d['submodel']
-   def mouseDoubleClickEvent(self, event):
-      # descent into child diagram
-      #self.editParameters()
-      print('descent')
-      scene = self.scene()
-      if scene:
-         for view in scene.views():
-            view.diagram = self.subModel
-            view.zoomAll()
-
-class DiagramScene(QGraphicsScene):
-   """ A diagram scene consisting of blocks and connections """
-   structureChanged = pyqtSignal()
-   def __init__(self):
-      super(DiagramScene, self).__init__()
-      self.startedConnection = None
-
-   blocks = property(lambda sel: [i for i in sel.items() if isinstance(i, Block)])
-   connections = property(lambda sel: [i for i in sel.items() if type(i) is Connection])
-   def addItem(self, item):
-      super(DiagramScene, self).addItem(item)
-      if isinstance(item, Block):
-         self.structureChanged.emit()
-   def removeItem(self, item):
-      super(DiagramScene, self).removeItem(item)
-      if isinstance(item, Block):
-         self.structureChanged.emit()
-   def setDict(self, d):
-      for block in d['blocks']:
-         b = Block()
-         self.addItem(b)
-         b.Dict = block
-      for con in d['connections']:
-         fromPort = self.findPort(con['fromBlock'], con['fromPort'])
-         toPort = self.findPort(con['toBlock'], con['toPort'])
-         self.addItem(Connection(fromPort, toPort))
-   def getDict(self):
-      return {'blocks': [b.Dict for b in self.blocks], 'connections': [c.Dict for c in self.connections]}
-   Dict = property(getDict, setDict)
-   def gencode(self):
-      c = []
-      for b in self.blocks:
-         c += b.gencode()
-      for b in self.blocks:
-         c.append('{0}()'.format(b.name))
-      return c
-   def findPort(self, blockname, portname):
-      block = self.findBlock(blockname)
-      if block:
-         for port in block.inputs + block.outputs:
-            if port.name == portname: return port
-   def findBlock(self, blockname):
-      for block in self.blocks:
-         if block.name == blockname: return block
-   def uniqify(self, name):
-      blocknames = [item.name for item in self.blocks]
-      return uniqify(name, blocknames)
-   def mouseMoveEvent(self, event):
-      if self.startedConnection:
-         pos = event.scenePos()
-         self.startedConnection.setEndPos(pos)
-      super(DiagramScene, self).mouseMoveEvent(event)
-   def mouseReleaseEvent(self, event):
-      if self.startedConnection:
-         for item in self.items(event.scenePos()):
-            if type(item) is InputPort and item.connection == None:
-               self.startedConnection.setToPort(item)
-               self.startedConnection = None
-               return
-         self.startedConnection.myDelete()
-         self.startedConnection = None
-      super(DiagramScene, self).mouseReleaseEvent(event)
-   def startConnection(self, port):
-      self.startedConnection = Connection(port, None)
-      pos = port.scenePos()
-      self.startedConnection.setEndPos(pos)
-      self.addItem(self.startedConnection)
-   def deleteItems(self):
-      for item in list(self.selectedItems()): item.myDelete()
-
--- a/python/apps/icons.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-
-
-saveicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGGklEQVR42s2XeWxURRjAv7d3L9ay\nlJBCbAx/SIIpCWilhNLSFsrR0qUgyCmnnKVFa/xDjNbUKGIUSrlaLhEREWlZaQoC24VymBivoGJB\n/MuEtEpjoNt2z/H7Zt+8fdPdGk2MOu23MzvvzXy/+Y6ZWQX+46L8bwC2vLTlZte9e6MMRiMYjQYY\nPWYsZGXngM1iBkUxoERej1RYayJmYGrF1Dbj/31+P1xtuwQ3vvmaP6M/h8Nx69Xq6kclgDWrn2W3\nbt+G5KQkSE9Ph/E5eTB1xixIQID+yIraEMoVJYLGay4KGNS2ty8Aza4muHqpVZvClmCDHbW1igSw\neuUq1tPTA2EWRohkmJCbD9OLS+Fu14M4ZlP6M8lwSvSdEUNTwNXYCFc87iiAzQY7d9XJACuXr2Dd\n3d1gNpvBarXCxMmFUDzLCUk2S3zfKTrlqmIlYgqtTfWDXh80NZ6CNvdFnQUSYNfuXTLAimXLmV5B\nTn4hlDrLICUxHoAC+tHSTNz1jIcCw48HvX60AAK0RgGsaIE9e/fIAMuWPiMB5BZMAWfZHBiUaI1r\nAaZ+Mi32VKVqX5h/ZzwGzpxuRAtckFywt36fDLB08RIZoHAqlDhnQ0eXdwDlosFAP1APRGVoahK0\nYBBedp+XLNCwv0EGWLxwUT+AIphZ6ozNghhlEQCtrZqeqRC+QAjOftqEFogCkAX2HzwgAyxasFAC\nmFQwFaaVEIAJ5P2K6T5ln2uu0LnEHwzBZ2ea4Epr1AUU5AcPH5IBFsx/Wg5CBCgqdoLVbBxg5Xov\nDGyFQCgMF5tPI8B5CeDwkfdkgPlPzYsBmDLTCffu98b3f78OzS4s+g7Vg5Ot4G5xwdV+AEeOvi8D\nzJszV5p7IgLkT3equ9zAAPo4EMpFAIpnnrMuuKYDsCDA0WMfyABzy+bIAPlTIG9aKfzZecV0y5dc\nIdosMvzyORdc90RjwGKxwLHjH8oAZc7ZEoBj6DAYOeoxPJiMYKIDymTkbYPBoB5CkRpABByDcDjM\nJUQSDEIwFIIwyk83b0DXrx0SwPETH8kAs2eVxrhXKsrfPLnZwNOZEeDEyY9lgNLiEvYXpv1HCgGc\nPPWJDFAys/jfA8AD71RTowxQPH3GgAAK+t2IQv7X4oC+q5cSKiIORCyEyP9qLfr1AI2u0zLAjKJp\ncQHWblgPGRkZ0Q7G4uwFch8d6xXlm3jw0qEUCARgOF5yRDGZTOBqPiMDFBUUxsxLh8aa9evAbrfz\nVYuVRvVG2uKZ6COrvFj1Ao92fiL2eME+yK4pM6EFms+2yAAFeZNjAawWWF9eDqmpqVBT/ZqWZn1+\nH7y5dat2LxRmp1qY/pUtL/NgY9ju6e3lVz29Bc5dOC8D5OVMigNghfLKCg7wXOVm3kd53e31Qv3+\nBq6clAUx5/v7/I2a17mvOXBfHyTgLUgDQNdc8LTKADnZE2IAiHRz1fPgGDIEKjeW8z7aZPwBP9TW\n1WlK9QAC4p1tb2sAPp8PbLgYunFb8HgPBILgabssA0zIejIGgHy4uaoKARywacPGCABO7sOr9rs7\ntsdEOwnBkNRu34EAJnQBAz++TwB8V0WoIAZl2/VrMkDWuMdjAJISE2EjuoCCsBKjOuJrVISTbt32\nlqZMrJyiXQDt2VnHldGYYDCA7rSBGS0awvEmowmufH5dBhibOeYu+nSYHiABAdZhGg4igIoKbkqa\nnLKjpqZGWrneErTihn31XGEEIAgJOIZixqim5hdffRkFSElOUfDX0LgR6cNbMECGaBbAyF21dg2v\n+UBdkFGu6wH0z0jhgfp6vlIeuPiMrmGiUNr+0P5jcp/P5xUWoDoN/bT8kYczqjH4rCILFi5ZAvaH\n7JKPRZtMLtJPCE1Oz44cOsSh1X0KrBaLHiD47fffjcTmL/ojLhFlNCovtJjNDmRi2dnjk57IyhqM\nsWBBf1pxQjMJzmgke6rKmULJwVgQm36E8nd2dNxv9Xh+//nOHR9Ivxj4WjGRQu24+mb88psegNqE\nSQlrJH9lZmYacnNzjWlpaQpmBBdKLXXHU9QNiIkdEa0T9nq94c7OzpDb7Q63t7crTD6WFRXEj0J3\nveAfetNmUUsM6bsAAAAASUVORK5CYII=\n'
-
-loadicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACsElEQVR42u2Xf0hTURTHv++ZczlD\n6SeUREVRiRT9gFWM1rbAwr+iYAathPqjMosIQQqJQAhLLDI0CMwflRa1vyQst0oNLKxhCGWR9UfB\nwFCRaqC2vc6d7+1tr/7YnuwW5IEv95y79875vHvP7t4E/GUTpgGmAaL8vaRzpDlx3iuRXpEOkz5N\nFWDhrHR8bL+LtGXLKUqRJcoKyeUk1Q8Fges3gLIKeGlm+1QBHA4rPJ7WxG4eHqLlWoJRcvfJaPHY\nV1LPbwB5Dnja7if+BFUVQEdX7OqETdL48vD+C/DODze5e9iUCmAjgDt6FzJ+m/gG5GyD9OEz1lPY\nqwLQFrQ1JR+Amc0JPO0O941XBbAQQB0nABcBvNACbCGAWk4ABwngpRbATACXEksU7rsJGlnzUSZB\nkEdAbW9lXgnJtx0jAJ8WYCMBnE8MIESFx7+rRQRRLiaPESANmL2EAF6jgaLSCIA9Bx53sZokJpEY\nm4zFzP85BgTn0mUZUL9y7CPpz8CCvAJdA0DrE6D6NnxsLp9UaV2KVfW7Jy8QWcGUyUJhP0piFJA0\nmw6iAn19EAgAmdkICpRw5EEdsjabgXQDYo9gRZENVxVeIJO8Gjqs7y2wxoJ+IXUGxkcHkDrTqC+R\nXrt5D3AVoYU9yJs+L1bnruQLUFJO+34NpxlAc2MVCly7+ALkHQAedSKfAZwq3o/KK2X8ikvUT4ss\nkPyDWMwAtm5ai47uZn4Ag8PAAgvoxxzzGUCGMQ1DI89gMBr4ADymtwHHIXSSa1UOIt/zBqwz5/IB\nqG4Bjl9EDblFCkDN5ZM4csLJB+DoBaDWDTp3cVUBcDntaLx1hg/AzlKgvQc7yH2oAGSbjOg/WwjT\nvMzkFvdT65U34UdgDCtYGP1avoFUSMpK8gKw7q8n9bLgn/pj8n8C/ALihrxpNKi7hQAAAABJRU5E\nrkJggg==\n'
-
-newicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADSUlEQVR42r2XO0xaURjHLzYmdXRi\nYXBwdDScJl3djQNLw0TSAR88FR9JU6P4QKMCaTqQdGgXsQQMQXFwcGXhCCG+4iNEo6mDMZL45kK/\n76THUO+9Qi/efskJcm4O3+/+v8f51Al/LBaLmTs6Or43gAkq7eHhoXh2dmZva2v7WusZHf9jZGTE\nPz4+blfjuFwuC6IoCsViUbi8vCwDhM1oNH75V4AAANjUAJRKJeYc183NjXB1dVU+Pj7+CIp+qxlg\neHg44PV6VQHg2z8+PjKAu7s7oampSQAVxL29PUtnZ+eP/waA6/r6WtDr9UyJ09NTcXd319LV1aUI\n8QQwNDQUmJiYqBsA5BcMBgPLC4Q4OTkRt7e3LSaTSRbiCWBwcDAwOTmpOgfQOVSBcHFxIbS0tLB9\nDgH5IGYyGYvZbJZAvAoAOsL4IwTEngGxH9fp2MJnhUJBTKfT5t7e3rAsgMfjYQB4oB4V+OJAuI+A\naGtra6nz8/P3o6OjJQnAwMBAYGpqSjUAh8Aw8JLE3OBqIMTGxgbNZrPE5/MVFQFUe6+A4M5xoWMe\nIg4ASksB+vv761aAG3eKMFwBBFhfX6ebm5sEyl0eAHOgjqvgRSBUA3KAghHouFIAt9vNFNACgIci\nmUxSKEcyNjYmBXC5XK8Wgudvz8OAAJgDigD1lGE155UAsiFwOp2vUgVKzisBZJMQAdR2wlqco62s\nrNBcLkfgzpECOByOuhXg5cc733NLJBIMQLYP2O12BqB0uJrjyk8li8fjdGtri4AfeQAMAUpXayJW\ne2MlANlWbLPZGAB2LPagCoQapZaXl+nOzg6ZmZmRB8CBhANoYTB5U5iQyOzsrDwAjmR4hWpl0WiU\nwpxI5ubmpAAwKLAQ4HWqlUUiEbq/v0/m5+flATAEWiqwtLREDw4OyMLCgjyA1iEIh8P08PCQ+P1+\nKUBPTw8D0DIEi4uL9OjoiASDQSlAd3c3A7i/v9cUAKsgFApJAaxWa2B6etp2e3v71yGlen++X60v\n4EwAAOlUKvUO+oEUoLW19UNfX9/nxsbGhsoOxy+Wl75X2+drdXX1J/zX9AkmI+lU3N7e/hYSxAAT\n0Rs+FdX69rXsA1y5ubn5Vz6fL1Q++w30VO4/0/9IewAAAABJRU5ErkJggg==\n'
-
--- a/python/apps/ide.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-import sys, os, base64
-if sys.version_info.major != 3:
-   print("Needs to be run in python version 3.x")
-   sys.exit(1)
-
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-
-# Compiler imports:
-sys.path.insert(0, os.path.join('..','libs'))
-from project import Project
-from compiler import Compiler
-from widgets import CodeEdit, AstViewer
-
-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 el in self.project.elements:
-         fitem = QStandardItem(el)
-         pitem.appendRow(fitem)
-         fitem.setEditable(False)
-         fitem.setData(el)
-      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')
-    self.compiler = Compiler()
-    icon = QPixmap()
-    icon.loadFromData(lcfospng)
-    self.setWindowIcon(QIcon(icon))
-
-    # Create menus:
-    mb = self.menuBar()
-    self.projectMenu = mb.addMenu('Project')
-    self.viewMenu = mb.addMenu('View')
-    self.helpMenu = mb.addMenu('Help')
-
-    # Create mdi area:
-    self.mdiArea = QMdiArea()
-    self.setCentralWidget(self.mdiArea)
-
-    # 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
-
-    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.projectview = addComponent('Project explorer', ProjectView())
-    self.projectview.sigLoadFile.connect(self.loadFile)
-
-    # About dialog:
-    self.aboutDialog = AboutDialog()
-    self.aboutDialog.setWindowIcon(QIcon(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.projectMenu, self.newProject)
-    addMenuEntry("Open", self.projectMenu, self.openProject)
-    addMenuEntry("Save", self.projectMenu, self.saveProject)
-    addMenuEntry("Close", self.projectMenu, self.closeProject)
-    addMenuEntry("Build", self.projectMenu, self.buildProject, 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)
-
-    # Load settings:
-    self.settings = QSettings('windelsoft', 'lcfoside')
-    self.loadSettings()
-
-  # File handling:
-  def newProject(self):
-     filename = QFileDialog.getSaveFileName(self, \
-       "Select new projectfile", "", "lcfos Project files (*.lcp2)")
-     if filename:
-        self.project = Project()
-        self.project.filename = filename
-        self.project.save()
-
-  def saveProject(self):
-     self.project.save()
-
-  def closeProject(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
-
-  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 (*.lcp2)")
-     if filename:
-        self.loadProject(filename)
-
-  # 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:
-
-  # Build recepy:
-  def buildProject(self):
-     """ Build project """
-     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.show()
-   app.exec_()
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/bouncing_cube.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,406 @@
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+from PyQt4.QtOpenGL import QGLWidget
+from OpenGL.GL import *
+from OpenGL.GLU import gluPerspective
+import sys
+from random import random
+from math import pi, cos, sin, fabs, sqrt
+from numpy import mat, array, ones, zeros, eye
+from numpy.linalg import norm
+import numpy as np
+import time
+import scipy.integrate
+#import pyopencl
+
+"""
+  Test script that lets a dice bounce.
+  Converted from 20-sim equations into python code.
+
+  20-sim website:
+    http://www.20sim.com
+
+"""
+def drawCube(w):
+      glBegin(GL_QUADS)			# Start Drawing The Cube
+      glColor3f(0.0,1.0,0.0)			# Set The Color To Blue
+      glVertex3f( w, w,-w)		# Top Right Of The Quad (Top)
+      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Top)
+      glVertex3f(-w, w, w)		# Bottom Left Of The Quad (Top)
+      glVertex3f( w, w, w)		# Bottom Right Of The Quad (Top)
+
+      glColor3f(1.0,0.5,0.0)			# Set The Color To Orange
+      glVertex3f( w,-w, w)		# Top Right Of The Quad (Bottom)
+      glVertex3f(-w,-w, w)		# Top Left Of The Quad (Bottom)
+      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Bottom)
+      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Bottom)
+
+      glColor3f(1.0,0.0,0.0)			# Set The Color To Red
+      glVertex3f( w, w, w)		# Top Right Of The Quad (Front)
+      glVertex3f(-w, w, w)		# Top Left Of The Quad (Front)
+      glVertex3f(-w,-w, w)		# Bottom Left Of The Quad (Front)
+      glVertex3f( w,-w, w)		# Bottom Right Of The Quad (Front)
+
+      glColor3f(1.0,1.0,0.0)			# Set The Color To Yellow
+      glVertex3f( w,-w,-w)		# Bottom Left Of The Quad (Back)
+      glVertex3f(-w,-w,-w)		# Bottom Right Of The Quad (Back)
+      glVertex3f(-w, w,-w)		# Top Right Of The Quad (Back)
+      glVertex3f( w, w,-w)		# Top Left Of The Quad (Back)
+
+      glColor3f(0.0,0.0,1.0)			# Set The Color To Blue
+      glVertex3f(-w, w, w)		# Top Right Of The Quad (Left)
+      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Left)
+      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Left)
+      glVertex3f(-w,-w, w)		# Bottom Right Of The Quad (Left)
+
+      glColor3f(1.0,0.0,1.0)			# Set The Color To Violet
+      glVertex3f( w, w,-w)		# Top Right Of The Quad (Right)
+      glVertex3f( w, w, w)		# Top Left Of The Quad (Right)
+      glVertex3f( w,-w, w)		# Bottom Left Of The Quad (Right)
+      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Right)
+      glEnd()				# Done Drawing The Quad
+
+def drawFloor(w, h):
+      glBegin(GL_QUADS)			# Start Drawing The Cube
+
+      glColor3f(1.0,0.5,0.0) # Set The Color To Orange
+      glVertex3f( w,-w,h)# Top Right Of The Quad (Bottom)
+      glVertex3f(-w,-w,h)# Top Left Of The Quad (Bottom)
+      glVertex3f(-w,w,h)# Bottom Left Of The Quad (Bottom)
+      glVertex3f( w,w,h)# Bottom Right Of The Quad (Bottom)
+      glEnd()				# Done Drawing The Quad
+
+def drawAxis():
+  glLineWidth(0.5)
+  glBegin(GL_LINES)
+  glColor3f(1.0, 0.0, 0.0)
+  glVertex3f(0,0,0)
+  glVertex3f(1,0,0)
+  glColor3f(0.0, 1.0, 0.0)
+  glVertex3f(0,0,0)
+  glVertex3f(0,1,0)
+  glColor3f(0.0, 0.0, 1.0)
+  glVertex3f(0,0,0)
+  glVertex3f(0,0,1)
+  glEnd()
+
+
+def cross(A, B):
+   a = A.A1
+   b = B.A1
+   return mat(np.cross(a, b)).T
+
+def skew(X):
+  Y = mat(zeros( (3, 3) ))
+  a,b,c = X.A1
+  Y[0,1] = -c
+  Y[0,2] = b
+  Y[1,0] = c
+  Y[1,2] = -a
+  Y[2,0] = -b
+  Y[2,1] = a
+  return Y
+
+def adjoint(T):
+  W = T[0:3, 0]
+  V = T[3:6, 0]
+  a = mat(zeros( (6,6) ) )
+  a[0:3, 0:3] = skew(W)
+  a[3:6, 0:3] = skew(V)
+  a[3:6, 3:6] = skew(W)
+  return a
+
+def Adjoint(H):
+  R = H[0:3, 0:3]
+  P = H[0:3, 3]
+  a = mat(zeros( (6,6) ) )
+  a[0:3, 0:3] = R
+  a[3:6, 3:6] = R
+  a[3:6, 0:3] = skew(P) * R
+  return a
+
+def quatToR(q):
+  x, y, z, w = q.A1
+  r = mat(eye(3))
+  r[0,0] = 1 - (2*y**2+2*z**2)
+  r[0,1] = 2*x*y+2*z*w
+  r[0,2] = 2*x*z - 2*y*w
+  r[1,0] = 2*x*y-2*z*w
+  r[1,1] = 1 - (2*x**2 + 2*z**2)
+  r[1,2] = 2*y*z + 2*x*w
+  r[2,0] = 2*x*z+2*y*w
+  r[2,1] = 2*y*z - 2*x*w
+  r[2,2] = 1 - (2*x**2+2*y**2)
+  return r
+
+def rotateAbout(axis, angle):
+   ax, ay, az = (axis/norm(axis)).A1
+   qx = ax*sin(angle/2.0)
+   qy = ay*sin(angle/2.0)
+   qz = az*sin(angle/2.0)
+   qw = cos(angle/2.0)
+   q = mat(array([qx,qy,qz,qw])).T
+   return q
+
+def normalizeQuaternion(quat):
+  x,y,z,w = quat.A1
+  magnitude = sqrt(x*x + y*y + z*z + w*w)
+  x = x / magnitude
+  y = y / magnitude
+  z = z / magnitude
+  w = w / magnitude
+  quat[0, 0] = x
+  quat[1, 0] = y
+  quat[2, 0] = z
+  quat[3, 0] = w
+  return quat
+
+def VTo4x4(V):
+    v1, v2, v3 = V.A1
+    return mat(array( \
+      [[0.0, -v3,  v2, -v1], \
+      [ v3,  0.0, -v1, -v2], \
+      [-v2, v1, 0.0, -v3], \
+      [v1, v2, v3, 0.0] ]))
+
+def homogeneous(R,p):
+    H = mat(eye(4))
+    H[0:3, 0:3] = R
+    H[0:3, 3] = p
+    return H
+
+def rateOfChange(states, thetime, parameters):
+    quat = states[0:4,  0] # Orientation (4)
+    pos  = states[4:7,  0] # Position (3)
+    P    = states[7:13, 0] # Momentum (6)
+    massI, gravity = parameters
+    # Rigid body parts:
+    # Forward Kinematic chain:
+    H = homogeneous(quatToR(quat), pos) # Forward kinematics
+
+    AdjX2 = mat(eye(6)) # The connectionpoint in the real world
+    adjAdjX2_1 = adjoint(AdjX2[0:6,0])
+    adjAdjX2_2 = adjoint(AdjX2[0:6,1])
+    adjAdjX2_3 = adjoint(AdjX2[0:6,2])
+    adjAdjX2_4 = adjoint(AdjX2[0:6,3])
+    adjAdjX2_5 = adjoint(AdjX2[0:6,4])
+    adjAdjX2_6 = adjoint(AdjX2[0:6,5])
+    AdjInv2 = Adjoint(H.I)
+    M2 = AdjInv2.T * (massI * AdjInv2) # Transfor mass to base frame
+    MassMatrix = M2
+
+    wrenchGrav2 = mat( zeros((1,6)) )
+    wrenchGrav2[0, 0:3] = -cross(gravity, pos).T
+    wrenchGrav2[0, 3:6] = gravity.T
+
+    Bk = mat( zeros( (6,6) ))
+    Bk[0:3, 0:3] = skew(P[0:3, 0])
+    Bk[3:6, 0:3] = skew(P[3:6, 0])
+    Bk[0:3, 3:6] = skew(P[3:6, 0])
+
+    # TODO: do this a cholesky:
+    v = np.linalg.solve(MassMatrix, P) # Matrix inverse like thingy !
+
+    T2_00 = v # Calculate the relative twist!
+    TM2 = T2_00.T * M2
+    twistExternal = T2_00 # Twist van het blokje
+    TMSum2 = TM2
+
+    PDotBodies = mat( zeros( (6,1)) )
+    PDotBodies[0,0] = TMSum2 * (adjAdjX2_1 * T2_00)
+    PDotBodies[1,0] = TMSum2 * (adjAdjX2_2 * T2_00)
+    PDotBodies[2,0] = TMSum2 * (adjAdjX2_3 * T2_00)
+    PDotBodies[3,0] = TMSum2 * (adjAdjX2_4 * T2_00)
+    PDotBodies[4,0] = TMSum2 * (adjAdjX2_5 * T2_00)
+    PDotBodies[5,0] = TMSum2 * (adjAdjX2_6 * T2_00)
+    
+    PDot = -PDotBodies - Bk * v
+    PDot += wrenchGrav2.T
+    
+    ##### Contact wrench part:
+    HB_W = H # Is H-matrix van het blokje
+    WrenchB = mat(zeros( (1,6) ))
+    for px in [-0.5, 0.5]:
+      for py in [-0.5, 0.5]:
+        for pz in [-0.5, 0.5]:
+          HB1_B = homogeneous(mat(eye(3)), mat([px,py,pz]).T)
+          HB1_W = HB_W * HB1_B
+          HW1_W = homogeneous(mat(eye(3)), HB1_W[0:3,3])
+          HW_W1 = HW1_W.I
+          HB_W1 = HW_W1 * HB_W
+    
+          AdjHB_W1 = Adjoint(HB_W1)
+          TB_W1_W1 = AdjHB_W1 * twistExternal
+          z = HB1_W[2, 3]
+          vx, vy, vz = TB_W1_W1[3:6, 0].A1
+          if z < 0:
+            # Contact forces:
+            Fx = -50.0*vx
+            Fy = -50.0*vy
+            Fz = -z*50000.0 
+          else:
+            Fx = 0.0
+            Fy = 0.0
+            Fz = 0.0
+          # TODO: reflect impulse
+          WrenchW1 = mat([0,0,0,0,0,Fz])
+          # Transform it back:
+          WrenchB += (AdjHB_W1.T * WrenchW1.T).T
+    ##### End of contact wrench
+
+    PDot += (WrenchB * AdjInv2).T
+
+    # Position and orientation rates:
+    QOmega = VTo4x4(v[0:3, 0])
+    quatDot = 0.5 * QOmega * quat
+    vel = v[3:6, 0]
+    posDot = skew(v[0:3]) * pos + vel
+    # The rate vector:
+    rates = mat(zeros( (13,1) ))
+    rates[0:4, 0] = quatDot
+    rates[4:7, 0] = posDot
+    rates[7:13, 0] = PDot
+    return rates
+
+def fWrapper(y, t, parameters):
+   y = mat(y).T
+   dy = rateOfChange(y, t, parameters)
+   return dy.T.A1
+  
+def SCIPY(endtime, dt, state, parameters):
+    times = np.arange(0.0, endtime, dt)
+    y0 = state.T.A1
+    res = scipy.integrate.odeint(fWrapper, y0, times, args=(parameters,))
+    states = []
+    res = res.T
+    r,c =  res.shape
+    for ci in range(0,c):
+      states.append(mat(res[:,ci]).T)
+    return states
+  
+def RK4(endtime, dt, state, parameters):
+    t = 0.0
+    states = []
+    while t < endtime:
+      newstate = mat (zeros( state.shape )) # Create a new object
+
+      #### Runge Kutta integration:
+      k1 = rateOfChange(state,             t, parameters)
+      k2 = rateOfChange(state + 0.5*dt*k1, t, parameters)
+      k3 = rateOfChange(state + 0.5*dt*k1, t, parameters)
+      k4 = rateOfChange(state + dt*k3,     t, parameters)
+      newstate = state + (dt/6.0)*(k1+2*k2+2*k3+k4)
+
+      # Normalize quat:
+      newstate[0:4, 0] = normalizeQuaternion(newstate[0:4, 0])
+      states.append(newstate)
+
+      state = newstate
+
+      t += dt
+      print state[6,0], t, ' ', (t/endtime)*100.0, '%'
+    return states
+  
+
+def simulate(endtime, dt):
+    PInitial = mat( zeros((6,1)) )
+    posInitial = mat(array([-1.2, -1.3, 2.8])).T
+    quatInitial = rotateAbout(mat(array([0.2, 1.0, 0.4])).T, 0.5)
+    # Parameters:
+    gravity = mat( array([0,0,-9.81]) ).T
+    massI = mat(eye(6)) * 1.01 # Mass matrix
+    parameters = (massI, gravity)
+
+    # The state vector!
+    state = mat(zeros( (13,1) ))
+    state[0:4, 0] = quatInitial
+    state[4:7, 0] = posInitial
+    state[7:13, 0] = PInitial
+
+    return SCIPY(endtime, dt, state, parameters)
+
+class W(QGLWidget):
+  time = 0.0
+  index = 0
+  def __init__(self, states, dt, parent=None):
+    super(W, self).__init__(parent)
+    self.firstRun = True
+    self.savePNGS = False
+    self.dt = dt
+    self.resize(500,500)
+    self.states = states
+    self.UP()
+    t = QTimer(self)
+    t.timeout.connect(self.UP)
+    t.start(self.dt*1000.0)
+
+  def UP(self):
+    self.time += self.dt
+    if self.states:
+      state = self.states[self.index]
+      self.Dicequat = state[0:4, 0]
+      self.Dicepos = state[4:7, 0]
+      self.index += 1
+      if self.index == len(self.states):
+        self.index = 0
+        self.firstRun = False
+    # Paint:
+    self.update()
+    if self.firstRun:
+       # Create png images for the movie:
+       if self.savePNGS:
+          pm = self.renderPixmap()
+          pm.save('image'+str(self.index)+'.png')
+
+  def initializeGL(self):
+      glClearColor(0.0, 0.5, 0.0, 1.0)
+      glEnable(GL_DEPTH_TEST)
+      glDepthFunc(GL_LESS)
+      glShadeModel(GL_SMOOTH)
+  def resizeGL(self,w,h):
+      glViewport(0, 0, w, h)
+      glMatrixMode(GL_PROJECTION)
+      glLoadIdentity()
+      gluPerspective(45.0, float(w)/float(h), 0.1, 100.0)
+      glMatrixMode(GL_MODELVIEW)
+  def paintGL(self):
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Clear buffers
+      glLoadIdentity() # Reset The View
+
+      glLoadIdentity()
+      glTranslatef(0.0,-2.0,-10.0) # Move Left And Into The Screen
+      glRotatef(-90.0, 1.0, 0.0, 0.0)
+      drawFloor(2.0, 0.0)
+      drawAxis()
+      self.renderText(1.0, 0.0, 0.0, 'X')
+      self.renderText(0.0, 1.0, 0.0, 'Y')
+      self.renderText(0.0, 0.0, 1.0, 'Z')
+
+      self.renderText(0.0,0.0,1.2,str(self.time))
+
+      x,y,z = self.Dicepos.A1
+      R = quatToR(self.Dicequat)
+
+      glTranslatef(x, y, z)
+      # Trick to rotate the openGL matrix:
+      r = R.A1
+      rotR = (r[0], r[3], r[6], 0.0,
+              r[1], r[4], r[7], 0.0,
+              r[2], r[5], r[8], 0.0,
+              0.0,  0.0,  0.0,  1.0)
+      glMultMatrixd(rotR)
+      
+      drawCube(0.6)
+
+et = 20.0
+dt = 0.04
+print 'starting integration... endtime =', et, ' stepsize =', dt
+t0 = time.time()
+states = simulate(et, dt)
+t1 = time.time()
+print 'That was heavy, it took me ', t1-t0, ' seconds!'
+app = QApplication(sys.argv)
+w = W(states, dt)
+w.show()
+sys.exit(app.exec_())
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/build.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,20 @@
+import sys, os, argparse
+sys.path.insert(0, os.path.join('..','libs'))
+
+# Compiler imports:
+from compiler import Compiler
+from project import Project
+
+if __name__ == '__main__':
+   parser = argparse.ArgumentParser(description='Build tool to build projects')
+   parser.add_argument('project', type=str, help='the project to be build')
+   args = parser.parse_args()
+
+   try:
+      project = Project(args.project)
+   except IOError:
+      print('Failed to load {0}'.format(args.project))
+      sys.exit(3)
+   pc = Compiler()
+   pc.compileProject(project)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/diagrameditor.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,314 @@
+#!/usr/bin/python
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+import sys, json, base64
+
+from diagramitems import Connection, ResizeSelectionHandle, Block, DiagramScene, CodeBlock
+from icons import newicon, saveicon, loadicon
+import diagramitems
+
+"""
+ Author: Windel Bouwman
+ Year: 2012
+ Description: This script implements a diagram editor.
+ run with python 3.x as:
+  $ python [thisfile.py]
+"""
+def indent(lines):
+   return ['   ' + line for line in lines]
+
+class ParameterDialog(QDialog):
+   def __init__(self, block, parent = None):
+      super(ParameterDialog, self).__init__(parent)
+      self.block = block
+      self.button = QPushButton('Ok', self)
+      self.nameEdit = QLineEdit(self.block.name)
+      self.codeEdit = QTextEdit(self)
+      self.codeEdit.setPlainText(self.block.code)
+      l = QFormLayout(self)
+      l.addRow('Name:', self.nameEdit)
+      l.addRow('Code:', self.codeEdit)
+      l.addWidget(self.button)
+      self.button.clicked.connect(self.OK)
+   def OK(self):
+      self.block.name = self.nameEdit.text()
+      self.block.code = self.codeEdit.toPlainText()
+      self.close()
+
+class EditorGraphicsView(QGraphicsView):
+   def __init__(self, parent=None):
+      QGraphicsView.__init__(self, parent)
+      self.setDragMode(QGraphicsView.RubberBandDrag)
+      self.delShort = QShortcut(QKeySequence.Delete, self)
+      self._model = None
+      self.treeView = QTreeView()
+      self.treeView.activated.connect(self.itemActivated)
+   def itemActivated(self, idx):
+      b = idx.internalPointer()
+      s = b.scene()
+      s.clearSelection()
+      b.setSelected(True)
+   def setDiagram(self, d):
+      self.setScene(d)
+      self.delShort.activated.connect(d.deleteItems)
+   def getModel(self): 
+      return self._model
+   def setModel(self, m):
+      self._model = m
+      if m:
+         self.treeView.setModel(m)
+         self.diagram = m.rootDiagram
+         self.model.modelReset.connect(self.treeView.expandAll)
+   model = property(getModel, setModel)
+   diagram = property(lambda s: s.scene(), setDiagram)
+   def save(self):
+      if self.model:
+         if not self.model.filename:
+            self.model.filename = QFileDialog.getSaveFileName(self)
+         if self.model.filename:
+            with open(self.model.filename, 'w') as f:
+               f.write(json.dumps(self.model.Dict, indent=2))
+   def load(self):
+      filename = QFileDialog.getOpenFileName(self)
+      if filename:
+         self.model = loadModel(filename)
+   def newModel(self):
+      self.model = ModelHierarchyModel()
+   def goUp(self):
+      if hasattr(self.diagram, 'containingBlock'):
+         self.diagram = self.diagram.containingBlock.scene()
+         self.zoomAll()
+   def showCode(self):
+      if self.model:
+         c = self.model.gencode()
+         c = '\n'.join(c)
+         d = QDialog()
+         l = QFormLayout(d)
+         codeview = QTextEdit()
+         codeview.setPlainText(c)
+         l.addRow('code', codeview)
+         runButton = QPushButton('Run')
+         outputview = QTextEdit()
+         l.addRow('Output', outputview)
+         l.addWidget(runButton)
+         def print2(txt):
+            txt2 = outputview.toPlainText()
+            outputview.setPlainText(txt2 + '\n' + txt)
+         def runIt():
+            outputview.clear()
+            globs = {'print': print2}
+            exec(codeview.toPlainText(), globs)
+         runButton.clicked.connect(runIt)
+         d.exec_()
+   def zoomAll(self):
+      """ zoom to fit all items """
+      rect = self.diagram.itemsBoundingRect()
+      self.fitInView(rect, Qt.KeepAspectRatio)
+   def wheelEvent(self, event):
+      pos = event.pos()
+      posbefore = self.mapToScene(pos)
+      degrees = event.delta() / 8.0
+      sx = (100.0 + degrees) / 100.0
+      self.scale(sx, sx)
+      event.accept()
+   def dragEnterEvent(self, event):
+      if event.mimeData().hasFormat('component/name'):
+         event.accept()
+   def dragMoveEvent(self, event):
+      if event.mimeData().hasFormat('component/name'): event.accept()
+   def dropEvent(self, event):
+      if event.mimeData().hasFormat('component/name'):
+         name = bytes(event.mimeData().data('component/name')).decode()
+         kind, name = name.split(':')
+         pos = self.mapToScene(event.pos())
+         s = self.scene()
+         print(kind, 'name:', name)
+         kind = getattr(diagramitems, kind)
+         print(kind)
+         b = kind(s.uniqify(name))
+         b.setPos(pos)
+         s.addItem(b)
+
+class LibraryModel(QStandardItemModel):
+   mimeTypes = lambda self: ['component/name']
+   def mimeData(self, idxs):
+      mimedata = QMimeData()
+      for idx in idxs:
+         if idx.isValid():
+            txt = self.data(idx, Qt.DisplayRole)
+            mimedata.setData('component/name', txt)
+      return mimedata
+
+class ModelHierarchyModel(QAbstractItemModel):
+   def __init__(self):
+      super(ModelHierarchyModel, self).__init__()
+      self.rootDiagram = DiagramScene()
+      self.rootDiagram.structureChanged.connect(self.handlechange)
+      self.filename = None
+   def handlechange(self):
+      self.modelReset.emit()
+   def setDict(self, d):
+      self.rootDiagram.Dict = d
+      self.modelReset.emit()
+   def getDict(self):
+      return self.rootDiagram.Dict
+   Dict = property(getDict, setDict)
+   def gencode(self):
+      c = ['def topLevel():']
+      c += indent(self.rootDiagram.gencode())
+      c.append('print("Running model")')
+      c.append('topLevel()')
+      c.append('print("Done")')
+      return c
+   def index(self, row, column, parent=None):
+      if parent.isValid():
+         parent = parent.internalPointer().subModel
+      else:
+         parent = self.rootDiagram
+      blocks = sorted(parent.blocks, key=lambda b:  b.name)
+      block = blocks[row]
+      # Store the index to retrieve it later in the parent function.
+      # TODO: solve this in a better way.
+      block.index = self.createIndex(row, column, block)
+      return block.index
+   def parent(self, index):
+      if index.isValid():
+         block = index.internalPointer()
+         if block.scene() == self.rootDiagram:
+            return QModelIndex()
+         else:
+            print(block)
+            outerBlock = block.scene().containingBlock
+            return outerBlock.index
+      print('parent: No valid index')
+   def data(self, index, role):
+      if index.isValid() and role == Qt.DisplayRole:
+         b = index.internalPointer()
+         if index.column() == 0:
+            return b.name
+         elif index.column() == 1:
+            return str(type(b))
+   def headerData(self, section, orientation, role):
+      if orientation == Qt.Horizontal and role == Qt.DisplayRole:
+         if section == 0:
+            return "Element"
+         elif section == 1:
+            return "Type"
+         else:
+            return "x"
+   def rowCount(self, parent):
+      if parent.column() > 0: 
+         return 0
+      if parent.isValid():
+         block = parent.internalPointer()
+         if hasattr(block, 'subModel'):
+            return len(block.subModel.blocks)
+         else:
+            return 0
+      else:
+         return len(self.rootDiagram.blocks)
+   def columnCount(self, parent):
+      return 2
+
+class LibraryWidget(QListView):
+   def __init__(self):
+      super(LibraryWidget, self).__init__(None)
+      self.libraryModel = LibraryModel(self)
+      self.libraryModel.setColumnCount(1)
+      # Create an icon with an icon:
+      pixmap = QPixmap(60, 60)
+      pixmap.fill()
+      painter = QPainter(pixmap)
+      painter.fillRect(10, 10, 40, 40, Qt.blue)
+      painter.setBrush(Qt.yellow)
+      painter.drawEllipse(20, 20, 20, 20)
+      painter.end()
+      # Fill library:
+      for name in ['CodeBlock:codeBlock', 'DiagramBlock:submod', 'Block:blk']:
+         self.libraryModel.appendRow(QStandardItem(QIcon(pixmap), name))
+      self.setModel(self.libraryModel)
+      self.setViewMode(self.IconMode)
+      self.setDragDropMode(self.DragOnly)
+
+def warning(txt):
+   QMessageBox.warning(None, "Warning", txt)
+
+def loadModel(filename):
+   try:
+      m = ModelHierarchyModel()
+      with open(filename, 'r') as f: data = f.read()
+      m.filename = filename
+      m.Dict = json.loads(data)
+      return m
+   except KeyError:
+      warning('Corrupt model: {0}'.format(filename))
+   except ValueError:
+      warning('Corrupt model: {0}'.format(filename))
+   except FileNotFoundError:
+      warning('File [{0}] not found'.format(filename))
+
+class Main(QMainWindow):
+   def __init__(self):
+      super(Main, self).__init__(None)
+      self.editor = EditorGraphicsView()
+      self.setCentralWidget(self.editor)
+      self.setWindowTitle("Diagram editor")
+      def buildIcon(b64):
+         icon = base64.decodestring(b64)
+         pm = QPixmap()
+         pm.loadFromData(icon)
+         return QIcon(pm)
+      toolbar = self.addToolBar('Tools')
+      toolbar.setObjectName('Tools')
+      def act(name, shortcut, callback, icon=None):
+         a = QAction(icon, name, self) if icon else QAction(name, self)
+         a.setShortcuts(shortcut)
+         a.triggered.connect(callback)
+         toolbar.addAction(a)
+      act('New', QKeySequence.New, self.editor.newModel, buildIcon(newicon))
+      act('Save', QKeySequence.Save, self.editor.save, buildIcon(saveicon))
+      act('Load', QKeySequence.Open, self.editor.load, buildIcon(loadicon))
+      act('Full screen', QKeySequence("F11"), self.toggleFullScreen)
+      act('Fit in view', QKeySequence("F8"), self.editor.zoomAll)
+      act('Go up', QKeySequence(Qt.Key_Up), self.editor.goUp)
+      act('Model code', QKeySequence("F7"), self.editor.showCode)
+      def addDock(name, widget):
+         dock = QDockWidget(name, self)
+         dock.setObjectName(name)
+         dock.setWidget(widget)
+         self.addDockWidget(Qt.LeftDockWidgetArea, dock)
+      addDock('Library', LibraryWidget())
+      addDock('Model tree', self.editor.treeView)
+      self.settings = QSettings('windelsoft', 'diagrameditor')
+      self.loadSettings()
+   def toggleFullScreen(self):
+      self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)
+      self.editor.zoomAll()
+   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('openedmodel'):
+         modelfile = self.settings.value('openedmodel')
+         self.editor.model = loadModel(modelfile)
+   def closeEvent(self, ev):
+      self.settings.setValue('mainwindowstate', self.saveState())
+      self.settings.setValue('mainwindowgeometry', self.saveGeometry())
+      if self.editor.model and self.editor.model.filename:
+         self.settings.setValue('openedmodel', self.editor.model.filename)
+         # TODO: ask for save of opened files
+      else:
+         self.settings.remove('openedmodel')
+      ev.accept()
+
+if __name__ == '__main__':
+   if sys.version_info.major != 3:
+      print('Please use python 3.x')
+      sys.exit(1)
+   app = QApplication(sys.argv)
+   main = Main()
+   main.show()
+   app.exec_()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/diagramitems.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,435 @@
+"""
+ Contains all blocks that can be used to build models.
+"""
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+
+def uniqify(name, names):
+   newname, i = name, 1
+   while newname in names: newname, i = name + str(i), i + 1
+   return newname
+
+def enum(**enums):
+   return type('Enum', (), enums)
+
+Position = enum(TOP=0, TOP_RIGHT=1, RIGHT=2, BOTTOM_RIGHT=3, BOTTOM=4, BOTTOM_LEFT=5, LEFT=6, TOP_LEFT=7)
+
+def buildPath(pts):
+   path = QPainterPath(pts[0])
+   for pt in pts[1:]: path.lineTo(pt)
+   return path
+
+def equalSpace(n, l, offset=15):
+   if n == 1:
+      return [l / 2]
+   elif n > 1:
+      return [offset + (l - offset*2)/(n - 1)*i for i in range(n)]
+   return []
+
+class Connection(QGraphicsPathItem):
+   """ A connection between blocks """
+   def __init__(self, fromPort=None, toPort=None):
+      super(Connection, self).__init__()
+      self.pos2 = self.fromPort = self.toPort = None
+      self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape)
+      pen = QPen(Qt.blue, 2, cap=Qt.RoundCap)
+      self.setPen(pen)
+      self.arrowhead = QGraphicsPathItem(self)
+      self.arrowhead.setPath(buildPath([QPointF(0.0, 0.0), QPointF(-6.0, 10.0), QPointF(6.0, 10.0), QPointF(0.0, 0.0)]))
+      self.arrowhead.setPen(pen)
+      self.arrowhead.setBrush(QBrush(pen.color()))
+      self.vias = []
+      self.setFromPort(fromPort)
+      self.setToPort(toPort)
+   def getDict(self):
+      d = {}
+      d['fromBlock'] = self.fromPort.block.name
+      d['fromPort'] = self.fromPort.name
+      d['toBlock'] = self.toPort.block.name
+      d['toPort'] = self.toPort.name
+      return d
+   Dict = property(getDict)
+   def myDelete(self):
+      scene = self.scene()
+      if scene:
+         self.setFromPort(None)
+         self.setToPort(None)
+         scene.removeItem(self)
+   def setFromPort(self, fromPort):
+      if self.fromPort:
+         self.fromPort.posCallbacks.remove(self.setBeginPos)
+         self.fromPort.connection = None
+      self.fromPort = fromPort
+      if self.fromPort:
+         self.fromPort.connection = self
+         self.updateLineStukken()
+         self.fromPort.posCallbacks.append(self.setBeginPos)
+   def setToPort(self, toPort):
+      if self.toPort:
+         self.toPort.posCallbacks.remove(self.setEndPos)
+         self.toPort.connection = None
+      self.toPort = toPort
+      if self.toPort:
+         self.setEndPos(toPort.scenePos())
+         self.toPort.connection = self
+         self.toPort.posCallbacks.append(self.setEndPos)
+   def getPos1(self):
+      if self.fromPort:
+         return self.fromPort.scenePos()
+   def setBeginPos(self, pos1): self.updateLineStukken()
+   def setEndPos(self, endpos):
+      self.pos2 = endpos
+      self.updateLineStukken()
+   def itemChange(self, change, value):
+      if change == self.ItemSelectedHasChanged:
+         for via in self.vias:
+            via.setVisible(value)
+      return super(Connection, self).itemChange(change, value)
+   def shape(self): return self.myshape
+   def updateLineStukken(self):
+      """
+         This algorithm determines the optimal routing of all signals.
+         TODO: implement nice automatic line router
+      """
+      pos1 = self.getPos1()
+      pos2 = self.pos2
+      if pos1 is None or pos2 is None:
+         return
+      scene = self.scene()
+      vias = [pos1 + QPointF(20, 0)] + self.vias + [pos2 + QPointF(-20, 0)]
+      if scene:
+         litem = QGraphicsLineItem()
+         litem.setFlags(self.ItemIsSelectable)
+         scene.addItem(litem)
+         for p1, p2 in zip(vias[:-1], vias[1:]):
+            line = QLineF(p1, p2)
+            litem.setLine(line)
+            citems = scene.collidingItems(litem)
+            citems = [i for i in citems if type(i) is Block]
+         scene.removeItem(litem)
+      pts = [pos1] + vias + [pos2]
+      self.arrowhead.setPos(pos2)
+      self.arrowhead.setRotation(90)
+      p = buildPath(pts)
+      self.setPath(p)
+      """ Create a shape outline using the path stroker """
+      s = super(Connection, self).shape()
+      pps = QPainterPathStroker()
+      pps.setWidth(10)
+      self.myshape = pps.createStroke(s).simplified()
+
+class PortItem(QGraphicsPathItem):
+   """ Represents a port to a subsystem """
+   def __init__(self, name, block):
+      super(PortItem, self).__init__(block)
+      self.textItem = QGraphicsTextItem(self)
+      self.connection = None
+      self.block = block
+      self.setCursor(QCursor(Qt.CrossCursor))
+      self.setPen(QPen(Qt.blue, 2, cap=Qt.RoundCap))
+      self.name = name
+      self.posCallbacks = []
+      self.setFlag(self.ItemSendsScenePositionChanges, True)
+   def getName(self): return self.textItem.toPlainText()
+   def setName(self, name):
+      self.textItem.setPlainText(name)
+      rect = self.textItem.boundingRect()
+      lw, lh = rect.width(), rect.height()
+      lx = 3 if type(self) is InputPort else -3 - lw
+      self.textItem.setPos(lx, -lh / 2)
+   name = property(getName, setName)
+   def getDict(self): 
+      return {'name': self.name}
+   Dict = property(getDict)
+   def itemChange(self, change, value):
+      if change == self.ItemScenePositionHasChanged:
+         for cb in self.posCallbacks: cb(value)
+         return value
+      return super(PortItem, self).itemChange(change, value)
+
+class OutputPort(PortItem):
+   def __init__(self, name, block, d=10.0):
+      super(OutputPort, self).__init__(name, block)
+      self.setPath(buildPath([QPointF(0.0, -d), QPointF(d, 0), QPointF(0.0, d)]))
+   def mousePressEvent(self, event):
+      self.scene().startConnection(self)
+
+class InputPort(PortItem):
+   def __init__(self, name, block, d=10.0):
+      super(InputPort, self).__init__(name, block)
+      self.setPath(buildPath([QPointF(-d, -d), QPointF(0, 0), QPointF(-d, d)]))
+
+class Handle(QGraphicsEllipseItem):
+   """ A handle that can be moved by the mouse """
+   def __init__(self, dx=10.0, parent=None):
+      super(Handle, self).__init__(QRectF(-0.5*dx,-0.5*dx,dx,dx), parent)
+      self.setBrush(QBrush(Qt.white))
+      self.setFlags(self.ItemIsMovable)
+      self.setZValue(1)
+      self.setVisible(False)
+      self.setCursor(QCursor(Qt.SizeFDiagCursor))
+   def mouseMoveEvent(self, event):
+      """ Move function without moving the other selected elements """
+      p = self.mapToParent(event.pos())
+      self.setPos(p)
+
+class ResizeSelectionHandle(Handle):
+   def __init__(self, position, block):
+      super(ResizeSelectionHandle, self).__init__(dx=12, parent=block)
+      self.position = position
+      self.block = block
+      if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]:
+         self.setCursor(QCursor(Qt.SizeFDiagCursor))
+      elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]:
+         self.setCursor(QCursor(Qt.SizeBDiagCursor))
+      elif position in [Position.TOP, Position.BOTTOM]:
+         self.setCursor(QCursor(Qt.SizeVerCursor))
+      elif position in [Position.LEFT, Position.RIGHT]:
+         self.setCursor(QCursor(Qt.SizeHorCursor))
+   def mouseMoveEvent(self, event):
+      self.block.sizerMoveEvent(self, event.scenePos())
+
+class Block(QGraphicsRectItem):
+   """ Represents a block in the diagram. """
+   def __init__(self, name='Untitled', parent=None):
+      super(Block, self).__init__(parent)
+      self.selectionHandles = [ResizeSelectionHandle(i, self) for i in range(8)]
+      # Properties of the rectangle:
+      self.setPen(QPen(Qt.blue, 2))
+      self.setBrush(QBrush(Qt.lightGray))
+      self.setFlags(self.ItemIsSelectable | self.ItemIsMovable | self.ItemSendsScenePositionChanges)
+      self.setCursor(QCursor(Qt.PointingHandCursor))
+      self.setAcceptHoverEvents(True)
+      self.label = QGraphicsTextItem(name, self)
+      self.name = name
+      # Create corner for resize:
+      button = QPushButton('+in')
+      button.clicked.connect(self.newInputPort)
+      self.buttonItemAddInput = QGraphicsProxyWidget(self)
+      self.buttonItemAddInput.setWidget(button)
+      self.buttonItemAddInput.setVisible(False)
+      button = QPushButton('+out')
+      button.clicked.connect(self.newOutputPort)
+      self.buttonItemAddOutput = QGraphicsProxyWidget(self)
+      self.buttonItemAddOutput.setWidget(button)
+      self.buttonItemAddOutput.setVisible(False)
+      # Inputs and outputs of the block:
+      self.inputs = []
+      self.outputs = []
+      self.changeSize(2,2)
+   def editParameters(self):
+      pd = ParameterDialog(self, self.window())
+      pd.exec_()
+   def newInputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addInput(InputPort(uniqify('in', names), self))
+   def newOutputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addOutput(OutputPort(uniqify('out', names), self))
+   def setName(self, name): self.label.setPlainText(name)
+   def getName(self): return self.label.toPlainText()
+   name = property(getName, setName)
+   def getDict(self):
+      d = {'x': self.scenePos().x(), 'y': self.scenePos().y()}
+      rect = self.rect()
+      d.update({'width': rect.width(), 'height': rect.height()})
+      d['name'] = self.name
+      d['inputs'] = [inp.Dict for inp in self.inputs]
+      d['outputs'] = [outp.Dict for outp in self.outputs]
+      return d
+   def setDict(self, d):
+      self.name = d['name']
+      self.setPos(d['x'], d['y'])
+      self.changeSize(d['width'], d['height'])
+      for inp in d['inputs']:
+         self.addInput(InputPort(inp['name'], self))
+      for outp in d['outputs']:
+         self.addOutput(OutputPort(outp['name'], self))
+   Dict = property(getDict, setDict)
+   def addInput(self, i):
+      self.inputs.append(i)
+      self.updateSize()
+   def addOutput(self, o):
+      self.outputs.append(o)
+      self.updateSize()
+   def contextMenuEvent(self, event):
+      menu = QMenu()
+      pa = menu.addAction('Parameters')
+      pa.triggered.connect(self.editParameters)
+      menu.exec_(event.screenPos())
+   def itemChange(self, change, value):
+      if change == self.ItemSelectedHasChanged:
+         for child in [self.buttonItemAddInput, self.buttonItemAddOutput]:
+            child.setVisible(value)
+         if value:
+            self.repositionAndShowHandles()
+         else:
+            [h.setVisible(False) for h in self.selectionHandles]
+
+      return super(Block, self).itemChange(change, value)
+   def hoverEnterEvent(self, event):
+      if not self.isSelected():
+         self.repositionAndShowHandles()
+      super(Block, self).hoverEnterEvent(event)
+   def hoverLeaveEvent(self, event):
+      if not self.isSelected():
+         [h.setVisible(False) for h in self.selectionHandles]
+      super(Block, self).hoverLeaveEvent(event)
+   def myDelete(self):
+      for p in self.inputs + self.outputs:
+         if p.connection: p.connection.myDelete()
+      self.scene().removeItem(self)
+   def repositionAndShowHandles(self):
+         r = self.rect()
+         self.selectionHandles[Position.TOP_LEFT].setPos(r.topLeft())
+         self.selectionHandles[Position.TOP].setPos(r.center().x(), r.top())
+         self.selectionHandles[Position.TOP_RIGHT].setPos(r.topRight())
+         self.selectionHandles[Position.RIGHT].setPos(r.right(), r.center().y())
+         self.selectionHandles[Position.BOTTOM_RIGHT].setPos(r.bottomRight())
+         self.selectionHandles[Position.BOTTOM].setPos(r.center().x(), r.bottom())
+         self.selectionHandles[Position.BOTTOM_LEFT].setPos(r.bottomLeft())
+         self.selectionHandles[Position.LEFT].setPos(r.left(), r.center().y())
+         for h in self.selectionHandles:
+            h.setVisible(True)
+   def sizerMoveEvent(self, handle, pos):
+      r = self.rect().translated(self.pos())
+      if handle.position == Position.TOP_LEFT: r.setTopLeft(pos)
+      elif handle.position == Position.TOP: r.setTop(pos.y())
+      elif handle.position == Position.TOP_RIGHT: r.setTopRight(pos)
+      elif handle.position == Position.RIGHT: r.setRight(pos.x())
+      elif handle.position == Position.BOTTOM_RIGHT: r.setBottomRight(pos)
+      elif handle.position == Position.BOTTOM: r.setBottom(pos.y())
+      elif handle.position == Position.BOTTOM_LEFT: r.setBottomLeft(pos)
+      elif handle.position == Position.LEFT: r.setLeft(pos.x())
+      else:
+         print('invalid position')
+      self.setCenterAndSize(r.center(), r.size())
+      self.repositionAndShowHandles()
+   def updateSize(self):
+      rect = self.rect()
+      h, w = rect.height(), rect.width()
+      self.buttonItemAddInput.setPos(0, h + 4)
+      self.buttonItemAddOutput.setPos(w+10, h+4)
+      for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)):
+         inp.setPos(0.0, y)
+      for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)):
+         outp.setPos(w, y)
+   def setCenterAndSize(self, center, size):
+      self.changeSize(size.width(), size.height())
+      p = QPointF(size.width(), size.height())
+      self.setPos(center - p / 2)
+   def changeSize(self, w, h):
+      h = 20 if h < 20 else h
+      w = 40 if w < 40 else w
+      self.setRect(0.0, 0.0, w, h)
+      rect = self.label.boundingRect()
+      self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2)
+      self.updateSize()
+
+class CodeBlock(Block):
+   def __init__(self, name='Untitled', parent=None):
+      super(CodeBlock, self).__init__(name, parent)
+      self.code = ''
+   def setDict(self, d):
+      super(CodeBlock, self).setDict(d)
+      self.code = d['code']
+   def getDict(self):
+      d = super(CodeBlock, self).getDict()
+      d['code'] = self.code
+      return d
+   def gencode(self):
+      c = ['def {0}():'.format(self.name)]
+      if self.code:
+         c += indent(self.code.split('\n'))
+      else:
+         c += indent(['pass'])
+      return c
+
+class DiagramBlock(Block):
+   def __init__(self, name='Untitled', parent=None):
+      super(DiagramBlock, self).__init__(name, parent)
+      self.subModel = DiagramScene()
+      self.subModel.containingBlock = self
+   def setDict(self, d):
+      self.subModel.Dict = d['submodel']
+   def mouseDoubleClickEvent(self, event):
+      # descent into child diagram
+      #self.editParameters()
+      print('descent')
+      scene = self.scene()
+      if scene:
+         for view in scene.views():
+            view.diagram = self.subModel
+            view.zoomAll()
+
+class DiagramScene(QGraphicsScene):
+   """ A diagram scene consisting of blocks and connections """
+   structureChanged = pyqtSignal()
+   def __init__(self):
+      super(DiagramScene, self).__init__()
+      self.startedConnection = None
+
+   blocks = property(lambda sel: [i for i in sel.items() if isinstance(i, Block)])
+   connections = property(lambda sel: [i for i in sel.items() if type(i) is Connection])
+   def addItem(self, item):
+      super(DiagramScene, self).addItem(item)
+      if isinstance(item, Block):
+         self.structureChanged.emit()
+   def removeItem(self, item):
+      super(DiagramScene, self).removeItem(item)
+      if isinstance(item, Block):
+         self.structureChanged.emit()
+   def setDict(self, d):
+      for block in d['blocks']:
+         b = Block()
+         self.addItem(b)
+         b.Dict = block
+      for con in d['connections']:
+         fromPort = self.findPort(con['fromBlock'], con['fromPort'])
+         toPort = self.findPort(con['toBlock'], con['toPort'])
+         self.addItem(Connection(fromPort, toPort))
+   def getDict(self):
+      return {'blocks': [b.Dict for b in self.blocks], 'connections': [c.Dict for c in self.connections]}
+   Dict = property(getDict, setDict)
+   def gencode(self):
+      c = []
+      for b in self.blocks:
+         c += b.gencode()
+      for b in self.blocks:
+         c.append('{0}()'.format(b.name))
+      return c
+   def findPort(self, blockname, portname):
+      block = self.findBlock(blockname)
+      if block:
+         for port in block.inputs + block.outputs:
+            if port.name == portname: return port
+   def findBlock(self, blockname):
+      for block in self.blocks:
+         if block.name == blockname: return block
+   def uniqify(self, name):
+      blocknames = [item.name for item in self.blocks]
+      return uniqify(name, blocknames)
+   def mouseMoveEvent(self, event):
+      if self.startedConnection:
+         pos = event.scenePos()
+         self.startedConnection.setEndPos(pos)
+      super(DiagramScene, self).mouseMoveEvent(event)
+   def mouseReleaseEvent(self, event):
+      if self.startedConnection:
+         for item in self.items(event.scenePos()):
+            if type(item) is InputPort and item.connection == None:
+               self.startedConnection.setToPort(item)
+               self.startedConnection = None
+               return
+         self.startedConnection.myDelete()
+         self.startedConnection = None
+      super(DiagramScene, self).mouseReleaseEvent(event)
+   def startConnection(self, port):
+      self.startedConnection = Connection(port, None)
+      pos = port.scenePos()
+      self.startedConnection.setEndPos(pos)
+      self.addItem(self.startedConnection)
+   def deleteItems(self):
+      for item in list(self.selectedItems()): item.myDelete()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/icons.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,8 @@
+
+
+saveicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGGklEQVR42s2XeWxURRjAv7d3L9ay\nlJBCbAx/SIIpCWilhNLSFsrR0qUgyCmnnKVFa/xDjNbUKGIUSrlaLhEREWlZaQoC24VymBivoGJB\n/MuEtEpjoNt2z/H7Zt+8fdPdGk2MOu23MzvvzXy/+Y6ZWQX+46L8bwC2vLTlZte9e6MMRiMYjQYY\nPWYsZGXngM1iBkUxoERej1RYayJmYGrF1Dbj/31+P1xtuwQ3vvmaP6M/h8Nx69Xq6kclgDWrn2W3\nbt+G5KQkSE9Ph/E5eTB1xixIQID+yIraEMoVJYLGay4KGNS2ty8Aza4muHqpVZvClmCDHbW1igSw\neuUq1tPTA2EWRohkmJCbD9OLS+Fu14M4ZlP6M8lwSvSdEUNTwNXYCFc87iiAzQY7d9XJACuXr2Dd\n3d1gNpvBarXCxMmFUDzLCUk2S3zfKTrlqmIlYgqtTfWDXh80NZ6CNvdFnQUSYNfuXTLAimXLmV5B\nTn4hlDrLICUxHoAC+tHSTNz1jIcCw48HvX60AAK0RgGsaIE9e/fIAMuWPiMB5BZMAWfZHBiUaI1r\nAaZ+Mi32VKVqX5h/ZzwGzpxuRAtckFywt36fDLB08RIZoHAqlDhnQ0eXdwDlosFAP1APRGVoahK0\nYBBedp+XLNCwv0EGWLxwUT+AIphZ6ozNghhlEQCtrZqeqRC+QAjOftqEFogCkAX2HzwgAyxasFAC\nmFQwFaaVEIAJ5P2K6T5ln2uu0LnEHwzBZ2ea4Epr1AUU5AcPH5IBFsx/Wg5CBCgqdoLVbBxg5Xov\nDGyFQCgMF5tPI8B5CeDwkfdkgPlPzYsBmDLTCffu98b3f78OzS4s+g7Vg5Ot4G5xwdV+AEeOvi8D\nzJszV5p7IgLkT3equ9zAAPo4EMpFAIpnnrMuuKYDsCDA0WMfyABzy+bIAPlTIG9aKfzZecV0y5dc\nIdosMvzyORdc90RjwGKxwLHjH8oAZc7ZEoBj6DAYOeoxPJiMYKIDymTkbYPBoB5CkRpABByDcDjM\nJUQSDEIwFIIwyk83b0DXrx0SwPETH8kAs2eVxrhXKsrfPLnZwNOZEeDEyY9lgNLiEvYXpv1HCgGc\nPPWJDFAys/jfA8AD71RTowxQPH3GgAAK+t2IQv7X4oC+q5cSKiIORCyEyP9qLfr1AI2u0zLAjKJp\ncQHWblgPGRkZ0Q7G4uwFch8d6xXlm3jw0qEUCARgOF5yRDGZTOBqPiMDFBUUxsxLh8aa9evAbrfz\nVYuVRvVG2uKZ6COrvFj1Ao92fiL2eME+yK4pM6EFms+2yAAFeZNjAawWWF9eDqmpqVBT/ZqWZn1+\nH7y5dat2LxRmp1qY/pUtL/NgY9ju6e3lVz29Bc5dOC8D5OVMigNghfLKCg7wXOVm3kd53e31Qv3+\nBq6clAUx5/v7/I2a17mvOXBfHyTgLUgDQNdc8LTKADnZE2IAiHRz1fPgGDIEKjeW8z7aZPwBP9TW\n1WlK9QAC4p1tb2sAPp8PbLgYunFb8HgPBILgabssA0zIejIGgHy4uaoKARywacPGCABO7sOr9rs7\ntsdEOwnBkNRu34EAJnQBAz++TwB8V0WoIAZl2/VrMkDWuMdjAJISE2EjuoCCsBKjOuJrVISTbt32\nlqZMrJyiXQDt2VnHldGYYDCA7rSBGS0awvEmowmufH5dBhibOeYu+nSYHiABAdZhGg4igIoKbkqa\nnLKjpqZGWrneErTihn31XGEEIAgJOIZixqim5hdffRkFSElOUfDX0LgR6cNbMECGaBbAyF21dg2v\n+UBdkFGu6wH0z0jhgfp6vlIeuPiMrmGiUNr+0P5jcp/P5xUWoDoN/bT8kYczqjH4rCILFi5ZAvaH\n7JKPRZtMLtJPCE1Oz44cOsSh1X0KrBaLHiD47fffjcTmL/ojLhFlNCovtJjNDmRi2dnjk57IyhqM\nsWBBf1pxQjMJzmgke6rKmULJwVgQm36E8nd2dNxv9Xh+//nOHR9Ivxj4WjGRQu24+mb88psegNqE\nSQlrJH9lZmYacnNzjWlpaQpmBBdKLXXHU9QNiIkdEa0T9nq94c7OzpDb7Q63t7crTD6WFRXEj0J3\nveAfetNmUUsM6bsAAAAASUVORK5CYII=\n'
+
+loadicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACsElEQVR42u2Xf0hTURTHv++ZczlD\n6SeUREVRiRT9gFWM1rbAwr+iYAathPqjMosIQQqJQAhLLDI0CMwflRa1vyQst0oNLKxhCGWR9UfB\nwFCRaqC2vc6d7+1tr/7YnuwW5IEv95y79875vHvP7t4E/GUTpgGmAaL8vaRzpDlx3iuRXpEOkz5N\nFWDhrHR8bL+LtGXLKUqRJcoKyeUk1Q8Fges3gLIKeGlm+1QBHA4rPJ7WxG4eHqLlWoJRcvfJaPHY\nV1LPbwB5Dnja7if+BFUVQEdX7OqETdL48vD+C/DODze5e9iUCmAjgDt6FzJ+m/gG5GyD9OEz1lPY\nqwLQFrQ1JR+Amc0JPO0O941XBbAQQB0nABcBvNACbCGAWk4ABwngpRbATACXEksU7rsJGlnzUSZB\nkEdAbW9lXgnJtx0jAJ8WYCMBnE8MIESFx7+rRQRRLiaPESANmL2EAF6jgaLSCIA9Bx53sZokJpEY\nm4zFzP85BgTn0mUZUL9y7CPpz8CCvAJdA0DrE6D6NnxsLp9UaV2KVfW7Jy8QWcGUyUJhP0piFJA0\nmw6iAn19EAgAmdkICpRw5EEdsjabgXQDYo9gRZENVxVeIJO8Gjqs7y2wxoJ+IXUGxkcHkDrTqC+R\nXrt5D3AVoYU9yJs+L1bnruQLUFJO+34NpxlAc2MVCly7+ALkHQAedSKfAZwq3o/KK2X8ikvUT4ss\nkPyDWMwAtm5ai47uZn4Ag8PAAgvoxxzzGUCGMQ1DI89gMBr4ADymtwHHIXSSa1UOIt/zBqwz5/IB\nqG4Bjl9EDblFCkDN5ZM4csLJB+DoBaDWDTp3cVUBcDntaLx1hg/AzlKgvQc7yH2oAGSbjOg/WwjT\nvMzkFvdT65U34UdgDCtYGP1avoFUSMpK8gKw7q8n9bLgn/pj8n8C/ALihrxpNKi7hQAAAABJRU5E\nrkJggg==\n'
+
+newicon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADSUlEQVR42r2XO0xaURjHLzYmdXRi\nYXBwdDScJl3djQNLw0TSAR88FR9JU6P4QKMCaTqQdGgXsQQMQXFwcGXhCCG+4iNEo6mDMZL45kK/\n76THUO+9Qi/efskJcm4O3+/+v8f51Al/LBaLmTs6Or43gAkq7eHhoXh2dmZva2v7WusZHf9jZGTE\nPz4+blfjuFwuC6IoCsViUbi8vCwDhM1oNH75V4AAANjUAJRKJeYc183NjXB1dVU+Pj7+CIp+qxlg\neHg44PV6VQHg2z8+PjKAu7s7oampSQAVxL29PUtnZ+eP/waA6/r6WtDr9UyJ09NTcXd319LV1aUI\n8QQwNDQUmJiYqBsA5BcMBgPLC4Q4OTkRt7e3LSaTSRbiCWBwcDAwOTmpOgfQOVSBcHFxIbS0tLB9\nDgH5IGYyGYvZbJZAvAoAOsL4IwTEngGxH9fp2MJnhUJBTKfT5t7e3rAsgMfjYQB4oB4V+OJAuI+A\naGtra6nz8/P3o6OjJQnAwMBAYGpqSjUAh8Aw8JLE3OBqIMTGxgbNZrPE5/MVFQFUe6+A4M5xoWMe\nIg4ASksB+vv761aAG3eKMFwBBFhfX6ebm5sEyl0eAHOgjqvgRSBUA3KAghHouFIAt9vNFNACgIci\nmUxSKEcyNjYmBXC5XK8Wgudvz8OAAJgDigD1lGE155UAsiFwOp2vUgVKzisBZJMQAdR2wlqco62s\nrNBcLkfgzpECOByOuhXg5cc733NLJBIMQLYP2O12BqB0uJrjyk8li8fjdGtri4AfeQAMAUpXayJW\ne2MlANlWbLPZGAB2LPagCoQapZaXl+nOzg6ZmZmRB8CBhANoYTB5U5iQyOzsrDwAjmR4hWpl0WiU\nwpxI5ubmpAAwKLAQ4HWqlUUiEbq/v0/m5+flATAEWiqwtLREDw4OyMLCgjyA1iEIh8P08PCQ+P1+\nKUBPTw8D0DIEi4uL9OjoiASDQSlAd3c3A7i/v9cUAKsgFApJAaxWa2B6etp2e3v71yGlen++X60v\n4EwAAOlUKvUO+oEUoLW19UNfX9/nxsbGhsoOxy+Wl75X2+drdXX1J/zX9AkmI+lU3N7e/hYSxAAT\n0Rs+FdX69rXsA1y5ubn5Vz6fL1Q++w30VO4/0/9IewAAAABJRU5ErkJggg==\n'
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ide.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,299 @@
+import sys, os, base64
+if sys.version_info.major != 3:
+   print("Needs to be run in python version 3.x")
+   sys.exit(1)
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+# Compiler imports:
+sys.path.insert(0, os.path.join('..','libs'))
+from project import Project
+from compiler import Compiler
+from widgets import CodeEdit, AstViewer
+
+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 el in self.project.elements:
+         fitem = QStandardItem(el)
+         pitem.appendRow(fitem)
+         fitem.setEditable(False)
+         fitem.setData(el)
+      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')
+    self.compiler = Compiler()
+    icon = QPixmap()
+    icon.loadFromData(lcfospng)
+    self.setWindowIcon(QIcon(icon))
+
+    # Create menus:
+    mb = self.menuBar()
+    self.projectMenu = mb.addMenu('Project')
+    self.viewMenu = mb.addMenu('View')
+    self.helpMenu = mb.addMenu('Help')
+
+    # Create mdi area:
+    self.mdiArea = QMdiArea()
+    self.setCentralWidget(self.mdiArea)
+
+    # 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
+
+    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.projectview = addComponent('Project explorer', ProjectView())
+    self.projectview.sigLoadFile.connect(self.loadFile)
+
+    # About dialog:
+    self.aboutDialog = AboutDialog()
+    self.aboutDialog.setWindowIcon(QIcon(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.projectMenu, self.newProject)
+    addMenuEntry("Open", self.projectMenu, self.openProject)
+    addMenuEntry("Save", self.projectMenu, self.saveProject)
+    addMenuEntry("Close", self.projectMenu, self.closeProject)
+    addMenuEntry("Build", self.projectMenu, self.buildProject, 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)
+
+    # Load settings:
+    self.settings = QSettings('windelsoft', 'lcfoside')
+    self.loadSettings()
+
+  # File handling:
+  def newProject(self):
+     filename = QFileDialog.getSaveFileName(self, \
+       "Select new projectfile", "", "lcfos Project files (*.lcp2)")
+     if filename:
+        self.project = Project()
+        self.project.filename = filename
+        self.project.save()
+
+  def saveProject(self):
+     self.project.save()
+
+  def closeProject(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
+
+  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 (*.lcp2)")
+     if filename:
+        self.loadProject(filename)
+
+  # 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:
+
+  # Build recepy:
+  def buildProject(self):
+     """ Build project """
+     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.show()
+   app.exec_()
+
--- a/python/libs/compiler/core/__init__.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-from .instruction import *
-from .function import *
-from .value import *
-from .bitreader import BitReader
-from .errors import CompilerException
-
--- a/python/libs/compiler/core/basicblock.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-
-class BasicBlock(Value):
-   def __init__(self):
-      pass
-
--- a/python/libs/compiler/core/bitreader.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-from .errors import CompilerException
-import struct
-
-def bits(f):
-   while True:
-      Byte = f.read(1)
-      for i in range(8):
-         yield Byte & 0x1
-         Byte >>= 1
-
-class BitReader:
-   def __init__(self, f):
-      self.stream = bits(f)
-      self.curword = None
-   def parseModule(self):
-      if self.read(8) != ord('B') or self.read(8) != ord('C'):
-         raise CompilerException('Invalid bitcode signature')
-      for bitsig in [0x0, 0xC, 0xE, 0xD]:
-         if self.read(4) != bitsig:
-            raise CompilerException('Invalid bitcode signature')
-
-   def read(self, numbits):
-      if numbits == 8:
-         b = self.stream.read(1)
-         print(b)
-         return int(b[0])
-      return 2
-
--- a/python/libs/compiler/core/context.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-class Context:
-   pass
-
--- a/python/libs/compiler/core/errors.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-""" Error handling routines """
-
-class CompilerException(Exception):
-  def __init__(self, msg, row=0, col=0, filename=None):
-    self.msg = msg
-    self.row = row
-    self.col = col
-    self.filename = filename
-  def __repr__(self):
-     return self.msg
-  def __str__(self):
-     return self.msg
-
-class ErrorNode:
-   def __init__(self, row, col, msg):
-      self.row, self.col = row,col
-      self.msg = msg
-
-def Error(msg, node=None):
-   if node is None:
-      raise CompilerException(msg)
-   else:
-      raise CompilerException(msg, node.row, node.col)
-
-def printError(source, e):
-     def printLine(row, txt):
-        print(str(row)+':'+txt)
-     if e.row == 0:
-        print('Error: {0}'.format(e.msg))
-     else:
-        lines = source.split('\n')
-        prerow = e.row - 3
-        if prerow < 1:
-           prerow = 1
-        afterrow = e.row + 3
-        if afterrow > len(lines):
-           afterrow = len(lines)
-
-        # print preceding source lines:
-        for r in range(prerow, e.row):
-           printLine(r, lines[r-1])
-        # print source line containing error:
-        printLine(e.row, lines[e.row-1])
-        print(' '*(len(str(e.row)+':')+e.col-1) + '^ Error: {0}'.format(e.msg))
-        # print trailing source line:
-        for r in range(e.row+1, afterrow+1):
-          printLine(r, lines[r-1])
--- a/python/libs/compiler/core/function.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-class Function:
-   def __init__(self):
-      pass
-
-
--- a/python/libs/compiler/core/instruction.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-from .value import Value
-
-class Instruction(Value):
-   pass
-
-class CallInstruction(Instruction):
-   pass
-
-class BinaryOperator(Instruction):
-   pass
-
-class LoadInstruction(Instruction):
-   def __init__(self, ptr, name, insertBefore):
-      self.setName(name)
-
--- a/python/libs/compiler/core/llvmtype.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-
-def Enum(**enums):
-   return type('Enum', (), enums)
-
-class llvmType:
-   typeID = Enum(Void=0, Double=3, Integer=10, \
-                 Function=11, Struct=12, \
-                 Array=13, Pointer=14\
-                 Vector=15)
-   def __init__(self, context, tid):
-      self.context = context
-      
-
--- a/python/libs/compiler/core/module.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-class Module:
-   pass
-   
--- a/python/libs/compiler/core/value.py	Mon Dec 24 13:21:13 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-
-class Value:
-   def __init__(self, vty):
-      self.valueType = ty
-      self.name = None
-   def getContext(self):
-      return self.valueType.context
-
-   def setName(self, name):
-      if not self.name and not name:
-         return
-      self.name = name
-
-      if self.st:
-         pass
-      else:
-         pass
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/__init__.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,6 @@
+from .instruction import *
+from .function import *
+from .value import *
+from .bitreader import BitReader
+from .errors import CompilerException
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/basicblock.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,5 @@
+
+class BasicBlock(Value):
+   def __init__(self):
+      pass
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/bitreader.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,28 @@
+from .errors import CompilerException
+import struct
+
+def bits(f):
+   while True:
+      Byte = f.read(1)
+      for i in range(8):
+         yield Byte & 0x1
+         Byte >>= 1
+
+class BitReader:
+   def __init__(self, f):
+      self.stream = bits(f)
+      self.curword = None
+   def parseModule(self):
+      if self.read(8) != ord('B') or self.read(8) != ord('C'):
+         raise CompilerException('Invalid bitcode signature')
+      for bitsig in [0x0, 0xC, 0xE, 0xD]:
+         if self.read(4) != bitsig:
+            raise CompilerException('Invalid bitcode signature')
+
+   def read(self, numbits):
+      if numbits == 8:
+         b = self.stream.read(1)
+         print(b)
+         return int(b[0])
+      return 2
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/context.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,4 @@
+
+class Context:
+   pass
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/errors.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,47 @@
+""" Error handling routines """
+
+class CompilerException(Exception):
+  def __init__(self, msg, row=0, col=0, filename=None):
+    self.msg = msg
+    self.row = row
+    self.col = col
+    self.filename = filename
+  def __repr__(self):
+     return self.msg
+  def __str__(self):
+     return self.msg
+
+class ErrorNode:
+   def __init__(self, row, col, msg):
+      self.row, self.col = row,col
+      self.msg = msg
+
+def Error(msg, node=None):
+   if node is None:
+      raise CompilerException(msg)
+   else:
+      raise CompilerException(msg, node.row, node.col)
+
+def printError(source, e):
+     def printLine(row, txt):
+        print(str(row)+':'+txt)
+     if e.row == 0:
+        print('Error: {0}'.format(e.msg))
+     else:
+        lines = source.split('\n')
+        prerow = e.row - 3
+        if prerow < 1:
+           prerow = 1
+        afterrow = e.row + 3
+        if afterrow > len(lines):
+           afterrow = len(lines)
+
+        # print preceding source lines:
+        for r in range(prerow, e.row):
+           printLine(r, lines[r-1])
+        # print source line containing error:
+        printLine(e.row, lines[e.row-1])
+        print(' '*(len(str(e.row)+':')+e.col-1) + '^ Error: {0}'.format(e.msg))
+        # print trailing source line:
+        for r in range(e.row+1, afterrow+1):
+          printLine(r, lines[r-1])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/function.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,6 @@
+
+class Function:
+   def __init__(self):
+      pass
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/instruction.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,15 @@
+from .value import Value
+
+class Instruction(Value):
+   pass
+
+class CallInstruction(Instruction):
+   pass
+
+class BinaryOperator(Instruction):
+   pass
+
+class LoadInstruction(Instruction):
+   def __init__(self, ptr, name, insertBefore):
+      self.setName(name)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/llvmtype.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,13 @@
+
+def Enum(**enums):
+   return type('Enum', (), enums)
+
+class llvmType:
+   typeID = Enum(Void=0, Double=3, Integer=10, \
+                 Function=11, Struct=12, \
+                 Array=13, Pointer=14\
+                 Vector=15)
+   def __init__(self, context, tid):
+      self.context = context
+      
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/module.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,4 @@
+
+class Module:
+   pass
+   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/core/value.py	Mon Dec 24 13:24:59 2012 +0100
@@ -0,0 +1,18 @@
+
+class Value:
+   def __init__(self, vty):
+      self.valueType = ty
+      self.name = None
+   def getContext(self):
+      return self.valueType.context
+
+   def setName(self, name):
+      if not self.name and not name:
+         return
+      self.name = name
+
+      if self.st:
+         pass
+      else:
+         pass
+